diff options
Diffstat (limited to 'src/map')
72 files changed, 103648 insertions, 103509 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c index a67c67108..394f4fb11 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -61,97 +61,100 @@ typedef struct AliasInfo AliasInfo; int atcmd_binding_count = 0; struct AtCommandInfo { - char command[ATCOMMAND_LENGTH]; - AtCommandFunc func; - char *at_groups;/* quick @commands "can-use" lookup */ - char *char_groups;/* quick @charcommands "can-use" lookup */ + char command[ATCOMMAND_LENGTH]; + AtCommandFunc func; + char* at_groups;/* quick @commands "can-use" lookup */ + char* char_groups;/* quick @charcommands "can-use" lookup */ }; struct AliasInfo { - AtCommandInfo *command; - char alias[ATCOMMAND_LENGTH]; + AtCommandInfo *command; + char alias[ATCOMMAND_LENGTH]; }; char atcommand_symbol = '@'; // first char of the commands char charcommand_symbol = '#'; -static char *msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) -static DBMap *atcommand_db = NULL; //name -> AtCommandInfo -static DBMap *atcommand_alias_db = NULL; //alias -> AtCommandInfo +static char* msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) +static DBMap* atcommand_db = NULL; //name -> AtCommandInfo +static DBMap* atcommand_alias_db = NULL; //alias -> AtCommandInfo static config_t atcommand_config; static char atcmd_output[CHAT_SIZE_MAX]; static char atcmd_player_name[NAME_LENGTH]; -static AtCommandInfo *get_atcommandinfo_byname(const char *name); // @help -static const char *atcommand_checkalias(const char *aliasname); // @help -static void atcommand_get_suggestions(struct map_session_data *sd, const char *name, bool atcommand); // @help +static AtCommandInfo* get_atcommandinfo_byname(const char *name); // @help +static const char* atcommand_checkalias(const char *aliasname); // @help +static void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool atcommand); // @help // @commands (script-based) -struct atcmd_binding_data *get_atcommandbind_byname(const char *name) { - int i = 0; +struct atcmd_binding_data* get_atcommandbind_byname(const char* name) { + int i = 0; - if (*name == atcommand_symbol || *name == charcommand_symbol) - name++; // for backwards compatibility + if( *name == atcommand_symbol || *name == charcommand_symbol ) + name++; // for backwards compatibility - ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command, name) == 0); + ARR_FIND( 0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command, name) == 0 ); - return (i < atcmd_binding_count) ? atcmd_binding[i] : NULL; + return ( i < atcmd_binding_count ) ? atcmd_binding[i] : NULL; } //----------------------------------------------------------- // Return the message string of the specified number by [Yor] //----------------------------------------------------------- -const char *msg_txt(int msg_number) +const char* msg_txt(int msg_number) { - if (msg_number >= 0 && msg_number < MAX_MSG && - msg_table[msg_number] != NULL && msg_table[msg_number][0] != '\0') - return msg_table[msg_number]; + if (msg_number >= 0 && msg_number < MAX_MSG && + msg_table[msg_number] != NULL && msg_table[msg_number][0] != '\0') + return msg_table[msg_number]; - return "??"; + return "??"; } /*========================================== * Read Message Data *------------------------------------------*/ -int msg_config_read(const char *cfgName) +int msg_config_read(const char* cfgName) { - int msg_number; - char line[1024], w1[1024], w2[1024]; - FILE *fp; - static int called = 1; + int msg_number; + char line[1024], w1[1024], w2[1024]; + FILE *fp; + static int called = 1; - if ((fp = fopen(cfgName, "r")) == NULL) { - ShowError("Messages file not found: %s\n", cfgName); - return 1; - } + if ((fp = fopen(cfgName, "r")) == NULL) { + ShowError("Messages file not found: %s\n", cfgName); + return 1; + } - if ((--called) == 0) - memset(msg_table, 0, sizeof(msg_table[0]) * MAX_MSG); + if ((--called) == 0) + memset(msg_table, 0, sizeof(msg_table[0]) * MAX_MSG); - while (fgets(line, sizeof(line), fp)) { - if (line[0] == '/' && line[1] == '/') - continue; - if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2) - continue; + while(fgets(line, sizeof(line), fp)) + { + if (line[0] == '/' && line[1] == '/') + continue; + if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) != 2) + continue; - if (strcmpi(w1, "import") == 0) - msg_config_read(w2); - else { - msg_number = atoi(w1); - if (msg_number >= 0 && msg_number < MAX_MSG) { - if (msg_table[msg_number] != NULL) - aFree(msg_table[msg_number]); - msg_table[msg_number] = (char *)aMalloc((strlen(w2) + 1)*sizeof(char)); - strcpy(msg_table[msg_number],w2); - } - } - } + if (strcmpi(w1, "import") == 0) + msg_config_read(w2); + else + { + msg_number = atoi(w1); + if (msg_number >= 0 && msg_number < MAX_MSG) + { + if (msg_table[msg_number] != NULL) + aFree(msg_table[msg_number]); + msg_table[msg_number] = (char *)aMalloc((strlen(w2) + 1)*sizeof (char)); + strcpy(msg_table[msg_number],w2); + } + } + } - fclose(fp); + fclose(fp); - return 0; + return 0; } /*========================================== @@ -159,9 +162,9 @@ int msg_config_read(const char *cfgName) *------------------------------------------*/ void do_final_msg(void) { - int i; - for (i = 0; i < MAX_MSG; i++) - aFree(msg_table[i]); + int i; + for (i = 0; i < MAX_MSG; i++) + aFree(msg_table[i]); } /** @@ -170,34 +173,34 @@ void do_final_msg(void) * @param name the name of the command to retrieve help information for * @return the string associated with the command, or NULL */ -static const char *atcommand_help_string(const char *command) +static const char* atcommand_help_string(const char* command) { - const char *str = NULL; - config_setting_t *info; + const char* str = NULL; + config_setting_t* info; - if (*command == atcommand_symbol || *command == charcommand_symbol) { - // remove the prefix symbol for the raw name of the command - command ++; - } + if( *command == atcommand_symbol || *command == charcommand_symbol ) + {// remove the prefix symbol for the raw name of the command + command ++; + } - // convert alias to the real command name - command = atcommand_checkalias(command); + // convert alias to the real command name + command = atcommand_checkalias(command); - // attept to find the first default help command - info = config_lookup(&atcommand_config, "help"); + // attept to find the first default help command + info = config_lookup(&atcommand_config, "help"); - if (info == NULL) { - // failed to find the help property in the configuration file - return NULL; - } + if( info == NULL ) + {// failed to find the help property in the configuration file + return NULL; + } - if (!config_setting_lookup_string(info, command, &str)) { - // failed to find the matching help string - return NULL; - } + if( !config_setting_lookup_string( info, command, &str ) ) + {// failed to find the matching help string + return NULL; + } - // push the result from the method - return str; + // push the result from the method + return str; } @@ -206,243 +209,228 @@ static const char *atcommand_help_string(const char *command) *------------------------------------------*/ ACMD_FUNC(send) { - int len=0,off,end,type; - long num; + int len=0,off,end,type; + long num; - // read message type as hex number (without the 0x) - if (!message || !*message || - !((sscanf(message, "len %x", &type)==1 && (len=1)) - || sscanf(message, "%x", &type)==1)) { - int i; - for (i = 900; i <= 903; ++i) - clif_displaymessage(fd, msg_txt(i)); - return -1; - } + // read message type as hex number (without the 0x) + if(!message || !*message || + !((sscanf(message, "len %x", &type)==1 && (len=1)) + || sscanf(message, "%x", &type)==1) ) + { + int i; + for (i = 900; i <= 903; ++i) + clif_displaymessage(fd, msg_txt(i)); + return -1; + } #define PARSE_ERROR(error,p) \ - {\ - clif_displaymessage(fd, (error));\ - sprintf(atcmd_output, ">%s", (p));\ - clif_displaymessage(fd, atcmd_output);\ - } - //define PARSE_ERROR + {\ + clif_displaymessage(fd, (error));\ + sprintf(atcmd_output, ">%s", (p));\ + clif_displaymessage(fd, atcmd_output);\ + } +//define PARSE_ERROR #define CHECK_EOS(p) \ - if(*(p) == 0){\ - clif_displaymessage(fd, "Unexpected end of string");\ - return -1;\ - } - //define CHECK_EOS + if(*(p) == 0){\ + clif_displaymessage(fd, "Unexpected end of string");\ + return -1;\ + } +//define CHECK_EOS #define SKIP_VALUE(p) \ - {\ - while(*(p) && !ISSPACE(*(p))) ++(p); /* non-space */\ - while(*(p) && ISSPACE(*(p))) ++(p); /* space */\ - } - //define SKIP_VALUE + {\ + while(*(p) && !ISSPACE(*(p))) ++(p); /* non-space */\ + while(*(p) && ISSPACE(*(p))) ++(p); /* space */\ + } +//define SKIP_VALUE #define GET_VALUE(p,num) \ - {\ - if(sscanf((p), "x%lx", &(num)) < 1 && sscanf((p), "%ld ", &(num)) < 1){\ - PARSE_ERROR("Invalid number in:",(p));\ - return -1;\ - }\ - } - //define GET_VALUE - - if (type > 0 && type < MAX_PACKET_DB) { - - if (len) { - // show packet length - sprintf(atcmd_output, msg_txt(904), type, packet_db[sd->packet_ver][type].len); // Packet 0x%x length: %d - clif_displaymessage(fd, atcmd_output); - return 0; - } - - len=packet_db[sd->packet_ver][type].len; - off=2; - if (len == 0) { - // unknown packet - ERROR - sprintf(atcmd_output, msg_txt(905), type); // Unknown packet: 0x%x - clif_displaymessage(fd, atcmd_output); - return -1; - } else if (len == -1) { - // dynamic packet - len=SHRT_MAX-4; // maximum length - off=4; - } - WFIFOHEAD(fd, len); - WFIFOW(fd,0)=TOW(type); - - // parse packet contents - SKIP_VALUE(message); - while (*message != 0 && off < len) { - if (ISDIGIT(*message) || *message == '-' || *message == '+') { - // default (byte) - GET_VALUE(message,num); - WFIFOB(fd,off)=TOB(num); - ++off; - } else if (TOUPPER(*message) == 'B') { - // byte - ++message; - GET_VALUE(message,num); - WFIFOB(fd,off)=TOB(num); - ++off; - } else if (TOUPPER(*message) == 'W') { - // word (2 bytes) - ++message; - GET_VALUE(message,num); - WFIFOW(fd,off)=TOW(num); - off+=2; - } else if (TOUPPER(*message) == 'L') { - // long word (4 bytes) - ++message; - GET_VALUE(message,num); - WFIFOL(fd,off)=TOL(num); - off+=4; - } else if (TOUPPER(*message) == 'S') { - // string - escapes are valid - // get string length - num <= 0 means not fixed length (default) - ++message; - if (*message == '"') { - num=0; - } else { - GET_VALUE(message,num); - while (*message != '"') { - // find start of string - if (*message == 0 || ISSPACE(*message)) { - PARSE_ERROR(msg_txt(906),message); // Not a string: - return -1; - } - ++message; - } - } - - // parse string - ++message; - CHECK_EOS(message); - end=(num<=0? 0: min(off+((int)num),len)); - for (; *message != '"' && (off < end || end == 0); ++off) { - if (*message == '\\') { - ++message; - CHECK_EOS(message); - switch (*message) { - case 'a': - num=0x07; - break; // Bell - case 'b': - num=0x08; - break; // Backspace - case 't': - num=0x09; - break; // Horizontal tab - case 'n': - num=0x0A; - break; // Line feed - case 'v': - num=0x0B; - break; // Vertical tab - case 'f': - num=0x0C; - break; // Form feed - case 'r': - num=0x0D; - break; // Carriage return - case 'e': - num=0x1B; - break; // Escape - default: - num=*message; - break; - case 'x': { // Hexadecimal - ++message; - CHECK_EOS(message); - if (!ISXDIGIT(*message)) { - PARSE_ERROR(msg_txt(907),message); // Not a hexadecimal digit: - return -1; - } - num=(ISDIGIT(*message)?*message-'0':TOLOWER(*message)-'a'+10); - if (ISXDIGIT(*message)) { - ++message; - CHECK_EOS(message); - num<<=8; - num+=(ISDIGIT(*message)?*message-'0':TOLOWER(*message)-'a'+10); - } - WFIFOB(fd,off)=TOB(num); - ++message; - CHECK_EOS(message); - continue; - } - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': { // Octal - num=*message-'0'; // 1st octal digit - ++message; - CHECK_EOS(message); - if (ISDIGIT(*message) && *message < '8') { - num<<=3; - num+=*message-'0'; // 2nd octal digit - ++message; - CHECK_EOS(message); - if (ISDIGIT(*message) && *message < '8') { - num<<=3; - num+=*message-'0'; // 3rd octal digit - ++message; - CHECK_EOS(message); - } - } - WFIFOB(fd,off)=TOB(num); - continue; - } - } - } else - num=*message; - WFIFOB(fd,off)=TOB(num); - ++message; - CHECK_EOS(message); - }//for - while (*message != '"') { - // ignore extra characters - ++message; - CHECK_EOS(message); - } - - // terminate the string - if (off < end) { - // fill the rest with 0's - memset(WFIFOP(fd,off),0,end-off); - off=end; - } - } else { - // unknown - PARSE_ERROR(msg_txt(908),message); // Unknown type of value in: - return -1; - } - SKIP_VALUE(message); - } - - if (packet_db[sd->packet_ver][type].len == -1) { - // send dynamic packet - WFIFOW(fd,2)=TOW(off); - WFIFOSET(fd,off); - } else { - // send static packet - if (off < len) - memset(WFIFOP(fd,off),0,len-off); - WFIFOSET(fd,len); - } - } else { - clif_displaymessage(fd, msg_txt(259)); // Invalid packet - return -1; - } - sprintf(atcmd_output, msg_txt(258), type, type); // Sent packet 0x%x (%d) - clif_displaymessage(fd, atcmd_output); - return 0; + {\ + if(sscanf((p), "x%lx", &(num)) < 1 && sscanf((p), "%ld ", &(num)) < 1){\ + PARSE_ERROR("Invalid number in:",(p));\ + return -1;\ + }\ + } +//define GET_VALUE + + if (type > 0 && type < MAX_PACKET_DB) { + + if(len) + {// show packet length + sprintf(atcmd_output, msg_txt(904), type, packet_db[sd->packet_ver][type].len); // Packet 0x%x length: %d + clif_displaymessage(fd, atcmd_output); + return 0; + } + + len=packet_db[sd->packet_ver][type].len; + off=2; + if(len == 0) + {// unknown packet - ERROR + sprintf(atcmd_output, msg_txt(905), type); // Unknown packet: 0x%x + clif_displaymessage(fd, atcmd_output); + return -1; + } else if(len == -1) + {// dynamic packet + len=SHRT_MAX-4; // maximum length + off=4; + } + WFIFOHEAD(fd, len); + WFIFOW(fd,0)=TOW(type); + + // parse packet contents + SKIP_VALUE(message); + while(*message != 0 && off < len){ + if(ISDIGIT(*message) || *message == '-' || *message == '+') + {// default (byte) + GET_VALUE(message,num); + WFIFOB(fd,off)=TOB(num); + ++off; + } else if(TOUPPER(*message) == 'B') + {// byte + ++message; + GET_VALUE(message,num); + WFIFOB(fd,off)=TOB(num); + ++off; + } else if(TOUPPER(*message) == 'W') + {// word (2 bytes) + ++message; + GET_VALUE(message,num); + WFIFOW(fd,off)=TOW(num); + off+=2; + } else if(TOUPPER(*message) == 'L') + {// long word (4 bytes) + ++message; + GET_VALUE(message,num); + WFIFOL(fd,off)=TOL(num); + off+=4; + } else if(TOUPPER(*message) == 'S') + {// string - escapes are valid + // get string length - num <= 0 means not fixed length (default) + ++message; + if(*message == '"'){ + num=0; + } else { + GET_VALUE(message,num); + while(*message != '"') + {// find start of string + if(*message == 0 || ISSPACE(*message)){ + PARSE_ERROR(msg_txt(906),message); // Not a string: + return -1; + } + ++message; + } + } + + // parse string + ++message; + CHECK_EOS(message); + end=(num<=0? 0: min(off+((int)num),len)); + for(; *message != '"' && (off < end || end == 0); ++off){ + if(*message == '\\'){ + ++message; + CHECK_EOS(message); + switch(*message){ + case 'a': num=0x07; break; // Bell + case 'b': num=0x08; break; // Backspace + case 't': num=0x09; break; // Horizontal tab + case 'n': num=0x0A; break; // Line feed + case 'v': num=0x0B; break; // Vertical tab + case 'f': num=0x0C; break; // Form feed + case 'r': num=0x0D; break; // Carriage return + case 'e': num=0x1B; break; // Escape + default: num=*message; break; + case 'x': // Hexadecimal + { + ++message; + CHECK_EOS(message); + if(!ISXDIGIT(*message)){ + PARSE_ERROR(msg_txt(907),message); // Not a hexadecimal digit: + return -1; + } + num=(ISDIGIT(*message)?*message-'0':TOLOWER(*message)-'a'+10); + if(ISXDIGIT(*message)){ + ++message; + CHECK_EOS(message); + num<<=8; + num+=(ISDIGIT(*message)?*message-'0':TOLOWER(*message)-'a'+10); + } + WFIFOB(fd,off)=TOB(num); + ++message; + CHECK_EOS(message); + continue; + } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': // Octal + { + num=*message-'0'; // 1st octal digit + ++message; + CHECK_EOS(message); + if(ISDIGIT(*message) && *message < '8'){ + num<<=3; + num+=*message-'0'; // 2nd octal digit + ++message; + CHECK_EOS(message); + if(ISDIGIT(*message) && *message < '8'){ + num<<=3; + num+=*message-'0'; // 3rd octal digit + ++message; + CHECK_EOS(message); + } + } + WFIFOB(fd,off)=TOB(num); + continue; + } + } + } else + num=*message; + WFIFOB(fd,off)=TOB(num); + ++message; + CHECK_EOS(message); + }//for + while(*message != '"') + {// ignore extra characters + ++message; + CHECK_EOS(message); + } + + // terminate the string + if(off < end) + {// fill the rest with 0's + memset(WFIFOP(fd,off),0,end-off); + off=end; + } + } else + {// unknown + PARSE_ERROR(msg_txt(908),message); // Unknown type of value in: + return -1; + } + SKIP_VALUE(message); + } + + if(packet_db[sd->packet_ver][type].len == -1) + {// send dynamic packet + WFIFOW(fd,2)=TOW(off); + WFIFOSET(fd,off); + } else + {// send static packet + if(off < len) + memset(WFIFOP(fd,off),0,len-off); + WFIFOSET(fd,len); + } + } else { + clif_displaymessage(fd, msg_txt(259)); // Invalid packet + return -1; + } + sprintf (atcmd_output, msg_txt(258), type, type); // Sent packet 0x%x (%d) + clif_displaymessage(fd, atcmd_output); + return 0; #undef PARSE_ERROR #undef CHECK_EOS #undef SKIP_VALUE @@ -454,53 +442,53 @@ ACMD_FUNC(send) *------------------------------------------*/ ACMD_FUNC(mapmove) { - char map_name[MAP_NAME_LENGTH_EXT]; - unsigned short mapindex; - short x = 0, y = 0; - int m = -1; + char map_name[MAP_NAME_LENGTH_EXT]; + unsigned short mapindex; + short x = 0, y = 0; + int m = -1; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - memset(map_name, '\0', sizeof(map_name)); + memset(map_name, '\0', sizeof(map_name)); - if (!message || !*message || - (sscanf(message, "%15s %hd %hd", map_name, &x, &y) < 3 && - sscanf(message, "%15[^,],%hd,%hd", map_name, &x, &y) < 1)) { + if (!message || !*message || + (sscanf(message, "%15s %hd %hd", map_name, &x, &y) < 3 && + sscanf(message, "%15[^,],%hd,%hd", map_name, &x, &y) < 1)) { - clif_displaymessage(fd, msg_txt(909)); // Please enter a map (usage: @warp/@rura/@mapmove <mapname> <x> <y>). - return -1; - } + clif_displaymessage(fd, msg_txt(909)); // Please enter a map (usage: @warp/@rura/@mapmove <mapname> <x> <y>). + return -1; + } - mapindex = mapindex_name2id(map_name); - if (mapindex) - m = map_mapindex2mapid(mapindex); + mapindex = mapindex_name2id(map_name); + if (mapindex) + m = map_mapindex2mapid(mapindex); - if (!mapindex) { // m < 0 means on different server! [Kevin] - clif_displaymessage(fd, msg_txt(1)); // Map not found. - return -1; - } + if (!mapindex) { // m < 0 means on different server! [Kevin] + clif_displaymessage(fd, msg_txt(1)); // Map not found. + return -1; + } - if ((x || y) && map_getcell(m, x, y, CELL_CHKNOPASS)) { - //This is to prevent the pc_setpos call from printing an error. - clif_displaymessage(fd, msg_txt(2)); - if (!map_search_freecell(NULL, m, &x, &y, 10, 10, 1)) - x = y = 0; //Invalid cell, use random spot. - } - if (map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(247)); - return -1; - } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(248)); - return -1; - } - if (pc_setpos(sd, mapindex, x, y, CLR_TELEPORT) != 0) { - clif_displaymessage(fd, msg_txt(1)); // Map not found. - return -1; - } + if ((x || y) && map_getcell(m, x, y, CELL_CHKNOPASS)) + { //This is to prevent the pc_setpos call from printing an error. + clif_displaymessage(fd, msg_txt(2)); + if (!map_search_freecell(NULL, m, &x, &y, 10, 10, 1)) + x = y = 0; //Invalid cell, use random spot. + } + if (map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(247)); + return -1; + } + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(248)); + return -1; + } + if (pc_setpos(sd, mapindex, x, y, CLR_TELEPORT) != 0) { + clif_displaymessage(fd, msg_txt(1)); // Map not found. + return -1; + } - clif_displaymessage(fd, msg_txt(0)); // Warped. - return 0; + clif_displaymessage(fd, msg_txt(0)); // Warped. + return 0; } /*========================================== @@ -508,29 +496,29 @@ ACMD_FUNC(mapmove) *------------------------------------------*/ ACMD_FUNC(where) { - struct map_session_data *pl_sd; + struct map_session_data* pl_sd; - nullpo_retr(-1, sd); - memset(atcmd_player_name, '\0', sizeof atcmd_player_name); + nullpo_retr(-1, sd); + memset(atcmd_player_name, '\0', sizeof atcmd_player_name); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(910)); // Please enter a player name (usage: @where <char name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, msg_txt(910)); // Please enter a player name (usage: @where <char name>). + return -1; + } - pl_sd = map_nick2sd(atcmd_player_name); - if (pl_sd == NULL || - strncmp(pl_sd->status.name, atcmd_player_name, NAME_LENGTH) != 0 || - (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > pc_get_group_level(sd) && !pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID)) - ) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + pl_sd = map_nick2sd(atcmd_player_name); + if (pl_sd == NULL || + strncmp(pl_sd->status.name, atcmd_player_name, NAME_LENGTH) != 0 || + (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > pc_get_group_level(sd) && !pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID)) + ) { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - snprintf(atcmd_output, sizeof atcmd_output, "%s %s %d %d", pl_sd->status.name, mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, atcmd_output); + snprintf(atcmd_output, sizeof atcmd_output, "%s %s %d %d", pl_sd->status.name, mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); + clif_displaymessage(fd, atcmd_output); - return 0; + return 0; } /*========================================== @@ -538,40 +526,44 @@ ACMD_FUNC(where) *------------------------------------------*/ ACMD_FUNC(jumpto) { - struct map_session_data *pl_sd = NULL; + struct map_session_data *pl_sd = NULL; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(911)); // Please enter a player name (usage: @jumpto/@warpto/@goto <char name/ID>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(911)); // Please enter a player name (usage: @jumpto/@warpto/@goto <char name/ID>). + return -1; + } - if ((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + if((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) + { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(247)); // You are not authorized to warp to this map. - return -1; - } + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) + { + clif_displaymessage(fd, msg_txt(247)); // You are not authorized to warp to this map. + return -1; + } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. - return -1; - } + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) + { + clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. + return -1; + } - if (pc_isdead(sd)) { - clif_displaymessage(fd, msg_txt(664)); - return -1; - } + if( pc_isdead(sd) ) + { + clif_displaymessage(fd, msg_txt(664)); + return -1; + } - pc_setpos(sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); - sprintf(atcmd_output, msg_txt(4), pl_sd->status.name); // Jumped to %s - clif_displaymessage(fd, atcmd_output); + pc_setpos(sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); + sprintf(atcmd_output, msg_txt(4), pl_sd->status.name); // Jumped to %s + clif_displaymessage(fd, atcmd_output); - return 0; + return 0; } /*========================================== @@ -579,35 +571,36 @@ ACMD_FUNC(jumpto) *------------------------------------------*/ ACMD_FUNC(jump) { - short x = 0, y = 0; + short x = 0, y = 0; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - sscanf(message, "%hd %hd", &x, &y); + sscanf(message, "%hd %hd", &x, &y); - if (map[sd->bl.m].flag.noteleport && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. - return -1; - } + if (map[sd->bl.m].flag.noteleport && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. + return -1; + } - if (pc_isdead(sd)) { - clif_displaymessage(fd, msg_txt(664)); - return -1; - } + if( pc_isdead(sd) ) + { + clif_displaymessage(fd, msg_txt(664)); + return -1; + } - if ((x || y) && map_getcell(sd->bl.m, x, y, CELL_CHKNOPASS)) { - //This is to prevent the pc_setpos call from printing an error. - clif_displaymessage(fd, msg_txt(2)); - if (!map_search_freecell(NULL, sd->bl.m, &x, &y, 10, 10, 1)) - x = y = 0; //Invalid cell, use random spot. - } + if ((x || y) && map_getcell(sd->bl.m, x, y, CELL_CHKNOPASS)) + { //This is to prevent the pc_setpos call from printing an error. + clif_displaymessage(fd, msg_txt(2)); + if (!map_search_freecell(NULL, sd->bl.m, &x, &y, 10, 10, 1)) + x = y = 0; //Invalid cell, use random spot. + } - pc_setpos(sd, sd->mapindex, x, y, CLR_TELEPORT); - sprintf(atcmd_output, msg_txt(5), sd->bl.x, sd->bl.y); // Jumped to %d %d - clif_displaymessage(fd, atcmd_output); - return 0; + pc_setpos(sd, sd->mapindex, x, y, CLR_TELEPORT); + sprintf(atcmd_output, msg_txt(5), sd->bl.x, sd->bl.y); // Jumped to %d %d + clif_displaymessage(fd, atcmd_output); + return 0; } /*========================================== @@ -616,101 +609,101 @@ ACMD_FUNC(jump) *------------------------------------------*/ ACMD_FUNC(who) { - struct map_session_data *pl_sd = NULL; - struct s_mapiterator *iter = NULL; - char map_name[MAP_NAME_LENGTH_EXT] = ""; - char player_name[NAME_LENGTH] = ""; - int count = 0; - int level = 0; - StringBuf buf; - /** - * 1 = @who : Player name, [Title], [Party name], [Guild name] - * 2 = @who2 : Player name, [Title], BLvl, JLvl, Job - * 3 = @who3 : [CID/AID] Player name [Title], Map, X, Y - */ - int display_type = 1; - int map_id = -1; - - nullpo_retr(-1, sd); - - if (strstr(command, "map") != NULL) { - if (sscanf(message, "%15s %23s", map_name, player_name) < 1 || (map_id = map_mapname2mapid(map_name)) < 0) - map_id = sd->bl.m; - } else { - sscanf(message, "%23s", player_name); - } - - if (strstr(command, "2") != NULL) - display_type = 2; - else if (strstr(command, "3") != NULL) - display_type = 3; - - level = pc_get_group_level(sd); - StringBuf_Init(&buf); - - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pc_get_group_level(pl_sd) > level)) { // you can look only lower or same level - if (stristr(pl_sd->status.name, player_name) == NULL // search with no case sensitive - || (map_id >= 0 && pl_sd->bl.m != map_id)) - continue; - switch (display_type) { - case 2: { - StringBuf_Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " - if (pc_get_group_id(pl_sd) > 0) // Player title, if exists - StringBuf_Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " - StringBuf_Printf(&buf, msg_txt(347), pl_sd->status.base_level, pl_sd->status.job_level, - job_name(pl_sd->status.class_)); // "| Lv:%d/%d | Job: %s" - break; - } - case 3: { - if (pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID)) - StringBuf_Printf(&buf, msg_txt(912), pl_sd->status.char_id, pl_sd->status.account_id); // "(CID:%d/AID:%d) " - StringBuf_Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " - if (pc_get_group_id(pl_sd) > 0) // Player title, if exists - StringBuf_Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " - StringBuf_Printf(&buf, msg_txt(348), mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); // "| Location: %s %d %d" - break; - } - default: { - struct party_data *p = party_search(pl_sd->status.party_id); - struct guild *g = guild_search(pl_sd->status.guild_id); - - StringBuf_Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " - if (pc_get_group_id(pl_sd) > 0) // Player title, if exists - StringBuf_Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " - if (p != NULL) - StringBuf_Printf(&buf, msg_txt(345), p->party.name); // " | Party: '%s'" - if (g != NULL) - StringBuf_Printf(&buf, msg_txt(346), g->name); // " | Guild: '%s'" - break; - } - } - clif_displaymessage(fd, StringBuf_Value(&buf)); - StringBuf_Clear(&buf); - count++; - } - } - mapit_free(iter); - - if (map_id < 0) { - if (count == 0) - StringBuf_Printf(&buf, msg_txt(28)); // No player found. - else if (count == 1) - StringBuf_Printf(&buf, msg_txt(29)); // 1 player found. - else - StringBuf_Printf(&buf, msg_txt(30), count); // %d players found. - } else { - if (count == 0) - StringBuf_Printf(&buf, msg_txt(54), map[map_id].name); // No player found in map '%s'. - else if (count == 1) - StringBuf_Printf(&buf, msg_txt(55), map[map_id].name); // 1 player found in map '%s'. - else - StringBuf_Printf(&buf, msg_txt(56), count, map[map_id].name); // %d players found in map '%s'. - } - clif_displaymessage(fd, StringBuf_Value(&buf)); - StringBuf_Destroy(&buf); - return 0; + struct map_session_data *pl_sd = NULL; + struct s_mapiterator *iter = NULL; + char map_name[MAP_NAME_LENGTH_EXT] = ""; + char player_name[NAME_LENGTH] = ""; + int count = 0; + int level = 0; + StringBuf buf; + /** + * 1 = @who : Player name, [Title], [Party name], [Guild name] + * 2 = @who2 : Player name, [Title], BLvl, JLvl, Job + * 3 = @who3 : [CID/AID] Player name [Title], Map, X, Y + */ + int display_type = 1; + int map_id = -1; + + nullpo_retr(-1, sd); + + if (strstr(command, "map") != NULL) { + if (sscanf(message, "%15s %23s", map_name, player_name) < 1 || (map_id = map_mapname2mapid(map_name)) < 0) + map_id = sd->bl.m; + } else { + sscanf(message, "%23s", player_name); + } + + if (strstr(command, "2") != NULL) + display_type = 2; + else if (strstr(command, "3") != NULL) + display_type = 3; + + level = pc_get_group_level(sd); + StringBuf_Init(&buf); + + iter = mapit_getallusers(); + for (pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter)) { + if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pc_get_group_level(pl_sd) > level)) { // you can look only lower or same level + if (stristr(pl_sd->status.name, player_name) == NULL // search with no case sensitive + || (map_id >= 0 && pl_sd->bl.m != map_id)) + continue; + switch (display_type) { + case 2: { + StringBuf_Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " + if (pc_get_group_id(pl_sd) > 0) // Player title, if exists + StringBuf_Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " + StringBuf_Printf(&buf, msg_txt(347), pl_sd->status.base_level, pl_sd->status.job_level, + job_name(pl_sd->status.class_)); // "| Lv:%d/%d | Job: %s" + break; + } + case 3: { + if (pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID)) + StringBuf_Printf(&buf, msg_txt(912), pl_sd->status.char_id, pl_sd->status.account_id); // "(CID:%d/AID:%d) " + StringBuf_Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " + if (pc_get_group_id(pl_sd) > 0) // Player title, if exists + StringBuf_Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " + StringBuf_Printf(&buf, msg_txt(348), mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); // "| Location: %s %d %d" + break; + } + default: { + struct party_data *p = party_search(pl_sd->status.party_id); + struct guild *g = guild_search(pl_sd->status.guild_id); + + StringBuf_Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " + if (pc_get_group_id(pl_sd) > 0) // Player title, if exists + StringBuf_Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " + if (p != NULL) + StringBuf_Printf(&buf, msg_txt(345), p->party.name); // " | Party: '%s'" + if (g != NULL) + StringBuf_Printf(&buf, msg_txt(346), g->name); // " | Guild: '%s'" + break; + } + } + clif_displaymessage(fd, StringBuf_Value(&buf)); + StringBuf_Clear(&buf); + count++; + } + } + mapit_free(iter); + + if (map_id < 0) { + if (count == 0) + StringBuf_Printf(&buf, msg_txt(28)); // No player found. + else if (count == 1) + StringBuf_Printf(&buf, msg_txt(29)); // 1 player found. + else + StringBuf_Printf(&buf, msg_txt(30), count); // %d players found. + } else { + if (count == 0) + StringBuf_Printf(&buf, msg_txt(54), map[map_id].name); // No player found in map '%s'. + else if (count == 1) + StringBuf_Printf(&buf, msg_txt(55), map[map_id].name); // 1 player found in map '%s'. + else + StringBuf_Printf(&buf, msg_txt(56), count, map[map_id].name); // %d players found in map '%s'. + } + clif_displaymessage(fd, StringBuf_Value(&buf)); + StringBuf_Destroy(&buf); + return 0; } /*========================================== @@ -718,83 +711,85 @@ ACMD_FUNC(who) *------------------------------------------*/ ACMD_FUNC(whogm) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; - int j, count; - int pl_level, level; - char match_text[CHAT_SIZE_MAX]; - char player_name[NAME_LENGTH]; - struct guild *g; - struct party_data *p; - - 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)); - - if (sscanf(message, "%199[^\n]", match_text) < 1) - strcpy(match_text, ""); - for (j = 0; match_text[j]; j++) - match_text[j] = TOLOWER(match_text[j]); - - count = 0; - level = pc_get_group_level(sd); - - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - pl_level = pc_get_group_level(pl_sd); - if (!pl_level) - continue; - - if (match_text[0]) { - memcpy(player_name, pl_sd->status.name, NAME_LENGTH); - for (j = 0; player_name[j]; j++) - player_name[j] = TOLOWER(player_name[j]); - // search with no case sensitive - if (strstr(player_name, match_text) == NULL) - continue; - } - if (pl_level > level) { - if (pl_sd->sc.option & OPTION_INVISIBLE) - continue; - sprintf(atcmd_output, msg_txt(913), pl_sd->status.name); // Name: %s (GM) - clif_displaymessage(fd, atcmd_output); - count++; - continue; - } - - sprintf(atcmd_output, msg_txt(914), // Name: %s (GM:%d) | Location: %s %d %d - pl_sd->status.name, pl_level, - mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, atcmd_output); - - sprintf(atcmd_output, msg_txt(915), // 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); - - p = party_search(pl_sd->status.party_id); - g = guild_search(pl_sd->status.guild_id); - - sprintf(atcmd_output,msg_txt(916), // Party: '%s' | Guild: '%s' - p?p->party.name:msg_txt(917), g?g->name:msg_txt(917)); // None. - - clif_displaymessage(fd, atcmd_output); - count++; - } - mapit_free(iter); - - if (count == 0) - clif_displaymessage(fd, msg_txt(150)); // No GM found. - else if (count == 1) - clif_displaymessage(fd, msg_txt(151)); // 1 GM found. - else { - sprintf(atcmd_output, msg_txt(152), count); // %d GMs found. - clif_displaymessage(fd, atcmd_output); - } - - return 0; + struct map_session_data* pl_sd; + struct s_mapiterator* iter; + int j, count; + int pl_level, level; + char match_text[CHAT_SIZE_MAX]; + char player_name[NAME_LENGTH]; + struct guild *g; + struct party_data *p; + + 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)); + + if (sscanf(message, "%199[^\n]", match_text) < 1) + strcpy(match_text, ""); + for (j = 0; match_text[j]; j++) + match_text[j] = TOLOWER(match_text[j]); + + count = 0; + level = pc_get_group_level(sd); + + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + pl_level = pc_get_group_level(pl_sd); + if (!pl_level) + continue; + + if (match_text[0]) + { + memcpy(player_name, pl_sd->status.name, NAME_LENGTH); + for (j = 0; player_name[j]; j++) + player_name[j] = TOLOWER(player_name[j]); + // search with no case sensitive + if (strstr(player_name, match_text) == NULL) + continue; + } + if (pl_level > level) { + if (pl_sd->sc.option & OPTION_INVISIBLE) + continue; + sprintf(atcmd_output, msg_txt(913), pl_sd->status.name); // Name: %s (GM) + clif_displaymessage(fd, atcmd_output); + count++; + continue; + } + + sprintf(atcmd_output, msg_txt(914), // Name: %s (GM:%d) | Location: %s %d %d + pl_sd->status.name, pl_level, + mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); + clif_displaymessage(fd, atcmd_output); + + sprintf(atcmd_output, msg_txt(915), // 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); + + p = party_search(pl_sd->status.party_id); + g = guild_search(pl_sd->status.guild_id); + + sprintf(atcmd_output,msg_txt(916), // Party: '%s' | Guild: '%s' + p?p->party.name:msg_txt(917), g?g->name:msg_txt(917)); // None. + + clif_displaymessage(fd, atcmd_output); + count++; + } + mapit_free(iter); + + if (count == 0) + clif_displaymessage(fd, msg_txt(150)); // No GM found. + else if (count == 1) + clif_displaymessage(fd, msg_txt(151)); // 1 GM found. + else { + sprintf(atcmd_output, msg_txt(152), count); // %d GMs found. + clif_displaymessage(fd, atcmd_output); + } + + return 0; } /*========================================== @@ -802,17 +797,17 @@ ACMD_FUNC(whogm) *------------------------------------------*/ ACMD_FUNC(save) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - pc_setsavepoint(sd, sd->mapindex, sd->bl.x, sd->bl.y); - if (sd->status.pet_id > 0 && sd->pd) - intif_save_petdata(sd->status.account_id, &sd->pd->pet); + pc_setsavepoint(sd, sd->mapindex, sd->bl.x, sd->bl.y); + if (sd->status.pet_id > 0 && sd->pd) + intif_save_petdata(sd->status.account_id, &sd->pd->pet); - chrif_save(sd,0); + chrif_save(sd,0); - clif_displaymessage(fd, msg_txt(6)); // Your save point has been changed. + clif_displaymessage(fd, msg_txt(6)); // Your save point has been changed. - return 0; + return 0; } /*========================================== @@ -820,24 +815,24 @@ ACMD_FUNC(save) *------------------------------------------*/ ACMD_FUNC(load) { - int m; + int m; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - m = map_mapindex2mapid(sd->status.save_point.map); - if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(249)); // You are not authorized to warp to your save map. - return -1; - } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. - return -1; - } + m = map_mapindex2mapid(sd->status.save_point.map); + if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(249)); // You are not authorized to warp to your save map. + return -1; + } + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. + return -1; + } - pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_OUTSIGHT); - clif_displaymessage(fd, msg_txt(7)); // Warping to save point.. + pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_OUTSIGHT); + clif_displaymessage(fd, msg_txt(7)); // Warping to save point.. - return 0; + return 0; } /*========================================== @@ -845,22 +840,22 @@ ACMD_FUNC(load) *------------------------------------------*/ ACMD_FUNC(speed) { - int speed; + int speed; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d", &speed) < 1) { - sprintf(atcmd_output, msg_txt(918), MIN_WALK_SPEED, MAX_WALK_SPEED); // Please enter a speed value (usage: @speed <%d-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; - } + if (!message || !*message || sscanf(message, "%d", &speed) < 1) { + sprintf(atcmd_output, msg_txt(918), MIN_WALK_SPEED, MAX_WALK_SPEED); // Please enter a speed value (usage: @speed <%d-%d>). + clif_displaymessage(fd, atcmd_output); + return -1; + } - sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED); - status_calc_bl(&sd->bl, SCB_SPEED); - clif_displaymessage(fd, msg_txt(8)); // Speed changed. - return 0; + sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED); + status_calc_bl(&sd->bl, SCB_SPEED); + clif_displaymessage(fd, msg_txt(8)); // Speed changed. + return 0; } /*========================================== @@ -868,20 +863,20 @@ ACMD_FUNC(speed) *------------------------------------------*/ ACMD_FUNC(storage) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag) - return -1; + if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag) + return -1; - if (storage_storageopen(sd) == 1) { - //Already open. - clif_displaymessage(fd, msg_txt(250)); - return -1; - } + if (storage_storageopen(sd) == 1) + { //Already open. + clif_displaymessage(fd, msg_txt(250)); + return -1; + } - clif_displaymessage(fd, msg_txt(919)); // Storage opened. + clif_displaymessage(fd, msg_txt(919)); // Storage opened. - return 0; + return 0; } @@ -890,29 +885,29 @@ ACMD_FUNC(storage) *------------------------------------------*/ ACMD_FUNC(guildstorage) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!sd->status.guild_id) { - clif_displaymessage(fd, msg_txt(252)); - return -1; - } + if (!sd->status.guild_id) { + clif_displaymessage(fd, msg_txt(252)); + return -1; + } - if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading) - return -1; + if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading) + return -1; - if (sd->state.storage_flag == 1) { - clif_displaymessage(fd, msg_txt(250)); - return -1; - } + if (sd->state.storage_flag == 1) { + clif_displaymessage(fd, msg_txt(250)); + return -1; + } - if (sd->state.storage_flag == 2) { - clif_displaymessage(fd, msg_txt(251)); - return -1; - } + if (sd->state.storage_flag == 2) { + clif_displaymessage(fd, msg_txt(251)); + return -1; + } - storage_guild_storageopen(sd); - clif_displaymessage(fd, msg_txt(920)); // Guild storage opened. - return 0; + storage_guild_storageopen(sd); + clif_displaymessage(fd, msg_txt(920)); // Guild storage opened. + return 0; } /*========================================== @@ -920,34 +915,34 @@ ACMD_FUNC(guildstorage) *------------------------------------------*/ ACMD_FUNC(option) { - int param1 = 0, param2 = 0, param3 = 0; - nullpo_retr(-1, sd); + 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) { - // failed to match the parameters so inform the user of the options - const char *text = NULL; + if (!message || !*message || sscanf(message, "%d %d %d", ¶m1, ¶m2, ¶m3) < 1 || param1 < 0 || param2 < 0 || param3 < 0) + {// failed to match the parameters so inform the user of the options + const char* text = NULL; - // attempt to find the setting information for this command - text = atcommand_help_string(command); + // attempt to find the setting information for this command + text = atcommand_help_string( command ); - // notify the user of the requirement to enter an option - clif_displaymessage(fd, msg_txt(921)); // Please enter at least one option. + // notify the user of the requirement to enter an option + clif_displaymessage(fd, msg_txt(921)); // Please enter at least one option. - if (text) { - // send the help text associated with this command - clif_displaymessage(fd, text); - } + if( text ) + {// send the help text associated with this command + clif_displaymessage( fd, text ); + } - return -1; - } + return -1; + } - sd->sc.opt1 = param1; - sd->sc.opt2 = param2; - pc_setoption(sd, param3); + sd->sc.opt1 = param1; + sd->sc.opt2 = param2; + pc_setoption(sd, param3); - clif_displaymessage(fd, msg_txt(9)); // Options changed. + clif_displaymessage(fd, msg_txt(9)); // Options changed. - return 0; + return 0; } /*========================================== @@ -955,41 +950,41 @@ ACMD_FUNC(option) *------------------------------------------*/ ACMD_FUNC(hide) { - nullpo_retr(-1, sd); - if (sd->sc.option & OPTION_INVISIBLE) { - sd->sc.option &= ~OPTION_INVISIBLE; - if (sd->disguise) - status_set_viewdata(&sd->bl, sd->disguise); - else - status_set_viewdata(&sd->bl, sd->status.class_); - clif_displaymessage(fd, msg_txt(10)); // Invisible: Off + nullpo_retr(-1, sd); + if (sd->sc.option & OPTION_INVISIBLE) { + sd->sc.option &= ~OPTION_INVISIBLE; + if (sd->disguise) + status_set_viewdata(&sd->bl, sd->disguise); + else + status_set_viewdata(&sd->bl, sd->status.class_); + clif_displaymessage(fd, msg_txt(10)); // Invisible: Off - // increment the number of pvp players on the map - map[sd->bl.m].users_pvp++; + // increment the number of pvp players on the map + map[sd->bl.m].users_pvp++; - if (map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank) { - // register the player for ranking calculations - sd->pvp_timer = add_timer(gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0); - } - //bugreport:2266 - map_foreachinmovearea(clif_insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl); - } else { - sd->sc.option |= OPTION_INVISIBLE; - sd->vd.class_ = INVISIBLE_CLASS; - clif_displaymessage(fd, msg_txt(11)); // Invisible: On + if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank ) + {// register the player for ranking calculations + sd->pvp_timer = add_timer( gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0 ); + } + //bugreport:2266 + map_foreachinmovearea(clif_insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl); + } else { + sd->sc.option |= OPTION_INVISIBLE; + sd->vd.class_ = INVISIBLE_CLASS; + clif_displaymessage(fd, msg_txt(11)); // Invisible: On - // decrement the number of pvp players on the map - map[sd->bl.m].users_pvp--; + // decrement the number of pvp players on the map + map[sd->bl.m].users_pvp--; - if (map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER) { - // unregister the player for ranking - delete_timer(sd->pvp_timer, pc_calc_pvprank_timer); - sd->pvp_timer = INVALID_TIMER; - } - } - clif_changeoption(&sd->bl); + if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) + {// unregister the player for ranking + delete_timer( sd->pvp_timer, pc_calc_pvprank_timer ); + sd->pvp_timer = INVALID_TIMER; + } + } + clif_changeoption(&sd->bl); - return 0; + return 0; } /*========================================== @@ -997,53 +992,183 @@ ACMD_FUNC(hide) *------------------------------------------*/ ACMD_FUNC(jobchange) { - int job = 0, upper = 0; - const char *text; - nullpo_retr(-1, sd); - - if (!message || !*message || sscanf(message, "%d %d", &job, &upper) < 1) { - int i, found = 0; - - for (i = JOB_NOVICE; i < JOB_MAX; ++i) { - if (strncmpi(message, job_name(i), 16) == 0) { - job = i; - upper = 0; - found = 1; - break; - } - } - - if (!found) { - text = atcommand_help_string(command); - if (text) - clif_displaymessage(fd, text); - return -1; - } - } - - if (job == JOB_KNIGHT2 || job == JOB_CRUSADER2 || job == JOB_WEDDING || job == JOB_XMAS || job == JOB_SUMMER - || job == JOB_LORD_KNIGHT2 || job == JOB_PALADIN2 || job == JOB_BABY_KNIGHT2 || job == JOB_BABY_CRUSADER2 || job == JOB_STAR_GLADIATOR2 - || (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2) || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2) - ) { // Deny direct transformation into dummy jobs - clif_displaymessage(fd, msg_txt(923)); //"You can not change to this job by command." - return 0; - } - - if (pcdb_checkid(job)) { - if (pc_jobchange(sd, job, upper) == 0) - clif_displaymessage(fd, msg_txt(12)); // Your job has been changed. - else { - clif_displaymessage(fd, msg_txt(155)); // You are unable to change your job. - return -1; - } - } else { - text = atcommand_help_string(command); - if (text) - clif_displaymessage(fd, text); - return -1; - } - - return 0; + //FIXME: redundancy, potentially wrong code, should use job_name() or similar instead of hardcoding the table [ultramage] + int job = 0, upper = 0; + const char* text; + nullpo_retr(-1, sd); + + if (!message || !*message || sscanf(message, "%d %d", &job, &upper) < 1) + { + int i, found = 0; + const struct { char name[24]; int id; } jobs[] = { + { "novice", 0 }, + { "swordman", 1 }, + { "swordsman", 1 }, + { "magician", 2 }, + { "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 }, + { "gunslinger", 24 }, + { "gunner", 24 }, + { "ninja", 25 }, + { "novice high", 4001 }, + { "high novice", 4001 }, + { "swordman high", 4002 }, + { "swordsman high", 4002 }, + { "magician high", 4003 }, + { "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 swordman", 4024 }, + { "baby swordsman", 4024 }, + { "baby magician", 4025 }, + { "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 }, + { "taekwon", 4046 }, + { "taekwon boy", 4046 }, + { "taekwon girl", 4046 }, + { "star gladiator", 4047 }, + { "soul linker", 4049 }, + { "gangsi", 4050 }, + { "bongun", 4050 }, + { "munak", 4050 }, + { "death knight", 4051 }, + { "dark collector", 4052 }, + { "rune knight", 4054 }, + { "warlock", 4055 }, + { "ranger", 4056 }, + { "arch bishop", 4057 }, + { "mechanic", 4058 }, + { "guillotine", 4059 }, + { "rune knight2", 4060 }, + { "warlock2", 4061 }, + { "ranger2", 4062 }, + { "arch bishop2", 4063 }, + { "mechanic2", 4064 }, + { "guillotine2", 4065 }, + { "royal guard", 4066 }, + { "sorcerer", 4067 }, + { "minstrel", 4068 }, + { "wanderer", 4069 }, + { "sura", 4070 }, + { "genetic", 4071 }, + { "shadow chaser", 4072 }, + { "royal guard2", 4073 }, + { "sorcerer2", 4074 }, + { "minstrel2", 4075 }, + { "wanderer2", 4076 }, + { "sura2", 4077 }, + { "genetic2", 4078 }, + { "shadow chaser2", 4079 }, + { "baby rune", 4096 }, + { "baby warlock", 4097 }, + { "baby ranger", 4098 }, + { "baby bishop", 4099 }, + { "baby mechanic", 4100 }, + { "baby cross", 4101 }, + { "baby guard", 4102 }, + { "baby sorcerer", 4103 }, + { "baby minstrel", 4104 }, + { "baby wanderer", 4105 }, + { "baby sura", 4106 }, + { "baby genetic", 4107 }, + { "baby chaser", 4108 }, + { "super novice e", 4190 }, + { "super baby e", 4191 }, + { "kagerou", 4211 }, + { "oboro", 4212 }, + }; + + for (i=0; i < ARRAYLENGTH(jobs); i++) { + if (strncmpi(message, jobs[i].name, 16) == 0) { + job = jobs[i].id; + upper = 0; + found = 1; + break; + } + } + + if (!found) { + text = atcommand_help_string(command); + if (text) clif_displaymessage(fd, text); + return -1; + } + } + + if (job == 13 || job == 21 || job == 22 || job == 26 || job == 27 || job == 4014 || job == 4022 || job == 4036 || job == 4044 || job == 4048 + || (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2) || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2) + ) // Deny direct transformation into dummy jobs + {clif_displaymessage(fd, msg_txt(923)); //"You can not change to this job by command." + return 0;} + + if (pcdb_checkid(job)) + { + if (pc_jobchange(sd, job, upper) == 0) + clif_displaymessage(fd, msg_txt(12)); // Your job has been changed. + else { + clif_displaymessage(fd, msg_txt(155)); // You are unable to change your job. + return -1; + } + } else { + text = atcommand_help_string(command); + if (text) clif_displaymessage(fd, text); + return -1; + } + + return 0; } /*========================================== @@ -1051,12 +1176,12 @@ ACMD_FUNC(jobchange) *------------------------------------------*/ ACMD_FUNC(kill) { - nullpo_retr(-1, sd); - status_kill(&sd->bl); - clif_displaymessage(sd->fd, msg_txt(13)); // A pity! You've died. - if (fd != sd->fd) - clif_displaymessage(fd, msg_txt(14)); // Character killed. - return 0; + nullpo_retr(-1, sd); + status_kill(&sd->bl); + clif_displaymessage(sd->fd, msg_txt(13)); // A pity! You've died. + if (fd != sd->fd) + clif_displaymessage(fd, msg_txt(14)); // Character killed. + return 0; } /*========================================== @@ -1064,14 +1189,15 @@ ACMD_FUNC(kill) *------------------------------------------*/ ACMD_FUNC(alive) { - nullpo_retr(-1, sd); - if (!status_revive(&sd->bl, 100, 100)) { - clif_displaymessage(fd, msg_txt(667)); - return -1; - } - clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); - clif_displaymessage(fd, msg_txt(16)); // You've been revived! It's a miracle! - return 0; + nullpo_retr(-1, sd); + if (!status_revive(&sd->bl, 100, 100)) + { + clif_displaymessage(fd, msg_txt(667)); + return -1; + } + clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); + clif_displaymessage(fd, msg_txt(16)); // You've been revived! It's a miracle! + return 0; } /*========================================== @@ -1079,35 +1205,35 @@ ACMD_FUNC(alive) *------------------------------------------*/ ACMD_FUNC(kami) { - unsigned long color=0; - nullpo_retr(-1, sd); + unsigned long color=0; + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (*(command + 5) != 'c' && *(command + 5) != 'C') { - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(980)); // Please enter a message (usage: @kami <message>). - return -1; - } + if(*(command + 5) != 'c' && *(command + 5) != 'C') { + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(980)); // Please enter a message (usage: @kami <message>). + return -1; + } - sscanf(message, "%199[^\n]", atcmd_output); - if (strstr(command, "l") != NULL) - clif_broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP); - else - intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(command + 5) == 'b' || *(command + 5) == 'B') ? 0x10 : 0); - } else { - if (!message || !*message || (sscanf(message, "%lx %199[^\n]", &color, atcmd_output) < 2)) { - clif_displaymessage(fd, msg_txt(981)); // Please enter color and message (usage: @kamic <color> <message>). - return -1; - } + sscanf(message, "%199[^\n]", atcmd_output); + if (strstr(command, "l") != NULL) + clif_broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP); + else + intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(command + 5) == 'b' || *(command + 5) == 'B') ? 0x10 : 0); + } else { + if(!message || !*message || (sscanf(message, "%lx %199[^\n]", &color, atcmd_output) < 2)) { + clif_displaymessage(fd, msg_txt(981)); // Please enter color and message (usage: @kamic <color> <message>). + return -1; + } - if (color > 0xFFFFFF) { - clif_displaymessage(fd, msg_txt(982)); // Invalid color. - return -1; - } - intif_broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0); - } - return 0; + if(color > 0xFFFFFF) { + clif_displaymessage(fd, msg_txt(982)); // Invalid color. + return -1; + } + intif_broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0); + } + return 0; } /*========================================== @@ -1115,57 +1241,57 @@ ACMD_FUNC(kami) *------------------------------------------*/ ACMD_FUNC(heal) { - int hp = 0, sp = 0; // [Valaris] thanks to fov - nullpo_retr(-1, sd); - - sscanf(message, "%d %d", &hp, &sp); - - // some overflow checks - if (hp == INT_MIN) hp++; - if (sp == INT_MIN) sp++; - - if (hp == 0 && sp == 0) { - if (!status_percent_heal(&sd->bl, 100, 100)) - clif_displaymessage(fd, msg_txt(157)); // HP and SP have already been recovered. - else - clif_displaymessage(fd, msg_txt(17)); // HP, SP recovered. - return 0; - } - - if (hp > 0 && sp >= 0) { - if (!status_heal(&sd->bl, hp, sp, 0)) - clif_displaymessage(fd, msg_txt(157)); // HP and SP are already with the good value. - else - clif_displaymessage(fd, msg_txt(17)); // HP, SP recovered. - return 0; - } - - if (hp < 0 && sp <= 0) { - status_damage(NULL, &sd->bl, -hp, -sp, 0, 0); - clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, 4, 0); - clif_displaymessage(fd, msg_txt(156)); // HP or/and SP modified. - return 0; - } - - //Opposing signs. - if (hp) { - if (hp > 0) - status_heal(&sd->bl, hp, 0, 0); - else { - status_damage(NULL, &sd->bl, -hp, 0, 0, 0); - clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, 4, 0); - } - } - - if (sp) { - if (sp > 0) - status_heal(&sd->bl, 0, sp, 0); - else - status_damage(NULL, &sd->bl, 0, -sp, 0, 0); - } - - clif_displaymessage(fd, msg_txt(156)); // HP or/and SP modified. - return 0; + int hp = 0, sp = 0; // [Valaris] thanks to fov + nullpo_retr(-1, sd); + + sscanf(message, "%d %d", &hp, &sp); + + // some overflow checks + if( hp == INT_MIN ) hp++; + if( sp == INT_MIN ) sp++; + + if ( hp == 0 && sp == 0 ) { + if (!status_percent_heal(&sd->bl, 100, 100)) + clif_displaymessage(fd, msg_txt(157)); // HP and SP have already been recovered. + else + clif_displaymessage(fd, msg_txt(17)); // HP, SP recovered. + return 0; + } + + if ( hp > 0 && sp >= 0 ) { + if(!status_heal(&sd->bl, hp, sp, 0)) + clif_displaymessage(fd, msg_txt(157)); // HP and SP are already with the good value. + else + clif_displaymessage(fd, msg_txt(17)); // HP, SP recovered. + return 0; + } + + if ( hp < 0 && sp <= 0 ) { + status_damage(NULL, &sd->bl, -hp, -sp, 0, 0); + clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, 4, 0); + clif_displaymessage(fd, msg_txt(156)); // HP or/and SP modified. + return 0; + } + + //Opposing signs. + if ( hp ) { + if (hp > 0) + status_heal(&sd->bl, hp, 0, 0); + else { + status_damage(NULL, &sd->bl, -hp, 0, 0, 0); + clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, 4, 0); + } + } + + if ( sp ) { + if (sp > 0) + status_heal(&sd->bl, 0, sp, 0); + else + status_damage(NULL, &sd->bl, 0, -sp, 0, 0); + } + + clif_displaymessage(fd, msg_txt(156)); // HP or/and SP modified. + return 0; } /*========================================== @@ -1173,53 +1299,54 @@ ACMD_FUNC(heal) *------------------------------------------*/ ACMD_FUNC(item) { - char item_name[100]; - int number = 0, item_id, flag = 0; - struct item item_tmp; - struct item_data *item_data; - int get_count, i; - nullpo_retr(-1, sd); - - memset(item_name, '\0', sizeof(item_name)); - - if (!message || !*message || ( - sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 && - sscanf(message, "%99s %d", item_name, &number) < 1 - )) { - clif_displaymessage(fd, msg_txt(983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>). - return -1; - } - - if (number <= 0) - number = 1; - - if ((item_data = itemdb_searchname(item_name)) == NULL && - (item_data = itemdb_exists(atoi(item_name))) == NULL) { - clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. - return -1; - } - - item_id = item_data->nameid; - get_count = number; - //Check if it's stackable. - if (!itemdb_isstackable2(item_data)) - get_count = 1; - - for (i = 0; i < number; i += get_count) { - // if not pet egg - if (!pet_create_egg(sd, item_id)) { - memset(&item_tmp, 0, sizeof(item_tmp)); - item_tmp.nameid = item_id; - item_tmp.identify = 1; - - if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND))) - clif_additem(sd, 0, 0, flag); - } - } - - if (flag == 0) - clif_displaymessage(fd, msg_txt(18)); // Item created. - return 0; + char item_name[100]; + int number = 0, item_id, flag = 0; + struct item item_tmp; + struct item_data *item_data; + int get_count, i; + nullpo_retr(-1, sd); + + memset(item_name, '\0', sizeof(item_name)); + + if (!message || !*message || ( + sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 && + sscanf(message, "%99s %d", item_name, &number) < 1 + )) { + clif_displaymessage(fd, msg_txt(983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>). + return -1; + } + + if (number <= 0) + number = 1; + + if ((item_data = itemdb_searchname(item_name)) == NULL && + (item_data = itemdb_exists(atoi(item_name))) == NULL) + { + clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. + return -1; + } + + item_id = item_data->nameid; + get_count = number; + //Check if it's stackable. + if (!itemdb_isstackable2(item_data)) + get_count = 1; + + for (i = 0; i < number; i += get_count) { + // if not pet egg + if (!pet_create_egg(sd, item_id)) { + memset(&item_tmp, 0, sizeof(item_tmp)); + item_tmp.nameid = item_id; + item_tmp.identify = 1; + + if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND))) + clif_additem(sd, 0, 0, flag); + } + } + + if (flag == 0) + clif_displaymessage(fd, msg_txt(18)); // Item created. + return 0; } /*========================================== @@ -1227,76 +1354,76 @@ ACMD_FUNC(item) *------------------------------------------*/ ACMD_FUNC(item2) { - struct item item_tmp; - struct item_data *item_data; - char item_name[100]; - int item_id, number = 0; - int identify = 0, refine = 0, attr = 0; - int c1 = 0, c2 = 0, c3 = 0, c4 = 0; - int flag = 0; - int loop, get_count, i; - nullpo_retr(-1, sd); - - memset(item_name, '\0', sizeof(item_name)); - - if (!message || !*message || ( - sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 && - sscanf(message, "%99s %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 - )) { - clif_displaymessage(fd, msg_txt(984)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity> - clif_displaymessage(fd, msg_txt(985)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4>). - 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) { - loop = 1; - get_count = number; - if (item_data->type == IT_WEAPON || item_data->type == IT_ARMOR || - item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR) { - loop = number; - get_count = 1; - if (item_data->type == IT_PETEGG) { - identify = 1; - refine = 0; - } - if (item_data->type == IT_PETARMOR) - refine = 0; - if (refine > MAX_REFINE) - refine = MAX_REFINE; - } else { - identify = 1; - refine = attr = 0; - } - for (i = 0; i < loop; i++) { - memset(&item_tmp, 0, sizeof(item_tmp)); - item_tmp.nameid = item_id; - item_tmp.identify = identify; - item_tmp.refine = refine; - item_tmp.attribute = attr; - item_tmp.card[0] = c1; - item_tmp.card[1] = c2; - item_tmp.card[2] = c3; - item_tmp.card[3] = c4; - if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND))) - clif_additem(sd, 0, 0, flag); - } - - if (flag == 0) - clif_displaymessage(fd, msg_txt(18)); // Item created. - } else { - clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. - return -1; - } - - return 0; + struct item item_tmp; + struct item_data *item_data; + char item_name[100]; + int item_id, number = 0; + int identify = 0, refine = 0, attr = 0; + int c1 = 0, c2 = 0, c3 = 0, c4 = 0; + int flag = 0; + int loop, get_count, i; + nullpo_retr(-1, sd); + + memset(item_name, '\0', sizeof(item_name)); + + if (!message || !*message || ( + sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 && + sscanf(message, "%99s %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 + )) { + clif_displaymessage(fd, msg_txt(984)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity> + clif_displaymessage(fd, msg_txt(985)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4>). + 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) { + loop = 1; + get_count = number; + if (item_data->type == IT_WEAPON || item_data->type == IT_ARMOR || + item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR) { + loop = number; + get_count = 1; + if (item_data->type == IT_PETEGG) { + identify = 1; + refine = 0; + } + if (item_data->type == IT_PETARMOR) + refine = 0; + if (refine > MAX_REFINE) + refine = MAX_REFINE; + } else { + identify = 1; + refine = attr = 0; + } + for (i = 0; i < loop; i++) { + memset(&item_tmp, 0, sizeof(item_tmp)); + item_tmp.nameid = item_id; + item_tmp.identify = identify; + item_tmp.refine = refine; + item_tmp.attribute = attr; + item_tmp.card[0] = c1; + item_tmp.card[1] = c2; + item_tmp.card[2] = c3; + item_tmp.card[3] = c4; + if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND))) + clif_additem(sd, 0, 0, flag); + } + + if (flag == 0) + clif_displaymessage(fd, msg_txt(18)); // Item created. + } else { + clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. + return -1; + } + + return 0; } /*========================================== @@ -1304,17 +1431,17 @@ ACMD_FUNC(item2) *------------------------------------------*/ ACMD_FUNC(itemreset) { - int i; - nullpo_retr(-1, sd); + 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) { - pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_COMMAND); - } - } - clif_displaymessage(fd, msg_txt(20)); // All of your items have been removed. + for (i = 0; i < MAX_INVENTORY; i++) { + if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0) { + pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_COMMAND); + } + } + clif_displaymessage(fd, msg_txt(20)); // All of your items have been removed. - return 0; + return 0; } /*========================================== @@ -1322,59 +1449,59 @@ ACMD_FUNC(itemreset) *------------------------------------------*/ ACMD_FUNC(baselevelup) { - int level=0, i=0, status_point=0; - nullpo_retr(-1, sd); - level = atoi(message); - - if (!message || !*message || !level) { - clif_displaymessage(fd, msg_txt(986)); // Please enter a level adjustment (usage: @lvup/@blevel/@baselvlup <number of levels>). - return -1; - } - - if (level > 0) { - if (sd->status.base_level >= pc_maxbaselv(sd)) { // check for max level by Valaris - clif_displaymessage(fd, msg_txt(47)); // Base level can't go any higher. - return -1; - } // End Addition - if ((unsigned int)level > pc_maxbaselv(sd) || (unsigned int)level > pc_maxbaselv(sd) - sd->status.base_level) // fix positiv overflow - level = pc_maxbaselv(sd) - sd->status.base_level; - for (i = 0; i < level; i++) - status_point += pc_gets_status_point(sd->status.base_level + i); - - sd->status.status_point += status_point; - sd->status.base_level += (unsigned int)level; - status_percent_heal(&sd->bl, 100, 100); - clif_misceffect(&sd->bl, 0); - clif_displaymessage(fd, msg_txt(21)); // Base level raised. - } else { - if (sd->status.base_level == 1) { - clif_displaymessage(fd, msg_txt(158)); // Base level can't go any lower. - return -1; - } - level*=-1; - if ((unsigned int)level >= sd->status.base_level) - level = sd->status.base_level-1; - for (i = 0; i > -level; i--) - status_point += pc_gets_status_point(sd->status.base_level + i - 1); - if (sd->status.status_point < status_point) - pc_resetstate(sd); - if (sd->status.status_point < status_point) - sd->status.status_point = 0; - else - sd->status.status_point -= status_point; - sd->status.base_level -= (unsigned int)level; - clif_displaymessage(fd, msg_txt(22)); // Base level lowered. - } - sd->status.base_exp = 0; - clif_updatestatus(sd, SP_STATUSPOINT); - clif_updatestatus(sd, SP_BASELEVEL); - clif_updatestatus(sd, SP_BASEEXP); - clif_updatestatus(sd, SP_NEXTBASEEXP); - status_calc_pc(sd, 0); - pc_baselevelchanged(sd); - if (sd->status.party_id) - party_send_levelup(sd); - return 0; + int level=0, i=0, status_point=0; + nullpo_retr(-1, sd); + level = atoi(message); + + if (!message || !*message || !level) { + clif_displaymessage(fd, msg_txt(986)); // Please enter a level adjustment (usage: @lvup/@blevel/@baselvlup <number of levels>). + return -1; + } + + if (level > 0) { + if (sd->status.base_level >= pc_maxbaselv(sd)) { // check for max level by Valaris + clif_displaymessage(fd, msg_txt(47)); // Base level can't go any higher. + return -1; + } // End Addition + if ((unsigned int)level > pc_maxbaselv(sd) || (unsigned int)level > pc_maxbaselv(sd) - sd->status.base_level) // fix positiv overflow + level = pc_maxbaselv(sd) - sd->status.base_level; + for (i = 0; i < level; i++) + status_point += pc_gets_status_point(sd->status.base_level + i); + + sd->status.status_point += status_point; + sd->status.base_level += (unsigned int)level; + status_percent_heal(&sd->bl, 100, 100); + clif_misceffect(&sd->bl, 0); + clif_displaymessage(fd, msg_txt(21)); // Base level raised. + } else { + if (sd->status.base_level == 1) { + clif_displaymessage(fd, msg_txt(158)); // Base level can't go any lower. + return -1; + } + level*=-1; + if ((unsigned int)level >= sd->status.base_level) + level = sd->status.base_level-1; + for (i = 0; i > -level; i--) + status_point += pc_gets_status_point(sd->status.base_level + i - 1); + if (sd->status.status_point < status_point) + pc_resetstate(sd); + if (sd->status.status_point < status_point) + sd->status.status_point = 0; + else + sd->status.status_point -= status_point; + sd->status.base_level -= (unsigned int)level; + clif_displaymessage(fd, msg_txt(22)); // Base level lowered. + } + sd->status.base_exp = 0; + clif_updatestatus(sd, SP_STATUSPOINT); + clif_updatestatus(sd, SP_BASELEVEL); + clif_updatestatus(sd, SP_BASEEXP); + clif_updatestatus(sd, SP_NEXTBASEEXP); + status_calc_pc(sd, 0); + pc_baselevelchanged(sd); + if(sd->status.party_id) + party_send_levelup(sd); + return 0; } /*========================================== @@ -1382,51 +1509,51 @@ ACMD_FUNC(baselevelup) *------------------------------------------*/ ACMD_FUNC(joblevelup) { - int level=0; - nullpo_retr(-1, sd); - - level = atoi(message); - - if (!message || !*message || !level) { - clif_displaymessage(fd, msg_txt(987)); // Please enter a level adjustment (usage: @joblvup/@jlevel/@joblvlup <number of levels>). - return -1; - } - if (level > 0) { - if (sd->status.job_level >= pc_maxjoblv(sd)) { - clif_displaymessage(fd, msg_txt(23)); // Job level can't go any higher. - return -1; - } - if ((unsigned int)level > pc_maxjoblv(sd) || (unsigned int)level > pc_maxjoblv(sd) - sd->status.job_level) // fix positiv overflow - level = pc_maxjoblv(sd) - sd->status.job_level; - sd->status.job_level += (unsigned int)level; - sd->status.skill_point += level; - clif_misceffect(&sd->bl, 1); - clif_displaymessage(fd, msg_txt(24)); // Job level raised. - } else { - if (sd->status.job_level == 1) { - clif_displaymessage(fd, msg_txt(159)); // Job level can't go any lower. - return -1; - } - level *=-1; - if ((unsigned int)level >= sd->status.job_level) // fix negativ overflow - level = sd->status.job_level-1; - sd->status.job_level -= (unsigned int)level; - if (sd->status.skill_point < level) - pc_resetskill(sd,0); //Reset skills since we need to substract more points. - if (sd->status.skill_point < level) - sd->status.skill_point = 0; - else - sd->status.skill_point -= level; - clif_displaymessage(fd, msg_txt(25)); // Job level lowered. - } - sd->status.job_exp = 0; - clif_updatestatus(sd, SP_JOBLEVEL); - clif_updatestatus(sd, SP_JOBEXP); - clif_updatestatus(sd, SP_NEXTJOBEXP); - clif_updatestatus(sd, SP_SKILLPOINT); - status_calc_pc(sd, 0); - - return 0; + int level=0; + nullpo_retr(-1, sd); + + level = atoi(message); + + if (!message || !*message || !level) { + clif_displaymessage(fd, msg_txt(987)); // Please enter a level adjustment (usage: @joblvup/@jlevel/@joblvlup <number of levels>). + return -1; + } + if (level > 0) { + if (sd->status.job_level >= pc_maxjoblv(sd)) { + clif_displaymessage(fd, msg_txt(23)); // Job level can't go any higher. + return -1; + } + if ((unsigned int)level > pc_maxjoblv(sd) || (unsigned int)level > pc_maxjoblv(sd) - sd->status.job_level) // fix positiv overflow + level = pc_maxjoblv(sd) - sd->status.job_level; + sd->status.job_level += (unsigned int)level; + sd->status.skill_point += level; + clif_misceffect(&sd->bl, 1); + clif_displaymessage(fd, msg_txt(24)); // Job level raised. + } else { + if (sd->status.job_level == 1) { + clif_displaymessage(fd, msg_txt(159)); // Job level can't go any lower. + return -1; + } + level *=-1; + if ((unsigned int)level >= sd->status.job_level) // fix negativ overflow + level = sd->status.job_level-1; + sd->status.job_level -= (unsigned int)level; + if (sd->status.skill_point < level) + pc_resetskill(sd,0); //Reset skills since we need to substract more points. + if (sd->status.skill_point < level) + sd->status.skill_point = 0; + else + sd->status.skill_point -= level; + clif_displaymessage(fd, msg_txt(25)); // Job level lowered. + } + sd->status.job_exp = 0; + clif_updatestatus(sd, SP_JOBLEVEL); + clif_updatestatus(sd, SP_JOBEXP); + clif_updatestatus(sd, SP_NEXTJOBEXP); + clif_updatestatus(sd, SP_SKILLPOINT); + status_calc_pc(sd, 0); + + return 0; } /*========================================== @@ -1434,116 +1561,116 @@ ACMD_FUNC(joblevelup) *------------------------------------------*/ ACMD_FUNC(help) { - config_setting_t *help; - const char *text = NULL; - const char *command_name = NULL; - char *default_command = "help"; - - nullpo_retr(-1, sd); - - help = config_lookup(&atcommand_config, "help"); - if (help == NULL) { - clif_displaymessage(fd, msg_txt(27)); // "Commands help is not available." - return -1; - } - - if (!message || !*message) { - command_name = default_command; // If no command_name specified, display help for @help. - } else { - if (*message == atcommand_symbol || *message == charcommand_symbol) - ++message; - command_name = atcommand_checkalias(message); - } - - if (!pc_can_use_command(sd, command_name, COMMAND_ATCOMMAND)) { - sprintf(atcmd_output, msg_txt(153), message); // "%s is Unknown Command" - clif_displaymessage(fd, atcmd_output); - atcommand_get_suggestions(sd, command_name, true); - return -1; - } - - if (!config_setting_lookup_string(help, command_name, &text)) { - sprintf(atcmd_output, msg_txt(988), atcommand_symbol, command_name); // There is no help for %c%s. - clif_displaymessage(fd, atcmd_output); - atcommand_get_suggestions(sd, command_name, true); - return -1; - } - - sprintf(atcmd_output, msg_txt(989), atcommand_symbol, command_name); // Help for command %c%s: - clif_displaymessage(fd, atcmd_output); - - { - // Display aliases - DBIterator *iter; - AtCommandInfo *command_info; - AliasInfo *alias_info = NULL; - StringBuf buf; - bool has_aliases = false; - - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, msg_txt(990)); // Available aliases: - command_info = get_atcommandinfo_byname(command_name); - iter = db_iterator(atcommand_alias_db); - for (alias_info = dbi_first(iter); dbi_exists(iter); alias_info = dbi_next(iter)) { - if (alias_info->command == command_info) { - StringBuf_Printf(&buf, " %s", alias_info->alias); - has_aliases = true; - } - } - dbi_destroy(iter); - if (has_aliases) - clif_displaymessage(fd, StringBuf_Value(&buf)); - StringBuf_Destroy(&buf); - } - - // Display help contents - clif_displaymessage(fd, text); - return 0; + config_setting_t *help; + const char *text = NULL; + const char *command_name = NULL; + char *default_command = "help"; + + nullpo_retr(-1, sd); + + help = config_lookup(&atcommand_config, "help"); + if (help == NULL) { + clif_displaymessage(fd, msg_txt(27)); // "Commands help is not available." + return -1; + } + + if (!message || !*message) { + command_name = default_command; // If no command_name specified, display help for @help. + } else { + if (*message == atcommand_symbol || *message == charcommand_symbol) + ++message; + command_name = atcommand_checkalias(message); + } + + if (!pc_can_use_command(sd, command_name, COMMAND_ATCOMMAND)) { + sprintf(atcmd_output, msg_txt(153), message); // "%s is Unknown Command" + clif_displaymessage(fd, atcmd_output); + atcommand_get_suggestions(sd, command_name, true); + return -1; + } + + if (!config_setting_lookup_string(help, command_name, &text)) { + sprintf(atcmd_output, msg_txt(988), atcommand_symbol, command_name); // There is no help for %c%s. + clif_displaymessage(fd, atcmd_output); + atcommand_get_suggestions(sd, command_name, true); + return -1; + } + + sprintf(atcmd_output, msg_txt(989), atcommand_symbol, command_name); // Help for command %c%s: + clif_displaymessage(fd, atcmd_output); + + { // Display aliases + DBIterator* iter; + AtCommandInfo *command_info; + AliasInfo *alias_info = NULL; + StringBuf buf; + bool has_aliases = false; + + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, msg_txt(990)); // Available aliases: + command_info = get_atcommandinfo_byname(command_name); + iter = db_iterator(atcommand_alias_db); + for (alias_info = dbi_first(iter); dbi_exists(iter); alias_info = dbi_next(iter)) { + if (alias_info->command == command_info) { + StringBuf_Printf(&buf, " %s", alias_info->alias); + has_aliases = true; + } + } + dbi_destroy(iter); + if (has_aliases) + clif_displaymessage(fd, StringBuf_Value(&buf)); + StringBuf_Destroy(&buf); + } + + // Display help contents + clif_displaymessage(fd, text); + return 0; } // helper function, used in foreach calls to stop auto-attack timers // parameter: '0' - everyone, 'id' - only those attacking someone with that id static int atcommand_stopattack(struct block_list *bl,va_list ap) { - struct unit_data *ud = unit_bl2ud(bl); - int id = va_arg(ap, int); - if (ud && ud->attacktimer != INVALID_TIMER && (!id || id == ud->target)) { - unit_stop_attack(bl); - return 1; - } - return 0; + struct unit_data *ud = unit_bl2ud(bl); + int id = va_arg(ap, int); + if (ud && ud->attacktimer != INVALID_TIMER && (!id || id == ud->target)) + { + unit_stop_attack(bl); + return 1; + } + return 0; } /*========================================== * *------------------------------------------*/ static int atcommand_pvpoff_sub(struct block_list *bl,va_list ap) { - TBL_PC *sd = (TBL_PC *)bl; - clif_pvpset(sd, 0, 0, 2); - if (sd->pvp_timer != INVALID_TIMER) { - delete_timer(sd->pvp_timer, pc_calc_pvprank_timer); - sd->pvp_timer = INVALID_TIMER; - } - return 0; + TBL_PC* sd = (TBL_PC*)bl; + clif_pvpset(sd, 0, 0, 2); + if (sd->pvp_timer != INVALID_TIMER) { + delete_timer(sd->pvp_timer, pc_calc_pvprank_timer); + sd->pvp_timer = INVALID_TIMER; + } + return 0; } ACMD_FUNC(pvpoff) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!map[sd->bl.m].flag.pvp) { - clif_displaymessage(fd, msg_txt(160)); // PvP is already Off. - return -1; - } + if (!map[sd->bl.m].flag.pvp) { + clif_displaymessage(fd, msg_txt(160)); // PvP is already Off. + return -1; + } - map[sd->bl.m].flag.pvp = 0; + map[sd->bl.m].flag.pvp = 0; - if (!battle_config.pk_mode) - clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING); - map_foreachinmap(atcommand_pvpoff_sub,sd->bl.m, BL_PC); - map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0); - clif_displaymessage(fd, msg_txt(31)); // PvP: Off. - return 0; + if (!battle_config.pk_mode) + clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING); + map_foreachinmap(atcommand_pvpoff_sub,sd->bl.m, BL_PC); + map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0); + clif_displaymessage(fd, msg_txt(31)); // PvP: Off. + return 0; } /*========================================== @@ -1551,38 +1678,38 @@ ACMD_FUNC(pvpoff) *------------------------------------------*/ static int atcommand_pvpon_sub(struct block_list *bl,va_list ap) { - TBL_PC *sd = (TBL_PC *)bl; - if (sd->pvp_timer == INVALID_TIMER) { - sd->pvp_timer = add_timer(gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0); - sd->pvp_rank = 0; - sd->pvp_lastusers = 0; - sd->pvp_point = 5; - sd->pvp_won = 0; - sd->pvp_lost = 0; - } - return 0; + TBL_PC* sd = (TBL_PC*)bl; + if (sd->pvp_timer == INVALID_TIMER) { + sd->pvp_timer = add_timer(gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0); + sd->pvp_rank = 0; + sd->pvp_lastusers = 0; + sd->pvp_point = 5; + sd->pvp_won = 0; + sd->pvp_lost = 0; + } + return 0; } ACMD_FUNC(pvpon) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (map[sd->bl.m].flag.pvp) { - clif_displaymessage(fd, msg_txt(161)); // PvP is already On. - return -1; - } + if (map[sd->bl.m].flag.pvp) { + clif_displaymessage(fd, msg_txt(161)); // PvP is already On. + return -1; + } - map[sd->bl.m].flag.pvp = 1; + map[sd->bl.m].flag.pvp = 1; - if (!battle_config.pk_mode) { - // display pvp circle and rank - clif_map_property_mapall(sd->bl.m, MAPPROPERTY_FREEPVPZONE); - map_foreachinmap(atcommand_pvpon_sub,sd->bl.m, BL_PC); - } + if (!battle_config.pk_mode) + {// display pvp circle and rank + clif_map_property_mapall(sd->bl.m, MAPPROPERTY_FREEPVPZONE); + map_foreachinmap(atcommand_pvpon_sub,sd->bl.m, BL_PC); + } - clif_displaymessage(fd, msg_txt(32)); // PvP: On. + clif_displaymessage(fd, msg_txt(32)); // PvP: On. - return 0; + return 0; } /*========================================== @@ -1590,19 +1717,19 @@ ACMD_FUNC(pvpon) *------------------------------------------*/ ACMD_FUNC(gvgoff) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!map[sd->bl.m].flag.gvg) { - clif_displaymessage(fd, msg_txt(162)); // GvG is already Off. - return -1; - } + if (!map[sd->bl.m].flag.gvg) { + clif_displaymessage(fd, msg_txt(162)); // GvG is already Off. + return -1; + } - map[sd->bl.m].flag.gvg = 0; - clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING); - map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0); - clif_displaymessage(fd, msg_txt(33)); // GvG: Off. + map[sd->bl.m].flag.gvg = 0; + clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING); + map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0); + clif_displaymessage(fd, msg_txt(33)); // GvG: Off. - return 0; + return 0; } /*========================================== @@ -1610,18 +1737,18 @@ ACMD_FUNC(gvgoff) *------------------------------------------*/ ACMD_FUNC(gvgon) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (map[sd->bl.m].flag.gvg) { - clif_displaymessage(fd, msg_txt(163)); // GvG is already On. - return -1; - } + if (map[sd->bl.m].flag.gvg) { + clif_displaymessage(fd, msg_txt(163)); // GvG is already On. + return -1; + } - map[sd->bl.m].flag.gvg = 1; - clif_map_property_mapall(sd->bl.m, MAPPROPERTY_AGITZONE); - clif_displaymessage(fd, msg_txt(34)); // GvG: On. + map[sd->bl.m].flag.gvg = 1; + clif_map_property_mapall(sd->bl.m, MAPPROPERTY_AGITZONE); + clif_displaymessage(fd, msg_txt(34)); // GvG: On. - return 0; + return 0; } /*========================================== @@ -1629,31 +1756,31 @@ ACMD_FUNC(gvgon) *------------------------------------------*/ ACMD_FUNC(model) { - int hair_style = 0, hair_color = 0, cloth_color = 0; - nullpo_retr(-1, sd); + int hair_style = 0, hair_color = 0, cloth_color = 0; + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d %d %d", &hair_style, &hair_color, &cloth_color) < 1) { - sprintf(atcmd_output, msg_txt(991), // Please enter at least one 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, atcmd_output); - return -1; - } + if (!message || !*message || sscanf(message, "%d %d %d", &hair_style, &hair_color, &cloth_color) < 1) { + sprintf(atcmd_output, msg_txt(991), // Please enter at least one 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, atcmd_output); + return -1; + } - 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) { - pc_changelook(sd, LOOK_HAIR, hair_style); - pc_changelook(sd, LOOK_HAIR_COLOR, hair_color); - pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); - clif_displaymessage(fd, msg_txt(36)); // Appearence changed. - } else { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; - } + 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) { + pc_changelook(sd, LOOK_HAIR, hair_style); + pc_changelook(sd, LOOK_HAIR_COLOR, hair_color); + pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); + clif_displaymessage(fd, msg_txt(36)); // Appearence changed. + } else { + clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. + return -1; + } - return 0; + return 0; } /*========================================== @@ -1661,26 +1788,26 @@ ACMD_FUNC(model) *------------------------------------------*/ ACMD_FUNC(dye) { - int cloth_color = 0; - nullpo_retr(-1, sd); + int cloth_color = 0; + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d", &cloth_color) < 1) { - sprintf(atcmd_output, msg_txt(992), MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); // Please enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; - } + if (!message || !*message || sscanf(message, "%d", &cloth_color) < 1) { + sprintf(atcmd_output, msg_txt(992), MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); // Please enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>). + clif_displaymessage(fd, atcmd_output); + return -1; + } - if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) { - pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); - clif_displaymessage(fd, msg_txt(36)); // Appearence changed. - } else { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; - } + if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) { + pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); + clif_displaymessage(fd, msg_txt(36)); // Appearence changed. + } else { + clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. + return -1; + } - return 0; + return 0; } /*========================================== @@ -1688,26 +1815,26 @@ ACMD_FUNC(dye) *------------------------------------------*/ ACMD_FUNC(hair_style) { - int hair_style = 0; - nullpo_retr(-1, sd); + int hair_style = 0; + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d", &hair_style) < 1) { - sprintf(atcmd_output, msg_txt(993), MIN_HAIR_STYLE, MAX_HAIR_STYLE); // Please enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; - } + if (!message || !*message || sscanf(message, "%d", &hair_style) < 1) { + sprintf(atcmd_output, msg_txt(993), MIN_HAIR_STYLE, MAX_HAIR_STYLE); // Please enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>). + clif_displaymessage(fd, atcmd_output); + return -1; + } - if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE) { - pc_changelook(sd, LOOK_HAIR, hair_style); - clif_displaymessage(fd, msg_txt(36)); // Appearence changed. - } else { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; - } + if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE) { + pc_changelook(sd, LOOK_HAIR, hair_style); + clif_displaymessage(fd, msg_txt(36)); // Appearence changed. + } else { + clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. + return -1; + } - return 0; + return 0; } /*========================================== @@ -1715,26 +1842,26 @@ ACMD_FUNC(hair_style) *------------------------------------------*/ ACMD_FUNC(hair_color) { - int hair_color = 0; - nullpo_retr(-1, sd); + int hair_color = 0; + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d", &hair_color) < 1) { - sprintf(atcmd_output, msg_txt(994), MIN_HAIR_COLOR, MAX_HAIR_COLOR); // Please enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; - } + if (!message || !*message || sscanf(message, "%d", &hair_color) < 1) { + sprintf(atcmd_output, msg_txt(994), MIN_HAIR_COLOR, MAX_HAIR_COLOR); // Please enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>). + clif_displaymessage(fd, atcmd_output); + return -1; + } - if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR) { - pc_changelook(sd, LOOK_HAIR_COLOR, hair_color); - clif_displaymessage(fd, msg_txt(36)); // Appearence changed. - } else { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; - } + if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR) { + pc_changelook(sd, LOOK_HAIR_COLOR, hair_color); + clif_displaymessage(fd, msg_txt(36)); // Appearence changed. + } else { + clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. + return -1; + } - return 0; + return 0; } /*========================================== @@ -1742,198 +1869,199 @@ ACMD_FUNC(hair_color) *------------------------------------------*/ ACMD_FUNC(go) { - int i; - int town; - char map_name[MAP_NAME_LENGTH]; - int m; - - const struct { - char map[MAP_NAME_LENGTH]; - int x, y; - } data[] = { - { MAP_PRONTERA, 156, 191 }, // 0=Prontera - { MAP_MORROC, 156, 93 }, // 1=Morroc - { MAP_GEFFEN, 119, 59 }, // 2=Geffen - { MAP_PAYON, 162, 233 }, // 3=Payon - { MAP_ALBERTA, 192, 147 }, // 4=Alberta + int i; + int town; + char map_name[MAP_NAME_LENGTH]; + int m; + + const struct { + char map[MAP_NAME_LENGTH]; + int x, y; + } data[] = { + { MAP_PRONTERA, 156, 191 }, // 0=Prontera + { MAP_MORROC, 156, 93 }, // 1=Morroc + { MAP_GEFFEN, 119, 59 }, // 2=Geffen + { MAP_PAYON, 162, 233 }, // 3=Payon + { MAP_ALBERTA, 192, 147 }, // 4=Alberta #ifdef RENEWAL - { MAP_IZLUDE, 128, 146 }, // 5=Izlude (Renewal) + { MAP_IZLUDE, 128, 146 }, // 5=Izlude (Renewal) #else - { MAP_IZLUDE, 128, 114 }, // 5=Izlude + { MAP_IZLUDE, 128, 114 }, // 5=Izlude #endif - { MAP_ALDEBARAN, 140, 131 }, // 6=Al de Baran - { MAP_LUTIE, 147, 134 }, // 7=Lutie - { MAP_COMODO, 209, 143 }, // 8=Comodo - { MAP_YUNO, 157, 51 }, // 9=Yuno - { MAP_AMATSU, 198, 84 }, // 10=Amatsu - { MAP_GONRYUN, 160, 120 }, // 11=Gonryun - { MAP_UMBALA, 89, 157 }, // 12=Umbala - { MAP_NIFLHEIM, 21, 153 }, // 13=Niflheim - { MAP_LOUYANG, 217, 40 }, // 14=Louyang - { MAP_NOVICE, 53, 111 }, // 15=Training Grounds - { MAP_JAIL, 23, 61 }, // 16=Prison - { MAP_JAWAII, 249, 127 }, // 17=Jawaii - { MAP_AYOTHAYA, 151, 117 }, // 18=Ayothaya - { MAP_EINBROCH, 64, 200 }, // 19=Einbroch - { MAP_LIGHTHALZEN, 158, 92 }, // 20=Lighthalzen - { MAP_EINBECH, 70, 95 }, // 21=Einbech - { MAP_HUGEL, 96, 145 }, // 22=Hugel - { MAP_RACHEL, 130, 110 }, // 23=Rachel - { MAP_VEINS, 216, 123 }, // 24=Veins - { MAP_MOSCOVIA, 223, 184 }, // 25=Moscovia - { MAP_MIDCAMP, 180, 240 }, // 26=Midgard Camp - { MAP_MANUK, 282, 138 }, // 27=Manuk - { MAP_SPLENDIDE, 197, 176 }, // 28=Splendide - { MAP_BRASILIS, 182, 239 }, // 29=Brasilis - { MAP_DICASTES, 198, 187 }, // 30=El Dicastes - { MAP_MORA, 44, 151 }, // 31=Mora - { MAP_DEWATA, 200, 180 }, // 32=Dewata - { MAP_MALANGDO, 140, 114 }, // 33=Malangdo Island - { MAP_MALAYA, 242, 211 }, // 34=Malaya Port - { MAP_ECLAGE, 110, 39 }, // 35=Eclage - }; - - nullpo_retr(-1, sd); - - if (map[sd->bl.m].flag.nogo && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(sd->fd,msg_txt(995)); // You cannot use @go on this map. - return 0; - } - - memset(map_name, '\0', sizeof(map_name)); - memset(atcmd_output, '\0', sizeof(atcmd_output)); - - // get the number - town = atoi(message); - - if (!message || !*message || sscanf(message, "%11s", map_name) < 1 || town < 0 || town >= ARRAYLENGTH(data)) { - // no value matched so send the list of locations - const char *text; - - // attempt to find the text help string - text = atcommand_help_string(command); - - clif_displaymessage(fd, msg_txt(38)); // Invalid location number, or name. - - if (text) { - // send the text to the client - clif_displaymessage(fd, text); - } - - return -1; - } - - // get possible name of the city - map_name[MAP_NAME_LENGTH-1] = '\0'; - for (i = 0; map_name[i]; i++) - map_name[i] = TOLOWER(map_name[i]); - // try to identify the map name - if (strncmp(map_name, "prontera", 3) == 0) { - town = 0; - } else if (strncmp(map_name, "morocc", 4) == 0 || - strncmp(map_name, "morroc", 4) == 0) { - town = 1; - } else if (strncmp(map_name, "geffen", 3) == 0) { - town = 2; - } else if (strncmp(map_name, "payon", 3) == 0) { - town = 3; - } else if (strncmp(map_name, "alberta", 3) == 0) { - town = 4; - } else if (strncmp(map_name, "izlude", 3) == 0) { - town = 5; - } else if (strncmp(map_name, "aldebaran", 3) == 0) { - town = 6; - } else if (strncmp(map_name, "lutie", 3) == 0 || - strcmp(map_name, "christmas") == 0 || - strncmp(map_name, "xmas", 3) == 0 || - strncmp(map_name, "x-mas", 3) == 0) { - town = 7; - } else if (strncmp(map_name, "comodo", 3) == 0) { - town = 8; - } else if (strncmp(map_name, "juno", 3) == 0 || - strncmp(map_name, "yuno", 3) == 0) { - town = 9; - } else if (strncmp(map_name, "amatsu", 3) == 0) { - town = 10; - } else if (strncmp(map_name, "kunlun", 3) == 0 || - strncmp(map_name, "gonryun", 3) == 0) { - town = 11; - } else if (strncmp(map_name, "umbala", 3) == 0) { - town = 12; - } else if (strncmp(map_name, "niflheim", 3) == 0) { - town = 13; - } else if (strncmp(map_name, "louyang", 3) == 0) { - town = 14; - } else if (strncmp(map_name, "new_1-1", 3) == 0 || - strncmp(map_name, "startpoint", 3) == 0 || - strncmp(map_name, "beginning", 3) == 0) { - town = 15; - } else if (strncmp(map_name, "sec_pri", 3) == 0 || - strncmp(map_name, "prison", 3) == 0 || - strncmp(map_name, "jail", 3) == 0) { - town = 16; - } else if (strncmp(map_name, "jawaii", 3) == 0) { - town = 17; - } else if (strncmp(map_name, "ayothaya", 3) == 0) { - town = 18; - } else if (strncmp(map_name, "einbroch", 5) == 0) { - town = 19; - } else if (strncmp(map_name, "lighthalzen", 3) == 0) { - town = 20; - } else if (strncmp(map_name, "einbech", 5) == 0) { - town = 21; - } else if (strncmp(map_name, "hugel", 3) == 0) { - town = 22; - } else if (strncmp(map_name, "rachel", 3) == 0) { - town = 23; - } else if (strncmp(map_name, "veins", 3) == 0) { - town = 24; - } else if (strncmp(map_name, "moscovia", 3) == 0) { - town = 25; - } else if (strncmp(map_name, "mid_camp", 3) == 0) { - town = 26; - } else if (strncmp(map_name, "manuk", 3) == 0) { - town = 27; - } else if (strncmp(map_name, "splendide", 3) == 0) { - town = 28; - } else if (strncmp(map_name, "brasilis", 3) == 0) { - town = 29; - } else if (strncmp(map_name, "dicastes01", 3) == 0) { - town = 30; - } else if (strcmp(map_name, "mora") == 0) { - town = 31; - } else if (strncmp(map_name, "dewata", 3) == 0) { - town = 32; - } else if (strncmp(map_name, "malangdo", 5) == 0) { - town = 33; - } else if (strncmp(map_name, "malaya", 5) == 0) { - town = 34; - } else if (strncmp(map_name, "eclage", 3) == 0) { - town = 35; - } - - if (town >= 0 && town < ARRAYLENGTH(data)) { - m = map_mapname2mapid(data[town].map); - if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(247)); - return -1; - } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(248)); - return -1; - } - if (pc_setpos(sd, mapindex_name2id(data[town].map), data[town].x, data[town].y, CLR_TELEPORT) == 0) { - clif_displaymessage(fd, msg_txt(0)); // Warped. - } else { - clif_displaymessage(fd, msg_txt(1)); // Map not found. - return -1; - } - } else { // if you arrive here, you have an error in town variable when reading of names - clif_displaymessage(fd, msg_txt(38)); // Invalid location number or name. - return -1; - } - - return 0; + { MAP_ALDEBARAN, 140, 131 }, // 6=Al de Baran + { MAP_LUTIE, 147, 134 }, // 7=Lutie + { MAP_COMODO, 209, 143 }, // 8=Comodo + { MAP_YUNO, 157, 51 }, // 9=Yuno + { MAP_AMATSU, 198, 84 }, // 10=Amatsu + { MAP_GONRYUN, 160, 120 }, // 11=Gonryun + { MAP_UMBALA, 89, 157 }, // 12=Umbala + { MAP_NIFLHEIM, 21, 153 }, // 13=Niflheim + { MAP_LOUYANG, 217, 40 }, // 14=Louyang + { MAP_NOVICE, 53, 111 }, // 15=Training Grounds + { MAP_JAIL, 23, 61 }, // 16=Prison + { MAP_JAWAII, 249, 127 }, // 17=Jawaii + { MAP_AYOTHAYA, 151, 117 }, // 18=Ayothaya + { MAP_EINBROCH, 64, 200 }, // 19=Einbroch + { MAP_LIGHTHALZEN, 158, 92 }, // 20=Lighthalzen + { MAP_EINBECH, 70, 95 }, // 21=Einbech + { MAP_HUGEL, 96, 145 }, // 22=Hugel + { MAP_RACHEL, 130, 110 }, // 23=Rachel + { MAP_VEINS, 216, 123 }, // 24=Veins + { MAP_MOSCOVIA, 223, 184 }, // 25=Moscovia + { MAP_MIDCAMP, 180, 240 }, // 26=Midgard Camp + { MAP_MANUK, 282, 138 }, // 27=Manuk + { MAP_SPLENDIDE, 197, 176 }, // 28=Splendide + { MAP_BRASILIS, 182, 239 }, // 29=Brasilis + { MAP_DICASTES, 198, 187 }, // 30=El Dicastes + { MAP_MORA, 44, 151 }, // 31=Mora + { MAP_DEWATA, 200, 180 }, // 32=Dewata + { MAP_MALANGDO, 140, 114 }, // 33=Malangdo Island + { MAP_MALAYA, 242, 211 }, // 34=Malaya Port + { MAP_ECLAGE, 110, 39 }, // 35=Eclage + }; + + nullpo_retr(-1, sd); + + if( map[sd->bl.m].flag.nogo && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) { + clif_displaymessage(sd->fd,msg_txt(995)); // You cannot use @go on this map. + return 0; + } + + memset(map_name, '\0', sizeof(map_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + // get the number + town = atoi(message); + + if (!message || !*message || sscanf(message, "%11s", map_name) < 1 || town < 0 || town >= ARRAYLENGTH(data)) + {// no value matched so send the list of locations + const char* text; + + // attempt to find the text help string + text = atcommand_help_string( command ); + + clif_displaymessage(fd, msg_txt(38)); // Invalid location number, or name. + + if( text ) + {// send the text to the client + clif_displaymessage( fd, text ); + } + + return -1; + } + + // get possible name of the city + map_name[MAP_NAME_LENGTH-1] = '\0'; + for (i = 0; map_name[i]; i++) + map_name[i] = TOLOWER(map_name[i]); + // try to identify the map name + if (strncmp(map_name, "prontera", 3) == 0) { + town = 0; + } else if (strncmp(map_name, "morocc", 4) == 0 || + strncmp(map_name, "morroc", 4) == 0) { + town = 1; + } else if (strncmp(map_name, "geffen", 3) == 0) { + town = 2; + } else if (strncmp(map_name, "payon", 3) == 0) { + town = 3; + } else if (strncmp(map_name, "alberta", 3) == 0) { + town = 4; + } else if (strncmp(map_name, "izlude", 3) == 0) { + town = 5; + } else if (strncmp(map_name, "aldebaran", 3) == 0) { + town = 6; + } else if (strncmp(map_name, "lutie", 3) == 0 || + strcmp(map_name, "christmas") == 0 || + strncmp(map_name, "xmas", 3) == 0 || + strncmp(map_name, "x-mas", 3) == 0) { + town = 7; + } else if (strncmp(map_name, "comodo", 3) == 0) { + town = 8; + } else if (strncmp(map_name, "juno", 3) == 0 || + strncmp(map_name, "yuno", 3) == 0) { + town = 9; + } else if (strncmp(map_name, "amatsu", 3) == 0) { + town = 10; + } else if (strncmp(map_name, "kunlun", 3) == 0 || + strncmp(map_name, "gonryun", 3) == 0) { + town = 11; + } else if (strncmp(map_name, "umbala", 3) == 0) { + town = 12; + } else if (strncmp(map_name, "niflheim", 3) == 0) { + town = 13; + } else if (strncmp(map_name, "louyang", 3) == 0) { + town = 14; + } else if (strncmp(map_name, "new_1-1", 3) == 0 || + strncmp(map_name, "startpoint", 3) == 0 || + strncmp(map_name, "beginning", 3) == 0) { + town = 15; + } else if (strncmp(map_name, "sec_pri", 3) == 0 || + strncmp(map_name, "prison", 3) == 0 || + strncmp(map_name, "jail", 3) == 0) { + town = 16; + } else if (strncmp(map_name, "jawaii", 3) == 0) { + town = 17; + } else if (strncmp(map_name, "ayothaya", 3) == 0) { + town = 18; + } else if (strncmp(map_name, "einbroch", 5) == 0) { + town = 19; + } else if (strncmp(map_name, "lighthalzen", 3) == 0) { + town = 20; + } else if (strncmp(map_name, "einbech", 5) == 0) { + town = 21; + } else if (strncmp(map_name, "hugel", 3) == 0) { + town = 22; + } else if (strncmp(map_name, "rachel", 3) == 0) { + town = 23; + } else if (strncmp(map_name, "veins", 3) == 0) { + town = 24; + } else if (strncmp(map_name, "moscovia", 3) == 0) { + town = 25; + } else if (strncmp(map_name, "mid_camp", 3) == 0) { + town = 26; + } else if (strncmp(map_name, "manuk", 3) == 0) { + town = 27; + } else if (strncmp(map_name, "splendide", 3) == 0) { + town = 28; + } else if (strncmp(map_name, "brasilis", 3) == 0) { + town = 29; + } else if (strncmp(map_name, "dicastes01", 3) == 0) { + town = 30; + } else if (strcmp(map_name, "mora") == 0) { + town = 31; + } else if (strncmp(map_name, "dewata", 3) == 0) { + town = 32; + } else if (strncmp(map_name, "malangdo", 5) == 0) { + town = 33; + } else if (strncmp(map_name, "malaya", 5) == 0) { + town = 34; + } else if (strncmp(map_name, "eclage", 3) == 0) { + town = 35; + } + + if (town >= 0 && town < ARRAYLENGTH(data)) + { + m = map_mapname2mapid(data[town].map); + if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(247)); + return -1; + } + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(248)); + return -1; + } + if (pc_setpos(sd, mapindex_name2id(data[town].map), data[town].x, data[town].y, CLR_TELEPORT) == 0) { + clif_displaymessage(fd, msg_txt(0)); // Warped. + } else { + clif_displaymessage(fd, msg_txt(1)); // Map not found. + return -1; + } + } else { // if you arrive here, you have an error in town variable when reading of names + clif_displaymessage(fd, msg_txt(38)); // Invalid location number or name. + return -1; + } + + return 0; } /*========================================== @@ -1941,96 +2069,96 @@ ACMD_FUNC(go) *------------------------------------------*/ ACMD_FUNC(monster) { - char name[NAME_LENGTH]; - char monster[NAME_LENGTH]; - char eventname[EVENT_NAME_LENGTH] = ""; - int mob_id; - int number = 0; - int count; - int i, k, range; - short mx, my; - unsigned int size; - nullpo_retr(-1, sd); - - memset(name, '\0', sizeof(name)); - memset(monster, '\0', sizeof(monster)); - memset(atcmd_output, '\0', sizeof(atcmd_output)); - - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(80)); // Give the display name or monster name/id please. - return -1; - } - if (sscanf(message, "\"%23[^\"]\" %23s %d", name, monster, &number) > 1 || - sscanf(message, "%23s \"%23[^\"]\" %d", monster, name, &number) > 1) { - //All data can be left as it is. - } else if ((count=sscanf(message, "%23s %d %23s", monster, &number, name)) > 1) { - //Here, it is possible name was not given and we are using monster for it. - if (count < 3) //Blank mob's name. - name[0] = '\0'; - } else if (sscanf(message, "%23s %23s %d", name, monster, &number) > 1) { - //All data can be left as it is. - } else if (sscanf(message, "%23s", monster) > 0) { - //As before, name may be already filled. - name[0] = '\0'; - } else { - clif_displaymessage(fd, msg_txt(80)); // Give a display name and monster name/id please. - return -1; - } - - if ((mob_id = mobdb_searchname(monster)) == 0) // check name first (to avoid possible name begining by a number) - mob_id = mobdb_checkid(atoi(monster)); - - if (mob_id == 0) { - clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. - return -1; - } - - if (mob_id == MOBID_EMPERIUM) { - clif_displaymessage(fd, msg_txt(83)); // Monster 'Emperium' cannot be spawned. - return -1; - } - - if (number <= 0) - number = 1; - - if (!name[0]) - strcpy(name, "--ja--"); - - // If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive - if (battle_config.atc_spawn_quantity_limit && number > battle_config.atc_spawn_quantity_limit) - number = battle_config.atc_spawn_quantity_limit; - - if (strcmp(command+1, "monstersmall") == 0) - size = SZ_MEDIUM; // This is just gorgeous [mkbu95] - else if (strcmp(command+1, "monsterbig") == 0) - size = SZ_BIG; - else - size = SZ_SMALL; - - if (battle_config.etc_log) - ShowInfo("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, sd->bl.x, sd->bl.y); - - count = 0; - range = (int)sqrt((float)number) +2; // calculation of an odd number (+ 4 area around) - for (i = 0; i < number; i++) { - map_search_freecell(&sd->bl, 0, &mx, &my, range, range, 0); - k = mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, eventname, size, AI_NONE); - count += (k != 0) ? 1 : 0; - } - - if (count != 0) - if (number == count) - clif_displaymessage(fd, msg_txt(39)); // All monster summoned! - else { - sprintf(atcmd_output, msg_txt(240), count); // %d monster(s) summoned! - clif_displaymessage(fd, atcmd_output); - } - else { - clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. - return -1; - } - - return 0; + char name[NAME_LENGTH]; + char monster[NAME_LENGTH]; + char eventname[EVENT_NAME_LENGTH] = ""; + int mob_id; + int number = 0; + int count; + int i, k, range; + short mx, my; + unsigned int size; + nullpo_retr(-1, sd); + + memset(name, '\0', sizeof(name)); + memset(monster, '\0', sizeof(monster)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(80)); // Give the display name or monster name/id please. + return -1; + } + if (sscanf(message, "\"%23[^\"]\" %23s %d", name, monster, &number) > 1 || + sscanf(message, "%23s \"%23[^\"]\" %d", monster, name, &number) > 1) { + //All data can be left as it is. + } else if ((count=sscanf(message, "%23s %d %23s", monster, &number, name)) > 1) { + //Here, it is possible name was not given and we are using monster for it. + if (count < 3) //Blank mob's name. + name[0] = '\0'; + } else if (sscanf(message, "%23s %23s %d", name, monster, &number) > 1) { + //All data can be left as it is. + } else if (sscanf(message, "%23s", monster) > 0) { + //As before, name may be already filled. + name[0] = '\0'; + } else { + clif_displaymessage(fd, msg_txt(80)); // Give a display name and monster name/id please. + return -1; + } + + if ((mob_id = mobdb_searchname(monster)) == 0) // check name first (to avoid possible name begining by a number) + mob_id = mobdb_checkid(atoi(monster)); + + if (mob_id == 0) { + clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. + return -1; + } + + if (mob_id == MOBID_EMPERIUM) { + clif_displaymessage(fd, msg_txt(83)); // Monster 'Emperium' cannot be spawned. + return -1; + } + + if (number <= 0) + number = 1; + + if( !name[0] ) + strcpy(name, "--ja--"); + + // If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive + if (battle_config.atc_spawn_quantity_limit && number > battle_config.atc_spawn_quantity_limit) + number = battle_config.atc_spawn_quantity_limit; + + if (strcmp(command+1, "monstersmall") == 0) + size = SZ_MEDIUM; // This is just gorgeous [mkbu95] + else if (strcmp(command+1, "monsterbig") == 0) + size = SZ_BIG; + else + size = SZ_SMALL; + + if (battle_config.etc_log) + ShowInfo("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, sd->bl.x, sd->bl.y); + + count = 0; + range = (int)sqrt((float)number) +2; // calculation of an odd number (+ 4 area around) + for (i = 0; i < number; i++) { + map_search_freecell(&sd->bl, 0, &mx, &my, range, range, 0); + k = mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, eventname, size, AI_NONE); + count += (k != 0) ? 1 : 0; + } + + if (count != 0) + if (number == count) + clif_displaymessage(fd, msg_txt(39)); // All monster summoned! + else { + sprintf(atcmd_output, msg_txt(240), count); // %d monster(s) summoned! + clif_displaymessage(fd, atcmd_output); + } + else { + clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. + return -1; + } + + return 0; } /*========================================== @@ -2038,44 +2166,44 @@ ACMD_FUNC(monster) *------------------------------------------*/ static int atkillmonster_sub(struct block_list *bl, va_list ap) { - struct mob_data *md; - int flag; + struct mob_data *md; + int flag; - nullpo_ret(md=(struct mob_data *)bl); - flag = va_arg(ap, int); + nullpo_ret(md=(struct mob_data *)bl); + flag = va_arg(ap, int); - if (md->guardian_data) - return 0; //Do not touch WoE mobs! + if (md->guardian_data) + return 0; //Do not touch WoE mobs! - if (flag) - status_zap(bl,md->status.hp, 0); - else - status_kill(bl); - return 1; + if (flag) + status_zap(bl,md->status.hp, 0); + else + status_kill(bl); + return 1; } ACMD_FUNC(killmonster) { - int map_id, drop_flag; - char map_name[MAP_NAME_LENGTH_EXT]; - nullpo_retr(-1, sd); + int map_id, drop_flag; + char map_name[MAP_NAME_LENGTH_EXT]; + nullpo_retr(-1, sd); - memset(map_name, '\0', sizeof(map_name)); + memset(map_name, '\0', sizeof(map_name)); - if (!message || !*message || sscanf(message, "%15s", map_name) < 1) - map_id = sd->bl.m; - else { - if ((map_id = map_mapname2mapid(map_name)) < 0) - map_id = sd->bl.m; - } + if (!message || !*message || sscanf(message, "%15s", map_name) < 1) + map_id = sd->bl.m; + else { + if ((map_id = map_mapname2mapid(map_name)) < 0) + map_id = sd->bl.m; + } - drop_flag = strcmp(command+1, "killmonster2"); + drop_flag = strcmp(command+1, "killmonster2"); - map_foreachinmap(atkillmonster_sub, map_id, BL_MOB, -drop_flag); + map_foreachinmap(atkillmonster_sub, map_id, BL_MOB, -drop_flag); - clif_displaymessage(fd, msg_txt(165)); // All monsters killed! + clif_displaymessage(fd, msg_txt(165)); // All monsters killed! - return 0; + return 0; } /*========================================== @@ -2083,77 +2211,77 @@ ACMD_FUNC(killmonster) *------------------------------------------*/ ACMD_FUNC(refine) { - int i,j, position = 0, refine = 0, current_position, final_refine; - int count; - nullpo_retr(-1, sd); - - memset(atcmd_output, '\0', sizeof(atcmd_output)); - - if (!message || !*message || sscanf(message, "%d %d", &position, &refine) < 2) { - clif_displaymessage(fd, msg_txt(996)); // Please enter a position and an amount (usage: @refine <equip position> <+/- amount>). - sprintf(atcmd_output, msg_txt(997), EQP_HEAD_LOW); // %d: Lower Headgear - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(998), EQP_HAND_R); // %d: Right Hand - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(999), EQP_GARMENT); // %d: Garment - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1000), EQP_ACC_L); // %d: Left Accessory - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1001), EQP_ARMOR); // %d: Body Armor - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1002), EQP_HAND_L); // %d: Left Hand - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1003), EQP_SHOES); // %d: Shoes - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1004), EQP_ACC_R); // %d: Right Accessory - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1005), EQP_HEAD_TOP); // %d: Top Headgear - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1006), EQP_HEAD_MID); // %d: Mid Headgear - clif_displaymessage(fd, atcmd_output); - return -1; - } - - refine = cap_value(refine, -MAX_REFINE, MAX_REFINE); - - count = 0; - for (j = 0; j < EQI_MAX-1; j++) { - if ((i = sd->equip_index[j]) < 0) - continue; - if (j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == i) - continue; - if (j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == i) - continue; - if (j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == i || sd->equip_index[EQI_HEAD_LOW] == i)) - continue; - - if (position && !(sd->status.inventory[i].equip & position)) - continue; - - final_refine = cap_value(sd->status.inventory[i].refine + refine, 0, MAX_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, 3); - clif_refine(fd, 0, i, sd->status.inventory[i].refine); - clif_delitem(sd, i, 1, 3); - clif_additem(sd, i, 1, 0); - pc_equipitem(sd, i, current_position); - clif_misceffect(&sd->bl, 3); - count++; - } - } - - if (count == 0) - clif_displaymessage(fd, msg_txt(166)); // No item has been refined. - else if (count == 1) - clif_displaymessage(fd, msg_txt(167)); // 1 item has been refined. - else { - sprintf(atcmd_output, msg_txt(168), count); // %d items have been refined. - clif_displaymessage(fd, atcmd_output); - } - - return 0; + int i,j, position = 0, refine = 0, current_position, final_refine; + int count; + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!message || !*message || sscanf(message, "%d %d", &position, &refine) < 2) { + clif_displaymessage(fd, msg_txt(996)); // Please enter a position and an amount (usage: @refine <equip position> <+/- amount>). + sprintf(atcmd_output, msg_txt(997), EQP_HEAD_LOW); // %d: Lower Headgear + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(998), EQP_HAND_R); // %d: Right Hand + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(999), EQP_GARMENT); // %d: Garment + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1000), EQP_ACC_L); // %d: Left Accessory + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1001), EQP_ARMOR); // %d: Body Armor + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1002), EQP_HAND_L); // %d: Left Hand + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1003), EQP_SHOES); // %d: Shoes + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1004), EQP_ACC_R); // %d: Right Accessory + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1005), EQP_HEAD_TOP); // %d: Top Headgear + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1006), EQP_HEAD_MID); // %d: Mid Headgear + clif_displaymessage(fd, atcmd_output); + return -1; + } + + refine = cap_value(refine, -MAX_REFINE, MAX_REFINE); + + count = 0; + for (j = 0; j < EQI_MAX-1; j++) { + if ((i = sd->equip_index[j]) < 0) + continue; + if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == i) + continue; + if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == i) + continue; + if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == i || sd->equip_index[EQI_HEAD_LOW] == i)) + continue; + + if(position && !(sd->status.inventory[i].equip & position)) + continue; + + final_refine = cap_value(sd->status.inventory[i].refine + refine, 0, MAX_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, 3); + clif_refine(fd, 0, i, sd->status.inventory[i].refine); + clif_delitem(sd, i, 1, 3); + clif_additem(sd, i, 1, 0); + pc_equipitem(sd, i, current_position); + clif_misceffect(&sd->bl, 3); + count++; + } + } + + if (count == 0) + clif_displaymessage(fd, msg_txt(166)); // No item has been refined. + else if (count == 1) + clif_displaymessage(fd, msg_txt(167)); // 1 item has been refined. + else { + sprintf(atcmd_output, msg_txt(168), count); // %d items have been refined. + clif_displaymessage(fd, atcmd_output); + } + + return 0; } /*========================================== @@ -2161,58 +2289,58 @@ ACMD_FUNC(refine) *------------------------------------------*/ ACMD_FUNC(produce) { - char item_name[100]; - int item_id, attribute = 0, star = 0; - int flag = 0; - struct item_data *item_data; - struct item tmp_item; - nullpo_retr(-1, sd); - - memset(atcmd_output, '\0', sizeof(atcmd_output)); - memset(item_name, '\0', sizeof(item_name)); - - if (!message || !*message || ( - sscanf(message, "\"%99[^\"]\" %d %d", item_name, &attribute, &star) < 1 && - sscanf(message, "%99s %d %d", item_name, &attribute, &star) < 1 - )) { - clif_displaymessage(fd, msg_txt(1007)); // Please enter at least one item name/ID (usage: @produce <equip name/ID> <element> <# of very's>). - return -1; - } - - if ((item_data = itemdb_searchname(item_name)) == NULL && - (item_data = itemdb_exists(atoi(item_name))) == NULL) { - clif_displaymessage(fd, msg_txt(170)); //This item is not an equipment. - return -1; - } - - item_id = item_data->nameid; - - if (itemdb_isequip2(item_data)) { - if (attribute < MIN_ATTRIBUTE || attribute > MAX_ATTRIBUTE) - attribute = ATTRIBUTE_NORMAL; - if (star < MIN_STAR || star > MAX_STAR) - star = 0; - memset(&tmp_item, 0, sizeof tmp_item); - tmp_item.nameid = item_id; - tmp_item.amount = 1; - tmp_item.identify = 1; - tmp_item.card[0] = CARD0_FORGE; - tmp_item.card[1] = item_data->type==IT_WEAPON? - ((star*5) << 8) + attribute:0; - tmp_item.card[2] = GetWord(sd->status.char_id, 0); - tmp_item.card[3] = GetWord(sd->status.char_id, 1); - clif_produceeffect(sd, 0, item_id); - clif_misceffect(&sd->bl, 3); - - if ((flag = pc_additem(sd, &tmp_item, 1, LOG_TYPE_COMMAND))) - clif_additem(sd, 0, 0, flag); - } else { - sprintf(atcmd_output, msg_txt(169), item_id, item_data->name); // The item (%d: '%s') is not equipable. - clif_displaymessage(fd, atcmd_output); - return -1; - } - - return 0; + char item_name[100]; + int item_id, attribute = 0, star = 0; + int flag = 0; + struct item_data *item_data; + struct item tmp_item; + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(item_name, '\0', sizeof(item_name)); + + if (!message || !*message || ( + sscanf(message, "\"%99[^\"]\" %d %d", item_name, &attribute, &star) < 1 && + sscanf(message, "%99s %d %d", item_name, &attribute, &star) < 1 + )) { + clif_displaymessage(fd, msg_txt(1007)); // Please enter at least one item name/ID (usage: @produce <equip name/ID> <element> <# of very's>). + return -1; + } + + if ( (item_data = itemdb_searchname(item_name)) == NULL && + (item_data = itemdb_exists(atoi(item_name))) == NULL ) { + clif_displaymessage(fd, msg_txt(170)); //This item is not an equipment. + return -1; + } + + item_id = item_data->nameid; + + if (itemdb_isequip2(item_data)) { + if (attribute < MIN_ATTRIBUTE || attribute > MAX_ATTRIBUTE) + attribute = ATTRIBUTE_NORMAL; + if (star < MIN_STAR || star > MAX_STAR) + star = 0; + memset(&tmp_item, 0, sizeof tmp_item); + tmp_item.nameid = item_id; + tmp_item.amount = 1; + tmp_item.identify = 1; + tmp_item.card[0] = CARD0_FORGE; + tmp_item.card[1] = item_data->type==IT_WEAPON? + ((star*5) << 8) + attribute:0; + tmp_item.card[2] = GetWord(sd->status.char_id, 0); + tmp_item.card[3] = GetWord(sd->status.char_id, 1); + clif_produceeffect(sd, 0, item_id); + clif_misceffect(&sd->bl, 3); + + if ((flag = pc_additem(sd, &tmp_item, 1, LOG_TYPE_COMMAND))) + clif_additem(sd, 0, 0, flag); + } else { + sprintf(atcmd_output, msg_txt(169), item_id, item_data->name); // The item (%d: '%s') is not equipable. + clif_displaymessage(fd, atcmd_output); + return -1; + } + + return 0; } /*========================================== @@ -2220,32 +2348,35 @@ ACMD_FUNC(produce) *------------------------------------------*/ ACMD_FUNC(memo) { - int position = 0; - nullpo_retr(-1, sd); + int position = 0; + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%d", &position) < 1) { - int i; - clif_displaymessage(sd->fd, msg_txt(668)); - for (i = 0; i < MAX_MEMOPOINTS; i++) { - if (sd->status.memo_point[i].map) - sprintf(atcmd_output, "%d - %s (%d,%d)", i, mapindex_id2name(sd->status.memo_point[i].map), sd->status.memo_point[i].x, sd->status.memo_point[i].y); - else - sprintf(atcmd_output, msg_txt(171), i); // %d - void - clif_displaymessage(sd->fd, atcmd_output); - } - return 0; - } + if( !message || !*message || sscanf(message, "%d", &position) < 1 ) + { + int i; + clif_displaymessage(sd->fd, msg_txt(668)); + for( i = 0; i < MAX_MEMOPOINTS; i++ ) + { + if( sd->status.memo_point[i].map ) + sprintf(atcmd_output, "%d - %s (%d,%d)", i, mapindex_id2name(sd->status.memo_point[i].map), sd->status.memo_point[i].x, sd->status.memo_point[i].y); + else + sprintf(atcmd_output, msg_txt(171), i); // %d - void + clif_displaymessage(sd->fd, atcmd_output); + } + return 0; + } - if (position < 0 || position >= MAX_MEMOPOINTS) { - sprintf(atcmd_output, msg_txt(1008), 0, MAX_MEMOPOINTS-1); // Please enter a valid position (usage: @memo <memo_position:%d-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; - } + if( position < 0 || position >= MAX_MEMOPOINTS ) + { + sprintf(atcmd_output, msg_txt(1008), 0, MAX_MEMOPOINTS-1); // Please enter a valid position (usage: @memo <memo_position:%d-%d>). + clif_displaymessage(fd, atcmd_output); + return -1; + } - pc_memo(sd, position); - return 0; + pc_memo(sd, position); + return 0; } /*========================================== @@ -2253,24 +2384,24 @@ ACMD_FUNC(memo) *------------------------------------------*/ ACMD_FUNC(gat) { - int y; - nullpo_retr(-1, sd); + int y; + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - for (y = 2; y >= -2; y--) { - 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)); + for (y = 2; y >= -2; y--) { + 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); - } + clif_displaymessage(fd, atcmd_output); + } - return 0; + return 0; } /*========================================== @@ -2278,19 +2409,19 @@ ACMD_FUNC(gat) *------------------------------------------*/ ACMD_FUNC(displaystatus) { - int i, type, flag, tick, val1 = 0, val2 = 0, val3 = 0; - nullpo_retr(-1, sd); + int i, type, flag, tick, val1 = 0, val2 = 0, val3 = 0; + nullpo_retr(-1, sd); - if (!message || !*message || (i = sscanf(message, "%d %d %d %d %d %d", &type, &flag, &tick, &val1, &val2, &val3)) < 1) { - clif_displaymessage(fd, msg_txt(1009)); // Please enter a status type/flag (usage: @displaystatus <status type> <flag> <tick> {<val1> {<val2> {<val3>}}}). - return -1; - } - if (i < 2) flag = 1; - if (i < 3) tick = 0; + if (!message || !*message || (i = sscanf(message, "%d %d %d %d %d %d", &type, &flag, &tick, &val1, &val2, &val3)) < 1) { + clif_displaymessage(fd, msg_txt(1009)); // Please enter a status type/flag (usage: @displaystatus <status type> <flag> <tick> {<val1> {<val2> {<val3>}}}). + return -1; + } + if (i < 2) flag = 1; + if (i < 3) tick = 0; - clif_status_change(&sd->bl, type, flag, tick, val1, val2, val3); + clif_status_change(&sd->bl, type, flag, tick, val1, val2, val3); - return 0; + return 0; } /*========================================== @@ -2298,39 +2429,47 @@ ACMD_FUNC(displaystatus) *------------------------------------------*/ ACMD_FUNC(statuspoint) { - int point; - unsigned int new_status_point; - - if (!message || !*message || (point = atoi(message)) == 0) { - clif_displaymessage(fd, msg_txt(1010)); // Please enter a number (usage: @stpoint <number of points>). - return -1; - } - - if (point < 0) { - if (sd->status.status_point < (unsigned int)(-point)) { - new_status_point = 0; - } else { - new_status_point = sd->status.status_point + point; - } - } else if (UINT_MAX - sd->status.status_point < (unsigned int)point) { - new_status_point = UINT_MAX; - } else { - new_status_point = sd->status.status_point + point; - } - - if (new_status_point != sd->status.status_point) { - sd->status.status_point = new_status_point; - clif_updatestatus(sd, SP_STATUSPOINT); - clif_displaymessage(fd, msg_txt(174)); // Number of status points changed. - } else { - if (point < 0) - clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. - else - clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. - return -1; - } - - return 0; + int point; + unsigned int new_status_point; + + if (!message || !*message || (point = atoi(message)) == 0) { + clif_displaymessage(fd, msg_txt(1010)); // Please enter a number (usage: @stpoint <number of points>). + return -1; + } + + if(point < 0) + { + if(sd->status.status_point < (unsigned int)(-point)) + { + new_status_point = 0; + } + else + { + new_status_point = sd->status.status_point + point; + } + } + else if(UINT_MAX - sd->status.status_point < (unsigned int)point) + { + new_status_point = UINT_MAX; + } + else + { + new_status_point = sd->status.status_point + point; + } + + if (new_status_point != sd->status.status_point) { + sd->status.status_point = new_status_point; + clif_updatestatus(sd, SP_STATUSPOINT); + clif_displaymessage(fd, msg_txt(174)); // Number of status points changed. + } else { + if (point < 0) + clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + else + clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. + return -1; + } + + return 0; } /*========================================== @@ -2338,40 +2477,48 @@ ACMD_FUNC(statuspoint) *------------------------------------------*/ ACMD_FUNC(skillpoint) { - int point; - unsigned int new_skill_point; - nullpo_retr(-1, sd); - - if (!message || !*message || (point = atoi(message)) == 0) { - clif_displaymessage(fd, msg_txt(1011)); // Please enter a number (usage: @skpoint <number of points>). - return -1; - } - - if (point < 0) { - if (sd->status.skill_point < (unsigned int)(-point)) { - new_skill_point = 0; - } else { - new_skill_point = sd->status.skill_point + point; - } - } else if (UINT_MAX - sd->status.skill_point < (unsigned int)point) { - new_skill_point = UINT_MAX; - } else { - new_skill_point = sd->status.skill_point + point; - } - - if (new_skill_point != sd->status.skill_point) { - sd->status.skill_point = new_skill_point; - clif_updatestatus(sd, SP_SKILLPOINT); - clif_displaymessage(fd, msg_txt(175)); // Number of skill points changed. - } else { - if (point < 0) - clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. - else - clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. - return -1; - } - - return 0; + int point; + unsigned int new_skill_point; + nullpo_retr(-1, sd); + + if (!message || !*message || (point = atoi(message)) == 0) { + clif_displaymessage(fd, msg_txt(1011)); // Please enter a number (usage: @skpoint <number of points>). + return -1; + } + + if(point < 0) + { + if(sd->status.skill_point < (unsigned int)(-point)) + { + new_skill_point = 0; + } + else + { + new_skill_point = sd->status.skill_point + point; + } + } + else if(UINT_MAX - sd->status.skill_point < (unsigned int)point) + { + new_skill_point = UINT_MAX; + } + else + { + new_skill_point = sd->status.skill_point + point; + } + + if (new_skill_point != sd->status.skill_point) { + sd->status.skill_point = new_skill_point; + clif_updatestatus(sd, SP_SKILLPOINT); + clif_displaymessage(fd, msg_txt(175)); // Number of skill points changed. + } else { + if (point < 0) + clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + else + clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. + return -1; + } + + return 0; } /*========================================== @@ -2379,24 +2526,25 @@ ACMD_FUNC(skillpoint) *------------------------------------------*/ ACMD_FUNC(zeny) { - int zeny=0, ret=-1; - nullpo_retr(-1, sd); + int zeny=0, ret=-1; + nullpo_retr(-1, sd); - if (!message || !*message || (zeny = atoi(message)) == 0) { - clif_displaymessage(fd, msg_txt(1012)); // Please enter an amount (usage: @zeny <amount>). - return -1; - } + if (!message || !*message || (zeny = atoi(message)) == 0) { + clif_displaymessage(fd, msg_txt(1012)); // Please enter an amount (usage: @zeny <amount>). + return -1; + } - if (zeny > 0) { - if ((ret=pc_getzeny(sd,zeny,LOG_TYPE_COMMAND,NULL)) == 1) - clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. - } else { - if (sd->status.zeny < -zeny) zeny = -sd->status.zeny; - if ((ret=pc_payzeny(sd,-zeny,LOG_TYPE_COMMAND,NULL)) == 1) - clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. - } - if (!ret) clif_displaymessage(fd, msg_txt(176)); //ret=0 mean cmd success - return 0; + if(zeny > 0){ + if((ret=pc_getzeny(sd,zeny,LOG_TYPE_COMMAND,NULL)) == 1) + clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. + } + else { + if( sd->status.zeny < -zeny ) zeny = -sd->status.zeny; + if((ret=pc_payzeny(sd,-zeny,LOG_TYPE_COMMAND,NULL)) == 1) + clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + } + if(!ret) clif_displaymessage(fd, msg_txt(176)); //ret=0 mean cmd success + return 0; } /*========================================== @@ -2404,61 +2552,61 @@ ACMD_FUNC(zeny) *------------------------------------------*/ ACMD_FUNC(param) { - int i, value = 0, new_value, max; - const char *param[] = { "str", "agi", "vit", "int", "dex", "luk" }; - short *status[6]; - //we don't use direct initialization because it isn't part of the c standard. - nullpo_retr(-1, sd); - - memset(atcmd_output, '\0', sizeof(atcmd_output)); - - if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) { - clif_displaymessage(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>). - return -1; - } - - ARR_FIND(0, ARRAYLENGTH(param), i, strcmpi(command+1, param[i]) == 0); - - if (i == ARRAYLENGTH(param) || i > MAX_STATUS_TYPE) { // normally impossible... - clif_displaymessage(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>). - return -1; - } - - status[0] = &sd->status.str; - status[1] = &sd->status.agi; - status[2] = &sd->status.vit; - status[3] = &sd->status.int_; - status[4] = &sd->status.dex; - status[5] = &sd->status.luk; - - if (battle_config.atcommand_max_stat_bypass) - max = SHRT_MAX; - else - max = pc_maxparameter(sd); - - if (value < 0 && *status[i] <= -value) { - new_value = 1; - } else if (max - *status[i] < value) { - new_value = max; - } else { - new_value = *status[i] + value; - } - - if (new_value != *status[i]) { - *status[i] = new_value; - clif_updatestatus(sd, SP_STR + i); - clif_updatestatus(sd, SP_USTR + i); - status_calc_pc(sd, 0); - clif_displaymessage(fd, msg_txt(42)); // Stat changed. - } else { - if (value < 0) - clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. - else - clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. - return -1; - } - - return 0; + int i, value = 0, new_value, max; + const char* param[] = { "str", "agi", "vit", "int", "dex", "luk" }; + short* status[6]; + //we don't use direct initialization because it isn't part of the c standard. + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) { + clif_displaymessage(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>). + return -1; + } + + ARR_FIND( 0, ARRAYLENGTH(param), i, strcmpi(command+1, param[i]) == 0 ); + + if( i == ARRAYLENGTH(param) || i > MAX_STATUS_TYPE) { // normally impossible... + clif_displaymessage(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>). + return -1; + } + + status[0] = &sd->status.str; + status[1] = &sd->status.agi; + status[2] = &sd->status.vit; + status[3] = &sd->status.int_; + status[4] = &sd->status.dex; + status[5] = &sd->status.luk; + + if( battle_config.atcommand_max_stat_bypass ) + max = SHRT_MAX; + else + max = pc_maxparameter(sd); + + if(value < 0 && *status[i] <= -value) { + new_value = 1; + } else if(max - *status[i] < value) { + new_value = max; + } else { + new_value = *status[i] + value; + } + + if (new_value != *status[i]) { + *status[i] = new_value; + clif_updatestatus(sd, SP_STR + i); + clif_updatestatus(sd, SP_USTR + i); + status_calc_pc(sd, 0); + clif_displaymessage(fd, msg_txt(42)); // Stat changed. + } else { + if (value < 0) + clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + else + clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. + return -1; + } + + return 0; } /*========================================== @@ -2466,58 +2614,58 @@ ACMD_FUNC(param) *------------------------------------------*/ ACMD_FUNC(stat_all) { - int index, count, value, max, new_value; - short *status[6]; - //we don't use direct initialization because it isn't part of the c standard. - nullpo_retr(-1, sd); - - status[0] = &sd->status.str; - status[1] = &sd->status.agi; - status[2] = &sd->status.vit; - status[3] = &sd->status.int_; - status[4] = &sd->status.dex; - status[5] = &sd->status.luk; - - if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) { - value = pc_maxparameter(sd); - max = pc_maxparameter(sd); - } else { - if (battle_config.atcommand_max_stat_bypass) - max = SHRT_MAX; - else - max = pc_maxparameter(sd); - } - - count = 0; - for (index = 0; index < ARRAYLENGTH(status); index++) { - - if (value > 0 && *status[index] > max - value) - new_value = max; - else if (value < 0 && *status[index] <= -value) - new_value = 1; - else - new_value = *status[index] +value; - - if (new_value != (int)*status[index]) { - *status[index] = new_value; - clif_updatestatus(sd, SP_STR + index); - clif_updatestatus(sd, SP_USTR + index); - count++; - } - } - - if (count > 0) { // if at least 1 stat modified - status_calc_pc(sd, 0); - clif_displaymessage(fd, msg_txt(84)); // All stats changed! - } else { - if (value < 0) - clif_displaymessage(fd, msg_txt(177)); // You cannot decrease that stat anymore. - else - clif_displaymessage(fd, msg_txt(178)); // You cannot increase that stat anymore. - return -1; - } - - return 0; + int index, count, value, max, new_value; + short* status[6]; + //we don't use direct initialization because it isn't part of the c standard. + nullpo_retr(-1, sd); + + status[0] = &sd->status.str; + status[1] = &sd->status.agi; + status[2] = &sd->status.vit; + status[3] = &sd->status.int_; + status[4] = &sd->status.dex; + status[5] = &sd->status.luk; + + if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) { + value = pc_maxparameter(sd); + max = pc_maxparameter(sd); + } else { + if( battle_config.atcommand_max_stat_bypass ) + max = SHRT_MAX; + else + max = pc_maxparameter(sd); + } + + count = 0; + for (index = 0; index < ARRAYLENGTH(status); index++) { + + if (value > 0 && *status[index] > max - value) + new_value = max; + else if (value < 0 && *status[index] <= -value) + new_value = 1; + else + new_value = *status[index] +value; + + if (new_value != (int)*status[index]) { + *status[index] = new_value; + clif_updatestatus(sd, SP_STR + index); + clif_updatestatus(sd, SP_USTR + index); + count++; + } + } + + if (count > 0) { // if at least 1 stat modified + status_calc_pc(sd, 0); + clif_displaymessage(fd, msg_txt(84)); // All stats changed! + } else { + if (value < 0) + clif_displaymessage(fd, msg_txt(177)); // You cannot decrease that stat anymore. + else + clif_displaymessage(fd, msg_txt(178)); // You cannot increase that stat anymore. + return -1; + } + + return 0; } /*========================================== @@ -2525,40 +2673,40 @@ ACMD_FUNC(stat_all) *------------------------------------------*/ ACMD_FUNC(guildlevelup) { - int level = 0; - short added_level; - struct guild *guild_info; - nullpo_retr(-1, sd); + 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, msg_txt(1014)); // Please enter a valid level (usage: @guildlvup/@guildlvlup <# of levels>). - return -1; - } + if (!message || !*message || sscanf(message, "%d", &level) < 1 || level == 0) { + clif_displaymessage(fd, msg_txt(1014)); // Please enter a valid level (usage: @guildlvup/@guildlvlup <# of levels>). + return -1; + } - if (sd->status.guild_id <= 0 || (guild_info = guild_search(sd->status.guild_id)) == NULL) { - clif_displaymessage(fd, msg_txt(43)); // You're not in a guild. - return -1; - } - //if (strcmp(sd->status.name, guild_info->master) != 0) { - // clif_displaymessage(fd, msg_txt(44)); // You're not the master of your guild. - // return -1; - //} + if (sd->status.guild_id <= 0 || (guild_info = guild_search(sd->status.guild_id)) == NULL) { + clif_displaymessage(fd, msg_txt(43)); // You're not in a guild. + return -1; + } + //if (strcmp(sd->status.name, guild_info->master) != 0) { + // clif_displaymessage(fd, msg_txt(44)); // You're not the master of your guild. + // return -1; + //} - added_level = (short)level; - if (level > 0 && (level > MAX_GUILDLEVEL || added_level > ((short)MAX_GUILDLEVEL - guild_info->guild_lv))) // fix positiv overflow - added_level = (short)MAX_GUILDLEVEL - guild_info->guild_lv; - else if (level < 0 && (level < -MAX_GUILDLEVEL || added_level < (1 - guild_info->guild_lv))) // fix negativ overflow - added_level = 1 - guild_info->guild_lv; + added_level = (short)level; + if (level > 0 && (level > MAX_GUILDLEVEL || added_level > ((short)MAX_GUILDLEVEL - guild_info->guild_lv))) // fix positiv overflow + added_level = (short)MAX_GUILDLEVEL - guild_info->guild_lv; + else if (level < 0 && (level < -MAX_GUILDLEVEL || added_level < (1 - guild_info->guild_lv))) // fix negativ overflow + added_level = 1 - guild_info->guild_lv; - if (added_level != 0) { - intif_guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, sizeof(added_level)); - clif_displaymessage(fd, msg_txt(179)); // Guild level changed. - } else { - clif_displaymessage(fd, msg_txt(45)); // Guild level change failed. - return -1; - } + if (added_level != 0) { + intif_guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, sizeof(added_level)); + clif_displaymessage(fd, msg_txt(179)); // Guild level changed. + } else { + clif_displaymessage(fd, msg_txt(45)); // Guild level change failed. + return -1; + } - return 0; + return 0; } /*========================================== @@ -2566,38 +2714,39 @@ ACMD_FUNC(guildlevelup) *------------------------------------------*/ ACMD_FUNC(makeegg) { - struct item_data *item_data; - int id, pet_id; - nullpo_retr(-1, sd); - - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>). - return -1; - } - - if ((item_data = itemdb_searchname(message)) != NULL) // for egg name - id = item_data->nameid; - else if ((id = mobdb_searchname(message)) != 0) // for monster name - ; - else - id = atoi(message); - - pet_id = search_petDB_index(id, PET_CLASS); - 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_; - intif_create_pet( - sd->status.account_id, 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); - } else { - clif_displaymessage(fd, msg_txt(180)); // The monster/egg name/id doesn't exist. - return -1; - } - - return 0; + struct item_data *item_data; + int id, pet_id; + nullpo_retr(-1, sd); + + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>). + return -1; + } + + if ((item_data = itemdb_searchname(message)) != NULL) // for egg name + id = item_data->nameid; + else + if ((id = mobdb_searchname(message)) != 0) // for monster name + ; + else + id = atoi(message); + + pet_id = search_petDB_index(id, PET_CLASS); + 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_; + intif_create_pet( + sd->status.account_id, 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); + } else { + clif_displaymessage(fd, msg_txt(180)); // The monster/egg name/id doesn't exist. + return -1; + } + + return 0; } /*========================================== @@ -2605,15 +2754,15 @@ ACMD_FUNC(makeegg) *------------------------------------------*/ ACMD_FUNC(hatch) { - nullpo_retr(-1, sd); - if (sd->status.pet_id <= 0) - clif_sendegg(sd); - else { - clif_displaymessage(fd, msg_txt(181)); // You already have a pet. - return -1; - } + nullpo_retr(-1, sd); + if (sd->status.pet_id <= 0) + clif_sendegg(sd); + else { + clif_displaymessage(fd, msg_txt(181)); // You already have a pet. + return -1; + } - return 0; + return 0; } /*========================================== @@ -2621,35 +2770,36 @@ ACMD_FUNC(hatch) *------------------------------------------*/ ACMD_FUNC(petfriendly) { - int friendly; - struct pet_data *pd; - nullpo_retr(-1, sd); + int friendly; + struct pet_data *pd; + nullpo_retr(-1, sd); - if (!message || !*message || (friendly = atoi(message)) < 0) { - clif_displaymessage(fd, msg_txt(1016)); // Please enter a valid value (usage: @petfriendly <0-1000>). - return -1; - } + if (!message || !*message || (friendly = atoi(message)) < 0) { + clif_displaymessage(fd, msg_txt(1016)); // Please enter a valid value (usage: @petfriendly <0-1000>). + return -1; + } - pd = sd->pd; - if (!pd) { - clif_displaymessage(fd, msg_txt(184)); // Sorry, but you have no pet. - return -1; - } + pd = sd->pd; + if (!pd) { + clif_displaymessage(fd, msg_txt(184)); // Sorry, but you have no pet. + return -1; + } - if (friendly < 0 || friendly > 1000) { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; - } + if (friendly < 0 || friendly > 1000) + { + clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. + return -1; + } - if (friendly == pd->pet.intimate) { - clif_displaymessage(fd, msg_txt(183)); // Pet intimacy is already at maximum. - return -1; - } + if (friendly == pd->pet.intimate) { + clif_displaymessage(fd, msg_txt(183)); // Pet intimacy is already at maximum. + return -1; + } - pet_set_intimate(pd, friendly); - clif_send_petstatus(sd); - clif_displaymessage(fd, msg_txt(182)); // Pet intimacy changed. - return 0; + pet_set_intimate(pd, friendly); + clif_send_petstatus(sd); + clif_displaymessage(fd, msg_txt(182)); // Pet intimacy changed. + return 0; } /*========================================== @@ -2657,34 +2807,34 @@ ACMD_FUNC(petfriendly) *------------------------------------------*/ ACMD_FUNC(pethungry) { - int hungry; - struct pet_data *pd; - nullpo_retr(-1, sd); + int hungry; + struct pet_data *pd; + nullpo_retr(-1, sd); - if (!message || !*message || (hungry = atoi(message)) < 0) { - clif_displaymessage(fd, msg_txt(1017)); // Please enter a valid number (usage: @pethungry <0-100>). - return -1; - } + if (!message || !*message || (hungry = atoi(message)) < 0) { + clif_displaymessage(fd, msg_txt(1017)); // Please enter a valid number (usage: @pethungry <0-100>). + return -1; + } - pd = sd->pd; - if (!sd->status.pet_id || !pd) { - clif_displaymessage(fd, msg_txt(184)); // Sorry, but you have no pet. - return -1; - } - if (hungry < 0 || hungry > 100) { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; - } - if (hungry == pd->pet.hungry) { - clif_displaymessage(fd, msg_txt(186)); // Pet hunger is already at maximum. - return -1; - } + pd = sd->pd; + if (!sd->status.pet_id || !pd) { + clif_displaymessage(fd, msg_txt(184)); // Sorry, but you have no pet. + return -1; + } + if (hungry < 0 || hungry > 100) { + clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. + return -1; + } + if (hungry == pd->pet.hungry) { + clif_displaymessage(fd, msg_txt(186)); // Pet hunger is already at maximum. + return -1; + } - pd->pet.hungry = hungry; - clif_send_petstatus(sd); - clif_displaymessage(fd, msg_txt(185)); // Pet hunger changed. + pd->pet.hungry = hungry; + clif_send_petstatus(sd); + clif_displaymessage(fd, msg_txt(185)); // Pet hunger changed. - return 0; + return 0; } /*========================================== @@ -2692,66 +2842,64 @@ ACMD_FUNC(pethungry) *------------------------------------------*/ ACMD_FUNC(petrename) { - struct pet_data *pd; - nullpo_retr(-1, sd); - if (!sd->status.pet_id || !sd->pd) { - clif_displaymessage(fd, msg_txt(184)); // Sorry, but you have no pet. - return -1; - } - pd = sd->pd; - if (!pd->pet.rename_flag) { - clif_displaymessage(fd, msg_txt(188)); // You can already rename your pet. - return -1; - } + struct pet_data *pd; + nullpo_retr(-1, sd); + if (!sd->status.pet_id || !sd->pd) { + clif_displaymessage(fd, msg_txt(184)); // Sorry, but you have no pet. + return -1; + } + pd = sd->pd; + if (!pd->pet.rename_flag) { + clif_displaymessage(fd, msg_txt(188)); // You can already rename your pet. + return -1; + } - pd->pet.rename_flag = 0; - intif_save_petdata(sd->status.account_id, &pd->pet); - clif_send_petstatus(sd); - clif_displaymessage(fd, msg_txt(187)); // You can now rename your pet. + pd->pet.rename_flag = 0; + intif_save_petdata(sd->status.account_id, &pd->pet); + clif_send_petstatus(sd); + clif_displaymessage(fd, msg_txt(187)); // You can now rename your pet. - return 0; + return 0; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(recall) -{ - struct map_session_data *pl_sd = NULL; +ACMD_FUNC(recall) { + struct map_session_data *pl_sd = NULL; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1018)); // Please enter a player name (usage: @recall <char name/ID>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1018)); // Please enter a player name (usage: @recall <char name/ID>). + return -1; + } - if ((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + if((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) + { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { - clif_displaymessage(fd, msg_txt(81)); // Your GM level doesn't authorize you to preform this action on the specified player. - return -1; - } + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) + { + clif_displaymessage(fd, msg_txt(81)); // Your GM level doesn't authorize you to preform this action on the specified player. + return -1; + } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(1019)); // You are not authorized to warp someone to this map. - return -1; - } - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(1020)); // You are not authorized to warp this player from their map. - return -1; - } - if (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y) { - return -1; - } - pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); - sprintf(atcmd_output, msg_txt(46), pl_sd->status.name); // %s recalled! - clif_displaymessage(fd, atcmd_output); + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(1019)); // You are not authorized to warp someone to this map. + return -1; + } + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(1020)); // You are not authorized to warp this player from their map. + return -1; + } + pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); + sprintf(atcmd_output, msg_txt(46), pl_sd->status.name); // %s recalled! + clif_displaymessage(fd, atcmd_output); - return 0; + return 0; } /*========================================== @@ -2760,19 +2908,19 @@ ACMD_FUNC(recall) *------------------------------------------*/ ACMD_FUNC(char_block) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1021)); // Please enter a player name (usage: @charblock/@block <char name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, msg_txt(1021)); // Please enter a player name (usage: @charblock/@block <char name>). + return -1; + } - 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_txt(88)); // Character name sent to char-server to ask it. + 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_txt(88)); // Character name sent to char-server to ask it. - return 0; + return 0; } /*========================================== @@ -2792,84 +2940,84 @@ ACMD_FUNC(char_block) *------------------------------------------*/ ACMD_FUNC(char_ban) { - char *modif_p; - int year, month, day, hour, minute, second, value; - time_t timestamp; - struct tm *tmtime; - nullpo_retr(-1, sd); - - memset(atcmd_output, '\0', sizeof(atcmd_output)); - memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - - if (!message || !*message || sscanf(message, "%s %23[^\n]", atcmd_output, atcmd_player_name) < 2) { - clif_displaymessage(fd, msg_txt(1022)); // Please enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <char name>). - return -1; - } - - atcmd_output[sizeof(atcmd_output)-1] = '\0'; - - modif_p = atcmd_output; - year = month = day = hour = minute = second = 0; - while (modif_p[0] != '\0') { - value = atoi(modif_p); - if (value == 0) - modif_p++; - else { - if (modif_p[0] == '-' || modif_p[0] == '+') - modif_p++; - while (modif_p[0] >= '0' && modif_p[0] <= '9') - modif_p++; - if (modif_p[0] == 's') { - second = value; - modif_p++; - } else if (modif_p[0] == 'n') { - minute = value; - modif_p++; - } else if (modif_p[0] == 'm' && modif_p[1] == 'n') { - minute = value; - modif_p = modif_p + 2; - } else if (modif_p[0] == 'h') { - hour = value; - modif_p++; - } else if (modif_p[0] == 'd' || modif_p[0] == 'j') { - day = value; - modif_p++; - } else if (modif_p[0] == 'm') { - month = value; - modif_p++; - } else if (modif_p[0] == 'y' || modif_p[0] == 'a') { - year = value; - modif_p++; - } else if (modif_p[0] != '\0') { - modif_p++; - } - } - } - if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0 && second == 0) { - clif_displaymessage(fd, msg_txt(85)); // Invalid time for ban command. - return -1; - } - /** - * We now check if you can adjust the ban to negative (and if this is the case) - **/ - timestamp = time(NULL); - tmtime = localtime(×tamp); - tmtime->tm_year = tmtime->tm_year + year; - tmtime->tm_mon = tmtime->tm_mon + month; - tmtime->tm_mday = tmtime->tm_mday + day; - tmtime->tm_hour = tmtime->tm_hour + hour; - tmtime->tm_min = tmtime->tm_min + minute; - tmtime->tm_sec = tmtime->tm_sec + second; - timestamp = mktime(tmtime); - if (timestamp <= time(NULL) && !pc_can_use_command(sd, "unban", COMMAND_ATCOMMAND)) { - clif_displaymessage(fd,msg_txt(1023)); // You are not allowed to reduce the length of a ban. - return -1; - } - - 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_txt(88)); // Character name sent to char-server to ask it. - - return 0; + char * modif_p; + int year, month, day, hour, minute, second, value; + time_t timestamp; + struct tm *tmtime; + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + + if (!message || !*message || sscanf(message, "%s %23[^\n]", atcmd_output, atcmd_player_name) < 2) { + clif_displaymessage(fd, msg_txt(1022)); // Please enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <char name>). + return -1; + } + + atcmd_output[sizeof(atcmd_output)-1] = '\0'; + + modif_p = atcmd_output; + year = month = day = hour = minute = second = 0; + while (modif_p[0] != '\0') { + value = atoi(modif_p); + if (value == 0) + modif_p++; + else { + if (modif_p[0] == '-' || modif_p[0] == '+') + modif_p++; + while (modif_p[0] >= '0' && modif_p[0] <= '9') + modif_p++; + if (modif_p[0] == 's') { + second = value; + modif_p++; + } else if (modif_p[0] == 'n') { + minute = value; + modif_p++; + } else if (modif_p[0] == 'm' && modif_p[1] == 'n') { + minute = value; + modif_p = modif_p + 2; + } else if (modif_p[0] == 'h') { + hour = value; + modif_p++; + } else if (modif_p[0] == 'd' || modif_p[0] == 'j') { + day = value; + modif_p++; + } else if (modif_p[0] == 'm') { + month = value; + modif_p++; + } else if (modif_p[0] == 'y' || modif_p[0] == 'a') { + year = value; + modif_p++; + } else if (modif_p[0] != '\0') { + modif_p++; + } + } + } + if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0 && second == 0) { + clif_displaymessage(fd, msg_txt(85)); // Invalid time for ban command. + return -1; + } + /** + * We now check if you can adjust the ban to negative (and if this is the case) + **/ + timestamp = time(NULL); + tmtime = localtime(×tamp); + tmtime->tm_year = tmtime->tm_year + year; + tmtime->tm_mon = tmtime->tm_mon + month; + tmtime->tm_mday = tmtime->tm_mday + day; + tmtime->tm_hour = tmtime->tm_hour + hour; + tmtime->tm_min = tmtime->tm_min + minute; + tmtime->tm_sec = tmtime->tm_sec + second; + timestamp = mktime(tmtime); + if( timestamp <= time(NULL) && !pc_can_use_command(sd, "unban", COMMAND_ATCOMMAND) ) { + clif_displaymessage(fd,msg_txt(1023)); // You are not allowed to reduce the length of a ban. + return -1; + } + + 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_txt(88)); // Character name sent to char-server to ask it. + + return 0; } /*========================================== @@ -2877,20 +3025,20 @@ ACMD_FUNC(char_ban) *------------------------------------------*/ ACMD_FUNC(char_unblock) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1024)); // Please enter a player name (usage: @charunblock <char name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, msg_txt(1024)); // Please enter a player name (usage: @charunblock <char name>). + return -1; + } - // send answer to login server via char-server - 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_txt(88)); // Character name sent to char-server to ask it. + // send answer to login server via char-server + 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_txt(88)); // Character name sent to char-server to ask it. - return 0; + return 0; } /*========================================== @@ -2898,20 +3046,20 @@ ACMD_FUNC(char_unblock) *------------------------------------------*/ ACMD_FUNC(char_unban) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1025)); // Please enter a player name (usage: @charunban <char name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, msg_txt(1025)); // Please enter a player name (usage: @charunban <char name>). + return -1; + } - // send answer to login server via char-server - 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_txt(88)); // Character name sent to char-server to ask it. + // send answer to login server via char-server + 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_txt(88)); // Character name sent to char-server to ask it. - return 0; + return 0; } /*========================================== @@ -2919,16 +3067,16 @@ ACMD_FUNC(char_unban) *------------------------------------------*/ ACMD_FUNC(night) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (night_flag != 1) { - map_night_timer(night_timer_tid, 0, 0, 1); - } else { - clif_displaymessage(fd, msg_txt(89)); // Night mode is already enabled. - return -1; - } + if (night_flag != 1) { + map_night_timer(night_timer_tid, 0, 0, 1); + } else { + clif_displaymessage(fd, msg_txt(89)); // Night mode is already enabled. + return -1; + } - return 0; + return 0; } /*========================================== @@ -2936,16 +3084,16 @@ ACMD_FUNC(night) *------------------------------------------*/ ACMD_FUNC(day) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (night_flag != 0) { - map_day_timer(day_timer_tid, 0, 0, 1); - } else { - clif_displaymessage(fd, msg_txt(90)); // Day mode is already enabled. - return -1; - } + if (night_flag != 0) { + map_day_timer(day_timer_tid, 0, 0, 1); + } else { + clif_displaymessage(fd, msg_txt(90)); // Day mode is already enabled. + return -1; + } - return 0; + return 0; } /*========================================== @@ -2953,24 +3101,26 @@ ACMD_FUNC(day) *------------------------------------------*/ ACMD_FUNC(doom) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; + struct map_session_data* pl_sd; + struct s_mapiterator* iter; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (pl_sd->fd != fd && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { - status_kill(&pl_sd->bl); - clif_specialeffect(&pl_sd->bl,450,AREA); - clif_displaymessage(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement. - } - } - mapit_free(iter); + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + if (pl_sd->fd != fd && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) + { + status_kill(&pl_sd->bl); + clif_specialeffect(&pl_sd->bl,450,AREA); + clif_displaymessage(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement. + } + } + mapit_free(iter); - clif_displaymessage(fd, msg_txt(62)); // Judgement was made. + clif_displaymessage(fd, msg_txt(62)); // Judgement was made. - return 0; + return 0; } /*========================================== @@ -2978,36 +3128,37 @@ ACMD_FUNC(doom) *------------------------------------------*/ ACMD_FUNC(doommap) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; + struct map_session_data* pl_sd; + struct s_mapiterator* iter; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (pl_sd->fd != fd && sd->bl.m == pl_sd->bl.m && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { - status_kill(&pl_sd->bl); - clif_specialeffect(&pl_sd->bl,450,AREA); - clif_displaymessage(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement. - } - } - mapit_free(iter); + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + if (pl_sd->fd != fd && sd->bl.m == pl_sd->bl.m && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) + { + status_kill(&pl_sd->bl); + clif_specialeffect(&pl_sd->bl,450,AREA); + clif_displaymessage(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement. + } + } + mapit_free(iter); - clif_displaymessage(fd, msg_txt(62)); // Judgement was made. + clif_displaymessage(fd, msg_txt(62)); // Judgement was made. - return 0; + return 0; } /*========================================== * *------------------------------------------*/ -static void atcommand_raise_sub(struct map_session_data *sd) -{ +static void atcommand_raise_sub(struct map_session_data* sd) { - status_revive(&sd->bl, 100, 100); + status_revive(&sd->bl, 100, 100); - clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); - clif_displaymessage(sd->fd, msg_txt(63)); // Mercy has been shown. + clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); + clif_displaymessage(sd->fd, msg_txt(63)); // Mercy has been shown. } /*========================================== @@ -3015,20 +3166,20 @@ static void atcommand_raise_sub(struct map_session_data *sd) *------------------------------------------*/ ACMD_FUNC(raise) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; + struct map_session_data* pl_sd; + struct s_mapiterator* iter; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) - if (pc_isdead(pl_sd)) - atcommand_raise_sub(pl_sd); - mapit_free(iter); + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + if( pc_isdead(pl_sd) ) + atcommand_raise_sub(pl_sd); + mapit_free(iter); - clif_displaymessage(fd, msg_txt(64)); // Mercy has been granted. + clif_displaymessage(fd, msg_txt(64)); // Mercy has been granted. - return 0; + return 0; } /*========================================== @@ -3036,20 +3187,20 @@ ACMD_FUNC(raise) *------------------------------------------*/ ACMD_FUNC(raisemap) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; + struct map_session_data* pl_sd; + struct s_mapiterator* iter; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) - if (sd->bl.m == pl_sd->bl.m && pc_isdead(pl_sd)) - atcommand_raise_sub(pl_sd); - mapit_free(iter); + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + if (sd->bl.m == pl_sd->bl.m && pc_isdead(pl_sd) ) + atcommand_raise_sub(pl_sd); + mapit_free(iter); - clif_displaymessage(fd, msg_txt(64)); // Mercy has been granted. + clif_displaymessage(fd, msg_txt(64)); // Mercy has been granted. - return 0; + return 0; } /*========================================== @@ -3057,29 +3208,31 @@ ACMD_FUNC(raisemap) *------------------------------------------*/ ACMD_FUNC(kick) { - struct map_session_data *pl_sd; - nullpo_retr(-1, sd); + struct map_session_data *pl_sd; + nullpo_retr(-1, sd); - memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1026)); // Please enter a player name (usage: @kick <char name/ID>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1026)); // Please enter a player name (usage: @kick <char name/ID>). + return -1; + } - if ((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + if((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) + { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; - } + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) + { + clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return -1; + } - clif_GM_kick(sd, pl_sd); + clif_GM_kick(sd, pl_sd); - return 0; + return 0; } /*========================================== @@ -3087,22 +3240,23 @@ ACMD_FUNC(kick) *------------------------------------------*/ ACMD_FUNC(kickall) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; - nullpo_retr(-1, sd); + struct map_session_data* pl_sd; + struct s_mapiterator* iter; + nullpo_retr(-1, sd); - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kick only lower or same gm level - if (sd->status.account_id != pl_sd->status.account_id) - clif_GM_kick(NULL, pl_sd); - } - } - mapit_free(iter); + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kick only lower or same gm level + if (sd->status.account_id != pl_sd->status.account_id) + clif_GM_kick(NULL, pl_sd); + } + } + mapit_free(iter); - clif_displaymessage(fd, msg_txt(195)); // All players have been kicked! + clif_displaymessage(fd, msg_txt(195)); // All players have been kicked! - return 0; + return 0; } /*========================================== @@ -3110,13 +3264,13 @@ ACMD_FUNC(kickall) *------------------------------------------*/ ACMD_FUNC(allskill) { - nullpo_retr(-1, sd); - pc_allskillup(sd); // all skills - sd->status.skill_point = 0; // 0 skill points - clif_updatestatus(sd, SP_SKILLPOINT); // update - clif_displaymessage(fd, msg_txt(76)); // All skills have been added to your skill tree. + nullpo_retr(-1, sd); + pc_allskillup(sd); // all skills + sd->status.skill_point = 0; // 0 skill points + clif_updatestatus(sd, SP_SKILLPOINT); // update + clif_displaymessage(fd, msg_txt(76)); // All skills have been added to your skill tree. - return 0; + return 0; } /*========================================== @@ -3124,43 +3278,43 @@ ACMD_FUNC(allskill) *------------------------------------------*/ ACMD_FUNC(questskill) { - int skill_id; - nullpo_retr(-1, sd); + int skill_id; + nullpo_retr(-1, sd); - if (!message || !*message || (skill_id = atoi(message)) < 0) { - // also send a list of skills applicable to this command - const char *text; + if (!message || !*message || (skill_id = atoi(message)) < 0) + {// also send a list of skills applicable to this command + const char* text; - // attempt to find the text corresponding to this command - text = atcommand_help_string(command); + // attempt to find the text corresponding to this command + text = atcommand_help_string( command ); - // send the error message as always - clif_displaymessage(fd, msg_txt(1027)); // Please enter a quest skill number. + // send the error message as always + clif_displaymessage(fd, msg_txt(1027)); // Please enter a quest skill number. - if (text) { - // send the skill ID list associated with this command - clif_displaymessage(fd, text); - } + if( text ) + {// send the skill ID list associated with this command + clif_displaymessage( fd, text ); + } - return -1; - } - if (skill_id < 0 && skill_id >= MAX_SKILL_DB) { - clif_displaymessage(fd, msg_txt(198)); // This skill number doesn't exist. - return -1; - } - if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) { - clif_displaymessage(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill. - return -1; - } - if (pc_checkskill(sd, skill_id) > 0) { - clif_displaymessage(fd, msg_txt(196)); // You already have this quest skill. - return -1; - } + return -1; + } + if (skill_id < 0 && skill_id >= MAX_SKILL_DB) { + clif_displaymessage(fd, msg_txt(198)); // This skill number doesn't exist. + return -1; + } + if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) { + clif_displaymessage(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill. + return -1; + } + if (pc_checkskill(sd, skill_id) > 0) { + clif_displaymessage(fd, msg_txt(196)); // You already have this quest skill. + return -1; + } - pc_skill(sd, skill_id, 1, 0); - clif_displaymessage(fd, msg_txt(70)); // You have learned the skill. + pc_skill(sd, skill_id, 1, 0); + clif_displaymessage(fd, msg_txt(70)); // You have learned the skill. - return 0; + return 0; } /*========================================== @@ -3168,45 +3322,45 @@ ACMD_FUNC(questskill) *------------------------------------------*/ ACMD_FUNC(lostskill) { - int skill_id; - nullpo_retr(-1, sd); + int skill_id; + nullpo_retr(-1, sd); - if (!message || !*message || (skill_id = atoi(message)) < 0) { - // also send a list of skills applicable to this command - const char *text; + if (!message || !*message || (skill_id = atoi(message)) < 0) + {// also send a list of skills applicable to this command + const char* text; - // attempt to find the text corresponding to this command - text = atcommand_help_string(command); + // attempt to find the text corresponding to this command + text = atcommand_help_string( command ); - // send the error message as always - clif_displaymessage(fd, msg_txt(1027)); // Please enter a quest skill number. + // send the error message as always + clif_displaymessage(fd, msg_txt(1027)); // Please enter a quest skill number. - if (text) { - // send the skill ID list associated with this command - clif_displaymessage(fd, text); - } + if( text ) + {// send the skill ID list associated with this command + clif_displaymessage( fd, text ); + } - return -1; - } - if (skill_id < 0 && skill_id >= MAX_SKILL) { - clif_displaymessage(fd, msg_txt(198)); // This skill number doesn't exist. - return -1; - } - if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) { - clif_displaymessage(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill. - return -1; - } - if (pc_checkskill(sd, skill_id) == 0) { - clif_displaymessage(fd, msg_txt(201)); // You don't have this quest skill. - return -1; - } + return -1; + } + if (skill_id < 0 && skill_id >= MAX_SKILL) { + clif_displaymessage(fd, msg_txt(198)); // This skill number doesn't exist. + return -1; + } + if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) { + clif_displaymessage(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill. + return -1; + } + if (pc_checkskill(sd, skill_id) == 0) { + clif_displaymessage(fd, msg_txt(201)); // You don't have this quest skill. + return -1; + } - sd->status.skill[skill_id].lv = 0; - sd->status.skill[skill_id].flag = 0; - clif_deleteskill(sd,skill_id); - clif_displaymessage(fd, msg_txt(71)); // You have forgotten the skill. + sd->status.skill[skill_id].lv = 0; + sd->status.skill[skill_id].flag = 0; + clif_deleteskill(sd,skill_id); + clif_displaymessage(fd, msg_txt(71)); // You have forgotten the skill. - return 0; + return 0; } /*========================================== @@ -3214,26 +3368,27 @@ ACMD_FUNC(lostskill) *------------------------------------------*/ ACMD_FUNC(spiritball) { - int max_spiritballs; - int number; - nullpo_retr(-1, sd); + int max_spiritballs; + int number; + nullpo_retr(-1, sd); - max_spiritballs = min(ARRAYLENGTH(sd->spirit_timer), 0x7FFF); + max_spiritballs = min(ARRAYLENGTH(sd->spirit_timer), 0x7FFF); - if (!message || !*message || (number = atoi(message)) < 0 || number > max_spiritballs) { - char msg[CHAT_SIZE_MAX]; - safesnprintf(msg, sizeof(msg), msg_txt(1028), max_spiritballs); // Please enter a party name (usage: @party <party_name>). - clif_displaymessage(fd, msg); - return -1; - } + if( !message || !*message || (number = atoi(message)) < 0 || number > max_spiritballs ) + { + char msg[CHAT_SIZE_MAX]; + safesnprintf(msg, sizeof(msg), msg_txt(1028), max_spiritballs); // Please enter a party name (usage: @party <party_name>). + clif_displaymessage(fd, msg); + return -1; + } - if (sd->spiritball > 0) - pc_delspiritball(sd, sd->spiritball, 1); - sd->spiritball = number; - clif_spiritball(&sd->bl); - // no message, player can look the difference + if( sd->spiritball > 0 ) + pc_delspiritball(sd, sd->spiritball, 1); + sd->spiritball = number; + clif_spiritball(&sd->bl); + // no message, player can look the difference - return 0; + return 0; } /*========================================== @@ -3241,19 +3396,19 @@ ACMD_FUNC(spiritball) *------------------------------------------*/ ACMD_FUNC(party) { - char party[NAME_LENGTH]; - nullpo_retr(-1, sd); + char party[NAME_LENGTH]; + nullpo_retr(-1, sd); - memset(party, '\0', sizeof(party)); + memset(party, '\0', sizeof(party)); - if (!message || !*message || sscanf(message, "%23[^\n]", party) < 1) { - clif_displaymessage(fd, msg_txt(1029)); // Please enter a party name (usage: @party <party_name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", party) < 1) { + clif_displaymessage(fd, msg_txt(1029)); // Please enter a party name (usage: @party <party_name>). + return -1; + } - party_create(sd, party, 0, 0); + party_create(sd, party, 0, 0); - return 0; + return 0; } /*========================================== @@ -3261,23 +3416,23 @@ ACMD_FUNC(party) *------------------------------------------*/ ACMD_FUNC(guild) { - char guild[NAME_LENGTH]; - int prev; - nullpo_retr(-1, sd); + char guild[NAME_LENGTH]; + int prev; + nullpo_retr(-1, sd); - memset(guild, '\0', sizeof(guild)); + memset(guild, '\0', sizeof(guild)); - if (!message || !*message || sscanf(message, "%23[^\n]", guild) < 1) { - clif_displaymessage(fd, msg_txt(1030)); // Please enter a guild name (usage: @guild <guild_name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", guild) < 1) { + clif_displaymessage(fd, msg_txt(1030)); // Please enter a guild name (usage: @guild <guild_name>). + return -1; + } - prev = battle_config.guild_emperium_check; - battle_config.guild_emperium_check = 0; - guild_create(sd, guild); - battle_config.guild_emperium_check = prev; + prev = battle_config.guild_emperium_check; + battle_config.guild_emperium_check = 0; + guild_create(sd, guild); + battle_config.guild_emperium_check = prev; - return 0; + return 0; } /*========================================== @@ -3285,17 +3440,17 @@ ACMD_FUNC(guild) *------------------------------------------*/ ACMD_FUNC(agitstart) { - nullpo_retr(-1, sd); - if (agit_flag == 1) { - clif_displaymessage(fd, msg_txt(73)); // War of Emperium is currently in progress. - return -1; - } + nullpo_retr(-1, sd); + if (agit_flag == 1) { + clif_displaymessage(fd, msg_txt(73)); // War of Emperium is currently in progress. + return -1; + } - agit_flag = 1; - guild_agit_start(); - clif_displaymessage(fd, msg_txt(72)); // War of Emperium has been initiated. + agit_flag = 1; + guild_agit_start(); + clif_displaymessage(fd, msg_txt(72)); // War of Emperium has been initiated. - return 0; + return 0; } /*========================================== @@ -3303,17 +3458,17 @@ ACMD_FUNC(agitstart) *------------------------------------------*/ ACMD_FUNC(agitstart2) { - nullpo_retr(-1, sd); - if (agit2_flag == 1) { - clif_displaymessage(fd, msg_txt(404)); // "War of Emperium SE is currently in progress." - return -1; - } + nullpo_retr(-1, sd); + if (agit2_flag == 1) { + clif_displaymessage(fd, msg_txt(404)); // "War of Emperium SE is currently in progress." + return -1; + } - agit2_flag = 1; - guild_agit2_start(); - clif_displaymessage(fd, msg_txt(403)); // "War of Emperium SE has been initiated." + agit2_flag = 1; + guild_agit2_start(); + clif_displaymessage(fd, msg_txt(403)); // "War of Emperium SE has been initiated." - return 0; + return 0; } /*========================================== @@ -3321,17 +3476,17 @@ ACMD_FUNC(agitstart2) *------------------------------------------*/ ACMD_FUNC(agitend) { - nullpo_retr(-1, sd); - if (agit_flag == 0) { - clif_displaymessage(fd, msg_txt(75)); // War of Emperium is currently not in progress. - return -1; - } + nullpo_retr(-1, sd); + if (agit_flag == 0) { + clif_displaymessage(fd, msg_txt(75)); // War of Emperium is currently not in progress. + return -1; + } - agit_flag = 0; - guild_agit_end(); - clif_displaymessage(fd, msg_txt(74)); // War of Emperium has been ended. + agit_flag = 0; + guild_agit_end(); + clif_displaymessage(fd, msg_txt(74)); // War of Emperium has been ended. - return 0; + return 0; } /*========================================== @@ -3339,17 +3494,17 @@ ACMD_FUNC(agitend) *------------------------------------------*/ ACMD_FUNC(agitend2) { - nullpo_retr(-1, sd); - if (agit2_flag == 0) { - clif_displaymessage(fd, msg_txt(406)); // "War of Emperium SE is currently not in progress." - return -1; - } + nullpo_retr(-1, sd); + if (agit2_flag == 0) { + clif_displaymessage(fd, msg_txt(406)); // "War of Emperium SE is currently not in progress." + return -1; + } - agit2_flag = 0; - guild_agit2_end(); - clif_displaymessage(fd, msg_txt(405)); // "War of Emperium SE has been ended." + agit2_flag = 0; + guild_agit2_end(); + clif_displaymessage(fd, msg_txt(405)); // "War of Emperium SE has been ended." - return 0; + return 0; } /*========================================== @@ -3357,10 +3512,10 @@ ACMD_FUNC(agitend2) *------------------------------------------*/ ACMD_FUNC(mapexit) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - do_shutdown(); - return 0; + do_shutdown(); + return 0; } /*========================================== @@ -3368,35 +3523,35 @@ ACMD_FUNC(mapexit) *------------------------------------------*/ ACMD_FUNC(idsearch) { - char item_name[100]; - unsigned int i, match; - struct item_data *item_array[MAX_SEARCH]; - nullpo_retr(-1, sd); + char item_name[100]; + unsigned int i, match; + struct item_data *item_array[MAX_SEARCH]; + nullpo_retr(-1, sd); - memset(item_name, '\0', sizeof(item_name)); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(item_name, '\0', sizeof(item_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message || sscanf(message, "%99s", item_name) < 0) { - clif_displaymessage(fd, msg_txt(1031)); // Please enter part of an item name (usage: @idsearch <part_of_item_name>). - return -1; - } + if (!message || !*message || sscanf(message, "%99s", item_name) < 0) { + clif_displaymessage(fd, msg_txt(1031)); // Please enter part of an item name (usage: @idsearch <part_of_item_name>). + return -1; + } - sprintf(atcmd_output, msg_txt(77), item_name); // The reference result of '%s' (name: id): - clif_displaymessage(fd, atcmd_output); - match = itemdb_searchname_array(item_array, MAX_SEARCH, item_name); - if (match > MAX_SEARCH) { - sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, match); - clif_displaymessage(fd, atcmd_output); - match = MAX_SEARCH; - } - for (i = 0; i < match; i++) { - sprintf(atcmd_output, msg_txt(78), item_array[i]->jname, item_array[i]->nameid); // %s: %d - clif_displaymessage(fd, atcmd_output); - } - sprintf(atcmd_output, msg_txt(79), match); // It is %d affair above. - clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(77), item_name); // The reference result of '%s' (name: id): + clif_displaymessage(fd, atcmd_output); + match = itemdb_searchname_array(item_array, MAX_SEARCH, item_name); + if (match > MAX_SEARCH) { + sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, match); + clif_displaymessage(fd, atcmd_output); + match = MAX_SEARCH; + } + for(i = 0; i < match; i++) { + sprintf(atcmd_output, msg_txt(78), item_array[i]->jname, item_array[i]->nameid); // %s: %d + clif_displaymessage(fd, atcmd_output); + } + sprintf(atcmd_output, msg_txt(79), match); // It is %d affair above. + clif_displaymessage(fd, atcmd_output); - return 0; + return 0; } /*========================================== @@ -3404,44 +3559,44 @@ ACMD_FUNC(idsearch) *------------------------------------------*/ ACMD_FUNC(recallall) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; - int count; - nullpo_retr(-1, sd); - - memset(atcmd_output, '\0', sizeof(atcmd_output)); - - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. - return -1; - } - - count = 0; - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (sd->status.account_id != pl_sd->status.account_id && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { - if (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y) - continue; // Don't waste time warping the character to the same place. - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) - count++; - else { - if (pc_isdead(pl_sd)) { //Wake them up - pc_setstand(pl_sd); - pc_setrestartvalue(pl_sd,1); - } - pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); - } - } - } - mapit_free(iter); - - clif_displaymessage(fd, msg_txt(92)); // All characters recalled! - if (count) { - sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. - clif_displaymessage(fd, atcmd_output); - } - - return 0; + struct map_session_data* pl_sd; + struct s_mapiterator* iter; + int count; + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. + return -1; + } + + count = 0; + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + if (sd->status.account_id != pl_sd->status.account_id && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) + { + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) + count++; + else { + if (pc_isdead(pl_sd)) { //Wake them up + pc_setstand(pl_sd); + pc_setrestartvalue(pl_sd,1); + } + pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); + } + } + } + mapit_free(iter); + + clif_displaymessage(fd, msg_txt(92)); // All characters recalled! + if (count) { + sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. + clif_displaymessage(fd, atcmd_output); + } + + return 0; } /*========================================== @@ -3449,55 +3604,58 @@ ACMD_FUNC(recallall) *------------------------------------------*/ ACMD_FUNC(guildrecall) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; - int count; - char guild_name[NAME_LENGTH]; - struct guild *g; - nullpo_retr(-1, sd); - - memset(guild_name, '\0', sizeof(guild_name)); - memset(atcmd_output, '\0', sizeof(atcmd_output)); - - if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { - clif_displaymessage(fd, msg_txt(1034)); // Please enter a guild name/ID (usage: @guildrecall <guild_name/ID>). - return -1; - } - - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. - return -1; - } - - if ((g = guild_searchname(guild_name)) == NULL && // name first to avoid error when name begin with a number - (g = guild_search(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. - return -1; - } - - count = 0; - - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.guild_id == g->guild_id) { - if (pc_get_group_level(pl_sd) > pc_get_group_level(sd) || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y)) - continue; //Skip GMs greater than you. - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) - count++; - else - pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); - } - } - mapit_free(iter); - - sprintf(atcmd_output, msg_txt(93), g->name); // All online characters of the %s guild have been recalled to your position. - clif_displaymessage(fd, atcmd_output); - if (count) { - sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. - clif_displaymessage(fd, atcmd_output); - } - - return 0; + struct map_session_data* pl_sd; + struct s_mapiterator* iter; + int count; + char guild_name[NAME_LENGTH]; + struct guild *g; + nullpo_retr(-1, sd); + + memset(guild_name, '\0', sizeof(guild_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { + clif_displaymessage(fd, msg_txt(1034)); // Please enter a guild name/ID (usage: @guildrecall <guild_name/ID>). + return -1; + } + + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. + return -1; + } + + if ((g = guild_searchname(guild_name)) == NULL && // name first to avoid error when name begin with a number + (g = guild_search(atoi(message))) == NULL) + { + clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. + return -1; + } + + count = 0; + + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.guild_id == g->guild_id) + { + if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) + continue; //Skip GMs greater than you. + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) + count++; + else + pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); + } + } + mapit_free(iter); + + sprintf(atcmd_output, msg_txt(93), g->name); // All online characters of the %s guild have been recalled to your position. + clif_displaymessage(fd, atcmd_output); + if (count) { + sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. + clif_displaymessage(fd, atcmd_output); + } + + return 0; } /*========================================== @@ -3505,55 +3663,58 @@ ACMD_FUNC(guildrecall) *------------------------------------------*/ ACMD_FUNC(partyrecall) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; - char party_name[NAME_LENGTH]; - struct party_data *p; - int count; - nullpo_retr(-1, sd); - - memset(party_name, '\0', sizeof(party_name)); - memset(atcmd_output, '\0', sizeof(atcmd_output)); - - if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) { - clif_displaymessage(fd, msg_txt(1035)); // Please enter a party name/ID (usage: @partyrecall <party_name/ID>). - return -1; - } - - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. - return -1; - } - - if ((p = party_searchname(party_name)) == NULL && // name first to avoid error when name begin with a number - (p = party_search(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(96)); // Incorrect name or ID, or no one from the party is online. - return -1; - } - - count = 0; - - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.party_id == p->party.party_id) { - if (pc_get_group_level(pl_sd) > pc_get_group_level(sd) || (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y)) - continue; //Skip GMs greater than you. - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) - count++; - else - pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); - } - } - mapit_free(iter); - - sprintf(atcmd_output, msg_txt(95), p->party.name); // All online characters of the %s party have been recalled to your position. - clif_displaymessage(fd, atcmd_output); - if (count) { - sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. - clif_displaymessage(fd, atcmd_output); - } - - return 0; + struct map_session_data* pl_sd; + struct s_mapiterator* iter; + char party_name[NAME_LENGTH]; + struct party_data *p; + int count; + nullpo_retr(-1, sd); + + memset(party_name, '\0', sizeof(party_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) { + clif_displaymessage(fd, msg_txt(1035)); // Please enter a party name/ID (usage: @partyrecall <party_name/ID>). + return -1; + } + + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. + return -1; + } + + if ((p = party_searchname(party_name)) == NULL && // name first to avoid error when name begin with a number + (p = party_search(atoi(message))) == NULL) + { + clif_displaymessage(fd, msg_txt(96)); // Incorrect name or ID, or no one from the party is online. + return -1; + } + + count = 0; + + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.party_id == p->party.party_id) + { + if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) + continue; //Skip GMs greater than you. + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) + count++; + else + pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); + } + } + mapit_free(iter); + + sprintf(atcmd_output, msg_txt(95), p->party.name); // All online characters of the %s party have been recalled to your position. + clif_displaymessage(fd, atcmd_output); + if (count) { + sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. + clif_displaymessage(fd, atcmd_output); + } + + return 0; } /*========================================== @@ -3561,11 +3722,11 @@ ACMD_FUNC(partyrecall) *------------------------------------------*/ ACMD_FUNC(reloaditemdb) { - nullpo_retr(-1, sd); - itemdb_reload(); - clif_displaymessage(fd, msg_txt(97)); // Item database has been reloaded. + nullpo_retr(-1, sd); + itemdb_reload(); + clif_displaymessage(fd, msg_txt(97)); // Item database has been reloaded. - return 0; + return 0; } /*========================================== @@ -3573,16 +3734,16 @@ ACMD_FUNC(reloaditemdb) *------------------------------------------*/ ACMD_FUNC(reloadmobdb) { - nullpo_retr(-1, sd); - mob_reload(); - read_petdb(); - merc_reload(); - read_mercenarydb(); - read_mercenary_skilldb(); - reload_elementaldb(); - clif_displaymessage(fd, msg_txt(98)); // Monster database has been reloaded. + nullpo_retr(-1, sd); + mob_reload(); + read_petdb(); + merc_reload(); + read_mercenarydb(); + read_mercenary_skilldb(); + reload_elementaldb(); + clif_displaymessage(fd, msg_txt(98)); // Monster database has been reloaded. - return 0; + return 0; } /*========================================== @@ -3590,108 +3751,107 @@ ACMD_FUNC(reloadmobdb) *------------------------------------------*/ ACMD_FUNC(reloadskilldb) { - nullpo_retr(-1, sd); - skill_reload(); - merc_skill_reload(); - reload_elemental_skilldb(); - read_mercenary_skilldb(); - clif_displaymessage(fd, msg_txt(99)); // Skill database has been reloaded. + nullpo_retr(-1, sd); + skill_reload(); + merc_skill_reload(); + reload_elemental_skilldb(); + read_mercenary_skilldb(); + clif_displaymessage(fd, msg_txt(99)); // Skill database has been reloaded. - return 0; + return 0; } /*========================================== * @reloadatcommand - reloads atcommand_athena.conf groups.conf *------------------------------------------*/ void atcommand_doload(); -ACMD_FUNC(reloadatcommand) -{ - config_t run_test; +ACMD_FUNC(reloadatcommand) { + config_t run_test; - if (conf_read_file(&run_test, "conf/groups.conf")) { - clif_displaymessage(fd, msg_txt(1036)); // Error reading groups.conf, reload failed. - return -1; - } + if (conf_read_file(&run_test, "conf/groups.conf")) { + clif_displaymessage(fd, msg_txt(1036)); // Error reading groups.conf, reload failed. + return -1; + } - config_destroy(&run_test); + config_destroy(&run_test); - if (conf_read_file(&run_test, ATCOMMAND_CONF_FILENAME)) { - clif_displaymessage(fd, msg_txt(1037)); // Error reading atcommand_athena.conf, reload failed. - return -1; - } + if (conf_read_file(&run_test, ATCOMMAND_CONF_FILENAME)) { + clif_displaymessage(fd, msg_txt(1037)); // Error reading atcommand_athena.conf, reload failed. + return -1; + } - config_destroy(&run_test); + config_destroy(&run_test); - atcommand_doload(); - pc_groups_reload(); - clif_displaymessage(fd, msg_txt(254)); - return 0; + atcommand_doload(); + pc_groups_reload(); + clif_displaymessage(fd, msg_txt(254)); + return 0; } /*========================================== * @reloadbattleconf - reloads battle_athena.conf *------------------------------------------*/ ACMD_FUNC(reloadbattleconf) { - struct Battle_Config prev_config; - memcpy(&prev_config, &battle_config, sizeof(prev_config)); - - battle_config_read(BATTLE_CONF_FILENAME); - - if (prev_config.item_rate_mvp != battle_config.item_rate_mvp - || prev_config.item_rate_common != battle_config.item_rate_common - || prev_config.item_rate_common_boss != battle_config.item_rate_common_boss - || prev_config.item_rate_card != battle_config.item_rate_card - || prev_config.item_rate_card_boss != battle_config.item_rate_card_boss - || prev_config.item_rate_equip != battle_config.item_rate_equip - || prev_config.item_rate_equip_boss != battle_config.item_rate_equip_boss - || prev_config.item_rate_heal != battle_config.item_rate_heal - || prev_config.item_rate_heal_boss != battle_config.item_rate_heal_boss - || prev_config.item_rate_use != battle_config.item_rate_use - || prev_config.item_rate_use_boss != battle_config.item_rate_use_boss - || prev_config.item_rate_treasure != battle_config.item_rate_treasure - || prev_config.item_rate_adddrop != battle_config.item_rate_adddrop - || prev_config.logarithmic_drops != battle_config.logarithmic_drops - || prev_config.item_drop_common_min != battle_config.item_drop_common_min - || prev_config.item_drop_common_max != battle_config.item_drop_common_max - || prev_config.item_drop_card_min != battle_config.item_drop_card_min - || prev_config.item_drop_card_max != battle_config.item_drop_card_max - || prev_config.item_drop_equip_min != battle_config.item_drop_equip_min - || prev_config.item_drop_equip_max != battle_config.item_drop_equip_max - || prev_config.item_drop_mvp_min != battle_config.item_drop_mvp_min - || prev_config.item_drop_mvp_max != battle_config.item_drop_mvp_max - || prev_config.item_drop_heal_min != battle_config.item_drop_heal_min - || prev_config.item_drop_heal_max != battle_config.item_drop_heal_max - || prev_config.item_drop_use_min != battle_config.item_drop_use_min - || prev_config.item_drop_use_max != battle_config.item_drop_use_max - || prev_config.item_drop_treasure_min != battle_config.item_drop_treasure_min - || prev_config.item_drop_treasure_max != battle_config.item_drop_treasure_max - || prev_config.base_exp_rate != battle_config.base_exp_rate - || prev_config.job_exp_rate != battle_config.job_exp_rate - ) { - // Exp or Drop rates changed. - mob_reload(); //Needed as well so rate changes take effect. - chrif_ragsrvinfo(battle_config.base_exp_rate, battle_config.job_exp_rate, battle_config.item_rate_common); - } - clif_displaymessage(fd, msg_txt(255)); - return 0; + struct Battle_Config prev_config; + memcpy(&prev_config, &battle_config, sizeof(prev_config)); + + battle_config_read(BATTLE_CONF_FILENAME); + + if( prev_config.item_rate_mvp != battle_config.item_rate_mvp + || prev_config.item_rate_common != battle_config.item_rate_common + || prev_config.item_rate_common_boss != battle_config.item_rate_common_boss + || prev_config.item_rate_card != battle_config.item_rate_card + || prev_config.item_rate_card_boss != battle_config.item_rate_card_boss + || prev_config.item_rate_equip != battle_config.item_rate_equip + || prev_config.item_rate_equip_boss != battle_config.item_rate_equip_boss + || prev_config.item_rate_heal != battle_config.item_rate_heal + || prev_config.item_rate_heal_boss != battle_config.item_rate_heal_boss + || prev_config.item_rate_use != battle_config.item_rate_use + || prev_config.item_rate_use_boss != battle_config.item_rate_use_boss + || prev_config.item_rate_treasure != battle_config.item_rate_treasure + || prev_config.item_rate_adddrop != battle_config.item_rate_adddrop + || prev_config.logarithmic_drops != battle_config.logarithmic_drops + || prev_config.item_drop_common_min != battle_config.item_drop_common_min + || prev_config.item_drop_common_max != battle_config.item_drop_common_max + || prev_config.item_drop_card_min != battle_config.item_drop_card_min + || prev_config.item_drop_card_max != battle_config.item_drop_card_max + || prev_config.item_drop_equip_min != battle_config.item_drop_equip_min + || prev_config.item_drop_equip_max != battle_config.item_drop_equip_max + || prev_config.item_drop_mvp_min != battle_config.item_drop_mvp_min + || prev_config.item_drop_mvp_max != battle_config.item_drop_mvp_max + || prev_config.item_drop_heal_min != battle_config.item_drop_heal_min + || prev_config.item_drop_heal_max != battle_config.item_drop_heal_max + || prev_config.item_drop_use_min != battle_config.item_drop_use_min + || prev_config.item_drop_use_max != battle_config.item_drop_use_max + || prev_config.item_drop_treasure_min != battle_config.item_drop_treasure_min + || prev_config.item_drop_treasure_max != battle_config.item_drop_treasure_max + || prev_config.base_exp_rate != battle_config.base_exp_rate + || prev_config.job_exp_rate != battle_config.job_exp_rate + ) + { // Exp or Drop rates changed. + mob_reload(); //Needed as well so rate changes take effect. + chrif_ragsrvinfo(battle_config.base_exp_rate, battle_config.job_exp_rate, battle_config.item_rate_common); + } + clif_displaymessage(fd, msg_txt(255)); + return 0; } /*========================================== * @reloadstatusdb - reloads job_db1.txt job_db2.txt job_db2-2.txt refine_db.txt size_fix.txt *------------------------------------------*/ ACMD_FUNC(reloadstatusdb) { - status_readdb(); - clif_displaymessage(fd, msg_txt(256)); - return 0; + status_readdb(); + clif_displaymessage(fd, msg_txt(256)); + return 0; } /*========================================== * @reloadpcdb - reloads exp.txt skill_tree.txt attr_fix.txt statpoint.txt *------------------------------------------*/ ACMD_FUNC(reloadpcdb) { - pc_readdb(); - clif_displaymessage(fd, msg_txt(257)); - return 0; + pc_readdb(); + clif_displaymessage(fd, msg_txt(257)); + return 0; } /*========================================== @@ -3699,9 +3859,9 @@ ACMD_FUNC(reloadpcdb) *------------------------------------------*/ ACMD_FUNC(reloadmotd) { - pc_read_motd(); - clif_displaymessage(fd, msg_txt(268)); - return 0; + pc_read_motd(); + clif_displaymessage(fd, msg_txt(268)); + return 0; } /*========================================== @@ -3709,18 +3869,18 @@ ACMD_FUNC(reloadmotd) *------------------------------------------*/ ACMD_FUNC(reloadscript) { - nullpo_retr(-1, sd); - //atcommand_broadcast( fd, sd, "@broadcast", "Server is reloading scripts..." ); - //atcommand_broadcast( fd, sd, "@broadcast", "You will feel a bit of lag at this point !" ); + nullpo_retr(-1, sd); + //atcommand_broadcast( fd, sd, "@broadcast", "Server is reloading scripts..." ); + //atcommand_broadcast( fd, sd, "@broadcast", "You will feel a bit of lag at this point !" ); - flush_fifos(); - map_reloadnpc(true); // reload config files seeking for npcs - script_reload(); - npc_reload(); + flush_fifos(); + map_reloadnpc(true); // reload config files seeking for npcs + script_reload(); + npc_reload(); - clif_displaymessage(fd, msg_txt(100)); // Scripts have been reloaded. + clif_displaymessage(fd, msg_txt(100)); // Scripts have been reloaded. - return 0; + return 0; } /*========================================== @@ -3733,268 +3893,253 @@ ACMD_FUNC(reloadscript) *------------------------------------------*/ ACMD_FUNC(mapinfo) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; - struct npc_data *nd = NULL; - struct chat_data *cd = NULL; - char direction[12]; - int i, m_id, chat_num, list = 0; - unsigned short m_index; - char mapname[24]; - - nullpo_retr(-1, sd); - - memset(atcmd_output, '\0', sizeof(atcmd_output)); - memset(mapname, '\0', sizeof(mapname)); - memset(direction, '\0', sizeof(direction)); - - sscanf(message, "%d %23[^\n]", &list, mapname); - - if (list < 0 || list > 3) { - clif_displaymessage(fd, msg_txt(1038)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>). - return -1; - } - - if (mapname[0] == '\0') { - safestrncpy(mapname, mapindex_id2name(sd->mapindex), MAP_NAME_LENGTH); - m_id = map_mapindex2mapid(sd->mapindex); - } else { - m_id = map_mapname2mapid(mapname); - } - - if (m_id < 0) { - clif_displaymessage(fd, msg_txt(1)); // Map not found. - return -1; - } - m_index = mapindex_name2id(mapname); //This one shouldn't fail since the previous seek did not. - - clif_displaymessage(fd, msg_txt(1039)); // ------ Map Info ------ - - // count chats (for initial message) - chat_num = 0; - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) - if ((cd = (struct chat_data *)map_id2bl(pl_sd->chatID)) != NULL && pl_sd->mapindex == m_index && cd->usersd[0] == pl_sd) - chat_num++; - mapit_free(iter); - - sprintf(atcmd_output, msg_txt(1040), mapname, map[m_id].users, map[m_id].npc_num, chat_num); // Map Name: %s | Players In Map: %d | NPCs In Map: %d | Chats In Map: %d - clif_displaymessage(fd, atcmd_output); - clif_displaymessage(fd, msg_txt(1041)); // ------ Map Flags ------ - if (map[m_id].flag.town) - clif_displaymessage(fd, msg_txt(1042)); // Town Map - - if (battle_config.autotrade_mapflag == map[m_id].flag.autotrade) - clif_displaymessage(fd, msg_txt(1043)); // Autotrade Enabled - else - clif_displaymessage(fd, msg_txt(1044)); // Autotrade Disabled - - if (map[m_id].flag.battleground) - clif_displaymessage(fd, msg_txt(1045)); // Battlegrounds ON - - strcpy(atcmd_output,msg_txt(1046)); // PvP Flags: - if (map[m_id].flag.pvp) - strcat(atcmd_output, msg_txt(1047)); // Pvp ON | - if (map[m_id].flag.pvp_noguild) - strcat(atcmd_output, msg_txt(1048)); // NoGuild | - if (map[m_id].flag.pvp_noparty) - strcat(atcmd_output, msg_txt(1049)); // NoParty | - if (map[m_id].flag.pvp_nightmaredrop) - strcat(atcmd_output, msg_txt(1050)); // NightmareDrop | - if (map[m_id].flag.pvp_nocalcrank) - strcat(atcmd_output, msg_txt(1051)); // NoCalcRank | - clif_displaymessage(fd, atcmd_output); - - strcpy(atcmd_output,msg_txt(1052)); // GvG Flags: - if (map[m_id].flag.gvg) - strcat(atcmd_output, msg_txt(1053)); // GvG ON | - if (map[m_id].flag.gvg_dungeon) - strcat(atcmd_output, msg_txt(1054)); // GvG Dungeon | - if (map[m_id].flag.gvg_castle) - strcat(atcmd_output, msg_txt(1055)); // GvG Castle | - if (map[m_id].flag.gvg_noparty) - strcat(atcmd_output, msg_txt(1056)); // NoParty | - clif_displaymessage(fd, atcmd_output); - - strcpy(atcmd_output,msg_txt(1057)); // Teleport Flags: - if (map[m_id].flag.noteleport) - strcat(atcmd_output, msg_txt(1058)); // NoTeleport | - if (map[m_id].flag.monster_noteleport) - strcat(atcmd_output, msg_txt(1059)); // Monster NoTeleport | - if (map[m_id].flag.nowarp) - strcat(atcmd_output, msg_txt(1060)); // NoWarp | - if (map[m_id].flag.nowarpto) - strcat(atcmd_output, msg_txt(1061)); // NoWarpTo | - if (map[m_id].flag.noreturn) - strcat(atcmd_output, msg_txt(1062)); // NoReturn | - if (map[m_id].flag.nogo) - strcat(atcmd_output, msg_txt(1063)); // NoGo | - if (map[m_id].flag.nomemo) - strcat(atcmd_output, msg_txt(1064)); // NoMemo | - clif_displaymessage(fd, atcmd_output); - - sprintf(atcmd_output, msg_txt(1065), // No Exp Penalty: %s | No Zeny Penalty: %s - (map[m_id].flag.noexppenalty) ? msg_txt(1066) : msg_txt(1067), (map[m_id].flag.nozenypenalty) ? msg_txt(1066) : msg_txt(1067)); // On / Off - clif_displaymessage(fd, atcmd_output); - - if (map[m_id].flag.nosave) { - if (!map[m_id].save.map) - clif_displaymessage(fd, msg_txt(1068)); // No Save (Return to last Save Point) - else if (map[m_id].save.x == -1 || map[m_id].save.y == -1) { - sprintf(atcmd_output, msg_txt(1069), mapindex_id2name(map[m_id].save.map)); // No Save, Save Point: %s,Random - clif_displaymessage(fd, atcmd_output); - } else { - sprintf(atcmd_output, msg_txt(1070), // No Save, Save Point: %s,%d,%d - mapindex_id2name(map[m_id].save.map),map[m_id].save.x,map[m_id].save.y); - clif_displaymessage(fd, atcmd_output); - } - } - - strcpy(atcmd_output,msg_txt(1071)); // Weather Flags: - if (map[m_id].flag.snow) - strcat(atcmd_output, msg_txt(1072)); // Snow | - if (map[m_id].flag.fog) - strcat(atcmd_output, msg_txt(1073)); // Fog | - if (map[m_id].flag.sakura) - strcat(atcmd_output, msg_txt(1074)); // Sakura | - if (map[m_id].flag.clouds) - strcat(atcmd_output, msg_txt(1075)); // Clouds | - if (map[m_id].flag.clouds2) - strcat(atcmd_output, msg_txt(1076)); // Clouds2 | - if (map[m_id].flag.fireworks) - strcat(atcmd_output, msg_txt(1077)); // Fireworks | - if (map[m_id].flag.leaves) - strcat(atcmd_output, msg_txt(1078)); // Leaves | - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //if (map[m_id].flag.rain) - // strcat(atcmd_output, msg_txt(1079)); // Rain | - if (map[m_id].flag.nightenabled) - strcat(atcmd_output, msg_txt(1080)); // Displays Night | - clif_displaymessage(fd, atcmd_output); - - strcpy(atcmd_output,msg_txt(1081)); // Other Flags: - if (map[m_id].flag.nobranch) - strcat(atcmd_output, msg_txt(1082)); // NoBranch | - if (map[m_id].flag.notrade) - strcat(atcmd_output, msg_txt(1083)); // NoTrade | - if (map[m_id].flag.novending) - strcat(atcmd_output, msg_txt(1084)); // NoVending | - if (map[m_id].flag.nodrop) - strcat(atcmd_output, msg_txt(1085)); // NoDrop | - if (map[m_id].flag.noskill) - strcat(atcmd_output, msg_txt(1086)); // NoSkill | - if (map[m_id].flag.noicewall) - strcat(atcmd_output, msg_txt(1087)); // NoIcewall | - if (map[m_id].flag.allowks) - strcat(atcmd_output, msg_txt(1088)); // AllowKS | - if (map[m_id].flag.reset) - strcat(atcmd_output, msg_txt(1089)); // Reset | - clif_displaymessage(fd, atcmd_output); - - strcpy(atcmd_output,msg_txt(1090)); // Other Flags: - if (map[m_id].nocommand) - strcat(atcmd_output, msg_txt(1091)); // NoCommand | - if (map[m_id].flag.nobaseexp) - strcat(atcmd_output, msg_txt(1092)); // NoBaseEXP | - if (map[m_id].flag.nojobexp) - strcat(atcmd_output, msg_txt(1093)); // NoJobEXP | - if (map[m_id].flag.nomobloot) - strcat(atcmd_output, msg_txt(1094)); // NoMobLoot | - if (map[m_id].flag.nomvploot) - strcat(atcmd_output, msg_txt(1095)); // NoMVPLoot | - if (map[m_id].flag.partylock) - strcat(atcmd_output, msg_txt(1096)); // PartyLock | - if (map[m_id].flag.guildlock) - strcat(atcmd_output, msg_txt(1097)); // GuildLock | - clif_displaymessage(fd, atcmd_output); - - switch (list) { - case 0: - // Do nothing. It's list 0, no additional display. - break; - case 1: - clif_displaymessage(fd, msg_txt(1098)); // ----- Players in Map ----- - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (pl_sd->mapindex == m_index) { - sprintf(atcmd_output, msg_txt(1099), // Player '%s' (session #%d) | Location: %d,%d - pl_sd->status.name, pl_sd->fd, pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, atcmd_output); - } - } - mapit_free(iter); - break; - case 2: - clif_displaymessage(fd, msg_txt(1100)); // ----- NPCs in Map ----- - for (i = 0; i < map[m_id].npc_num;) { - nd = map[m_id].npc[i]; - switch (nd->ud.dir) { - case 0: - strcpy(direction, msg_txt(1101)); - break; // North - case 1: - strcpy(direction, msg_txt(1102)); - break; // North West - case 2: - strcpy(direction, msg_txt(1103)); - break; // West - case 3: - strcpy(direction, msg_txt(1104)); - break; // South West - case 4: - strcpy(direction, msg_txt(1105)); - break; // South - case 5: - strcpy(direction, msg_txt(1106)); - break; // South East - case 6: - strcpy(direction, msg_txt(1107)); - break; // East - case 7: - strcpy(direction, msg_txt(1108)); - break; // North East - case 9: - strcpy(direction, msg_txt(1109)); - break; // North - default: - strcpy(direction, msg_txt(1110)); - break; // Unknown - } - if (strcmp(nd->name,nd->exname) == 0) - sprintf(atcmd_output, msg_txt(1111), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d - ++i, nd->name, direction, nd->class_, nd->bl.x, nd->bl.y); - else - sprintf(atcmd_output, msg_txt(1112), // NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d - ++i, nd->name, nd->exname, direction, nd->class_, nd->bl.x, nd->bl.y); - clif_displaymessage(fd, atcmd_output); - } - break; - case 3: - clif_displaymessage(fd, msg_txt(1113)); // ----- Chats in Map ----- - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if ((cd = (struct chat_data *)map_id2bl(pl_sd->chatID)) != NULL && - pl_sd->mapindex == m_index && - cd->usersd[0] == pl_sd) { - sprintf(atcmd_output, msg_txt(1114), // Chat: %s | Player: %s | Location: %d %d - cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y); - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1115), // Users: %d/%d | Password: %s | Public: %s - cd->users, cd->limit, cd->pass, (cd->pub) ? msg_txt(1116) : msg_txt(1117)); // Yes / No - clif_displaymessage(fd, atcmd_output); - } - } - mapit_free(iter); - break; - default: // normally impossible to arrive here - clif_displaymessage(fd, msg_txt(1118)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>). - return -1; - break; - } - - return 0; + struct map_session_data* pl_sd; + struct s_mapiterator* iter; + struct npc_data *nd = NULL; + struct chat_data *cd = NULL; + char direction[12]; + int i, m_id, chat_num, list = 0; + unsigned short m_index; + char mapname[24]; + + nullpo_retr(-1, sd); + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(mapname, '\0', sizeof(mapname)); + memset(direction, '\0', sizeof(direction)); + + sscanf(message, "%d %23[^\n]", &list, mapname); + + if (list < 0 || list > 3) { + clif_displaymessage(fd, msg_txt(1038)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>). + return -1; + } + + if (mapname[0] == '\0') { + safestrncpy(mapname, mapindex_id2name(sd->mapindex), MAP_NAME_LENGTH); + m_id = map_mapindex2mapid(sd->mapindex); + } else { + m_id = map_mapname2mapid(mapname); + } + + if (m_id < 0) { + clif_displaymessage(fd, msg_txt(1)); // Map not found. + return -1; + } + m_index = mapindex_name2id(mapname); //This one shouldn't fail since the previous seek did not. + + clif_displaymessage(fd, msg_txt(1039)); // ------ Map Info ------ + + // count chats (for initial message) + chat_num = 0; + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + if( (cd = (struct chat_data*)map_id2bl(pl_sd->chatID)) != NULL && pl_sd->mapindex == m_index && cd->usersd[0] == pl_sd ) + chat_num++; + mapit_free(iter); + + sprintf(atcmd_output, msg_txt(1040), mapname, map[m_id].users, map[m_id].npc_num, chat_num); // Map Name: %s | Players In Map: %d | NPCs In Map: %d | Chats In Map: %d + clif_displaymessage(fd, atcmd_output); + clif_displaymessage(fd, msg_txt(1041)); // ------ Map Flags ------ + if (map[m_id].flag.town) + clif_displaymessage(fd, msg_txt(1042)); // Town Map + + if (battle_config.autotrade_mapflag == map[m_id].flag.autotrade) + clif_displaymessage(fd, msg_txt(1043)); // Autotrade Enabled + else + clif_displaymessage(fd, msg_txt(1044)); // Autotrade Disabled + + if (map[m_id].flag.battleground) + clif_displaymessage(fd, msg_txt(1045)); // Battlegrounds ON + + strcpy(atcmd_output,msg_txt(1046)); // PvP Flags: + if (map[m_id].flag.pvp) + strcat(atcmd_output, msg_txt(1047)); // Pvp ON | + if (map[m_id].flag.pvp_noguild) + strcat(atcmd_output, msg_txt(1048)); // NoGuild | + if (map[m_id].flag.pvp_noparty) + strcat(atcmd_output, msg_txt(1049)); // NoParty | + if (map[m_id].flag.pvp_nightmaredrop) + strcat(atcmd_output, msg_txt(1050)); // NightmareDrop | + if (map[m_id].flag.pvp_nocalcrank) + strcat(atcmd_output, msg_txt(1051)); // NoCalcRank | + clif_displaymessage(fd, atcmd_output); + + strcpy(atcmd_output,msg_txt(1052)); // GvG Flags: + if (map[m_id].flag.gvg) + strcat(atcmd_output, msg_txt(1053)); // GvG ON | + if (map[m_id].flag.gvg_dungeon) + strcat(atcmd_output, msg_txt(1054)); // GvG Dungeon | + if (map[m_id].flag.gvg_castle) + strcat(atcmd_output, msg_txt(1055)); // GvG Castle | + if (map[m_id].flag.gvg_noparty) + strcat(atcmd_output, msg_txt(1056)); // NoParty | + clif_displaymessage(fd, atcmd_output); + + strcpy(atcmd_output,msg_txt(1057)); // Teleport Flags: + if (map[m_id].flag.noteleport) + strcat(atcmd_output, msg_txt(1058)); // NoTeleport | + if (map[m_id].flag.monster_noteleport) + strcat(atcmd_output, msg_txt(1059)); // Monster NoTeleport | + if (map[m_id].flag.nowarp) + strcat(atcmd_output, msg_txt(1060)); // NoWarp | + if (map[m_id].flag.nowarpto) + strcat(atcmd_output, msg_txt(1061)); // NoWarpTo | + if (map[m_id].flag.noreturn) + strcat(atcmd_output, msg_txt(1062)); // NoReturn | + if (map[m_id].flag.nogo) + strcat(atcmd_output, msg_txt(1063)); // NoGo | + if (map[m_id].flag.nomemo) + strcat(atcmd_output, msg_txt(1064)); // NoMemo | + clif_displaymessage(fd, atcmd_output); + + sprintf(atcmd_output, msg_txt(1065), // No Exp Penalty: %s | No Zeny Penalty: %s + (map[m_id].flag.noexppenalty) ? msg_txt(1066) : msg_txt(1067), (map[m_id].flag.nozenypenalty) ? msg_txt(1066) : msg_txt(1067)); // On / Off + clif_displaymessage(fd, atcmd_output); + + if (map[m_id].flag.nosave) { + if (!map[m_id].save.map) + clif_displaymessage(fd, msg_txt(1068)); // No Save (Return to last Save Point) + else if (map[m_id].save.x == -1 || map[m_id].save.y == -1 ) { + sprintf(atcmd_output, msg_txt(1069), mapindex_id2name(map[m_id].save.map)); // No Save, Save Point: %s,Random + clif_displaymessage(fd, atcmd_output); + } + else { + sprintf(atcmd_output, msg_txt(1070), // No Save, Save Point: %s,%d,%d + mapindex_id2name(map[m_id].save.map),map[m_id].save.x,map[m_id].save.y); + clif_displaymessage(fd, atcmd_output); + } + } + + strcpy(atcmd_output,msg_txt(1071)); // Weather Flags: + if (map[m_id].flag.snow) + strcat(atcmd_output, msg_txt(1072)); // Snow | + if (map[m_id].flag.fog) + strcat(atcmd_output, msg_txt(1073)); // Fog | + if (map[m_id].flag.sakura) + strcat(atcmd_output, msg_txt(1074)); // Sakura | + if (map[m_id].flag.clouds) + strcat(atcmd_output, msg_txt(1075)); // Clouds | + if (map[m_id].flag.clouds2) + strcat(atcmd_output, msg_txt(1076)); // Clouds2 | + if (map[m_id].flag.fireworks) + strcat(atcmd_output, msg_txt(1077)); // Fireworks | + if (map[m_id].flag.leaves) + strcat(atcmd_output, msg_txt(1078)); // Leaves | + /** + * No longer available, keeping here just in case it's back someday. [Ind] + **/ + //if (map[m_id].flag.rain) + // strcat(atcmd_output, msg_txt(1079)); // Rain | + if (map[m_id].flag.nightenabled) + strcat(atcmd_output, msg_txt(1080)); // Displays Night | + clif_displaymessage(fd, atcmd_output); + + strcpy(atcmd_output,msg_txt(1081)); // Other Flags: + if (map[m_id].flag.nobranch) + strcat(atcmd_output, msg_txt(1082)); // NoBranch | + if (map[m_id].flag.notrade) + strcat(atcmd_output, msg_txt(1083)); // NoTrade | + if (map[m_id].flag.novending) + strcat(atcmd_output, msg_txt(1084)); // NoVending | + if (map[m_id].flag.nodrop) + strcat(atcmd_output, msg_txt(1085)); // NoDrop | + if (map[m_id].flag.noskill) + strcat(atcmd_output, msg_txt(1086)); // NoSkill | + if (map[m_id].flag.noicewall) + strcat(atcmd_output, msg_txt(1087)); // NoIcewall | + if (map[m_id].flag.allowks) + strcat(atcmd_output, msg_txt(1088)); // AllowKS | + if (map[m_id].flag.reset) + strcat(atcmd_output, msg_txt(1089)); // Reset | + clif_displaymessage(fd, atcmd_output); + + strcpy(atcmd_output,msg_txt(1090)); // Other Flags: + if (map[m_id].nocommand) + strcat(atcmd_output, msg_txt(1091)); // NoCommand | + if (map[m_id].flag.nobaseexp) + strcat(atcmd_output, msg_txt(1092)); // NoBaseEXP | + if (map[m_id].flag.nojobexp) + strcat(atcmd_output, msg_txt(1093)); // NoJobEXP | + if (map[m_id].flag.nomobloot) + strcat(atcmd_output, msg_txt(1094)); // NoMobLoot | + if (map[m_id].flag.nomvploot) + strcat(atcmd_output, msg_txt(1095)); // NoMVPLoot | + if (map[m_id].flag.partylock) + strcat(atcmd_output, msg_txt(1096)); // PartyLock | + if (map[m_id].flag.guildlock) + strcat(atcmd_output, msg_txt(1097)); // GuildLock | + clif_displaymessage(fd, atcmd_output); + + switch (list) { + case 0: + // Do nothing. It's list 0, no additional display. + break; + case 1: + clif_displaymessage(fd, msg_txt(1098)); // ----- Players in Map ----- + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + if (pl_sd->mapindex == m_index) { + sprintf(atcmd_output, msg_txt(1099), // Player '%s' (session #%d) | Location: %d,%d + pl_sd->status.name, pl_sd->fd, pl_sd->bl.x, pl_sd->bl.y); + clif_displaymessage(fd, atcmd_output); + } + } + mapit_free(iter); + break; + case 2: + clif_displaymessage(fd, msg_txt(1100)); // ----- NPCs in Map ----- + for (i = 0; i < map[m_id].npc_num;) + { + nd = map[m_id].npc[i]; + switch(nd->ud.dir) { + case 0: strcpy(direction, msg_txt(1101)); break; // North + case 1: strcpy(direction, msg_txt(1102)); break; // North West + case 2: strcpy(direction, msg_txt(1103)); break; // West + case 3: strcpy(direction, msg_txt(1104)); break; // South West + case 4: strcpy(direction, msg_txt(1105)); break; // South + case 5: strcpy(direction, msg_txt(1106)); break; // South East + case 6: strcpy(direction, msg_txt(1107)); break; // East + case 7: strcpy(direction, msg_txt(1108)); break; // North East + case 9: strcpy(direction, msg_txt(1109)); break; // North + default: strcpy(direction, msg_txt(1110)); break; // Unknown + } + if(strcmp(nd->name,nd->exname) == 0) + sprintf(atcmd_output, msg_txt(1111), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d + ++i, nd->name, direction, nd->class_, nd->bl.x, nd->bl.y); + else + sprintf(atcmd_output, msg_txt(1112), // NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d + ++i, nd->name, nd->exname, direction, nd->class_, nd->bl.x, nd->bl.y); + clif_displaymessage(fd, atcmd_output); + } + break; + case 3: + clif_displaymessage(fd, msg_txt(1113)); // ----- Chats in Map ----- + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + if ((cd = (struct chat_data*)map_id2bl(pl_sd->chatID)) != NULL && + pl_sd->mapindex == m_index && + cd->usersd[0] == pl_sd) + { + sprintf(atcmd_output, msg_txt(1114), // Chat: %s | Player: %s | Location: %d %d + cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y); + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1115), // Users: %d/%d | Password: %s | Public: %s + cd->users, cd->limit, cd->pass, (cd->pub) ? msg_txt(1116) : msg_txt(1117)); // Yes / No + clif_displaymessage(fd, atcmd_output); + } + } + mapit_free(iter); + break; + default: // normally impossible to arrive here + clif_displaymessage(fd, msg_txt(1118)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>). + return -1; + break; + } + + return 0; } /*========================================== @@ -4002,58 +4147,58 @@ ACMD_FUNC(mapinfo) *------------------------------------------*/ ACMD_FUNC(mount_peco) { - nullpo_retr(-1, sd); - - if (sd->disguise) { - clif_displaymessage(fd, msg_txt(212)); // Cannot mount while in disguise. - return -1; - } - - if ((sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) { - if (!(sd->sc.option&OPTION_DRAGON1)) { - clif_displaymessage(sd->fd,msg_txt(1119)); // You have mounted your Dragon. - pc_setoption(sd, sd->sc.option|OPTION_DRAGON1); - } else { - clif_displaymessage(sd->fd,msg_txt(1120)); // You have released your Dragon. - pc_setoption(sd, sd->sc.option&~OPTION_DRAGON1); - } - return 0; - } - if ((sd->class_&MAPID_THIRDMASK) == MAPID_RANGER && pc_checkskill(sd,RA_WUGRIDER) > 0) { - if (!pc_isridingwug(sd)) { - clif_displaymessage(sd->fd,msg_txt(1121)); // You have mounted your Warg. - pc_setoption(sd, sd->sc.option|OPTION_WUGRIDER); - } else { - clif_displaymessage(sd->fd,msg_txt(1122)); // You have released your Warg. - pc_setoption(sd, sd->sc.option&~OPTION_WUGRIDER); - } - return 0; - } - if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC) { - if (!pc_ismadogear(sd)) { - clif_displaymessage(sd->fd,msg_txt(1123)); // You have mounted your Mado Gear. - pc_setoption(sd, sd->sc.option|OPTION_MADOGEAR); - } else { - clif_displaymessage(sd->fd,msg_txt(1124)); // You have released your Mado Gear. - pc_setoption(sd, sd->sc.option&~OPTION_MADOGEAR); - } - return 0; - } - if (!pc_isriding(sd)) { // if actually no peco - - if (!pc_checkskill(sd, KN_RIDING)) { - clif_displaymessage(fd, msg_txt(213)); // You can not mount a Peco Peco with your current job. - return -1; - } - - pc_setoption(sd, sd->sc.option | OPTION_RIDING); - clif_displaymessage(fd, msg_txt(102)); // You have mounted a Peco Peco. - } else {//Dismount - pc_setoption(sd, sd->sc.option & ~OPTION_RIDING); - clif_displaymessage(fd, msg_txt(214)); // You have released your Peco Peco. - } - - return 0; + nullpo_retr(-1, sd); + + if (sd->disguise) { + clif_displaymessage(fd, msg_txt(212)); // Cannot mount while in disguise. + return -1; + } + + if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT && pc_checkskill(sd,RK_DRAGONTRAINING) > 0 ) { + if( !(sd->sc.option&OPTION_DRAGON1) ) { + clif_displaymessage(sd->fd,msg_txt(1119)); // You have mounted your Dragon. + pc_setoption(sd, sd->sc.option|OPTION_DRAGON1); + } else { + clif_displaymessage(sd->fd,msg_txt(1120)); // You have released your Dragon. + pc_setoption(sd, sd->sc.option&~OPTION_DRAGON1); + } + return 0; + } + if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER && pc_checkskill(sd,RA_WUGRIDER) > 0 ) { + if( !pc_isridingwug(sd) ) { + clif_displaymessage(sd->fd,msg_txt(1121)); // You have mounted your Warg. + pc_setoption(sd, sd->sc.option|OPTION_WUGRIDER); + } else { + clif_displaymessage(sd->fd,msg_txt(1122)); // You have released your Warg. + pc_setoption(sd, sd->sc.option&~OPTION_WUGRIDER); + } + return 0; + } + if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) { + if( !pc_ismadogear(sd) ) { + clif_displaymessage(sd->fd,msg_txt(1123)); // You have mounted your Mado Gear. + pc_setoption(sd, sd->sc.option|OPTION_MADOGEAR); + } else { + clif_displaymessage(sd->fd,msg_txt(1124)); // You have released your Mado Gear. + pc_setoption(sd, sd->sc.option&~OPTION_MADOGEAR); + } + return 0; + } + if (!pc_isriding(sd)) { // if actually no peco + + if (!pc_checkskill(sd, KN_RIDING)) { + clif_displaymessage(fd, msg_txt(213)); // You can not mount a Peco Peco with your current job. + return -1; + } + + pc_setoption(sd, sd->sc.option | OPTION_RIDING); + clif_displaymessage(fd, msg_txt(102)); // You have mounted a Peco Peco. + } else {//Dismount + pc_setoption(sd, sd->sc.option & ~OPTION_RIDING); + clif_displaymessage(fd, msg_txt(214)); // You have released your Peco Peco. + } + + return 0; } /*========================================== @@ -4061,39 +4206,40 @@ ACMD_FUNC(mount_peco) *------------------------------------------*/ ACMD_FUNC(guildspy) { - char guild_name[NAME_LENGTH]; - struct guild *g; - nullpo_retr(-1, sd); - - memset(guild_name, '\0', sizeof(guild_name)); - memset(atcmd_output, '\0', sizeof(atcmd_output)); - - if (!enable_spy) { - clif_displaymessage(fd, msg_txt(1125)); // The mapserver has spy command support disabled. - return -1; - } - if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { - clif_displaymessage(fd, msg_txt(1126)); // Please enter a guild name/ID (usage: @guildspy <guild_name/ID>). - return -1; - } - - if ((g = guild_searchname(guild_name)) != NULL || // name first to avoid error when name begin with a number - (g = guild_search(atoi(message))) != NULL) { - if (sd->guildspy == g->guild_id) { - sd->guildspy = 0; - sprintf(atcmd_output, msg_txt(103), g->name); // No longer spying on the %s guild. - clif_displaymessage(fd, atcmd_output); - } else { - sd->guildspy = g->guild_id; - sprintf(atcmd_output, msg_txt(104), g->name); // Spying on the %s guild. - clif_displaymessage(fd, atcmd_output); - } - } else { - clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the specified guild is online. - return -1; - } - - return 0; + char guild_name[NAME_LENGTH]; + struct guild *g; + nullpo_retr(-1, sd); + + memset(guild_name, '\0', sizeof(guild_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); + + if (!enable_spy) + { + clif_displaymessage(fd, msg_txt(1125)); // The mapserver has spy command support disabled. + return -1; + } + if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { + clif_displaymessage(fd, msg_txt(1126)); // Please enter a guild name/ID (usage: @guildspy <guild_name/ID>). + return -1; + } + + if ((g = guild_searchname(guild_name)) != NULL || // name first to avoid error when name begin with a number + (g = guild_search(atoi(message))) != NULL) { + if (sd->guildspy == g->guild_id) { + sd->guildspy = 0; + sprintf(atcmd_output, msg_txt(103), g->name); // No longer spying on the %s guild. + clif_displaymessage(fd, atcmd_output); + } else { + sd->guildspy = g->guild_id; + sprintf(atcmd_output, msg_txt(104), g->name); // Spying on the %s guild. + clif_displaymessage(fd, atcmd_output); + } + } else { + clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the specified guild is online. + return -1; + } + + return 0; } /*========================================== @@ -4101,40 +4247,41 @@ ACMD_FUNC(guildspy) *------------------------------------------*/ ACMD_FUNC(partyspy) { - char party_name[NAME_LENGTH]; - struct party_data *p; - nullpo_retr(-1, sd); + char party_name[NAME_LENGTH]; + struct party_data *p; + nullpo_retr(-1, sd); - memset(party_name, '\0', sizeof(party_name)); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(party_name, '\0', sizeof(party_name)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!enable_spy) { - clif_displaymessage(fd, msg_txt(1125)); // The mapserver has spy command support disabled. - return -1; - } + if (!enable_spy) + { + clif_displaymessage(fd, msg_txt(1125)); // The mapserver has spy command support disabled. + return -1; + } - if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) { - clif_displaymessage(fd, msg_txt(1127)); // Please enter a party name/ID (usage: @partyspy <party_name/ID>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) { + clif_displaymessage(fd, msg_txt(1127)); // Please enter a party name/ID (usage: @partyspy <party_name/ID>). + return -1; + } - if ((p = party_searchname(party_name)) != NULL || // name first to avoid error when name begin with a number - (p = party_search(atoi(message))) != NULL) { - if (sd->partyspy == p->party.party_id) { - sd->partyspy = 0; - sprintf(atcmd_output, msg_txt(105), p->party.name); // No longer spying on the %s party. - clif_displaymessage(fd, atcmd_output); - } else { - sd->partyspy = p->party.party_id; - sprintf(atcmd_output, msg_txt(106), p->party.name); // Spying on the %s party. - clif_displaymessage(fd, atcmd_output); - } - } else { - clif_displaymessage(fd, msg_txt(96)); // Incorrect name/ID, or no one from the specified party is online. - return -1; - } + if ((p = party_searchname(party_name)) != NULL || // name first to avoid error when name begin with a number + (p = party_search(atoi(message))) != NULL) { + if (sd->partyspy == p->party.party_id) { + sd->partyspy = 0; + sprintf(atcmd_output, msg_txt(105), p->party.name); // No longer spying on the %s party. + clif_displaymessage(fd, atcmd_output); + } else { + sd->partyspy = p->party.party_id; + sprintf(atcmd_output, msg_txt(106), p->party.name); // Spying on the %s party. + clif_displaymessage(fd, atcmd_output); + } + } else { + clif_displaymessage(fd, msg_txt(96)); // Incorrect name/ID, or no one from the specified party is online. + return -1; + } - return 0; + return 0; } /*========================================== @@ -4142,28 +4289,28 @@ ACMD_FUNC(partyspy) *------------------------------------------*/ ACMD_FUNC(repairall) { - int count, i; - nullpo_retr(-1, sd); + int count, i; + nullpo_retr(-1, sd); - count = 0; - for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid && sd->status.inventory[i].attribute == 1) { - sd->status.inventory[i].attribute = 0; - clif_produceeffect(sd, 0, sd->status.inventory[i].nameid); - count++; - } - } + count = 0; + for (i = 0; i < MAX_INVENTORY; i++) { + if (sd->status.inventory[i].nameid && sd->status.inventory[i].attribute == 1) { + sd->status.inventory[i].attribute = 0; + clif_produceeffect(sd, 0, sd->status.inventory[i].nameid); + count++; + } + } - if (count > 0) { - clif_misceffect(&sd->bl, 3); - clif_equiplist(sd); - clif_displaymessage(fd, msg_txt(107)); // All items have been repaired. - } else { - clif_displaymessage(fd, msg_txt(108)); // No item need to be repaired. - return -1; - } + if (count > 0) { + clif_misceffect(&sd->bl, 3); + clif_equiplist(sd); + clif_displaymessage(fd, msg_txt(107)); // All items have been repaired. + } else { + clif_displaymessage(fd, msg_txt(108)); // No item need to be repaired. + return -1; + } - return 0; + return 0; } /*========================================== @@ -4171,30 +4318,30 @@ ACMD_FUNC(repairall) *------------------------------------------*/ ACMD_FUNC(nuke) { - struct map_session_data *pl_sd; - nullpo_retr(-1, sd); + struct map_session_data *pl_sd; + nullpo_retr(-1, sd); - memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1128)); // Please enter a player name (usage: @nuke <char name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, msg_txt(1128)); // Please enter a player name (usage: @nuke <char name>). + return -1; + } - if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { - if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kill only lower or same GM level - skill_castend_nodamage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, gettick(), 0); - clif_displaymessage(fd, msg_txt(109)); // Player has been nuked! - } else { - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; - } - } else { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { + if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kill only lower or same GM level + skill_castend_nodamage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, gettick(), 0); + clif_displaymessage(fd, msg_txt(109)); // Player has been nuked! + } else { + clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return -1; + } + } else { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - return 0; + return 0; } /*========================================== @@ -4202,29 +4349,29 @@ ACMD_FUNC(nuke) *------------------------------------------*/ ACMD_FUNC(tonpc) { - char npcname[NAME_LENGTH+1]; - struct npc_data *nd; + char npcname[NAME_LENGTH+1]; + struct npc_data *nd; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - memset(npcname, 0, sizeof(npcname)); + memset(npcname, 0, sizeof(npcname)); - if (!message || !*message || sscanf(message, "%23[^\n]", npcname) < 1) { - clif_displaymessage(fd, msg_txt(1129)); // Please enter a NPC name (usage: @tonpc <NPC_name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", npcname) < 1) { + clif_displaymessage(fd, msg_txt(1129)); // Please enter a NPC name (usage: @tonpc <NPC_name>). + return -1; + } - if ((nd = npc_name2id(npcname)) != NULL) { - if (pc_setpos(sd, map_id2index(nd->bl.m), nd->bl.x, nd->bl.y, CLR_TELEPORT) == 0) - clif_displaymessage(fd, msg_txt(0)); // Warped. - else - return -1; - } else { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. - return -1; - } + if ((nd = npc_name2id(npcname)) != NULL) { + if (pc_setpos(sd, map_id2index(nd->bl.m), nd->bl.x, nd->bl.y, CLR_TELEPORT) == 0) + clif_displaymessage(fd, msg_txt(0)); // Warped. + else + return -1; + } else { + clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. + return -1; + } - return 0; + return 0; } /*========================================== @@ -4232,25 +4379,25 @@ ACMD_FUNC(tonpc) *------------------------------------------*/ ACMD_FUNC(shownpc) { - char NPCname[NAME_LENGTH+1]; - nullpo_retr(-1, sd); + char NPCname[NAME_LENGTH+1]; + nullpo_retr(-1, sd); - memset(NPCname, '\0', sizeof(NPCname)); + memset(NPCname, '\0', sizeof(NPCname)); - if (!message || !*message || sscanf(message, "%23[^\n]", NPCname) < 1) { - clif_displaymessage(fd, msg_txt(1130)); // Please enter a NPC name (usage: @enablenpc <NPC_name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", NPCname) < 1) { + clif_displaymessage(fd, msg_txt(1130)); // Please enter a NPC name (usage: @enablenpc <NPC_name>). + return -1; + } - if (npc_name2id(NPCname) != NULL) { - npc_enable(NPCname, 1); - clif_displaymessage(fd, msg_txt(110)); // Npc Enabled. - } else { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. - return -1; - } + if (npc_name2id(NPCname) != NULL) { + npc_enable(NPCname, 1); + clif_displaymessage(fd, msg_txt(110)); // Npc Enabled. + } else { + clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. + return -1; + } - return 0; + return 0; } /*========================================== @@ -4258,114 +4405,114 @@ ACMD_FUNC(shownpc) *------------------------------------------*/ ACMD_FUNC(hidenpc) { - char NPCname[NAME_LENGTH+1]; - nullpo_retr(-1, sd); + char NPCname[NAME_LENGTH+1]; + nullpo_retr(-1, sd); - memset(NPCname, '\0', sizeof(NPCname)); + memset(NPCname, '\0', sizeof(NPCname)); - if (!message || !*message || sscanf(message, "%23[^\n]", NPCname) < 1) { - clif_displaymessage(fd, msg_txt(1131)); // Please enter a NPC name (usage: @hidenpc <NPC_name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", NPCname) < 1) { + clif_displaymessage(fd, msg_txt(1131)); // Please enter a NPC name (usage: @hidenpc <NPC_name>). + return -1; + } - if (npc_name2id(NPCname) == NULL) { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. - return -1; - } + if (npc_name2id(NPCname) == NULL) { + clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. + return -1; + } - npc_enable(NPCname, 0); - clif_displaymessage(fd, msg_txt(112)); // Npc Disabled. - return 0; + npc_enable(NPCname, 0); + clif_displaymessage(fd, msg_txt(112)); // Npc Disabled. + return 0; } ACMD_FUNC(loadnpc) { - FILE *fp; + FILE *fp; - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1132)); // Please enter a script file name (usage: @loadnpc <file name>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1132)); // Please enter a script file name (usage: @loadnpc <file name>). + return -1; + } - // check if script file exists - if ((fp = fopen(message, "r")) == NULL) { - clif_displaymessage(fd, msg_txt(261)); - return -1; - } - fclose(fp); + // check if script file exists + if ((fp = fopen(message, "r")) == NULL) { + clif_displaymessage(fd, msg_txt(261)); + return -1; + } + fclose(fp); - // add to list of script sources and run it - npc_addsrcfile(message); - npc_parsesrcfile(message,true); - npc_read_event_script(); + // add to list of script sources and run it + npc_addsrcfile(message); + npc_parsesrcfile(message,true); + npc_read_event_script(); - clif_displaymessage(fd, msg_txt(262)); + clif_displaymessage(fd, msg_txt(262)); - return 0; + return 0; } ACMD_FUNC(unloadnpc) { - struct npc_data *nd; - char NPCname[NAME_LENGTH+1]; - nullpo_retr(-1, sd); + struct npc_data *nd; + char NPCname[NAME_LENGTH+1]; + nullpo_retr(-1, sd); - memset(NPCname, '\0', sizeof(NPCname)); + memset(NPCname, '\0', sizeof(NPCname)); - if (!message || !*message || sscanf(message, "%24[^\n]", NPCname) < 1) { - clif_displaymessage(fd, msg_txt(1133)); // Please enter a NPC name (usage: @npcoff <NPC_name>). - return -1; - } + if (!message || !*message || sscanf(message, "%24[^\n]", NPCname) < 1) { + clif_displaymessage(fd, msg_txt(1133)); // Please enter a NPC name (usage: @npcoff <NPC_name>). + return -1; + } - if ((nd = npc_name2id(NPCname)) == NULL) { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. - return -1; - } + if ((nd = npc_name2id(NPCname)) == NULL) { + clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. + return -1; + } - npc_unload_duplicates(nd); - npc_unload(nd,true); - npc_read_event_script(); - clif_displaymessage(fd, msg_txt(112)); // Npc Disabled. - return 0; + npc_unload_duplicates(nd); + npc_unload(nd,true); + npc_read_event_script(); + clif_displaymessage(fd, msg_txt(112)); // Npc Disabled. + return 0; } /*========================================== * time in txt for time command (by [Yor]) *------------------------------------------*/ -char *txt_time(unsigned int duration) +char* txt_time(unsigned int duration) { - int days, hours, minutes, seconds; - char temp[CHAT_SIZE_MAX]; - static char temp1[CHAT_SIZE_MAX]; + int days, hours, minutes, seconds; + char temp[CHAT_SIZE_MAX]; + static char temp1[CHAT_SIZE_MAX]; - memset(temp, '\0', sizeof(temp)); - memset(temp1, '\0', sizeof(temp1)); + memset(temp, '\0', sizeof(temp)); + memset(temp1, '\0', sizeof(temp1)); - days = duration / (60 * 60 * 24); - duration = duration - (60 * 60 * 24 * days); - hours = duration / (60 * 60); - duration = duration - (60 * 60 * hours); - minutes = duration / 60; - seconds = duration - (60 * minutes); + days = duration / (60 * 60 * 24); + duration = duration - (60 * 60 * 24 * days); + hours = duration / (60 * 60); + duration = duration - (60 * 60 * hours); + minutes = duration / 60; + seconds = duration - (60 * minutes); - if (days == 1) - sprintf(temp, msg_txt(219), days); // %d day - else if (days > 1) - sprintf(temp, msg_txt(220), days); // %d days - if (hours == 1) - sprintf(temp1, msg_txt(221), temp, hours); // %s %d hour - else if (hours > 1) - sprintf(temp1, msg_txt(222), temp, hours); // %s %d hours - if (minutes < 2) - sprintf(temp, msg_txt(223), temp1, minutes); // %s %d minute - else - sprintf(temp, msg_txt(224), temp1, minutes); // %s %d minutes - if (seconds == 1) - sprintf(temp1, msg_txt(225), temp, seconds); // %s and %d second - else if (seconds > 1) - sprintf(temp1, msg_txt(226), temp, seconds); // %s and %d seconds + if (days == 1) + sprintf(temp, msg_txt(219), days); // %d day + else if (days > 1) + sprintf(temp, msg_txt(220), days); // %d days + if (hours == 1) + sprintf(temp1, msg_txt(221), temp, hours); // %s %d hour + else if (hours > 1) + sprintf(temp1, msg_txt(222), temp, hours); // %s %d hours + if (minutes < 2) + sprintf(temp, msg_txt(223), temp1, minutes); // %s %d minute + else + sprintf(temp, msg_txt(224), temp1, minutes); // %s %d minutes + if (seconds == 1) + sprintf(temp1, msg_txt(225), temp, seconds); // %s and %d second + else if (seconds > 1) + sprintf(temp1, msg_txt(226), temp, seconds); // %s and %d seconds - return temp1; + return temp1; } /*========================================== @@ -4374,99 +4521,99 @@ char *txt_time(unsigned int duration) *------------------------------------------*/ ACMD_FUNC(servertime) { - const struct TimerData *timer_data; - const struct TimerData *timer_data2; - 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[CHAT_SIZE_MAX]; - nullpo_retr(-1, sd); - - memset(temp, '\0', sizeof(temp)); - - time(&time_server); // get time in seconds since 1/1/1970 - datetime = localtime(&time_server); // convert seconds in structure - // like sprintf, but only for date/time (Sunday, November 02 2003 15:12:52) - strftime(temp, sizeof(temp)-1, msg_txt(230), datetime); // Server time (normal time): %A, %B %d %Y %X. - clif_displaymessage(fd, temp); - - if (battle_config.night_duration == 0 && battle_config.day_duration == 0) { - if (night_flag == 0) - clif_displaymessage(fd, msg_txt(231)); // Game time: The game is in permanent daylight. - else - clif_displaymessage(fd, msg_txt(232)); // Game time: The game is in permanent night. - } else if (battle_config.night_duration == 0) - if (night_flag == 1) { // we start with night - timer_data = get_timer(day_timer_tid); - sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in night for %s. - clif_displaymessage(fd, temp); - clif_displaymessage(fd, msg_txt(234)); // Game time: After, the game will be in permanent daylight. - } else - clif_displaymessage(fd, msg_txt(231)); // Game time: The game is in permanent daylight. - else if (battle_config.day_duration == 0) - if (night_flag == 0) { // we start with day - timer_data = get_timer(night_timer_tid); - sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in daylight for %s. - clif_displaymessage(fd, temp); - clif_displaymessage(fd, msg_txt(236)); // Game time: After, the game will be in permanent night. - } else - clif_displaymessage(fd, msg_txt(232)); // Game time: The game is in permanent night. - else { - if (night_flag == 0) { - timer_data = get_timer(night_timer_tid); - timer_data2 = get_timer(day_timer_tid); - sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in daylight for %s. - clif_displaymessage(fd, temp); - if (DIFF_TICK(timer_data->tick, timer_data2->tick) > 0) - sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data->interval,DIFF_TICK(timer_data->tick,timer_data2->tick)) / 1000)); // Game time: After, the game will be in night for %s. - else - sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000)); // Game time: After, the game will be in night for %s. - clif_displaymessage(fd, temp); - sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s. - clif_displaymessage(fd, temp); - } else { - timer_data = get_timer(day_timer_tid); - timer_data2 = get_timer(night_timer_tid); - sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,gettick()) / 1000)); // Game time: The game is actualy in night for %s. - clif_displaymessage(fd, temp); - if (DIFF_TICK(timer_data->tick,timer_data2->tick) > 0) - sprintf(temp, msg_txt(239), txt_time((timer_data->interval - DIFF_TICK(timer_data->tick, timer_data2->tick)) / 1000)); // Game time: After, the game will be in daylight for %s. - else - sprintf(temp, msg_txt(239), txt_time(DIFF_TICK(timer_data2->tick, timer_data->tick) / 1000)); // Game time: After, the game will be in daylight for %s. - clif_displaymessage(fd, temp); - sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s. - clif_displaymessage(fd, temp); - } - } - - return 0; + const struct TimerData * timer_data; + const struct TimerData * timer_data2; + 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[CHAT_SIZE_MAX]; + nullpo_retr(-1, sd); + + memset(temp, '\0', sizeof(temp)); + + time(&time_server); // get time in seconds since 1/1/1970 + datetime = localtime(&time_server); // convert seconds in structure + // like sprintf, but only for date/time (Sunday, November 02 2003 15:12:52) + strftime(temp, sizeof(temp)-1, msg_txt(230), datetime); // Server time (normal time): %A, %B %d %Y %X. + clif_displaymessage(fd, temp); + + if (battle_config.night_duration == 0 && battle_config.day_duration == 0) { + if (night_flag == 0) + clif_displaymessage(fd, msg_txt(231)); // Game time: The game is in permanent daylight. + else + clif_displaymessage(fd, msg_txt(232)); // Game time: The game is in permanent night. + } else if (battle_config.night_duration == 0) + if (night_flag == 1) { // we start with night + timer_data = get_timer(day_timer_tid); + sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in night for %s. + clif_displaymessage(fd, temp); + clif_displaymessage(fd, msg_txt(234)); // Game time: After, the game will be in permanent daylight. + } else + clif_displaymessage(fd, msg_txt(231)); // Game time: The game is in permanent daylight. + else if (battle_config.day_duration == 0) + if (night_flag == 0) { // we start with day + timer_data = get_timer(night_timer_tid); + sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in daylight for %s. + clif_displaymessage(fd, temp); + clif_displaymessage(fd, msg_txt(236)); // Game time: After, the game will be in permanent night. + } else + clif_displaymessage(fd, msg_txt(232)); // Game time: The game is in permanent night. + else { + if (night_flag == 0) { + timer_data = get_timer(night_timer_tid); + timer_data2 = get_timer(day_timer_tid); + sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in daylight for %s. + clif_displaymessage(fd, temp); + if (DIFF_TICK(timer_data->tick, timer_data2->tick) > 0) + sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data->interval,DIFF_TICK(timer_data->tick,timer_data2->tick)) / 1000)); // Game time: After, the game will be in night for %s. + else + sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000)); // Game time: After, the game will be in night for %s. + clif_displaymessage(fd, temp); + sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s. + clif_displaymessage(fd, temp); + } else { + timer_data = get_timer(day_timer_tid); + timer_data2 = get_timer(night_timer_tid); + sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,gettick()) / 1000)); // Game time: The game is actualy in night for %s. + clif_displaymessage(fd, temp); + if (DIFF_TICK(timer_data->tick,timer_data2->tick) > 0) + sprintf(temp, msg_txt(239), txt_time((timer_data->interval - DIFF_TICK(timer_data->tick, timer_data2->tick)) / 1000)); // Game time: After, the game will be in daylight for %s. + else + sprintf(temp, msg_txt(239), txt_time(DIFF_TICK(timer_data2->tick, timer_data->tick) / 1000)); // Game time: After, the game will be in daylight for %s. + clif_displaymessage(fd, temp); + sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s. + clif_displaymessage(fd, temp); + } + } + + return 0; } //Added by Coltaro //We're using this function here instead of using time_t so that it only counts player's jail time when he/she's online (and since the idea is to reduce the amount of minutes one by one in status_change_timer...). //Well, using time_t could still work but for some reason that looks like more coding x_x -static void get_jail_time(int jailtime, int *year, int *month, int *day, int *hour, int *minute) +static void get_jail_time(int jailtime, int* year, int* month, int* day, int* hour, int* minute) { - const int factor_year = 518400; //12*30*24*60 = 518400 - const int factor_month = 43200; //30*24*60 = 43200 - const int factor_day = 1440; //24*60 = 1440 - const int factor_hour = 60; + const int factor_year = 518400; //12*30*24*60 = 518400 + const int factor_month = 43200; //30*24*60 = 43200 + const int factor_day = 1440; //24*60 = 1440 + const int factor_hour = 60; - *year = jailtime/factor_year; - jailtime -= *year*factor_year; - *month = jailtime/factor_month; - jailtime -= *month*factor_month; - *day = jailtime/factor_day; - jailtime -= *day*factor_day; - *hour = jailtime/factor_hour; - jailtime -= *hour*factor_hour; - *minute = jailtime; + *year = jailtime/factor_year; + jailtime -= *year*factor_year; + *month = jailtime/factor_month; + jailtime -= *month*factor_month; + *day = jailtime/factor_day; + jailtime -= *day*factor_day; + *hour = jailtime/factor_hour; + jailtime -= *hour*factor_hour; + *minute = jailtime; - *year = *year > 0? *year : 0; - *month = *month > 0? *month : 0; - *day = *day > 0? *day : 0; - *hour = *hour > 0? *hour : 0; - *minute = *minute > 0? *minute : 0; - return; + *year = *year > 0? *year : 0; + *month = *month > 0? *month : 0; + *day = *day > 0? *day : 0; + *hour = *hour > 0? *hour : 0; + *minute = *minute > 0? *minute : 0; + return; } /*========================================== @@ -4475,52 +4622,53 @@ static void get_jail_time(int jailtime, int *year, int *month, int *day, int *ho *------------------------------------------*/ ACMD_FUNC(jail) { - struct map_session_data *pl_sd; - int x, y; - unsigned short m_index; - nullpo_retr(-1, sd); - - memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1134)); // Please enter a player name (usage: @jail <char_name>). - return -1; - } - - if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } - - if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { - // you can jail only lower or same GM - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; - } - - if (pl_sd->sc.data[SC_JAILED]) { - clif_displaymessage(fd, msg_txt(118)); // Player warped in jails. - return -1; - } - - switch (rnd() % 2) { //Jail Locations - case 0: - m_index = mapindex_name2id(MAP_JAIL); - x = 24; - y = 75; - break; - default: - m_index = mapindex_name2id(MAP_JAIL); - x = 49; - y = 75; - break; - } - - //Duration of INT_MAX to specify infinity. - sc_start4(&pl_sd->bl,SC_JAILED,100,INT_MAX,m_index,x,y,1000); - clif_displaymessage(pl_sd->fd, msg_txt(117)); // GM has send you in jails. - clif_displaymessage(fd, msg_txt(118)); // Player warped in jails. - return 0; + struct map_session_data *pl_sd; + int x, y; + unsigned short m_index; + nullpo_retr(-1, sd); + + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, msg_txt(1134)); // Please enter a player name (usage: @jail <char_name>). + return -1; + } + + if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } + + if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) + { // you can jail only lower or same GM + clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return -1; + } + + if (pl_sd->sc.data[SC_JAILED]) + { + clif_displaymessage(fd, msg_txt(118)); // Player warped in jails. + return -1; + } + + switch(rnd() % 2) { //Jail Locations + case 0: + m_index = mapindex_name2id(MAP_JAIL); + x = 24; + y = 75; + break; + default: + m_index = mapindex_name2id(MAP_JAIL); + x = 49; + y = 75; + break; + } + + //Duration of INT_MAX to specify infinity. + sc_start4(&pl_sd->bl,SC_JAILED,100,INT_MAX,m_index,x,y,1000); + clif_displaymessage(pl_sd->fd, msg_txt(117)); // GM has send you in jails. + clif_displaymessage(fd, msg_txt(118)); // Player warped in jails. + return 0; } /*========================================== @@ -4529,180 +4677,180 @@ ACMD_FUNC(jail) *------------------------------------------*/ ACMD_FUNC(unjail) { - struct map_session_data *pl_sd; + struct map_session_data *pl_sd; - memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1135)); // Please enter a player name (usage: @unjail/@discharge <char_name>). - return -1; - } + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { + clif_displaymessage(fd, msg_txt(1135)); // Please enter a player name (usage: @unjail/@discharge <char_name>). + return -1; + } - if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can jail only lower or same GM + if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can jail only lower or same GM - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; - } + clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return -1; + } - if (!pl_sd->sc.data[SC_JAILED]) { - clif_displaymessage(fd, msg_txt(119)); // This player is not in jails. - return -1; - } + if (!pl_sd->sc.data[SC_JAILED]) + { + clif_displaymessage(fd, msg_txt(119)); // This player is not in jails. + return -1; + } - //Reset jail time to 1 sec. - sc_start(&pl_sd->bl,SC_JAILED,100,1,1000); - clif_displaymessage(pl_sd->fd, msg_txt(120)); // A GM has discharged you from jail. - clif_displaymessage(fd, msg_txt(121)); // Player unjailed. - return 0; + //Reset jail time to 1 sec. + sc_start(&pl_sd->bl,SC_JAILED,100,1,1000); + clif_displaymessage(pl_sd->fd, msg_txt(120)); // A GM has discharged you from jail. + clif_displaymessage(fd, msg_txt(121)); // Player unjailed. + return 0; } ACMD_FUNC(jailfor) { - struct map_session_data *pl_sd = NULL; - int year, month, day, hour, minute, value; - char *modif_p; - int jailtime = 0,x,y; - short m_index = 0; - nullpo_retr(-1, sd); - - if (!message || !*message || sscanf(message, "%s %23[^\n]",atcmd_output,atcmd_player_name) < 2) { - clif_displaymessage(fd, msg_txt(400)); //Usage: @jailfor <time> <character name> - return -1; - } - - atcmd_output[sizeof(atcmd_output)-1] = '\0'; - - modif_p = atcmd_output; - year = month = day = hour = minute = 0; - while (modif_p[0] != '\0') { - value = atoi(modif_p); - if (value == 0) - modif_p++; - else { - if (modif_p[0] == '-' || modif_p[0] == '+') - modif_p++; - while (modif_p[0] >= '0' && modif_p[0] <= '9') - modif_p++; - if (modif_p[0] == 'n') { - minute = value; - modif_p++; - } else if (modif_p[0] == 'm' && modif_p[1] == 'n') { - minute = value; - modif_p = modif_p + 2; - } else if (modif_p[0] == 'h') { - hour = value; - modif_p++; - } else if (modif_p[0] == 'd' || modif_p[0] == 'j') { - day = value; - modif_p++; - } else if (modif_p[0] == 'm') { - month = value; - modif_p++; - } else if (modif_p[0] == 'y' || modif_p[0] == 'a') { - year = value; - modif_p++; - } else if (modif_p[0] != '\0') { - modif_p++; - } - } - } - - if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0) { - clif_displaymessage(fd, msg_txt(1136)); // Invalid time for jail command. - return -1; - } - - if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } - - if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; - } - - jailtime = year*12*30*24*60 + month*30*24*60 + day*24*60 + hour*60 + minute; //In minutes - - if (jailtime==0) { - clif_displaymessage(fd, msg_txt(1136)); // Invalid time for jail command. - return -1; - } - - //Added by Coltaro - if (pl_sd->sc.data[SC_JAILED] && - pl_sd->sc.data[SC_JAILED]->val1 != INT_MAX) { - //Update the player's jail time - jailtime += pl_sd->sc.data[SC_JAILED]->val1; - if (jailtime <= 0) { - jailtime = 0; - clif_displaymessage(pl_sd->fd, msg_txt(120)); // GM has discharge you. - clif_displaymessage(fd, msg_txt(121)); // Player unjailed - } else { - get_jail_time(jailtime,&year,&month,&day,&hour,&minute); - sprintf(atcmd_output,msg_txt(402),msg_txt(1137),year,month,day,hour,minute); //%s in jail for %d years, %d months, %d days, %d hours and %d minutes - clif_displaymessage(pl_sd->fd, atcmd_output); - sprintf(atcmd_output,msg_txt(402),msg_txt(1138),year,month,day,hour,minute); //This player is now in jail for %d years, %d months, %d days, %d hours and %d minutes - clif_displaymessage(fd, atcmd_output); - } - } else if (jailtime < 0) { - clif_displaymessage(fd, msg_txt(1136)); - return -1; - } - - //Jail locations, add more as you wish. - switch (rnd()%2) { - case 1: //Jail #1 - m_index = mapindex_name2id(MAP_JAIL); - x = 49; - y = 75; - break; - default: //Default Jail - m_index = mapindex_name2id(MAP_JAIL); - x = 24; - y = 75; - break; - } - - sc_start4(&pl_sd->bl,SC_JAILED,100,jailtime,m_index,x,y,jailtime?60000:1000); //jailtime = 0: Time was reset to 0. Wait 1 second to warp player out (since it's done in status_change_timer). - return 0; + struct map_session_data *pl_sd = NULL; + int year, month, day, hour, minute, value; + char * modif_p; + int jailtime = 0,x,y; + short m_index = 0; + nullpo_retr(-1, sd); + + if (!message || !*message || sscanf(message, "%s %23[^\n]",atcmd_output,atcmd_player_name) < 2) { + clif_displaymessage(fd, msg_txt(400)); //Usage: @jailfor <time> <character name> + return -1; + } + + atcmd_output[sizeof(atcmd_output)-1] = '\0'; + + modif_p = atcmd_output; + year = month = day = hour = minute = 0; + while (modif_p[0] != '\0') { + value = atoi(modif_p); + if (value == 0) + modif_p++; + else { + if (modif_p[0] == '-' || modif_p[0] == '+') + modif_p++; + while (modif_p[0] >= '0' && modif_p[0] <= '9') + modif_p++; + if (modif_p[0] == 'n') { + minute = value; + modif_p++; + } else if (modif_p[0] == 'm' && modif_p[1] == 'n') { + minute = value; + modif_p = modif_p + 2; + } else if (modif_p[0] == 'h') { + hour = value; + modif_p++; + } else if (modif_p[0] == 'd' || modif_p[0] == 'j') { + day = value; + modif_p++; + } else if (modif_p[0] == 'm') { + month = value; + modif_p++; + } else if (modif_p[0] == 'y' || modif_p[0] == 'a') { + year = value; + modif_p++; + } else if (modif_p[0] != '\0') { + modif_p++; + } + } + } + + if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0) { + clif_displaymessage(fd, msg_txt(1136)); // Invalid time for jail command. + return -1; + } + + if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } + + if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { + clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return -1; + } + + jailtime = year*12*30*24*60 + month*30*24*60 + day*24*60 + hour*60 + minute; //In minutes + + if(jailtime==0) { + clif_displaymessage(fd, msg_txt(1136)); // Invalid time for jail command. + return -1; + } + + //Added by Coltaro + if(pl_sd->sc.data[SC_JAILED] && + pl_sd->sc.data[SC_JAILED]->val1 != INT_MAX) + { //Update the player's jail time + jailtime += pl_sd->sc.data[SC_JAILED]->val1; + if (jailtime <= 0) { + jailtime = 0; + clif_displaymessage(pl_sd->fd, msg_txt(120)); // GM has discharge you. + clif_displaymessage(fd, msg_txt(121)); // Player unjailed + } else { + get_jail_time(jailtime,&year,&month,&day,&hour,&minute); + sprintf(atcmd_output,msg_txt(402),msg_txt(1137),year,month,day,hour,minute); //%s in jail for %d years, %d months, %d days, %d hours and %d minutes + clif_displaymessage(pl_sd->fd, atcmd_output); + sprintf(atcmd_output,msg_txt(402),msg_txt(1138),year,month,day,hour,minute); //This player is now in jail for %d years, %d months, %d days, %d hours and %d minutes + clif_displaymessage(fd, atcmd_output); + } + } else if (jailtime < 0) { + clif_displaymessage(fd, msg_txt(1136)); + return -1; + } + + //Jail locations, add more as you wish. + switch(rnd()%2) + { + case 1: //Jail #1 + m_index = mapindex_name2id(MAP_JAIL); + x = 49; y = 75; + break; + default: //Default Jail + m_index = mapindex_name2id(MAP_JAIL); + x = 24; y = 75; + break; + } + + sc_start4(&pl_sd->bl,SC_JAILED,100,jailtime,m_index,x,y,jailtime?60000:1000); //jailtime = 0: Time was reset to 0. Wait 1 second to warp player out (since it's done in status_change_timer). + return 0; } //By Coltaro ACMD_FUNC(jailtime) { - int year, month, day, hour, minute; + int year, month, day, hour, minute; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!sd->sc.data[SC_JAILED]) { - clif_displaymessage(fd, msg_txt(1139)); // You are not in jail. - return -1; - } + if (!sd->sc.data[SC_JAILED]) { + clif_displaymessage(fd, msg_txt(1139)); // You are not in jail. + return -1; + } - if (sd->sc.data[SC_JAILED]->val1 == INT_MAX) { - clif_displaymessage(fd, msg_txt(1140)); // You have been jailed indefinitely. - return 0; - } + if (sd->sc.data[SC_JAILED]->val1 == INT_MAX) { + clif_displaymessage(fd, msg_txt(1140)); // You have been jailed indefinitely. + return 0; + } - if (sd->sc.data[SC_JAILED]->val1 <= 0) { // Was not jailed with @jailfor (maybe @jail? or warped there? or got recalled?) - clif_displaymessage(fd, msg_txt(1141)); // You have been jailed for an unknown amount of time. - return -1; - } + if (sd->sc.data[SC_JAILED]->val1 <= 0) { // Was not jailed with @jailfor (maybe @jail? or warped there? or got recalled?) + clif_displaymessage(fd, msg_txt(1141)); // You have been jailed for an unknown amount of time. + return -1; + } - //Get remaining jail time - get_jail_time(sd->sc.data[SC_JAILED]->val1,&year,&month,&day,&hour,&minute); - sprintf(atcmd_output,msg_txt(402),msg_txt(1142),year,month,day,hour,minute); // You will remain in jail for %d years, %d months, %d days, %d hours and %d minutes + //Get remaining jail time + get_jail_time(sd->sc.data[SC_JAILED]->val1,&year,&month,&day,&hour,&minute); + sprintf(atcmd_output,msg_txt(402),msg_txt(1142),year,month,day,hour,minute); // You will remain in jail for %d years, %d months, %d days, %d hours and %d minutes - clif_displaymessage(fd, atcmd_output); + clif_displaymessage(fd, atcmd_output); - return 0; + return 0; } /*========================================== @@ -4710,40 +4858,43 @@ ACMD_FUNC(jailtime) *------------------------------------------*/ ACMD_FUNC(disguise) { - int id = 0; - nullpo_retr(-1, sd); + int id = 0; + nullpo_retr(-1, sd); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1143)); // Please enter a Monster/NPC name/ID (usage: @disguise <name/ID>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1143)); // Please enter a Monster/NPC name/ID (usage: @disguise <name/ID>). + return -1; + } - if ((id = atoi(message)) > 0) { - //Acquired an ID - if (!mobdb_checkid(id) && !npcdb_checkid(id)) - id = 0; //Invalid id for either mobs or npcs. - } else { //Acquired a Name - if ((id = mobdb_searchname(message)) == 0) { - struct npc_data *nd = npc_name2id(message); - if (nd != NULL) - id = nd->class_; - } - } + if ((id = atoi(message)) > 0) + { //Acquired an ID + if (!mobdb_checkid(id) && !npcdb_checkid(id)) + id = 0; //Invalid id for either mobs or npcs. + } else { //Acquired a Name + if ((id = mobdb_searchname(message)) == 0) + { + struct npc_data* nd = npc_name2id(message); + if (nd != NULL) + id = nd->class_; + } + } - if (id == 0) { - clif_displaymessage(fd, msg_txt(123)); // Invalid Monster/NPC name/ID specified. - return -1; - } + if (id == 0) + { + clif_displaymessage(fd, msg_txt(123)); // Invalid Monster/NPC name/ID specified. + return -1; + } - if (pc_isriding(sd)) { - clif_displaymessage(fd, msg_txt(1144)); // Character cannot be disguised while mounted. - return -1; - } + if(pc_isriding(sd)) + { + clif_displaymessage(fd, msg_txt(1144)); // Character cannot be disguised while mounted. + return -1; + } - pc_disguise(sd, id); - clif_displaymessage(fd, msg_txt(122)); // Disguise applied. + pc_disguise(sd, id); + clif_displaymessage(fd, msg_txt(122)); // Disguise applied. - return 0; + return 0; } /*========================================== @@ -4751,31 +4902,31 @@ ACMD_FUNC(disguise) *------------------------------------------*/ ACMD_FUNC(disguiseall) { - int mob_id=0; - struct map_session_data *pl_sd; - struct s_mapiterator *iter; - nullpo_retr(-1, sd); + int mob_id=0; + struct map_session_data *pl_sd; + struct s_mapiterator* iter; + nullpo_retr(-1, sd); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1145)); // Please enter a Monster/NPC name/ID (usage: @disguiseall <name/ID>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1145)); // Please enter a Monster/NPC name/ID (usage: @disguiseall <name/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 = mobdb_searchname(message)) == 0) // check name first (to avoid possible name begining by a number) + mob_id = atoi(message); - if (!mobdb_checkid(mob_id) && !npcdb_checkid(mob_id)) { //if mob or npc... - clif_displaymessage(fd, msg_txt(123)); // Monster/NPC name/id not found. - return -1; - } + if (!mobdb_checkid(mob_id) && !npcdb_checkid(mob_id)) { //if mob or npc... + clif_displaymessage(fd, msg_txt(123)); // Monster/NPC name/id not found. + return -1; + } - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) - pc_disguise(pl_sd, mob_id); - mapit_free(iter); + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + pc_disguise(pl_sd, mob_id); + mapit_free(iter); - clif_displaymessage(fd, msg_txt(122)); // Disguise applied. - return 0; + clif_displaymessage(fd, msg_txt(122)); // Disguise applied. + return 0; } /*========================================== @@ -4783,46 +4934,46 @@ ACMD_FUNC(disguiseall) *------------------------------------------*/ ACMD_FUNC(disguiseguild) { - int id = 0, i; - char monster[NAME_LENGTH], guild[NAME_LENGTH]; - struct map_session_data *pl_sd; - struct guild *g; + int id = 0, i; + char monster[NAME_LENGTH], guild[NAME_LENGTH]; + struct map_session_data *pl_sd; + struct guild *g; - memset(monster, '\0', sizeof(monster)); - memset(guild, '\0', sizeof(guild)); + memset(monster, '\0', sizeof(monster)); + memset(guild, '\0', sizeof(guild)); - if (!message || !*message || sscanf(message, "%23[^,], %23[^\r\n]", monster, guild) < 2) { - clif_displaymessage(fd, msg_txt(1146)); // Please enter a mob name/ID and guild name/ID (usage: @disguiseguild <mob name/ID>, <guild name/ID>). - return -1; - } + if( !message || !*message || sscanf(message, "%23[^,], %23[^\r\n]", monster, guild) < 2 ) { + clif_displaymessage(fd, msg_txt(1146)); // Please enter a mob name/ID and guild name/ID (usage: @disguiseguild <mob name/ID>, <guild name/ID>). + return -1; + } - if ((id = atoi(monster)) > 0) { - if (!mobdb_checkid(id) && !npcdb_checkid(id)) - id = 0; - } else { - if ((id = mobdb_searchname(monster)) == 0) { - struct npc_data *nd = npc_name2id(monster); - if (nd != NULL) - id = nd->class_; - } - } + if( (id = atoi(monster)) > 0 ) { + if( !mobdb_checkid(id) && !npcdb_checkid(id) ) + id = 0; + } else { + if( (id = mobdb_searchname(monster)) == 0 ) { + struct npc_data* nd = npc_name2id(monster); + if( nd != NULL ) + id = nd->class_; + } + } - if (id == 0) { - clif_displaymessage(fd, msg_txt(123)); // Monster/NPC name/id hasn't been found. - return -1; - } + if( id == 0 ) { + clif_displaymessage(fd, msg_txt(123)); // Monster/NPC name/id hasn't been found. + return -1; + } - if ((g = guild_searchname(guild)) == NULL && (g = guild_search(atoi(guild))) == NULL) { - clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. - return -1; - } + if( (g = guild_searchname(guild)) == NULL && (g = guild_search(atoi(guild))) == NULL ) { + clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. + return -1; + } - for (i = 0; i < g->max_member; i++) - if ((pl_sd = g->member[i].sd) && !pc_isriding(pl_sd)) - pc_disguise(pl_sd, id); + for( i = 0; i < g->max_member; i++ ) + if( (pl_sd = g->member[i].sd) && !pc_isriding(pl_sd) ) + pc_disguise(pl_sd, id); - clif_displaymessage(fd, msg_txt(122)); // Disguise applied. - return 0; + clif_displaymessage(fd, msg_txt(122)); // Disguise applied. + return 0; } @@ -4831,16 +4982,16 @@ ACMD_FUNC(disguiseguild) *------------------------------------------*/ ACMD_FUNC(undisguise) { - nullpo_retr(-1, sd); - if (sd->disguise) { - pc_disguise(sd, 0); - clif_displaymessage(fd, msg_txt(124)); // Undisguise applied. - } else { - clif_displaymessage(fd, msg_txt(125)); // You're not disguised. - return -1; - } + nullpo_retr(-1, sd); + if (sd->disguise) { + pc_disguise(sd, 0); + clif_displaymessage(fd, msg_txt(124)); // Undisguise applied. + } else { + clif_displaymessage(fd, msg_txt(125)); // You're not disguised. + return -1; + } - return 0; + return 0; } /*========================================== @@ -4848,19 +4999,19 @@ ACMD_FUNC(undisguise) *------------------------------------------*/ ACMD_FUNC(undisguiseall) { - struct map_session_data *pl_sd; - struct s_mapiterator *iter; - nullpo_retr(-1, sd); + struct map_session_data *pl_sd; + struct s_mapiterator* iter; + nullpo_retr(-1, sd); - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) - if (pl_sd->disguise) - pc_disguise(pl_sd, 0); - mapit_free(iter); + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + if( pl_sd->disguise ) + pc_disguise(pl_sd, 0); + mapit_free(iter); - clif_displaymessage(fd, msg_txt(124)); // Undisguise applied. + clif_displaymessage(fd, msg_txt(124)); // Undisguise applied. - return 0; + return 0; } /*========================================== @@ -4868,31 +5019,31 @@ ACMD_FUNC(undisguiseall) *------------------------------------------*/ ACMD_FUNC(undisguiseguild) { - char guild_name[NAME_LENGTH]; - struct map_session_data *pl_sd; - struct guild *g; - int i; - nullpo_retr(-1, sd); + char guild_name[NAME_LENGTH]; + struct map_session_data *pl_sd; + struct guild *g; + int i; + nullpo_retr(-1, sd); - memset(guild_name, '\0', sizeof(guild_name)); + memset(guild_name, '\0', sizeof(guild_name)); - if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { - clif_displaymessage(fd, msg_txt(1147)); // Please enter guild name/ID (usage: @undisguiseguild <guild name/ID>). - return -1; - } + if(!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { + clif_displaymessage(fd, msg_txt(1147)); // Please enter guild name/ID (usage: @undisguiseguild <guild name/ID>). + return -1; + } - if ((g = guild_searchname(guild_name)) == NULL && (g = guild_search(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. - return -1; - } + if( (g = guild_searchname(guild_name)) == NULL && (g = guild_search(atoi(message))) == NULL ) { + clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. + return -1; + } - for (i = 0; i < g->max_member; i++) - if ((pl_sd = g->member[i].sd) && pl_sd->disguise) - pc_disguise(pl_sd, 0); + for(i = 0; i < g->max_member; i++) + if( (pl_sd = g->member[i].sd) && pl_sd->disguise ) + pc_disguise(pl_sd, 0); - clif_displaymessage(fd, msg_txt(124)); // Undisguise applied. + clif_displaymessage(fd, msg_txt(124)); // Undisguise applied. - return 0; + return 0; } /*========================================== @@ -4900,22 +5051,22 @@ ACMD_FUNC(undisguiseguild) *------------------------------------------*/ ACMD_FUNC(exp) { - char output[CHAT_SIZE_MAX]; - double nextb, nextj; - nullpo_retr(-1, sd); - memset(output, '\0', sizeof(output)); + char output[CHAT_SIZE_MAX]; + double nextb, nextj; + nullpo_retr(-1, sd); + memset(output, '\0', sizeof(output)); - nextb = pc_nextbaseexp(sd); - if (nextb) - nextb = sd->status.base_exp*100.0/nextb; + nextb = pc_nextbaseexp(sd); + if (nextb) + nextb = sd->status.base_exp*100.0/nextb; - nextj = pc_nextjobexp(sd); - if (nextj) - nextj = sd->status.job_exp*100.0/nextj; + nextj = pc_nextjobexp(sd); + if (nextj) + nextj = sd->status.job_exp*100.0/nextj; - sprintf(output, msg_txt(1148), sd->status.base_level, nextb, sd->status.job_level, nextj); // Base Level: %d (%.3f%%) | Job Level: %d (%.3f%%) - clif_displaymessage(fd, output); - return 0; + sprintf(output, msg_txt(1148), sd->status.base_level, nextb, sd->status.job_level, nextj); // Base Level: %d (%.3f%%) | Job Level: %d (%.3f%%) + clif_displaymessage(fd, output); + return 0; } @@ -4924,19 +5075,19 @@ ACMD_FUNC(exp) *------------------------------------------*/ ACMD_FUNC(broadcast) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1149)); // Please enter a message (usage: @broadcast <message>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1149)); // Please enter a message (usage: @broadcast <message>). + return -1; + } - sprintf(atcmd_output, "%s: %s", sd->status.name, message); - intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, 0); + sprintf(atcmd_output, "%s: %s", sd->status.name, message); + intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, 0); - return 0; + return 0; } /*========================================== @@ -4944,20 +5095,20 @@ ACMD_FUNC(broadcast) *------------------------------------------*/ ACMD_FUNC(localbroadcast) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1150)); // Please enter a message (usage: @localbroadcast <message>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1150)); // Please enter a message (usage: @localbroadcast <message>). + return -1; + } - sprintf(atcmd_output, "%s: %s", sd->status.name, message); + sprintf(atcmd_output, "%s: %s", sd->status.name, message); - clif_broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP); + clif_broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP); - return 0; + return 0; } /*========================================== @@ -4965,35 +5116,35 @@ ACMD_FUNC(localbroadcast) *------------------------------------------*/ ACMD_FUNC(email) { - char actual_email[100]; - char new_email[100]; - nullpo_retr(-1, sd); + 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)); + memset(actual_email, '\0', sizeof(actual_email)); + memset(new_email, '\0', sizeof(new_email)); - if (!message || !*message || sscanf(message, "%99s %99s", actual_email, new_email) < 2) { - clif_displaymessage(fd, msg_txt(1151)); // Please enter 2 emails (usage: @email <actual@email> <new@email>). - return -1; - } + if (!message || !*message || sscanf(message, "%99s %99s", actual_email, new_email) < 2) { + clif_displaymessage(fd, msg_txt(1151)); // Please enter 2 emails (usage: @email <actual@email> <new@email>). + return -1; + } - if (e_mail_check(actual_email) == 0) { - clif_displaymessage(fd, msg_txt(144)); // Invalid actual email. If you have default e-mail, give a@a.com. - return -1; - } else if (e_mail_check(new_email) == 0) { - clif_displaymessage(fd, msg_txt(145)); // Invalid new email. Please enter a real e-mail. - return -1; - } else if (strcmpi(new_email, "a@a.com") == 0) { - clif_displaymessage(fd, msg_txt(146)); // New email must be a real e-mail. - return -1; - } else if (strcmpi(actual_email, new_email) == 0) { - clif_displaymessage(fd, msg_txt(147)); // New email must be different of the actual e-mail. - return -1; - } + if (e_mail_check(actual_email) == 0) { + clif_displaymessage(fd, msg_txt(144)); // Invalid actual email. If you have default e-mail, give a@a.com. + return -1; + } else if (e_mail_check(new_email) == 0) { + clif_displaymessage(fd, msg_txt(145)); // Invalid new email. Please enter a real e-mail. + return -1; + } else if (strcmpi(new_email, "a@a.com") == 0) { + clif_displaymessage(fd, msg_txt(146)); // New email must be a real e-mail. + return -1; + } else if (strcmpi(actual_email, new_email) == 0) { + clif_displaymessage(fd, msg_txt(147)); // New email must be different of the actual e-mail. + return -1; + } - chrif_changeemail(sd->status.account_id, actual_email, new_email); - clif_displaymessage(fd, msg_txt(148)); // Information sended to login-server via char-server. - return 0; + chrif_changeemail(sd->status.account_id, actual_email, new_email); + clif_displaymessage(fd, msg_txt(148)); // Information sended to login-server via char-server. + return 0; } /*========================================== @@ -5001,17 +5152,17 @@ ACMD_FUNC(email) *------------------------------------------*/ ACMD_FUNC(effect) { - int type = 0, flag = 0; - nullpo_retr(-1, sd); + int type = 0, flag = 0; + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%d", &type) < 1) { - clif_displaymessage(fd, msg_txt(1152)); // Please enter an effect number (usage: @effect <effect number>). - return -1; - } + if (!message || !*message || sscanf(message, "%d", &type) < 1) { + clif_displaymessage(fd, msg_txt(1152)); // Please enter an effect number (usage: @effect <effect number>). + return -1; + } - clif_specialeffect(&sd->bl, type, (send_target)flag); - clif_displaymessage(fd, msg_txt(229)); // Your effect has changed. - return 0; + clif_specialeffect(&sd->bl, type, (send_target)flag); + clif_displaymessage(fd, msg_txt(229)); // Your effect has changed. + return 0; } /*========================================== @@ -5020,16 +5171,16 @@ ACMD_FUNC(effect) *------------------------------------------*/ ACMD_FUNC(killer) { - nullpo_retr(-1, sd); - sd->state.killer = !sd->state.killer; + nullpo_retr(-1, sd); + sd->state.killer = !sd->state.killer; - if (sd->state.killer) - clif_displaymessage(fd, msg_txt(241)); - else { - clif_displaymessage(fd, msg_txt(292)); - pc_stop_attack(sd); - } - return 0; + if(sd->state.killer) + clif_displaymessage(fd, msg_txt(241)); + else { + clif_displaymessage(fd, msg_txt(292)); + pc_stop_attack(sd); + } + return 0; } /*========================================== @@ -5038,16 +5189,16 @@ ACMD_FUNC(killer) *------------------------------------------*/ ACMD_FUNC(killable) { - nullpo_retr(-1, sd); - sd->state.killable = !sd->state.killable; + nullpo_retr(-1, sd); + sd->state.killable = !sd->state.killable; - if (sd->state.killable) - clif_displaymessage(fd, msg_txt(242)); - else { - clif_displaymessage(fd, msg_txt(288)); - map_foreachinrange(atcommand_stopattack,&sd->bl, AREA_SIZE, BL_CHAR, sd->bl.id); - } - return 0; + if(sd->state.killable) + clif_displaymessage(fd, msg_txt(242)); + else { + clif_displaymessage(fd, msg_txt(288)); + map_foreachinrange(atcommand_stopattack,&sd->bl, AREA_SIZE, BL_CHAR, sd->bl.id); + } + return 0; } /*========================================== @@ -5056,10 +5207,10 @@ ACMD_FUNC(killable) *------------------------------------------*/ ACMD_FUNC(skillon) { - nullpo_retr(-1, sd); - map[sd->bl.m].flag.noskill = 0; - clif_displaymessage(fd, msg_txt(244)); - return 0; + nullpo_retr(-1, sd); + map[sd->bl.m].flag.noskill = 0; + clif_displaymessage(fd, msg_txt(244)); + return 0; } /*========================================== @@ -5068,10 +5219,10 @@ ACMD_FUNC(skillon) *------------------------------------------*/ ACMD_FUNC(skilloff) { - nullpo_retr(-1, sd); - map[sd->bl.m].flag.noskill = 1; - clif_displaymessage(fd, msg_txt(243)); - return 0; + nullpo_retr(-1, sd); + map[sd->bl.m].flag.noskill = 1; + clif_displaymessage(fd, msg_txt(243)); + return 0; } /*========================================== @@ -5080,34 +5231,36 @@ ACMD_FUNC(skilloff) *------------------------------------------*/ ACMD_FUNC(npcmove) { - int x = 0, y = 0, m; - struct npc_data *nd = 0; - nullpo_retr(-1, sd); - memset(atcmd_player_name, '\0', sizeof atcmd_player_name); + int x = 0, y = 0, m; + struct npc_data *nd = 0; + nullpo_retr(-1, sd); + memset(atcmd_player_name, '\0', sizeof atcmd_player_name); - if (!message || !*message || sscanf(message, "%d %d %23[^\n]", &x, &y, atcmd_player_name) < 3) { - clif_displaymessage(fd, msg_txt(1153)); // Usage: @npcmove <X> <Y> <npc_name> - return -1; - } + if (!message || !*message || sscanf(message, "%d %d %23[^\n]", &x, &y, atcmd_player_name) < 3) { + clif_displaymessage(fd, msg_txt(1153)); // Usage: @npcmove <X> <Y> <npc_name> + return -1; + } - if ((nd = npc_name2id(atcmd_player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. - return -1; - } + if ((nd = npc_name2id(atcmd_player_name)) == NULL) + { + clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. + return -1; + } - if ((m=nd->bl.m) < 0 || nd->bl.prev == NULL) { - clif_displaymessage(fd, msg_txt(1154)); // NPC is not on this map. - return -1; //Not on a map. - } + if ((m=nd->bl.m) < 0 || nd->bl.prev == NULL) + { + clif_displaymessage(fd, msg_txt(1154)); // NPC is not on this map. + return -1; //Not on a map. + } - x = cap_value(x, 0, map[m].xs-1); - y = cap_value(y, 0, map[m].ys-1); - map_foreachinrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); - map_moveblock(&nd->bl, x, y, gettick()); - map_foreachinrange(clif_insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); - clif_displaymessage(fd, msg_txt(1155)); // NPC moved. + x = cap_value(x, 0, map[m].xs-1); + y = cap_value(y, 0, map[m].ys-1); + map_foreachinrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); + map_moveblock(&nd->bl, x, y, gettick()); + map_foreachinrange(clif_insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); + clif_displaymessage(fd, msg_txt(1155)); // NPC moved. - return 0; + return 0; } /*========================================== @@ -5116,33 +5269,34 @@ ACMD_FUNC(npcmove) *------------------------------------------*/ ACMD_FUNC(addwarp) { - char mapname[32], warpname[NAME_LENGTH+1]; - int x,y; - unsigned short m; - struct npc_data *nd; + char mapname[32], warpname[NAME_LENGTH+1]; + int x,y; + unsigned short m; + struct npc_data* nd; - nullpo_retr(-1, sd); - memset(warpname, '\0', sizeof(warpname)); + nullpo_retr(-1, sd); + memset(warpname, '\0', sizeof(warpname)); - if (!message || !*message || sscanf(message, "%31s %d %d %23[^\n]", mapname, &x, &y, warpname) < 4) { - clif_displaymessage(fd, msg_txt(1156)); // Usage: @addwarp <mapname> <X> <Y> <npc name> - return -1; - } + if (!message || !*message || sscanf(message, "%31s %d %d %23[^\n]", mapname, &x, &y, warpname) < 4) { + clif_displaymessage(fd, msg_txt(1156)); // Usage: @addwarp <mapname> <X> <Y> <npc name> + return -1; + } - m = mapindex_name2id(mapname); - if (m == 0) { - sprintf(atcmd_output, msg_txt(1157), mapname); // Unknown map '%s'. - clif_displaymessage(fd, atcmd_output); - return -1; - } + m = mapindex_name2id(mapname); + if( m == 0 ) + { + sprintf(atcmd_output, msg_txt(1157), mapname); // Unknown map '%s'. + clif_displaymessage(fd, atcmd_output); + return -1; + } - nd = npc_add_warp(warpname, sd->bl.m, sd->bl.x, sd->bl.y, 2, 2, m, x, y); - if (nd == NULL) - return -1; + nd = npc_add_warp(warpname, sd->bl.m, sd->bl.x, sd->bl.y, 2, 2, m, x, y); + if( nd == NULL ) + return -1; - sprintf(atcmd_output, msg_txt(1158), nd->exname); // New warp NPC '%s' created. - clif_displaymessage(fd, atcmd_output); - return 0; + sprintf(atcmd_output, msg_txt(1158), nd->exname); // New warp NPC '%s' created. + clif_displaymessage(fd, atcmd_output); + return 0; } /*========================================== @@ -5151,32 +5305,33 @@ ACMD_FUNC(addwarp) *------------------------------------------*/ ACMD_FUNC(follow) { - struct map_session_data *pl_sd = NULL; - nullpo_retr(-1, sd); + struct map_session_data *pl_sd = NULL; + nullpo_retr(-1, sd); - if (!message || !*message) { - if (sd->followtarget == -1) - return -1; + if (!message || !*message) { + if (sd->followtarget == -1) + return -1; - pc_stop_following(sd); - clif_displaymessage(fd, msg_txt(1159)); // Follow mode OFF. - return 0; - } + pc_stop_following (sd); + clif_displaymessage(fd, msg_txt(1159)); // Follow mode OFF. + return 0; + } - if ((pl_sd = map_nick2sd((char *)message)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + if ( (pl_sd = map_nick2sd((char *)message)) == NULL ) + { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - if (sd->followtarget == pl_sd->bl.id) { - pc_stop_following(sd); - clif_displaymessage(fd, msg_txt(1159)); // Follow mode OFF. - } else { - pc_follow(sd, pl_sd->bl.id); - clif_displaymessage(fd, msg_txt(1160)); // Follow mode ON. - } + if (sd->followtarget == pl_sd->bl.id) { + pc_stop_following (sd); + clif_displaymessage(fd, msg_txt(1159)); // Follow mode OFF. + } else { + pc_follow(sd, pl_sd->bl.id); + clif_displaymessage(fd, msg_txt(1160)); // Follow mode ON. + } - return 0; + return 0; } @@ -5186,16 +5341,16 @@ ACMD_FUNC(follow) *------------------------------------------*/ ACMD_FUNC(dropall) { - 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, 3); - pc_dropitem(sd, i, sd->status.inventory[i].amount); - } - } - return 0; + 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, 3); + pc_dropitem(sd, i, sd->status.inventory[i].amount); + } + } + return 0; } /*========================================== @@ -5204,28 +5359,28 @@ ACMD_FUNC(dropall) *------------------------------------------*/ ACMD_FUNC(storeall) { - int i; - nullpo_retr(-1, sd); + int i; + nullpo_retr(-1, sd); - if (sd->state.storage_flag != 1) { - //Open storage. - if (storage_storageopen(sd) == 1) { - clif_displaymessage(fd, msg_txt(1161)); // You currently cannot open your storage. - return -1; - } - } + if (sd->state.storage_flag != 1) + { //Open storage. + if( storage_storageopen(sd) == 1 ) { + clif_displaymessage(fd, msg_txt(1161)); // You currently cannot open your storage. + return -1; + } + } - for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].amount) { - if (sd->status.inventory[i].equip != 0) - pc_unequipitem(sd, i, 3); - storage_storageadd(sd, i, sd->status.inventory[i].amount); - } - } - storage_storageclose(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, 3); + storage_storageadd(sd, i, sd->status.inventory[i].amount); + } + } + storage_storageclose(sd); - clif_displaymessage(fd, msg_txt(1162)); // All items stored. - return 0; + clif_displaymessage(fd, msg_txt(1162)); // All items stored. + return 0; } /*========================================== @@ -5234,24 +5389,26 @@ ACMD_FUNC(storeall) *------------------------------------------*/ ACMD_FUNC(skillid) { - int skillen, idx; - nullpo_retr(-1, sd); + int skillen, idx; + nullpo_retr(-1, sd); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1163)); // Please enter a skill name to look up (usage: @skillid <skill name>). - return -1; - } + if (!message || !*message) + { + clif_displaymessage(fd, msg_txt(1163)); // Please enter a skill name to look up (usage: @skillid <skill name>). + return -1; + } - skillen = strlen(message); + skillen = strlen(message); - for (idx = 0; idx < MAX_SKILL_DB; idx++) { - if (strnicmp(skill_db[idx].name, message, skillen) == 0 || strnicmp(skill_db[idx].desc, message, skillen) == 0) { - sprintf(atcmd_output, msg_txt(1164), idx, skill_db[idx].desc); // skill %d: %s - clif_displaymessage(fd, atcmd_output); - } - } + for (idx = 0; idx < MAX_SKILL_DB; idx++) { + if (strnicmp(skill_db[idx].name, message, skillen) == 0 || strnicmp(skill_db[idx].desc, message, skillen) == 0) + { + sprintf(atcmd_output, msg_txt(1164), idx, skill_db[idx].desc); // skill %d: %s + clif_displaymessage(fd, atcmd_output); + } + } - return 0; + return 0; } /*========================================== @@ -5260,40 +5417,42 @@ ACMD_FUNC(skillid) *------------------------------------------*/ ACMD_FUNC(useskill) { - struct map_session_data *pl_sd = NULL; - struct block_list *bl; - int skillnum; - int skilllv; - char target[100]; - nullpo_retr(-1, sd); + struct map_session_data *pl_sd = NULL; + struct block_list *bl; + int skillnum; + int skilllv; + char target[100]; + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%d %d %23[^\n]", &skillnum, &skilllv, target) != 3) { - clif_displaymessage(fd, msg_txt(1165)); // Usage: @useskill <skill ID> <skill level> <target> - return -1; - } + if(!message || !*message || sscanf(message, "%d %d %23[^\n]", &skillnum, &skilllv, target) != 3) { + clif_displaymessage(fd, msg_txt(1165)); // Usage: @useskill <skill ID> <skill level> <target> + return -1; + } - if ((pl_sd = map_nick2sd(target)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + if ( (pl_sd = map_nick2sd(target)) == NULL ) + { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; - } + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) + { + clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return -1; + } - if (skillnum >= HM_SKILLBASE && skillnum < HM_SKILLBASE+MAX_HOMUNSKILL - && sd->hd && merc_is_hom_active(sd->hd)) // (If used with @useskill, put the homunc as dest) - bl = &sd->hd->bl; - else - bl = &sd->bl; + if (skillnum >= HM_SKILLBASE && skillnum < HM_SKILLBASE+MAX_HOMUNSKILL + && sd->hd && merc_is_hom_active(sd->hd)) // (If used with @useskill, put the homunc as dest) + bl = &sd->hd->bl; + else + bl = &sd->bl; - if (skill_get_inf(skillnum)&INF_GROUND_SKILL) - unit_skilluse_pos(bl, pl_sd->bl.x, pl_sd->bl.y, skillnum, skilllv); - else - unit_skilluse_id(bl, pl_sd->bl.id, skillnum, skilllv); + if (skill_get_inf(skillnum)&INF_GROUND_SKILL) + unit_skilluse_pos(bl, pl_sd->bl.x, pl_sd->bl.y, skillnum, skilllv); + else + unit_skilluse_id(bl, pl_sd->bl.id, skillnum, skilllv); - return 0; + return 0; } /*========================================== @@ -5303,22 +5462,23 @@ ACMD_FUNC(useskill) *------------------------------------------*/ ACMD_FUNC(displayskill) { - struct status_data *status; - unsigned int tick; - int skillnum; - int skilllv = 1; - nullpo_retr(-1, sd); + struct status_data * status; + unsigned int tick; + int skillnum; + int skilllv = 1; + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%d %d", &skillnum, &skilllv) < 1) { - clif_displaymessage(fd, msg_txt(1166)); // Usage: @displayskill <skill ID> {<skill level>} - return -1; - } - status = status_get_status_data(&sd->bl); - tick = gettick(); - clif_skill_damage(&sd->bl,&sd->bl, tick, status->amotion, status->dmotion, 1, 1, skillnum, skilllv, 5); - clif_skill_nodamage(&sd->bl, &sd->bl, skillnum, skilllv, 1); - clif_skill_poseffect(&sd->bl, skillnum, skilllv, sd->bl.x, sd->bl.y, tick); - return 0; + if (!message || !*message || sscanf(message, "%d %d", &skillnum, &skilllv) < 1) + { + clif_displaymessage(fd, msg_txt(1166)); // Usage: @displayskill <skill ID> {<skill level>} + return -1; + } + status = status_get_status_data(&sd->bl); + tick = gettick(); + clif_skill_damage(&sd->bl,&sd->bl, tick, status->amotion, status->dmotion, 1, 1, skillnum, skilllv, 5); + clif_skill_nodamage(&sd->bl, &sd->bl, skillnum, skilllv, 1); + clif_skill_poseffect(&sd->bl, skillnum, skilllv, sd->bl.x, sd->bl.y, tick); + return 0; } /*========================================== @@ -5327,70 +5487,74 @@ ACMD_FUNC(displayskill) *------------------------------------------*/ ACMD_FUNC(skilltree) { - struct map_session_data *pl_sd = NULL; - int skillnum; - int meets, j, c=0; - char target[NAME_LENGTH]; - struct skill_tree_entry *ent; - nullpo_retr(-1, sd); - - if (!message || !*message || sscanf(message, "%d %23[^\r\n]", &skillnum, target) != 2) { - clif_displaymessage(fd, msg_txt(1167)); // Usage: @skilltree <skill ID> <target> - return -1; - } - - if ((pl_sd = map_nick2sd(target)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } - - c = pc_calc_skilltree_normalize_job(pl_sd); - c = pc_mapid2jobid(c, pl_sd->status.sex); - - sprintf(atcmd_output, msg_txt(1168), job_name(c), pc_checkskill(pl_sd, NV_BASIC)); // Player is using %s skill tree (%d basic points). - clif_displaymessage(fd, atcmd_output); - - ARR_FIND(0, MAX_SKILL_TREE, j, skill_tree[c][j].id == 0 || skill_tree[c][j].id == skillnum); - if (j == MAX_SKILL_TREE || skill_tree[c][j].id == 0) { - clif_displaymessage(fd, msg_txt(1169)); // The player cannot use that skill. - return 0; - } - - ent = &skill_tree[c][j]; - - meets = 1; - for (j=0; j<MAX_PC_SKILL_REQUIRE; j++) { - if (ent->need[j].id && pc_checkskill(sd,ent->need[j].id) < ent->need[j].lv) { - sprintf(atcmd_output, msg_txt(1170), ent->need[j].lv, skill_db[ent->need[j].id].desc); // Player requires level %d of skill %s. - clif_displaymessage(fd, atcmd_output); - meets = 0; - } - } - if (meets == 1) { - clif_displaymessage(fd, msg_txt(1171)); // The player meets all the requirements for that skill. - } - - return 0; + struct map_session_data *pl_sd = NULL; + int skillnum; + int meets, j, c=0; + char target[NAME_LENGTH]; + struct skill_tree_entry *ent; + nullpo_retr(-1, sd); + + if(!message || !*message || sscanf(message, "%d %23[^\r\n]", &skillnum, target) != 2) { + clif_displaymessage(fd, msg_txt(1167)); // Usage: @skilltree <skill ID> <target> + return -1; + } + + if ( (pl_sd = map_nick2sd(target)) == NULL ) + { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } + + c = pc_calc_skilltree_normalize_job(pl_sd); + c = pc_mapid2jobid(c, pl_sd->status.sex); + + sprintf(atcmd_output, msg_txt(1168), job_name(c), pc_checkskill(pl_sd, NV_BASIC)); // Player is using %s skill tree (%d basic points). + clif_displaymessage(fd, atcmd_output); + + ARR_FIND( 0, MAX_SKILL_TREE, j, skill_tree[c][j].id == 0 || skill_tree[c][j].id == skillnum ); + if( j == MAX_SKILL_TREE || skill_tree[c][j].id == 0 ) + { + clif_displaymessage(fd, msg_txt(1169)); // The player cannot use that skill. + return 0; + } + + ent = &skill_tree[c][j]; + + meets = 1; + for(j=0;j<MAX_PC_SKILL_REQUIRE;j++) + { + if( ent->need[j].id && pc_checkskill(sd,ent->need[j].id) < ent->need[j].lv) + { + sprintf(atcmd_output, msg_txt(1170), ent->need[j].lv, skill_db[ent->need[j].id].desc); // Player requires level %d of skill %s. + clif_displaymessage(fd, atcmd_output); + meets = 0; + } + } + if (meets == 1) { + clif_displaymessage(fd, msg_txt(1171)); // The player meets all the requirements for that skill. + } + + return 0; } // Hand a ring with partners name on it to this char -void getring(struct map_session_data *sd) +void getring (struct map_session_data* sd) { - int flag, item_id; - struct item item_tmp; - item_id = (sd->status.sex) ? WEDDING_RING_M : WEDDING_RING_F; + int flag, item_id; + struct item item_tmp; + item_id = (sd->status.sex) ? WEDDING_RING_M : WEDDING_RING_F; - memset(&item_tmp, 0, sizeof(item_tmp)); - item_tmp.nameid = item_id; - item_tmp.identify = 1; - item_tmp.card[0] = 255; - item_tmp.card[2] = sd->status.partner_id; - item_tmp.card[3] = sd->status.partner_id >> 16; + memset(&item_tmp, 0, sizeof(item_tmp)); + item_tmp.nameid = item_id; + item_tmp.identify = 1; + item_tmp.card[0] = 255; + item_tmp.card[2] = sd->status.partner_id; + item_tmp.card[3] = sd->status.partner_id >> 16; - if ((flag = pc_additem(sd,&item_tmp,1,LOG_TYPE_COMMAND))) { - clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } + if((flag = pc_additem(sd,&item_tmp,1,LOG_TYPE_COMMAND))) { + clif_additem(sd,0,0,flag); + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } } /*========================================== @@ -5399,31 +5563,31 @@ void getring(struct map_session_data *sd) *------------------------------------------*/ ACMD_FUNC(marry) { - struct map_session_data *pl_sd = NULL; - char player_name[NAME_LENGTH] = ""; + struct map_session_data *pl_sd = NULL; + char player_name[NAME_LENGTH] = ""; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%23s", player_name) != 1) { - clif_displaymessage(fd, msg_txt(1172)); // Usage: @marry <char name> - return -1; - } + if (!message || !*message || sscanf(message, "%23s", player_name) != 1) { + clif_displaymessage(fd, msg_txt(1172)); // Usage: @marry <char name> + return -1; + } - if ((pl_sd = map_nick2sd(player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); - return -1; - } + if ((pl_sd = map_nick2sd(player_name)) == NULL) { + clif_displaymessage(fd, msg_txt(3)); + return -1; + } - if (pc_marriage(sd, pl_sd) == 0) { - clif_displaymessage(fd, msg_txt(1173)); // They are married... wish them well. - clif_wedding_effect(&pl_sd->bl); //wedding effect and music [Lupus] - getring(sd); // Auto-give named rings (Aru) - getring(pl_sd); - return 0; - } + if (pc_marriage(sd, pl_sd) == 0) { + clif_displaymessage(fd, msg_txt(1173)); // They are married... wish them well. + clif_wedding_effect(&pl_sd->bl); //wedding effect and music [Lupus] + getring(sd); // Auto-give named rings (Aru) + getring(pl_sd); + return 0; + } - clif_displaymessage(fd, msg_txt(1174)); // The two cannot wed because one is either a baby or already married. - return -1; + clif_displaymessage(fd, msg_txt(1174)); // The two cannot wed because one is either a baby or already married. + return -1; } /*========================================== @@ -5432,17 +5596,17 @@ ACMD_FUNC(marry) *------------------------------------------*/ ACMD_FUNC(divorce) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (pc_divorce(sd) != 0) { - sprintf(atcmd_output, msg_txt(1175), sd->status.name); // '%s' is not married. - clif_displaymessage(fd, atcmd_output); - return -1; - } + if (pc_divorce(sd) != 0) { + sprintf(atcmd_output, msg_txt(1175), sd->status.name); // '%s' is not married. + clif_displaymessage(fd, atcmd_output); + return -1; + } - sprintf(atcmd_output, msg_txt(1176), sd->status.name); // '%s' and his/her partner are now divorced. - clif_displaymessage(fd, atcmd_output); - return 0; + sprintf(atcmd_output, msg_txt(1176), sd->status.name); // '%s' and his/her partner are now divorced. + clif_displaymessage(fd, atcmd_output); + return 0; } /*========================================== @@ -5450,25 +5614,25 @@ ACMD_FUNC(divorce) *------------------------------------------*/ ACMD_FUNC(changelook) { - int i, j = 0, k = 0; - int pos[7] = { LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HEAD_BOTTOM,LOOK_WEAPON,LOOK_SHIELD,LOOK_SHOES,LOOK_ROBE }; + int i, j = 0, k = 0; + int pos[7] = { LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HEAD_BOTTOM,LOOK_WEAPON,LOOK_SHIELD,LOOK_SHOES,LOOK_ROBE }; - if ((i = sscanf(message, "%d %d", &j, &k)) < 1) { - clif_displaymessage(fd, msg_txt(1177)); // Usage: @changelook {<position>} <view id> - clif_displaymessage(fd, msg_txt(1178)); // Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield 6-Shoes 7-Robe - return -1; - } else if (i == 2) { - if (j < 1 || j > 7) - j = 1; - j = pos[j - 1]; - } else if (i == 1) { // position not defined, use HEAD_TOP as default - k = j; // swap - j = LOOK_HEAD_TOP; - } + if((i = sscanf(message, "%d %d", &j, &k)) < 1) { + clif_displaymessage(fd, msg_txt(1177)); // Usage: @changelook {<position>} <view id> + clif_displaymessage(fd, msg_txt(1178)); // Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield 6-Shoes 7-Robe + return -1; + } else if ( i == 2 ) { + if (j < 1 || j > 7) + j = 1; + 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); + clif_changelook(&sd->bl,j,k); - return 0; + return 0; } /*========================================== @@ -5477,31 +5641,32 @@ ACMD_FUNC(changelook) *------------------------------------------*/ ACMD_FUNC(autotrade) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (map[sd->bl.m].flag.autotrade != battle_config.autotrade_mapflag) { - clif_displaymessage(fd, msg_txt(1179)); // Autotrade is not allowed on this map. - return -1; - } + if( map[sd->bl.m].flag.autotrade != battle_config.autotrade_mapflag ) { + clif_displaymessage(fd, msg_txt(1179)); // Autotrade is not allowed on this map. + return -1; + } - if (pc_isdead(sd)) { - clif_displaymessage(fd, msg_txt(1180)); // You cannot autotrade when dead. - return -1; - } + if( pc_isdead(sd) ) { + clif_displaymessage(fd, msg_txt(1180)); // You cannot autotrade when dead. + return -1; + } - if (!sd->state.vending && !sd->state.buyingstore) { //check if player is vending or buying - clif_displaymessage(fd, msg_txt(549)); // "You should have a shop open to use @autotrade." - return -1; - } + if( !sd->state.vending && !sd->state.buyingstore ) { //check if player is vending or buying + clif_displaymessage(fd, msg_txt(549)); // "You should have a shop open to use @autotrade." + return -1; + } - sd->state.autotrade = 1; - if (battle_config.at_timeout) { - int timeout = atoi(message); - status_change_start(&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0); - } - clif_authfail_fd(fd, 15); + sd->state.autotrade = 1; + if( battle_config.at_timeout ) + { + int timeout = atoi(message); + status_change_start(&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0); + } + clif_authfail_fd(fd, 15); - return 0; + return 0; } /*========================================== @@ -5510,32 +5675,32 @@ ACMD_FUNC(autotrade) *------------------------------------------*/ ACMD_FUNC(changegm) { - struct guild *g; - struct map_session_data *pl_sd; - nullpo_retr(-1, sd); + struct guild *g; + struct map_session_data *pl_sd; + nullpo_retr(-1, sd); - if (sd->status.guild_id == 0 || (g = guild_search(sd->status.guild_id)) == NULL || strcmp(g->master,sd->status.name)) { - clif_displaymessage(fd, msg_txt(1181)); // You need to be a Guild Master to use this command. - return -1; - } + if (sd->status.guild_id == 0 || (g = guild_search(sd->status.guild_id)) == NULL || strcmp(g->master,sd->status.name)) { + clif_displaymessage(fd, msg_txt(1181)); // You need to be a Guild Master to use this command. + return -1; + } - if (map[sd->bl.m].flag.guildlock || map[sd->bl.m].flag.gvg_castle) { - clif_displaymessage(fd, msg_txt(1182)); // You cannot change guild leaders on this map. - return -1; - } + if( map[sd->bl.m].flag.guildlock || map[sd->bl.m].flag.gvg_castle ) { + clif_displaymessage(fd, msg_txt(1182)); // You cannot change guild leaders on this map. + return -1; + } - if (!message[0]) { - clif_displaymessage(fd, msg_txt(1183)); // Usage: @changegm <guild_member_name> - return -1; - } + if( !message[0] ) { + clif_displaymessage(fd, msg_txt(1183)); // Usage: @changegm <guild_member_name> + return -1; + } - if ((pl_sd=map_nick2sd((char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) { - clif_displaymessage(fd, msg_txt(1184)); // Target character must be online and be a guild member. - return -1; - } + if((pl_sd=map_nick2sd((char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) { + clif_displaymessage(fd, msg_txt(1184)); // Target character must be online and be a guild member. + return -1; + } - guild_gm_change(sd->status.guild_id, pl_sd); - return 0; + guild_gm_change(sd->status.guild_id, pl_sd); + return 0; } /*========================================== @@ -5544,16 +5709,17 @@ ACMD_FUNC(changegm) *------------------------------------------*/ ACMD_FUNC(changeleader) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!message[0]) { - clif_displaymessage(fd, msg_txt(1185)); // Usage: @changeleader <party_member_name> - return -1; - } + if( !message[0] ) + { + clif_displaymessage(fd, msg_txt(1185)); // Usage: @changeleader <party_member_name> + return -1; + } - if (party_changeleader(sd, map_nick2sd((char *) message))) - return 0; - return -1; + if (party_changeleader(sd, map_nick2sd((char *) message))) + return 0; + return -1; } /*========================================== @@ -5562,39 +5728,42 @@ ACMD_FUNC(changeleader) *------------------------------------------*/ ACMD_FUNC(partyoption) { - struct party_data *p; - int mi, option; - char w1[16], w2[16]; - nullpo_retr(-1, sd); + struct party_data *p; + int mi, option; + char w1[16], w2[16]; + nullpo_retr(-1, sd); - if (sd->status.party_id == 0 || (p = party_search(sd->status.party_id)) == NULL) { - clif_displaymessage(fd, msg_txt(282)); - return -1; - } + if (sd->status.party_id == 0 || (p = party_search(sd->status.party_id)) == NULL) + { + clif_displaymessage(fd, msg_txt(282)); + return -1; + } - ARR_FIND(0, MAX_PARTY, mi, p->data[mi].sd == sd); - if (mi == MAX_PARTY) - return -1; //Shouldn't happen + ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd ); + if (mi == MAX_PARTY) + return -1; //Shouldn't happen - if (!p->party.member[mi].leader) { - clif_displaymessage(fd, msg_txt(282)); - return -1; - } + if (!p->party.member[mi].leader) + { + clif_displaymessage(fd, msg_txt(282)); + return -1; + } - if (!message || !*message || sscanf(message, "%15s %15s", w1, w2) < 2) { - clif_displaymessage(fd, msg_txt(1186)); // Usage: @partyoption <pickup share: yes/no> <item distribution: yes/no> - return -1; - } + if(!message || !*message || sscanf(message, "%15s %15s", w1, w2) < 2) + { + clif_displaymessage(fd, msg_txt(1186)); // Usage: @partyoption <pickup share: yes/no> <item distribution: yes/no> + return -1; + } - option = (config_switch(w1)?1:0)|(config_switch(w2)?2:0); + option = (config_switch(w1)?1:0)|(config_switch(w2)?2:0); - //Change item share type. - if (option != p->party.item) - party_changeoption(sd, p->party.exp, option); - else - clif_displaymessage(fd, msg_txt(286)); + //Change item share type. + if (option != p->party.item) + party_changeoption(sd, p->party.exp, option); + else + clif_displaymessage(fd, msg_txt(286)); - return 0; + return 0; } /*========================================== @@ -5603,30 +5772,31 @@ ACMD_FUNC(partyoption) *------------------------------------------*/ ACMD_FUNC(autoloot) { - int rate; - double drate; - nullpo_retr(-1, sd); - // autoloot command without value - if (!message || !*message) { - if (sd->state.autoloot) - rate = 0; - else - rate = 10000; - } else { - drate = atof(message); - rate = (int)(drate*100); - } - if (rate < 0) rate = 0; - if (rate > 10000) rate = 10000; - - sd->state.autoloot = rate; - if (sd->state.autoloot) { - snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1187),((double)sd->state.autoloot)/100.); // Autolooting items with drop rates of %0.02f%% and below. - clif_displaymessage(fd, atcmd_output); - } else - clif_displaymessage(fd, msg_txt(1188)); // Autoloot is now off. - - return 0; + int rate; + double drate; + nullpo_retr(-1, sd); + // autoloot command without value + if(!message || !*message) + { + if (sd->state.autoloot) + rate = 0; + else + rate = 10000; + } else { + drate = atof(message); + rate = (int)(drate*100); + } + if (rate < 0) rate = 0; + if (rate > 10000) rate = 10000; + + sd->state.autoloot = rate; + if (sd->state.autoloot) { + snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1187),((double)sd->state.autoloot)/100.); // Autolooting items with drop rates of %0.02f%% and below. + clif_displaymessage(fd, atcmd_output); + }else + clif_displaymessage(fd, msg_txt(1188)); // Autoloot is now off. + + return 0; } /*========================================== @@ -5634,91 +5804,95 @@ ACMD_FUNC(autoloot) *------------------------------------------*/ ACMD_FUNC(autolootitem) { - struct item_data *item_data = NULL; - int i; - int action = 3; // 1=add, 2=remove, 3=help+list (default), 4=reset - - if (message && *message) { - if (message[0] == '+') { - message++; - action = 1; - } else if (message[0] == '-') { - message++; - action = 2; - } else if (!strcmp(message,"reset")) - action = 4; - } - - if (action < 3) { // add or remove - if ((item_data = itemdb_exists(atoi(message))) == NULL) - item_data = itemdb_searchname(message); - if (!item_data) { - // No items founds in the DB with Id or Name - clif_displaymessage(fd, msg_txt(1189)); // Item not found. - return -1; - } - } - - switch (action) { - case 1: - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == item_data->nameid); - if (i != AUTOLOOTITEM_SIZE) { - clif_displaymessage(fd, msg_txt(1190)); // You're already autolooting this item. - return -1; - } - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == 0); - if (i == AUTOLOOTITEM_SIZE) { - clif_displaymessage(fd, msg_txt(1191)); // Your autolootitem list is full. Remove some items first with @autolootid -<item name or ID>. - return -1; - } - sd->state.autolootid[i] = item_data->nameid; // Autoloot Activated - sprintf(atcmd_output, msg_txt(1192), item_data->name, item_data->jname, item_data->nameid); // Autolooting item: '%s'/'%s' {%d} - clif_displaymessage(fd, atcmd_output); - sd->state.autolooting = 1; - break; - case 2: - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == item_data->nameid); - if (i == AUTOLOOTITEM_SIZE) { - clif_displaymessage(fd, msg_txt(1193)); // You're currently not autolooting this item. - return -1; - } - sd->state.autolootid[i] = 0; - sprintf(atcmd_output, msg_txt(1194), item_data->name, item_data->jname, item_data->nameid); // Removed item: '%s'/'%s' {%d} from your autolootitem list. - clif_displaymessage(fd, atcmd_output); - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] != 0); - if (i == AUTOLOOTITEM_SIZE) { - sd->state.autolooting = 0; - } - break; - case 3: - sprintf(atcmd_output, msg_txt(1195), AUTOLOOTITEM_SIZE); // You can have %d items on your autolootitem list. - clif_displaymessage(fd, atcmd_output); - clif_displaymessage(fd, msg_txt(1196)); // To add an item to the list, use "@alootid +<item name or ID>". To remove an item, use "@alootid -<item name or ID>". - clif_displaymessage(fd, msg_txt(1197)); // "@alootid reset" will clear your autolootitem list. - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] != 0); - if (i == AUTOLOOTITEM_SIZE) { - clif_displaymessage(fd, msg_txt(1198)); // Your autolootitem list is empty. - } else { - clif_displaymessage(fd, msg_txt(1199)); // Items on your autolootitem list: - for (i = 0; i < AUTOLOOTITEM_SIZE; i++) { - if (sd->state.autolootid[i] == 0) - continue; - if (!(item_data = itemdb_exists(sd->state.autolootid[i]))) { - ShowDebug("Non-existant item %d on autolootitem list (account_id: %d, char_id: %d)", sd->state.autolootid[i], sd->status.account_id, sd->status.char_id); - continue; - } - sprintf(atcmd_output, "'%s'/'%s' {%d}", item_data->name, item_data->jname, item_data->nameid); - clif_displaymessage(fd, atcmd_output); - } - } - break; - case 4: - memset(sd->state.autolootid, 0, sizeof(sd->state.autolootid)); - clif_displaymessage(fd, msg_txt(1200)); // Your autolootitem list has been reset. - sd->state.autolooting = 0; - break; - } - return 0; + struct item_data *item_data = NULL; + int i; + int action = 3; // 1=add, 2=remove, 3=help+list (default), 4=reset + + if (message && *message) { + if (message[0] == '+') { + message++; + action = 1; + } + else if (message[0] == '-') { + message++; + action = 2; + } + else if (!strcmp(message,"reset")) + action = 4; + } + + if (action < 3) // add or remove + { + if ((item_data = itemdb_exists(atoi(message))) == NULL) + item_data = itemdb_searchname(message); + if (!item_data) { + // No items founds in the DB with Id or Name + clif_displaymessage(fd, msg_txt(1189)); // Item not found. + return -1; + } + } + + switch(action) { + case 1: + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == item_data->nameid); + if (i != AUTOLOOTITEM_SIZE) { + clif_displaymessage(fd, msg_txt(1190)); // You're already autolooting this item. + return -1; + } + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == 0); + if (i == AUTOLOOTITEM_SIZE) { + clif_displaymessage(fd, msg_txt(1191)); // Your autolootitem list is full. Remove some items first with @autolootid -<item name or ID>. + return -1; + } + sd->state.autolootid[i] = item_data->nameid; // Autoloot Activated + sprintf(atcmd_output, msg_txt(1192), item_data->name, item_data->jname, item_data->nameid); // Autolooting item: '%s'/'%s' {%d} + clif_displaymessage(fd, atcmd_output); + sd->state.autolooting = 1; + break; + case 2: + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == item_data->nameid); + if (i == AUTOLOOTITEM_SIZE) { + clif_displaymessage(fd, msg_txt(1193)); // You're currently not autolooting this item. + return -1; + } + sd->state.autolootid[i] = 0; + sprintf(atcmd_output, msg_txt(1194), item_data->name, item_data->jname, item_data->nameid); // Removed item: '%s'/'%s' {%d} from your autolootitem list. + clif_displaymessage(fd, atcmd_output); + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] != 0); + if (i == AUTOLOOTITEM_SIZE) { + sd->state.autolooting = 0; + } + break; + case 3: + sprintf(atcmd_output, msg_txt(1195), AUTOLOOTITEM_SIZE); // You can have %d items on your autolootitem list. + clif_displaymessage(fd, atcmd_output); + clif_displaymessage(fd, msg_txt(1196)); // To add an item to the list, use "@alootid +<item name or ID>". To remove an item, use "@alootid -<item name or ID>". + clif_displaymessage(fd, msg_txt(1197)); // "@alootid reset" will clear your autolootitem list. + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] != 0); + if (i == AUTOLOOTITEM_SIZE) { + clif_displaymessage(fd, msg_txt(1198)); // Your autolootitem list is empty. + } else { + clif_displaymessage(fd, msg_txt(1199)); // Items on your autolootitem list: + for(i = 0; i < AUTOLOOTITEM_SIZE; i++) + { + if (sd->state.autolootid[i] == 0) + continue; + if (!(item_data = itemdb_exists(sd->state.autolootid[i]))) { + ShowDebug("Non-existant item %d on autolootitem list (account_id: %d, char_id: %d)", sd->state.autolootid[i], sd->status.account_id, sd->status.char_id); + continue; + } + sprintf(atcmd_output, "'%s'/'%s' {%d}", item_data->name, item_data->jname, item_data->nameid); + clif_displaymessage(fd, atcmd_output); + } + } + break; + case 4: + memset(sd->state.autolootid, 0, sizeof(sd->state.autolootid)); + clif_displaymessage(fd, msg_txt(1200)); // Your autolootitem list has been reset. + sd->state.autolooting = 0; + break; + } + return 0; } /** * No longer available, keeping here just in case it's back someday. [Ind] @@ -5728,17 +5902,17 @@ ACMD_FUNC(autolootitem) *------------------------------------------*/ //ACMD_FUNC(rain) //{ -// nullpo_retr(-1, sd); -// if (map[sd->bl.m].flag.rain) { -// map[sd->bl.m].flag.rain=0; -// clif_weather(sd->bl.m); -// clif_displaymessage(fd, msg_txt(1201)); // The rain has stopped. -// } else { -// map[sd->bl.m].flag.rain=1; -// clif_weather(sd->bl.m); -// clif_displaymessage(fd, msg_txt(1202)); // It has started to rain. -// } -// return 0; +// nullpo_retr(-1, sd); +// if (map[sd->bl.m].flag.rain) { +// map[sd->bl.m].flag.rain=0; +// clif_weather(sd->bl.m); +// clif_displaymessage(fd, msg_txt(1201)); // The rain has stopped. +// } else { +// map[sd->bl.m].flag.rain=1; +// clif_weather(sd->bl.m); +// clif_displaymessage(fd, msg_txt(1202)); // It has started to rain. +// } +// return 0; //} /*========================================== @@ -5746,18 +5920,18 @@ ACMD_FUNC(autolootitem) *------------------------------------------*/ ACMD_FUNC(snow) { - nullpo_retr(-1, sd); - if (map[sd->bl.m].flag.snow) { - map[sd->bl.m].flag.snow=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1203)); // Snow has stopped falling. - } else { - map[sd->bl.m].flag.snow=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1204)); // It has started to snow. - } + nullpo_retr(-1, sd); + if (map[sd->bl.m].flag.snow) { + map[sd->bl.m].flag.snow=0; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1203)); // Snow has stopped falling. + } else { + map[sd->bl.m].flag.snow=1; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1204)); // It has started to snow. + } - return 0; + return 0; } /*========================================== @@ -5765,17 +5939,17 @@ ACMD_FUNC(snow) *------------------------------------------*/ ACMD_FUNC(sakura) { - nullpo_retr(-1, sd); - if (map[sd->bl.m].flag.sakura) { - map[sd->bl.m].flag.sakura=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1205)); // Cherry tree leaves no longer fall. - } else { - map[sd->bl.m].flag.sakura=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1206)); // Cherry tree leaves have begun to fall. - } - return 0; + nullpo_retr(-1, sd); + if (map[sd->bl.m].flag.sakura) { + map[sd->bl.m].flag.sakura=0; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1205)); // Cherry tree leaves no longer fall. + } else { + map[sd->bl.m].flag.sakura=1; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1206)); // Cherry tree leaves have begun to fall. + } + return 0; } /*========================================== @@ -5783,18 +5957,18 @@ ACMD_FUNC(sakura) *------------------------------------------*/ ACMD_FUNC(clouds) { - nullpo_retr(-1, sd); - if (map[sd->bl.m].flag.clouds) { - map[sd->bl.m].flag.clouds=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1207)); // The clouds has disappear. - } else { - map[sd->bl.m].flag.clouds=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1208)); // Clouds appear. - } + nullpo_retr(-1, sd); + if (map[sd->bl.m].flag.clouds) { + map[sd->bl.m].flag.clouds=0; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1207)); // The clouds has disappear. + } else { + map[sd->bl.m].flag.clouds=1; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1208)); // Clouds appear. + } - return 0; + return 0; } /*========================================== @@ -5802,18 +5976,18 @@ ACMD_FUNC(clouds) *------------------------------------------*/ ACMD_FUNC(clouds2) { - nullpo_retr(-1, sd); - if (map[sd->bl.m].flag.clouds2) { - map[sd->bl.m].flag.clouds2=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1209)); // The alternative clouds disappear. - } else { - map[sd->bl.m].flag.clouds2=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1210)); // Alternative clouds appear. - } + nullpo_retr(-1, sd); + if (map[sd->bl.m].flag.clouds2) { + map[sd->bl.m].flag.clouds2=0; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1209)); // The alternative clouds disappear. + } else { + map[sd->bl.m].flag.clouds2=1; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1210)); // Alternative clouds appear. + } - return 0; + return 0; } /*========================================== @@ -5821,17 +5995,17 @@ ACMD_FUNC(clouds2) *------------------------------------------*/ ACMD_FUNC(fog) { - nullpo_retr(-1, sd); - if (map[sd->bl.m].flag.fog) { - map[sd->bl.m].flag.fog=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1211)); // The fog has gone. - } else { - map[sd->bl.m].flag.fog=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1212)); // Fog hangs over. - } - return 0; + nullpo_retr(-1, sd); + if (map[sd->bl.m].flag.fog) { + map[sd->bl.m].flag.fog=0; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1211)); // The fog has gone. + } else { + map[sd->bl.m].flag.fog=1; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1212)); // Fog hangs over. + } + return 0; } /*========================================== @@ -5839,18 +6013,18 @@ ACMD_FUNC(fog) *------------------------------------------*/ ACMD_FUNC(leaves) { - nullpo_retr(-1, sd); - if (map[sd->bl.m].flag.leaves) { - map[sd->bl.m].flag.leaves=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1213)); // Leaves no longer fall. - } else { - map[sd->bl.m].flag.leaves=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1214)); // Fallen leaves fall. - } + nullpo_retr(-1, sd); + if (map[sd->bl.m].flag.leaves) { + map[sd->bl.m].flag.leaves=0; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1213)); // Leaves no longer fall. + } else { + map[sd->bl.m].flag.leaves=1; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1214)); // Fallen leaves fall. + } - return 0; + return 0; } /*========================================== @@ -5858,18 +6032,18 @@ ACMD_FUNC(leaves) *------------------------------------------*/ ACMD_FUNC(fireworks) { - nullpo_retr(-1, sd); - if (map[sd->bl.m].flag.fireworks) { - map[sd->bl.m].flag.fireworks=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1215)); // Fireworks have ended. - } else { - map[sd->bl.m].flag.fireworks=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1216)); // Fireworks have launched. - } + nullpo_retr(-1, sd); + if (map[sd->bl.m].flag.fireworks) { + map[sd->bl.m].flag.fireworks=0; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1215)); // Fireworks have ended. + } else { + map[sd->bl.m].flag.fireworks=1; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(1216)); // Fireworks have launched. + } - return 0; + return 0; } /*========================================== @@ -5877,22 +6051,22 @@ ACMD_FUNC(fireworks) *------------------------------------------*/ ACMD_FUNC(clearweather) { - nullpo_retr(-1, sd); - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //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.clouds=0; - map[sd->bl.m].flag.clouds2=0; - map[sd->bl.m].flag.fog=0; - map[sd->bl.m].flag.fireworks=0; - map[sd->bl.m].flag.leaves=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(291)); + nullpo_retr(-1, sd); + /** + * No longer available, keeping here just in case it's back someday. [Ind] + **/ + //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.clouds=0; + map[sd->bl.m].flag.clouds2=0; + map[sd->bl.m].flag.fog=0; + map[sd->bl.m].flag.fireworks=0; + map[sd->bl.m].flag.leaves=0; + clif_weather(sd->bl.m); + clif_displaymessage(fd, msg_txt(291)); - return 0; + return 0; } /*=============================================================== @@ -5900,112 +6074,97 @@ ACMD_FUNC(clearweather) *---------------------------------------------------------------*/ ACMD_FUNC(sound) { - char sound_file[100]; + char sound_file[100]; - memset(sound_file, '\0', sizeof(sound_file)); + memset(sound_file, '\0', sizeof(sound_file)); - if (!message || !*message || sscanf(message, "%99[^\n]", sound_file) < 1) { - clif_displaymessage(fd, msg_txt(1217)); // Please enter a sound filename (usage: @sound <filename>). - return -1; - } + if(!message || !*message || sscanf(message, "%99[^\n]", sound_file) < 1) { + clif_displaymessage(fd, msg_txt(1217)); // Please enter a sound filename (usage: @sound <filename>). + return -1; + } - if (strstr(sound_file, ".wav") == NULL) - strcat(sound_file, ".wav"); + if(strstr(sound_file, ".wav") == NULL) + strcat(sound_file, ".wav"); - clif_soundeffectall(&sd->bl, sound_file, 0, AREA); + clif_soundeffectall(&sd->bl, sound_file, 0, AREA); - return 0; + return 0; } /*========================================== - * MOB Search + * MOB Search *------------------------------------------*/ ACMD_FUNC(mobsearch) { - char mob_name[100]; - int mob_id; - int number = 0; - struct s_mapiterator *it; - - nullpo_retr(-1, sd); - - if (!message || !*message || sscanf(message, "%99[^\n]", mob_name) < 1) { - clif_displaymessage(fd, msg_txt(1218)); // Please enter a monster name (usage: @mobsearch <monster name>). - return -1; - } - - if ((mob_id = atoi(mob_name)) == 0) - mob_id = mobdb_searchname(mob_name); - if (mob_id > 0 && mobdb_checkid(mob_id) == 0) { - snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1219),mob_name); // Invalid mob ID %s! - clif_displaymessage(fd, atcmd_output); - return -1; - } - 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-- - - snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1220), mob_name, mapindex_id2name(sd->mapindex)); // Mob Search... %s %s - clif_displaymessage(fd, atcmd_output); - - it = mapit_geteachmob(); - for (;;) { - TBL_MOB *md = (TBL_MOB *)mapit_next(it); - if (md == NULL) - break;// no more mobs - - if (md->bl.m != sd->bl.m) - continue; - if (mob_id != -1 && md->class_ != mob_id) - continue; - - ++number; - if (md->spawn_timer == INVALID_TIMER) - snprintf(atcmd_output, sizeof(atcmd_output), "%2d[%3d:%3d] %s", number, md->bl.x, md->bl.y, md->name); - else - snprintf(atcmd_output, sizeof(atcmd_output), "%2d[%s] %s", number, "dead", md->name); - clif_displaymessage(fd, atcmd_output); - } - mapit_free(it); - - return 0; + char mob_name[100]; + int mob_id; + int number = 0; + struct s_mapiterator* it; + + nullpo_retr(-1, sd); + + if (!message || !*message || sscanf(message, "%99[^\n]", mob_name) < 1) { + clif_displaymessage(fd, msg_txt(1218)); // Please enter a monster name (usage: @mobsearch <monster name>). + return -1; + } + + if ((mob_id = atoi(mob_name)) == 0) + mob_id = mobdb_searchname(mob_name); + if(mob_id > 0 && mobdb_checkid(mob_id) == 0){ + snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1219),mob_name); // Invalid mob ID %s! + clif_displaymessage(fd, atcmd_output); + return -1; + } + 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-- + + snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1220), mob_name, mapindex_id2name(sd->mapindex)); // Mob Search... %s %s + clif_displaymessage(fd, atcmd_output); + + it = mapit_geteachmob(); + for(;;) + { + TBL_MOB* md = (TBL_MOB*)mapit_next(it); + if( md == NULL ) + break;// no more mobs + + if( md->bl.m != sd->bl.m ) + continue; + if( mob_id != -1 && md->class_ != mob_id ) + continue; + + ++number; + if( md->spawn_timer == INVALID_TIMER ) + snprintf(atcmd_output, sizeof(atcmd_output), "%2d[%3d:%3d] %s", number, md->bl.x, md->bl.y, md->name); + else + snprintf(atcmd_output, sizeof(atcmd_output), "%2d[%s] %s", number, "dead", md->name); + clif_displaymessage(fd, atcmd_output); + } + mapit_free(it); + + return 0; } /*========================================== * @cleanmap - cleans items on the ground - * @cleanarea - cleans items on the ground within an specified area *------------------------------------------*/ -static int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap) +static int atcommand_cleanmap_sub(struct block_list *bl, va_list ap) { - nullpo_ret(bl); - map_clearflooritem(bl); + nullpo_ret(bl); + map_clearflooritem(bl); - return 0; + return 0; } ACMD_FUNC(cleanmap) { - map_foreachinmap(atcommand_cleanfloor_sub, sd->bl.m, BL_ITEM); - clif_displaymessage(fd, msg_txt(1221)); // All dropped items have been cleaned up. - return 0; -} - -ACMD_FUNC(cleanarea) -{ - int x0 = 0, y0 = 0, x1 = 0, y1 = 0; - - if (!message || !*message || sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) < 1) { - map_foreachinarea(atcommand_cleanfloor_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); - } - else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 1) { - map_foreachinarea(atcommand_cleanfloor_sub, sd->bl.m, sd->bl.x - x0, sd->bl.y - x0, sd->bl.x + x0, sd->bl.y + x0, BL_ITEM); - } - else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 4) { - map_foreachinarea(atcommand_cleanfloor_sub, sd->bl.m, x0, y0, x1, y1, BL_ITEM); - } - - clif_displaymessage(fd, msg_txt(1221)); // All dropped items have been cleaned up. - return 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); + clif_displaymessage(fd, msg_txt(1221)); // All dropped items have been cleaned up. + return 0; } /*========================================== @@ -6014,146 +6173,151 @@ ACMD_FUNC(cleanarea) *------------------------------------------*/ ACMD_FUNC(npctalk) { - char name[NAME_LENGTH],mes[100],temp[100]; - struct npc_data *nd; - bool ifcolor=(*(command + 8) != 'c' && *(command + 8) != 'C')?0:1; - unsigned long color=0; + char name[NAME_LENGTH],mes[100],temp[100]; + struct npc_data *nd; + bool ifcolor=(*(command + 8) != 'c' && *(command + 8) != 'C')?0:1; + unsigned long color=0; - if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) - return -1; + if (sd->sc.count && //no "chatting" while muted. + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) + return -1; - if (!ifcolor) { - if (!message || !*message || sscanf(message, "%23[^,], %99[^\n]", name, mes) < 2) { - clif_displaymessage(fd, msg_txt(1222)); // Please enter the correct parameters (usage: @npctalk <npc name>, <message>). - return -1; - } - } else { - if (!message || !*message || sscanf(message, "%lx %23[^,], %99[^\n]", &color, name, mes) < 3) { - clif_displaymessage(fd, msg_txt(1223)); // Please enter the correct parameters (usage: @npctalkc <color> <npc name>, <message>). - return -1; - } - } + if(!ifcolor) { + if (!message || !*message || sscanf(message, "%23[^,], %99[^\n]", name, mes) < 2) { + clif_displaymessage(fd, msg_txt(1222)); // Please enter the correct parameters (usage: @npctalk <npc name>, <message>). + return -1; + } + } + else { + if (!message || !*message || sscanf(message, "%lx %23[^,], %99[^\n]", &color, name, mes) < 3) { + clif_displaymessage(fd, msg_txt(1223)); // Please enter the correct parameters (usage: @npctalkc <color> <npc name>, <message>). + return -1; + } + } - if (!(nd = npc_name2id(name))) { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist - return -1; - } + if (!(nd = npc_name2id(name))) { + clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist + return -1; + } - strtok(name, "#"); // discard extra name identifier if present - snprintf(temp, sizeof(temp), "%s : %s", name, mes); + strtok(name, "#"); // discard extra name identifier if present + snprintf(temp, sizeof(temp), "%s : %s", name, mes); - if (ifcolor) clif_messagecolor(&nd->bl,color,temp); - else clif_message(&nd->bl, temp); + if(ifcolor) clif_messagecolor(&nd->bl,color,temp); + else clif_message(&nd->bl, temp); - return 0; + return 0; } ACMD_FUNC(pettalk) { - char mes[100],temp[100]; - struct pet_data *pd; - - nullpo_retr(-1, sd); - - if (battle_config.min_chat_delay) { - if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) - return 0; - sd->cantalk_tick = gettick() + battle_config.min_chat_delay; - } - - if (!sd->status.pet_id || !(pd=sd->pd)) { - clif_displaymessage(fd, msg_txt(184)); - return -1; - } - - if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) - return -1; - - if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) { - clif_displaymessage(fd, msg_txt(1224)); // Please enter a message (usage: @pettalk <message>). - return -1; - } - - if (message[0] == '/') { - // pet emotion processing - const char *emo[] = { - "/!", "/?", "/ho", "/lv", "/swt", "/ic", "/an", "/ag", "/$", "/...", - "/scissors", "/rock", "/paper", "/korea", "/lv2", "/thx", "/wah", "/sry", "/heh", "/swt2", - "/hmm", "/no1", "/??", "/omg", "/O", "/X", "/hlp", "/go", "/sob", "/gg", - "/kis", "/kis2", "/pif", "/ok", "-?-", "/indonesia", "/bzz", "/rice", "/awsm", "/meh", - "/shy", "/pat", "/mp", "/slur", "/com", "/yawn", "/grat", "/hp", "/philippines", "/malaysia", - "/singapore", "/brazil", "/fsh", "/spin", "/sigh", "/dum", "/crwd", "/desp", "/dice", "-dice2", - "-dice3", "-dice4", "-dice5", "-dice6", "/india", "/love", "/russia", "-?-", "/mobile", "/mail", - "/chinese", "/antenna1", "/antenna2", "/antenna3", "/hum", "/abs", "/oops", "/spit", "/ene", "/panic", - "/whisp" - }; - int i; - ARR_FIND(0, ARRAYLENGTH(emo), i, stricmp(message, emo[i]) == 0); - if (i == E_DICE1) i = rnd()%6 + E_DICE1; // randomize /dice - if (i < ARRAYLENGTH(emo)) { - if (sd->emotionlasttime + 1 >= time(NULL)) { // not more than 1 per second - sd->emotionlasttime = time(NULL); - return 0; - } - sd->emotionlasttime = time(NULL); - - clif_emotion(&pd->bl, i); - return 0; - } - } - - snprintf(temp, sizeof temp ,"%s : %s", pd->pet.name, mes); - clif_message(&pd->bl, temp); - - return 0; + char mes[100],temp[100]; + struct pet_data *pd; + + nullpo_retr(-1, sd); + + if ( battle_config.min_chat_delay ) { + if( DIFF_TICK(sd->cantalk_tick, gettick()) > 0 ) + return 0; + sd->cantalk_tick = gettick() + battle_config.min_chat_delay; + } + + if(!sd->status.pet_id || !(pd=sd->pd)) + { + clif_displaymessage(fd, msg_txt(184)); + return -1; + } + + if (sd->sc.count && //no "chatting" while muted. + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) + return -1; + + if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) { + clif_displaymessage(fd, msg_txt(1224)); // Please enter a message (usage: @pettalk <message>). + return -1; + } + + if (message[0] == '/') + {// pet emotion processing + const char* emo[] = { + "/!", "/?", "/ho", "/lv", "/swt", "/ic", "/an", "/ag", "/$", "/...", + "/scissors", "/rock", "/paper", "/korea", "/lv2", "/thx", "/wah", "/sry", "/heh", "/swt2", + "/hmm", "/no1", "/??", "/omg", "/O", "/X", "/hlp", "/go", "/sob", "/gg", + "/kis", "/kis2", "/pif", "/ok", "-?-", "/indonesia", "/bzz", "/rice", "/awsm", "/meh", + "/shy", "/pat", "/mp", "/slur", "/com", "/yawn", "/grat", "/hp", "/philippines", "/malaysia", + "/singapore", "/brazil", "/fsh", "/spin", "/sigh", "/dum", "/crwd", "/desp", "/dice", "-dice2", + "-dice3", "-dice4", "-dice5", "-dice6", "/india", "/love", "/russia", "-?-", "/mobile", "/mail", + "/chinese", "/antenna1", "/antenna2", "/antenna3", "/hum", "/abs", "/oops", "/spit", "/ene", "/panic", + "/whisp" + }; + int i; + ARR_FIND( 0, ARRAYLENGTH(emo), i, stricmp(message, emo[i]) == 0 ); + if( i == E_DICE1 ) i = rnd()%6 + E_DICE1; // randomize /dice + if( i < ARRAYLENGTH(emo) ) + { + if (sd->emotionlasttime + 1 >= time(NULL)) { // not more than 1 per second + sd->emotionlasttime = time(NULL); + return 0; + } + sd->emotionlasttime = time(NULL); + + clif_emotion(&pd->bl, i); + return 0; + } + } + + snprintf(temp, sizeof temp ,"%s : %s", pd->pet.name, mes); + clif_message(&pd->bl, temp); + + return 0; } /// @users - displays the number of players present on each map (and percentage) /// #users displays on the target user instead of self ACMD_FUNC(users) { - char buf[CHAT_SIZE_MAX]; - int i; - int users[MAX_MAPINDEX]; - int users_all; - struct s_mapiterator *iter; + char buf[CHAT_SIZE_MAX]; + int i; + int users[MAX_MAPINDEX]; + int users_all; + struct s_mapiterator* iter; - memset(users, 0, sizeof(users)); - users_all = 0; + memset(users, 0, sizeof(users)); + users_all = 0; - // count users on each map - iter = mapit_getallusers(); - for (;;) { - struct map_session_data *sd2 = (struct map_session_data *)mapit_next(iter); - if (sd2 == NULL) - break;// no more users + // count users on each map + iter = mapit_getallusers(); + for(;;) + { + struct map_session_data* sd2 = (struct map_session_data*)mapit_next(iter); + if( sd2 == NULL ) + break;// no more users - if (sd2->mapindex >= MAX_MAPINDEX) - continue;// invalid mapindex + if( sd2->mapindex >= MAX_MAPINDEX ) + continue;// invalid mapindex - if (users[sd2->mapindex] < INT_MAX) ++users[sd2->mapindex]; - if (users_all < INT_MAX) ++users_all; - } - mapit_free(iter); + if( users[sd2->mapindex] < INT_MAX ) ++users[sd2->mapindex]; + if( users_all < INT_MAX ) ++users_all; + } + mapit_free(iter); - // display results for each map - for (i = 0; i < MAX_MAPINDEX; ++i) { - if (users[i] == 0) - continue;// empty + // display results for each map + for( i = 0; i < MAX_MAPINDEX; ++i ) + { + if( users[i] == 0 ) + continue;// empty - safesnprintf(buf, sizeof(buf), "%s: %d (%.2f%%)", mapindex_id2name(i), users[i], (float)(100.0f*users[i]/users_all)); - clif_displaymessage(sd->fd, buf); - } + safesnprintf(buf, sizeof(buf), "%s: %d (%.2f%%)", mapindex_id2name(i), users[i], (float)(100.0f*users[i]/users_all)); + clif_displaymessage(sd->fd, buf); + } - // display overall count - safesnprintf(buf, sizeof(buf), "all: %d", users_all); - clif_displaymessage(sd->fd, buf); + // display overall count + safesnprintf(buf, sizeof(buf), "all: %d", users_all); + clif_displaymessage(sd->fd, buf); - return 0; + return 0; } /*========================================== @@ -6161,11 +6325,11 @@ ACMD_FUNC(users) *------------------------------------------*/ ACMD_FUNC(reset) { - pc_resetstate(sd); - pc_resetskill(sd,1); - sprintf(atcmd_output, msg_txt(208), sd->status.name); // '%s' skill and stats points reseted! - clif_displaymessage(fd, atcmd_output); - return 0; + pc_resetstate(sd); + pc_resetskill(sd,1); + sprintf(atcmd_output, msg_txt(208), sd->status.name); // '%s' skill and stats points reseted! + clif_displaymessage(fd, atcmd_output); + return 0; } /*========================================== @@ -6173,46 +6337,48 @@ ACMD_FUNC(reset) *------------------------------------------*/ ACMD_FUNC(summon) { - char name[NAME_LENGTH]; - int mob_id = 0; - int duration = 0; - struct mob_data *md; - unsigned int tick=gettick(); + char name[NAME_LENGTH]; + int mob_id = 0; + int duration = 0; + struct mob_data *md; + unsigned int tick=gettick(); - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%23s %d", name, &duration) < 1) { - clif_displaymessage(fd, msg_txt(1225)); // Please enter a monster name (usage: @summon <monster name> {duration}). - return -1; - } + if (!message || !*message || sscanf(message, "%23s %d", name, &duration) < 1) + { + clif_displaymessage(fd, msg_txt(1225)); // Please enter a monster name (usage: @summon <monster name> {duration}). + return -1; + } - if (duration < 1) - duration =1; - else if (duration > 60) - duration =60; + if (duration < 1) + duration =1; + else if (duration > 60) + duration =60; - if ((mob_id = atoi(name)) == 0) - mob_id = mobdb_searchname(name); - if (mob_id == 0 || mobdb_checkid(mob_id) == 0) { - clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. - return -1; - } + if ((mob_id = atoi(name)) == 0) + mob_id = mobdb_searchname(name); + if(mob_id == 0 || mobdb_checkid(mob_id) == 0) + { + clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. + return -1; + } - md = mob_once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, "--ja--", mob_id, "", SZ_SMALL, AI_NONE); + md = mob_once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, "--ja--", mob_id, "", SZ_SMALL, AI_NONE); - if (!md) - return -1; + if(!md) + return -1; - md->master_id=sd->bl.id; - md->special_state.ai=1; - md->deletetimer=add_timer(tick+(duration*60000),mob_timer_delete,md->bl.id,0); - clif_specialeffect(&md->bl,344,AREA); - mob_spawn(md); - sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); - clif_skill_poseffect(&sd->bl,AM_CALLHOMUN,1,md->bl.x,md->bl.y,tick); - clif_displaymessage(fd, msg_txt(39)); // All monster summoned! + md->master_id=sd->bl.id; + md->special_state.ai=1; + md->deletetimer=add_timer(tick+(duration*60000),mob_timer_delete,md->bl.id,0); + clif_specialeffect(&md->bl,344,AREA); + mob_spawn(md); + sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); + clif_skill_poseffect(&sd->bl,AM_CALLHOMUN,1,md->bl.x,md->bl.y,tick); + clif_displaymessage(fd, msg_txt(39)); // All monster summoned! - return 0; + return 0; } /*========================================== @@ -6222,24 +6388,24 @@ ACMD_FUNC(summon) *------------------------------------------*/ ACMD_FUNC(adjgroup) { - int new_group = 0; - nullpo_retr(-1, sd); + int new_group = 0; + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%d", &new_group) != 1) { - clif_displaymessage(fd, msg_txt(1226)); // Usage: @adjgroup <group_id> - return -1; - } + if (!message || !*message || sscanf(message, "%d", &new_group) != 1) { + clif_displaymessage(fd, msg_txt(1226)); // Usage: @adjgroup <group_id> + return -1; + } - if (!pc_group_exists(new_group)) { - clif_displaymessage(fd, msg_txt(1227)); // Specified group does not exist. - return -1; - } + if (!pc_group_exists(new_group)) { + clif_displaymessage(fd, msg_txt(1227)); // Specified group does not exist. + return -1; + } - sd->group_id = new_group; - pc_group_pc_load(sd);/* update cache */ - clif_displaymessage(fd, msg_txt(1228)); // Group changed successfully. - clif_displaymessage(sd->fd, msg_txt(1229)); // Your group has changed. - return 0; + sd->group_id = new_group; + pc_group_pc_load(sd);/* update cache */ + clif_displaymessage(fd, msg_txt(1228)); // Group changed successfully. + clif_displaymessage(sd->fd, msg_txt(1229)); // Your group has changed. + return 0; } /*========================================== @@ -6249,20 +6415,21 @@ ACMD_FUNC(adjgroup) ACMD_FUNC(trade) { struct map_session_data *pl_sd = NULL; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1230)); // Please enter a player name (usage: @trade <char name>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1230)); // Please enter a player name (usage: @trade <char name>). + return -1; + } - if ((pl_sd = map_nick2sd((char *)message)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + if ( (pl_sd = map_nick2sd((char *)message)) == NULL ) + { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - trade_traderequest(sd, pl_sd); - return 0; + trade_traderequest(sd, pl_sd); + return 0; } /*========================================== @@ -6271,22 +6438,23 @@ ACMD_FUNC(trade) *------------------------------------------*/ ACMD_FUNC(setbattleflag) { - char flag[128], value[128]; - nullpo_retr(-1, sd); + char flag[128], value[128]; + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%127s %127s", flag, value) != 2) { - clif_displaymessage(fd, msg_txt(1231)); // Usage: @setbattleflag <flag> <value> - return -1; - } + if (!message || !*message || sscanf(message, "%127s %127s", flag, value) != 2) { + clif_displaymessage(fd, msg_txt(1231)); // Usage: @setbattleflag <flag> <value> + return -1; + } - if (battle_set_value(flag, value) == 0) { - clif_displaymessage(fd, msg_txt(1232)); // Unknown battle_config flag. - return -1; - } + if (battle_set_value(flag, value) == 0) + { + clif_displaymessage(fd, msg_txt(1232)); // Unknown battle_config flag. + return -1; + } - clif_displaymessage(fd, msg_txt(1233)); // Set battle_config as requested. + clif_displaymessage(fd, msg_txt(1233)); // Set battle_config as requested. - return 0; + return 0; } /*========================================== @@ -6294,29 +6462,30 @@ ACMD_FUNC(setbattleflag) *------------------------------------------*/ ACMD_FUNC(unmute) { - struct map_session_data *pl_sd = NULL; - nullpo_retr(-1, sd); + struct map_session_data *pl_sd = NULL; + nullpo_retr(-1, sd); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1234)); // Please enter a player name (usage: @unmute <char name>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1234)); // Please enter a player name (usage: @unmute <char name>). + return -1; + } - if ((pl_sd = map_nick2sd((char *)message)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + if ( (pl_sd = map_nick2sd((char *)message)) == NULL ) + { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - if (!pl_sd->sc.data[SC_NOCHAT]) { - clif_displaymessage(sd->fd,msg_txt(1235)); // Player is not muted. - return -1; - } + if(!pl_sd->sc.data[SC_NOCHAT]) { + clif_displaymessage(sd->fd,msg_txt(1235)); // Player is not muted. + return -1; + } - pl_sd->status.manner = 0; - status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER); - clif_displaymessage(sd->fd,msg_txt(1236)); // Player unmuted. + pl_sd->status.manner = 0; + status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER); + clif_displaymessage(sd->fd,msg_txt(1236)); // Player unmuted. - return 0; + return 0; } /*========================================== @@ -6324,22 +6493,22 @@ ACMD_FUNC(unmute) *------------------------------------------*/ ACMD_FUNC(uptime) { - unsigned long seconds = 0, day = 24*60*60, hour = 60*60, - minute = 60, days = 0, hours = 0, minutes = 0; - nullpo_retr(-1, sd); + unsigned long seconds = 0, day = 24*60*60, hour = 60*60, + minute = 60, days = 0, hours = 0, minutes = 0; + nullpo_retr(-1, sd); - seconds = get_uptime(); - 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; + seconds = get_uptime(); + 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; - snprintf(atcmd_output, sizeof(atcmd_output), msg_txt(245), days, hours, minutes, seconds); - clif_displaymessage(fd, atcmd_output); + snprintf(atcmd_output, sizeof(atcmd_output), msg_txt(245), days, hours, minutes, seconds); + clif_displaymessage(fd, atcmd_output); - return 0; + return 0; } /*========================================== @@ -6348,14 +6517,14 @@ ACMD_FUNC(uptime) *------------------------------------------*/ ACMD_FUNC(changesex) { - int i; - nullpo_retr(-1, sd); - pc_resetskill(sd,4); - // to avoid any problem with equipment and invalid sex, equipment is unequiped. - for (i=0; i<EQI_MAX; i++) - if (sd->equip_index[i] >= 0) pc_unequipitem(sd, sd->equip_index[i], 3); - chrif_changesex(sd); - return 0; + int i; + nullpo_retr(-1, sd); + pc_resetskill(sd,4); + // to avoid any problem with equipment and invalid sex, equipment is unequiped. + for( i=0; i<EQI_MAX; i++ ) + if( sd->equip_index[i] >= 0 ) pc_unequipitem(sd, sd->equip_index[i], 3); + chrif_changesex(sd); + return 0; } /*================================================ @@ -6363,39 +6532,41 @@ ACMD_FUNC(changesex) *------------------------------------------------*/ ACMD_FUNC(mute) { - struct map_session_data *pl_sd = NULL; - int manner; - nullpo_retr(-1, sd); + struct map_session_data *pl_sd = NULL; + int manner; + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%d %23[^\n]", &manner, atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1237)); // Usage: @mute <time> <char name> - return -1; - } + if (!message || !*message || sscanf(message, "%d %23[^\n]", &manner, atcmd_player_name) < 1) { + clif_displaymessage(fd, msg_txt(1237)); // Usage: @mute <time> <char name> + return -1; + } - if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; - } + if ( (pl_sd = map_nick2sd(atcmd_player_name)) == NULL ) + { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return -1; + } - if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; - } + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) + { + clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return -1; + } - clif_manner_message(sd, 0); - clif_manner_message(pl_sd, 5); + clif_manner_message(sd, 0); + clif_manner_message(pl_sd, 5); - if (pl_sd->status.manner < manner) { - pl_sd->status.manner -= manner; - sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0); - } else { - pl_sd->status.manner = 0; - status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER); - } + if( pl_sd->status.manner < manner ) { + pl_sd->status.manner -= manner; + sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0); + } else { + pl_sd->status.manner = 0; + status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER); + } - clif_GM_silence(sd, pl_sd, (manner > 0 ? 1 : 0)); + clif_GM_silence(sd, pl_sd, (manner > 0 ? 1 : 0)); - return 0; + return 0; } /*========================================== @@ -6403,9 +6574,9 @@ ACMD_FUNC(mute) *------------------------------------------*/ ACMD_FUNC(refresh) { - nullpo_retr(-1, sd); - clif_refresh(sd); - return 0; + nullpo_retr(-1, sd); + clif_refresh(sd); + return 0; } /*========================================== @@ -6414,21 +6585,21 @@ ACMD_FUNC(refresh) *------------------------------------------*/ ACMD_FUNC(identify) { - int i,num; + int i,num; - nullpo_retr(-1, sd); + 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); - } else { - clif_displaymessage(fd,msg_txt(1238)); // There are no items to appraise. - } - return 0; + 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); + } else { + clif_displaymessage(fd,msg_txt(1238)); // There are no items to appraise. + } + return 0; } /*========================================== @@ -6437,45 +6608,49 @@ ACMD_FUNC(identify) *------------------------------------------*/ ACMD_FUNC(gmotd) { - char buf[CHAT_SIZE_MAX]; - size_t len; - FILE *fp; + char buf[CHAT_SIZE_MAX]; + size_t len; + FILE* fp; - if ((fp = fopen(motd_txt, "r")) != NULL) { - while (fgets(buf, sizeof(buf), fp)) { - if (buf[0] == '/' && buf[1] == '/') { - continue; - } + if( ( fp = fopen(motd_txt, "r") ) != NULL ) + { + while( fgets(buf, sizeof(buf), fp) ) + { + if( buf[0] == '/' && buf[1] == '/' ) + { + continue; + } - len = strlen(buf); + len = strlen(buf); - while (len && (buf[len-1] == '\r' || buf[len-1] == '\n')) { - // strip trailing EOL characters - len--; - } + while( len && ( buf[len-1] == '\r' || buf[len-1] == '\n' ) ) + {// strip trailing EOL characters + len--; + } - if (len) { - buf[len] = 0; + if( len ) + { + buf[len] = 0; - intif_broadcast(buf, len+1, 0); - } - } - fclose(fp); - } - return 0; + intif_broadcast(buf, len+1, 0); + } + } + fclose(fp); + } + return 0; } ACMD_FUNC(misceffect) { - int effect = 0; - nullpo_retr(-1, sd); - if (!message || !*message) - return -1; - if (sscanf(message, "%d", &effect) < 1) - return -1; - clif_misceffect(&sd->bl,effect); + int effect = 0; + nullpo_retr(-1, sd); + if (!message || !*message) + return -1; + if (sscanf(message, "%d", &effect) < 1) + return -1; + clif_misceffect(&sd->bl,effect); - return 0; + return 0; } /*========================================== @@ -6483,9 +6658,9 @@ ACMD_FUNC(misceffect) *------------------------------------------*/ ACMD_FUNC(mail) { - nullpo_ret(sd); - mail_openmail(sd); - return 0; + nullpo_ret(sd); + mail_openmail(sd); + return 0; } /*========================================== @@ -6494,110 +6669,111 @@ ACMD_FUNC(mail) *------------------------------------------*/ ACMD_FUNC(mobinfo) { - 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[10][8] = {"Neutral", "Water", "Earth", "Fire", "Wind", "Poison", "Holy", "Dark", "Ghost", "Undead"}; - char atcmd_output2[CHAT_SIZE_MAX]; - struct item_data *item_data; - struct mob_db *mob, *mob_array[MAX_SEARCH]; - int count; - int i, j, k; - - memset(atcmd_output, '\0', sizeof(atcmd_output)); - memset(atcmd_output2, '\0', sizeof(atcmd_output2)); - - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1239)); // Please enter a monster name/ID (usage: @mobinfo <monster_name_or_monster_ID>). - return -1; - } - - // If monster identifier/name argument is a name - if ((i = mobdb_checkid(atoi(message)))) { - mob_array[0] = mob_db(i); - count = 1; - } else - count = mobdb_searchname_array(mob_array, MAX_SEARCH, message); - - if (!count) { - clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. - return -1; - } - - if (count > MAX_SEARCH) { - sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); - clif_displaymessage(fd, atcmd_output); - count = MAX_SEARCH; - } - for (k = 0; k < count; k++) { - mob = mob_array[k]; - - // stats - if (mob->mexp) - sprintf(atcmd_output, msg_txt(1240), mob->name, mob->jname, mob->sprite, mob->vd.class_); // MVP Monster: '%s'/'%s'/'%s' (%d) - else - sprintf(atcmd_output, msg_txt(1241), mob->name, mob->jname, mob->sprite, mob->vd.class_); // Monster: '%s'/'%s'/'%s' (%d) - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1242), mob->lv, mob->status.max_hp, mob->base_exp, mob->job_exp,MOB_HIT(mob), MOB_FLEE(mob)); // Lv:%d HP:%d Base EXP:%u Job EXP:%u HIT:%d FLEE:%d - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1243), // DEF:%d MDEF:%d STR:%d AGI:%d VIT:%d INT:%d DEX:%d LUK:%d - mob->status.def, mob->status.mdef,mob->status.str, mob->status.agi, - mob->status.vit, mob->status.int_, mob->status.dex, mob->status.luk); - clif_displaymessage(fd, atcmd_output); - - sprintf(atcmd_output, msg_txt(1244), // ATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d) - mob->status.rhw.atk, mob->status.rhw.atk2, mob->status.rhw.range, - mob->range2 , mob->range3, msize[mob->status.size], - mrace[mob->status.race], melement[mob->status.def_ele], mob->status.ele_lv); - clif_displaymessage(fd, atcmd_output); - // drops - clif_displaymessage(fd, msg_txt(1245)); // Drops: - strcpy(atcmd_output, " "); - j = 0; - for (i = 0; i < MAX_MOB_DROP; i++) { - int droprate; - if (mob->dropitem[i].nameid <= 0 || mob->dropitem[i].p < 1 || (item_data = itemdb_exists(mob->dropitem[i].nameid)) == NULL) - continue; - droprate = mob->dropitem[i].p; - - if (item_data->slot) - sprintf(atcmd_output2, " - %s[%d] %02.02f%%", item_data->jname, item_data->slot, (float)droprate / 100); - else - sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)droprate / 100); - strcat(atcmd_output, atcmd_output2); - if (++j % 3 == 0) { - clif_displaymessage(fd, atcmd_output); - strcpy(atcmd_output, " "); - } - } - if (j == 0) - clif_displaymessage(fd, msg_txt(1246)); // This monster has no drops. - else if (j % 3 != 0) - clif_displaymessage(fd, atcmd_output); - // mvp - if (mob->mexp) { - sprintf(atcmd_output, msg_txt(1247), mob->mexp); // MVP Bonus EXP:%u - clif_displaymessage(fd, atcmd_output); - strcpy(atcmd_output, msg_txt(1248)); // MVP Items: - j = 0; - for (i = 0; i < MAX_MVP_DROP; i++) { - if (mob->mvpitem[i].nameid <= 0 || (item_data = itemdb_exists(mob->mvpitem[i].nameid)) == NULL) - continue; - if (mob->mvpitem[i].p > 0) { - j++; - if (j == 1) - sprintf(atcmd_output2, " %s %02.02f%%", item_data->jname, (float)mob->mvpitem[i].p / 100); - else - sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)mob->mvpitem[i].p / 100); - strcat(atcmd_output, atcmd_output2); - } - } - if (j == 0) - clif_displaymessage(fd, msg_txt(1249)); // This monster has no MVP prizes. - else - clif_displaymessage(fd, atcmd_output); - } - } - return 0; + 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[10][8] = {"Neutral", "Water", "Earth", "Fire", "Wind", "Poison", "Holy", "Dark", "Ghost", "Undead"}; + char atcmd_output2[CHAT_SIZE_MAX]; + struct item_data *item_data; + struct mob_db *mob, *mob_array[MAX_SEARCH]; + int count; + int i, j, k; + + memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(atcmd_output2, '\0', sizeof(atcmd_output2)); + + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1239)); // Please enter a monster name/ID (usage: @mobinfo <monster_name_or_monster_ID>). + return -1; + } + + // If monster identifier/name argument is a name + if ((i = mobdb_checkid(atoi(message)))) + { + mob_array[0] = mob_db(i); + count = 1; + } else + count = mobdb_searchname_array(mob_array, MAX_SEARCH, message); + + if (!count) { + clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. + return -1; + } + + if (count > MAX_SEARCH) { + sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); + clif_displaymessage(fd, atcmd_output); + count = MAX_SEARCH; + } + for (k = 0; k < count; k++) { + mob = mob_array[k]; + + // stats + if (mob->mexp) + sprintf(atcmd_output, msg_txt(1240), mob->name, mob->jname, mob->sprite, mob->vd.class_); // MVP Monster: '%s'/'%s'/'%s' (%d) + else + sprintf(atcmd_output, msg_txt(1241), mob->name, mob->jname, mob->sprite, mob->vd.class_); // Monster: '%s'/'%s'/'%s' (%d) + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1242), mob->lv, mob->status.max_hp, mob->base_exp, mob->job_exp,MOB_HIT(mob), MOB_FLEE(mob)); // Lv:%d HP:%d Base EXP:%u Job EXP:%u HIT:%d FLEE:%d + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1243), // DEF:%d MDEF:%d STR:%d AGI:%d VIT:%d INT:%d DEX:%d LUK:%d + mob->status.def, mob->status.mdef,mob->status.str, mob->status.agi, + mob->status.vit, mob->status.int_, mob->status.dex, mob->status.luk); + clif_displaymessage(fd, atcmd_output); + + sprintf(atcmd_output, msg_txt(1244), // ATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d) + mob->status.rhw.atk, mob->status.rhw.atk2, mob->status.rhw.range, + mob->range2 , mob->range3, msize[mob->status.size], + mrace[mob->status.race], melement[mob->status.def_ele], mob->status.ele_lv); + clif_displaymessage(fd, atcmd_output); + // drops + clif_displaymessage(fd, msg_txt(1245)); // Drops: + strcpy(atcmd_output, " "); + j = 0; + for (i = 0; i < MAX_MOB_DROP; i++) { + int droprate; + if (mob->dropitem[i].nameid <= 0 || mob->dropitem[i].p < 1 || (item_data = itemdb_exists(mob->dropitem[i].nameid)) == NULL) + continue; + droprate = mob->dropitem[i].p; + + if (item_data->slot) + sprintf(atcmd_output2, " - %s[%d] %02.02f%%", item_data->jname, item_data->slot, (float)droprate / 100); + else + sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)droprate / 100); + strcat(atcmd_output, atcmd_output2); + if (++j % 3 == 0) { + clif_displaymessage(fd, atcmd_output); + strcpy(atcmd_output, " "); + } + } + if (j == 0) + clif_displaymessage(fd, msg_txt(1246)); // This monster has no drops. + else if (j % 3 != 0) + clif_displaymessage(fd, atcmd_output); + // mvp + if (mob->mexp) { + sprintf(atcmd_output, msg_txt(1247), mob->mexp); // MVP Bonus EXP:%u + clif_displaymessage(fd, atcmd_output); + strcpy(atcmd_output, msg_txt(1248)); // MVP Items: + j = 0; + for (i = 0; i < MAX_MVP_DROP; i++) { + if (mob->mvpitem[i].nameid <= 0 || (item_data = itemdb_exists(mob->mvpitem[i].nameid)) == NULL) + continue; + if (mob->mvpitem[i].p > 0) { + j++; + if (j == 1) + sprintf(atcmd_output2, " %s %02.02f%%", item_data->jname, (float)mob->mvpitem[i].p / 100); + else + sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)mob->mvpitem[i].p / 100); + strcat(atcmd_output, atcmd_output2); + } + } + if (j == 0) + clif_displaymessage(fd, msg_txt(1249)); // This monster has no MVP prizes. + else + clif_displaymessage(fd, atcmd_output); + } + } + return 0; } /*========================================= @@ -6606,58 +6782,59 @@ ACMD_FUNC(mobinfo) *------------------------------------------*/ ACMD_FUNC(showmobs) { - char mob_name[100]; - int mob_id; - int number = 0; - struct s_mapiterator *it; + char mob_name[100]; + int mob_id; + int number = 0; + struct s_mapiterator* it; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (sscanf(message, "%99[^\n]", mob_name) < 0) - return -1; + 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 > 0 && mobdb_checkid(mob_id) == 0) { - snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1250),mob_name); // Invalid mob id %s! - clif_displaymessage(fd, atcmd_output); - return 0; - } + if((mob_id = atoi(mob_name)) == 0) + mob_id = mobdb_searchname(mob_name); + if(mob_id > 0 && mobdb_checkid(mob_id) == 0){ + snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1250),mob_name); // Invalid mob id %s! + clif_displaymessage(fd, atcmd_output); + return 0; + } - if (mob_db(mob_id)->status.mode&MD_BOSS && !pc_has_permission(sd, PC_PERM_SHOW_BOSS)) { // If player group does not have access to boss mobs. - clif_displaymessage(fd, msg_txt(1251)); // Can't show boss mobs! - return 0; - } + if(mob_db(mob_id)->status.mode&MD_BOSS && !pc_has_permission(sd, PC_PERM_SHOW_BOSS)){ // If player group does not have access to boss mobs. + clif_displaymessage(fd, msg_txt(1251)); // Can't show boss mobs! + 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-- + 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-- - snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1252), // Mob Search... %s %s - mob_name, mapindex_id2name(sd->mapindex)); - clif_displaymessage(fd, atcmd_output); + snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1252), // Mob Search... %s %s + mob_name, mapindex_id2name(sd->mapindex)); + clif_displaymessage(fd, atcmd_output); - it = mapit_geteachmob(); - for (;;) { - TBL_MOB *md = (TBL_MOB *)mapit_next(it); - if (md == NULL) - break;// no more mobs + it = mapit_geteachmob(); + for(;;) + { + TBL_MOB* md = (TBL_MOB*)mapit_next(it); + if( md == NULL ) + break;// no more mobs - if (md->bl.m != sd->bl.m) - continue; - if (mob_id != -1 && md->class_ != mob_id) - continue; - if (md->special_state.ai || md->master_id) - continue; // hide slaves and player summoned mobs - if (md->spawn_timer != INVALID_TIMER) - continue; // hide mobs waiting for respawn + if( md->bl.m != sd->bl.m ) + continue; + if( mob_id != -1 && md->class_ != mob_id ) + continue; + if( md->special_state.ai || md->master_id ) + continue; // hide slaves and player summoned mobs + if( md->spawn_timer != INVALID_TIMER ) + continue; // hide mobs waiting for respawn - ++number; - clif_viewpoint(sd, 1, 0, md->bl.x, md->bl.y, number, 0xFFFFFF); - } - mapit_free(it); + ++number; + clif_viewpoint(sd, 1, 0, md->bl.x, md->bl.y, number, 0xFFFFFF); + } + mapit_free(it); - return 0; + return 0; } /*========================================== @@ -6665,31 +6842,31 @@ ACMD_FUNC(showmobs) *------------------------------------------*/ ACMD_FUNC(homlevel) { - TBL_HOM *hd; - int level = 0, i = 0; + TBL_HOM * hd; + int level = 0, i = 0; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!message || !*message || (level = atoi(message)) < 1) { - clif_displaymessage(fd, msg_txt(1253)); // Please enter a level adjustment (usage: @homlevel <number of levels>). - return -1; - } + if ( !message || !*message || ( level = atoi(message) ) < 1 ) { + clif_displaymessage(fd, msg_txt(1253)); // Please enter a level adjustment (usage: @homlevel <number of levels>). + return -1; + } - if (!merc_is_hom_active(sd->hd)) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; - } + if ( !merc_is_hom_active(sd->hd) ) { + clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. + return -1; + } - hd = sd->hd; + hd = sd->hd; - for (i = 1; i <= level && hd->exp_next; i++) { - hd->homunculus.exp += hd->exp_next; - merc_hom_levelup(hd); - } - status_calc_homunculus(hd,0); - status_percent_heal(&hd->bl, 100, 100); - clif_specialeffect(&hd->bl,568,AREA); - return 0; + for (i = 1; i <= level && hd->exp_next; i++){ + hd->homunculus.exp += hd->exp_next; + merc_hom_levelup(hd); + } + status_calc_homunculus(hd,0); + status_percent_heal(&hd->bl, 100, 100); + clif_specialeffect(&hd->bl,568,AREA); + return 0; } /*========================================== @@ -6697,19 +6874,19 @@ ACMD_FUNC(homlevel) *------------------------------------------*/ ACMD_FUNC(homevolution) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!merc_is_hom_active(sd->hd)) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; - } + if ( !merc_is_hom_active(sd->hd) ) { + clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. + return -1; + } - if (!merc_hom_evolution(sd->hd)) { - clif_displaymessage(fd, msg_txt(1255)); // Your homunculus doesn't evolve. - return -1; - } - clif_homskillinfoblock(sd); - return 0; + if ( !merc_hom_evolution(sd->hd) ) { + clif_displaymessage(fd, msg_txt(1255)); // Your homunculus doesn't evolve. + return -1; + } + clif_homskillinfoblock(sd); + return 0; } /*========================================== @@ -6717,27 +6894,28 @@ ACMD_FUNC(homevolution) *------------------------------------------*/ ACMD_FUNC(makehomun) { - int homunid; - nullpo_retr(-1, sd); + int homunid; + nullpo_retr(-1, sd); - if (sd->status.hom_id) { - clif_displaymessage(fd, msg_txt(450)); - return -1; - } + if ( sd->status.hom_id ) { + clif_displaymessage(fd, msg_txt(450)); + return -1; + } - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1256)); // Please enter a homunculus ID (usage: @makehomun <homunculus id>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1256)); // Please enter a homunculus ID (usage: @makehomun <homunculus id>). + return -1; + } - homunid = atoi(message); - if (homunid < HM_CLASS_BASE || homunid > HM_CLASS_BASE + MAX_HOMUNCULUS_CLASS - 1) { - clif_displaymessage(fd, msg_txt(1257)); // Invalid Homunculus ID. - return -1; - } + homunid = atoi(message); + if( homunid < HM_CLASS_BASE || homunid > HM_CLASS_BASE + MAX_HOMUNCULUS_CLASS - 1 ) + { + clif_displaymessage(fd, msg_txt(1257)); // Invalid Homunculus ID. + return -1; + } - merc_create_homunculus_request(sd,homunid); - return 0; + merc_create_homunculus_request(sd,homunid); + return 0; } /*========================================== @@ -6745,26 +6923,26 @@ ACMD_FUNC(makehomun) *------------------------------------------*/ ACMD_FUNC(homfriendly) { - int friendly = 0; + int friendly = 0; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!merc_is_hom_active(sd->hd)) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; - } + if ( !merc_is_hom_active(sd->hd) ) { + clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. + return -1; + } - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1258)); // Please enter a friendly value (usage: @homfriendly <friendly value [0-1000]>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1258)); // Please enter a friendly value (usage: @homfriendly <friendly value [0-1000]>). + return -1; + } - friendly = atoi(message); - friendly = cap_value(friendly, 0, 1000); + friendly = atoi(message); + friendly = cap_value(friendly, 0, 1000); - sd->hd->homunculus.intimacy = friendly * 100 ; - clif_send_homdata(sd,SP_INTIMATE,friendly); - return 0; + sd->hd->homunculus.intimacy = friendly * 100 ; + clif_send_homdata(sd,SP_INTIMATE,friendly); + return 0; } /*========================================== @@ -6772,26 +6950,26 @@ ACMD_FUNC(homfriendly) *------------------------------------------*/ ACMD_FUNC(homhungry) { - int hungry = 0; + int hungry = 0; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!merc_is_hom_active(sd->hd)) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; - } + if ( !merc_is_hom_active(sd->hd) ) { + clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. + return -1; + } - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1259)); // Please enter a hunger value (usage: @homhungry <hunger value [0-100]>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1259)); // Please enter a hunger value (usage: @homhungry <hunger value [0-100]>). + return -1; + } - hungry = atoi(message); - hungry = cap_value(hungry, 0, 100); + hungry = atoi(message); + hungry = cap_value(hungry, 0, 100); - sd->hd->homunculus.hunger = hungry; - clif_send_homdata(sd,SP_HUNGRY,hungry); - return 0; + sd->hd->homunculus.hunger = hungry; + clif_send_homdata(sd,SP_HUNGRY,hungry); + return 0; } /*========================================== @@ -6799,35 +6977,35 @@ ACMD_FUNC(homhungry) *------------------------------------------*/ ACMD_FUNC(homtalk) { - char mes[100],temp[100]; + char mes[100],temp[100]; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (battle_config.min_chat_delay) { - if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) - return 0; - sd->cantalk_tick = gettick() + battle_config.min_chat_delay; - } + if ( battle_config.min_chat_delay ) { + if( DIFF_TICK(sd->cantalk_tick, gettick()) > 0 ) + return 0; + sd->cantalk_tick = gettick() + battle_config.min_chat_delay; + } - if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) - return -1; + if (sd->sc.count && //no "chatting" while muted. + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) + return -1; - if (!merc_is_hom_active(sd->hd)) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; - } + if ( !merc_is_hom_active(sd->hd) ) { + clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. + return -1; + } - if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) { - clif_displaymessage(fd, msg_txt(1260)); // Please enter a message (usage: @homtalk <message>). - return -1; - } + if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) { + clif_displaymessage(fd, msg_txt(1260)); // Please enter a message (usage: @homtalk <message>). + return -1; + } - snprintf(temp, sizeof temp ,"%s : %s", sd->hd->homunculus.name, mes); - clif_message(&sd->hd->bl, temp); + snprintf(temp, sizeof temp ,"%s : %s", sd->hd->homunculus.name, mes); + clif_message(&sd->hd->bl, temp); - return 0; + return 0; } /*========================================== @@ -6835,122 +7013,122 @@ ACMD_FUNC(homtalk) *------------------------------------------*/ ACMD_FUNC(hominfo) { - struct homun_data *hd; - struct status_data *status; - nullpo_retr(-1, sd); + struct homun_data *hd; + struct status_data *status; + nullpo_retr(-1, sd); - if (!merc_is_hom_active(sd->hd)) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; - } + if ( !merc_is_hom_active(sd->hd) ) { + clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. + return -1; + } - hd = sd->hd; - status = status_get_status_data(&hd->bl); - clif_displaymessage(fd, msg_txt(1261)); // Homunculus stats: + hd = sd->hd; + status = status_get_status_data(&hd->bl); + clif_displaymessage(fd, msg_txt(1261)); // Homunculus stats: - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1262), // HP: %d/%d - SP: %d/%d - status->hp, status->max_hp, status->sp, status->max_sp); - clif_displaymessage(fd, atcmd_output); + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1262), // HP: %d/%d - SP: %d/%d + status->hp, status->max_hp, status->sp, status->max_sp); + clif_displaymessage(fd, atcmd_output); - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1263), // ATK: %d - MATK: %d~%d - status->rhw.atk2 +status->batk, status->matk_min, status->matk_max); - clif_displaymessage(fd, atcmd_output); + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1263), // ATK: %d - MATK: %d~%d + status->rhw.atk2 +status->batk, status->matk_min, status->matk_max); + clif_displaymessage(fd, atcmd_output); - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1264), // Hungry: %d - Intimacy: %u - hd->homunculus.hunger, hd->homunculus.intimacy/100); - clif_displaymessage(fd, atcmd_output); + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1264), // Hungry: %d - Intimacy: %u + hd->homunculus.hunger, hd->homunculus.intimacy/100); + clif_displaymessage(fd, atcmd_output); - snprintf(atcmd_output, sizeof(atcmd_output) , - msg_txt(1265), // Stats: Str %d / Agi %d / Vit %d / Int %d / Dex %d / Luk %d - status->str, status->agi, status->vit, - status->int_, status->dex, status->luk); - clif_displaymessage(fd, atcmd_output); + snprintf(atcmd_output, sizeof(atcmd_output) , + msg_txt(1265), // Stats: Str %d / Agi %d / Vit %d / Int %d / Dex %d / Luk %d + status->str, status->agi, status->vit, + status->int_, status->dex, status->luk); + clif_displaymessage(fd, atcmd_output); - return 0; + return 0; } ACMD_FUNC(homstats) { - struct homun_data *hd; - struct s_homunculus_db *db; - struct s_homunculus *hom; - int lv, min, max, evo; + struct homun_data *hd; + struct s_homunculus_db *db; + struct s_homunculus *hom; + int lv, min, max, evo; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!merc_is_hom_active(sd->hd)) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; - } + if ( !merc_is_hom_active(sd->hd) ) { + clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. + return -1; + } - hd = sd->hd; + hd = sd->hd; - hom = &hd->homunculus; - db = hd->homunculusDB; - lv = hom->level; + hom = &hd->homunculus; + db = hd->homunculusDB; + lv = hom->level; - snprintf(atcmd_output, sizeof(atcmd_output) , - msg_txt(1266), lv, db->name); // Homunculus growth stats (Lv %d %s): - clif_displaymessage(fd, atcmd_output); - lv--; //Since the first increase is at level 2. + snprintf(atcmd_output, sizeof(atcmd_output) , + msg_txt(1266), lv, db->name); // Homunculus growth stats (Lv %d %s): + clif_displaymessage(fd, atcmd_output); + lv--; //Since the first increase is at level 2. - evo = (hom->class_ == db->evo_class); - min = db->base.HP +lv*db->gmin.HP +(evo?db->emin.HP:0); - max = db->base.HP +lv*db->gmax.HP +(evo?db->emax.HP:0);; - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1267), hom->max_hp, min, max); // Max HP: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); + evo = (hom->class_ == db->evo_class); + min = db->base.HP +lv*db->gmin.HP +(evo?db->emin.HP:0); + max = db->base.HP +lv*db->gmax.HP +(evo?db->emax.HP:0);; + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1267), hom->max_hp, min, max); // Max HP: %d (%d~%d) + clif_displaymessage(fd, atcmd_output); - min = db->base.SP +lv*db->gmin.SP +(evo?db->emin.SP:0); - max = db->base.SP +lv*db->gmax.SP +(evo?db->emax.SP:0);; - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1268), hom->max_sp, min, max); // Max SP: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); + min = db->base.SP +lv*db->gmin.SP +(evo?db->emin.SP:0); + max = db->base.SP +lv*db->gmax.SP +(evo?db->emax.SP:0);; + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1268), hom->max_sp, min, max); // Max SP: %d (%d~%d) + clif_displaymessage(fd, atcmd_output); - min = db->base.str +lv*(db->gmin.str/10) +(evo?db->emin.str:0); - max = db->base.str +lv*(db->gmax.str/10) +(evo?db->emax.str:0);; - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1269), hom->str/10, min, max); // Str: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); + min = db->base.str +lv*(db->gmin.str/10) +(evo?db->emin.str:0); + max = db->base.str +lv*(db->gmax.str/10) +(evo?db->emax.str:0);; + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1269), hom->str/10, min, max); // Str: %d (%d~%d) + clif_displaymessage(fd, atcmd_output); - min = db->base.agi +lv*(db->gmin.agi/10) +(evo?db->emin.agi:0); - max = db->base.agi +lv*(db->gmax.agi/10) +(evo?db->emax.agi:0);; - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1270), hom->agi/10, min, max); // Agi: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); + min = db->base.agi +lv*(db->gmin.agi/10) +(evo?db->emin.agi:0); + max = db->base.agi +lv*(db->gmax.agi/10) +(evo?db->emax.agi:0);; + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1270), hom->agi/10, min, max); // Agi: %d (%d~%d) + clif_displaymessage(fd, atcmd_output); - min = db->base.vit +lv*(db->gmin.vit/10) +(evo?db->emin.vit:0); - max = db->base.vit +lv*(db->gmax.vit/10) +(evo?db->emax.vit:0);; - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1271), hom->vit/10, min, max); // Vit: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); + min = db->base.vit +lv*(db->gmin.vit/10) +(evo?db->emin.vit:0); + max = db->base.vit +lv*(db->gmax.vit/10) +(evo?db->emax.vit:0);; + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1271), hom->vit/10, min, max); // Vit: %d (%d~%d) + clif_displaymessage(fd, atcmd_output); - min = db->base.int_ +lv*(db->gmin.int_/10) +(evo?db->emin.int_:0); - max = db->base.int_ +lv*(db->gmax.int_/10) +(evo?db->emax.int_:0);; - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1272), hom->int_/10, min, max); // Int: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); + min = db->base.int_ +lv*(db->gmin.int_/10) +(evo?db->emin.int_:0); + max = db->base.int_ +lv*(db->gmax.int_/10) +(evo?db->emax.int_:0);; + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1272), hom->int_/10, min, max); // Int: %d (%d~%d) + clif_displaymessage(fd, atcmd_output); - min = db->base.dex +lv*(db->gmin.dex/10) +(evo?db->emin.dex:0); - max = db->base.dex +lv*(db->gmax.dex/10) +(evo?db->emax.dex:0);; - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1273), hom->dex/10, min, max); // Dex: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); + min = db->base.dex +lv*(db->gmin.dex/10) +(evo?db->emin.dex:0); + max = db->base.dex +lv*(db->gmax.dex/10) +(evo?db->emax.dex:0);; + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1273), hom->dex/10, min, max); // Dex: %d (%d~%d) + clif_displaymessage(fd, atcmd_output); - min = db->base.luk +lv*(db->gmin.luk/10) +(evo?db->emin.luk:0); - max = db->base.luk +lv*(db->gmax.luk/10) +(evo?db->emax.luk:0);; - snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1274), hom->luk/10, min, max); // Luk: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); + min = db->base.luk +lv*(db->gmin.luk/10) +(evo?db->emin.luk:0); + max = db->base.luk +lv*(db->gmax.luk/10) +(evo?db->emax.luk:0);; + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1274), hom->luk/10, min, max); // Luk: %d (%d~%d) + clif_displaymessage(fd, atcmd_output); - return 0; + return 0; } ACMD_FUNC(homshuffle) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!sd->hd) - return -1; // nothing to do + if(!sd->hd) + return -1; // nothing to do - if (!merc_hom_shuffle(sd->hd)) - return -1; + if(!merc_hom_shuffle(sd->hd)) + return -1; - clif_displaymessage(sd->fd, msg_txt(1275)); // Homunculus stats altered. - atcommand_homstats(fd, sd, command, message); //Print out the new stats - return 0; + clif_displaymessage(sd->fd, msg_txt(1275)); // Homunculus stats altered. + atcommand_homstats(fd, sd, command, message); //Print out the new stats + return 0; } /*========================================== @@ -6959,48 +7137,48 @@ ACMD_FUNC(homshuffle) *------------------------------------------*/ ACMD_FUNC(iteminfo) { - struct item_data *item_data, *item_array[MAX_SEARCH]; - int i, count = 1; - - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1276)); // Please enter an item name/ID (usage: @ii/@iteminfo <item name/ID>). - return -1; - } - if ((item_array[0] = itemdb_exists(atoi(message))) == NULL) - count = itemdb_searchname_array(item_array, MAX_SEARCH, message); - - if (!count) { - clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. - return -1; - } - - if (count > MAX_SEARCH) { - sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); // Displaying first %d out of %d matches - clif_displaymessage(fd, atcmd_output); - count = MAX_SEARCH; - } - for (i = 0; i < count; i++) { - item_data = item_array[i]; - sprintf(atcmd_output, msg_txt(1277), // Item: '%s'/'%s'[%d] (%d) Type: %s | Extra Effect: %s - item_data->name,item_data->jname,item_data->slot,item_data->nameid, - itemdb_typename(item_data->type), - (item_data->script==NULL)? msg_txt(1278) : msg_txt(1279) // None / With script - ); - clif_displaymessage(fd, atcmd_output); - - sprintf(atcmd_output, msg_txt(1280), item_data->value_buy, item_data->value_sell, item_data->weight/10.); // NPC Buy:%dz, Sell:%dz | Weight: %.1f - clif_displaymessage(fd, atcmd_output); - - if (item_data->maxchance == -1) - strcpy(atcmd_output, msg_txt(1281)); // - Available in the shops only. - else if (!battle_config.atcommand_mobinfo_type && item_data->maxchance) - sprintf(atcmd_output, msg_txt(1282), (float)item_data->maxchance / 100); // - Maximal monsters drop chance: %02.02f%% - else - strcpy(atcmd_output, msg_txt(1283)); // - Monsters don't drop this item. - clif_displaymessage(fd, atcmd_output); - - } - return 0; + struct item_data *item_data, *item_array[MAX_SEARCH]; + int i, count = 1; + + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1276)); // Please enter an item name/ID (usage: @ii/@iteminfo <item name/ID>). + return -1; + } + if ((item_array[0] = itemdb_exists(atoi(message))) == NULL) + count = itemdb_searchname_array(item_array, MAX_SEARCH, message); + + if (!count) { + clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. + return -1; + } + + if (count > MAX_SEARCH) { + sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); // Displaying first %d out of %d matches + clif_displaymessage(fd, atcmd_output); + count = MAX_SEARCH; + } + for (i = 0; i < count; i++) { + item_data = item_array[i]; + sprintf(atcmd_output, msg_txt(1277), // Item: '%s'/'%s'[%d] (%d) Type: %s | Extra Effect: %s + item_data->name,item_data->jname,item_data->slot,item_data->nameid, + itemdb_typename(item_data->type), + (item_data->script==NULL)? msg_txt(1278) : msg_txt(1279) // None / With script + ); + clif_displaymessage(fd, atcmd_output); + + sprintf(atcmd_output, msg_txt(1280), item_data->value_buy, item_data->value_sell, item_data->weight/10. ); // NPC Buy:%dz, Sell:%dz | Weight: %.1f + clif_displaymessage(fd, atcmd_output); + + if (item_data->maxchance == -1) + strcpy(atcmd_output, msg_txt(1281)); // - Available in the shops only. + else if (!battle_config.atcommand_mobinfo_type && item_data->maxchance) + sprintf(atcmd_output, msg_txt(1282), (float)item_data->maxchance / 100 ); // - Maximal monsters drop chance: %02.02f%% + else + strcpy(atcmd_output, msg_txt(1283)); // - Monsters don't drop this item. + clif_displaymessage(fd, atcmd_output); + + } + return 0; } /*========================================== @@ -7008,91 +7186,94 @@ ACMD_FUNC(iteminfo) *------------------------------------------*/ ACMD_FUNC(whodrops) { - struct item_data *item_data, *item_array[MAX_SEARCH]; - int i,j, count = 1; - - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1284)); // Please enter item name/ID (usage: @whodrops <item name/ID>). - return -1; - } - if ((item_array[0] = itemdb_exists(atoi(message))) == NULL) - count = itemdb_searchname_array(item_array, MAX_SEARCH, message); - - if (!count) { - clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. - return -1; - } - - if (count > MAX_SEARCH) { - sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); // Displaying first %d out of %d matches - clif_displaymessage(fd, atcmd_output); - count = MAX_SEARCH; - } - for (i = 0; i < count; i++) { - item_data = item_array[i]; - sprintf(atcmd_output, msg_txt(1285), item_data->jname,item_data->slot); // Item: '%s'[%d] - clif_displaymessage(fd, atcmd_output); - - if (item_data->mob[0].chance == 0) { - strcpy(atcmd_output, msg_txt(1286)); // - Item is not dropped by mobs. - clif_displaymessage(fd, atcmd_output); - } else { - sprintf(atcmd_output, msg_txt(1287), MAX_SEARCH); // - Common mobs with highest drop chance (only max %d are listed): - clif_displaymessage(fd, atcmd_output); - - for (j=0; j < MAX_SEARCH && item_data->mob[j].chance > 0; j++) { - sprintf(atcmd_output, "- %s (%02.02f%%)", mob_db(item_data->mob[j].id)->jname, item_data->mob[j].chance/100.); - clif_displaymessage(fd, atcmd_output); - } - } - } - return 0; + struct item_data *item_data, *item_array[MAX_SEARCH]; + int i,j, count = 1; + + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1284)); // Please enter item name/ID (usage: @whodrops <item name/ID>). + return -1; + } + if ((item_array[0] = itemdb_exists(atoi(message))) == NULL) + count = itemdb_searchname_array(item_array, MAX_SEARCH, message); + + if (!count) { + clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. + return -1; + } + + if (count > MAX_SEARCH) { + sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); // Displaying first %d out of %d matches + clif_displaymessage(fd, atcmd_output); + count = MAX_SEARCH; + } + for (i = 0; i < count; i++) { + item_data = item_array[i]; + sprintf(atcmd_output, msg_txt(1285), item_data->jname,item_data->slot); // Item: '%s'[%d] + clif_displaymessage(fd, atcmd_output); + + if (item_data->mob[0].chance == 0) { + strcpy(atcmd_output, msg_txt(1286)); // - Item is not dropped by mobs. + clif_displaymessage(fd, atcmd_output); + } else { + sprintf(atcmd_output, msg_txt(1287), MAX_SEARCH); // - Common mobs with highest drop chance (only max %d are listed): + clif_displaymessage(fd, atcmd_output); + + for (j=0; j < MAX_SEARCH && item_data->mob[j].chance > 0; j++) + { + sprintf(atcmd_output, "- %s (%02.02f%%)", mob_db(item_data->mob[j].id)->jname, item_data->mob[j].chance/100.); + clif_displaymessage(fd, atcmd_output); + } + } + } + return 0; } ACMD_FUNC(whereis) { - struct mob_db *mob, *mob_array[MAX_SEARCH]; - int count; - int i, j, k; - - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1288)); // Please enter a monster name/ID (usage: @whereis <monster_name_or_monster_ID>). - return -1; - } - - // If monster identifier/name argument is a name - if ((i = mobdb_checkid(atoi(message)))) { - mob_array[0] = mob_db(i); - count = 1; - } else - count = mobdb_searchname_array(mob_array, MAX_SEARCH, message); - - if (!count) { - clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. - return -1; - } - - if (count > MAX_SEARCH) { - sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); - clif_displaymessage(fd, atcmd_output); - count = MAX_SEARCH; - } - for (k = 0; k < count; k++) { - mob = mob_array[k]; - snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1289), mob->jname); // %s spawns in: - clif_displaymessage(fd, atcmd_output); - - for (i = 0; i < ARRAYLENGTH(mob->spawn) && mob->spawn[i].qty; i++) { - j = map_mapindex2mapid(mob->spawn[i].mapindex); - if (j < 0) continue; - snprintf(atcmd_output, sizeof atcmd_output, "%s (%d)", map[j].name, mob->spawn[i].qty); - clif_displaymessage(fd, atcmd_output); - } - if (i == 0) - clif_displaymessage(fd, msg_txt(1290)); // This monster does not spawn normally. - } - - return 0; + struct mob_db *mob, *mob_array[MAX_SEARCH]; + int count; + int i, j, k; + + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1288)); // Please enter a monster name/ID (usage: @whereis <monster_name_or_monster_ID>). + return -1; + } + + // If monster identifier/name argument is a name + if ((i = mobdb_checkid(atoi(message)))) + { + mob_array[0] = mob_db(i); + count = 1; + } else + count = mobdb_searchname_array(mob_array, MAX_SEARCH, message); + + if (!count) { + clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. + return -1; + } + + if (count > MAX_SEARCH) { + sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); + clif_displaymessage(fd, atcmd_output); + count = MAX_SEARCH; + } + for (k = 0; k < count; k++) { + mob = mob_array[k]; + snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1289), mob->jname); // %s spawns in: + clif_displaymessage(fd, atcmd_output); + + for (i = 0; i < ARRAYLENGTH(mob->spawn) && mob->spawn[i].qty; i++) + { + j = map_mapindex2mapid(mob->spawn[i].mapindex); + if (j < 0) continue; + snprintf(atcmd_output, sizeof atcmd_output, "%s (%d)", map[j].name, mob->spawn[i].qty); + clif_displaymessage(fd, atcmd_output); + } + if (i == 0) + clif_displaymessage(fd, msg_txt(1290)); // This monster does not spawn normally. + } + + return 0; } /*========================================== @@ -7101,57 +7282,57 @@ ACMD_FUNC(whereis) *------------------------------------------*/ ACMD_FUNC(adopt) { - struct map_session_data *pl_sd1, *pl_sd2, *pl_sd3; - char player1[NAME_LENGTH], player2[NAME_LENGTH], player3[NAME_LENGTH]; - char output[CHAT_SIZE_MAX]; + struct map_session_data *pl_sd1, *pl_sd2, *pl_sd3; + char player1[NAME_LENGTH], player2[NAME_LENGTH], player3[NAME_LENGTH]; + char output[CHAT_SIZE_MAX]; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%23[^,],%23[^,],%23[^\r\n]", player1, player2, player3) < 3) { - clif_displaymessage(fd, msg_txt(1291)); // Usage: @adopt <father>,<mother>,<child> - return -1; - } + if (!message || !*message || sscanf(message, "%23[^,],%23[^,],%23[^\r\n]", player1, player2, player3) < 3) { + clif_displaymessage(fd, msg_txt(1291)); // Usage: @adopt <father>,<mother>,<child> + return -1; + } - if (battle_config.etc_log) - ShowInfo(msg_txt(1292),player1,player2,player3); // Adopting: --%s--%s--%s--\n + if (battle_config.etc_log) + ShowInfo(msg_txt(1292),player1,player2,player3); // Adopting: --%s--%s--%s--\n - if ((pl_sd1=map_nick2sd((char *) player1)) == NULL) { - sprintf(output, msg_txt(1293), player1); // Cannot find player %s online. - clif_displaymessage(fd, output); - return -1; - } + if((pl_sd1=map_nick2sd((char *) player1)) == NULL) { + sprintf(output, msg_txt(1293), player1); // Cannot find player %s online. + clif_displaymessage(fd, output); + return -1; + } - if ((pl_sd2=map_nick2sd((char *) player2)) == NULL) { - sprintf(output, msg_txt(1293), player2); // Cannot find player %s online. - clif_displaymessage(fd, output); - return -1; - } + if((pl_sd2=map_nick2sd((char *) player2)) == NULL) { + sprintf(output, msg_txt(1293), player2); // Cannot find player %s online. + clif_displaymessage(fd, output); + return -1; + } - if ((pl_sd3=map_nick2sd((char *) player3)) == NULL) { - sprintf(output, msg_txt(1293), player3); // Cannot find player %s online. - clif_displaymessage(fd, output); - return -1; - } + if((pl_sd3=map_nick2sd((char *) player3)) == NULL) { + sprintf(output, msg_txt(1293), player3); // Cannot find player %s online. + clif_displaymessage(fd, output); + return -1; + } - if (!pc_adoption(pl_sd1, pl_sd2, pl_sd3)) { - return -1; - } + if( !pc_adoption(pl_sd1, pl_sd2, pl_sd3) ) { + return -1; + } - clif_displaymessage(fd, msg_txt(1294)); // They are family... wish them luck. - return 0; + clif_displaymessage(fd, msg_txt(1294)); // They are family... wish them luck. + return 0; } ACMD_FUNC(version) { - const char *revision; + const char * revision; - if ((revision = get_svn_revision()) != 0) { - sprintf(atcmd_output,msg_txt(1295),revision); // rAthena Version SVN r%s - clif_displaymessage(fd,atcmd_output); - } else - clif_displaymessage(fd,msg_txt(1296)); // Cannot determine SVN revision. + if ((revision = get_svn_revision()) != 0) { + sprintf(atcmd_output,msg_txt(1295),revision); // rAthena Version SVN r%s + clif_displaymessage(fd,atcmd_output); + } else + clif_displaymessage(fd,msg_txt(1296)); // Cannot determine SVN revision. - return 0; + return 0; } /*========================================== @@ -7160,65 +7341,65 @@ ACMD_FUNC(version) static int atcommand_mutearea_sub(struct block_list *bl,va_list ap) { - int time, id; - struct map_session_data *pl_sd = (struct map_session_data *)bl; - if (pl_sd == NULL) - return 0; + int time, id; + struct map_session_data *pl_sd = (struct map_session_data *)bl; + if (pl_sd == NULL) + return 0; - id = va_arg(ap, int); - time = va_arg(ap, int); + id = va_arg(ap, int); + time = va_arg(ap, int); - if (id != bl->id && !pc_get_group_level(pl_sd)) { - pl_sd->status.manner -= time; - if (pl_sd->status.manner < 0) - sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0); - else - status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER); - } - return 0; + if (id != bl->id && !pc_get_group_level(pl_sd)) { + pl_sd->status.manner -= time; + if (pl_sd->status.manner < 0) + sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0); + else + status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER); + } + return 0; } ACMD_FUNC(mutearea) { - int time; - nullpo_ret(sd); + int time; + nullpo_ret(sd); - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1297)); // Please enter a time in minutes (usage: @mutearea/@stfu <time in minutes>). - return -1; - } + if (!message || !*message) { + clif_displaymessage(fd, msg_txt(1297)); // Please enter a time in minutes (usage: @mutearea/@stfu <time in minutes>). + return -1; + } - time = atoi(message); + time = atoi(message); - map_foreachinarea(atcommand_mutearea_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_PC, sd->bl.id, time); + map_foreachinarea(atcommand_mutearea_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_PC, sd->bl.id, time); - return 0; + return 0; } ACMD_FUNC(rates) { - char buf[CHAT_SIZE_MAX]; + char buf[CHAT_SIZE_MAX]; - nullpo_ret(sd); - memset(buf, '\0', sizeof(buf)); + nullpo_ret(sd); + memset(buf, '\0', sizeof(buf)); - snprintf(buf, CHAT_SIZE_MAX, msg_txt(1298), // Experience rates: Base %.2fx / Job %.2fx - battle_config.base_exp_rate/100., battle_config.job_exp_rate/100.); - clif_displaymessage(fd, buf); - snprintf(buf, CHAT_SIZE_MAX, msg_txt(1299), // Normal Drop Rates: Common %.2fx / Healing %.2fx / Usable %.2fx / Equipment %.2fx / Card %.2fx - battle_config.item_rate_common/100., battle_config.item_rate_heal/100., battle_config.item_rate_use/100., battle_config.item_rate_equip/100., battle_config.item_rate_card/100.); - clif_displaymessage(fd, buf); - snprintf(buf, CHAT_SIZE_MAX, msg_txt(1300), // Boss Drop Rates: Common %.2fx / Healing %.2fx / Usable %.2fx / Equipment %.2fx / Card %.2fx - battle_config.item_rate_common_boss/100., battle_config.item_rate_heal_boss/100., battle_config.item_rate_use_boss/100., battle_config.item_rate_equip_boss/100., battle_config.item_rate_card_boss/100.); - clif_displaymessage(fd, buf); - snprintf(buf, CHAT_SIZE_MAX, msg_txt(1301), // Other Drop Rates: MvP %.2fx / Card-Based %.2fx / Treasure %.2fx - battle_config.item_rate_mvp/100., battle_config.item_rate_adddrop/100., battle_config.item_rate_treasure/100.); - clif_displaymessage(fd, buf); + snprintf(buf, CHAT_SIZE_MAX, msg_txt(1298), // Experience rates: Base %.2fx / Job %.2fx + battle_config.base_exp_rate/100., battle_config.job_exp_rate/100.); + clif_displaymessage(fd, buf); + snprintf(buf, CHAT_SIZE_MAX, msg_txt(1299), // Normal Drop Rates: Common %.2fx / Healing %.2fx / Usable %.2fx / Equipment %.2fx / Card %.2fx + battle_config.item_rate_common/100., battle_config.item_rate_heal/100., battle_config.item_rate_use/100., battle_config.item_rate_equip/100., battle_config.item_rate_card/100.); + clif_displaymessage(fd, buf); + snprintf(buf, CHAT_SIZE_MAX, msg_txt(1300), // Boss Drop Rates: Common %.2fx / Healing %.2fx / Usable %.2fx / Equipment %.2fx / Card %.2fx + battle_config.item_rate_common_boss/100., battle_config.item_rate_heal_boss/100., battle_config.item_rate_use_boss/100., battle_config.item_rate_equip_boss/100., battle_config.item_rate_card_boss/100.); + clif_displaymessage(fd, buf); + snprintf(buf, CHAT_SIZE_MAX, msg_txt(1301), // Other Drop Rates: MvP %.2fx / Card-Based %.2fx / Treasure %.2fx + battle_config.item_rate_mvp/100., battle_config.item_rate_adddrop/100., battle_config.item_rate_treasure/100.); + clif_displaymessage(fd, buf); - return 0; + return 0; } /*========================================== @@ -7227,26 +7408,26 @@ ACMD_FUNC(rates) *------------------------------------------*/ ACMD_FUNC(me) { - char tempmes[CHAT_SIZE_MAX]; - nullpo_retr(-1, sd); + char tempmes[CHAT_SIZE_MAX]; + nullpo_retr(-1, sd); - memset(tempmes, '\0', sizeof(tempmes)); - memset(atcmd_output, '\0', sizeof(atcmd_output)); + memset(tempmes, '\0', sizeof(tempmes)); + memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) - return -1; + if (sd->sc.count && //no "chatting" while muted. + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) + return -1; - if (!message || !*message || sscanf(message, "%199[^\n]", tempmes) < 0) { - clif_displaymessage(fd, msg_txt(1302)); // Please enter a message (usage: @me <message>). - return -1; - } + if (!message || !*message || sscanf(message, "%199[^\n]", tempmes) < 0) { + clif_displaymessage(fd, msg_txt(1302)); // Please enter a message (usage: @me <message>). + return -1; + } - sprintf(atcmd_output, msg_txt(270), sd->status.name, tempmes); // *%s %s* - clif_disp_overhead(sd, atcmd_output); + sprintf(atcmd_output, msg_txt(270), sd->status.name, tempmes); // *%s %s* + clif_disp_overhead(sd, atcmd_output); - return 0; + return 0; } @@ -7256,95 +7437,95 @@ ACMD_FUNC(me) *------------------------------------------*/ ACMD_FUNC(size) { - int size = 0; - nullpo_retr(-1, sd); + int size = 0; + nullpo_retr(-1, sd); - size = cap_value(atoi(message),SZ_SMALL,SZ_BIG); + size = cap_value(atoi(message),SZ_SMALL,SZ_BIG); - if (sd->state.size) { - sd->state.size = SZ_SMALL; - pc_setpos(sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_TELEPORT); - } + if(sd->state.size) { + sd->state.size = SZ_SMALL; + pc_setpos(sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_TELEPORT); + } - sd->state.size = size; - if (size == SZ_MEDIUM) - clif_specialeffect(&sd->bl,420,AREA); - else if (size == SZ_BIG) - clif_specialeffect(&sd->bl,422,AREA); + sd->state.size = size; + if( size == SZ_MEDIUM ) + clif_specialeffect(&sd->bl,420,AREA); + else if( size == SZ_BIG ) + clif_specialeffect(&sd->bl,422,AREA); - clif_displaymessage(fd, msg_txt(1303)); // Size change applied. - return 0; + clif_displaymessage(fd, msg_txt(1303)); // Size change applied. + return 0; } ACMD_FUNC(sizeall) { - int size; - struct map_session_data *pl_sd; - struct s_mapiterator *iter; + int size; + struct map_session_data *pl_sd; + struct s_mapiterator* iter; - size = atoi(message); - size = cap_value(size,0,2); + size = atoi(message); + size = cap_value(size,0,2); - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (pl_sd->state.size != size) { - if (pl_sd->state.size) { - pl_sd->state.size = SZ_SMALL; - pc_setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); - } + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { + if( pl_sd->state.size != size ) { + if( pl_sd->state.size ) { + pl_sd->state.size = SZ_SMALL; + pc_setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); + } - pl_sd->state.size = size; - if (size == SZ_MEDIUM) - clif_specialeffect(&pl_sd->bl,420,AREA); - else if (size == SZ_BIG) - clif_specialeffect(&pl_sd->bl,422,AREA); - } - } - mapit_free(iter); + pl_sd->state.size = size; + if( size == SZ_MEDIUM ) + clif_specialeffect(&pl_sd->bl,420,AREA); + else if( size == SZ_BIG ) + clif_specialeffect(&pl_sd->bl,422,AREA); + } + } + mapit_free(iter); - clif_displaymessage(fd, msg_txt(1303)); // Size change applied. - return 0; + clif_displaymessage(fd, msg_txt(1303)); // Size change applied. + return 0; } ACMD_FUNC(sizeguild) { - int size = 0, i; - char guild[NAME_LENGTH]; - struct map_session_data *pl_sd; - struct guild *g; - nullpo_retr(-1, sd); + int size = 0, i; + char guild[NAME_LENGTH]; + struct map_session_data *pl_sd; + struct guild *g; + nullpo_retr(-1, sd); - memset(guild, '\0', sizeof(guild)); + memset(guild, '\0', sizeof(guild)); - if (!message || !*message || sscanf(message, "%d %23[^\n]", &size, guild) < 2) { - clif_displaymessage(fd, msg_txt(1304)); // Please enter guild name/ID (usage: @sizeguild <size> <guild name/ID>). - return -1; - } + if( !message || !*message || sscanf(message, "%d %23[^\n]", &size, guild) < 2 ) { + clif_displaymessage(fd, msg_txt(1304)); // Please enter guild name/ID (usage: @sizeguild <size> <guild name/ID>). + return -1; + } - if ((g = guild_searchname(guild)) == NULL && (g = guild_search(atoi(guild))) == NULL) { - clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. - return -1; - } + if( (g = guild_searchname(guild)) == NULL && (g = guild_search(atoi(guild))) == NULL ) { + clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. + return -1; + } - size = cap_value(size,SZ_SMALL,SZ_BIG); + size = cap_value(size,SZ_SMALL,SZ_BIG); - for (i = 0; i < g->max_member; i++) { - if ((pl_sd = g->member[i].sd) && pl_sd->state.size != size) { - if (pl_sd->state.size) { - pl_sd->state.size = SZ_SMALL; - pc_setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); - } + for( i = 0; i < g->max_member; i++ ) { + if( (pl_sd = g->member[i].sd) && pl_sd->state.size != size ) { + if( pl_sd->state.size ) { + pl_sd->state.size = SZ_SMALL; + pc_setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); + } - pl_sd->state.size = size; - if (size == SZ_MEDIUM) - clif_specialeffect(&pl_sd->bl,420,AREA); - else if (size == SZ_BIG) - clif_specialeffect(&pl_sd->bl,422,AREA); - } - } + pl_sd->state.size = size; + if( size == SZ_MEDIUM ) + clif_specialeffect(&pl_sd->bl,420,AREA); + else if( size == SZ_BIG ) + clif_specialeffect(&pl_sd->bl,422,AREA); + } + } - clif_displaymessage(fd, msg_txt(1303)); // Size change applied. - return 0; + clif_displaymessage(fd, msg_txt(1303)); // Size change applied. + return 0; } /*========================================== @@ -7353,17 +7534,17 @@ ACMD_FUNC(sizeguild) *------------------------------------------*/ ACMD_FUNC(monsterignore) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!sd->state.monster_ignore) { - sd->state.monster_ignore = 1; - clif_displaymessage(sd->fd, msg_txt(1305)); // You are now immune to attacks. - } else { - sd->state.monster_ignore = 0; - clif_displaymessage(sd->fd, msg_txt(1306)); // Returned to normal state. - } + if (!sd->state.monster_ignore) { + sd->state.monster_ignore = 1; + clif_displaymessage(sd->fd, msg_txt(1305)); // You are now immune to attacks. + } else { + sd->state.monster_ignore = 0; + clif_displaymessage(sd->fd, msg_txt(1306)); // Returned to normal state. + } - return 0; + return 0; } /*========================================== * @fakename @@ -7371,169 +7552,103 @@ ACMD_FUNC(monsterignore) *------------------------------------------*/ ACMD_FUNC(fakename) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - if (!message || !*message) { - if (sd->fakename[0]) { - sd->fakename[0] = '\0'; - clif_charnameack(0, &sd->bl); - clif_displaymessage(sd->fd, msg_txt(1307)); // Returned to real name. - return 0; - } + if( !message || !*message ) + { + if( sd->fakename[0] ) + { + sd->fakename[0] = '\0'; + clif_charnameack(0, &sd->bl); + clif_displaymessage(sd->fd, msg_txt(1307)); // Returned to real name. + return 0; + } - clif_displaymessage(sd->fd, msg_txt(1308)); // You must enter a name. - return -1; - } + clif_displaymessage(sd->fd, msg_txt(1308)); // You must enter a name. + return -1; + } - if (strlen(message) < 2) { - clif_displaymessage(sd->fd, msg_txt(1309)); // Fake name must be at least two characters. - return -1; - } + if( strlen(message) < 2 ) + { + clif_displaymessage(sd->fd, msg_txt(1309)); // Fake name must be at least two characters. + return -1; + } - safestrncpy(sd->fakename, message, sizeof(sd->fakename)); - clif_charnameack(0, &sd->bl); - clif_displaymessage(sd->fd, msg_txt(1310)); // Fake name enabled. + safestrncpy(sd->fakename, message, sizeof(sd->fakename)); + clif_charnameack(0, &sd->bl); + clif_displaymessage(sd->fd, msg_txt(1310)); // Fake name enabled. - return 0; + return 0; } /*========================================== * Ragnarok Resources *------------------------------------------*/ -ACMD_FUNC(mapflag) -{ +ACMD_FUNC(mapflag) { #define checkflag( cmd ) if ( map[ sd->bl.m ].flag.cmd ) clif_displaymessage(sd->fd,#cmd) #define setflag( cmd ) \ - if ( strcmp( flag_name , #cmd ) == 0 ){\ - map[ sd->bl.m ].flag.cmd = flag;\ - sprintf(atcmd_output,"[ @mapflag ] %s flag has been set to %s",#cmd,flag?"On":"Off");\ - clif_displaymessage(sd->fd,atcmd_output);\ - return 0;\ - } - char flag_name[100]; - int flag=0,i; - nullpo_retr(-1, sd); - memset(flag_name, '\0', sizeof(flag_name)); - - if (!message || !*message || (sscanf(message, "%99s %d", flag_name, &flag) < 1)) { - clif_displaymessage(sd->fd,msg_txt(1311)); // Enabled Mapflags in this map: - clif_displaymessage(sd->fd,"----------------------------------"); - checkflag(autotrade); - checkflag(allowks); - checkflag(nomemo); - checkflag(noteleport); - checkflag(noreturn); - checkflag(monster_noteleport); - checkflag(nosave); - checkflag(nobranch); - checkflag(noexppenalty); - checkflag(pvp); - checkflag(pvp_noparty); - checkflag(pvp_noguild); - checkflag(pvp_nightmaredrop); - checkflag(pvp_nocalcrank); - checkflag(gvg_castle); - checkflag(gvg); - checkflag(gvg_dungeon); - checkflag(gvg_noparty); - checkflag(battleground); - checkflag(nozenypenalty); - checkflag(notrade); - checkflag(noskill); - checkflag(nowarp); - checkflag(nowarpto); - checkflag(noicewall); - checkflag(snow); - checkflag(clouds); - checkflag(clouds2); - checkflag(fog); - checkflag(fireworks); - checkflag(sakura); - checkflag(leaves); - checkflag(nogo); - checkflag(nobaseexp); - checkflag(nojobexp); - checkflag(nomobloot); - checkflag(nomvploot); - checkflag(nightenabled); - checkflag(restricted); - checkflag(nodrop); - checkflag(novending); - checkflag(loadevent); - checkflag(nochat); - checkflag(partylock); - checkflag(guildlock); - checkflag(src4instance); - clif_displaymessage(sd->fd," "); - clif_displaymessage(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) - clif_displaymessage(sd->fd,msg_txt(1313)); // Type "@mapflag available" to list the available mapflags. - return 1; - } - for (i = 0; flag_name[i]; i++) flag_name[i] = tolower(flag_name[i]); //lowercase - - setflag(autotrade); - setflag(allowks); - setflag(nomemo); - setflag(noteleport); - setflag(noreturn); - setflag(monster_noteleport); - setflag(nosave); - setflag(nobranch); - setflag(noexppenalty); - setflag(pvp); - setflag(pvp_noparty); - setflag(pvp_noguild); - setflag(pvp_nightmaredrop); - setflag(pvp_nocalcrank); - setflag(gvg_castle); - setflag(gvg); - setflag(gvg_dungeon); - setflag(gvg_noparty); - setflag(battleground); - setflag(nozenypenalty); - setflag(notrade); - setflag(noskill); - setflag(nowarp); - setflag(nowarpto); - setflag(noicewall); - setflag(snow); - setflag(clouds); - setflag(clouds2); - setflag(fog); - setflag(fireworks); - setflag(sakura); - setflag(leaves); - setflag(nogo); - setflag(nobaseexp); - setflag(nojobexp); - setflag(nomobloot); - setflag(nomvploot); - setflag(nightenabled); - setflag(restricted); - setflag(nodrop); - setflag(novending); - setflag(loadevent); - setflag(nochat); - setflag(partylock); - setflag(guildlock); - setflag(src4instance); - - clif_displaymessage(sd->fd,msg_txt(1314)); // Invalid flag name or flag. - clif_displaymessage(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) - clif_displaymessage(sd->fd,msg_txt(1315)); // Available Flags: - clif_displaymessage(sd->fd,"----------------------------------"); - clif_displaymessage(sd->fd,"town, autotrade, allowks, nomemo, noteleport, noreturn, monster_noteleport, nosave,"); - clif_displaymessage(sd->fd,"nobranch, noexppenalty, pvp, pvp_noparty, pvp_noguild, pvp_nightmaredrop,"); - clif_displaymessage(sd->fd,"pvp_nocalcrank, gvg_castle, gvg, gvg_dungeon, gvg_noparty, battleground,"); - clif_displaymessage(sd->fd,"nozenypenalty, notrade, noskill, nowarp, nowarpto, noicewall, snow, clouds, clouds2,"); - clif_displaymessage(sd->fd,"fog, fireworks, sakura, leaves, nogo, nobaseexp, nojobexp, nomobloot,"); - clif_displaymessage(sd->fd,"nomvploot, nightenabled, restricted, nodrop, novending, loadevent, nochat, partylock,"); - clif_displaymessage(sd->fd,"guildlock, src4instance"); + if ( strcmp( flag_name , #cmd ) == 0 ){\ + map[ sd->bl.m ].flag.cmd = flag;\ + sprintf(atcmd_output,"[ @mapflag ] %s flag has been set to %s",#cmd,flag?"On":"Off");\ + clif_displaymessage(sd->fd,atcmd_output);\ + return 0;\ + } + unsigned char flag_name[100]; + int flag=0,i; + nullpo_retr(-1, sd); + memset(flag_name, '\0', sizeof(flag_name)); + + if (!message || !*message || (sscanf(message, "%99s %d", flag_name, &flag) < 1)) { + clif_displaymessage(sd->fd,msg_txt(1311)); // Enabled Mapflags in this map: + clif_displaymessage(sd->fd,"----------------------------------"); + checkflag(autotrade); checkflag(allowks); checkflag(nomemo); checkflag(noteleport); + checkflag(noreturn); checkflag(monster_noteleport); checkflag(nosave); checkflag(nobranch); + checkflag(noexppenalty); checkflag(pvp); checkflag(pvp_noparty); checkflag(pvp_noguild); + checkflag(pvp_nightmaredrop); checkflag(pvp_nocalcrank); checkflag(gvg_castle); checkflag(gvg); + checkflag(gvg_dungeon); checkflag(gvg_noparty); checkflag(battleground);checkflag(nozenypenalty); + checkflag(notrade); checkflag(noskill); checkflag(nowarp); checkflag(nowarpto); + checkflag(noicewall); checkflag(snow); checkflag(clouds); checkflag(clouds2); + checkflag(fog); checkflag(fireworks); checkflag(sakura); checkflag(leaves); + checkflag(nogo); checkflag(nobaseexp); + checkflag(nojobexp); checkflag(nomobloot); checkflag(nomvploot); checkflag(nightenabled); + checkflag(restricted); checkflag(nodrop); checkflag(novending); checkflag(loadevent); + checkflag(nochat); checkflag(partylock); checkflag(guildlock); checkflag(src4instance); + clif_displaymessage(sd->fd," "); + clif_displaymessage(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) + clif_displaymessage(sd->fd,msg_txt(1313)); // Type "@mapflag available" to list the available mapflags. + return 1; + } + for (i = 0; flag_name[i]; i++) flag_name[i] = tolower(flag_name[i]); //lowercase + + setflag(autotrade); setflag(allowks); setflag(nomemo); setflag(noteleport); + setflag(noreturn); setflag(monster_noteleport);setflag(nosave); setflag(nobranch); + setflag(noexppenalty); setflag(pvp); setflag(pvp_noparty); setflag(pvp_noguild); + setflag(pvp_nightmaredrop); setflag(pvp_nocalcrank); setflag(gvg_castle); setflag(gvg); + setflag(gvg_dungeon); setflag(gvg_noparty); setflag(battleground); setflag(nozenypenalty); + setflag(notrade); setflag(noskill); setflag(nowarp); setflag(nowarpto); + setflag(noicewall); setflag(snow); setflag(clouds); setflag(clouds2); + setflag(fog); setflag(fireworks); setflag(sakura); setflag(leaves); + setflag(nogo); setflag(nobaseexp); + setflag(nojobexp); setflag(nomobloot); setflag(nomvploot); setflag(nightenabled); + setflag(restricted); setflag(nodrop); setflag(novending); setflag(loadevent); + setflag(nochat); setflag(partylock); setflag(guildlock); setflag(src4instance); + + clif_displaymessage(sd->fd,msg_txt(1314)); // Invalid flag name or flag. + clif_displaymessage(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) + clif_displaymessage(sd->fd,msg_txt(1315)); // Available Flags: + clif_displaymessage(sd->fd,"----------------------------------"); + clif_displaymessage(sd->fd,"town, autotrade, allowks, nomemo, noteleport, noreturn, monster_noteleport, nosave,"); + clif_displaymessage(sd->fd,"nobranch, noexppenalty, pvp, pvp_noparty, pvp_noguild, pvp_nightmaredrop,"); + clif_displaymessage(sd->fd,"pvp_nocalcrank, gvg_castle, gvg, gvg_dungeon, gvg_noparty, battleground,"); + clif_displaymessage(sd->fd,"nozenypenalty, notrade, noskill, nowarp, nowarpto, noicewall, snow, clouds, clouds2,"); + clif_displaymessage(sd->fd,"fog, fireworks, sakura, leaves, nogo, nobaseexp, nojobexp, nomobloot,"); + clif_displaymessage(sd->fd,"nomvploot, nightenabled, restricted, nodrop, novending, loadevent, nochat, partylock,"); + clif_displaymessage(sd->fd,"guildlock, src4instance"); #undef checkflag #undef setflag - return 0; + return 0; } /*=================================== @@ -7541,41 +7656,41 @@ ACMD_FUNC(mapflag) *-----------------------------------*/ ACMD_FUNC(showexp) { - if (sd->state.showexp) { - sd->state.showexp = 0; - clif_displaymessage(fd, msg_txt(1316)); // Gained exp will not be shown. - return 0; - } + if (sd->state.showexp) { + sd->state.showexp = 0; + clif_displaymessage(fd, msg_txt(1316)); // Gained exp will not be shown. + return 0; + } - sd->state.showexp = 1; - clif_displaymessage(fd, msg_txt(1317)); // Gained exp is now shown. - return 0; + sd->state.showexp = 1; + clif_displaymessage(fd, msg_txt(1317)); // Gained exp is now shown. + return 0; } ACMD_FUNC(showzeny) { - if (sd->state.showzeny) { - sd->state.showzeny = 0; - clif_displaymessage(fd, msg_txt(1318)); // Gained zeny will not be shown. - return 0; - } + if (sd->state.showzeny) { + sd->state.showzeny = 0; + clif_displaymessage(fd, msg_txt(1318)); // Gained zeny will not be shown. + return 0; + } - sd->state.showzeny = 1; - clif_displaymessage(fd, msg_txt(1319)); // Gained zeny is now shown. - return 0; + sd->state.showzeny = 1; + clif_displaymessage(fd, msg_txt(1319)); // Gained zeny is now shown. + return 0; } ACMD_FUNC(showdelay) { - if (sd->state.showdelay) { - sd->state.showdelay = 0; - clif_displaymessage(fd, msg_txt(1320)); // Skill delay failures will not be shown. - return 0; - } + if (sd->state.showdelay) { + sd->state.showdelay = 0; + clif_displaymessage(fd, msg_txt(1320)); // Skill delay failures will not be shown. + return 0; + } - sd->state.showdelay = 1; - clif_displaymessage(fd, msg_txt(1321)); // Skill delay failures are now shown. - return 0; + sd->state.showdelay = 1; + clif_displaymessage(fd, msg_txt(1321)); // Skill delay failures are now shown. + return 0; } /*========================================== @@ -7589,156 +7704,158 @@ ACMD_FUNC(showdelay) *------------------------------------------*/ ACMD_FUNC(invite) { - unsigned int did = sd->duel_group; - struct map_session_data *target_sd = map_nick2sd((char *)message); + unsigned int did = sd->duel_group; + struct map_session_data *target_sd = map_nick2sd((char *)message); - if (did <= 0) { - // "Duel: @invite without @duel." - clif_displaymessage(fd, msg_txt(350)); - return 0; - } + if(did <= 0) { + // "Duel: @invite without @duel." + clif_displaymessage(fd, msg_txt(350)); + return 0; + } - if (duel_list[did].max_players_limit > 0 && - duel_list[did].members_count >= duel_list[did].max_players_limit) { + if(duel_list[did].max_players_limit > 0 && + duel_list[did].members_count >= duel_list[did].max_players_limit) { - // "Duel: Limit of players is reached." - clif_displaymessage(fd, msg_txt(351)); - return 0; - } + // "Duel: Limit of players is reached." + clif_displaymessage(fd, msg_txt(351)); + return 0; + } - if (target_sd == NULL) { - // "Duel: Player not found." - clif_displaymessage(fd, msg_txt(352)); - return 0; - } + if(target_sd == NULL) { + // "Duel: Player not found." + clif_displaymessage(fd, msg_txt(352)); + return 0; + } - if (target_sd->duel_group > 0 || target_sd->duel_invite > 0) { - // "Duel: Player already in duel." - clif_displaymessage(fd, msg_txt(353)); - return 0; - } + if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) { + // "Duel: Player already in duel." + clif_displaymessage(fd, msg_txt(353)); + return 0; + } - if (battle_config.duel_only_on_same_map && target_sd->bl.m != sd->bl.m) { - sprintf(atcmd_output, msg_txt(364), message); - clif_displaymessage(fd, atcmd_output); - return 0; - } + if(battle_config.duel_only_on_same_map && target_sd->bl.m != sd->bl.m) + { + sprintf(atcmd_output, msg_txt(364), message); + clif_displaymessage(fd, atcmd_output); + return 0; + } - duel_invite(did, sd, target_sd); - // "Duel: Invitation has been sent." - clif_displaymessage(fd, msg_txt(354)); - return 0; + duel_invite(did, sd, target_sd); + // "Duel: Invitation has been sent." + clif_displaymessage(fd, msg_txt(354)); + return 0; } ACMD_FUNC(duel) { - char output[CHAT_SIZE_MAX]; - unsigned int maxpl=0, newduel; - struct map_session_data *target_sd; - - if (sd->duel_group > 0) { - duel_showinfo(sd->duel_group, sd); - return 0; - } - - if (sd->duel_invite > 0) { - // "Duel: @duel without @reject." - clif_displaymessage(fd, msg_txt(355)); - return 0; - } - - if (!duel_checktime(sd)) { - // "Duel: You can take part in duel only one time per %d minutes." - sprintf(output, msg_txt(356), battle_config.duel_time_interval); - clif_displaymessage(fd, output); - return 0; - } - - if (message[0]) { - if (sscanf(message, "%d", &maxpl) >= 1) { - if (maxpl < 2 || maxpl > 65535) { - clif_displaymessage(fd, msg_txt(357)); // "Duel: Invalid value." - return 0; - } - duel_create(sd, maxpl); - } else { - target_sd = map_nick2sd((char *)message); - if (target_sd != NULL) { - if ((newduel = duel_create(sd, 2)) != -1) { - if (target_sd->duel_group > 0 || target_sd->duel_invite > 0) { - clif_displaymessage(fd, msg_txt(353)); // "Duel: Player already in duel." - return 0; - } - duel_invite(newduel, sd, target_sd); - clif_displaymessage(fd, msg_txt(354)); // "Duel: Invitation has been sent." - } - } else { - // "Duel: Player not found." - clif_displaymessage(fd, msg_txt(352)); - return 0; - } - } - } else - duel_create(sd, 0); - - return 0; + char output[CHAT_SIZE_MAX]; + unsigned int maxpl=0, newduel; + struct map_session_data *target_sd; + + if(sd->duel_group > 0) { + duel_showinfo(sd->duel_group, sd); + return 0; + } + + if(sd->duel_invite > 0) { + // "Duel: @duel without @reject." + clif_displaymessage(fd, msg_txt(355)); + return 0; + } + + if(!duel_checktime(sd)) { + // "Duel: You can take part in duel only one time per %d minutes." + sprintf(output, msg_txt(356), battle_config.duel_time_interval); + clif_displaymessage(fd, output); + return 0; + } + + if( message[0] ) { + if(sscanf(message, "%d", &maxpl) >= 1) { + if(maxpl < 2 || maxpl > 65535) { + clif_displaymessage(fd, msg_txt(357)); // "Duel: Invalid value." + return 0; + } + duel_create(sd, maxpl); + } else { + target_sd = map_nick2sd((char *)message); + if(target_sd != NULL) { + if((newduel = duel_create(sd, 2)) != -1) { + if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) { + clif_displaymessage(fd, msg_txt(353)); // "Duel: Player already in duel." + return 0; + } + duel_invite(newduel, sd, target_sd); + clif_displaymessage(fd, msg_txt(354)); // "Duel: Invitation has been sent." + } + } else { + // "Duel: Player not found." + clif_displaymessage(fd, msg_txt(352)); + return 0; + } + } + } else + duel_create(sd, 0); + + return 0; } ACMD_FUNC(leave) { - if (sd->duel_group <= 0) { - // "Duel: @leave without @duel." - clif_displaymessage(fd, msg_txt(358)); - return 0; - } + if(sd->duel_group <= 0) { + // "Duel: @leave without @duel." + clif_displaymessage(fd, msg_txt(358)); + return 0; + } - duel_leave(sd->duel_group, sd); - clif_displaymessage(fd, msg_txt(359)); // "Duel: You left the duel." - return 0; + duel_leave(sd->duel_group, sd); + clif_displaymessage(fd, msg_txt(359)); // "Duel: You left the duel." + return 0; } ACMD_FUNC(accept) { - char output[CHAT_SIZE_MAX]; + char output[CHAT_SIZE_MAX]; - if (!duel_checktime(sd)) { - // "Duel: You can take part in duel only one time per %d minutes." - sprintf(output, msg_txt(356), battle_config.duel_time_interval); - clif_displaymessage(fd, output); - return 0; - } + if(!duel_checktime(sd)) { + // "Duel: You can take part in duel only one time per %d minutes." + sprintf(output, msg_txt(356), battle_config.duel_time_interval); + clif_displaymessage(fd, output); + return 0; + } - if (sd->duel_invite <= 0) { - // "Duel: @accept without invititation." - clif_displaymessage(fd, msg_txt(360)); - return 0; - } + if(sd->duel_invite <= 0) { + // "Duel: @accept without invititation." + clif_displaymessage(fd, msg_txt(360)); + return 0; + } - if (duel_list[sd->duel_invite].max_players_limit > 0 && duel_list[sd->duel_invite].members_count >= duel_list[sd->duel_invite].max_players_limit) { - // "Duel: Limit of players is reached." - clif_displaymessage(fd, msg_txt(351)); - return 0; - } + if( duel_list[sd->duel_invite].max_players_limit > 0 && duel_list[sd->duel_invite].members_count >= duel_list[sd->duel_invite].max_players_limit ) + { + // "Duel: Limit of players is reached." + clif_displaymessage(fd, msg_txt(351)); + return 0; + } - duel_accept(sd->duel_invite, sd); - // "Duel: Invitation has been accepted." - clif_displaymessage(fd, msg_txt(361)); - return 0; + duel_accept(sd->duel_invite, sd); + // "Duel: Invitation has been accepted." + clif_displaymessage(fd, msg_txt(361)); + return 0; } ACMD_FUNC(reject) { - if (sd->duel_invite <= 0) { - // "Duel: @reject without invititation." - clif_displaymessage(fd, msg_txt(362)); - return 0; - } + if(sd->duel_invite <= 0) { + // "Duel: @reject without invititation." + clif_displaymessage(fd, msg_txt(362)); + return 0; + } - duel_reject(sd->duel_invite, sd); - // "Duel: Invitation has been rejected." - clif_displaymessage(fd, msg_txt(363)); - return 0; + duel_reject(sd->duel_invite, sd); + // "Duel: Invitation has been rejected." + clif_displaymessage(fd, msg_txt(363)); + return 0; } /*=================================== @@ -7746,99 +7863,105 @@ ACMD_FUNC(reject) *-----------------------------------*/ ACMD_FUNC(cash) { - char output[128]; - int value; - int ret=0; - nullpo_retr(-1, sd); - - if (!message || !*message || (value = atoi(message)) == 0) { - clif_displaymessage(fd, msg_txt(1322)); // Please enter an amount. - return -1; - } - - if (!strcmpi(command+1,"cash")) { - if (value > 0) { - if ((ret=pc_getcash(sd, value, 0)) >= 0) { - sprintf(output, msg_txt(505), ret, sd->cashPoints); - clif_disp_onlyself(sd, output, strlen(output)); - } else clif_displaymessage(fd, msg_txt(149)); // Unable to decrease the number/value. - } else { - if ((ret=pc_paycash(sd, -value, 0)) >= 0) { - sprintf(output, msg_txt(410), ret, sd->cashPoints); - clif_disp_onlyself(sd, output, strlen(output)); - } else clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. - } - } else { - // @points - if (value > 0) { - if ((ret=pc_getcash(sd, 0, value)) >= 0) { - sprintf(output, msg_txt(506), ret, sd->kafraPoints); - clif_disp_onlyself(sd, output, strlen(output)); - } else clif_displaymessage(fd, msg_txt(149)); // Unable to decrease the number/value. - } else { - if ((ret=pc_paycash(sd, -value, -value)) >= 0) { - sprintf(output, msg_txt(411), ret, sd->kafraPoints); - clif_disp_onlyself(sd, output, strlen(output)); - } else clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. - } - } - - return 0; + char output[128]; + int value; + int ret=0; + nullpo_retr(-1, sd); + + if( !message || !*message || (value = atoi(message)) == 0 ) { + clif_displaymessage(fd, msg_txt(1322)); // Please enter an amount. + return -1; + } + + if( !strcmpi(command+1,"cash") ) + { + if( value > 0 ) { + if( (ret=pc_getcash(sd, value, 0)) >= 0){ + sprintf(output, msg_txt(505), ret, sd->cashPoints); + clif_disp_onlyself(sd, output, strlen(output)); + } + else clif_displaymessage(fd, msg_txt(149)); // Unable to decrease the number/value. + } else { + if( (ret=pc_paycash(sd, -value, 0)) >= 0){ + sprintf(output, msg_txt(410), ret, sd->cashPoints); + clif_disp_onlyself(sd, output, strlen(output)); + } + else clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + } + } + else + { // @points + if( value > 0 ) { + if( (ret=pc_getcash(sd, 0, value)) >= 0){ + sprintf(output, msg_txt(506), ret, sd->kafraPoints); + clif_disp_onlyself(sd, output, strlen(output)); + } + else clif_displaymessage(fd, msg_txt(149)); // Unable to decrease the number/value. + } else { + if( (ret=pc_paycash(sd, -value, -value)) >= 0){ + sprintf(output, msg_txt(411), ret, sd->kafraPoints); + clif_disp_onlyself(sd, output, strlen(output)); + } + else clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + } + } + + return 0; } // @clone/@slaveclone/@evilclone <playername> [Valaris] ACMD_FUNC(clone) { - int x=0,y=0,flag=0,master=0,i=0; - struct map_session_data *pl_sd=NULL; - - if (!message || !*message) { - clif_displaymessage(sd->fd,msg_txt(1323)); // You must enter a player name or ID. - return 0; - } - - if ((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return 0; - } - - if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { - clif_displaymessage(fd, msg_txt(126)); // Cannot clone a player of higher GM level than yourself. - return 0; - } - - if (strcmpi(command+1, "clone") == 0) - flag = 1; - else if (strcmpi(command+1, "slaveclone") == 0) { - flag = 2; - if (pc_isdead(sd)) { - clif_displaymessage(fd, msg_txt(129+flag*2)); - return 0; - } - master = sd->bl.id; - if (battle_config.atc_slave_clone_limit - && mob_countslave(&sd->bl) >= battle_config.atc_slave_clone_limit) { - clif_displaymessage(fd, msg_txt(127)); // You've reached your slave clones limit. - return 0; - } - } - - do { - x = sd->bl.x + (rnd() % 10 - 5); - y = sd->bl.y + (rnd() % 10 - 5); - } while (map_getcell(sd->bl.m,x,y,CELL_CHKNOPASS) && i++ < 10); - - if (i >= 10) { - x = sd->bl.x; - y = sd->bl.y; - } - - if ((x = mob_clone_spawn(pl_sd, sd->bl.m, x, y, "", master, 0, flag?1:0, 0)) > 0) { - clif_displaymessage(fd, msg_txt(128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned. - return 0; - } - clif_displaymessage(fd, msg_txt(129+flag*2)); // Unable to spawn evil clone. Unable to spawn clone. Unable to spawn slave clone. - return 0; + int x=0,y=0,flag=0,master=0,i=0; + struct map_session_data *pl_sd=NULL; + + if (!message || !*message) { + clif_displaymessage(sd->fd,msg_txt(1323)); // You must enter a player name or ID. + return 0; + } + + if((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) { + clif_displaymessage(fd, msg_txt(3)); // Character not found. + return 0; + } + + if(pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { + clif_displaymessage(fd, msg_txt(126)); // Cannot clone a player of higher GM level than yourself. + return 0; + } + + if (strcmpi(command+1, "clone") == 0) + flag = 1; + else if (strcmpi(command+1, "slaveclone") == 0) { + flag = 2; + if(pc_isdead(sd)){ + clif_displaymessage(fd, msg_txt(129+flag*2)); + return 0; + } + master = sd->bl.id; + if (battle_config.atc_slave_clone_limit + && mob_countslave(&sd->bl) >= battle_config.atc_slave_clone_limit) { + clif_displaymessage(fd, msg_txt(127)); // You've reached your slave clones limit. + return 0; + } + } + + do { + x = sd->bl.x + (rnd() % 10 - 5); + y = sd->bl.y + (rnd() % 10 - 5); + } while (map_getcell(sd->bl.m,x,y,CELL_CHKNOPASS) && i++ < 10); + + if (i >= 10) { + x = sd->bl.x; + y = sd->bl.y; + } + + if((x = mob_clone_spawn(pl_sd, sd->bl.m, x, y, "", master, 0, flag?1:0, 0)) > 0) { + clif_displaymessage(fd, msg_txt(128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned. + return 0; + } + clif_displaymessage(fd, msg_txt(129+flag*2)); // Unable to spawn evil clone. Unable to spawn clone. Unable to spawn slave clone. + return 0; } /*=================================== @@ -7847,50 +7970,50 @@ ACMD_FUNC(clone) *-----------------------------------*/ ACMD_FUNC(main) { - if (message[0]) { - - if (strcmpi(message, "on") == 0) { - if (!sd->state.mainchat) { - sd->state.mainchat = 1; - clif_displaymessage(fd, msg_txt(380)); // Main chat has been activated. - } else { - clif_displaymessage(fd, msg_txt(381)); // Main chat already activated. - } - } else if (strcmpi(message, "off") == 0) { - if (sd->state.mainchat) { - sd->state.mainchat = 0; - clif_displaymessage(fd, msg_txt(382)); // Main chat has been disabled. - } else { - clif_displaymessage(fd, msg_txt(383)); // Main chat already disabled. - } - } else { - if (!sd->state.mainchat) { - sd->state.mainchat = 1; - clif_displaymessage(fd, msg_txt(380)); // Main chat has been activated. - } - if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) { - clif_displaymessage(fd, msg_txt(387)); - return -1; - } - - if (battle_config.min_chat_delay) { - if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) - return 0; - sd->cantalk_tick = gettick() + battle_config.min_chat_delay; - } - - // send the message using inter-server system - intif_main_message(sd, message); - } - - } else { - - if (sd->state.mainchat) - clif_displaymessage(fd, msg_txt(384)); // Main chat currently enabled. Usage: @main <on|off>, @main <message>. - else - clif_displaymessage(fd, msg_txt(385)); // Main chat currently disabled. Usage: @main <on|off>, @main <message>. - } - return 0; + if( message[0] ) { + + if(strcmpi(message, "on") == 0) { + if(!sd->state.mainchat) { + sd->state.mainchat = 1; + clif_displaymessage(fd, msg_txt(380)); // Main chat has been activated. + } else { + clif_displaymessage(fd, msg_txt(381)); // Main chat already activated. + } + } else if(strcmpi(message, "off") == 0) { + if(sd->state.mainchat) { + sd->state.mainchat = 0; + clif_displaymessage(fd, msg_txt(382)); // Main chat has been disabled. + } else { + clif_displaymessage(fd, msg_txt(383)); // Main chat already disabled. + } + } else { + if(!sd->state.mainchat) { + sd->state.mainchat = 1; + clif_displaymessage(fd, msg_txt(380)); // Main chat has been activated. + } + if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) { + clif_displaymessage(fd, msg_txt(387)); + return -1; + } + + if ( battle_config.min_chat_delay ) { + if( DIFF_TICK(sd->cantalk_tick, gettick()) > 0 ) + return 0; + sd->cantalk_tick = gettick() + battle_config.min_chat_delay; + } + + // send the message using inter-server system + intif_main_message( sd, message ); + } + + } else { + + if(sd->state.mainchat) + clif_displaymessage(fd, msg_txt(384)); // Main chat currently enabled. Usage: @main <on|off>, @main <message>. + else + clif_displaymessage(fd, msg_txt(385)); // Main chat currently disabled. Usage: @main <on|off>, @main <message>. + } + return 0; } /*===================================== @@ -7899,15 +8022,15 @@ ACMD_FUNC(main) *-------------------------------------*/ ACMD_FUNC(noask) { - if (sd->state.noask) { - clif_displaymessage(fd, msg_txt(391)); // Autorejecting is deactivated. - sd->state.noask = 0; - } else { - clif_displaymessage(fd, msg_txt(390)); // Autorejecting is activated. - sd->state.noask = 1; - } + if(sd->state.noask) { + clif_displaymessage(fd, msg_txt(391)); // Autorejecting is deactivated. + sd->state.noask = 0; + } else { + clif_displaymessage(fd, msg_txt(390)); // Autorejecting is activated. + sd->state.noask = 1; + } - return 0; + return 0; } /*===================================== @@ -7916,16 +8039,16 @@ ACMD_FUNC(noask) *-------------------------------------*/ ACMD_FUNC(request) { - if (!message || !*message) { - clif_displaymessage(sd->fd,msg_txt(277)); // Usage: @request <petition/message to online GMs>. - return -1; - } + if (!message || !*message) { + clif_displaymessage(sd->fd,msg_txt(277)); // Usage: @request <petition/message to online GMs>. + return -1; + } - sprintf(atcmd_output, msg_txt(278), message); // (@request): %s - intif_wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output); - clif_disp_onlyself(sd, atcmd_output, strlen(atcmd_output)); - clif_displaymessage(sd->fd,msg_txt(279)); // @request sent. - return 0; + sprintf(atcmd_output, msg_txt(278), message); // (@request): %s + intif_wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output); + clif_disp_onlyself(sd, atcmd_output, strlen(atcmd_output)); + clif_displaymessage(sd->fd,msg_txt(279)); // @request sent. + return 0; } /*========================================== @@ -7933,10 +8056,10 @@ ACMD_FUNC(request) *------------------------------------------*/ ACMD_FUNC(feelreset) { - pc_resetfeel(sd); - clif_displaymessage(fd, msg_txt(1324)); // Reset 'Feeling' maps. + pc_resetfeel(sd); + clif_displaymessage(fd, msg_txt(1324)); // Reset 'Feeling' maps. - return 0; + return 0; } /*========================================== @@ -7944,11 +8067,11 @@ ACMD_FUNC(feelreset) *------------------------------------------*/ ACMD_FUNC(auction) { - nullpo_ret(sd); + nullpo_ret(sd); - clif_Auction_openwindow(sd); + clif_Auction_openwindow(sd); - return 0; + return 0; } /*========================================== @@ -7956,62 +8079,69 @@ ACMD_FUNC(auction) *------------------------------------------*/ ACMD_FUNC(ksprotection) { - nullpo_retr(-1,sd); - - if (sd->state.noks) { - sd->state.noks = 0; - clif_displaymessage(fd, msg_txt(1325)); // [ K.S Protection Inactive ] - } else { - if (!message || !*message || !strcmpi(message, "party")) { - // Default is Party - sd->state.noks = 2; - clif_displaymessage(fd, msg_txt(1326)); // [ K.S Protection Active - Option: Party ] - } else if (!strcmpi(message, "self")) { - sd->state.noks = 1; - clif_displaymessage(fd, msg_txt(1327)); // [ K.S Protection Active - Option: Self ] - } else if (!strcmpi(message, "guild")) { - sd->state.noks = 3; - clif_displaymessage(fd, msg_txt(1328)); // [ K.S Protection Active - Option: Guild ] - } else - clif_displaymessage(fd, msg_txt(1329)); // Usage: @noks <self|party|guild> - } - return 0; + nullpo_retr(-1,sd); + + if( sd->state.noks ) { + sd->state.noks = 0; + clif_displaymessage(fd, msg_txt(1325)); // [ K.S Protection Inactive ] + } + else + { + if( !message || !*message || !strcmpi(message, "party") ) + { // Default is Party + sd->state.noks = 2; + clif_displaymessage(fd, msg_txt(1326)); // [ K.S Protection Active - Option: Party ] + } + else if( !strcmpi(message, "self") ) + { + sd->state.noks = 1; + clif_displaymessage(fd, msg_txt(1327)); // [ K.S Protection Active - Option: Self ] + } + else if( !strcmpi(message, "guild") ) + { + sd->state.noks = 3; + clif_displaymessage(fd, msg_txt(1328)); // [ K.S Protection Active - Option: Guild ] + } + else + clif_displaymessage(fd, msg_txt(1329)); // Usage: @noks <self|party|guild> + } + return 0; } /*========================================== * Map Kill Steal Protection Setting *------------------------------------------*/ ACMD_FUNC(allowks) { - nullpo_retr(-1,sd); + nullpo_retr(-1,sd); - if (map[sd->bl.m].flag.allowks) { - map[sd->bl.m].flag.allowks = 0; - clif_displaymessage(fd, msg_txt(1330)); // [ Map K.S Protection Active ] - } else { - map[sd->bl.m].flag.allowks = 1; - clif_displaymessage(fd, msg_txt(1331)); // [ Map K.S Protection Inactive ] - } - return 0; + if( map[sd->bl.m].flag.allowks ) { + map[sd->bl.m].flag.allowks = 0; + clif_displaymessage(fd, msg_txt(1330)); // [ Map K.S Protection Active ] + } else { + map[sd->bl.m].flag.allowks = 1; + clif_displaymessage(fd, msg_txt(1331)); // [ Map K.S Protection Inactive ] + } + return 0; } ACMD_FUNC(resetstat) { - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - pc_resetstate(sd); - sprintf(atcmd_output, msg_txt(207), sd->status.name); - clif_displaymessage(fd, atcmd_output); - return 0; + pc_resetstate(sd); + sprintf(atcmd_output, msg_txt(207), sd->status.name); + clif_displaymessage(fd, atcmd_output); + return 0; } ACMD_FUNC(resetskill) { - nullpo_retr(-1,sd); + nullpo_retr(-1,sd); - pc_resetskill(sd,1); - sprintf(atcmd_output, msg_txt(206), sd->status.name); - clif_displaymessage(fd, atcmd_output); - return 0; + pc_resetskill(sd,1); + sprintf(atcmd_output, msg_txt(206), sd->status.name); + clif_displaymessage(fd, atcmd_output); + return 0; } /*========================================== @@ -8021,262 +8151,289 @@ ACMD_FUNC(resetskill) *------------------------------------------*/ ACMD_FUNC(itemlist) { - int i, j, count, counter; - const char *location; - const struct item *items; - int size; - StringBuf buf; - - nullpo_retr(-1, sd); - - if (strcmp(command+1, "storagelist") == 0) { - location = "storage"; - items = sd->status.storage.items; - size = MAX_STORAGE; - } else if (strcmp(command+1, "cartlist") == 0) { - location = "cart"; - items = sd->status.cart; - size = MAX_CART; - } else if (strcmp(command+1, "itemlist") == 0) { - location = "inventory"; - items = sd->status.inventory; - size = MAX_INVENTORY; - } else - return 1; - - StringBuf_Init(&buf); - - count = 0; // total slots occupied - counter = 0; // total items found - for (i = 0; i < size; ++i) { - const struct item *it = &items[i]; - struct item_data *itd; - - if (it->nameid == 0 || (itd = itemdb_exists(it->nameid)) == NULL) - continue; - - counter += it->amount; - count++; - - if (count == 1) { - StringBuf_Printf(&buf, msg_txt(1332), location, sd->status.name); // ------ %s items list of '%s' ------ - clif_displaymessage(fd, StringBuf_Value(&buf)); - StringBuf_Clear(&buf); - } - - if (it->refine) - StringBuf_Printf(&buf, "%d %s %+d (%s, id: %d)", it->amount, itd->jname, it->refine, itd->name, it->nameid); - else - StringBuf_Printf(&buf, "%d %s (%s, id: %d)", it->amount, itd->jname, itd->name, it->nameid); - - if (it->equip) { - char equipstr[CHAT_SIZE_MAX]; - strcpy(equipstr, msg_txt(1333)); // | equipped: - if (it->equip & EQP_GARMENT) - strcat(equipstr, msg_txt(1334)); // garment, - if (it->equip & EQP_ACC_L) - strcat(equipstr, msg_txt(1335)); // left accessory, - if (it->equip & EQP_ARMOR) - strcat(equipstr, msg_txt(1336)); // body/armor, - if ((it->equip & EQP_ARMS) == EQP_HAND_R) - strcat(equipstr, msg_txt(1337)); // right hand, - if ((it->equip & EQP_ARMS) == EQP_HAND_L) - strcat(equipstr, msg_txt(1338)); // left hand, - if ((it->equip & EQP_ARMS) == EQP_ARMS) - strcat(equipstr, msg_txt(1339)); // both hands, - if (it->equip & EQP_SHOES) - strcat(equipstr, msg_txt(1340)); // feet, - if (it->equip & EQP_ACC_R) - strcat(equipstr, msg_txt(1341)); // right accessory, - if ((it->equip & EQP_HELM) == EQP_HEAD_LOW) - strcat(equipstr, msg_txt(1342)); // lower head, - if ((it->equip & EQP_HELM) == EQP_HEAD_TOP) - strcat(equipstr, msg_txt(1343)); // top head, - if ((it->equip & EQP_HELM) == (EQP_HEAD_LOW|EQP_HEAD_TOP)) - strcat(equipstr, msg_txt(1344)); // lower/top head, - if ((it->equip & EQP_HELM) == EQP_HEAD_MID) - strcat(equipstr, msg_txt(1345)); // mid head, - if ((it->equip & EQP_HELM) == (EQP_HEAD_LOW|EQP_HEAD_MID)) - strcat(equipstr, msg_txt(1346)); // lower/mid head, - if ((it->equip & EQP_HELM) == EQP_HELM) - strcat(equipstr, msg_txt(1347)); // lower/mid/top head, - // remove final ', ' - equipstr[strlen(equipstr) - 2] = '\0'; - StringBuf_AppendStr(&buf, equipstr); - } - - clif_displaymessage(fd, StringBuf_Value(&buf)); - StringBuf_Clear(&buf); - - if (it->card[0] == CARD0_PET) { - // pet egg - if (it->card[3]) - StringBuf_Printf(&buf, msg_txt(1348), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, named) - else - StringBuf_Printf(&buf, msg_txt(1349), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, unnamed) - } else if (it->card[0] == CARD0_FORGE) { - // forged item - StringBuf_Printf(&buf, msg_txt(1350), (unsigned int)MakeDWord(it->card[2], it->card[3]), it->card[1]>>8, it->card[1]&0x0f); // -> (crafted item, creator id: %u, star crumbs %d, element %d) - } else if (it->card[0] == CARD0_CREATE) { - // created item - StringBuf_Printf(&buf, msg_txt(1351), (unsigned int)MakeDWord(it->card[2], it->card[3])); // -> (produced item, creator id: %u) - } else { - // normal item - int counter2 = 0; - - for (j = 0; j < itd->slot; ++j) { - struct item_data *card; - - if (it->card[j] == 0 || (card = itemdb_exists(it->card[j])) == NULL) - continue; - - counter2++; - - if (counter2 == 1) - StringBuf_AppendStr(&buf, msg_txt(1352)); // -> (card(s): - - if (counter2 != 1) - StringBuf_AppendStr(&buf, ", "); - - StringBuf_Printf(&buf, "#%d %s (id: %d)", counter2, card->jname, card->nameid); - } - - if (counter2 > 0) - StringBuf_AppendStr(&buf, ")"); - } - - if (StringBuf_Length(&buf) > 0) - clif_displaymessage(fd, StringBuf_Value(&buf)); - - StringBuf_Clear(&buf); - } - - if (count == 0) - StringBuf_Printf(&buf, msg_txt(1353), location); // No item found in this player's %s. - else - StringBuf_Printf(&buf, msg_txt(1354), counter, count, location); // %d item(s) found in %d %s slots. - - clif_displaymessage(fd, StringBuf_Value(&buf)); - - StringBuf_Destroy(&buf); - - return 0; + int i, j, count, counter; + const char* location; + const struct item* items; + int size; + StringBuf buf; + + nullpo_retr(-1, sd); + + if( strcmp(command+1, "storagelist") == 0 ) + { + location = "storage"; + items = sd->status.storage.items; + size = MAX_STORAGE; + } + else + if( strcmp(command+1, "cartlist") == 0 ) + { + location = "cart"; + items = sd->status.cart; + size = MAX_CART; + } + else + if( strcmp(command+1, "itemlist") == 0 ) + { + location = "inventory"; + items = sd->status.inventory; + size = MAX_INVENTORY; + } + else + return 1; + + StringBuf_Init(&buf); + + count = 0; // total slots occupied + counter = 0; // total items found + for( i = 0; i < size; ++i ) + { + const struct item* it = &items[i]; + struct item_data* itd; + + if( it->nameid == 0 || (itd = itemdb_exists(it->nameid)) == NULL ) + continue; + + counter += it->amount; + count++; + + if( count == 1 ) + { + StringBuf_Printf(&buf, msg_txt(1332), location, sd->status.name); // ------ %s items list of '%s' ------ + clif_displaymessage(fd, StringBuf_Value(&buf)); + StringBuf_Clear(&buf); + } + + if( it->refine ) + StringBuf_Printf(&buf, "%d %s %+d (%s, id: %d)", it->amount, itd->jname, it->refine, itd->name, it->nameid); + else + StringBuf_Printf(&buf, "%d %s (%s, id: %d)", it->amount, itd->jname, itd->name, it->nameid); + + if( it->equip ) + { + char equipstr[CHAT_SIZE_MAX]; + strcpy(equipstr, msg_txt(1333)); // | equipped: + if( it->equip & EQP_GARMENT ) + strcat(equipstr, msg_txt(1334)); // garment, + if( it->equip & EQP_ACC_L ) + strcat(equipstr, msg_txt(1335)); // left accessory, + if( it->equip & EQP_ARMOR ) + strcat(equipstr, msg_txt(1336)); // body/armor, + if( (it->equip & EQP_ARMS) == EQP_HAND_R ) + strcat(equipstr, msg_txt(1337)); // right hand, + if( (it->equip & EQP_ARMS) == EQP_HAND_L ) + strcat(equipstr, msg_txt(1338)); // left hand, + if( (it->equip & EQP_ARMS) == EQP_ARMS ) + strcat(equipstr, msg_txt(1339)); // both hands, + if( it->equip & EQP_SHOES ) + strcat(equipstr, msg_txt(1340)); // feet, + if( it->equip & EQP_ACC_R ) + strcat(equipstr, msg_txt(1341)); // right accessory, + if( (it->equip & EQP_HELM) == EQP_HEAD_LOW ) + strcat(equipstr, msg_txt(1342)); // lower head, + if( (it->equip & EQP_HELM) == EQP_HEAD_TOP ) + strcat(equipstr, msg_txt(1343)); // top head, + if( (it->equip & EQP_HELM) == (EQP_HEAD_LOW|EQP_HEAD_TOP) ) + strcat(equipstr, msg_txt(1344)); // lower/top head, + if( (it->equip & EQP_HELM) == EQP_HEAD_MID ) + strcat(equipstr, msg_txt(1345)); // mid head, + if( (it->equip & EQP_HELM) == (EQP_HEAD_LOW|EQP_HEAD_MID) ) + strcat(equipstr, msg_txt(1346)); // lower/mid head, + if( (it->equip & EQP_HELM) == EQP_HELM ) + strcat(equipstr, msg_txt(1347)); // lower/mid/top head, + // remove final ', ' + equipstr[strlen(equipstr) - 2] = '\0'; + StringBuf_AppendStr(&buf, equipstr); + } + + clif_displaymessage(fd, StringBuf_Value(&buf)); + StringBuf_Clear(&buf); + + if( it->card[0] == CARD0_PET ) + {// pet egg + if (it->card[3]) + StringBuf_Printf(&buf, msg_txt(1348), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, named) + else + StringBuf_Printf(&buf, msg_txt(1349), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, unnamed) + } + else + if(it->card[0] == CARD0_FORGE) + {// forged item + StringBuf_Printf(&buf, msg_txt(1350), (unsigned int)MakeDWord(it->card[2], it->card[3]), it->card[1]>>8, it->card[1]&0x0f); // -> (crafted item, creator id: %u, star crumbs %d, element %d) + } + else + if(it->card[0] == CARD0_CREATE) + {// created item + StringBuf_Printf(&buf, msg_txt(1351), (unsigned int)MakeDWord(it->card[2], it->card[3])); // -> (produced item, creator id: %u) + } + else + {// normal item + int counter2 = 0; + + for( j = 0; j < itd->slot; ++j ) + { + struct item_data* card; + + if( it->card[j] == 0 || (card = itemdb_exists(it->card[j])) == NULL ) + continue; + + counter2++; + + if( counter2 == 1 ) + StringBuf_AppendStr(&buf, msg_txt(1352)); // -> (card(s): + + if( counter2 != 1 ) + StringBuf_AppendStr(&buf, ", "); + + StringBuf_Printf(&buf, "#%d %s (id: %d)", counter2, card->jname, card->nameid); + } + + if( counter2 > 0 ) + StringBuf_AppendStr(&buf, ")"); + } + + if( StringBuf_Length(&buf) > 0 ) + clif_displaymessage(fd, StringBuf_Value(&buf)); + + StringBuf_Clear(&buf); + } + + if( count == 0 ) + StringBuf_Printf(&buf, msg_txt(1353), location); // No item found in this player's %s. + else + StringBuf_Printf(&buf, msg_txt(1354), counter, count, location); // %d item(s) found in %d %s slots. + + clif_displaymessage(fd, StringBuf_Value(&buf)); + + StringBuf_Destroy(&buf); + + return 0; } ACMD_FUNC(stats) { - char job_jobname[100]; - char output[CHAT_SIZE_MAX]; - int i; - struct { - const char *format; - int value; - } output_table[] = { - { "Base Level - %d", 0 }, - { NULL, 0 }, - { "Hp - %d", 0 }, - { "MaxHp - %d", 0 }, - { "Sp - %d", 0 }, - { "MaxSp - %d", 0 }, - { "Str - %3d", 0 }, - { "Agi - %3d", 0 }, - { "Vit - %3d", 0 }, - { "Int - %3d", 0 }, - { "Dex - %3d", 0 }, - { "Luk - %3d", 0 }, - { "Zeny - %d", 0 }, - { "Free SK Points - %d", 0 }, - { "JobChangeLvl (2nd) - %d", 0 }, - { "JobChangeLvl (3rd) - %d", 0 }, - { NULL, 0 } - }; - - memset(job_jobname, '\0', sizeof(job_jobname)); - memset(output, '\0', sizeof(output)); - - //direct array initialization with variables is not standard C compliant. - output_table[0].value = sd->status.base_level; - output_table[1].format = job_jobname; - output_table[1].value = sd->status.job_level; - output_table[2].value = sd->status.hp; - output_table[3].value = sd->status.max_hp; - output_table[4].value = sd->status.sp; - output_table[5].value = sd->status.max_sp; - output_table[6].value = sd->status.str; - output_table[7].value = sd->status.agi; - output_table[8].value = sd->status.vit; - output_table[9].value = sd->status.int_; - output_table[10].value = sd->status.dex; - output_table[11].value = sd->status.luk; - output_table[12].value = sd->status.zeny; - output_table[13].value = sd->status.skill_point; - output_table[14].value = sd->change_level_2nd; - output_table[15].value = sd->change_level_3rd; - - sprintf(job_jobname, "Job - %s %s", job_name(sd->status.class_), "(level %d)"); - sprintf(output, msg_txt(53), sd->status.name); // '%s' stats: - - clif_displaymessage(fd, output); - - for (i = 0; output_table[i].format != NULL; i++) { - sprintf(output, output_table[i].format, output_table[i].value); - clif_displaymessage(fd, output); - } - - return 0; + char job_jobname[100]; + char output[CHAT_SIZE_MAX]; + int i; + struct { + const char* format; + int value; + } output_table[] = { + { "Base Level - %d", 0 }, + { NULL, 0 }, + { "Hp - %d", 0 }, + { "MaxHp - %d", 0 }, + { "Sp - %d", 0 }, + { "MaxSp - %d", 0 }, + { "Str - %3d", 0 }, + { "Agi - %3d", 0 }, + { "Vit - %3d", 0 }, + { "Int - %3d", 0 }, + { "Dex - %3d", 0 }, + { "Luk - %3d", 0 }, + { "Zeny - %d", 0 }, + { "Free SK Points - %d", 0 }, + { "JobChangeLvl (2nd) - %d", 0 }, + { "JobChangeLvl (3rd) - %d", 0 }, + { NULL, 0 } + }; + + memset(job_jobname, '\0', sizeof(job_jobname)); + memset(output, '\0', sizeof(output)); + + //direct array initialization with variables is not standard C compliant. + output_table[0].value = sd->status.base_level; + output_table[1].format = job_jobname; + output_table[1].value = sd->status.job_level; + output_table[2].value = sd->status.hp; + output_table[3].value = sd->status.max_hp; + output_table[4].value = sd->status.sp; + output_table[5].value = sd->status.max_sp; + output_table[6].value = sd->status.str; + output_table[7].value = sd->status.agi; + output_table[8].value = sd->status.vit; + output_table[9].value = sd->status.int_; + output_table[10].value = sd->status.dex; + output_table[11].value = sd->status.luk; + output_table[12].value = sd->status.zeny; + output_table[13].value = sd->status.skill_point; + output_table[14].value = sd->change_level_2nd; + output_table[15].value = sd->change_level_3rd; + + sprintf(job_jobname, "Job - %s %s", job_name(sd->status.class_), "(level %d)"); + sprintf(output, msg_txt(53), sd->status.name); // '%s' stats: + + clif_displaymessage(fd, output); + + for (i = 0; output_table[i].format != NULL; i++) { + sprintf(output, output_table[i].format, output_table[i].value); + clif_displaymessage(fd, output); + } + + return 0; } ACMD_FUNC(delitem) { - char item_name[100]; - int nameid, amount = 0, total, idx; - struct item_data *id; - - nullpo_retr(-1, sd); - - if (!message || !*message || (sscanf(message, "\"%99[^\"]\" %d", item_name, &amount) < 2 && sscanf(message, "%99s %d", item_name, &amount) < 2) || amount < 1) { - clif_displaymessage(fd, msg_txt(1355)); // Please enter an item name/ID, a quantity, and a player name (usage: #delitem <player> <item_name_or_ID> <quantity>). - return -1; - } - - if ((id = itemdb_searchname(item_name)) != NULL || (id = itemdb_exists(atoi(item_name))) != NULL) { - nameid = id->nameid; - } else { - clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. - return -1; - } - - total = amount; - - // delete items - while (amount && (idx = pc_search_inventory(sd, nameid)) != -1) { - int delamount = (amount < sd->status.inventory[idx].amount) ? amount : sd->status.inventory[idx].amount; - - if (sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET) { - // delete pet - intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); - } - pc_delitem(sd, idx, delamount, 0, 0, LOG_TYPE_COMMAND); - - amount-= delamount; - } - - // notify target - sprintf(atcmd_output, msg_txt(113), total-amount); // %d item(s) removed by a GM. - clif_displaymessage(sd->fd, atcmd_output); - - // notify source - if (amount == total) { - clif_displaymessage(fd, msg_txt(116)); // Character does not have the item. - } else if (amount) { - sprintf(atcmd_output, msg_txt(115), total-amount, total-amount, total); // %d item(s) removed. Player had only %d on %d items. - clif_displaymessage(fd, atcmd_output); - } else { - sprintf(atcmd_output, msg_txt(114), total); // %d item(s) removed from the player. - clif_displaymessage(fd, atcmd_output); - } - - return 0; + char item_name[100]; + int nameid, amount = 0, total, idx; + struct item_data* id; + + nullpo_retr(-1, sd); + + if( !message || !*message || ( sscanf(message, "\"%99[^\"]\" %d", item_name, &amount) < 2 && sscanf(message, "%99s %d", item_name, &amount) < 2 ) || amount < 1 ) + { + clif_displaymessage(fd, msg_txt(1355)); // Please enter an item name/ID, a quantity, and a player name (usage: #delitem <player> <item_name_or_ID> <quantity>). + return -1; + } + + if( ( id = itemdb_searchname(item_name) ) != NULL || ( id = itemdb_exists(atoi(item_name)) ) != NULL ) + { + nameid = id->nameid; + } + else + { + clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. + return -1; + } + + total = amount; + + // delete items + while( amount && ( idx = pc_search_inventory(sd, nameid) ) != -1 ) + { + int delamount = ( amount < sd->status.inventory[idx].amount ) ? amount : sd->status.inventory[idx].amount; + + if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) + {// delete pet + intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); + } + pc_delitem(sd, idx, delamount, 0, 0, LOG_TYPE_COMMAND); + + amount-= delamount; + } + + // notify target + sprintf(atcmd_output, msg_txt(113), total-amount); // %d item(s) removed by a GM. + clif_displaymessage(sd->fd, atcmd_output); + + // notify source + if( amount == total ) + { + clif_displaymessage(fd, msg_txt(116)); // Character does not have the item. + } + else if( amount ) + { + sprintf(atcmd_output, msg_txt(115), total-amount, total-amount, total); // %d item(s) removed. Player had only %d on %d items. + clif_displaymessage(fd, atcmd_output); + } + else + { + sprintf(atcmd_output, msg_txt(114), total); // %d item(s) removed from the player. + clif_displaymessage(fd, atcmd_output); + } + + return 0; } /*========================================== @@ -8284,86 +8441,94 @@ ACMD_FUNC(delitem) *------------------------------------------*/ ACMD_FUNC(font) { - int font_id; - nullpo_retr(-1,sd); - - font_id = atoi(message); - if (font_id == 0) { - if (sd->user_font) { - sd->user_font = 0; - clif_displaymessage(fd, msg_txt(1356)); // Returning to normal font. - clif_font(sd); - } else { - clif_displaymessage(fd, msg_txt(1357)); // Use @font <1-9> to change your message font. - clif_displaymessage(fd, msg_txt(1358)); // Use 0 or no parameter to return to normal font. - } - } else if (font_id < 0 || font_id > 9) - clif_displaymessage(fd, msg_txt(1359)); // Invalid font. Use a value from 0 to 9. - else if (font_id != sd->user_font) { - sd->user_font = font_id; - clif_font(sd); - clif_displaymessage(fd, msg_txt(1360)); // Font changed. - } else - clif_displaymessage(fd, msg_txt(1361)); // Already using this font. - - return 0; + int font_id; + nullpo_retr(-1,sd); + + font_id = atoi(message); + if( font_id == 0 ) + { + if( sd->user_font ) + { + sd->user_font = 0; + clif_displaymessage(fd, msg_txt(1356)); // Returning to normal font. + clif_font(sd); + } + else + { + clif_displaymessage(fd, msg_txt(1357)); // Use @font <1-9> to change your message font. + clif_displaymessage(fd, msg_txt(1358)); // Use 0 or no parameter to return to normal font. + } + } + else if( font_id < 0 || font_id > 9 ) + clif_displaymessage(fd, msg_txt(1359)); // Invalid font. Use a value from 0 to 9. + else if( font_id != sd->user_font ) + { + sd->user_font = font_id; + clif_font(sd); + clif_displaymessage(fd, msg_txt(1360)); // Font changed. + } + else + clif_displaymessage(fd, msg_txt(1361)); // Already using this font. + + return 0; } /*========================================== * type: 1 = commands (@), 2 = charcommands (#) *------------------------------------------*/ -static void atcommand_commands_sub(struct map_session_data *sd, const int fd, AtCommandType type) +static void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommandType type) { - char line_buff[CHATBOX_SIZE]; - char *cur = line_buff; - AtCommandInfo *cmd; - DBIterator *iter = db_iterator(atcommand_db); - int count = 0; + char line_buff[CHATBOX_SIZE]; + char* cur = line_buff; + AtCommandInfo* cmd; + DBIterator *iter = db_iterator(atcommand_db); + int count = 0; - memset(line_buff,' ',CHATBOX_SIZE); - line_buff[CHATBOX_SIZE-1] = 0; + memset(line_buff,' ',CHATBOX_SIZE); + line_buff[CHATBOX_SIZE-1] = 0; - clif_displaymessage(fd, msg_txt(273)); // "Commands available:" + clif_displaymessage(fd, msg_txt(273)); // "Commands available:" - for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) { - unsigned int slen = 0; + for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) { + unsigned int slen = 0; - switch (type) { - case COMMAND_CHARCOMMAND: - if (cmd->char_groups[sd->group_pos] == 0) - continue; - break; - case COMMAND_ATCOMMAND: - if (cmd->at_groups[sd->group_pos] == 0) - continue; - break; - default: - continue; - } + switch( type ) { + case COMMAND_CHARCOMMAND: + if( cmd->char_groups[sd->group_pos] == 0 ) + continue; + break; + case COMMAND_ATCOMMAND: + if( cmd->at_groups[sd->group_pos] == 0 ) + continue; + break; + default: + continue; + } - slen = strlen(cmd->command); + slen = strlen(cmd->command); - // flush the text buffer if this command won't fit into it - if (slen + cur - line_buff >= CHATBOX_SIZE) { - clif_displaymessage(fd,line_buff); - cur = line_buff; - memset(line_buff,' ',CHATBOX_SIZE); - line_buff[CHATBOX_SIZE-1] = 0; - } + // flush the text buffer if this command won't fit into it + if ( slen + cur - line_buff >= CHATBOX_SIZE ) + { + clif_displaymessage(fd,line_buff); + cur = line_buff; + memset(line_buff,' ',CHATBOX_SIZE); + line_buff[CHATBOX_SIZE-1] = 0; + } - memcpy(cur,cmd->command,slen); - cur += slen+(10-slen%10); + memcpy(cur,cmd->command,slen); + cur += slen+(10-slen%10); - count++; - } - dbi_destroy(iter); - clif_displaymessage(fd,line_buff); + count++; + } + dbi_destroy(iter); + clif_displaymessage(fd,line_buff); - sprintf(atcmd_output, msg_txt(274), count); // "%d commands found." - clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(274), count); // "%d commands found." + clif_displaymessage(fd, atcmd_output); - return; + return; } /*========================================== @@ -8371,8 +8536,8 @@ static void atcommand_commands_sub(struct map_session_data *sd, const int fd, At *------------------------------------------*/ ACMD_FUNC(commands) { - atcommand_commands_sub(sd, fd, COMMAND_ATCOMMAND); - return 0; + atcommand_commands_sub(sd, fd, COMMAND_ATCOMMAND); + return 0; } /*========================================== @@ -8380,275 +8545,268 @@ ACMD_FUNC(commands) *------------------------------------------*/ ACMD_FUNC(charcommands) { - atcommand_commands_sub(sd, fd, COMMAND_CHARCOMMAND); - return 0; + atcommand_commands_sub(sd, fd, COMMAND_CHARCOMMAND); + return 0; } /* for new mounts */ -ACMD_FUNC(mount2) -{ +ACMD_FUNC(mount2) { - clif_displaymessage(sd->fd,msg_txt(1362)); // NOTICE: If you crash with mount your LUA is outdated. - if (!(sd->sc.option&OPTION_MOUNTING)) { - clif_displaymessage(sd->fd,msg_txt(1363)); // You have mounted. - pc_setoption(sd, sd->sc.option|OPTION_MOUNTING); - } else { - clif_displaymessage(sd->fd,msg_txt(1364)); // You have released your mount. - pc_setoption(sd, sd->sc.option&~OPTION_MOUNTING); - } - return 0; + clif_displaymessage(sd->fd,msg_txt(1362)); // NOTICE: If you crash with mount your LUA is outdated. + if( !(sd->sc.option&OPTION_MOUNTING) ) { + clif_displaymessage(sd->fd,msg_txt(1363)); // You have mounted. + pc_setoption(sd, sd->sc.option|OPTION_MOUNTING); + } else { + clif_displaymessage(sd->fd,msg_txt(1364)); // You have released your mount. + pc_setoption(sd, sd->sc.option&~OPTION_MOUNTING); + } + return 0; } -ACMD_FUNC(accinfo) -{ - char query[NAME_LENGTH]; +ACMD_FUNC(accinfo) { + char query[NAME_LENGTH]; - if (!message || !*message || strlen(message) > NAME_LENGTH) { - clif_displaymessage(fd, msg_txt(1365)); // Usage: @accinfo/@accountinfo <account_id/char name> - clif_displaymessage(fd, msg_txt(1366)); // You may search partial name by making use of '%' in the search, ex. "@accinfo %Mario%" lists all characters whose name contains "Mario". - return -1; - } + if (!message || !*message || strlen(message) > NAME_LENGTH ) { + clif_displaymessage(fd, msg_txt(1365)); // Usage: @accinfo/@accountinfo <account_id/char name> + clif_displaymessage(fd, msg_txt(1366)); // You may search partial name by making use of '%' in the search, ex. "@accinfo %Mario%" lists all characters whose name contains "Mario". + return -1; + } - //remove const type - safestrncpy(query, message, NAME_LENGTH); + //remove const type + safestrncpy(query, message, NAME_LENGTH); - intif_request_accinfo(sd->fd, sd->bl.id, sd->group_id, query); + intif_request_accinfo( sd->fd, sd->bl.id, sd->group_id, query ); - return 0; + return 0; } /* [Ind] */ -ACMD_FUNC(set) -{ - char reg[32], val[128]; - struct script_data *data; - int toset = 0; - bool is_str = false; - - if (!message || !*message || (toset = sscanf(message, "%32s %128[^\n]s", reg, val)) < 1) { - clif_displaymessage(fd, msg_txt(1367)); // Usage: @set <variable name> <value> - clif_displaymessage(fd, msg_txt(1368)); // Usage: ex. "@set PoringCharVar 50" - clif_displaymessage(fd, msg_txt(1369)); // Usage: ex. "@set PoringCharVarSTR$ Super Duper String" - clif_displaymessage(fd, msg_txt(1370)); // Usage: ex. "@set PoringCharVarSTR$" outputs its value, Super Duper String. - return -1; - } - - /* disabled variable types (they require a proper script state to function, so allowing them would crash the server) */ - if (reg[0] == '.') { - clif_displaymessage(fd, msg_txt(1371)); // NPC variables may not be used with @set. - return -1; - } else if (reg[0] == '\'') { - clif_displaymessage(fd, msg_txt(1372)); // Instance variables may not be used with @set. - return -1; - } - - is_str = (reg[strlen(reg) - 1] == '$') ? true : false; - - if (toset >= 2) { /* we only set the var if there is an val, otherwise we only output the value */ - if (is_str) - set_var(sd, reg, (void *) val); - else - set_var(sd, reg, (void *)__64BPRTSIZE((int)(atoi(val)))); - - } - - CREATE(data, struct script_data,1); - - - if (is_str) { // string variable - - switch (reg[0]) { - case '@': - data->u.str = pc_readregstr(sd, add_str(reg)); - break; - case '$': - data->u.str = mapreg_readregstr(add_str(reg)); - break; - case '#': - if (reg[1] == '#') - data->u.str = pc_readaccountreg2str(sd, reg);// global - else - data->u.str = pc_readaccountregstr(sd, reg);// local - break; - default: - data->u.str = pc_readglobalreg_str(sd, reg); - break; - } - - if (data->u.str == NULL || data->u.str[0] == '\0') { // empty string - data->type = C_CONSTSTR; - data->u.str = ""; - } else {// duplicate string - data->type = C_STR; - data->u.str = aStrdup(data->u.str); - } - - } else {// integer variable - - data->type = C_INT; - switch (reg[0]) { - case '@': - data->u.num = pc_readreg(sd, add_str(reg)); - break; - case '$': - data->u.num = mapreg_readreg(add_str(reg)); - break; - case '#': - if (reg[1] == '#') - data->u.num = pc_readaccountreg2(sd, reg);// global - else - data->u.num = pc_readaccountreg(sd, reg);// local - break; - default: - data->u.num = pc_readglobalreg(sd, reg); - break; - } - - } - - - switch (data->type) { - case C_INT: - sprintf(atcmd_output,msg_txt(1373),reg,data->u.num); // %s value is now :%d - break; - case C_STR: - sprintf(atcmd_output,msg_txt(1374),reg,data->u.str); // %s value is now :%s - break; - case C_CONSTSTR: - sprintf(atcmd_output,msg_txt(1375),reg); // %s is empty - break; - default: - sprintf(atcmd_output,msg_txt(1376),reg,data->type); // %s data type is not supported :%u - break; - } - - clif_displaymessage(fd, atcmd_output); - - aFree(data); - - return 0; -} -ACMD_FUNC(reloadquestdb) -{ - do_reload_quest(); - clif_displaymessage(fd, msg_txt(1377)); // Quest database has been reloaded. - return 0; -} -ACMD_FUNC(addperm) -{ - int perm_size = ARRAYLENGTH(pc_g_permission_name); - bool add = (strcmpi(command+1, "addperm") == 0) ? true : false; - int i; - - if (!message || !*message) { - sprintf(atcmd_output, msg_txt(1378),command); // Usage: %s <permission_name> - clif_displaymessage(fd, atcmd_output); - clif_displaymessage(fd, msg_txt(1379)); // -- Permission List - for (i = 0; i < perm_size; i++) { - sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); - clif_displaymessage(fd, atcmd_output); - } - return -1; - } - - ARR_FIND(0, perm_size, i, strcmpi(pc_g_permission_name[i].name, message) == 0); - - if (i == perm_size) { - sprintf(atcmd_output,msg_txt(1380),message); // '%s' is not a known permission. - clif_displaymessage(fd, atcmd_output); - clif_displaymessage(fd, msg_txt(1379)); // -- Permission List - for (i = 0; i < perm_size; i++) { - sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); - clif_displaymessage(fd, atcmd_output); - } - return -1; - } - - if (add && (sd->permissions&pc_g_permission_name[i].permission)) { - sprintf(atcmd_output, msg_txt(1381),sd->status.name,pc_g_permission_name[i].name); // User '%s' already possesses the '%s' permission. - clif_displaymessage(fd, atcmd_output); - return -1; - } else if (!add && !(sd->permissions&pc_g_permission_name[i].permission)) { - sprintf(atcmd_output, msg_txt(1382),sd->status.name,pc_g_permission_name[i].name); // User '%s' doesn't possess the '%s' permission. - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output,msg_txt(1383),sd->status.name); // -- User '%s' Permissions - clif_displaymessage(fd, atcmd_output); - for (i = 0; i < perm_size; i++) { - if (sd->permissions&pc_g_permission_name[i].permission) { - sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); - clif_displaymessage(fd, atcmd_output); - } - } - - return -1; - } - - if (add) - sd->permissions |= pc_g_permission_name[i].permission; - else - sd->permissions &=~ pc_g_permission_name[i].permission; - - - sprintf(atcmd_output, msg_txt(1384),sd->status.name); // User '%s' permissions updated successfully. The changes are temporary. - clif_displaymessage(fd, atcmd_output); - - return 0; -} -ACMD_FUNC(unloadnpcfile) -{ - - if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1385)); // Usage: @unloadnpcfile <file name> - return -1; - } - - if (npc_unloadfile(message)) - clif_displaymessage(fd, msg_txt(1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed. - else { - clif_displaymessage(fd, msg_txt(1387)); // File not found. - return -1; - } - return 0; -} -ACMD_FUNC(cart) -{ +ACMD_FUNC(set) { + char reg[32], val[128]; + struct script_data* data; + int toset = 0; + bool is_str = false; + + if( !message || !*message || (toset = sscanf(message, "%32s %128[^\n]s", reg, val)) < 1 ) { + clif_displaymessage(fd, msg_txt(1367)); // Usage: @set <variable name> <value> + clif_displaymessage(fd, msg_txt(1368)); // Usage: ex. "@set PoringCharVar 50" + clif_displaymessage(fd, msg_txt(1369)); // Usage: ex. "@set PoringCharVarSTR$ Super Duper String" + clif_displaymessage(fd, msg_txt(1370)); // Usage: ex. "@set PoringCharVarSTR$" outputs its value, Super Duper String. + return -1; + } + + /* disabled variable types (they require a proper script state to function, so allowing them would crash the server) */ + if( reg[0] == '.' ) { + clif_displaymessage(fd, msg_txt(1371)); // NPC variables may not be used with @set. + return -1; + } else if( reg[0] == '\'' ) { + clif_displaymessage(fd, msg_txt(1372)); // Instance variables may not be used with @set. + return -1; + } + + is_str = ( reg[strlen(reg) - 1] == '$' ) ? true : false; + + if( toset >= 2 ) {/* we only set the var if there is an val, otherwise we only output the value */ + if( is_str ) + set_var(sd, reg, (void*) val); + else + set_var(sd, reg, (void*)__64BPRTSIZE((int)(atoi(val)))); + + } + + CREATE(data, struct script_data,1); + + + if( is_str ) {// string variable + + switch( reg[0] ) { + case '@': + data->u.str = pc_readregstr(sd, add_str(reg)); + break; + case '$': + data->u.str = mapreg_readregstr(add_str(reg)); + break; + case '#': + if( reg[1] == '#' ) + data->u.str = pc_readaccountreg2str(sd, reg);// global + else + data->u.str = pc_readaccountregstr(sd, reg);// local + break; + default: + data->u.str = pc_readglobalreg_str(sd, reg); + break; + } + + if( data->u.str == NULL || data->u.str[0] == '\0' ) {// empty string + data->type = C_CONSTSTR; + data->u.str = ""; + } else {// duplicate string + data->type = C_STR; + data->u.str = aStrdup(data->u.str); + } + + } else {// integer variable + + data->type = C_INT; + switch( reg[0] ) { + case '@': + data->u.num = pc_readreg(sd, add_str(reg)); + break; + case '$': + data->u.num = mapreg_readreg(add_str(reg)); + break; + case '#': + if( reg[1] == '#' ) + data->u.num = pc_readaccountreg2(sd, reg);// global + else + data->u.num = pc_readaccountreg(sd, reg);// local + break; + default: + data->u.num = pc_readglobalreg(sd, reg); + break; + } + + } + + + switch( data->type ) { + case C_INT: + sprintf(atcmd_output,msg_txt(1373),reg,data->u.num); // %s value is now :%d + break; + case C_STR: + sprintf(atcmd_output,msg_txt(1374),reg,data->u.str); // %s value is now :%s + break; + case C_CONSTSTR: + sprintf(atcmd_output,msg_txt(1375),reg); // %s is empty + break; + default: + sprintf(atcmd_output,msg_txt(1376),reg,data->type); // %s data type is not supported :%u + break; + } + + clif_displaymessage(fd, atcmd_output); + + aFree(data); + + return 0; +} +ACMD_FUNC(reloadquestdb) { + do_reload_quest(); + clif_displaymessage(fd, msg_txt(1377)); // Quest database has been reloaded. + return 0; +} +ACMD_FUNC(addperm) { + int perm_size = ARRAYLENGTH(pc_g_permission_name); + bool add = (strcmpi(command+1, "addperm") == 0) ? true : false; + int i; + + if( !message || !*message ) { + sprintf(atcmd_output, msg_txt(1378),command); // Usage: %s <permission_name> + clif_displaymessage(fd, atcmd_output); + clif_displaymessage(fd, msg_txt(1379)); // -- Permission List + for( i = 0; i < perm_size; i++ ) { + sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); + clif_displaymessage(fd, atcmd_output); + } + return -1; + } + + ARR_FIND(0, perm_size, i, strcmpi(pc_g_permission_name[i].name, message) == 0); + + if( i == perm_size ) { + sprintf(atcmd_output,msg_txt(1380),message); // '%s' is not a known permission. + clif_displaymessage(fd, atcmd_output); + clif_displaymessage(fd, msg_txt(1379)); // -- Permission List + for( i = 0; i < perm_size; i++ ) { + sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); + clif_displaymessage(fd, atcmd_output); + } + return -1; + } + + if( add && (sd->permissions&pc_g_permission_name[i].permission) ) { + sprintf(atcmd_output, msg_txt(1381),sd->status.name,pc_g_permission_name[i].name); // User '%s' already possesses the '%s' permission. + clif_displaymessage(fd, atcmd_output); + return -1; + } else if ( !add && !(sd->permissions&pc_g_permission_name[i].permission) ) { + sprintf(atcmd_output, msg_txt(1382),sd->status.name,pc_g_permission_name[i].name); // User '%s' doesn't possess the '%s' permission. + clif_displaymessage(fd, atcmd_output); + sprintf(atcmd_output,msg_txt(1383),sd->status.name); // -- User '%s' Permissions + clif_displaymessage(fd, atcmd_output); + for( i = 0; i < perm_size; i++ ) { + if( sd->permissions&pc_g_permission_name[i].permission ) { + sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); + clif_displaymessage(fd, atcmd_output); + } + } + + return -1; + } + + if( add ) + sd->permissions |= pc_g_permission_name[i].permission; + else + sd->permissions &=~ pc_g_permission_name[i].permission; + + + sprintf(atcmd_output, msg_txt(1384),sd->status.name); // User '%s' permissions updated successfully. The changes are temporary. + clif_displaymessage(fd, atcmd_output); + + return 0; +} +ACMD_FUNC(unloadnpcfile) { + + if( !message || !*message ) { + clif_displaymessage(fd, msg_txt(1385)); // Usage: @unloadnpcfile <file name> + return -1; + } + + if( npc_unloadfile(message) ) + clif_displaymessage(fd, msg_txt(1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed. + else { + clif_displaymessage(fd, msg_txt(1387)); // File not found. + return -1; + } + return 0; +} +ACMD_FUNC(cart) { #define MC_CART_MDFY(x) \ - sd->status.skill[MC_PUSHCART].id = x?MC_PUSHCART:0; \ - sd->status.skill[MC_PUSHCART].lv = x?1:0; \ - sd->status.skill[MC_PUSHCART].flag = x?1:0; + sd->status.skill[MC_PUSHCART].id = x?MC_PUSHCART:0; \ + sd->status.skill[MC_PUSHCART].lv = x?1:0; \ + sd->status.skill[MC_PUSHCART].flag = x?1:0; - int val = atoi(message); - bool need_skill = pc_checkskill(sd, MC_PUSHCART) ? false : true; + int val = atoi(message); + bool need_skill = pc_checkskill(sd, MC_PUSHCART) ? false : true; - if (!message || !*message || val < 0 || val > MAX_CARTS) { - sprintf(atcmd_output, msg_txt(1390),command,MAX_CARTS); // Unknown Cart (usage: %s <0-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; - } + if( !message || !*message || val < 0 || val > MAX_CARTS ) { + sprintf(atcmd_output, msg_txt(1390),command,MAX_CARTS); // Unknown Cart (usage: %s <0-%d>). + clif_displaymessage(fd, atcmd_output); + return -1; + } - if (val == 0 && !pc_iscarton(sd)) { - clif_displaymessage(fd, msg_txt(1391)); // You do not possess a cart to be removed - return -1; - } + if( val == 0 && !pc_iscarton(sd) ) { + clif_displaymessage(fd, msg_txt(1391)); // You do not possess a cart to be removed + return -1; + } - if (need_skill) { - MC_CART_MDFY(1); - } + if( need_skill ) { + MC_CART_MDFY(1); + } - if (pc_setcart(sd, val)) { - if (need_skill) { - MC_CART_MDFY(0); - } - return -1;/* @cart failed */ - } + if( pc_setcart(sd, val) ) { + if( need_skill ) { + MC_CART_MDFY(0); + } + return -1;/* @cart failed */ + } - if (need_skill) { - MC_CART_MDFY(0); - } + if( need_skill ) { + MC_CART_MDFY(0); + } - clif_displaymessage(fd, msg_txt(1392)); // Cart Added + clif_displaymessage(fd, msg_txt(1392)); // Cart Added - return 0; -#undef MC_CART_MDFY + return 0; + #undef MC_CART_MDFY } /** @@ -8656,697 +8814,693 @@ ACMD_FUNC(cart) **/ #define ACMD_DEF(x) { #x, atcommand_ ## x, NULL, NULL } #define ACMD_DEF2(x2, x) { x2, atcommand_ ## x, NULL, NULL } -void atcommand_basecommands(void) -{ - /** - * Command reference list, place the base of your commands here - **/ - AtCommandInfo atcommand_base[] = { - ACMD_DEF2("warp", mapmove), - ACMD_DEF(where), - ACMD_DEF(jumpto), - ACMD_DEF(jump), - ACMD_DEF(who), - ACMD_DEF2("who2", who), - ACMD_DEF2("who3", who), - ACMD_DEF2("whomap", who), - ACMD_DEF2("whomap2", who), - ACMD_DEF2("whomap3", who), - ACMD_DEF(whogm), - ACMD_DEF(save), - ACMD_DEF(load), - ACMD_DEF(speed), - ACMD_DEF(storage), - ACMD_DEF(guildstorage), - ACMD_DEF(option), - ACMD_DEF(hide), // + /hide - ACMD_DEF(jobchange), - ACMD_DEF(kill), - ACMD_DEF(alive), - ACMD_DEF(kami), - ACMD_DEF2("kamib", kami), - ACMD_DEF2("kamic", kami), - ACMD_DEF2("lkami", kami), - ACMD_DEF(heal), - ACMD_DEF(item), - ACMD_DEF(item2), - ACMD_DEF(itemreset), - ACMD_DEF2("blvl", baselevelup), - ACMD_DEF2("jlvl", joblevelup), - ACMD_DEF(help), - ACMD_DEF(pvpoff), - ACMD_DEF(pvpon), - ACMD_DEF(gvgoff), - ACMD_DEF(gvgon), - ACMD_DEF(model), - ACMD_DEF(go), - ACMD_DEF(monster), - ACMD_DEF2("monstersmall", monster), - ACMD_DEF2("monsterbig", monster), - ACMD_DEF(killmonster), - ACMD_DEF2("killmonster2", killmonster), - ACMD_DEF(refine), - ACMD_DEF(produce), - ACMD_DEF(memo), - ACMD_DEF(gat), - ACMD_DEF(displaystatus), - ACMD_DEF2("stpoint", statuspoint), - ACMD_DEF2("skpoint", skillpoint), - ACMD_DEF(zeny), - ACMD_DEF2("str", param), - ACMD_DEF2("agi", param), - ACMD_DEF2("vit", param), - ACMD_DEF2("int", param), - ACMD_DEF2("dex", param), - ACMD_DEF2("luk", param), - ACMD_DEF2("glvl", guildlevelup), - ACMD_DEF(makeegg), - ACMD_DEF(hatch), - ACMD_DEF(petfriendly), - ACMD_DEF(pethungry), - ACMD_DEF(petrename), - ACMD_DEF(recall), // + /recall - ACMD_DEF(night), - ACMD_DEF(day), - ACMD_DEF(doom), - ACMD_DEF(doommap), - ACMD_DEF(raise), - ACMD_DEF(raisemap), - ACMD_DEF(kick), // + right click menu for GM "(name) force to quit" - ACMD_DEF(kickall), - ACMD_DEF(allskill), - ACMD_DEF(questskill), - ACMD_DEF(lostskill), - ACMD_DEF(spiritball), - ACMD_DEF(party), - ACMD_DEF(guild), - ACMD_DEF(agitstart), - ACMD_DEF(agitend), - ACMD_DEF(mapexit), - ACMD_DEF(idsearch), - ACMD_DEF(broadcast), // + /b and /nb - ACMD_DEF(localbroadcast), // + /lb and /nlb - ACMD_DEF(recallall), - ACMD_DEF(reloaditemdb), - ACMD_DEF(reloadmobdb), - ACMD_DEF(reloadskilldb), - ACMD_DEF(reloadscript), - ACMD_DEF(reloadatcommand), - ACMD_DEF(reloadbattleconf), - ACMD_DEF(reloadstatusdb), - ACMD_DEF(reloadpcdb), - ACMD_DEF(reloadmotd), - ACMD_DEF(mapinfo), - ACMD_DEF(dye), - ACMD_DEF2("hairstyle", hair_style), - ACMD_DEF2("haircolor", hair_color), - ACMD_DEF2("allstats", stat_all), - ACMD_DEF2("block", char_block), - ACMD_DEF2("ban", char_ban), - ACMD_DEF2("unblock", char_unblock), - ACMD_DEF2("unban", char_unban), - ACMD_DEF2("mount", mount_peco), - ACMD_DEF(guildspy), - ACMD_DEF(partyspy), - ACMD_DEF(repairall), - ACMD_DEF(guildrecall), - ACMD_DEF(partyrecall), - ACMD_DEF(nuke), - ACMD_DEF(shownpc), - ACMD_DEF(hidenpc), - ACMD_DEF(loadnpc), - ACMD_DEF(unloadnpc), - ACMD_DEF2("time", servertime), - ACMD_DEF(jail), - ACMD_DEF(unjail), - ACMD_DEF(jailfor), - ACMD_DEF(jailtime), - ACMD_DEF(disguise), - ACMD_DEF(undisguise), - ACMD_DEF(email), - ACMD_DEF(effect), - ACMD_DEF(follow), - ACMD_DEF(addwarp), - ACMD_DEF(skillon), - ACMD_DEF(skilloff), - ACMD_DEF(killer), - ACMD_DEF(npcmove), - ACMD_DEF(killable), - ACMD_DEF(dropall), - ACMD_DEF(storeall), - ACMD_DEF(skillid), - ACMD_DEF(useskill), - ACMD_DEF(displayskill), - ACMD_DEF(snow), - ACMD_DEF(sakura), - ACMD_DEF(clouds), - ACMD_DEF(clouds2), - ACMD_DEF(fog), - ACMD_DEF(fireworks), - ACMD_DEF(leaves), - ACMD_DEF(summon), - ACMD_DEF(adjgroup), - ACMD_DEF(trade), - ACMD_DEF(send), - ACMD_DEF(setbattleflag), - ACMD_DEF(unmute), - ACMD_DEF(clearweather), - ACMD_DEF(uptime), - ACMD_DEF(changesex), - ACMD_DEF(mute), - ACMD_DEF(refresh), - ACMD_DEF(identify), - ACMD_DEF(gmotd), - ACMD_DEF(misceffect), - ACMD_DEF(mobsearch), - ACMD_DEF(cleanmap), - ACMD_DEF(cleanarea), - ACMD_DEF(npctalk), - ACMD_DEF(pettalk), - ACMD_DEF(users), - ACMD_DEF(reset), - ACMD_DEF(skilltree), - ACMD_DEF(marry), - ACMD_DEF(divorce), - ACMD_DEF(sound), - ACMD_DEF(undisguiseall), - ACMD_DEF(disguiseall), - ACMD_DEF(changelook), - ACMD_DEF(autoloot), - ACMD_DEF2("alootid", autolootitem), - ACMD_DEF(mobinfo), - ACMD_DEF(exp), - ACMD_DEF(adopt), - ACMD_DEF(version), - ACMD_DEF(mutearea), - ACMD_DEF(rates), - ACMD_DEF(iteminfo), - ACMD_DEF(whodrops), - ACMD_DEF(whereis), - ACMD_DEF(mapflag), - ACMD_DEF(me), - ACMD_DEF(monsterignore), - ACMD_DEF(fakename), - ACMD_DEF(size), - ACMD_DEF(showexp), - ACMD_DEF(showzeny), - ACMD_DEF(showdelay), - ACMD_DEF(autotrade), - ACMD_DEF(changegm), - ACMD_DEF(changeleader), - ACMD_DEF(partyoption), - ACMD_DEF(invite), - ACMD_DEF(duel), - ACMD_DEF(leave), - ACMD_DEF(accept), - ACMD_DEF(reject), - ACMD_DEF(main), - ACMD_DEF(clone), - ACMD_DEF2("slaveclone", clone), - ACMD_DEF2("evilclone", clone), - ACMD_DEF(tonpc), - ACMD_DEF(commands), - ACMD_DEF(noask), - ACMD_DEF(request), - ACMD_DEF(homlevel), - ACMD_DEF(homevolution), - ACMD_DEF(makehomun), - ACMD_DEF(homfriendly), - ACMD_DEF(homhungry), - ACMD_DEF(homtalk), - ACMD_DEF(hominfo), - ACMD_DEF(homstats), - ACMD_DEF(homshuffle), - ACMD_DEF(showmobs), - ACMD_DEF(feelreset), - ACMD_DEF(auction), - ACMD_DEF(mail), - ACMD_DEF2("noks", ksprotection), - ACMD_DEF(allowks), - ACMD_DEF(cash), - ACMD_DEF2("points", cash), - ACMD_DEF(agitstart2), - ACMD_DEF(agitend2), - ACMD_DEF2("skreset", resetskill), - ACMD_DEF2("streset", resetstat), - ACMD_DEF2("storagelist", itemlist), - ACMD_DEF2("cartlist", itemlist), - ACMD_DEF2("itemlist", itemlist), - ACMD_DEF(stats), - ACMD_DEF(delitem), - ACMD_DEF(charcommands), - ACMD_DEF(font), - ACMD_DEF(accinfo), - ACMD_DEF(set), - ACMD_DEF(reloadquestdb), - ACMD_DEF(undisguiseguild), - ACMD_DEF(disguiseguild), - ACMD_DEF(sizeall), - ACMD_DEF(sizeguild), - ACMD_DEF(addperm), - ACMD_DEF2("rmvperm", addperm), - ACMD_DEF(unloadnpcfile), - ACMD_DEF(cart), - ACMD_DEF(mount2) - }; - AtCommandInfo *atcommand; - int i; - - for (i = 0; i < ARRAYLENGTH(atcommand_base); i++) { - if (atcommand_exists(atcommand_base[i].command)) { // Should not happen if atcommand_base[] array is OK - ShowDebug("atcommand_basecommands: duplicate ACMD_DEF for '%s'.\n", atcommand_base[i].command); - continue; - } - CREATE(atcommand, AtCommandInfo, 1); - safestrncpy(atcommand->command, atcommand_base[i].command, sizeof(atcommand->command)); - atcommand->func = atcommand_base[i].func; - strdb_put(atcommand_db, atcommand->command, atcommand); - } - return; +void atcommand_basecommands(void) { + /** + * Command reference list, place the base of your commands here + **/ + AtCommandInfo atcommand_base[] = { + ACMD_DEF2("warp", mapmove), + ACMD_DEF(where), + ACMD_DEF(jumpto), + ACMD_DEF(jump), + ACMD_DEF(who), + ACMD_DEF2("who2", who), + ACMD_DEF2("who3", who), + ACMD_DEF2("whomap", who), + ACMD_DEF2("whomap2", who), + ACMD_DEF2("whomap3", who), + ACMD_DEF(whogm), + ACMD_DEF(save), + ACMD_DEF(load), + ACMD_DEF(speed), + ACMD_DEF(storage), + ACMD_DEF(guildstorage), + ACMD_DEF(option), + ACMD_DEF(hide), // + /hide + ACMD_DEF(jobchange), + ACMD_DEF(kill), + ACMD_DEF(alive), + ACMD_DEF(kami), + ACMD_DEF2("kamib", kami), + ACMD_DEF2("kamic", kami), + ACMD_DEF2("lkami", kami), + ACMD_DEF(heal), + ACMD_DEF(item), + ACMD_DEF(item2), + ACMD_DEF(itemreset), + ACMD_DEF2("blvl", baselevelup), + ACMD_DEF2("jlvl", joblevelup), + ACMD_DEF(help), + ACMD_DEF(pvpoff), + ACMD_DEF(pvpon), + ACMD_DEF(gvgoff), + ACMD_DEF(gvgon), + ACMD_DEF(model), + ACMD_DEF(go), + ACMD_DEF(monster), + ACMD_DEF2("monstersmall", monster), + ACMD_DEF2("monsterbig", monster), + ACMD_DEF(killmonster), + ACMD_DEF2("killmonster2", killmonster), + ACMD_DEF(refine), + ACMD_DEF(produce), + ACMD_DEF(memo), + ACMD_DEF(gat), + ACMD_DEF(displaystatus), + ACMD_DEF2("stpoint", statuspoint), + ACMD_DEF2("skpoint", skillpoint), + ACMD_DEF(zeny), + ACMD_DEF2("str", param), + ACMD_DEF2("agi", param), + ACMD_DEF2("vit", param), + ACMD_DEF2("int", param), + ACMD_DEF2("dex", param), + ACMD_DEF2("luk", param), + ACMD_DEF2("glvl", guildlevelup), + ACMD_DEF(makeegg), + ACMD_DEF(hatch), + ACMD_DEF(petfriendly), + ACMD_DEF(pethungry), + ACMD_DEF(petrename), + ACMD_DEF(recall), // + /recall + ACMD_DEF(night), + ACMD_DEF(day), + ACMD_DEF(doom), + ACMD_DEF(doommap), + ACMD_DEF(raise), + ACMD_DEF(raisemap), + ACMD_DEF(kick), // + right click menu for GM "(name) force to quit" + ACMD_DEF(kickall), + ACMD_DEF(allskill), + ACMD_DEF(questskill), + ACMD_DEF(lostskill), + ACMD_DEF(spiritball), + ACMD_DEF(party), + ACMD_DEF(guild), + ACMD_DEF(agitstart), + ACMD_DEF(agitend), + ACMD_DEF(mapexit), + ACMD_DEF(idsearch), + ACMD_DEF(broadcast), // + /b and /nb + ACMD_DEF(localbroadcast), // + /lb and /nlb + ACMD_DEF(recallall), + ACMD_DEF(reloaditemdb), + ACMD_DEF(reloadmobdb), + ACMD_DEF(reloadskilldb), + ACMD_DEF(reloadscript), + ACMD_DEF(reloadatcommand), + ACMD_DEF(reloadbattleconf), + ACMD_DEF(reloadstatusdb), + ACMD_DEF(reloadpcdb), + ACMD_DEF(reloadmotd), + ACMD_DEF(mapinfo), + ACMD_DEF(dye), + ACMD_DEF2("hairstyle", hair_style), + ACMD_DEF2("haircolor", hair_color), + ACMD_DEF2("allstats", stat_all), + ACMD_DEF2("block", char_block), + ACMD_DEF2("ban", char_ban), + ACMD_DEF2("unblock", char_unblock), + ACMD_DEF2("unban", char_unban), + ACMD_DEF2("mount", mount_peco), + ACMD_DEF(guildspy), + ACMD_DEF(partyspy), + ACMD_DEF(repairall), + ACMD_DEF(guildrecall), + ACMD_DEF(partyrecall), + ACMD_DEF(nuke), + ACMD_DEF(shownpc), + ACMD_DEF(hidenpc), + ACMD_DEF(loadnpc), + ACMD_DEF(unloadnpc), + ACMD_DEF2("time", servertime), + ACMD_DEF(jail), + ACMD_DEF(unjail), + ACMD_DEF(jailfor), + ACMD_DEF(jailtime), + ACMD_DEF(disguise), + ACMD_DEF(undisguise), + ACMD_DEF(email), + ACMD_DEF(effect), + ACMD_DEF(follow), + ACMD_DEF(addwarp), + ACMD_DEF(skillon), + ACMD_DEF(skilloff), + ACMD_DEF(killer), + ACMD_DEF(npcmove), + ACMD_DEF(killable), + ACMD_DEF(dropall), + ACMD_DEF(storeall), + ACMD_DEF(skillid), + ACMD_DEF(useskill), + ACMD_DEF(displayskill), + ACMD_DEF(snow), + ACMD_DEF(sakura), + ACMD_DEF(clouds), + ACMD_DEF(clouds2), + ACMD_DEF(fog), + ACMD_DEF(fireworks), + ACMD_DEF(leaves), + ACMD_DEF(summon), + ACMD_DEF(adjgroup), + ACMD_DEF(trade), + ACMD_DEF(send), + ACMD_DEF(setbattleflag), + ACMD_DEF(unmute), + ACMD_DEF(clearweather), + ACMD_DEF(uptime), + ACMD_DEF(changesex), + ACMD_DEF(mute), + ACMD_DEF(refresh), + ACMD_DEF(identify), + ACMD_DEF(gmotd), + ACMD_DEF(misceffect), + ACMD_DEF(mobsearch), + ACMD_DEF(cleanmap), + ACMD_DEF(npctalk), + ACMD_DEF(pettalk), + ACMD_DEF(users), + ACMD_DEF(reset), + ACMD_DEF(skilltree), + ACMD_DEF(marry), + ACMD_DEF(divorce), + ACMD_DEF(sound), + ACMD_DEF(undisguiseall), + ACMD_DEF(disguiseall), + ACMD_DEF(changelook), + ACMD_DEF(autoloot), + ACMD_DEF2("alootid", autolootitem), + ACMD_DEF(mobinfo), + ACMD_DEF(exp), + ACMD_DEF(adopt), + ACMD_DEF(version), + ACMD_DEF(mutearea), + ACMD_DEF(rates), + ACMD_DEF(iteminfo), + ACMD_DEF(whodrops), + ACMD_DEF(whereis), + ACMD_DEF(mapflag), + ACMD_DEF(me), + ACMD_DEF(monsterignore), + ACMD_DEF(fakename), + ACMD_DEF(size), + ACMD_DEF(showexp), + ACMD_DEF(showzeny), + ACMD_DEF(showdelay), + ACMD_DEF(autotrade), + ACMD_DEF(changegm), + ACMD_DEF(changeleader), + ACMD_DEF(partyoption), + ACMD_DEF(invite), + ACMD_DEF(duel), + ACMD_DEF(leave), + ACMD_DEF(accept), + ACMD_DEF(reject), + ACMD_DEF(main), + ACMD_DEF(clone), + ACMD_DEF2("slaveclone", clone), + ACMD_DEF2("evilclone", clone), + ACMD_DEF(tonpc), + ACMD_DEF(commands), + ACMD_DEF(noask), + ACMD_DEF(request), + ACMD_DEF(homlevel), + ACMD_DEF(homevolution), + ACMD_DEF(makehomun), + ACMD_DEF(homfriendly), + ACMD_DEF(homhungry), + ACMD_DEF(homtalk), + ACMD_DEF(hominfo), + ACMD_DEF(homstats), + ACMD_DEF(homshuffle), + ACMD_DEF(showmobs), + ACMD_DEF(feelreset), + ACMD_DEF(auction), + ACMD_DEF(mail), + ACMD_DEF2("noks", ksprotection), + ACMD_DEF(allowks), + ACMD_DEF(cash), + ACMD_DEF2("points", cash), + ACMD_DEF(agitstart2), + ACMD_DEF(agitend2), + ACMD_DEF2("skreset", resetskill), + ACMD_DEF2("streset", resetstat), + ACMD_DEF2("storagelist", itemlist), + ACMD_DEF2("cartlist", itemlist), + ACMD_DEF2("itemlist", itemlist), + ACMD_DEF(stats), + ACMD_DEF(delitem), + ACMD_DEF(charcommands), + ACMD_DEF(font), + ACMD_DEF(accinfo), + ACMD_DEF(set), + ACMD_DEF(reloadquestdb), + ACMD_DEF(undisguiseguild), + ACMD_DEF(disguiseguild), + ACMD_DEF(sizeall), + ACMD_DEF(sizeguild), + ACMD_DEF(addperm), + ACMD_DEF2("rmvperm", addperm), + ACMD_DEF(unloadnpcfile), + ACMD_DEF(cart), + ACMD_DEF(mount2) + }; + AtCommandInfo* atcommand; + int i; + + for( i = 0; i < ARRAYLENGTH(atcommand_base); i++ ) { + if(atcommand_exists(atcommand_base[i].command)) { // Should not happen if atcommand_base[] array is OK + ShowDebug("atcommand_basecommands: duplicate ACMD_DEF for '%s'.\n", atcommand_base[i].command); + continue; + } + CREATE(atcommand, AtCommandInfo, 1); + safestrncpy(atcommand->command, atcommand_base[i].command, sizeof(atcommand->command)); + atcommand->func = atcommand_base[i].func; + strdb_put(atcommand_db, atcommand->command, atcommand); + } + return; } /*========================================== * Command lookup functions *------------------------------------------*/ -bool atcommand_exists(const char *name) +bool atcommand_exists(const char* name) { - return strdb_exists(atcommand_db, name); + return strdb_exists(atcommand_db, name); } -static AtCommandInfo *get_atcommandinfo_byname(const char *name) +static AtCommandInfo* get_atcommandinfo_byname(const char *name) { - if (strdb_exists(atcommand_db, name)) - return (AtCommandInfo *)strdb_get(atcommand_db, name); - return NULL; + if (strdb_exists(atcommand_db, name)) + return (AtCommandInfo*)strdb_get(atcommand_db, name); + return NULL; } -static const char *atcommand_checkalias(const char *aliasname) +static const char* atcommand_checkalias(const char *aliasname) { - AliasInfo *alias_info = NULL; - if ((alias_info = (AliasInfo *)strdb_get(atcommand_alias_db, aliasname)) != NULL) - return alias_info->command->command; - return aliasname; + AliasInfo *alias_info = NULL; + if ((alias_info = (AliasInfo*)strdb_get(atcommand_alias_db, aliasname)) != NULL) + return alias_info->command->command; + return aliasname; } /// AtCommand suggestion -static void atcommand_get_suggestions(struct map_session_data *sd, const char *name, bool atcommand) -{ - DBIterator *atcommand_iter; - DBIterator *alias_iter; - AtCommandInfo *command_info = NULL; - AliasInfo *alias_info = NULL; - AtCommandType type = atcommand ? COMMAND_ATCOMMAND : COMMAND_CHARCOMMAND; - char *full_match[MAX_SUGGESTIONS]; - char *suggestions[MAX_SUGGESTIONS]; - char *match; - int prefix_count = 0, full_count = 0; - bool can_use; - - if (!battle_config.atcommand_suggestions_enabled) - return; - - atcommand_iter = db_iterator(atcommand_db); - alias_iter = db_iterator(atcommand_alias_db); - - // Build the matches - for (command_info = dbi_first(atcommand_iter); dbi_exists(atcommand_iter); command_info = dbi_next(atcommand_iter)) { - match = strstr(command_info->command, name); - can_use = pc_can_use_command(sd, command_info->command, type); - if (prefix_count < MAX_SUGGESTIONS && match == command_info->command && can_use) { - suggestions[prefix_count] = command_info->command; - ++prefix_count; - } - if (full_count < MAX_SUGGESTIONS && match != NULL && match != command_info->command && can_use) { - full_match[full_count] = command_info->command; - ++full_count; - } - } - - for (alias_info = dbi_first(alias_iter); dbi_exists(alias_iter); alias_info = dbi_next(alias_iter)) { - match = strstr(alias_info->alias, name); - can_use = pc_can_use_command(sd, alias_info->command->command, type); - if (prefix_count < MAX_SUGGESTIONS && match == alias_info->alias && can_use) { - suggestions[prefix_count] = alias_info->alias; - ++prefix_count; - } - if (full_count < MAX_SUGGESTIONS && match != NULL && match != alias_info->alias && can_use) { - full_match[full_count] = alias_info->alias; - ++full_count; - } - } - - if ((full_count+prefix_count) > 0) { - char buffer[512]; - int i; - - // Merge full match and prefix match results - if (prefix_count < MAX_SUGGESTIONS) { - memmove(&suggestions[prefix_count], full_match, sizeof(char *) * (MAX_SUGGESTIONS-prefix_count)); - prefix_count = min(prefix_count+full_count, MAX_SUGGESTIONS); - } - - // Build the suggestion string - strcpy(buffer, msg_txt(205)); - strcat(buffer,"\n"); - - for (i=0; i < prefix_count; ++i) { - strcat(buffer,suggestions[i]); - strcat(buffer," "); - } - - clif_displaymessage(sd->fd, buffer); - } - - dbi_destroy(atcommand_iter); - dbi_destroy(alias_iter); +static void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool atcommand) { + DBIterator* atcommand_iter; + DBIterator* alias_iter; + AtCommandInfo* command_info = NULL; + AliasInfo* alias_info = NULL; + AtCommandType type = atcommand ? COMMAND_ATCOMMAND : COMMAND_CHARCOMMAND; + char* full_match[MAX_SUGGESTIONS]; + char* suggestions[MAX_SUGGESTIONS]; + char* match; + int prefix_count = 0, full_count = 0; + bool can_use; + + if (!battle_config.atcommand_suggestions_enabled) + return; + + atcommand_iter = db_iterator(atcommand_db); + alias_iter = db_iterator(atcommand_alias_db); + + // Build the matches + for (command_info = dbi_first(atcommand_iter); dbi_exists(atcommand_iter); command_info = dbi_next(atcommand_iter)) { + match = strstr(command_info->command, name); + can_use = pc_can_use_command(sd, command_info->command, type); + if ( prefix_count < MAX_SUGGESTIONS && match == command_info->command && can_use ) { + suggestions[prefix_count] = command_info->command; + ++prefix_count; + } + if ( full_count < MAX_SUGGESTIONS && match != NULL && match != command_info->command && can_use ) { + full_match[full_count] = command_info->command; + ++full_count; + } + } + + for (alias_info = dbi_first(alias_iter); dbi_exists(alias_iter); alias_info = dbi_next(alias_iter)) { + match = strstr(alias_info->alias, name); + can_use = pc_can_use_command(sd, alias_info->command->command, type); + if ( prefix_count < MAX_SUGGESTIONS && match == alias_info->alias && can_use) { + suggestions[prefix_count] = alias_info->alias; + ++prefix_count; + } + if ( full_count < MAX_SUGGESTIONS && match != NULL && match != alias_info->alias && can_use ) { + full_match[full_count] = alias_info->alias; + ++full_count; + } + } + + if ((full_count+prefix_count) > 0) { + char buffer[512]; + int i; + + // Merge full match and prefix match results + if (prefix_count < MAX_SUGGESTIONS) { + memmove(&suggestions[prefix_count], full_match, sizeof(char*) * (MAX_SUGGESTIONS-prefix_count)); + prefix_count = min(prefix_count+full_count, MAX_SUGGESTIONS); + } + + // Build the suggestion string + strcpy(buffer, msg_txt(205)); + strcat(buffer,"\n"); + + for(i=0; i < prefix_count; ++i) { + strcat(buffer,suggestions[i]); + strcat(buffer," "); + } + + clif_displaymessage(sd->fd, buffer); + } + + dbi_destroy(atcommand_iter); + dbi_destroy(alias_iter); } /// Executes an at-command. -bool is_atcommand(const int fd, struct map_session_data *sd, const char *message, int type) -{ - char charname[NAME_LENGTH], params[100]; - char charname2[NAME_LENGTH], params2[100]; - char command[100]; - char output[CHAT_SIZE_MAX]; - - //Reconstructed message - char atcmd_msg[CHAT_SIZE_MAX]; - - TBL_PC *ssd = NULL; //sd for target - AtCommandInfo *info; - - nullpo_retr(false, sd); - - //Shouldn't happen - if (!message || !*message) - return false; - - //Block NOCHAT but do not display it as a normal message - if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCOMMAND) - return true; - - // skip 10/11-langtype's codepage indicator, if detected - if (message[0] == '|' && strlen(message) >= 4 && (message[3] == atcommand_symbol || message[3] == charcommand_symbol)) - message += 3; - - //Should display as a normal message - if (*message != atcommand_symbol && *message != charcommand_symbol) - return false; - - // type value 0 = server invoked: bypass restrictions - // 1 = player invoked - if (type == 1) { - //Commands are disabled on maps flagged as 'nocommand' - if (map[sd->bl.m].nocommand && pc_get_group_level(sd) < map[sd->bl.m].nocommand) { - clif_displaymessage(fd, msg_txt(143)); - return false; - } - } - - if (*message == charcommand_symbol) { - do { - int x, y, z; - - //Checks to see if #command has a name or a name + parameters. - x = sscanf(message, "%99s \"%23[^\"]\" %99[^\n]", command, charname, params); - y = sscanf(message, "%99s %23s %99[^\n]", command, charname2, params2); - - //z always has the value of the scan that was successful - z = (x > 1) ? x : y; - - //#command + name means the sufficient target was used and anything else after - //can be looked at by the actual command function since most scan to see if the - //right parameters are used. - if (x > 2) { - sprintf(atcmd_msg, "%s %s", command, params); - break; - } else if (y > 2) { - sprintf(atcmd_msg, "%s %s", command, params2); - break; - } - //Regardless of what style the #command is used, if it's correct, it will always have - //this value if there is no parameter. Send it as just the #command - else if (z == 2) { - sprintf(atcmd_msg, "%s", command); - break; - } - - if (!pc_get_group_level(sd)) { - if (x >= 1 || y >= 1) { /* we have command */ - info = get_atcommandinfo_byname(atcommand_checkalias(command + 1)); - if (!info || info->char_groups[sd->group_pos] == 0) /* if we can't use or doesn't exist: don't even display the command failed message */ - return false; - } else - return false;/* display as normal message */ - } - - sprintf(output, msg_txt(1388), charcommand_symbol); // Charcommand failed (usage: %c<command> <char name> <parameters>). - clif_displaymessage(fd, output); - return true; - } while (0); - } else if (*message == atcommand_symbol) { - //atcmd_msg is constructed above differently for charcommands - //it's copied from message if not a charcommand so it can - //pass through the rest of the code compatible with both symbols - sprintf(atcmd_msg, "%s", message); - } - - //Clearing these to be used once more. - memset(command, '\0', sizeof(command)); - memset(params, '\0', sizeof(params)); - - //check to see if any params exist within this command - if (sscanf(atcmd_msg, "%99s %99[^\n]", command, params) < 2) - params[0] = '\0'; - - // @commands (script based) - if (type == 1 && atcmd_binding_count > 0) { - struct atcmd_binding_data *binding; - - // Check if the command initiated is a character command - if (*message == charcommand_symbol && - (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL) { - sprintf(output, msg_txt(1389), command); // %s failed. Player not found. - clif_displaymessage(fd, output); - return true; - } - - // Get atcommand binding - binding = get_atcommandbind_byname(command); - - // Check if the binding isn't NULL and there is a NPC event, level of usage met, et cetera - if (binding != NULL && binding->npc_event[0] && - ((*atcmd_msg == atcommand_symbol && pc_get_group_level(sd) >= binding->level) || - (*atcmd_msg == charcommand_symbol && pc_get_group_level(sd) >= binding->level2))) { - // Check if self or character invoking; if self == character invoked, then self invoke. - bool invokeFlag = ((*atcmd_msg == atcommand_symbol) ? 1 : 0); - npc_do_atcmd_event((invokeFlag ? sd : ssd), command, params, binding->npc_event); - return true; - } - } - - //Grab the command information and check for the proper GM level required to use it or if the command exists - info = get_atcommandinfo_byname(atcommand_checkalias(command + 1)); - if (info == NULL) { - if (pc_get_group_level(sd)) { // TODO: remove or replace with proper permission - sprintf(output, msg_txt(153), command); // "%s is Unknown Command." - clif_displaymessage(fd, output); - atcommand_get_suggestions(sd, command + 1, *message == atcommand_symbol); - return true; - } else - return false; - } - - // type == 1 : player invoked - if (type == 1) { - if ((*command == atcommand_symbol && info->at_groups[sd->group_pos] == 0) || - (*command == charcommand_symbol && info->char_groups[sd->group_pos] == 0)) { - return false; - } - if (pc_isdead(sd) && pc_has_permission(sd,PC_PERM_DISABLE_CMD_DEAD)) { - clif_displaymessage(fd, msg_txt(1393)); // You can't use commands while dead - return true; - } - } - - // Check if target is valid only if confirmed that player can use command. - if (*message == charcommand_symbol && - (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL) { - sprintf(output, msg_txt(1389), command); // %s failed. Player not found. - clif_displaymessage(fd, output); - return true; - } - - //Attempt to use the command - if ((info->func(fd, (*atcmd_msg == atcommand_symbol) ? sd : ssd, command, params) != 0)) { - sprintf(output,msg_txt(154), command); // %s failed. - clif_displaymessage(fd, output); - return true; - } - - //Log only if successful. - if (*atcmd_msg == atcommand_symbol) - log_atcommand(sd, atcmd_msg); - else if (*atcmd_msg == charcommand_symbol) - log_atcommand(sd, message); - - return true; +bool is_atcommand(const int fd, struct map_session_data* sd, const char* message, int type) +{ + char charname[NAME_LENGTH], params[100]; + char charname2[NAME_LENGTH], params2[100]; + char command[100]; + char output[CHAT_SIZE_MAX]; + + //Reconstructed message + char atcmd_msg[CHAT_SIZE_MAX]; + + TBL_PC * ssd = NULL; //sd for target + AtCommandInfo * info; + + nullpo_retr(false, sd); + + //Shouldn't happen + if ( !message || !*message ) + return false; + + //Block NOCHAT but do not display it as a normal message + if ( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCOMMAND ) + return true; + + // skip 10/11-langtype's codepage indicator, if detected + if ( message[0] == '|' && strlen(message) >= 4 && (message[3] == atcommand_symbol || message[3] == charcommand_symbol) ) + message += 3; + + //Should display as a normal message + if ( *message != atcommand_symbol && *message != charcommand_symbol ) + return false; + + // type value 0 = server invoked: bypass restrictions + // 1 = player invoked + if ( type == 1) { + //Commands are disabled on maps flagged as 'nocommand' + if ( map[sd->bl.m].nocommand && pc_get_group_level(sd) < map[sd->bl.m].nocommand ) { + clif_displaymessage(fd, msg_txt(143)); + return false; + } + } + + if (*message == charcommand_symbol) { + do { + int x, y, z; + + //Checks to see if #command has a name or a name + parameters. + x = sscanf(message, "%99s \"%23[^\"]\" %99[^\n]", command, charname, params); + y = sscanf(message, "%99s %23s %99[^\n]", command, charname2, params2); + + //z always has the value of the scan that was successful + z = ( x > 1 ) ? x : y; + + //#command + name means the sufficient target was used and anything else after + //can be looked at by the actual command function since most scan to see if the + //right parameters are used. + if ( x > 2 ) { + sprintf(atcmd_msg, "%s %s", command, params); + break; + } + else if ( y > 2 ) { + sprintf(atcmd_msg, "%s %s", command, params2); + break; + } + //Regardless of what style the #command is used, if it's correct, it will always have + //this value if there is no parameter. Send it as just the #command + else if ( z == 2 ) { + sprintf(atcmd_msg, "%s", command); + break; + } + + if( !pc_get_group_level(sd) ) { + if( x >= 1 || y >= 1 ) { /* we have command */ + info = get_atcommandinfo_byname(atcommand_checkalias(command + 1)); + if( !info || info->char_groups[sd->group_pos] == 0 ) /* if we can't use or doesn't exist: don't even display the command failed message */ + return false; + } else + return false;/* display as normal message */ + } + + sprintf(output, msg_txt(1388), charcommand_symbol); // Charcommand failed (usage: %c<command> <char name> <parameters>). + clif_displaymessage(fd, output); + return true; + } while(0); + } + else if (*message == atcommand_symbol) { + //atcmd_msg is constructed above differently for charcommands + //it's copied from message if not a charcommand so it can + //pass through the rest of the code compatible with both symbols + sprintf(atcmd_msg, "%s", message); + } + + //Clearing these to be used once more. + memset(command, '\0', sizeof(command)); + memset(params, '\0', sizeof(params)); + + //check to see if any params exist within this command + if( sscanf(atcmd_msg, "%99s %99[^\n]", command, params) < 2 ) + params[0] = '\0'; + + // @commands (script based) + if(type == 1 && atcmd_binding_count > 0) { + struct atcmd_binding_data * binding; + + // Check if the command initiated is a character command + if (*message == charcommand_symbol && + (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL ) { + sprintf(output, msg_txt(1389), command); // %s failed. Player not found. + clif_displaymessage(fd, output); + return true; + } + + // Get atcommand binding + binding = get_atcommandbind_byname(command); + + // Check if the binding isn't NULL and there is a NPC event, level of usage met, et cetera + if( binding != NULL && binding->npc_event[0] && + ((*atcmd_msg == atcommand_symbol && pc_get_group_level(sd) >= binding->level) || + (*atcmd_msg == charcommand_symbol && pc_get_group_level(sd) >= binding->level2))) + { + // Check if self or character invoking; if self == character invoked, then self invoke. + bool invokeFlag = ((*atcmd_msg == atcommand_symbol) ? 1 : 0); + npc_do_atcmd_event((invokeFlag ? sd : ssd), command, params, binding->npc_event); + return true; + } + } + + //Grab the command information and check for the proper GM level required to use it or if the command exists + info = get_atcommandinfo_byname(atcommand_checkalias(command + 1)); + if (info == NULL) { + if( pc_get_group_level(sd) ) { // TODO: remove or replace with proper permission + sprintf(output, msg_txt(153), command); // "%s is Unknown Command." + clif_displaymessage(fd, output); + atcommand_get_suggestions(sd, command + 1, *message == atcommand_symbol); + return true; + } else + return false; + } + + // type == 1 : player invoked + if (type == 1) { + if ((*command == atcommand_symbol && info->at_groups[sd->group_pos] == 0) || + (*command == charcommand_symbol && info->char_groups[sd->group_pos] == 0) ) { + return false; + } + if( pc_isdead(sd) && pc_has_permission(sd,PC_PERM_DISABLE_CMD_DEAD) ) { + clif_displaymessage(fd, msg_txt(1393)); // You can't use commands while dead + return true; + } + } + + // Check if target is valid only if confirmed that player can use command. + if (*message == charcommand_symbol && + (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL ) { + sprintf(output, msg_txt(1389), command); // %s failed. Player not found. + clif_displaymessage(fd, output); + return true; + } + + //Attempt to use the command + if ( (info->func(fd, (*atcmd_msg == atcommand_symbol) ? sd : ssd, command, params) != 0) ) + { + sprintf(output,msg_txt(154), command); // %s failed. + clif_displaymessage(fd, output); + return true; + } + + //Log only if successful. + if ( *atcmd_msg == atcommand_symbol ) + log_atcommand(sd, atcmd_msg); + else if ( *atcmd_msg == charcommand_symbol ) + log_atcommand(sd, message); + + return true; } /*========================================== * *------------------------------------------*/ -static void atcommand_config_read(const char *config_filename) -{ - config_setting_t *aliases = NULL, *help = NULL; - const char *symbol = NULL; - int num_aliases = 0; - - if (conf_read_file(&atcommand_config, config_filename)) - return; - - // Command symbols - if (config_lookup_string(&atcommand_config, "atcommand_symbol", &symbol)) { - if (ISPRINT(*symbol) && // no control characters - *symbol != '/' && // symbol of client commands - *symbol != '%' && // symbol of party chat - *symbol != '$' && // symbol of guild chat - *symbol != charcommand_symbol) - atcommand_symbol = *symbol; - } - - if (config_lookup_string(&atcommand_config, "charcommand_symbol", &symbol)) { - if (ISPRINT(*symbol) && // no control characters - *symbol != '/' && // symbol of client commands - *symbol != '%' && // symbol of party chat - *symbol != '$' && // symbol of guild chat - *symbol != atcommand_symbol) - charcommand_symbol = *symbol; - } - - // Command aliases - aliases = config_lookup(&atcommand_config, "aliases"); - if (aliases != NULL) { - int i = 0; - int count = config_setting_length(aliases); - - for (i = 0; i < count; ++i) { - config_setting_t *command = NULL; - const char *commandname = NULL; - int j = 0, alias_count = 0; - AtCommandInfo *commandinfo = NULL; - - command = config_setting_get_elem(aliases, i); - if (config_setting_type(command) != CONFIG_TYPE_ARRAY) - continue; - commandname = config_setting_name(command); - if (!atcommand_exists(commandname)) { - ShowConfigWarning(command, "atcommand_config_read: can not set alias for non-existent command %s", commandname); - continue; - } - commandinfo = get_atcommandinfo_byname(commandname); - alias_count = config_setting_length(command); - for (j = 0; j < alias_count; ++j) { - const char *alias = config_setting_get_string_elem(command, j); - if (alias != NULL) { - AliasInfo *alias_info; - if (strdb_exists(atcommand_alias_db, alias)) { - ShowConfigWarning(command, "atcommand_config_read: alias %s already exists", alias); - continue; - } - CREATE(alias_info, AliasInfo, 1); - alias_info->command = commandinfo; - safestrncpy(alias_info->alias, alias, sizeof(alias_info->alias)); - strdb_put(atcommand_alias_db, alias, alias_info); - ++num_aliases; - } - } - } - } - - // Commands help - // We only check if all commands exist - help = config_lookup(&atcommand_config, "help"); - if (help != NULL) { - int count = config_setting_length(help); - int i; - - for (i = 0; i < count; ++i) { - config_setting_t *command = NULL; - const char *commandname = NULL; - - command = config_setting_get_elem(help, i); - commandname = config_setting_name(command); - if (!atcommand_exists(commandname)) - ShowConfigWarning(command, "atcommand_config_read: command %s does not exist", commandname); - } - } - - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' command aliases in '"CL_WHITE"%s"CL_RESET"'.\n", num_aliases, config_filename); - return; -} -void atcommand_db_load_groups(int *group_ids) -{ - DBIterator *iter = db_iterator(atcommand_db); - AtCommandInfo *cmd; - int i; - - for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) { - cmd->at_groups = aMalloc(pc_group_max * sizeof(char)); - cmd->char_groups = aMalloc(pc_group_max * sizeof(char)); - for (i = 0; i < pc_group_max; i++) { - if (pc_group_can_use_command(group_ids[i], cmd->command, COMMAND_ATCOMMAND)) - cmd->at_groups[i] = 1; - else - cmd->at_groups[i] = 0; - if (pc_group_can_use_command(group_ids[i], cmd->command, COMMAND_CHARCOMMAND)) - cmd->char_groups[i] = 1; - else - cmd->char_groups[i] = 0; - } - } - - dbi_destroy(iter); - - return; -} -void atcommand_db_clear(void) -{ - - if (atcommand_db != NULL) { - DBIterator *iter = db_iterator(atcommand_db); - AtCommandInfo *cmd; - - for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) { - aFree(cmd->at_groups); - aFree(cmd->char_groups); - } - - dbi_destroy(iter); - - db_destroy(atcommand_db); - } - if (atcommand_alias_db != NULL) - db_destroy(atcommand_alias_db); - - config_destroy(&atcommand_config); -} - -void atcommand_doload(void) -{ - atcommand_db_clear(); - atcommand_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); - atcommand_alias_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); - atcommand_basecommands(); //fills initial atcommand_db with known commands - atcommand_config_read(ATCOMMAND_CONF_FILENAME); -} - -void do_init_atcommand(void) -{ - atcommand_doload(); -} - -void do_final_atcommand(void) -{ - atcommand_db_clear(); +static void atcommand_config_read(const char* config_filename) +{ + config_setting_t *aliases = NULL, *help = NULL; + const char *symbol = NULL; + int num_aliases = 0; + + if (conf_read_file(&atcommand_config, config_filename)) + return; + + // Command symbols + if (config_lookup_string(&atcommand_config, "atcommand_symbol", &symbol)) { + if (ISPRINT(*symbol) && // no control characters + *symbol != '/' && // symbol of client commands + *symbol != '%' && // symbol of party chat + *symbol != '$' && // symbol of guild chat + *symbol != charcommand_symbol) + atcommand_symbol = *symbol; + } + + if (config_lookup_string(&atcommand_config, "charcommand_symbol", &symbol)) { + if (ISPRINT(*symbol) && // no control characters + *symbol != '/' && // symbol of client commands + *symbol != '%' && // symbol of party chat + *symbol != '$' && // symbol of guild chat + *symbol != atcommand_symbol) + charcommand_symbol = *symbol; + } + + // Command aliases + aliases = config_lookup(&atcommand_config, "aliases"); + if (aliases != NULL) { + int i = 0; + int count = config_setting_length(aliases); + + for (i = 0; i < count; ++i) { + config_setting_t *command = NULL; + const char *commandname = NULL; + int j = 0, alias_count = 0; + AtCommandInfo *commandinfo = NULL; + + command = config_setting_get_elem(aliases, i); + if (config_setting_type(command) != CONFIG_TYPE_ARRAY) + continue; + commandname = config_setting_name(command); + if (!atcommand_exists(commandname)) { + ShowConfigWarning(command, "atcommand_config_read: can not set alias for non-existent command %s", commandname); + continue; + } + commandinfo = get_atcommandinfo_byname(commandname); + alias_count = config_setting_length(command); + for (j = 0; j < alias_count; ++j) { + const char *alias = config_setting_get_string_elem(command, j); + if (alias != NULL) { + AliasInfo *alias_info; + if (strdb_exists(atcommand_alias_db, alias)) { + ShowConfigWarning(command, "atcommand_config_read: alias %s already exists", alias); + continue; + } + CREATE(alias_info, AliasInfo, 1); + alias_info->command = commandinfo; + safestrncpy(alias_info->alias, alias, sizeof(alias_info->alias)); + strdb_put(atcommand_alias_db, alias, alias_info); + ++num_aliases; + } + } + } + } + + // Commands help + // We only check if all commands exist + help = config_lookup(&atcommand_config, "help"); + if (help != NULL) { + int count = config_setting_length(help); + int i; + + for (i = 0; i < count; ++i) { + config_setting_t *command = NULL; + const char *commandname = NULL; + + command = config_setting_get_elem(help, i); + commandname = config_setting_name(command); + if (!atcommand_exists(commandname)) + ShowConfigWarning(command, "atcommand_config_read: command %s does not exist", commandname); + } + } + + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' command aliases in '"CL_WHITE"%s"CL_RESET"'.\n", num_aliases, config_filename); + return; +} +void atcommand_db_load_groups(int* group_ids) { + DBIterator *iter = db_iterator(atcommand_db); + AtCommandInfo* cmd; + int i; + + for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) { + cmd->at_groups = aMalloc( pc_group_max * sizeof(char) ); + cmd->char_groups = aMalloc( pc_group_max * sizeof(char) ); + for(i = 0; i < pc_group_max; i++) { + if( pc_group_can_use_command(group_ids[i], cmd->command, COMMAND_ATCOMMAND ) ) + cmd->at_groups[i] = 1; + else + cmd->at_groups[i] = 0; + if( pc_group_can_use_command(group_ids[i], cmd->command, COMMAND_CHARCOMMAND ) ) + cmd->char_groups[i] = 1; + else + cmd->char_groups[i] = 0; + } + } + + dbi_destroy(iter); + + return; +} +void atcommand_db_clear(void) { + + if (atcommand_db != NULL) { + DBIterator *iter = db_iterator(atcommand_db); + AtCommandInfo* cmd; + + for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) { + aFree(cmd->at_groups); + aFree(cmd->char_groups); + } + + dbi_destroy(iter); + + db_destroy(atcommand_db); + } + if (atcommand_alias_db != NULL) + db_destroy(atcommand_alias_db); + + config_destroy(&atcommand_config); +} + +void atcommand_doload(void) { + atcommand_db_clear(); + atcommand_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); + atcommand_alias_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); + atcommand_basecommands(); //fills initial atcommand_db with known commands + atcommand_config_read(ATCOMMAND_CONF_FILENAME); +} + +void do_init_atcommand(void) { + atcommand_doload(); +} + +void do_final_atcommand(void) { + atcommand_db_clear(); } diff --git a/src/map/atcommand.h b/src/map/atcommand.h index b3c7e4867..8affa4c26 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -16,36 +16,36 @@ extern char atcommand_symbol; extern char charcommand_symbol; typedef enum { - COMMAND_ATCOMMAND = 1, - COMMAND_CHARCOMMAND = 2, + COMMAND_ATCOMMAND = 1, + COMMAND_CHARCOMMAND = 2, } AtCommandType; -typedef int (*AtCommandFunc)(const int fd, struct map_session_data *sd, const char *command, const char *message); +typedef int (*AtCommandFunc)(const int fd, struct map_session_data* sd, const char* command, const char* message); -bool is_atcommand(const int fd, struct map_session_data *sd, const char *message, int type); +bool is_atcommand(const int fd, struct map_session_data* sd, const char* message, int type); void do_init_atcommand(void); void do_final_atcommand(void); -void atcommand_db_load_groups(int *group_ids); +void atcommand_db_load_groups(int* group_ids); -bool atcommand_exists(const char *name); +bool atcommand_exists(const char* name); -const char *msg_txt(int msg_number); -int msg_config_read(const char *cfgName); +const char* msg_txt(int msg_number); +int msg_config_read(const char* cfgName); void do_final_msg(void); extern int atcmd_binding_count; // @commands (script based) struct atcmd_binding_data { - char command[50]; - char npc_event[50]; - int level; - int level2; + char command[50]; + char npc_event[50]; + int level; + int level2; }; -struct atcmd_binding_data **atcmd_binding; +struct atcmd_binding_data** atcmd_binding; -struct atcmd_binding_data *get_atcommandbind_byname(const char *name); +struct atcmd_binding_data* get_atcommandbind_byname(const char* name); #endif /* _ATCOMMAND_H_ */ diff --git a/src/map/battle.c b/src/map/battle.c index 3bbdcc210..36d8051ef 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -40,274 +40,263 @@ int attr_fix_table[4][ELE_MAX][ELE_MAX]; struct Battle_Config battle_config; static struct eri *delay_damage_ers; //For battle delay damage structures. -int battle_getcurrentskill(struct block_list *bl) //Returns the current/last skill in use by this bl. -{ - struct unit_data *ud; +int battle_getcurrentskill(struct block_list *bl) { //Returns the current/last skill in use by this bl. + struct unit_data *ud; - if (bl->type == BL_SKILL) { - struct skill_unit *su = (struct skill_unit *)bl; - return su->group?su->group->skill_id:0; - } + if( bl->type == BL_SKILL ) { + struct skill_unit * su = (struct skill_unit*)bl; + return su->group?su->group->skill_id:0; + } - ud = unit_bl2ud(bl); + ud = unit_bl2ud(bl); - return ud?ud->skillid:0; + return ud?ud->skillid:0; } /*========================================== * Get random targetting enemy *------------------------------------------*/ -static int battle_gettargeted_sub(struct block_list *bl, va_list ap) -{ - struct block_list **bl_list; - struct unit_data *ud; - int target_id; - int *c; +static int battle_gettargeted_sub(struct block_list *bl, va_list ap) { + struct block_list **bl_list; + struct unit_data *ud; + int target_id; + int *c; - bl_list = va_arg(ap, struct block_list **); - c = va_arg(ap, int *); - target_id = va_arg(ap, int); + bl_list = va_arg(ap, struct block_list **); + c = va_arg(ap, int *); + target_id = va_arg(ap, int); - if (bl->id == target_id) - return 0; + if (bl->id == target_id) + return 0; - if (*c >= 24) - return 0; + if (*c >= 24) + return 0; - if (!(ud = unit_bl2ud(bl))) - return 0; + if ( !(ud = unit_bl2ud(bl)) ) + return 0; - if (ud->target == target_id || ud->skilltarget == target_id) { - bl_list[(*c)++] = bl; - return 1; - } + if (ud->target == target_id || ud->skilltarget == target_id) { + bl_list[(*c)++] = bl; + return 1; + } - return 0; + return 0; } -struct block_list *battle_gettargeted(struct block_list *target) { - struct block_list *bl_list[24]; - int c = 0; - nullpo_retr(NULL, target); - - memset(bl_list, 0, sizeof(bl_list)); - map_foreachinrange(battle_gettargeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id); - if (c == 0) - return NULL; - if (c > 24) - c = 24; - return bl_list[rnd()%c]; +struct block_list* battle_gettargeted(struct block_list *target) { + struct block_list *bl_list[24]; + int c = 0; + nullpo_retr(NULL, target); + + memset(bl_list, 0, sizeof(bl_list)); + map_foreachinrange(battle_gettargeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id); + if ( c == 0 ) + return NULL; + if( c > 24 ) + c = 24; + return bl_list[rnd()%c]; } //Returns the id of the current targetted character of the passed bl. [Skotlex] -int battle_gettarget(struct block_list *bl) -{ - - switch (bl->type) { - case BL_PC: - return ((struct map_session_data *)bl)->ud.target; - case BL_MOB: - return ((struct mob_data *)bl)->target_id; - case BL_PET: - return ((struct pet_data *)bl)->target_id; - case BL_HOM: - return ((struct homun_data *)bl)->ud.target; - case BL_MER: - return ((struct mercenary_data *)bl)->ud.target; - case BL_ELEM: - return ((struct elemental_data *)bl)->ud.target; - } +int battle_gettarget(struct block_list* bl) { + + switch (bl->type) { + case BL_PC: return ((struct map_session_data*)bl)->ud.target; + case BL_MOB: return ((struct mob_data*)bl)->target_id; + case BL_PET: return ((struct pet_data*)bl)->target_id; + case BL_HOM: return ((struct homun_data*)bl)->ud.target; + case BL_MER: return ((struct mercenary_data*)bl)->ud.target; + case BL_ELEM: return ((struct elemental_data*)bl)->ud.target; + } - return 0; + return 0; } -static int battle_getenemy_sub(struct block_list *bl, va_list ap) -{ - struct block_list **bl_list; - struct block_list *target; - int *c; +static int battle_getenemy_sub(struct block_list *bl, va_list ap) { + struct block_list **bl_list; + struct block_list *target; + int *c; - bl_list = va_arg(ap, struct block_list **); - c = va_arg(ap, int *); - target = va_arg(ap, struct block_list *); + bl_list = va_arg(ap, struct block_list **); + c = va_arg(ap, int *); + target = va_arg(ap, struct block_list *); - if (bl->id == target->id) - return 0; + if (bl->id == target->id) + return 0; - if (*c >= 24) - return 0; + if (*c >= 24) + return 0; - if (status_isdead(bl)) - return 0; + if (status_isdead(bl)) + return 0; - if (battle_check_target(target, bl, BCT_ENEMY) > 0) { - bl_list[(*c)++] = bl; - return 1; - } + if (battle_check_target(target, bl, BCT_ENEMY) > 0) { + bl_list[(*c)++] = bl; + return 1; + } - return 0; + return 0; } // Picks a random enemy of the given type (BL_PC, BL_CHAR, etc) within the range given. [Skotlex] -struct block_list *battle_getenemy(struct block_list *target, int type, int range) { - struct block_list *bl_list[24]; - int c = 0; +struct block_list* battle_getenemy(struct block_list *target, int type, int range) { + struct block_list *bl_list[24]; + int c = 0; - memset(bl_list, 0, sizeof(bl_list)); - map_foreachinrange(battle_getenemy_sub, target, range, type, bl_list, &c, target); + memset(bl_list, 0, sizeof(bl_list)); + map_foreachinrange(battle_getenemy_sub, target, range, type, bl_list, &c, target); - if (c == 0) - return NULL; + if ( c == 0 ) + return NULL; - if (c > 24) - c = 24; + if( c > 24 ) + c = 24; - return bl_list[rnd()%c]; + return bl_list[rnd()%c]; } -static int battle_getenemyarea_sub(struct block_list *bl, va_list ap) -{ - struct block_list **bl_list, *src; - int *c, ignore_id; +static int battle_getenemyarea_sub(struct block_list *bl, va_list ap) { + struct block_list **bl_list, *src; + int *c, ignore_id; - bl_list = va_arg(ap, struct block_list **); - c = va_arg(ap, int *); - src = va_arg(ap, struct block_list *); - ignore_id = va_arg(ap, int); + bl_list = va_arg(ap, struct block_list **); + c = va_arg(ap, int *); + src = va_arg(ap, struct block_list *); + ignore_id = va_arg(ap, int); - if (bl->id == src->id || bl->id == ignore_id) - return 0; // Ignores Caster and a possible pre-target + if( bl->id == src->id || bl->id == ignore_id ) + return 0; // Ignores Caster and a possible pre-target - if (*c >= 23) - return 0; + if( *c >= 23 ) + return 0; - if (status_isdead(bl)) - return 0; + if( status_isdead(bl) ) + return 0; - if (battle_check_target(src, bl, BCT_ENEMY) > 0) { // Is Enemy!... - bl_list[(*c)++] = bl; - return 1; - } + if( battle_check_target(src, bl, BCT_ENEMY) > 0 ) {// Is Enemy!... + bl_list[(*c)++] = bl; + return 1; + } - return 0; + return 0; } // Pick a random enemy -struct block_list *battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id) { - struct block_list *bl_list[24]; - int c = 0; +struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id) { + struct block_list *bl_list[24]; + int c = 0; - memset(bl_list, 0, sizeof(bl_list)); - map_foreachinarea(battle_getenemyarea_sub, src->m, x - range, y - range, x + range, y + range, type, bl_list, &c, src, ignore_id); + memset(bl_list, 0, sizeof(bl_list)); + map_foreachinarea(battle_getenemyarea_sub, src->m, x - range, y - range, x + range, y + range, type, bl_list, &c, src, ignore_id); - if (c == 0) - return NULL; - if (c >= 24) - c = 23; + if( c == 0 ) + return NULL; + if( c >= 24 ) + c = 23; - return bl_list[rnd()%c]; + return bl_list[rnd()%c]; } // Dammage delayed info struct delay_damage { - int src_id; - int target_id; - int damage; - int delay; - unsigned short distance; - unsigned short skill_lv; - unsigned short skill_id; - enum damage_lv dmg_lv; - unsigned short attack_type; + int src_id; + int target_id; + int damage; + int delay; + unsigned short distance; + unsigned short skill_lv; + unsigned short skill_id; + enum damage_lv dmg_lv; + unsigned short attack_type; }; -int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) -{ - struct delay_damage *dat = (struct delay_damage *)data; +int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { + struct delay_damage *dat = (struct delay_damage *)data; - if (dat) { - struct block_list *src; - struct block_list *target = map_id2bl(dat->target_id); + if ( dat ) { + struct block_list* src; + struct block_list* target = map_id2bl(dat->target_id); - if (!target || status_isdead(target)) { /* nothing we can do */ - ers_free(delay_damage_ers, dat); - return 0; - } + if( !target || status_isdead(target) ) {/* nothing we can do */ + ers_free(delay_damage_ers, dat); + return 0; + } - src = map_id2bl(dat->src_id); - - if (src && target->m == src->m && - (target->type != BL_PC || ((TBL_PC *)target)->invincible_timer == INVALID_TIMER) && - check_distance_bl(src, target, dat->distance)) { //Check to see if you haven't teleported. [Skotlex] - map_freeblock_lock(); - status_fix_damage(src, target, dat->damage, dat->delay); - if (dat->attack_type && !status_isdead(target)) - skill_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,dat->dmg_lv,tick); - if (dat->dmg_lv > ATK_BLOCK && dat->attack_type) - skill_counter_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); - map_freeblock_unlock(); - } else if (!src && dat->skill_id == CR_REFLECTSHIELD) { - /** - * it was monster reflected damage, and the monster died, we pass the damage to the character as expected - **/ - map_freeblock_lock(); - status_fix_damage(target, target, dat->damage, dat->delay); - map_freeblock_unlock(); - } - } - ers_free(delay_damage_ers, dat); - return 0; + src = map_id2bl(dat->src_id); + + if( src && target->m == src->m && + (target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == INVALID_TIMER) && + check_distance_bl(src, target, dat->distance) ) //Check to see if you haven't teleported. [Skotlex] + { + map_freeblock_lock(); + status_fix_damage(src, target, dat->damage, dat->delay); + if( dat->attack_type && !status_isdead(target) ) + skill_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,dat->dmg_lv,tick); + if( dat->dmg_lv > ATK_BLOCK && dat->attack_type ) + skill_counter_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); + map_freeblock_unlock(); + } else if( !src && dat->skill_id == CR_REFLECTSHIELD ) { + /** + * it was monster reflected damage, and the monster died, we pass the damage to the character as expected + **/ + map_freeblock_lock(); + status_fix_damage(target, target, dat->damage, dat->delay); + map_freeblock_unlock(); + } + } + ers_free(delay_damage_ers, dat); + return 0; } -int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, int skill_id, int skill_lv, int damage, enum damage_lv dmg_lv, int ddelay) +int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, int skill_id, int skill_lv, int damage, enum damage_lv dmg_lv, int ddelay) { - struct delay_damage *dat; - struct status_change *sc; - nullpo_ret(src); - nullpo_ret(target); - - sc = status_get_sc(target); - - if (sc && sc->data[SC_DEVOTION] && damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD) - damage = 0; - - if (!battle_config.delay_battle_damage || amotion <= 1) { - map_freeblock_lock(); - status_fix_damage(src, target, damage, ddelay); // We have to seperate here between reflect damage and others [icescope] - if (attack_type && !status_isdead(target)) - skill_additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, gettick()); - if (dmg_lv > ATK_BLOCK && attack_type) - skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick()); - map_freeblock_unlock(); - return 0; - } - dat = ers_alloc(delay_damage_ers, struct delay_damage); - dat->src_id = src->id; - dat->target_id = target->id; - dat->skill_id = skill_id; - dat->skill_lv = skill_lv; - dat->attack_type = attack_type; - dat->damage = damage; - dat->dmg_lv = dmg_lv; - dat->delay = ddelay; - dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported. - if (src->type != BL_PC && amotion > 1000) - amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex] - - add_timer(tick+amotion, battle_delay_damage_sub, 0, (intptr_t)dat); - - return 0; + struct delay_damage *dat; + struct status_change *sc; + nullpo_ret(src); + nullpo_ret(target); + + sc = status_get_sc(target); + + if( sc && sc->data[SC_DEVOTION] && damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD ) + damage = 0; + + if ( !battle_config.delay_battle_damage || amotion <= 1 ) { + map_freeblock_lock(); + status_fix_damage(src, target, damage, ddelay); // We have to seperate here between reflect damage and others [icescope] + if( attack_type && !status_isdead(target) ) + skill_additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, gettick()); + if( dmg_lv > ATK_BLOCK && attack_type ) + skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick()); + map_freeblock_unlock(); + return 0; + } + dat = ers_alloc(delay_damage_ers, struct delay_damage); + dat->src_id = src->id; + dat->target_id = target->id; + dat->skill_id = skill_id; + dat->skill_lv = skill_lv; + dat->attack_type = attack_type; + dat->damage = damage; + dat->dmg_lv = dmg_lv; + dat->delay = ddelay; + dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported. + if (src->type != BL_PC && amotion > 1000) + amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex] + + add_timer(tick+amotion, battle_delay_damage_sub, 0, (intptr_t)dat); + + return 0; } int battle_attr_ratio(int atk_elem,int def_type, int def_lv) { - if (atk_elem < 0 || atk_elem >= ELE_MAX) - return 100; + if (atk_elem < 0 || atk_elem >= ELE_MAX) + return 100; - if (def_type < 0 || def_type > ELE_MAX || def_lv < 1 || def_lv > 4) - return 100; + if (def_type < 0 || def_type > ELE_MAX || def_lv < 1 || def_lv > 4) + return 100; - return attr_fix_table[def_lv-1][atk_elem][def_type]; + return attr_fix_table[def_lv-1][atk_elem][def_type]; } /*========================================== @@ -317,416 +306,106 @@ int battle_attr_ratio(int atk_elem,int def_type, int def_lv) *------------------------------------------*/ int battle_attr_fix(struct block_list *src, struct block_list *target, int damage,int atk_elem,int def_type, int def_lv) { - struct status_change *sc=NULL, *tsc=NULL; - int ratio; - - if (src) sc = status_get_sc(src); - if (target) tsc = status_get_sc(target); - - if (atk_elem < 0 || atk_elem >= ELE_MAX) - atk_elem = rnd()%ELE_MAX; + struct status_change *sc=NULL, *tsc=NULL; + int ratio; - if (def_type < 0 || def_type > ELE_MAX || - def_lv < 1 || def_lv > 4) { - ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv); - return damage; - } - - ratio = attr_fix_table[def_lv-1][atk_elem][def_type]; - if (sc && sc->count) { - if (sc->data[SC_VOLCANO] && atk_elem == ELE_FIRE) - ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1]; - if (sc->data[SC_VIOLENTGALE] && atk_elem == ELE_WIND) - ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1]; - if (sc->data[SC_DELUGE] && atk_elem == ELE_WATER) - ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1]; - } - if (target && target->type == BL_SKILL) { - if (atk_elem == ELE_FIRE && battle_getcurrentskill(target) == GN_WALLOFTHORN) { - struct skill_unit *su = (struct skill_unit *)target; - struct skill_unit_group *sg; - struct block_list *src; - int x,y; - - if (!su || !su->alive || (sg = su->group) == NULL || !sg || sg->val3 == -1 || - (src = map_id2bl(sg->src_id)) == NULL || status_isdead(src)) - return 0; - - if (sg->unit_id != UNT_FIREWALL) { - x = sg->val3 >> 16; - y = sg->val3 & 0xffff; - skill_unitsetting(src,su->group->skill_id,su->group->skill_lv,x,y,1); - sg->val3 = -1; - sg->limit = DIFF_TICK(gettick(),sg->tick)+300; - } - } - } - if (tsc && tsc->count) { //since an atk can only have one type let's optimise this a bit - switch (atk_elem) { - case ELE_FIRE: - if (tsc->data[SC_SPIDERWEB]) { - tsc->data[SC_SPIDERWEB]->val1 = 0; // free to move now - if (tsc->data[SC_SPIDERWEB]->val2-- > 0) - damage <<= 1; // double damage - if (tsc->data[SC_SPIDERWEB]->val2 == 0) - status_change_end(target, SC_SPIDERWEB, INVALID_TIMER); - } - if (tsc->data[SC_THORNSTRAP]) - status_change_end(target, SC_THORNSTRAP, INVALID_TIMER); - if (tsc->data[SC_FIRE_CLOAK_OPTION]) - damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100; - if (tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB) - status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER); - if (tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2; - if (tsc->data[SC_ASH]) damage += damage/2; //150% - break; - case ELE_HOLY: - if (tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2; - break; - case ELE_POISON: - if (tsc->data[SC_VENOMIMPRESS]) ratio += tsc->data[SC_VENOMIMPRESS]->val2; - break; - case ELE_WIND: - if (tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB) damage += damage/2; - if (tsc->data[SC_WATER_INSIGNIA]) damage += damage/2; - break; - case ELE_WATER: - if (tsc->data[SC_FIRE_INSIGNIA]) damage += damage/2; - break; - case ELE_EARTH: - if (tsc->data[SC_WIND_INSIGNIA]) damage += damage/2; - break; - } - } //end tsc check - if (src && src->type == BL_PC) { - struct map_session_data *sd = BL_CAST(BL_PC, src); - int s; + if (src) sc = status_get_sc(src); + if (target) tsc = status_get_sc(target); - ARR_FIND(1, 6, s, sd->talisman[s] > 0); + if (atk_elem < 0 || atk_elem >= ELE_MAX) + atk_elem = rnd()%ELE_MAX; - if (s < 5 && atk_elem == s) - ratio += sd->talisman[s] * 2; // +2% custom value - } - if (target && target->type == BL_PC) { - struct map_session_data *tsd = BL_CAST(BL_PC, target); - int t; - - ARR_FIND(1, 6, t, tsd->talisman[t] > 0); - - if (t < 5 && atk_elem == t) - damage -= damage * tsd->talisman[t] * 3 / 100; // -3% custom value - } - return damage*ratio/100; -} -/*========================================== - * Calculates card bonuses damage adjustments. - *------------------------------------------*/ -int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag){ - struct map_session_data *sd, *tsd; - short cardfix = 1000, t_class, s_class, s_race2, t_race2; - struct status_data *sstatus, *tstatus; - int i; - - sd = BL_CAST(BL_PC, src); - tsd = BL_CAST(BL_PC, target); - t_class = status_get_class(target); - s_class = status_get_class(src); - sstatus = status_get_status_data(src); - tstatus = status_get_status_data(target); - s_race2 = status_get_race2(src); - t_race2 = status_get_race2(target); - - if( !damage ) - return 0; - - switch(attack_type){ - case BF_MAGIC: - if ( sd && !(nk&NK_NO_CARDFIX_ATK) ) { - cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) - cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100; - cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate;i++) { - if(sd->add_mdmg[i].class_ == t_class) { - cardfix=cardfix*(100+sd->add_mdmg[i].rate)/100; - continue; - } - } - if (cardfix != 1000) - damage = damage * cardfix / 1000; - } - - if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) - { // Target cards. - if (!(nk&NK_NO_ELEFIX)) - { - int ele_fix = tsd->subele[s_ele]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele) continue; - if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && - tsd->subele2[i].flag&flag&BF_RANGEMASK && - tsd->subele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix)/100; - } - cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; - cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; - cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; - cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; - - for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) { - if(tsd->add_mdef[i].class_ == s_class) { - cardfix=cardfix*(100-tsd->add_mdef[i].rate)/100; - break; - } - } - //It was discovered that ranged defense also counts vs magic! [Skotlex] - if ( flag&BF_SHORT ) - cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; - else - cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; - - cardfix = cardfix * ( 100 - tsd->bonus.magic_def_rate ) / 100; - - if( tsd->sc.data[SC_MDEF_RATE] ) - cardfix = cardfix * ( 100 - tsd->sc.data[SC_MDEF_RATE]->val1 ) / 100; - - if (cardfix != 1000) - damage = damage * cardfix / 1000; - } - break; - case BF_WEAPON: - if( sd && !(nk&NK_NO_CARDFIX_ATK) && (left&2) ) - { - short cardfix_ = 1000; - if(sd->state.arrow_atk) - { - cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) - { - int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele]; - for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { - if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; - if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK && - sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK && - sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += sd->right_weapon.addele2[i].rate; - } - cardfix=cardfix*(100+ele_fix)/100; - } - cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN])/100; - } - else - { // Melee attack - if( !battle_config.left_cardfix_to_right ) - { - cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) { - int ele_fix = sd->right_weapon.addele[tstatus->def_ele]; - for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { - if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; - if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK && - sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK && - sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += sd->right_weapon.addele2[i].rate; - } - cardfix=cardfix*(100+ele_fix)/100; - } - cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN])/100; - - if( left&1 ) - { - cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) { - int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele]; - for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) { - if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue; - if(!(sd->left_weapon.addele2[i].flag&flag&BF_WEAPONMASK && - sd->left_weapon.addele2[i].flag&flag&BF_RANGEMASK && - sd->left_weapon.addele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix_lh += sd->left_weapon.addele2[i].rate; - } - cardfix=cardfix*(100+ele_fix_lh)/100; - } - cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100; - cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100; - cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix_=cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; - } - } - else - { - int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]; - for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { - if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; - if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK && - sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK && - sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += sd->right_weapon.addele2[i].rate; - } - for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) { - if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue; - if(!(sd->left_weapon.addele2[i].flag&flag&BF_WEAPONMASK && - sd->left_weapon.addele2[i].flag&flag&BF_RANGEMASK && - sd->left_weapon.addele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += sd->left_weapon.addele2[i].rate; - } - - cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100; - cardfix=cardfix*(100+ele_fix)/100; - cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; - } - } - for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ ) - { - if( sd->right_weapon.add_dmg[i].class_ == t_class ) - { - cardfix=cardfix*(100+sd->right_weapon.add_dmg[i].rate)/100; - break; - } - } - - if( left&1 ) - { - for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ ) - { - if( sd->left_weapon.add_dmg[i].class_ == t_class ) - { - cardfix_=cardfix_*(100+sd->left_weapon.add_dmg[i].rate)/100; - break; - } - } - } - - if( flag&BF_LONG ) - cardfix = cardfix * ( 100 + sd->bonus.long_attack_atk_rate ) / 100; -#ifdef RENEWAL_EDP - if( sd->sc.data[SC_EDP] ){ - cardfix = cardfix * (100 + sd->sc.data[SC_EDP]->val1 * 60 ) / 100; - cardfix_ = cardfix_ * (100 + sd->sc.data[SC_EDP]->val1 * 60 ) / 100; - } -#endif - if( (left&1) && cardfix_ != 1000 ) - damage = damage * cardfix_ / 1000; - else if( cardfix != 1000 ) - damage = damage * cardfix / 1000; - - }else if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){ - if( !(nk&NK_NO_ELEFIX) ) - { - int ele_fix = tsd->subele[s_ele]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele) continue; - if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && - tsd->subele2[i].flag&flag&BF_RANGEMASK && - tsd->subele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix)/100; - if( left&1 && s_ele_ != s_ele ) - { - int ele_fix_lh = tsd->subele[s_ele_]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele_) continue; - if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && - tsd->subele2[i].flag&flag&BF_RANGEMASK && - tsd->subele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix_lh += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix_lh)/100; - } - } - cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; - cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; - cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; - cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + if (def_type < 0 || def_type > ELE_MAX || + def_lv < 1 || def_lv > 4) { + ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv); + return damage; + } - for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ) { - if( tsd->add_def[i].class_ == s_class ) { - cardfix=cardfix*(100-tsd->add_def[i].rate)/100; - break; - } + ratio = attr_fix_table[def_lv-1][atk_elem][def_type]; + if (sc && sc->count) { + if(sc->data[SC_VOLCANO] && atk_elem == ELE_FIRE) + ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1]; + if(sc->data[SC_VIOLENTGALE] && atk_elem == ELE_WIND) + ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1]; + if(sc->data[SC_DELUGE] && atk_elem == ELE_WATER) + ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1]; + } + if( target && target->type == BL_SKILL ) { + if( atk_elem == ELE_FIRE && battle_getcurrentskill(target) == GN_WALLOFTHORN ) { + struct skill_unit *su = (struct skill_unit*)target; + struct skill_unit_group *sg; + struct block_list *src; + int x,y; + + if( !su || !su->alive || (sg = su->group) == NULL || !sg || sg->val3 == -1 || + (src = map_id2bl(sg->src_id)) == NULL || status_isdead(src) ) + return 0; + + if( sg->unit_id != UNT_FIREWALL ) { + x = sg->val3 >> 16; + y = sg->val3 & 0xffff; + skill_unitsetting(src,su->group->skill_id,su->group->skill_lv,x,y,1); + sg->val3 = -1; + sg->limit = DIFF_TICK(gettick(),sg->tick)+300; } + } + } + if( tsc && tsc->count ) { //since an atk can only have one type let's optimise this a bit + switch(atk_elem){ + case ELE_FIRE: + if( tsc->data[SC_SPIDERWEB]) { + tsc->data[SC_SPIDERWEB]->val1 = 0; // free to move now + if( tsc->data[SC_SPIDERWEB]->val2-- > 0 ) + damage <<= 1; // double damage + if( tsc->data[SC_SPIDERWEB]->val2 == 0 ) + status_change_end(target, SC_SPIDERWEB, INVALID_TIMER); + } + if( tsc->data[SC_THORNSTRAP]) + status_change_end(target, SC_THORNSTRAP, INVALID_TIMER); + if( tsc->data[SC_FIRE_CLOAK_OPTION]) + damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100; + if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB) + status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER); + if( tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2; + if( tsc->data[SC_ASH]) damage += damage/2; //150% + break; + case ELE_HOLY: + if( tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2; + break; + case ELE_POISON: + if( tsc->data[SC_VENOMIMPRESS]) ratio += tsc->data[SC_VENOMIMPRESS]->val2; + break; + case ELE_WIND: + if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB) damage += damage/2; + if( tsc->data[SC_WATER_INSIGNIA]) damage += damage/2; + break; + case ELE_WATER: + if( tsc->data[SC_FIRE_INSIGNIA]) damage += damage/2; + break; + case ELE_EARTH: + if( tsc->data[SC_WIND_INSIGNIA]) damage += damage/2; + break; + } + } //end tsc check + if( src && src->type == BL_PC ){ + struct map_session_data *sd = BL_CAST(BL_PC, src); + int s; - if( flag&BF_SHORT ) - cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; - else // BF_LONG (there's no other choice) - cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; + ARR_FIND(1, 6, s, sd->talisman[s] > 0); - if( tsd->sc.data[SC_DEF_RATE] ) - cardfix = cardfix * ( 100 - tsd->sc.data[SC_DEF_RATE]->val1 ) / 100; + if( s < 5 && atk_elem == s ) + ratio += sd->talisman[s] * 2; // +2% custom value + } + if( target && target->type == BL_PC ) { + struct map_session_data *tsd = BL_CAST(BL_PC, target); + int t; - if( cardfix != 1000 ) - damage = damage * cardfix / 1000; - } - break; - case BF_MISC: - if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){ - // misc damage reduction from equipment - if (!(nk&NK_NO_ELEFIX)) - { - int ele_fix = tsd->subele[s_ele]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele) continue; - if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && - tsd->subele2[i].flag&flag&BF_RANGEMASK && - tsd->subele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix)/100; - } - cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; - cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; - cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; - cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; - - cardfix = cardfix * ( 100 - tsd->bonus.misc_def_rate ) / 100; - if( flag&BF_SHORT ) - cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; - else // BF_LONG (there's no other choice) - cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; + ARR_FIND(1, 6, t, tsd->talisman[t] > 0); - if (cardfix != 10000) - damage = (int)( (int64)damage * cardfix / 1000); - } - break; + if( t < 5 && atk_elem == t ) + damage -= damage * tsd->talisman[t] * 3 / 100; // -3% custom value } - - return damage; + return damage*ratio/100; } /*========================================== @@ -736,506 +415,519 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li *------------------------------------------*/ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int damage,int skill_num,int skill_lv) { - struct map_session_data *sd = NULL; - struct status_change *sc; - struct status_change_entry *sce; - int div_ = d->div_, flag = d->flag; + struct map_session_data *sd = NULL; + struct status_change *sc; + struct status_change_entry *sce; + int div_ = d->div_, flag = d->flag; - nullpo_ret(bl); + nullpo_ret(bl); - if (!damage) - return 0; - if (battle_config.ksprotection && mob_ksprotected(src, bl)) - return 0; + if( !damage ) + return 0; + if( battle_config.ksprotection && mob_ksprotected(src, bl) ) + return 0; - if (bl->type == BL_PC) { - sd=(struct map_session_data *)bl; - //Special no damage states - if (flag&BF_WEAPON && sd->special_state.no_weapon_damage) - damage -= damage*sd->special_state.no_weapon_damage/100; + if (bl->type == BL_PC) { + sd=(struct map_session_data *)bl; + //Special no damage states + if(flag&BF_WEAPON && sd->special_state.no_weapon_damage) + damage -= damage*sd->special_state.no_weapon_damage/100; - if (flag&BF_MAGIC && sd->special_state.no_magic_damage) - damage -= damage*sd->special_state.no_magic_damage/100; + if(flag&BF_MAGIC && sd->special_state.no_magic_damage) + damage -= damage*sd->special_state.no_magic_damage/100; - if (flag&BF_MISC && sd->special_state.no_misc_damage) - damage -= damage*sd->special_state.no_misc_damage/100; + if(flag&BF_MISC && sd->special_state.no_misc_damage) + damage -= damage*sd->special_state.no_misc_damage/100; - if (!damage) return 0; - } + if(!damage) return 0; + } - sc = status_get_sc(bl); + sc = status_get_sc(bl); - if (sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF]) - return 1; + if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) + return 1; - if (skill_num == PA_PRESSURE) - return damage; //This skill bypass everything else. + if (skill_num == PA_PRESSURE) + return damage; //This skill bypass everything else. - if (sc && sc->count) { - //First, sc_*'s that reduce damage to 0. - if (sc->data[SC_BASILICA] && !(status_get_mode(src)&MD_BOSS)) { - d->dmg_lv = ATK_BLOCK; - return 0; - } - if (sc->data[SC_WHITEIMPRISON] && skill_num != HW_GRAVITATION) { // Gravitation and Pressure do damage without removing the effect - if (skill_num == MG_NAPALMBEAT || - skill_num == MG_SOULSTRIKE || - skill_num == WL_SOULEXPANSION || - (skill_num && skill_get_ele(skill_num, skill_lv) == ELE_GHOST) || - (!skill_num && (status_get_status_data(src))->rhw.ele == ELE_GHOST) - ) { - if (skill_num == WL_SOULEXPANSION) - damage <<= 1; // If used against a player in White Imprison, the skill deals double damage. - status_change_end(bl,SC_WHITEIMPRISON,INVALID_TIMER); // Those skills do damage and removes effect - } else { - d->dmg_lv = ATK_BLOCK; - return 0; - } - } + if( sc && sc->count ) + { + //First, sc_*'s that reduce damage to 0. + if( sc->data[SC_BASILICA] && !(status_get_mode(src)&MD_BOSS) ) + { + d->dmg_lv = ATK_BLOCK; + return 0; + } + if( sc->data[SC_WHITEIMPRISON] && skill_num != HW_GRAVITATION ) { // Gravitation and Pressure do damage without removing the effect + if( skill_num == MG_NAPALMBEAT || + skill_num == MG_SOULSTRIKE || + skill_num == WL_SOULEXPANSION || + (skill_num && skill_get_ele(skill_num, skill_lv) == ELE_GHOST) || + (!skill_num && (status_get_status_data(src))->rhw.ele == ELE_GHOST) + ){ + if( skill_num == WL_SOULEXPANSION ) + damage <<= 1; // If used against a player in White Imprison, the skill deals double damage. + status_change_end(bl,SC_WHITEIMPRISON,INVALID_TIMER); // Those skills do damage and removes effect + }else{ + d->dmg_lv = ATK_BLOCK; + return 0; + } + } - if (sc->data[SC_ZEPHYR] && - flag&(BF_LONG|BF_SHORT)) { - d->dmg_lv = ATK_BLOCK; - return 0; - } + if(sc->data[SC_ZEPHYR] && + flag&(BF_LONG|BF_SHORT)){ + d->dmg_lv = ATK_BLOCK; + return 0; + } - if (sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT) { - struct skill_unit_group *group = skill_id2group(sc->data[SC_SAFETYWALL]->val3); - int skill_id = sc->data[SC_SAFETYWALL]->val2; - if (group) { - if (skill_id == MH_STEINWAND) { - if (--group->val2<=0) - skill_delunitgroup(group); - d->dmg_lv = ATK_BLOCK; - return 0; - } - /** - * in RE, SW possesses a lifetime equal to 3 times the caster's health - **/ -#ifdef RENEWAL - if ((group->val2 - damage) > 0) { - group->val2 -= damage; - d->dmg_lv = ATK_BLOCK; - return 0; - } else - damage -= group->val2; - skill_delunitgroup(group); -#else - if (--group->val2<=0) - skill_delunitgroup(group); - d->dmg_lv = ATK_BLOCK; - return 0; -#endif - } - status_change_end(bl, SC_SAFETYWALL, INVALID_TIMER); - } + if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) + { + struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3); + int skill_id = sc->data[SC_SAFETYWALL]->val2; + if (group) { + if(skill_id == MH_STEINWAND){ + if (--group->val2<=0) + skill_delunitgroup(group); + d->dmg_lv = ATK_BLOCK; + return 0; + } + /** + * in RE, SW possesses a lifetime equal to 3 times the caster's health + **/ + #ifdef RENEWAL + if ( ( group->val2 - damage) > 0 ) { + group->val2 -= damage; + d->dmg_lv = ATK_BLOCK; + return 0; + } else + damage -= group->val2; + skill_delunitgroup(group); + #else + if (--group->val2<=0) + skill_delunitgroup(group); + d->dmg_lv = ATK_BLOCK; + return 0; + #endif + } + status_change_end(bl, SC_SAFETYWALL, INVALID_TIMER); + } - if ((sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG) || sc->data[SC__MANHOLE]) { - d->dmg_lv = ATK_BLOCK; - return 0; - } - if (sc->data[SC_WEAPONBLOCKING] && flag&(BF_SHORT|BF_WEAPON) && rnd()%100 < sc->data[SC_WEAPONBLOCKING]->val2) { - clif_skill_nodamage(bl,src,GC_WEAPONBLOCKING,1,1); - d->dmg_lv = ATK_BLOCK; - sc_start2(bl,SC_COMBO,100,GC_WEAPONBLOCKING,src->id,2000); - return 0; - } - if ((sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2) { - int delay; - clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1); - // different delay depending on skill level [celest] - if (sce->val1 <= 5) - delay = 300; - else if (sce->val1 > 5 && sce->val1 <= 9) - delay = 200; - else - delay = 100; - unit_set_walkdelay(bl, gettick(), delay, 1); - - if (sc->data[SC_SHRINK] && rnd()%100<5*sce->val1) - skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1),-1,0); - return 0; - } + if( ( sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG ) || sc->data[SC__MANHOLE] ) { + d->dmg_lv = ATK_BLOCK; + return 0; + } + if( sc->data[SC_WEAPONBLOCKING] && flag&(BF_SHORT|BF_WEAPON) && rnd()%100 < sc->data[SC_WEAPONBLOCKING]->val2 ) + { + clif_skill_nodamage(bl,src,GC_WEAPONBLOCKING,1,1); + d->dmg_lv = ATK_BLOCK; + sc_start2(bl,SC_COMBO,100,GC_WEAPONBLOCKING,src->id,2000); + return 0; + } + if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2 ) + { + int delay; + clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1); + // different delay depending on skill level [celest] + if (sce->val1 <= 5) + delay = 300; + else if (sce->val1 > 5 && sce->val1 <= 9) + delay = 200; + else + delay = 100; + unit_set_walkdelay(bl, gettick(), delay, 1); + + if(sc->data[SC_SHRINK] && rnd()%100<5*sce->val1) + skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1),-1,0); + return 0; + } - if ((sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0) { - clif_skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1); - sce->val3 -= damage; // absorb damage - d->dmg_lv = ATK_BLOCK; - sc_start(bl,SC_STUN,15,0,skill_get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken. - if (sce->val3 <= 0) { // Shield Down - sce->val2--; - if (sce->val2 > 0) { - if (sd) - clif_millenniumshield(sd,sce->val2); - sce->val3 = 1000; // Next Shield - } else - status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down - } - return 0; - } + if( (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 ) { + clif_skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1); + sce->val3 -= damage; // absorb damage + d->dmg_lv = ATK_BLOCK; + sc_start(bl,SC_STUN,15,0,skill_get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken. + if( sce->val3 <= 0 ) { // Shield Down + sce->val2--; + if( sce->val2 > 0 ) { + if( sd ) + clif_millenniumshield(sd,sce->val2); + sce->val3 = 1000; // Next Shield + } else + status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down + } + return 0; + } - if ((sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON && skill_num != WS_CARTTERMINATION && rnd()%100 < sce->val2) { - // attack blocked by Parrying - clif_skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1); - return 0; - } + if( (sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON && skill_num != WS_CARTTERMINATION && rnd()%100 < sce->val2 ) + { // attack blocked by Parrying + clif_skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1); + return 0; + } - if (sc->data[SC_DODGE] && (!sc->opt1 || sc->opt1 == OPT1_BURNING) && - (flag&BF_LONG || sc->data[SC_SPURT]) - && rnd()%100 < 20) { - if (sd && pc_issit(sd)) pc_setstand(sd); //Stand it to dodge. - clif_skill_nodamage(bl,bl,TK_DODGE,1,1); - if (!sc->data[SC_COMBO]) - sc_start4(bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000); - return 0; - } + if(sc->data[SC_DODGE] && ( !sc->opt1 || sc->opt1 == OPT1_BURNING ) && + (flag&BF_LONG || sc->data[SC_SPURT]) + && rnd()%100 < 20) { + if (sd && pc_issit(sd)) pc_setstand(sd); //Stand it to dodge. + clif_skill_nodamage(bl,bl,TK_DODGE,1,1); + if (!sc->data[SC_COMBO]) + sc_start4(bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000); + return 0; + } - if (sc->data[SC_HERMODE] && flag&BF_MAGIC) - return 0; + if(sc->data[SC_HERMODE] && flag&BF_MAGIC) + return 0; - if (sc->data[SC_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG) - return 0; + if(sc->data[SC_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG) + return 0; - if (sc->data[SC_NEUTRALBARRIER] && (flag&(BF_MAGIC|BF_LONG)) == (BF_MAGIC|BF_LONG)) { - d->dmg_lv = ATK_MISS; - return 0; - } + if( sc->data[SC_NEUTRALBARRIER] && (flag&(BF_MAGIC|BF_LONG)) == (BF_MAGIC|BF_LONG) ) { + d->dmg_lv = ATK_MISS; + return 0; + } - if ((sce=sc->data[SC_KAUPE]) && rnd()%100 < sce->val2) { - //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries. - clif_specialeffect(bl, 462, AREA); - //Shouldn't end until Breaker's non-weapon part connects. - if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON)) - if (--(sce->val3) <= 0) //We make it work like Safety Wall, even though it only blocks 1 time. - status_change_end(bl, SC_KAUPE, INVALID_TIMER); - return 0; - } + if((sce=sc->data[SC_KAUPE]) && rnd()%100 < sce->val2) + { //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries. + clif_specialeffect(bl, 462, AREA); + //Shouldn't end until Breaker's non-weapon part connects. + if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON)) + if (--(sce->val3) <= 0) //We make it work like Safety Wall, even though it only blocks 1 time. + status_change_end(bl, SC_KAUPE, INVALID_TIMER); + return 0; + } - if (flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) && rnd()%100 < sce->val2) { - clif_specialeffect(bl, 462, AREA); // Still need confirm it. - return 0; - } + if( flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) && rnd()%100 < sce->val2) { + clif_specialeffect(bl, 462, AREA); // Still need confirm it. + return 0; + } - if (((sce=sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU]) - && flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK)) { + if (((sce=sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU]) + && flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK)) { - skill_additional_effect(src, bl, skill_num, skill_lv, flag, ATK_BLOCK, gettick()); - if (!status_isdead(src)) - skill_counter_additional_effect(src, bl, skill_num, skill_lv, flag, gettick()); - if (sce) { - clif_specialeffect(bl, 462, AREA); - skill_blown(src,bl,sce->val3,-1,0); - } - //Both need to be consumed if they are active. - if (sce && --(sce->val2) <= 0) - status_change_end(bl, SC_UTSUSEMI, INVALID_TIMER); - if ((sce=sc->data[SC_BUNSINJYUTSU]) && --(sce->val2) <= 0) - status_change_end(bl, SC_BUNSINJYUTSU, INVALID_TIMER); + skill_additional_effect (src, bl, skill_num, skill_lv, flag, ATK_BLOCK, gettick() ); + if( !status_isdead(src) ) + skill_counter_additional_effect( src, bl, skill_num, skill_lv, flag, gettick() ); + if (sce) { + clif_specialeffect(bl, 462, AREA); + skill_blown(src,bl,sce->val3,-1,0); + } + //Both need to be consumed if they are active. + if (sce && --(sce->val2) <= 0) + status_change_end(bl, SC_UTSUSEMI, INVALID_TIMER); + if ((sce=sc->data[SC_BUNSINJYUTSU]) && --(sce->val2) <= 0) + status_change_end(bl, SC_BUNSINJYUTSU, INVALID_TIMER); - return 0; - } + return 0; + } - //Now damage increasing effects - if (sc->data[SC_AETERNA] && skill_num != PF_SOULBURN) { - if (src->type != BL_MER || skill_num == 0) - damage <<= 1; // Lex Aeterna only doubles damage of regular attacks from mercenaries + //Now damage increasing effects + if( sc->data[SC_AETERNA] && skill_num != PF_SOULBURN ) + { + if( src->type != BL_MER || skill_num == 0 ) + damage <<= 1; // Lex Aeterna only doubles damage of regular attacks from mercenaries - if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON)) - status_change_end(bl, SC_AETERNA, INVALID_TIMER); //Shouldn't end until Breaker's non-weapon part connects. - } + if( skill_num != ASC_BREAKER || !(flag&BF_WEAPON) ) + status_change_end(bl, SC_AETERNA, INVALID_TIMER); //Shouldn't end until Breaker's non-weapon part connects. + } #ifdef RENEWAL - if (sc->data[SC_RAID]) { - damage += 20*damage/100; + if( sc->data[SC_RAID] ) + { + damage += 20*damage/100; - if (--sc->data[SC_RAID]->val1 == 0) - status_change_end(bl, SC_RAID, INVALID_TIMER); - } + if (--sc->data[SC_RAID]->val1 == 0) + status_change_end(bl, SC_RAID, INVALID_TIMER); + } #endif - if (damage) { - struct map_session_data *tsd = BL_CAST(BL_PC, src); - if (sc->data[SC_DEEPSLEEP]) { - damage += damage / 2; // 1.5 times more damage while in Deep Sleep. - status_change_end(bl,SC_DEEPSLEEP,INVALID_TIMER); - } - if (tsd && sd && sc->data[SC_CRYSTALIZE] && flag&BF_WEAPON) { - switch (tsd->status.weapon) { - case W_MACE: - case W_2HMACE: - case W_1HAXE: - case W_2HAXE: - damage = damage * 150 / 100; - break; - case W_MUSICAL: - case W_WHIP: - if (!sd->state.arrow_atk) - break; - case W_BOW: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - case W_DAGGER: - case W_1HSWORD: - case W_2HSWORD: - damage = damage * 50 / 100; - break; - } - } - if (sc->data[SC_VOICEOFSIREN]) - status_change_end(bl,SC_VOICEOFSIREN,INVALID_TIMER); - } + if( damage ) { + struct map_session_data *tsd = BL_CAST(BL_PC, src); + if( sc->data[SC_DEEPSLEEP] ) { + damage += damage / 2; // 1.5 times more damage while in Deep Sleep. + status_change_end(bl,SC_DEEPSLEEP,INVALID_TIMER); + } + if( tsd && sd && sc->data[SC_CRYSTALIZE] && flag&BF_WEAPON ){ + switch(tsd->status.weapon){ + case W_MACE: + case W_2HMACE: + case W_1HAXE: + case W_2HAXE: + damage = damage * 150 / 100; + break; + case W_MUSICAL: + case W_WHIP: + if(!sd->state.arrow_atk) + break; + case W_BOW: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + case W_DAGGER: + case W_1HSWORD: + case W_2HSWORD: + damage = damage * 50 / 100; + break; + } + } + if( sc->data[SC_VOICEOFSIREN] ) + status_change_end(bl,SC_VOICEOFSIREN,INVALID_TIMER); + } - //Finally damage reductions.... - // Assumptio doubles the def & mdef on RE mode, otherwise gives a reduction on the final damage. [Igniz] + //Finally damage reductions.... + // Assumptio doubles the def & mdef on RE mode, otherwise gives a reduction on the final damage. [Igniz] #ifndef RENEWAL - if (sc->data[SC_ASSUMPTIO]) { - if (map_flag_vs(bl->m)) - damage = damage*2/3; //Receive 66% damage - else - damage >>= 1; //Receive 50% damage - } + if( sc->data[SC_ASSUMPTIO] ) { + if( map_flag_vs(bl->m) ) + damage = damage*2/3; //Receive 66% damage + else + damage >>= 1; //Receive 50% damage + } #endif - if (sc->data[SC_DEFENDER] && - (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) - damage=damage*(100-sc->data[SC_DEFENDER]->val2)/100; + if(sc->data[SC_DEFENDER] && + (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) + damage=damage*(100-sc->data[SC_DEFENDER]->val2)/100; - if (sc->data[SC_ADJUSTMENT] && - (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) - damage -= 20*damage/100; + if(sc->data[SC_ADJUSTMENT] && + (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) + damage -= 20*damage/100; - if (sc->data[SC_FOGWALL] && skill_num != RK_DRAGONBREATH) { - if (flag&BF_SKILL) //25% reduction - damage -= 25*damage/100; - else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) - damage >>= 2; //75% reduction - } + if(sc->data[SC_FOGWALL] && skill_num != RK_DRAGONBREATH) { + if(flag&BF_SKILL) //25% reduction + damage -= 25*damage/100; + else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) + damage >>= 2; //75% reduction + } - // Compressed code, fixed by map.h [Epoque] - if (src->type == BL_MOB) { - int i; - if (sc->data[SC_MANU_DEF]) - for (i=0; ARRAYLENGTH(mob_manuk)>i; i++) - if (mob_manuk[i]==((TBL_MOB *)src)->class_) { - damage -= sc->data[SC_MANU_DEF]->val1*damage/100; - break; - } - if (sc->data[SC_SPL_DEF]) - for (i=0; ARRAYLENGTH(mob_splendide)>i; i++) - if (mob_splendide[i]==((TBL_MOB *)src)->class_) { - damage -= sc->data[SC_SPL_DEF]->val1*damage/100; - break; - } - } + // Compressed code, fixed by map.h [Epoque] + if (src->type == BL_MOB) { + int i; + if (sc->data[SC_MANU_DEF]) + for (i=0;ARRAYLENGTH(mob_manuk)>i;i++) + if (mob_manuk[i]==((TBL_MOB*)src)->class_) { + damage -= sc->data[SC_MANU_DEF]->val1*damage/100; + break; + } + if (sc->data[SC_SPL_DEF]) + for (i=0;ARRAYLENGTH(mob_splendide)>i;i++) + if (mob_splendide[i]==((TBL_MOB*)src)->class_) { + damage -= sc->data[SC_SPL_DEF]->val1*damage/100; + break; + } + } - if ((sce=sc->data[SC_ARMOR]) && //NPC_DEFENDER - sce->val3&flag && sce->val4&flag) - damage -= damage*sc->data[SC_ARMOR]->val2/100; + if((sce=sc->data[SC_ARMOR]) && //NPC_DEFENDER + sce->val3&flag && sce->val4&flag) + damage -= damage*sc->data[SC_ARMOR]->val2/100; #ifdef RENEWAL - if (sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON || flag&BF_MAGIC) && skill_num != WS_CARTTERMINATION) + if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON || flag&BF_MAGIC) && skill_num != WS_CARTTERMINATION) #else - if (sc->data[SC_ENERGYCOAT] && flag&BF_WEAPON && skill_num != WS_CARTTERMINATION) + if(sc->data[SC_ENERGYCOAT] && flag&BF_WEAPON && skill_num != WS_CARTTERMINATION) #endif - { - struct status_data *status = status_get_status_data(bl); - int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval - per /=20; //Uses 20% SP intervals. - //SP Cost: 1% + 0.5% per every 20% SP - if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000)) - status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER); - //Reduction: 6% + 6% every 20% - damage -= damage * 6 * (1+per) / 100; - } - if (sc->data[SC_GRANITIC_ARMOR]) { - damage -= damage * sc->data[SC_GRANITIC_ARMOR]->val2/100; - } - if (sc->data[SC_PAIN_KILLER]) { - damage -= damage * sc->data[SC_PAIN_KILLER]->val3/100; - } - if ((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2)) { - skill_castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,gettick(),0); - } + { + struct status_data *status = status_get_status_data(bl); + int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval + per /=20; //Uses 20% SP intervals. + //SP Cost: 1% + 0.5% per every 20% SP + if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000)) + status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER); + //Reduction: 6% + 6% every 20% + damage -= damage * 6 * (1+per) / 100; + } + if(sc->data[SC_GRANITIC_ARMOR]){ + damage -= damage * sc->data[SC_GRANITIC_ARMOR]->val2/100; + } + if(sc->data[SC_PAIN_KILLER]){ + damage -= damage * sc->data[SC_PAIN_KILLER]->val3/100; + } + if((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ){ + skill_castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,gettick(),0); + } - /** - * In renewal steel body reduces all incoming damage by 1/10 - **/ +/** + * In renewal steel body reduces all incoming damage by 1/10 + **/ #ifdef RENEWAL - if (sc->data[SC_STEELBODY]) { - damage = damage > 10 ? damage / 10 : 1; - } + if( sc->data[SC_STEELBODY] ) { + damage = damage > 10 ? damage / 10 : 1; + } #endif - //Finally added to remove the status of immobile when aimedbolt is used. [Jobbie] - if (skill_num == RA_AIMEDBOLT && (sc->data[SC_BITE] || sc->data[SC_ANKLE] || sc->data[SC_ELECTRICSHOCKER])) { - status_change_end(bl, SC_BITE, INVALID_TIMER); - status_change_end(bl, SC_ANKLE, INVALID_TIMER); - status_change_end(bl, SC_ELECTRICSHOCKER, INVALID_TIMER); - } + //Finally added to remove the status of immobile when aimedbolt is used. [Jobbie] + if( skill_num == RA_AIMEDBOLT && (sc->data[SC_BITE] || sc->data[SC_ANKLE] || sc->data[SC_ELECTRICSHOCKER]) ) + { + status_change_end(bl, SC_BITE, INVALID_TIMER); + status_change_end(bl, SC_ANKLE, INVALID_TIMER); + status_change_end(bl, SC_ELECTRICSHOCKER, INVALID_TIMER); + } - //Finally Kyrie because it may, or not, reduce damage to 0. - if ((sce = sc->data[SC_KYRIE]) && damage > 0) { - sce->val2-=damage; - if (flag&BF_WEAPON || skill_num == TF_THROWSTONE) { - if (sce->val2>=0) - damage=0; - else - damage=-sce->val2; - } - if ((--sce->val3)<=0 || (sce->val2<=0) || skill_num == AL_HOLYLIGHT) - status_change_end(bl, SC_KYRIE, INVALID_TIMER); - } + //Finally Kyrie because it may, or not, reduce damage to 0. + if((sce = sc->data[SC_KYRIE]) && damage > 0){ + sce->val2-=damage; + if(flag&BF_WEAPON || skill_num == TF_THROWSTONE){ + if(sce->val2>=0) + damage=0; + else + damage=-sce->val2; + } + if((--sce->val3)<=0 || (sce->val2<=0) || skill_num == AL_HOLYLIGHT) + status_change_end(bl, SC_KYRIE, INVALID_TIMER); + } - if (sc->data[SC_MEIKYOUSISUI] && rand()%100 < 40) // custom value - damage = 0; + if( sc->data[SC_MEIKYOUSISUI] && rand()%100 < 40 ) // custom value + damage = 0; - if (!damage) return 0; + if (!damage) return 0; - if ((sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1) { - int dx[8]= {0,-1,-1,-1,0,1,1,1}; - int dy[8]= {1,1,0,-1,-1,-1,0,1}; - int dir = map_calc_dir(bl, src->x, src->y); - if (unit_movepos(bl, src->x-dx[dir], src->y-dy[dir], 1, 1)) { - clif_slide(bl,src->x-dx[dir],src->y-dy[dir]); - unit_setdir(bl, dir); - } - d->dmg_lv = ATK_DEF; - status_change_end(bl, SC_LIGHTNINGWALK, INVALID_TIMER); - return 0; - } + if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1 ) { + int dx[8]={0,-1,-1,-1,0,1,1,1}; + int dy[8]={1,1,0,-1,-1,-1,0,1}; + int dir = map_calc_dir(bl, src->x, src->y); + if( unit_movepos(bl, src->x-dx[dir], src->y-dy[dir], 1, 1) ) { + clif_slide(bl,src->x-dx[dir],src->y-dy[dir]); + unit_setdir(bl, dir); + } + d->dmg_lv = ATK_DEF; + status_change_end(bl, SC_LIGHTNINGWALK, INVALID_TIMER); + return 0; + } - //Probably not the most correct place, but it'll do here - //(since battle_drain is strictly for players currently) - if ((sce=sc->data[SC_BLOODLUST]) && flag&BF_WEAPON && damage > 0 && - rnd()%100 < sce->val3) - status_heal(src, damage*sce->val4/100, 0, 3); + //Probably not the most correct place, but it'll do here + //(since battle_drain is strictly for players currently) + if ((sce=sc->data[SC_BLOODLUST]) && flag&BF_WEAPON && damage > 0 && + rnd()%100 < sce->val3) + status_heal(src, damage*sce->val4/100, 0, 3); - if (sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2) - pc_addspiritball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3); - if (sc->data[SC_STYLE_CHANGE] && rnd() % 100 < 50) { + if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 ) + pc_addspiritball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3); + if (sc->data[SC_STYLE_CHANGE] && rnd() % 100 < 50) { TBL_HOM *hd = BL_CAST(BL_HOM,bl); if (hd) hom_addspiritball(hd, 10); //add a sphere } - if (sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1) - status_change_spread(bl, src); // Deadly infect attacked side - - if (sc && sc->data[SC__SHADOWFORM]) { - struct block_list *s_bl = map_id2bl(sc->data[SC__SHADOWFORM]->val2); - if (!s_bl) { // If the shadow form target is not present remove the sc. - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - } else if (status_isdead(s_bl) || !battle_check_target(src,s_bl,BCT_ENEMY)) { // If the shadow form target is dead or not your enemy remove the sc in both. - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - if (s_bl->type == BL_PC) - ((TBL_PC *)s_bl)->shadowform_id = 0; - } else { - if ((--sc->data[SC__SHADOWFORM]->val3) < 0) { // If you have exceded max hits supported, remove the sc in both. - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - if (s_bl->type == BL_PC) - ((TBL_PC *)s_bl)->shadowform_id = 0; - } else { - status_damage(src, s_bl, damage, 0, clif_damage(s_bl, s_bl, gettick(), 500, 500, damage, -1, 0, 0), 0); - return ATK_NONE; - } - } - } - - } + if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) + status_change_spread(bl, src); // Deadly infect attacked side + + if( sc && sc->data[SC__SHADOWFORM] ) { + struct block_list *s_bl = map_id2bl(sc->data[SC__SHADOWFORM]->val2); + if( !s_bl ) { // If the shadow form target is not present remove the sc. + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + } else if( status_isdead(s_bl) || !battle_check_target(src,s_bl,BCT_ENEMY)) { // If the shadow form target is dead or not your enemy remove the sc in both. + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + if( s_bl->type == BL_PC ) + ((TBL_PC*)s_bl)->shadowform_id = 0; + } else { + if( (--sc->data[SC__SHADOWFORM]->val3) < 0 ) { // If you have exceded max hits supported, remove the sc in both. + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + if( s_bl->type == BL_PC ) + ((TBL_PC*)s_bl)->shadowform_id = 0; + } else { + status_damage(src, s_bl, damage, 0, clif_damage(s_bl, s_bl, gettick(), 500, 500, damage, -1, 0, 0), 0); + return ATK_NONE; + } + } + } - //SC effects from caster side. - sc = status_get_sc(src); + } - if (sc && sc->count) { - if (sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF]) - damage += damage * 75 / 100; - // [Epoque] - if (bl->type == BL_MOB) { - int i; - - if (((sce=sc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) || - ((sce=sc->data[SC_MANU_MATK]) && (flag&BF_MAGIC)) - ) - for (i=0; ARRAYLENGTH(mob_manuk)>i; i++) - if (((TBL_MOB *)bl)->class_==mob_manuk[i]) { - damage += damage*sce->val1/100; - break; - } - if (((sce=sc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) || - ((sce=sc->data[SC_SPL_MATK]) && (flag&BF_MAGIC)) - ) - for (i=0; ARRAYLENGTH(mob_splendide)>i; i++) - if (((TBL_MOB *)bl)->class_==mob_splendide[i]) { - damage += damage*sce->val1/100; - break; - } - } - if (sc->data[SC_POISONINGWEAPON] && skill_num != GC_VENOMPRESSURE && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < sc->data[SC_POISONINGWEAPON]->val3) - sc_start(bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1)); - if (sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1) - status_change_spread(src, bl); + //SC effects from caster side. + sc = status_get_sc(src); + + if (sc && sc->count) + { + if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) + damage += damage * 75 / 100; + // [Epoque] + if (bl->type == BL_MOB) + { + int i; + + if ( ((sce=sc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) || + ((sce=sc->data[SC_MANU_MATK]) && (flag&BF_MAGIC)) + ) + for (i=0;ARRAYLENGTH(mob_manuk)>i;i++) + if (((TBL_MOB*)bl)->class_==mob_manuk[i]) { + damage += damage*sce->val1/100; + break; + } + if ( ((sce=sc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) || + ((sce=sc->data[SC_SPL_MATK]) && (flag&BF_MAGIC)) + ) + for (i=0;ARRAYLENGTH(mob_splendide)>i;i++) + if (((TBL_MOB*)bl)->class_==mob_splendide[i]) { + damage += damage*sce->val1/100; + break; + } + } + if( sc->data[SC_POISONINGWEAPON] && skill_num != GC_VENOMPRESSURE && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < sc->data[SC_POISONINGWEAPON]->val3 ) + sc_start(bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1)); + if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) + status_change_spread(src, bl); if (sc->data[SC_STYLE_CHANGE] && rnd() % 100 < 50) { TBL_HOM *hd = BL_CAST(BL_HOM,bl); if (hd) hom_addspiritball(hd, 10); } - } + } - if (battle_config.pk_mode && sd && bl->type == BL_PC && damage && map[bl->m].flag.pvp) { - if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] - if (flag&BF_WEAPON) - damage = damage * battle_config.pk_weapon_damage_rate/100; - if (flag&BF_MAGIC) - damage = damage * battle_config.pk_magic_damage_rate/100; - if (flag&BF_MISC) - damage = damage * battle_config.pk_misc_damage_rate/100; - } else { //Normal attacks get reductions based on range. - if (flag & BF_SHORT) - damage = damage * battle_config.pk_short_damage_rate/100; - if (flag & BF_LONG) - damage = damage * battle_config.pk_long_damage_rate/100; - } - if (!damage) damage = 1; - } + if (battle_config.pk_mode && sd && bl->type == BL_PC && damage && map[bl->m].flag.pvp) + { + if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] + if (flag&BF_WEAPON) + damage = damage * battle_config.pk_weapon_damage_rate/100; + if (flag&BF_MAGIC) + damage = damage * battle_config.pk_magic_damage_rate/100; + if (flag&BF_MISC) + damage = damage * battle_config.pk_misc_damage_rate/100; + } else { //Normal attacks get reductions based on range. + if (flag & BF_SHORT) + damage = damage * battle_config.pk_short_damage_rate/100; + if (flag & BF_LONG) + damage = damage * battle_config.pk_long_damage_rate/100; + } + if(!damage) damage = 1; + } - if (battle_config.skill_min_damage && damage > 0 && damage < div_) { - if ((flag&BF_WEAPON && battle_config.skill_min_damage&1) - || (flag&BF_MAGIC && battle_config.skill_min_damage&2) - || (flag&BF_MISC && battle_config.skill_min_damage&4) - ) - damage = div_; - } + if(battle_config.skill_min_damage && damage > 0 && damage < div_) + { + if ((flag&BF_WEAPON && battle_config.skill_min_damage&1) + || (flag&BF_MAGIC && battle_config.skill_min_damage&2) + || (flag&BF_MISC && battle_config.skill_min_damage&4) + ) + damage = div_; + } - if (bl->type == BL_MOB && !status_isdead(bl) && src != bl) { - if (damage > 0) - mobskill_event((TBL_MOB *)bl,src,gettick(),flag); - if (skill_num) - mobskill_event((TBL_MOB *)bl,src,gettick(),MSC_SKILLUSED|(skill_num<<16)); - } - if (sd) { - if (pc_ismadogear(sd) && rnd()%100 < 50) { - short element = skill_get_ele(skill_num, skill_lv); - if (!skill_num || element == -1) { //Take weapon's element - struct status_data *sstatus = NULL; - if (src->type == BL_PC && ((TBL_PC *)src)->bonus.arrow_ele) - element = ((TBL_PC *)src)->bonus.arrow_ele; - else if ((sstatus = status_get_status_data(src))) { - element = sstatus->rhw.ele; - } - } else if (element == -2) //Use enchantment's element - element = status_get_attack_sc_element(src,status_get_sc(src)); - else if (element == -3) //Use random element - element = rnd()%ELE_MAX; - if (element == ELE_FIRE || element == ELE_WATER) - pc_overheat(sd,element == ELE_FIRE ? 1 : -1); - } - } + if( bl->type == BL_MOB && !status_isdead(bl) && src != bl) { + if (damage > 0 ) + mobskill_event((TBL_MOB*)bl,src,gettick(),flag); + if (skill_num) + mobskill_event((TBL_MOB*)bl,src,gettick(),MSC_SKILLUSED|(skill_num<<16)); + } + if( sd ) { + if( pc_ismadogear(sd) && rnd()%100 < 50 ) { + short element = skill_get_ele(skill_num, skill_lv); + if( !skill_num || element == -1 ) { //Take weapon's element + struct status_data *sstatus = NULL; + if( src->type == BL_PC && ((TBL_PC*)src)->bonus.arrow_ele ) + element = ((TBL_PC*)src)->bonus.arrow_ele; + else if( (sstatus = status_get_status_data(src)) ) { + element = sstatus->rhw.ele; + } + } + else if( element == -2 ) //Use enchantment's element + element = status_get_attack_sc_element(src,status_get_sc(src)); + else if( element == -3 ) //Use random element + element = rnd()%ELE_MAX; + if( element == ELE_FIRE || element == ELE_WATER ) + pc_overheat(sd,element == ELE_FIRE ? 1 : -1); + } + } - return damage; + return damage; } /*========================================== @@ -1243,42 +935,45 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag *------------------------------------------*/ int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int damage, int div_, int skill_num, int skill_lv, int flag) { - if (!damage) - return 0; + if( !damage ) + return 0; - if (bl->type == BL_MOB) { - struct mob_data *md = BL_CAST(BL_MOB, bl); - if (map[bl->m].flag.battleground && (md->class_ == MOBID_BLUE_CRYST || md->class_ == MOBID_PINK_CRYST) && flag&BF_SKILL) - return 0; // Crystal cannot receive skill damage on battlegrounds - } + if( bl->type == BL_MOB ) + { + struct mob_data* md = BL_CAST(BL_MOB, bl); + if( map[bl->m].flag.battleground && (md->class_ == MOBID_BLUE_CRYST || md->class_ == MOBID_PINK_CRYST) && flag&BF_SKILL ) + return 0; // Crystal cannot receive skill damage on battlegrounds + } - switch (skill_num) { - case PA_PRESSURE: - case HW_GRAVITATION: - case NJ_ZENYNAGE: - case KO_MUCHANAGE: - break; - default: - if (flag&BF_SKILL) { - //Skills get a different reduction than non-skills. [Skotlex] - if (flag&BF_WEAPON) - damage = damage * battle_config.bg_weapon_damage_rate/100; - if (flag&BF_MAGIC) - damage = damage * battle_config.bg_magic_damage_rate/100; - if (flag&BF_MISC) - damage = damage * battle_config.bg_misc_damage_rate/100; - } else { - //Normal attacks get reductions based on range. - if (flag&BF_SHORT) - damage = damage * battle_config.bg_short_damage_rate/100; - if (flag&BF_LONG) - damage = damage * battle_config.bg_long_damage_rate/100; - } + switch( skill_num ) + { + case PA_PRESSURE: + case HW_GRAVITATION: + case NJ_ZENYNAGE: + case KO_MUCHANAGE: + break; + default: + if( flag&BF_SKILL ) + { //Skills get a different reduction than non-skills. [Skotlex] + if( flag&BF_WEAPON ) + damage = damage * battle_config.bg_weapon_damage_rate/100; + if( flag&BF_MAGIC ) + damage = damage * battle_config.bg_magic_damage_rate/100; + if( flag&BF_MISC ) + damage = damage * battle_config.bg_misc_damage_rate/100; + } + else + { //Normal attacks get reductions based on range. + if( flag&BF_SHORT ) + damage = damage * battle_config.bg_short_damage_rate/100; + if( flag&BF_LONG ) + damage = damage * battle_config.bg_long_damage_rate/100; + } - if (!damage) damage = 1; - } + if( !damage ) damage = 1; + } - return damage; + return damage; } /*========================================== @@ -1286,65 +981,65 @@ int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int dam *------------------------------------------*/ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag) { - struct mob_data *md = BL_CAST(BL_MOB, bl); - int class_ = status_get_class(bl); + struct mob_data* md = BL_CAST(BL_MOB, bl); + int class_ = status_get_class(bl); - if (!damage) //No reductions to make. - return 0; + if (!damage) //No reductions to make. + return 0; - if (md && md->guardian_data) { - if (class_ == MOBID_EMPERIUM && flag&BF_SKILL) { - //Skill immunity. - switch (skill_num) { + if(md && md->guardian_data) { + if(class_ == MOBID_EMPERIUM && flag&BF_SKILL) { + //Skill immunity. + switch (skill_num) { #ifndef RENEWAL - case MO_TRIPLEATTACK: + case MO_TRIPLEATTACK: #endif - case HW_GRAVITATION: - break; - default: - return 0; - } - } - if (src->type != BL_MOB) { - struct guild *g = guild_search(status_get_guild_id(src)); + case HW_GRAVITATION: + break; + default: + return 0; + } + } + if(src->type != BL_MOB) { + struct guild *g = guild_search(status_get_guild_id(src)); - if (class_ == MOBID_EMPERIUM && (!g || guild_checkskill(g,GD_APPROVAL) <= 0)) - return 0; + if (class_ == MOBID_EMPERIUM && (!g || guild_checkskill(g,GD_APPROVAL) <= 0 )) + return 0; - if (g && battle_config.guild_max_castles && guild_checkcastles(g)>=battle_config.guild_max_castles) - return 0; // [MouseJstr] - } - } + if (g && battle_config.guild_max_castles && guild_checkcastles(g)>=battle_config.guild_max_castles) + return 0; // [MouseJstr] + } + } - switch (skill_num) { - //Skills with no damage reduction. - case PA_PRESSURE: - case HW_GRAVITATION: - case NJ_ZENYNAGE: - case KO_MUCHANAGE: - break; - default: - /* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka] - if (md && md->guardian_data) { - damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100; - } - */ - if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] - if (flag&BF_WEAPON) - damage = damage * battle_config.gvg_weapon_damage_rate/100; - if (flag&BF_MAGIC) - damage = damage * battle_config.gvg_magic_damage_rate/100; - if (flag&BF_MISC) - damage = damage * battle_config.gvg_misc_damage_rate/100; - } else { //Normal attacks get reductions based on range. - if (flag & BF_SHORT) - damage = damage * battle_config.gvg_short_damage_rate/100; - if (flag & BF_LONG) - damage = damage * battle_config.gvg_long_damage_rate/100; - } - if (!damage) damage = 1; - } - return damage; + switch (skill_num) { + //Skills with no damage reduction. + case PA_PRESSURE: + case HW_GRAVITATION: + case NJ_ZENYNAGE: + case KO_MUCHANAGE: + break; + default: + /* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka] + if (md && md->guardian_data) { + damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100; + } + */ + if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] + if (flag&BF_WEAPON) + damage = damage * battle_config.gvg_weapon_damage_rate/100; + if (flag&BF_MAGIC) + damage = damage * battle_config.gvg_magic_damage_rate/100; + if (flag&BF_MISC) + damage = damage * battle_config.gvg_misc_damage_rate/100; + } else { //Normal attacks get reductions based on range. + if (flag & BF_SHORT) + damage = damage * battle_config.gvg_short_damage_rate/100; + if (flag & BF_LONG) + damage = damage * battle_config.gvg_long_damage_rate/100; + } + if(!damage) damage = 1; + } + return damage; } /*========================================== @@ -1352,18 +1047,18 @@ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int dama *------------------------------------------*/ static int battle_calc_drain(int damage, int rate, int per) { - int diff = 0; - - if (per && rnd()%1000 < rate) { - diff = (damage * per) / 100; - if (diff == 0) { - if (per > 0) - diff = 1; - else - diff = -1; - } - } - return diff; + int diff = 0; + + if (per && rnd()%1000 < rate) { + diff = (damage * per) / 100; + if (diff == 0) { + if (per > 0) + diff = 1; + else + diff = -1; + } + } + return diff; } /*========================================== @@ -1371,105 +1066,106 @@ static int battle_calc_drain(int damage, int rate, int per) *------------------------------------------*/ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type) { - int damage,skill; - struct status_data *status = status_get_status_data(target); - int weapon; - damage = dmg; - - nullpo_ret(sd); - - if ((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 && - target->type == BL_MOB && //This bonus doesnt work against players. - (battle_check_undead(status->race,status->def_ele) || status->race==RC_DEMON)) - damage += (skill*(int)(3+(sd->status.base_level+1)*0.05)); // submitted by orn - //damage += (skill * 3); - if ((skill = pc_checkskill(sd, RA_RANGERMAIN)) > 0 && (status->race == RC_BRUTE || status->race == RC_PLANT || status->race == RC_FISH)) - damage += (skill * 5); - if ((skill = pc_checkskill(sd,NC_RESEARCHFE)) > 0 && (status->def_ele == ELE_FIRE || status->def_ele == ELE_EARTH)) - damage += (skill * 10); - if (pc_ismadogear(sd)) - damage += 20 + 20 * pc_checkskill(sd, NC_MADOLICENCE); - - if ((skill = pc_checkskill(sd,HT_BEASTBANE)) > 0 && (status->race==RC_BRUTE || status->race==RC_INSECT)) { - damage += (skill * 4); - if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_HUNTER) - damage += sd->status.str; - } + int damage,skill; + struct status_data *status = status_get_status_data(target); + int weapon; + damage = dmg; + + nullpo_ret(sd); + + if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 && + target->type == BL_MOB && //This bonus doesnt work against players. + (battle_check_undead(status->race,status->def_ele) || status->race==RC_DEMON) ) + damage += (skill*(int)(3+(sd->status.base_level+1)*0.05)); // submitted by orn + //damage += (skill * 3); + if( (skill = pc_checkskill(sd, RA_RANGERMAIN)) > 0 && (status->race == RC_BRUTE || status->race == RC_PLANT || status->race == RC_FISH) ) + damage += (skill * 5); + if( (skill = pc_checkskill(sd,NC_RESEARCHFE)) > 0 && (status->def_ele == ELE_FIRE || status->def_ele == ELE_EARTH) ) + damage += (skill * 10); + if( pc_ismadogear(sd) ) + damage += 20 + 20 * pc_checkskill(sd, NC_MADOLICENCE); + + if((skill = pc_checkskill(sd,HT_BEASTBANE)) > 0 && (status->race==RC_BRUTE || status->race==RC_INSECT) ) { + damage += (skill * 4); + if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_HUNTER) + damage += sd->status.str; + } - if (type == 0) - weapon = sd->weapontype1; - else - weapon = sd->weapontype2; - switch (weapon) { - case W_1HSWORD: -#ifdef RENEWAL - if ((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) - damage += (skill * 3); -#endif - case W_DAGGER: - if ((skill = pc_checkskill(sd,SM_SWORD)) > 0) - damage += (skill * 4); - if ((skill = pc_checkskill(sd,GN_TRAINING_SWORD)) > 0) - damage += skill * 10; - break; - case W_2HSWORD: -#ifdef RENEWAL - if ((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) - damage += (skill * 3); -#endif - if ((skill = pc_checkskill(sd,SM_TWOHAND)) > 0) - damage += (skill * 4); - break; - case W_1HSPEAR: - case W_2HSPEAR: - if ((skill = pc_checkskill(sd,KN_SPEARMASTERY)) > 0) { - if (!pc_isriding(sd)) - damage += (skill * 4); - else - damage += (skill * 5); - } - break; - case W_1HAXE: - case W_2HAXE: - if ((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) - damage += (skill * 3); - if ((skill = pc_checkskill(sd,NC_TRAININGAXE)) > 0) - damage += (skill * 5); - break; - case W_MACE: - case W_2HMACE: - if ((skill = pc_checkskill(sd,PR_MACEMASTERY)) > 0) - damage += (skill * 3); - if ((skill = pc_checkskill(sd,NC_TRAININGAXE)) > 0) - damage += (skill * 5); - break; - case W_FIST: - if ((skill = pc_checkskill(sd,TK_RUN)) > 0) - damage += (skill * 10); - // No break, fallthrough to Knuckles - case W_KNUCKLE: - if ((skill = pc_checkskill(sd,MO_IRONHAND)) > 0) - damage += (skill * 3); - break; - case W_MUSICAL: - if ((skill = pc_checkskill(sd,BA_MUSICALLESSON)) > 0) - damage += (skill * 3); - break; - case W_WHIP: - if ((skill = pc_checkskill(sd,DC_DANCINGLESSON)) > 0) - damage += (skill * 3); - break; - case W_BOOK: - if ((skill = pc_checkskill(sd,SA_ADVANCEDBOOK)) > 0) - damage += (skill * 3); - break; - case W_KATAR: - if ((skill = pc_checkskill(sd,AS_KATAR)) > 0) - damage += (skill * 3); - break; - } + if(type == 0) + weapon = sd->weapontype1; + else + weapon = sd->weapontype2; + switch(weapon) + { + case W_1HSWORD: + #ifdef RENEWAL + if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) + damage += (skill * 3); + #endif + case W_DAGGER: + if((skill = pc_checkskill(sd,SM_SWORD)) > 0) + damage += (skill * 4); + if((skill = pc_checkskill(sd,GN_TRAINING_SWORD)) > 0) + damage += skill * 10; + break; + case W_2HSWORD: + #ifdef RENEWAL + if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) + damage += (skill * 3); + #endif + if((skill = pc_checkskill(sd,SM_TWOHAND)) > 0) + damage += (skill * 4); + break; + case W_1HSPEAR: + case W_2HSPEAR: + if((skill = pc_checkskill(sd,KN_SPEARMASTERY)) > 0) { + if(!pc_isriding(sd)) + damage += (skill * 4); + else + damage += (skill * 5); + } + break; + case W_1HAXE: + case W_2HAXE: + if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0) + damage += (skill * 3); + if((skill = pc_checkskill(sd,NC_TRAININGAXE)) > 0) + damage += (skill * 5); + break; + case W_MACE: + case W_2HMACE: + if((skill = pc_checkskill(sd,PR_MACEMASTERY)) > 0) + damage += (skill * 3); + if((skill = pc_checkskill(sd,NC_TRAININGAXE)) > 0) + damage += (skill * 5); + break; + case W_FIST: + if((skill = pc_checkskill(sd,TK_RUN)) > 0) + damage += (skill * 10); + // No break, fallthrough to Knuckles + case W_KNUCKLE: + if((skill = pc_checkskill(sd,MO_IRONHAND)) > 0) + damage += (skill * 3); + break; + case W_MUSICAL: + if((skill = pc_checkskill(sd,BA_MUSICALLESSON)) > 0) + damage += (skill * 3); + break; + case W_WHIP: + if((skill = pc_checkskill(sd,DC_DANCINGLESSON)) > 0) + damage += (skill * 3); + break; + case W_BOOK: + if((skill = pc_checkskill(sd,SA_ADVANCEDBOOK)) > 0) + damage += (skill * 3); + break; + case W_KATAR: + if((skill = pc_checkskill(sd,AS_KATAR)) > 0) + damage += (skill * 3); + break; + } - return damage; + return damage; } /*========================================== * Calculates the standard damage of a normal attack assuming it hits, @@ -1485,138 +1181,139 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int */ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) { - unsigned short atkmin=0, atkmax=0; - short type = 0; - int damage = 0; - - if (!sd) { - //Mobs/Pets - if (flag&4) { - atkmin = status->matk_min; - atkmax = status->matk_max; - } else { - atkmin = wa->atk; - atkmax = wa->atk2; - } - if (atkmin > atkmax) - atkmin = atkmax; - } else { //PCs - atkmax = wa->atk; - type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R; - - if (!(flag&1) || (flag&2)) { - //Normal attacks - atkmin = status->dex; - - if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]]) - atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100; - - if (atkmin > atkmax) - atkmin = atkmax; - - if (flag&2 && !(flag&16)) { - //Bows - atkmin = atkmin*atkmax/100; - if (atkmin > atkmax) - atkmax = atkmin; - } - } - } + unsigned short atkmin=0, atkmax=0; + short type = 0; + int damage = 0; + + if (!sd) + { //Mobs/Pets + if(flag&4) + { + atkmin = status->matk_min; + atkmax = status->matk_max; + } else { + atkmin = wa->atk; + atkmax = wa->atk2; + } + if (atkmin > atkmax) + atkmin = atkmax; + } else { //PCs + atkmax = wa->atk; + type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R; + + if (!(flag&1) || (flag&2)) + { //Normal attacks + atkmin = status->dex; + + if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]]) + atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100; + + if (atkmin > atkmax) + atkmin = atkmax; + + if(flag&2 && !(flag&16)) + { //Bows + atkmin = atkmin*atkmax/100; + if (atkmin > atkmax) + atkmax = atkmin; + } + } + } - if (sc && sc->data[SC_MAXIMIZEPOWER]) - atkmin = atkmax; - - //Weapon Damage calculation - if (!(flag&1)) - damage = (atkmax>atkmin? rnd()%(atkmax-atkmin):0)+atkmin; - else - damage = atkmax; - - if (sd) { - //rodatazone says the range is 0~arrow_atk-1 for non crit - if (flag&2 && sd->bonus.arrow_atk) - damage += ((flag&1) ? sd->bonus.arrow_atk : rnd()%sd->bonus.arrow_atk); - - //SizeFix only for players - if (!(sd->special_state.no_sizefix || (flag&8))) - damage = damage*(type==EQI_HAND_L? - sd->left_weapon.atkmods[t_size]: - sd->right_weapon.atkmods[t_size])/100; - } + if (sc && sc->data[SC_MAXIMIZEPOWER]) + atkmin = atkmax; + + //Weapon Damage calculation + if (!(flag&1)) + damage = (atkmax>atkmin? rnd()%(atkmax-atkmin):0)+atkmin; + else + damage = atkmax; + + if (sd) + { + //rodatazone says the range is 0~arrow_atk-1 for non crit + if (flag&2 && sd->bonus.arrow_atk) + damage += ( (flag&1) ? sd->bonus.arrow_atk : rnd()%sd->bonus.arrow_atk ); + + //SizeFix only for players + if (!(sd->special_state.no_sizefix || (flag&8))) + damage = damage*(type==EQI_HAND_L? + sd->left_weapon.atkmods[t_size]: + sd->right_weapon.atkmods[t_size])/100; + } - //Finally, add baseatk - if (flag&4) - damage += status->matk_min; - else - damage += status->batk; - - //rodatazone says that Overrefine bonuses are part of baseatk - //Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands. - if (sd) { - if (type == EQI_HAND_L) { - if (sd->left_weapon.overrefine) - damage += rnd()%sd->left_weapon.overrefine+1; - if (sd->weapon_atk_rate[sd->weapontype2]) - damage += damage*sd->weapon_atk_rate[sd->weapontype2]/100;; - } else { //Right hand - if (sd->right_weapon.overrefine) - damage += rnd()%sd->right_weapon.overrefine+1; - if (sd->weapon_atk_rate[sd->weapontype1]) - damage += damage*sd->weapon_atk_rate[sd->weapontype1]/100;; - } - } - return damage; + //Finally, add baseatk + if(flag&4) + damage += status->matk_min; + else + damage += status->batk; + + //rodatazone says that Overrefine bonuses are part of baseatk + //Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands. + if(sd) { + if (type == EQI_HAND_L) { + if(sd->left_weapon.overrefine) + damage += rnd()%sd->left_weapon.overrefine+1; + if (sd->weapon_atk_rate[sd->weapontype2]) + damage += damage*sd->weapon_atk_rate[sd->weapontype2]/100;; + } else { //Right hand + if(sd->right_weapon.overrefine) + damage += rnd()%sd->right_weapon.overrefine+1; + if (sd->weapon_atk_rate[sd->weapontype1]) + damage += damage*sd->weapon_atk_rate[sd->weapontype1]/100;; + } + } + return damage; } /*========================================== * Consumes ammo for the given skill. *------------------------------------------*/ -void battle_consume_ammo(TBL_PC *sd, int skill, int lv) +void battle_consume_ammo(TBL_PC*sd, int skill, int lv) { - int qty=1; - if (!battle_config.arrow_decrement) - return; + int qty=1; + if (!battle_config.arrow_decrement) + return; - if (skill) { - qty = skill_get_ammo_qty(skill, lv); - if (!qty) qty = 1; - } + if (skill) { + qty = skill_get_ammo_qty(skill, lv); + if (!qty) qty = 1; + } - if (sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition - pc_delitem(sd,sd->equip_index[EQI_AMMO],qty,0,1,LOG_TYPE_CONSUME); + if(sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition + pc_delitem(sd,sd->equip_index[EQI_AMMO],qty,0,1,LOG_TYPE_CONSUME); - sd->state.arrow_atk = 0; + sd->state.arrow_atk = 0; } static int battle_range_type( - struct block_list *src, struct block_list *target, - int skill_num, int skill_lv) -{ - //Skill Range Criteria - if (battle_config.skillrange_by_distance && - (src->type&battle_config.skillrange_by_distance) - ) { //based on distance between src/target [Skotlex] - if (check_distance_bl(src, target, 5)) - return BF_SHORT; - return BF_LONG; - } - //based on used skill's range - if (skill_get_range2(src, skill_num, skill_lv) < 5) - return BF_SHORT; - return BF_LONG; + struct block_list *src, struct block_list *target, + int skill_num, int skill_lv) +{ //Skill Range Criteria + if (battle_config.skillrange_by_distance && + (src->type&battle_config.skillrange_by_distance) + ) { //based on distance between src/target [Skotlex] + if (check_distance_bl(src, target, 5)) + return BF_SHORT; + return BF_LONG; + } + //based on used skill's range + if (skill_get_range2(src, skill_num, skill_lv) < 5) + return BF_SHORT; + return BF_LONG; } static int battle_blewcount_bonus(struct map_session_data *sd, int skill_num) { - int i; - if (!sd->skillblown[0].id) - return 0; - //Apply the bonus blewcount. [Skotlex] - for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) { - if (sd->skillblown[i].id == skill_num) - return sd->skillblown[i].val; - } - return 0; + int i; + if (!sd->skillblown[0].id) + return 0; + //Apply the bonus blewcount. [Skotlex] + for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) { + if (sd->skillblown[i].id == skill_num) + return sd->skillblown[i].val; + } + return 0; } struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag); @@ -1627,3411 +1324,3741 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * /*========================================== * battle_calc_weapon_attack (by Skotlex) *------------------------------------------*/ -static struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int wflag) { - unsigned int skillratio = 100; //Skill dmg modifiers. - short skill=0; - short s_ele, s_ele_, t_class; - int i, nk; - bool n_ele = false; // non-elemental - - struct map_session_data *sd, *tsd; - struct Damage wd; - struct status_change *sc = status_get_sc(src); - struct status_change *tsc = status_get_sc(target); - struct status_data *sstatus = status_get_status_data(src); - struct status_data *tstatus = status_get_status_data(target); - struct { - unsigned hit : 1; //the attack Hit? (not a miss) - unsigned cri : 1; //Critical hit - unsigned idef : 1; //Ignore defense - unsigned idef2 : 1; //Ignore defense (left weapon) - unsigned pdef : 2; //Pierces defense (Investigate/Ice Pick) - unsigned pdef2 : 2; //1: Use def+def2/100, 2: Use def+def2/50 - unsigned infdef : 1; //Infinite defense (plants) - unsigned arrow : 1; //Attack is arrow-based - unsigned rh : 1; //Attack considers right hand (wd.damage) - unsigned lh : 1; //Attack considers left hand (wd.damage2) - unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that) - } flag; - - memset(&wd,0,sizeof(wd)); - memset(&flag,0,sizeof(flag)); - - if (src==NULL || target==NULL) { - nullpo_info(NLP_MARK); - return wd; - } - //Initial flag - flag.rh=1; - flag.weapon=1; - flag.infdef=(tstatus->mode&MD_PLANT && skill_num != RA_CLUSTERBOMB +static struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int wflag) +{ + unsigned int skillratio = 100; //Skill dmg modifiers. + short skill=0; + short s_ele, s_ele_, t_class; + int i, nk; + bool n_ele = false; // non-elemental + + struct map_session_data *sd, *tsd; + struct Damage wd; + struct status_change *sc = status_get_sc(src); + struct status_change *tsc = status_get_sc(target); + struct status_data *sstatus = status_get_status_data(src); + struct status_data *tstatus = status_get_status_data(target); + struct { + unsigned hit : 1; //the attack Hit? (not a miss) + unsigned cri : 1; //Critical hit + unsigned idef : 1; //Ignore defense + unsigned idef2 : 1; //Ignore defense (left weapon) + unsigned pdef : 2; //Pierces defense (Investigate/Ice Pick) + unsigned pdef2 : 2; //1: Use def+def2/100, 2: Use def+def2/50 + unsigned infdef : 1; //Infinite defense (plants) + unsigned arrow : 1; //Attack is arrow-based + unsigned rh : 1; //Attack considers right hand (wd.damage) + unsigned lh : 1; //Attack considers left hand (wd.damage2) + unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that) + } flag; + + memset(&wd,0,sizeof(wd)); + memset(&flag,0,sizeof(flag)); + + if(src==NULL || target==NULL) + { + nullpo_info(NLP_MARK); + return wd; + } + //Initial flag + flag.rh=1; + flag.weapon=1; + flag.infdef=(tstatus->mode&MD_PLANT && skill_num != RA_CLUSTERBOMB #ifdef RENEWAL - && skill_num != HT_FREEZINGTRAP + && skill_num != HT_FREEZINGTRAP #endif - ?1:0); - if (target->type == BL_SKILL) { - TBL_SKILL *su = (TBL_SKILL *)target; - if (su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD)) - flag.infdef = 1; - } + ?1:0); + if( target->type == BL_SKILL){ + TBL_SKILL *su = (TBL_SKILL*)target; + if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) + flag.infdef = 1; + } + + //Initial Values + wd.type=0; //Normal attack + wd.div_=skill_num?skill_get_num(skill_num,skill_lv):1; + wd.amotion=(skill_num && skill_get_inf(skill_num)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. + if(skill_num == KN_AUTOCOUNTER) + wd.amotion >>= 1; + wd.dmotion=tstatus->dmotion; + wd.blewcount=skill_get_blewcount(skill_num,skill_lv); + wd.flag = BF_WEAPON; //Initial Flag + wd.flag |= (skill_num||wflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish] + wd.dmg_lv=ATK_DEF; //This assumption simplifies the assignation later + nk = skill_get_nk(skill_num); + if( !skill_num && wflag ) //If flag, this is splash damage from Baphomet Card and it always hits. + nk |= NK_NO_CARDFIX_ATK|NK_IGNORE_FLEE; + flag.hit = nk&NK_IGNORE_FLEE?1:0; + flag.idef = flag.idef2 = nk&NK_IGNORE_DEF?1:0; + + if (sc && !sc->count) + sc = NULL; //Skip checking as there are no status changes active. + if (tsc && !tsc->count) + tsc = NULL; //Skip checking as there are no status changes active. + + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, target); - //Initial Values - wd.type=0; //Normal attack - wd.div_=skill_num?skill_get_num(skill_num,skill_lv):1; - wd.amotion=(skill_num && skill_get_inf(skill_num)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. - if (skill_num == KN_AUTOCOUNTER) - wd.amotion >>= 1; - wd.dmotion=tstatus->dmotion; - wd.blewcount=skill_get_blewcount(skill_num,skill_lv); - wd.flag = BF_WEAPON; //Initial Flag - wd.flag |= (skill_num||wflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish] - wd.dmg_lv=ATK_DEF; //This assumption simplifies the assignation later - nk = skill_get_nk(skill_num); - if (!skill_num && wflag) //If flag, this is splash damage from Baphomet Card and it always hits. - nk |= NK_NO_CARDFIX_ATK|NK_IGNORE_FLEE; - flag.hit = nk &NK_IGNORE_FLEE?1:0; - flag.idef = flag.idef2 = nk &NK_IGNORE_DEF?1:0; - - if (sc && !sc->count) - sc = NULL; //Skip checking as there are no status changes active. - if (tsc && !tsc->count) - tsc = NULL; //Skip checking as there are no status changes active. - - sd = BL_CAST(BL_PC, src); - tsd = BL_CAST(BL_PC, target); - - if (sd) - wd.blewcount += battle_blewcount_bonus(sd, skill_num); - - //Set miscellaneous data that needs be filled regardless of hit/miss - if ( - (sd && sd->state.arrow_atk) || - (!sd && ((skill_num && skill_get_ammotype(skill_num)) || sstatus->rhw.range>3)) - ) - flag.arrow = 1; - - if (skill_num) { - wd.flag |= battle_range_type(src, target, skill_num, skill_lv); - switch (skill_num) { - case MO_FINGEROFFENSIVE: - if (sd) { - if (battle_config.finger_offensive_type) - wd.div_ = 1; - else - wd.div_ = sd->spiritball_old; - } - break; - case HT_PHANTASMIC: - //Since these do not consume ammo, they need to be explicitly set as arrow attacks. - flag.arrow = 1; - break; + if(sd) + wd.blewcount += battle_blewcount_bonus(sd, skill_num); + + //Set miscellaneous data that needs be filled regardless of hit/miss + if( + (sd && sd->state.arrow_atk) || + (!sd && ((skill_num && skill_get_ammotype(skill_num)) || sstatus->rhw.range>3)) + ) + flag.arrow = 1; + + if(skill_num){ + wd.flag |= battle_range_type(src, target, skill_num, skill_lv); + switch(skill_num) + { + case MO_FINGEROFFENSIVE: + if(sd) { + if (battle_config.finger_offensive_type) + wd.div_ = 1; + else + wd.div_ = sd->spiritball_old; + } + break; + case HT_PHANTASMIC: + //Since these do not consume ammo, they need to be explicitly set as arrow attacks. + flag.arrow = 1; + break; #ifndef RENEWAL - case PA_SHIELDCHAIN: - case CR_SHIELDBOOMERANG: + case PA_SHIELDCHAIN: + case CR_SHIELDBOOMERANG: #endif - case LG_SHIELDPRESS: - case LG_EARTHDRIVE: - flag.weapon = 0; - break; - - case KN_PIERCE: - case ML_PIERCE: - wd.div_= (wd.div_>0?tstatus->size+1:-(tstatus->size+1)); - break; - - case TF_DOUBLE: //For NPC used skill. - case GS_CHAINACTION: - wd.type = 0x08; - break; - - case GS_GROUNDDRIFT: - case KN_SPEARSTAB: - case KN_BOWLINGBASH: - case MS_BOWLINGBASH: - case MO_BALKYOUNG: - case TK_TURNKICK: - wd.blewcount=0; - break; - - case KN_AUTOCOUNTER: - wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL; - break; - - case NPC_CRITICALSLASH: - case LG_PINPOINTATTACK: - flag.cri = 1; //Always critical skill. - break; - - case LK_SPIRALPIERCE: - if (!sd) wd.flag=(wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC; - break; - } - } else //Range for normal attacks. - wd.flag |= flag.arrow?BF_LONG:BF_SHORT; - - if ((!skill_num || skill_num == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2) { - //Check for Lucky Dodge - wd.type=0x0b; - wd.dmg_lv=ATK_LUCKY; - if (wd.div_ < 0) wd.div_*=-1; - return wd; - } + case LG_SHIELDPRESS: + case LG_EARTHDRIVE: + flag.weapon = 0; + break; + + case KN_PIERCE: + case ML_PIERCE: + wd.div_= (wd.div_>0?tstatus->size+1:-(tstatus->size+1)); + break; + + case TF_DOUBLE: //For NPC used skill. + case GS_CHAINACTION: + wd.type = 0x08; + break; + + case GS_GROUNDDRIFT: + case KN_SPEARSTAB: + case KN_BOWLINGBASH: + case MS_BOWLINGBASH: + case MO_BALKYOUNG: + case TK_TURNKICK: + wd.blewcount=0; + break; + + case KN_AUTOCOUNTER: + wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL; + break; + + case NPC_CRITICALSLASH: + case LG_PINPOINTATTACK: + flag.cri = 1; //Always critical skill. + break; + + case LK_SPIRALPIERCE: + if (!sd) wd.flag=(wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC; + break; + } + } else //Range for normal attacks. + wd.flag |= flag.arrow?BF_LONG:BF_SHORT; + + if ( (!skill_num || skill_num == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2 ) + { //Check for Lucky Dodge + wd.type=0x0b; + wd.dmg_lv=ATK_LUCKY; + if (wd.div_ < 0) wd.div_*=-1; + return wd; + } - t_class = status_get_class(target); - s_ele = s_ele_ = skill_get_ele(skill_num, skill_lv); - if (!skill_num || s_ele == -1) { - //Take weapon's element - s_ele = sstatus->rhw.ele; - s_ele_ = sstatus->lhw.ele; - if (sd) { //Summoning 10 talisman will endow your weapon. - ARR_FIND(1, 6, i, sd->talisman[i] >= 10); - if (i < 5) s_ele = s_ele_ = i; - } - if (flag.arrow && sd && sd->bonus.arrow_ele) - s_ele = sd->bonus.arrow_ele; - if (battle_config.attack_attr_none&src->type) - n_ele = true; //Weapon's element is "not elemental" - } else if (s_ele == -2) //Use enchantment's element - s_ele = s_ele_ = status_get_attack_sc_element(src,sc); - else if (s_ele == -3) //Use random element - s_ele = s_ele_ = rnd()%ELE_MAX; - switch (skill_num) { - case GS_GROUNDDRIFT: - s_ele = s_ele_ = wflag; //element comes in flag. - break; - case LK_SPIRALPIERCE: - if (!sd) n_ele = false; //forced neutral for monsters - break; - } + t_class = status_get_class(target); + s_ele = s_ele_ = skill_get_ele(skill_num, skill_lv); + if( !skill_num || s_ele == -1 ) + { //Take weapon's element + s_ele = sstatus->rhw.ele; + s_ele_ = sstatus->lhw.ele; + if( sd ){ //Summoning 10 talisman will endow your weapon. + ARR_FIND(1, 6, i, sd->talisman[i] >= 10); + if( i < 5 ) s_ele = s_ele_ = i; + } + if( flag.arrow && sd && sd->bonus.arrow_ele ) + s_ele = sd->bonus.arrow_ele; + if( battle_config.attack_attr_none&src->type ) + n_ele = true; //Weapon's element is "not elemental" + } + else if( s_ele == -2 ) //Use enchantment's element + s_ele = s_ele_ = status_get_attack_sc_element(src,sc); + else if( s_ele == -3 ) //Use random element + s_ele = s_ele_ = rnd()%ELE_MAX; + switch( skill_num ) + { + case GS_GROUNDDRIFT: + s_ele = s_ele_ = wflag; //element comes in flag. + break; + case LK_SPIRALPIERCE: + if (!sd) n_ele = false; //forced neutral for monsters + break; + } - if (!(nk &NK_NO_ELEFIX) && !n_ele) - if (src->type == BL_HOM) - n_ele = true; //skill is "not elemental" - if (sc && sc->data[SC_GOLDENE_FERSE] && ((!skill_num && (rnd() % 100 < sc->data[SC_GOLDENE_FERSE]->val4)) || skill_num == MH_STAHL_HORN)) { - s_ele = s_ele_ = ELE_HOLY; - n_ele = false; - } + if (!(nk & NK_NO_ELEFIX) && !n_ele) + if (src->type == BL_HOM) + n_ele = true; //skill is "not elemental" + if (sc && sc->data[SC_GOLDENE_FERSE] && ((!skill_num && (rnd() % 100 < sc->data[SC_GOLDENE_FERSE]->val4)) || skill_num == MH_STAHL_HORN)) { + s_ele = s_ele_ = ELE_HOLY; + n_ele = false; + } - if (!skill_num) { - //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2) - if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0) { - flag.rh=0; - flag.lh=1; - } - if (sstatus->lhw.atk) - flag.lh=1; - } + if(!skill_num) + { //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2) + if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0) + { + flag.rh=0; + flag.lh=1; + } + if (sstatus->lhw.atk) + flag.lh=1; + } - if (sd && !skill_num) { //Check for double attack. - if (((skill_lv = pc_checkskill(sd,TF_DOUBLE)) > 0 && sd->weapontype1 == W_DAGGER) - || (sd->bonus.double_rate > 0 && sd->weapontype1 != W_FIST) //Will fail bare-handed - || (sc && sc->data[SC_KAGEMUSYA] && sd->weapontype1 != W_FIST)) { // Need confirmation - //Success chance is not added, the higher one is used [Skotlex] - if (rnd()%100 < (5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate)) { - wd.div_ = skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1); - wd.type = 0x08; - } - } else if (sd->weapontype1 == W_REVOLVER && (skill_lv = pc_checkskill(sd,GS_CHAINACTION)) > 0 && rnd()%100 < 5*skill_lv) { - wd.div_ = skill_get_num(GS_CHAINACTION,skill_lv); - wd.type = 0x08; - } else if (sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1) { - short rate[] = { 4, 4, 7, 9, 10 }; - if (sc->data[SC_FEARBREEZE]->val1 > 0 && sc->data[SC_FEARBREEZE]->val1 < 6 && rand()%100 < rate[sc->data[SC_FEARBREEZE]->val1-1]) { - wd.type = 0x08; - wd.div_ = 2; - if (sc->data[SC_FEARBREEZE]->val1 > 2) { - int chance = rand()%100; - wd.div_ += (chance >= 40) + (chance >= 70) + (chance >= 90); - wd.div_ = min(wd.div_,sc->data[SC_FEARBREEZE]->val1); - } - wd.div_ = min(wd.div_,sd->status.inventory[i].amount); - sc->data[SC_FEARBREEZE]->val4 = wd.div_-1; - } - } - } + if( sd && !skill_num ) { //Check for double attack. + if( ( ( skill_lv = pc_checkskill(sd,TF_DOUBLE) ) > 0 && sd->weapontype1 == W_DAGGER ) + || ( sd->bonus.double_rate > 0 && sd->weapontype1 != W_FIST ) //Will fail bare-handed + || ( sc && sc->data[SC_KAGEMUSYA] && sd->weapontype1 != W_FIST )) // Need confirmation + { //Success chance is not added, the higher one is used [Skotlex] + if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) ) + { + wd.div_ = skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1); + wd.type = 0x08; + } + } + else if( sd->weapontype1 == W_REVOLVER && (skill_lv = pc_checkskill(sd,GS_CHAINACTION)) > 0 && rnd()%100 < 5*skill_lv ) + { + wd.div_ = skill_get_num(GS_CHAINACTION,skill_lv); + wd.type = 0x08; + } + else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1){ + short rate[] = { 4, 4, 7, 9, 10 }; + if(sc->data[SC_FEARBREEZE]->val1 > 0 && sc->data[SC_FEARBREEZE]->val1 < 6 && rand()%100 < rate[sc->data[SC_FEARBREEZE]->val1-1]) { + wd.type = 0x08; + wd.div_ = 2; + if(sc->data[SC_FEARBREEZE]->val1 > 2){ + int chance = rand()%100; + wd.div_ += (chance >= 40) + (chance >= 70) + (chance >= 90); + wd.div_ = min(wd.div_,sc->data[SC_FEARBREEZE]->val1); + } + wd.div_ = min(wd.div_,sd->status.inventory[i].amount); + sc->data[SC_FEARBREEZE]->val4 = wd.div_-1; + } + } + } - //Check for critical - if (!flag.cri && !(wd.type&0x08) && sstatus->cri && - (!skill_num || - skill_num == KN_AUTOCOUNTER || - skill_num == SN_SHARPSHOOTING || skill_num == MA_SHARPSHOOTING || - skill_num == NJ_KIRIKAGE)) { - short cri = sstatus->cri; - if (sd) { - cri+= sd->critaddrace[tstatus->race]; - if (flag.arrow) - cri += sd->bonus.arrow_cri; - } - if (sc && sc->data[SC_CAMOUFLAGE]) - cri += 10 * (10-sc->data[SC_CAMOUFLAGE]->val4); - //The official equation is *2, but that only applies when sd's do critical. - //Therefore, we use the old value 3 on cases when an sd gets attacked by a mob - cri -= tstatus->luk*(!sd&&tsd?3:2); - - if (tsc && tsc->data[SC_SLEEP]) { - cri <<= 1; - } - switch (skill_num) { - case KN_AUTOCOUNTER: - if (battle_config.auto_counter_type && - (battle_config.auto_counter_type&src->type)) - flag.cri = 1; - else - cri <<= 1; - break; - case SN_SHARPSHOOTING: - case MA_SHARPSHOOTING: - cri += 200; - break; - case NJ_KIRIKAGE: - cri += 250 + 50*skill_lv; - break; - } - if (tsd && tsd->bonus.critical_def) - cri = cri * (100 - tsd->bonus.critical_def) / 100; - if (rnd()%1000 < cri) - flag.cri = 1; - } - if (flag.cri) { - wd.type = 0x0a; - flag.idef = flag.idef2 = flag.hit = 1; - } else { //Check for Perfect Hit - if (sd && sd->bonus.perfect_hit > 0 && rnd()%100 < sd->bonus.perfect_hit) - flag.hit = 1; - if (sc && sc->data[SC_FUSION]) { - flag.hit = 1; //SG_FUSION always hit [Komurka] - flag.idef = flag.idef2 = 1; //def ignore [Komurka] - } - if (!flag.hit) - switch (skill_num) { - case AS_SPLASHER: - if (!wflag) // Always hits the one exploding. - flag.hit = 1; - break; - case CR_SHIELDBOOMERANG: - if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) - flag.hit = 1; - break; - } - if (tsc && !flag.hit && tsc->opt1 && tsc->opt1 != OPT1_STONEWAIT && tsc->opt1 != OPT1_BURNING) - flag.hit = 1; - } + //Check for critical + if( !flag.cri && !(wd.type&0x08) && sstatus->cri && + (!skill_num || + skill_num == KN_AUTOCOUNTER || + skill_num == SN_SHARPSHOOTING || skill_num == MA_SHARPSHOOTING || + skill_num == NJ_KIRIKAGE)) + { + short cri = sstatus->cri; + if (sd) + { + cri+= sd->critaddrace[tstatus->race]; + if(flag.arrow) + cri += sd->bonus.arrow_cri; + } + if( sc && sc->data[SC_CAMOUFLAGE] ) + cri += 10 * (10-sc->data[SC_CAMOUFLAGE]->val4); + //The official equation is *2, but that only applies when sd's do critical. + //Therefore, we use the old value 3 on cases when an sd gets attacked by a mob + cri -= tstatus->luk*(!sd&&tsd?3:2); + + if( tsc && tsc->data[SC_SLEEP] ) { + cri <<= 1; + } + switch (skill_num) { + case KN_AUTOCOUNTER: + if(battle_config.auto_counter_type && + (battle_config.auto_counter_type&src->type)) + flag.cri = 1; + else + cri <<= 1; + break; + case SN_SHARPSHOOTING: + case MA_SHARPSHOOTING: + cri += 200; + break; + case NJ_KIRIKAGE: + cri += 250 + 50*skill_lv; + break; + } + if(tsd && tsd->bonus.critical_def) + cri = cri * ( 100 - tsd->bonus.critical_def ) / 100; + if (rnd()%1000 < cri) + flag.cri = 1; + } + if (flag.cri) + { + wd.type = 0x0a; + flag.idef = flag.idef2 = flag.hit = 1; + } else { //Check for Perfect Hit + if(sd && sd->bonus.perfect_hit > 0 && rnd()%100 < sd->bonus.perfect_hit) + flag.hit = 1; + if (sc && sc->data[SC_FUSION]) { + flag.hit = 1; //SG_FUSION always hit [Komurka] + flag.idef = flag.idef2 = 1; //def ignore [Komurka] + } + if( !flag.hit ) + switch(skill_num) + { + case AS_SPLASHER: + if( !wflag ) // Always hits the one exploding. + flag.hit = 1; + break; + case CR_SHIELDBOOMERANG: + if( sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_CRUSADER ) + flag.hit = 1; + break; + } + if (tsc && !flag.hit && tsc->opt1 && tsc->opt1 != OPT1_STONEWAIT && tsc->opt1 != OPT1_BURNING) + flag.hit = 1; + } - if (!flag.hit) { - //Hit/Flee calculation - short - flee = tstatus->flee, + if (!flag.hit) + { //Hit/Flee calculation + short + flee = tstatus->flee, #ifdef RENEWAL - hitrate = 0; //Default hitrate + hitrate = 0; //Default hitrate #else - hitrate = 80; //Default hitrate + hitrate = 80; //Default hitrate #endif - if (battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) { - unsigned char attacker_count; //256 max targets should be a sane max - attacker_count = unit_counttargeted(target); - if (attacker_count >= battle_config.agi_penalty_count) { - if (battle_config.agi_penalty_type == 1) - flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; - else //asume type 2: absolute reduction - flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; - if (flee < 1) flee = 1; - } - } + if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) { + unsigned char attacker_count; //256 max targets should be a sane max + attacker_count = unit_counttargeted(target); + if(attacker_count >= battle_config.agi_penalty_count) { + if (battle_config.agi_penalty_type == 1) + flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; + else //asume type 2: absolute reduction + flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; + if(flee < 1) flee = 1; + } + } - hitrate+= sstatus->hit - flee; + hitrate+= sstatus->hit - flee; - if (wd.flag&BF_LONG && !skill_num && //Fogwall's hit penalty is only for normal ranged attacks. - tsc && tsc->data[SC_FOGWALL]) - hitrate -= 50; + if(wd.flag&BF_LONG && !skill_num && //Fogwall's hit penalty is only for normal ranged attacks. + tsc && tsc->data[SC_FOGWALL]) + hitrate -= 50; - if (sd && flag.arrow) - hitrate += sd->bonus.arrow_hit; + if(sd && flag.arrow) + hitrate += sd->bonus.arrow_hit; #ifdef RENEWAL - if (sd) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window - hitrate += pc_checkskill(sd,AC_VULTURE); + if( sd ) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window + hitrate += pc_checkskill(sd,AC_VULTURE); #endif - if (skill_num) - switch (skill_num) { - //Hit skill modifiers - //It is proven that bonus is applied on final hitrate, not hit. - case SM_BASH: - case MS_BASH: - hitrate += hitrate * 5 * skill_lv / 100; - break; - case MS_MAGNUM: - case SM_MAGNUM: - hitrate += hitrate * 10 * skill_lv / 100; - break; - case KN_AUTOCOUNTER: - case PA_SHIELDCHAIN: - case NPC_WATERATTACK: - case NPC_GROUNDATTACK: - case NPC_FIREATTACK: - case NPC_WINDATTACK: - case NPC_POISONATTACK: - case NPC_HOLYATTACK: - case NPC_DARKNESSATTACK: - case NPC_UNDEADATTACK: - case NPC_TELEKINESISATTACK: - case NPC_BLEEDING: - hitrate += hitrate * 20 / 100; - break; - case KN_PIERCE: - case ML_PIERCE: - hitrate += hitrate * 5 * skill_lv / 100; - break; - case AS_SONICBLOW: - if (sd && pc_checkskill(sd,AS_SONICACCEL)>0) - hitrate += hitrate * 50 / 100; - break; - case MC_CARTREVOLUTION: - case GN_CART_TORNADO: - case GN_CARTCANNON: - if (sd && pc_checkskill(sd, GN_REMODELING_CART)) - hitrate += pc_checkskill(sd, GN_REMODELING_CART) * 4; - break; - case GC_VENOMPRESSURE: - hitrate += 10 + 4 * skill_lv; - break; - } + if(skill_num) + switch(skill_num) + { //Hit skill modifiers + //It is proven that bonus is applied on final hitrate, not hit. + case SM_BASH: + case MS_BASH: + hitrate += hitrate * 5 * skill_lv / 100; + break; + case MS_MAGNUM: + case SM_MAGNUM: + hitrate += hitrate * 10 * skill_lv / 100; + break; + case KN_AUTOCOUNTER: + case PA_SHIELDCHAIN: + case NPC_WATERATTACK: + case NPC_GROUNDATTACK: + case NPC_FIREATTACK: + case NPC_WINDATTACK: + case NPC_POISONATTACK: + case NPC_HOLYATTACK: + case NPC_DARKNESSATTACK: + case NPC_UNDEADATTACK: + case NPC_TELEKINESISATTACK: + case NPC_BLEEDING: + hitrate += hitrate * 20 / 100; + break; + case KN_PIERCE: + case ML_PIERCE: + hitrate += hitrate * 5 * skill_lv / 100; + break; + case AS_SONICBLOW: + if(sd && pc_checkskill(sd,AS_SONICACCEL)>0) + hitrate += hitrate * 50 / 100; + break; + case MC_CARTREVOLUTION: + case GN_CART_TORNADO: + case GN_CARTCANNON: + if( sd && pc_checkskill(sd, GN_REMODELING_CART) ) + hitrate += pc_checkskill(sd, GN_REMODELING_CART) * 4; + break; + case GC_VENOMPRESSURE: + hitrate += 10 + 4 * skill_lv; + break; + } - if (sd) { - // Weaponry Research hidden bonus - if ((skill = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) - hitrate += hitrate * (2 * skill) / 100; + if( sd ) { + // Weaponry Research hidden bonus + if ((skill = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) + hitrate += hitrate * ( 2 * skill ) / 100; - if ((sd->status.weapon == W_1HSWORD || sd->status.weapon == W_DAGGER) && - (skill = pc_checkskill(sd, GN_TRAINING_SWORD))>0) - hitrate += 3 * skill; - } + if( (sd->status.weapon == W_1HSWORD || sd->status.weapon == W_DAGGER) && + (skill = pc_checkskill(sd, GN_TRAINING_SWORD))>0 ) + hitrate += 3 * skill; + } - hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); + hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); - if (rnd()%100 >= hitrate) - wd.dmg_lv = ATK_FLEE; - else - flag.hit = 1; - } //End hit/miss calculation + if(rnd()%100 >= hitrate) + wd.dmg_lv = ATK_FLEE; + else + flag.hit = 1; + } //End hit/miss calculation - if (flag.hit && !flag.infdef) { //No need to do the math for plants - //Hitting attack + if (flag.hit && !flag.infdef) //No need to do the math for plants + { //Hitting attack - //Assuming that 99% of the cases we will not need to check for the flag.rh... we don't. - //ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc +//Assuming that 99% of the cases we will not need to check for the flag.rh... we don't. +//ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc #define ATK_RATE( a ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(a)/100; } #define ATK_RATE2( a , b ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; } - //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage +//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage #define ATK_ADDRATE( a ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(a)/100; } #define ATK_ADDRATE2( a , b ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; } - //Adds an absolute value to damage. 100 = +100 damage +//Adds an absolute value to damage. 100 = +100 damage #define ATK_ADD( a ) { wd.damage+= a; if (flag.lh) wd.damage2+= a; } #define ATK_ADD2( a , b ) { wd.damage+= a; if (flag.lh) wd.damage2+= b; } - switch (skill_num) { - //Calc base damage according to skill - case NJ_ISSEN: - wd.damage = 40*sstatus->str +skill_lv*(sstatus->hp/10 + 35); - wd.damage2 = 0; - status_set_hp(src, 1, 0); - break; - case PA_SACRIFICE: - wd.damage = sstatus->max_hp* 9/100; - wd.damage2 = 0; - break; + switch (skill_num) + { //Calc base damage according to skill + case NJ_ISSEN: + wd.damage = 40*sstatus->str +skill_lv*(sstatus->hp/10 + 35); + wd.damage2 = 0; + status_set_hp(src, 1, 0); + break; + case PA_SACRIFICE: + wd.damage = sstatus->max_hp* 9/100; + wd.damage2 = 0; + break; #ifndef RENEWAL - case LK_SPIRALPIERCE: - case ML_SPIRALPIERCE: - if (sd) { - short index = sd->equip_index[EQI_HAND_R]; - - if (index >= 0 && - sd->inventory_data[index] && - sd->inventory_data[index]->type == IT_WEAPON) - wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight - } else - wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2 - - ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only. - i = sstatus->str/10; - i*=i; - ATK_ADD(i); //Add str bonus. - switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection? - case SZ_SMALL: //Small: 125% - ATK_RATE(125); - break; - //case SZ_MEDIUM: //Medium: 100% - case SZ_BIG: //Large: 75% - ATK_RATE(75); - break; - } - break; -#endif - case CR_SHIELDBOOMERANG: - case PA_SHIELDCHAIN: - case LG_SHIELDPRESS: - case LG_EARTHDRIVE: - wd.damage = sstatus->batk; - if (sd) { - short index = sd->equip_index[EQI_HAND_L]; - - if (index >= 0 && - sd->inventory_data[index] && - sd->inventory_data[index]->type == IT_ARMOR) - ATK_ADD(sd->inventory_data[index]->weight/10); - } else - ATK_ADD(sstatus->rhw.atk2); //Else use Atk2 - break; - case HFLI_SBR44: //[orn] - if (src->type == BL_HOM) { - wd.damage = ((TBL_HOM *)src)->homunculus.intimacy ; - break; - } - default: { - i = (flag.cri?1:0)| - (flag.arrow?2:0)| - (skill_num == HW_MAGICCRASHER?4:0)| - (!skill_num && sc && sc->data[SC_CHANGE]?4:0)| - (skill_num == MO_EXTREMITYFIST?8:0)| - (sc && sc->data[SC_WEAPONPERFECTION]?8:0); - if (flag.arrow && sd) - switch (sd->status.weapon) { - case W_BOW: - case W_REVOLVER: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - break; - default: - i |= 16; // for ex. shuriken must not be influenced by DEX - } - wd.damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i); - if (flag.lh) - wd.damage2 = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i); - - if (nk&NK_SPLASHSPLIT) { // Divide ATK among targets - if (wflag>0) - wd.damage/= wflag; - else - ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); - } - - //Add any bonuses that modify the base baseatk+watk (pre-skills) - if (sd) { - if (sd->bonus.atk_rate) - ATK_ADDRATE(sd->bonus.atk_rate); - - if (flag.cri && sd->bonus.crit_atk_rate) - ATK_ADDRATE(sd->bonus.crit_atk_rate); - - if (sd->status.party_id && (skill=pc_checkskill(sd,TK_POWER)) > 0) { - if ((i = party_foreachsamemap(party_sub_count, sd, 0)) > 1) // exclude the player himself [Inkfish] - ATK_ADDRATE(2*skill*i); - } - } - break; - } //End default case - } //End switch(skill_num) - - //Skill damage modifiers that stack linearly - if (sc && skill_num != PA_SACRIFICE) { - if (sc->data[SC_OVERTHRUST]) - skillratio += sc->data[SC_OVERTHRUST]->val3; - if (sc->data[SC_MAXOVERTHRUST]) - skillratio += sc->data[SC_MAXOVERTHRUST]->val2; - if (sc->data[SC_BERSERK] || sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST]) - skillratio += 100; - if (sc->data[SC_ZENKAI] && sstatus->rhw.ele == sc->data[SC_ZENKAI]->val2) - skillratio += sc->data[SC_ZENKAI]->val1 * 2; - } - if (!skill_num) { - ATK_RATE(skillratio); - } else { - switch (skill_num) { - case SM_BASH: - case MS_BASH: - skillratio += 30*skill_lv; - break; - case SM_MAGNUM: - case MS_MAGNUM: - skillratio += 20*skill_lv; - break; - case MC_MAMMONITE: - skillratio += 50*skill_lv; - break; - case HT_POWER: - skillratio += -50+8*sstatus->str; - break; - case AC_DOUBLE: - case MA_DOUBLE: - skillratio += 10*(skill_lv-1); - break; - case AC_SHOWER: - case MA_SHOWER: -#ifdef RENEWAL - skillratio += 50+10*skill_lv; -#else - skillratio += -25+5*skill_lv; + case LK_SPIRALPIERCE: + case ML_SPIRALPIERCE: + if (sd) { + short index = sd->equip_index[EQI_HAND_R]; + + if (index >= 0 && + sd->inventory_data[index] && + sd->inventory_data[index]->type == IT_WEAPON) + wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight + } else + wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2 + + ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only. + i = sstatus->str/10; + i*=i; + ATK_ADD(i); //Add str bonus. + switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection? + case SZ_SMALL: //Small: 125% + ATK_RATE(125); + break; + //case SZ_MEDIUM: //Medium: 100% + case SZ_BIG: //Large: 75% + ATK_RATE(75); + break; + } + break; #endif - break; - case AC_CHARGEARROW: - case MA_CHARGEARROW: - skillratio += 50; - break; + case CR_SHIELDBOOMERANG: + case PA_SHIELDCHAIN: + case LG_SHIELDPRESS: + case LG_EARTHDRIVE: + wd.damage = sstatus->batk; + if (sd) { + short index = sd->equip_index[EQI_HAND_L]; + + if (index >= 0 && + sd->inventory_data[index] && + sd->inventory_data[index]->type == IT_ARMOR) + ATK_ADD(sd->inventory_data[index]->weight/10); + } else + ATK_ADD(sstatus->rhw.atk2); //Else use Atk2 + break; + case HFLI_SBR44: //[orn] + if(src->type == BL_HOM) { + wd.damage = ((TBL_HOM*)src)->homunculus.intimacy ; + break; + } + default: + { + i = (flag.cri?1:0)| + (flag.arrow?2:0)| + (skill_num == HW_MAGICCRASHER?4:0)| + (!skill_num && sc && sc->data[SC_CHANGE]?4:0)| + (skill_num == MO_EXTREMITYFIST?8:0)| + (sc && sc->data[SC_WEAPONPERFECTION]?8:0); + if (flag.arrow && sd) + switch(sd->status.weapon) { + case W_BOW: + case W_REVOLVER: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + break; + default: + i |= 16; // for ex. shuriken must not be influenced by DEX + } + wd.damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i); + if (flag.lh) + wd.damage2 = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i); + + if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets + if(wflag>0) + wd.damage/= wflag; + else + ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); + } + + //Add any bonuses that modify the base baseatk+watk (pre-skills) + if(sd) { + if (sd->bonus.atk_rate) + ATK_ADDRATE(sd->bonus.atk_rate); + + if(flag.cri && sd->bonus.crit_atk_rate) + ATK_ADDRATE(sd->bonus.crit_atk_rate); + + if(sd->status.party_id && (skill=pc_checkskill(sd,TK_POWER)) > 0){ + if( (i = party_foreachsamemap(party_sub_count, sd, 0)) > 1 ) // exclude the player himself [Inkfish] + ATK_ADDRATE(2*skill*i); + } + } + break; + } //End default case + } //End switch(skill_num) + + //Skill damage modifiers that stack linearly + if(sc && skill_num != PA_SACRIFICE) + { + if(sc->data[SC_OVERTHRUST]) + skillratio += sc->data[SC_OVERTHRUST]->val3; + if(sc->data[SC_MAXOVERTHRUST]) + skillratio += sc->data[SC_MAXOVERTHRUST]->val2; + if (sc->data[SC_BERSERK] || sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST]) + skillratio += 100; + if(sc->data[SC_ZENKAI] && sstatus->rhw.ele == sc->data[SC_ZENKAI]->val2 ) + skillratio += sc->data[SC_ZENKAI]->val1 * 2; + } + if( !skill_num ) + { + ATK_RATE(skillratio); + } + else + { + switch( skill_num ) + { + case SM_BASH: + case MS_BASH: + skillratio += 30*skill_lv; + break; + case SM_MAGNUM: + case MS_MAGNUM: + skillratio += 20*skill_lv; + break; + case MC_MAMMONITE: + skillratio += 50*skill_lv; + break; + case HT_POWER: + skillratio += -50+8*sstatus->str; + break; + case AC_DOUBLE: + case MA_DOUBLE: + skillratio += 10*(skill_lv-1); + break; + case AC_SHOWER: + case MA_SHOWER: + #ifdef RENEWAL + skillratio += 50+10*skill_lv; + #else + skillratio += -25+5*skill_lv; + #endif + break; + case AC_CHARGEARROW: + case MA_CHARGEARROW: + skillratio += 50; + break; #ifndef RENEWAL - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - skillratio += -50+10*skill_lv; - break; -#endif - case KN_PIERCE: - case ML_PIERCE: - skillratio += 10*skill_lv; - break; - case MER_CRASH: - skillratio += 10*skill_lv; - break; - case KN_SPEARSTAB: - skillratio += 15*skill_lv; - break; - case KN_SPEARBOOMERANG: - skillratio += 50*skill_lv; - break; - case KN_BRANDISHSPEAR: - case ML_BRANDISH: { - int ratio = 100+20*skill_lv; - skillratio += ratio-100; - if (skill_lv>3 && wflag==1) skillratio += ratio/2; - if (skill_lv>6 && wflag==1) skillratio += ratio/4; - if (skill_lv>9 && wflag==1) skillratio += ratio/8; - if (skill_lv>6 && wflag==2) skillratio += ratio/2; - if (skill_lv>9 && wflag==2) skillratio += ratio/4; - if (skill_lv>9 && wflag==3) skillratio += ratio/2; - break; - } - case KN_BOWLINGBASH: - case MS_BOWLINGBASH: - skillratio+= 40*skill_lv; - break; - case AS_GRIMTOOTH: - skillratio += 20*skill_lv; - break; - case AS_POISONREACT: - skillratio += 30*skill_lv; - break; - case AS_SONICBLOW: - skillratio += -50+5*skill_lv; - break; - case TF_SPRINKLESAND: - skillratio += 30; - break; - case MC_CARTREVOLUTION: - skillratio += 50; - if (sd && sd->cart_weight) - skillratio += 100*sd->cart_weight/sd->cart_weight_max; // +1% every 1% weight - else if (!sd) - skillratio += 100; //Max damage for non players. - break; - case NPC_RANDOMATTACK: - skillratio += 100*skill_lv; - break; - case NPC_WATERATTACK: - case NPC_GROUNDATTACK: - case NPC_FIREATTACK: - case NPC_WINDATTACK: - case NPC_POISONATTACK: - case NPC_HOLYATTACK: - case NPC_DARKNESSATTACK: - case NPC_UNDEADATTACK: - case NPC_TELEKINESISATTACK: - case NPC_BLOODDRAIN: - case NPC_ACIDBREATH: - case NPC_DARKNESSBREATH: - case NPC_FIREBREATH: - case NPC_ICEBREATH: - case NPC_THUNDERBREATH: - case NPC_HELLJUDGEMENT: - case NPC_PULSESTRIKE: - skillratio += 100*(skill_lv-1); - break; - case RG_BACKSTAP: - if (sd && sd->status.weapon == W_BOW && battle_config.backstab_bow_penalty) - skillratio += (200+40*skill_lv)/2; - else - skillratio += 200+40*skill_lv; - break; - case RG_RAID: - skillratio += 40*skill_lv; - break; - case RG_INTIMIDATE: - skillratio += 30*skill_lv; - break; - case CR_SHIELDCHARGE: - skillratio += 20*skill_lv; - break; - case CR_SHIELDBOOMERANG: - skillratio += 30*skill_lv; - break; - case NPC_DARKCROSS: - case CR_HOLYCROSS: { - int ratio = 35*skill_lv; -#ifdef RENEWAL - if (sd && sd->status.weapon == W_2HSPEAR) - ratio *= 2; -#endif - skillratio += ratio; - break; - } - case AM_DEMONSTRATION: - skillratio += 20*skill_lv; - break; - case AM_ACIDTERROR: - skillratio += 40*skill_lv; - break; - case MO_FINGEROFFENSIVE: - skillratio+= 50 * skill_lv; - break; - case MO_INVESTIGATE: - skillratio += 75*skill_lv; - flag.pdef = flag.pdef2 = 2; - break; - case MO_EXTREMITYFIST: { - //Overflow check. [Skotlex] - unsigned int ratio = skillratio + 100*(8 + sstatus->sp/10); - //You'd need something like 6K SP to reach this max, so should be fine for most purposes. - if (ratio > 60000) ratio = 60000; //We leave some room here in case skillratio gets further increased. - skillratio = (unsigned short)ratio; - status_set_sp(src, 0, 0); - } - break; - case MO_TRIPLEATTACK: - skillratio += 20*skill_lv; - break; - case MO_CHAINCOMBO: - skillratio += 50+50*skill_lv; - break; - case MO_COMBOFINISH: - skillratio += 140+60*skill_lv; - break; - case BA_MUSICALSTRIKE: - case DC_THROWARROW: - skillratio += 25+25*skill_lv; - break; - case CH_TIGERFIST: - skillratio += 100*skill_lv-60; - break; - case CH_CHAINCRUSH: - skillratio += 300+100*skill_lv; - break; - case CH_PALMSTRIKE: - skillratio += 100+100*skill_lv; - break; - case LK_HEADCRUSH: - skillratio += 40*skill_lv; - break; - case LK_JOINTBEAT: - i = 10*skill_lv-50; - // Although not clear, it's being assumed that the 2x damage is only for the break neck ailment. - if (wflag&BREAK_NECK) i*=2; - skillratio += i; - break; -#ifdef RENEWAL - case LK_SPIRALPIERCE: - case ML_SPIRALPIERCE: { - // Formula: Floor[Floor(Weapon Weight/2)*skill level + ATK ]*(100%+50%*s.lvl) * 5 multi-hits - short index = sd?sd->equip_index[EQI_HAND_R]:0; - int weight = 0; - - if (sd && index >= 0 && - sd->inventory_data[index] && - sd->inventory_data[index]->type == IT_WEAPON) - weight = sd->inventory_data[index]->weight/20; - ATK_ADD(weight * skill_lv) - skillratio += 50*skill_lv; - } - break; + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + skillratio += -50+10*skill_lv; + break; #endif - case ASC_METEORASSAULT: - skillratio += 40*skill_lv-60; - break; - case SN_SHARPSHOOTING: - case MA_SHARPSHOOTING: - skillratio += 100+50*skill_lv; - break; - case CG_ARROWVULCAN: - skillratio += 100+100*skill_lv; - break; - case AS_SPLASHER: - skillratio += 400+50*skill_lv; - if (sd) - skillratio += 20 * pc_checkskill(sd,AS_POISONREACT); - break; - case ASC_BREAKER: - skillratio += 100*skill_lv-100; - break; - case PA_SACRIFICE: - skillratio += 10*skill_lv-10; - break; - case PA_SHIELDCHAIN: - skillratio += 30*skill_lv; - break; - case WS_CARTTERMINATION: - i = 10 * (16 - skill_lv); - if (i < 1) i = 1; - //Preserve damage ratio when max cart weight is changed. - if (sd && sd->cart_weight) - skillratio += sd->cart_weight/i * 80000/battle_config.max_cart_weight - 100; - else if (!sd) - skillratio += 80000 / i - 100; - break; - case TK_DOWNKICK: - skillratio += 60 + 20*skill_lv; - break; - case TK_STORMKICK: - skillratio += 60 + 20*skill_lv; - break; - case TK_TURNKICK: - skillratio += 90 + 30*skill_lv; - break; - case TK_COUNTER: - skillratio += 90 + 30*skill_lv; - break; - case TK_JUMPKICK: - skillratio += -70 + 10*skill_lv; - if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num) - skillratio += 10*status_get_lv(src)/3; //Tumble bonus - if (wflag) { - skillratio += 10*status_get_lv(src)/3; //Running bonus (TODO: What is the real bonus?) - if (sc && sc->data[SC_SPURT]) // Spurt bonus - skillratio *= 2; - } - break; - case GS_TRIPLEACTION: - skillratio += 50*skill_lv; - break; - case GS_BULLSEYE: - //Only works well against brute/demihumans non bosses. - if ((tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN) - && !(tstatus->mode&MD_BOSS)) - skillratio += 400; - break; - case GS_TRACKING: - skillratio += 100 *(skill_lv+1); - break; - case GS_PIERCINGSHOT: - skillratio += 20*skill_lv; - break; - case GS_RAPIDSHOWER: - skillratio += 10*skill_lv; - break; - case GS_DESPERADO: - skillratio += 50*(skill_lv-1); - break; - case GS_DUST: - skillratio += 50*skill_lv; - break; - case GS_FULLBUSTER: - skillratio += 100*(skill_lv+2); - break; - case GS_SPREADATTACK: + case KN_PIERCE: + case ML_PIERCE: + skillratio += 10*skill_lv; + break; + case MER_CRASH: + skillratio += 10*skill_lv; + break; + case KN_SPEARSTAB: + skillratio += 15*skill_lv; + break; + case KN_SPEARBOOMERANG: + skillratio += 50*skill_lv; + break; + case KN_BRANDISHSPEAR: + case ML_BRANDISH: + { + int ratio = 100+20*skill_lv; + skillratio += ratio-100; + if(skill_lv>3 && wflag==1) skillratio += ratio/2; + if(skill_lv>6 && wflag==1) skillratio += ratio/4; + if(skill_lv>9 && wflag==1) skillratio += ratio/8; + if(skill_lv>6 && wflag==2) skillratio += ratio/2; + if(skill_lv>9 && wflag==2) skillratio += ratio/4; + if(skill_lv>9 && wflag==3) skillratio += ratio/2; + break; + } + case KN_BOWLINGBASH: + case MS_BOWLINGBASH: + skillratio+= 40*skill_lv; + break; + case AS_GRIMTOOTH: + skillratio += 20*skill_lv; + break; + case AS_POISONREACT: + skillratio += 30*skill_lv; + break; + case AS_SONICBLOW: + skillratio += -50+5*skill_lv; + break; + case TF_SPRINKLESAND: + skillratio += 30; + break; + case MC_CARTREVOLUTION: + skillratio += 50; + if(sd && sd->cart_weight) + skillratio += 100*sd->cart_weight/sd->cart_weight_max; // +1% every 1% weight + else if (!sd) + skillratio += 100; //Max damage for non players. + break; + case NPC_RANDOMATTACK: + skillratio += 100*skill_lv; + break; + case NPC_WATERATTACK: + case NPC_GROUNDATTACK: + case NPC_FIREATTACK: + case NPC_WINDATTACK: + case NPC_POISONATTACK: + case NPC_HOLYATTACK: + case NPC_DARKNESSATTACK: + case NPC_UNDEADATTACK: + case NPC_TELEKINESISATTACK: + case NPC_BLOODDRAIN: + case NPC_ACIDBREATH: + case NPC_DARKNESSBREATH: + case NPC_FIREBREATH: + case NPC_ICEBREATH: + case NPC_THUNDERBREATH: + case NPC_HELLJUDGEMENT: + case NPC_PULSESTRIKE: + skillratio += 100*(skill_lv-1); + break; + case RG_BACKSTAP: + if(sd && sd->status.weapon == W_BOW && battle_config.backstab_bow_penalty) + skillratio += (200+40*skill_lv)/2; + else + skillratio += 200+40*skill_lv; + break; + case RG_RAID: + skillratio += 40*skill_lv; + break; + case RG_INTIMIDATE: + skillratio += 30*skill_lv; + break; + case CR_SHIELDCHARGE: + skillratio += 20*skill_lv; + break; + case CR_SHIELDBOOMERANG: + skillratio += 30*skill_lv; + break; + case NPC_DARKCROSS: + case CR_HOLYCROSS: + { + int ratio = 35*skill_lv; + #ifdef RENEWAL + if(sd && sd->status.weapon == W_2HSPEAR) + ratio *= 2; + #endif + skillratio += ratio; + break; + } + case AM_DEMONSTRATION: + skillratio += 20*skill_lv; + break; + case AM_ACIDTERROR: + skillratio += 40*skill_lv; + break; + case MO_FINGEROFFENSIVE: + skillratio+= 50 * skill_lv; + break; + case MO_INVESTIGATE: + skillratio += 75*skill_lv; + flag.pdef = flag.pdef2 = 2; + break; + case MO_EXTREMITYFIST: + { //Overflow check. [Skotlex] + unsigned int ratio = skillratio + 100*(8 + sstatus->sp/10); + //You'd need something like 6K SP to reach this max, so should be fine for most purposes. + if (ratio > 60000) ratio = 60000; //We leave some room here in case skillratio gets further increased. + skillratio = (unsigned short)ratio; + status_set_sp(src, 0, 0); + } + break; + case MO_TRIPLEATTACK: + skillratio += 20*skill_lv; + break; + case MO_CHAINCOMBO: + skillratio += 50+50*skill_lv; + break; + case MO_COMBOFINISH: + skillratio += 140+60*skill_lv; + break; + case BA_MUSICALSTRIKE: + case DC_THROWARROW: + skillratio += 25+25*skill_lv; + break; + case CH_TIGERFIST: + skillratio += 100*skill_lv-60; + break; + case CH_CHAINCRUSH: + skillratio += 300+100*skill_lv; + break; + case CH_PALMSTRIKE: + skillratio += 100+100*skill_lv; + break; + case LK_HEADCRUSH: + skillratio += 40*skill_lv; + break; + case LK_JOINTBEAT: + i = 10*skill_lv-50; + // Although not clear, it's being assumed that the 2x damage is only for the break neck ailment. + if (wflag&BREAK_NECK) i*=2; + skillratio += i; + break; #ifdef RENEWAL - skillratio += 20*(skill_lv); -#else - skillratio += 20*(skill_lv-1); + case LK_SPIRALPIERCE: + case ML_SPIRALPIERCE: + {// Formula: Floor[Floor(Weapon Weight/2)*skill level + ATK ]*(100%+50%*s.lvl) * 5 multi-hits + short index = sd?sd->equip_index[EQI_HAND_R]:0; + int weight = 0; + + if (sd && index >= 0 && + sd->inventory_data[index] && + sd->inventory_data[index]->type == IT_WEAPON) + weight = sd->inventory_data[index]->weight/20; + ATK_ADD(weight * skill_lv) + skillratio += 50*skill_lv; + } + break; #endif - break; - case NJ_HUUMA: - skillratio += 50 + 150*skill_lv; - break; - case NJ_TATAMIGAESHI: - skillratio += 10*skill_lv; - break; - case NJ_KASUMIKIRI: - skillratio += 10*skill_lv; - break; - case NJ_KIRIKAGE: - skillratio += 100*(skill_lv-1); - break; - case KN_CHARGEATK: { - int k = (wflag-1)/3; //+100% every 3 cells of distance - if (k > 2) k = 2; // ...but hard-limited to 300%. - skillratio += 100 * k; - } - break; - case HT_PHANTASMIC: - skillratio += 50; - break; - case MO_BALKYOUNG: - skillratio += 200; - break; - case HFLI_MOON: //[orn] - skillratio += 10+110*skill_lv; - break; - case HFLI_SBR44: //[orn] - skillratio += 100 *(skill_lv-1); - break; - case NPC_VAMPIRE_GIFT: - skillratio += ((skill_lv-1)%5+1)*100; - break; - case RK_SONICWAVE: - skillratio += 400 + 100 * skill_lv; - RE_LVL_DMOD(100); - break; - case RK_HUNDREDSPEAR: - skillratio += 500 + (80 * skill_lv); - if (sd) { - short index = sd->equip_index[EQI_HAND_R]; - if (index >= 0 && sd->inventory_data[index] - && sd->inventory_data[index]->type == IT_WEAPON) - skillratio += max(10000 - sd->inventory_data[index]->weight, 0) / 10; - skillratio += 50 * pc_checkskill(sd,LK_SPIRALPIERCE); - } // (1 + [(Casters Base Level - 100) / 200]) - skillratio = skillratio * (100 + (status_get_lv(src)-100) / 2) / 100; - break; - case RK_WINDCUTTER: - skillratio += 50 * skill_lv; - RE_LVL_DMOD(100); - break; - case RK_IGNITIONBREAK: - i = distance_bl(src,target); - if (i < 2) - skillratio = 200 + 200 * skill_lv; - else if (i < 4) - skillratio = 100 + 200 * skill_lv; - else - skillratio = 100 + 100 * skill_lv; - RE_LVL_DMOD(100); - if (sstatus->rhw.ele == ELE_FIRE) - skillratio += skillratio / 2; - break; - case RK_CRUSHSTRIKE: - if (sd) { - //ATK [{Weapon Level * (Weapon Upgrade Level + 6) * 100} + (Weapon ATK) + (Weapon Weight)]% - short index = sd->equip_index[EQI_HAND_R]; - if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON) - skillratio = sd->inventory_data[index]->weight/10 + sstatus->rhw.atk + - 100 * sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6); - } - break; - case RK_STORMBLAST: - skillratio = 100 * (sd ? pc_checkskill(sd,RK_RUNEMASTERY) : 1) + 100 * (sstatus->int_ / 4); - break; - case RK_PHANTOMTHRUST: - skillratio = 50 * skill_lv + 10 * (sd ? pc_checkskill(sd,KN_SPEARMASTERY) : 10); - //if( s_level > 100 ) skillratio += skillratio * s_level / 150; // Base level bonus. This is official, but is disabled until I can confirm something with was changed or not. [Rytech] - //if( s_level > 100 ) skillratio += skillratio * (s_level - 100) / 200; // Base level bonus. - break; - /** - * GC Guilotine Cross - **/ - case GC_CROSSIMPACT: - skillratio += 900 + 100 * skill_lv; - RE_LVL_DMOD(120); - break; - case GC_PHANTOMMENACE: - skillratio += 200; - break; - case GC_COUNTERSLASH: - //ATK [{(Skill Level x 100) + 300} x Caster's Base Level / 120]% + ATK [(AGI x 2) + (Caster's Job Level x 4)]% - skillratio += 200 + (100 * skill_lv); - RE_LVL_DMOD(120); - skillratio += sstatus->agi + (sd?sd->status.job_level:0) * 4; - break; - case GC_ROLLINGCUTTER: - skillratio += -50 + 50 * skill_lv; - RE_LVL_DMOD(100); - break; - case GC_CROSSRIPPERSLASHER: - skillratio += 300 + 80 * skill_lv; - RE_LVL_DMOD(100); - if (sc && sc->data[SC_ROLLINGCUTTER]) - skillratio += sc->data[SC_ROLLINGCUTTER]->val1 * sstatus->agi; - break; - /** - * Arch Bishop - **/ - case AB_DUPLELIGHT_MELEE: - skillratio += 10 * skill_lv; - break; - /** - * Ranger - **/ - case RA_ARROWSTORM: - skillratio += 900 + 80 * skill_lv; - RE_LVL_DMOD(100); - break; - case RA_AIMEDBOLT: - skillratio += 400 + 50 * skill_lv; - RE_LVL_DMOD(100); - if (tsc && (tsc->data[SC_BITE] || tsc->data[SC_ANKLE] || tsc->data[SC_ELECTRICSHOCKER])) - wd.div_ = tstatus->size + 2 + ((rnd()%100 < 50-tstatus->size*10) ? 1 : 0); - break; - case RA_CLUSTERBOMB: - skillratio += 100 + 100 * skill_lv; - break; - case RA_WUGDASH:// ATK 300% - skillratio += 200; - break; - case RA_WUGSTRIKE: - skillratio = 200 * skill_lv; - break; - case RA_WUGBITE: - skillratio += 300 + 200 * skill_lv; - if (skill_lv == 5) skillratio += 100; - break; - case RA_SENSITIVEKEEN: - skillratio += 50 * skill_lv; - break; - /** - * Mechanic - **/ - case NC_BOOSTKNUCKLE: - skillratio += 100 + 100 * skill_lv + sstatus->dex; - RE_LVL_DMOD(100); - break; - case NC_PILEBUNKER: - skillratio += 200 + 100 * skill_lv + sstatus->str; - RE_LVL_DMOD(100); - break; - case NC_VULCANARM: - skillratio = 70 * skill_lv + sstatus->dex; - RE_LVL_DMOD(100); - break; - case NC_FLAMELAUNCHER: - case NC_COLDSLOWER: - skillratio += 200 + 300 * skill_lv; - RE_LVL_DMOD(100); - break; - case NC_ARMSCANNON: - switch (tstatus->size) { - case SZ_SMALL: - skillratio += 100 + 500 * skill_lv; - break;// Small - case SZ_MEDIUM: - skillratio += 100 + 400 * skill_lv; - break;// Medium - case SZ_BIG: - skillratio += 100 + 300 * skill_lv; - break;// Large - } - RE_LVL_DMOD(100); - //NOTE: Their's some other factors that affects damage, but not sure how exactly. Will recheck one day. [Rytech] - break; - case NC_AXEBOOMERANG: - skillratio += 60 + 40 * skill_lv; - if (sd) { - short index = sd->equip_index[EQI_HAND_R]; - if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON) - skillratio += sd->inventory_data[index]->weight / 10;// Weight is divided by 10 since 10 weight in coding make 1 whole actural weight. [Rytech] - } - RE_LVL_DMOD(100); - break; - case NC_POWERSWING: - skillratio += 80 + 20 * skill_lv + sstatus->str + sstatus->dex; - RE_LVL_DMOD(100); - break; - case NC_AXETORNADO: - skillratio += 100 + 100 * skill_lv + sstatus->vit; - RE_LVL_DMOD(100); - break; - case SC_FATALMENACE: - skillratio += 100 * skill_lv; - break; - case SC_TRIANGLESHOT: - skillratio += 270 + 30 * skill_lv; - break; - case SC_FEINTBOMB: - skillratio += 100 + 100 * skill_lv; - break; - case LG_CANNONSPEAR:// Stimated formula. Still need confirm it. - skillratio += -100 + (50 + sstatus->str) * skill_lv; - RE_LVL_DMOD(100); - break; - case LG_BANISHINGPOINT: - skillratio += -100 + ((50 * skill_lv) + (30 * ((sd)?pc_checkskill(sd,SM_BASH):1))); - RE_LVL_DMOD(100); - break; - case LG_SHIELDPRESS: - skillratio += 60 + 43 * skill_lv; - RE_LVL_DMOD(100); - break; - case LG_PINPOINTATTACK: - skillratio = ((100 * skill_lv) + (10 * status_get_agi(src))); - RE_LVL_DMOD(100); - break; - case LG_RAGEBURST: - if (sd && sd->spiritball_old) - skillratio += -100 + (sd->spiritball_old * 200); - else - skillratio += -100 + 15 * 200; - RE_LVL_DMOD(100); - break; - case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield DEF x 10) + (Casters VIT x 2)] % - if (sd) { - struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; - skillratio = status_get_lv(src) * 4 + status_get_vit(src) * 2; - if (shield_data) - skillratio += shield_data->def * 10; - } else - skillratio += 2400; //2500% - break; - case LG_MOONSLASHER: - skillratio += -100 + (120 * skill_lv + ((sd) ? pc_checkskill(sd,LG_OVERBRAND) : 5) * 80); - RE_LVL_DMOD(100); - break; - case LG_OVERBRAND: - skillratio = 400 * skill_lv + (pc_checkskill(sd,CR_SPEARQUICKEN) * 30); - RE_LVL_DMOD(100); - break; - case LG_OVERBRAND_BRANDISH: - skillratio = 300 * skill_lv + (2 * (sstatus->str + sstatus->dex) / 3); - RE_LVL_DMOD(100); - break; - case LG_OVERBRAND_PLUSATK: - skillratio = 150 * skill_lv; - RE_LVL_DMOD(100); - break; - case LG_RAYOFGENESIS: - skillratio = skillratio + 200 + 300 * skill_lv; - RE_LVL_DMOD(100); - break; - case LG_EARTHDRIVE: - skillratio = (skillratio + 100) * skill_lv; - RE_LVL_DMOD(100); - break; - case LG_HESPERUSLIT: - skillratio += 120 * skill_lv - 100; - break; - case SR_DRAGONCOMBO: - skillratio += 40 * skill_lv; - RE_LVL_DMOD(100); - break; - case SR_SKYNETBLOW: - //ATK [{(Skill Level x 80) + (Caster AGI)} x Caster Base Level / 100] % - skillratio = 80 * skill_lv + sstatus->agi; - if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_DRAGONCOMBO) //ATK [{(Skill Level x 100) + (Caster AGI) + 150} x Caster Base Level / 100] % - skillratio = 100 * skill_lv + sstatus->agi + 150; - RE_LVL_DMOD(100); - break; - case SR_EARTHSHAKER: - if (tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || // [(Skill Level x 150) x (Caster Base Level / 100) + (Caster INT x 3)] % - tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || tsc->data[SC__INVISIBILITY])) { - skillratio = 150 * skill_lv; - RE_LVL_DMOD(100); - skillratio += sstatus->int_ * 3; - } else { //[(Skill Level x 50) x (Caster Base Level / 100) + (Caster INT x 2)] % - skillratio += 50 * (skill_lv-2); - RE_LVL_DMOD(100); - skillratio += sstatus->int_ * 2; - } - break; - case SR_FALLENEMPIRE:// ATK [(Skill Level x 150 + 100) x Caster Base Level / 150] % - skillratio += 150 *skill_lv; - RE_LVL_DMOD(150); - break; - case SR_TIGERCANNON: { // ATK [((Caster consumed HP + SP) / 4) x Caster Base Level / 100] % - int hp = sstatus->max_hp * (10 + 2 * skill_lv) / 100, - sp = sstatus->max_sp * (6 + skill_lv) / 100; - skillratio = (hp+sp) / 4; - if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) // ATK [((Caster consumed HP + SP) / 2) x Caster Base Level / 100] % - skillratio = (hp+sp) / 2; - RE_LVL_DMOD(100); - } - break; - case SR_RAMPAGEBLASTER: - skillratio += 20 * skill_lv * (sd?sd->spiritball_old:5) - 100; - if (sc && sc->data[SC_EXPLOSIONSPIRITS]) { - skillratio += sc->data[SC_EXPLOSIONSPIRITS]->val1 * 20; - RE_LVL_DMOD(120); - } else - RE_LVL_DMOD(150); - break; - case SR_KNUCKLEARROW: - if (wflag&4) { // ATK [(Skill Level x 150) + (1000 x Target current weight / Maximum weight) + (Target Base Level x 5) x (Caster Base Level / 150)] % - skillratio = 150 * skill_lv + status_get_lv(target) * 5 * (status_get_lv(src) / 100) ; - if (tsd && tsd->weight) - skillratio += 100 * (tsd->weight / tsd->max_weight); - } else // ATK [(Skill Level x 100 + 500) x Caster Base Level / 100] % - skillratio += 400 + (100 * skill_lv); - RE_LVL_DMOD(100); - break; - case SR_WINDMILL: // ATK [(Caster Base Level + Caster DEX) x Caster Base Level / 100] % - skillratio = status_get_lv(src) + sstatus->dex; - RE_LVL_DMOD(100); - break; - case SR_GATEOFHELL: - if (sc && sc->data[SC_COMBO] - && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) - skillratio += 800 * skill_lv -100; - else - skillratio += 500 * skill_lv -100; - RE_LVL_DMOD(100); - break; - case SR_GENTLETOUCH_QUIET: - skillratio += 100 * skill_lv - 100 + sstatus->dex; - RE_LVL_DMOD(100); - break; - case SR_HOWLINGOFLION: - skillratio += 300 * skill_lv - 100; - RE_LVL_DMOD(150); - break; - case SR_RIDEINLIGHTNING: // ATK [{(Skill Level x 200) + Additional Damage} x Caster Base Level / 100] % - if ((sstatus->rhw.ele) == ELE_WIND || (sstatus->lhw.ele) == ELE_WIND) - skillratio += skill_lv * 50; - skillratio += -100 + 200 * skill_lv; - RE_LVL_DMOD(100); - break; - case WM_REVERBERATION_MELEE: - // ATK [{(Skill Level x 100) + 300} x Caster Base Level / 100] - skillratio += 200 + 100 * pc_checkskill(sd, WM_REVERBERATION); - RE_LVL_DMOD(100); - break; - case WM_SEVERE_RAINSTORM_MELEE: - skillratio = 50 + 50 * skill_lv; - break; - case WM_GREAT_ECHO: - skillratio += 800 + 100 * skill_lv; - if (sd) { // Still need official value [pakpil] - short lv = (short)skill_lv; - skillratio += 100 * skill_check_pc_partner(sd,skill_num,&lv,skill_get_splash(skill_num,skill_lv),0); - } - break; - case WM_SOUND_OF_DESTRUCTION: - skillratio += 400; - break; - case GN_CART_TORNADO: - // ATK [( Skill Level x 50 ) + ( Cart Weight / ( 150 - Caster Base STR ))] + ( Cart Remodeling Skill Level x 50 )] % - skillratio = 50 * skill_lv; - if (sd && sd->cart_weight) - skillratio += sd->cart_weight/10 / max(150-sstatus->str,1) + pc_checkskill(sd, GN_REMODELING_CART) * 50; - break; - case GN_CARTCANNON: - // ATK [{( Cart Remodeling Skill Level x 50 ) x ( INT / 40 )} + ( Cart Cannon Skill Level x 60 )] % - skillratio = 60 * skill_lv; - if (sd) skillratio += pc_checkskill(sd, GN_REMODELING_CART) * 50 * (sstatus->int_ / 40); - break; - case GN_SPORE_EXPLOSION: - skillratio += 200 + 100 * skill_lv; - break; - case GN_CRAZYWEED_ATK: - skillratio += 400 + 100 * skill_lv; - break; - case GN_SLINGITEM_RANGEMELEEATK: - if (sd) { - switch (sd->itemid) { - case 13260: // Apple Bomob - case 13261: // Coconut Bomb - case 13262: // Melon Bomb - case 13263: // Pinapple Bomb - skillratio += 400; // Unconfirded - break; - case 13264: // Banana Bomb 2000% - skillratio += 1900; - break; - case 13265: - skillratio -= 75; - break; // Black Lump 25% - case 13266: - skillratio -= 25; - break; // Hard Black Lump 75% - case 13267: - skillratio += 100; - break; // Extremely Hard Black Lump 200% - } - } else - skillratio += 300; // Bombs - break; - case SO_VARETYR_SPEAR: //Assumed Formula. - skillratio += -100 + 200 * (sd ? pc_checkskill(sd, SA_LIGHTNINGLOADER) : 1); - if (sc && sc->data[SC_BLAST_OPTION]) - skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; - break; - // Physical Elemantal Spirits Attack Skills - case EL_CIRCLE_OF_FIRE: - case EL_FIRE_BOMB_ATK: - case EL_STONE_RAIN: - skillratio += 200; - break; - case EL_FIRE_WAVE_ATK: - skillratio += 500; - break; - case EL_TIDAL_WEAPON: - skillratio += 1400; - break; - case EL_WIND_SLASH: - skillratio += 100; - break; - case EL_HURRICANE: - skillratio += 600; - break; - case EL_TYPOON_MIS: - case EL_WATER_SCREW_ATK: - skillratio += 900; - break; - case EL_STONE_HAMMER: - skillratio += 400; - break; - case EL_ROCK_CRUSHER: - skillratio += 700; - break; - case KO_JYUMONJIKIRI: - if (tsc && tsc->data[SC_JYUMONJIKIRI]) - wd.div_ = wd.div_ * -1;// needs more info - skillratio += -100 + 150 * skill_lv; - case KO_HUUMARANKA: - skillratio += -100 + 150 * skill_lv + sstatus->dex/2 + sstatus->agi/2; // needs more info - break; - case KO_SETSUDAN: - skillratio += 100 * (skill_lv-1); - break; - case KO_BAKURETSU: - skillratio = 50 * skill_lv * (sd?pc_checkskill(sd,NJ_TOBIDOUGU):10); - break; - case MH_NEEDLE_OF_PARALYZE: - skillratio += 600 + 100 * skill_lv; - break; - case MH_STAHL_HORN: - skillratio += 400 + 100 * skill_lv; - break; - case MH_LAVA_SLIDE: - skillratio = 70 * skill_lv; - break; - case MH_MAGMA_FLOW: - skillratio += -100 + 100 * skill_lv; - break; - } + case ASC_METEORASSAULT: + skillratio += 40*skill_lv-60; + break; + case SN_SHARPSHOOTING: + case MA_SHARPSHOOTING: + skillratio += 100+50*skill_lv; + break; + case CG_ARROWVULCAN: + skillratio += 100+100*skill_lv; + break; + case AS_SPLASHER: + skillratio += 400+50*skill_lv; + if(sd) + skillratio += 20 * pc_checkskill(sd,AS_POISONREACT); + break; + case ASC_BREAKER: + skillratio += 100*skill_lv-100; + break; + case PA_SACRIFICE: + skillratio += 10*skill_lv-10; + break; + case PA_SHIELDCHAIN: + skillratio += 30*skill_lv; + break; + case WS_CARTTERMINATION: + i = 10 * (16 - skill_lv); + if (i < 1) i = 1; + //Preserve damage ratio when max cart weight is changed. + if(sd && sd->cart_weight) + skillratio += sd->cart_weight/i * 80000/battle_config.max_cart_weight - 100; + else if (!sd) + skillratio += 80000 / i - 100; + break; + case TK_DOWNKICK: + skillratio += 60 + 20*skill_lv; + break; + case TK_STORMKICK: + skillratio += 60 + 20*skill_lv; + break; + case TK_TURNKICK: + skillratio += 90 + 30*skill_lv; + break; + case TK_COUNTER: + skillratio += 90 + 30*skill_lv; + break; + case TK_JUMPKICK: + skillratio += -70 + 10*skill_lv; + if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num) + skillratio += 10*status_get_lv(src)/3; //Tumble bonus + if (wflag) + { + skillratio += 10*status_get_lv(src)/3; //Running bonus (TODO: What is the real bonus?) + if( sc && sc->data[SC_SPURT] ) // Spurt bonus + skillratio *= 2; + } + break; + case GS_TRIPLEACTION: + skillratio += 50*skill_lv; + break; + case GS_BULLSEYE: + //Only works well against brute/demihumans non bosses. + if((tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN) + && !(tstatus->mode&MD_BOSS)) + skillratio += 400; + break; + case GS_TRACKING: + skillratio += 100 *(skill_lv+1); + break; + case GS_PIERCINGSHOT: + skillratio += 20*skill_lv; + break; + case GS_RAPIDSHOWER: + skillratio += 10*skill_lv; + break; + case GS_DESPERADO: + skillratio += 50*(skill_lv-1); + break; + case GS_DUST: + skillratio += 50*skill_lv; + break; + case GS_FULLBUSTER: + skillratio += 100*(skill_lv+2); + break; + case GS_SPREADATTACK: + #ifdef RENEWAL + skillratio += 20*(skill_lv); + #else + skillratio += 20*(skill_lv-1); + #endif + break; + case NJ_HUUMA: + skillratio += 50 + 150*skill_lv; + break; + case NJ_TATAMIGAESHI: + skillratio += 10*skill_lv; + break; + case NJ_KASUMIKIRI: + skillratio += 10*skill_lv; + break; + case NJ_KIRIKAGE: + skillratio += 100*(skill_lv-1); + break; + case KN_CHARGEATK: + { + int k = (wflag-1)/3; //+100% every 3 cells of distance + if( k > 2 ) k = 2; // ...but hard-limited to 300%. + skillratio += 100 * k; + } + break; + case HT_PHANTASMIC: + skillratio += 50; + break; + case MO_BALKYOUNG: + skillratio += 200; + break; + case HFLI_MOON: //[orn] + skillratio += 10+110*skill_lv; + break; + case HFLI_SBR44: //[orn] + skillratio += 100 *(skill_lv-1); + break; + case NPC_VAMPIRE_GIFT: + skillratio += ((skill_lv-1)%5+1)*100; + break; + case RK_SONICWAVE: + skillratio += 400 + 100 * skill_lv; + RE_LVL_DMOD(100); + break; + case RK_HUNDREDSPEAR: + skillratio += 500 + (80 * skill_lv); + if( sd ) + { + short index = sd->equip_index[EQI_HAND_R]; + if( index >= 0 && sd->inventory_data[index] + && sd->inventory_data[index]->type == IT_WEAPON ) + skillratio += max(10000 - sd->inventory_data[index]->weight, 0) / 10; + skillratio += 50 * pc_checkskill(sd,LK_SPIRALPIERCE); + } // (1 + [(Casters Base Level - 100) / 200]) + skillratio = skillratio * (100 + (status_get_lv(src)-100) / 2) / 100; + break; + case RK_WINDCUTTER: + skillratio += 50 * skill_lv; + RE_LVL_DMOD(100); + break; + case RK_IGNITIONBREAK: + i = distance_bl(src,target); + if( i < 2 ) + skillratio = 200 + 200 * skill_lv; + else if( i < 4 ) + skillratio = 100 + 200 * skill_lv; + else + skillratio = 100 + 100 * skill_lv; + RE_LVL_DMOD(100); + if( sstatus->rhw.ele == ELE_FIRE ) + skillratio += skillratio / 2; + break; + case RK_CRUSHSTRIKE: + if( sd ) + {//ATK [{Weapon Level * (Weapon Upgrade Level + 6) * 100} + (Weapon ATK) + (Weapon Weight)]% + short index = sd->equip_index[EQI_HAND_R]; + if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON ) + skillratio = sd->inventory_data[index]->weight/10 + sstatus->rhw.atk + + 100 * sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6); + } + break; + case RK_STORMBLAST: + skillratio = 100 * (sd ? pc_checkskill(sd,RK_RUNEMASTERY) : 1) + 100 * (sstatus->int_ / 4); + break; + case RK_PHANTOMTHRUST: + skillratio = 50 * skill_lv + 10 * ( sd ? pc_checkskill(sd,KN_SPEARMASTERY) : 10); + //if( s_level > 100 ) skillratio += skillratio * s_level / 150; // Base level bonus. This is official, but is disabled until I can confirm something with was changed or not. [Rytech] + //if( s_level > 100 ) skillratio += skillratio * (s_level - 100) / 200; // Base level bonus. + break; + /** + * GC Guilotine Cross + **/ + case GC_CROSSIMPACT: + skillratio += 900 + 100 * skill_lv; + RE_LVL_DMOD(120); + break; + case GC_PHANTOMMENACE: + skillratio += 200; + break; + case GC_COUNTERSLASH: + //ATK [{(Skill Level x 100) + 300} x Caster's Base Level / 120]% + ATK [(AGI x 2) + (Caster's Job Level x 4)]% + skillratio += 200 + (100 * skill_lv); + RE_LVL_DMOD(120); + skillratio += sstatus->agi + (sd?sd->status.job_level:0) * 4; + break; + case GC_ROLLINGCUTTER: + skillratio += -50 + 50 * skill_lv; + RE_LVL_DMOD(100); + break; + case GC_CROSSRIPPERSLASHER: + skillratio += 300 + 80 * skill_lv; + RE_LVL_DMOD(100); + if( sc && sc->data[SC_ROLLINGCUTTER] ) + skillratio += sc->data[SC_ROLLINGCUTTER]->val1 * sstatus->agi; + break; + /** + * Arch Bishop + **/ + case AB_DUPLELIGHT_MELEE: + skillratio += 10 * skill_lv; + break; + /** + * Ranger + **/ + case RA_ARROWSTORM: + skillratio += 900 + 80 * skill_lv; + RE_LVL_DMOD(100); + break; + case RA_AIMEDBOLT: + skillratio += 400 + 50 * skill_lv; + RE_LVL_DMOD(100); + if( tsc && (tsc->data[SC_BITE] || tsc->data[SC_ANKLE] || tsc->data[SC_ELECTRICSHOCKER]) ) + wd.div_ = tstatus->size + 2 + ( (rnd()%100 < 50-tstatus->size*10) ? 1 : 0 ); + break; + case RA_CLUSTERBOMB: + skillratio += 100 + 100 * skill_lv; + break; + case RA_WUGDASH:// ATK 300% + skillratio += 200; + break; + case RA_WUGSTRIKE: + skillratio = 200 * skill_lv; + break; + case RA_WUGBITE: + skillratio += 300 + 200 * skill_lv; + if ( skill_lv == 5 ) skillratio += 100; + break; + case RA_SENSITIVEKEEN: + skillratio += 50 * skill_lv; + break; + /** + * Mechanic + **/ + case NC_BOOSTKNUCKLE: + skillratio += 100 + 100 * skill_lv + sstatus->dex; + RE_LVL_DMOD(100); + break; + case NC_PILEBUNKER: + skillratio += 200 + 100 * skill_lv + sstatus->str; + RE_LVL_DMOD(100); + break; + case NC_VULCANARM: + skillratio = 70 * skill_lv + sstatus->dex; + RE_LVL_DMOD(100); + break; + case NC_FLAMELAUNCHER: + case NC_COLDSLOWER: + skillratio += 200 + 300 * skill_lv; + RE_LVL_DMOD(100); + break; + case NC_ARMSCANNON: + switch( tstatus->size ) { + case SZ_SMALL: skillratio += 100 + 500 * skill_lv; break;// Small + case SZ_MEDIUM: skillratio += 100 + 400 * skill_lv; break;// Medium + case SZ_BIG: skillratio += 100 + 300 * skill_lv; break;// Large + } + RE_LVL_DMOD(100); + //NOTE: Their's some other factors that affects damage, but not sure how exactly. Will recheck one day. [Rytech] + break; + case NC_AXEBOOMERANG: + skillratio += 60 + 40 * skill_lv; + if( sd ) { + short index = sd->equip_index[EQI_HAND_R]; + if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON ) + skillratio += sd->inventory_data[index]->weight / 10;// Weight is divided by 10 since 10 weight in coding make 1 whole actural weight. [Rytech] + } + RE_LVL_DMOD(100); + break; + case NC_POWERSWING: + skillratio += 80 + 20 * skill_lv + sstatus->str + sstatus->dex; + RE_LVL_DMOD(100); + break; + case NC_AXETORNADO: + skillratio += 100 + 100 * skill_lv + sstatus->vit; + RE_LVL_DMOD(100); + break; + case SC_FATALMENACE: + skillratio += 100 * skill_lv; + break; + case SC_TRIANGLESHOT: + skillratio += 270 + 30 * skill_lv; + break; + case SC_FEINTBOMB: + skillratio += 100 + 100 * skill_lv; + break; + case LG_CANNONSPEAR:// Stimated formula. Still need confirm it. + skillratio += -100 + (50 + sstatus->str) * skill_lv; + RE_LVL_DMOD(100); + break; + case LG_BANISHINGPOINT: + skillratio += -100 + ((50 * skill_lv) + (30 * ((sd)?pc_checkskill(sd,SM_BASH):1))); + RE_LVL_DMOD(100); + break; + case LG_SHIELDPRESS: + skillratio += 60 + 43 * skill_lv; + RE_LVL_DMOD(100); + break; + case LG_PINPOINTATTACK: + skillratio = ((100 * skill_lv) + (10 * status_get_agi(src)) ); + RE_LVL_DMOD(100); + break; + case LG_RAGEBURST: + if( sd && sd->spiritball_old ) + skillratio += -100 + (sd->spiritball_old * 200); + else + skillratio += -100 + 15 * 200; + RE_LVL_DMOD(100); + break; + case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield DEF x 10) + (Casters VIT x 2)] % + if( sd ) { + struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; + skillratio = status_get_lv(src) * 4 + status_get_vit(src) * 2; + if( shield_data ) + skillratio += shield_data->def * 10; + } else + skillratio += 2400; //2500% + break; + case LG_MOONSLASHER: + skillratio += -100 + (120 * skill_lv + ((sd) ? pc_checkskill(sd,LG_OVERBRAND) : 5) * 80); + RE_LVL_DMOD(100); + break; + case LG_OVERBRAND: + skillratio = 400 * skill_lv + (pc_checkskill(sd,CR_SPEARQUICKEN) * 30); + RE_LVL_DMOD(100); + break; + case LG_OVERBRAND_BRANDISH: + skillratio = 300 * skill_lv + (2 * (sstatus->str + sstatus->dex) / 3); + RE_LVL_DMOD(100); + break; + case LG_OVERBRAND_PLUSATK: + skillratio = 150 * skill_lv; + RE_LVL_DMOD(100); + break; + case LG_RAYOFGENESIS: + skillratio = skillratio + 200 + 300 * skill_lv; + RE_LVL_DMOD(100); + break; + case LG_EARTHDRIVE: + skillratio = (skillratio + 100) * skill_lv; + RE_LVL_DMOD(100); + break; + case LG_HESPERUSLIT: + skillratio += 120 * skill_lv - 100; + break; + case SR_DRAGONCOMBO: + skillratio += 40 * skill_lv; + RE_LVL_DMOD(100); + break; + case SR_SKYNETBLOW: + //ATK [{(Skill Level x 80) + (Caster AGI)} x Caster Base Level / 100] % + skillratio = 80 * skill_lv + sstatus->agi; + if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_DRAGONCOMBO )//ATK [{(Skill Level x 100) + (Caster AGI) + 150} x Caster Base Level / 100] % + skillratio = 100 * skill_lv + sstatus->agi + 150; + RE_LVL_DMOD(100); + break; + case SR_EARTHSHAKER: + if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || // [(Skill Level x 150) x (Caster Base Level / 100) + (Caster INT x 3)] % + tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || tsc->data[SC__INVISIBILITY]) ){ + skillratio = 150 * skill_lv; + RE_LVL_DMOD(100); + skillratio += sstatus->int_ * 3; + }else{ //[(Skill Level x 50) x (Caster Base Level / 100) + (Caster INT x 2)] % + skillratio += 50 * (skill_lv-2); + RE_LVL_DMOD(100); + skillratio += sstatus->int_ * 2; + } + break; + case SR_FALLENEMPIRE:// ATK [(Skill Level x 150 + 100) x Caster Base Level / 150] % + skillratio += 150 *skill_lv; + RE_LVL_DMOD(150); + break; + case SR_TIGERCANNON:// ATK [((Caster consumed HP + SP) / 4) x Caster Base Level / 100] % + { + int hp = sstatus->max_hp * (10 + 2 * skill_lv) / 100, + sp = sstatus->max_sp * (6 + skill_lv) / 100; + skillratio = (hp+sp) / 4; + if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) // ATK [((Caster consumed HP + SP) / 2) x Caster Base Level / 100] % + skillratio = (hp+sp) / 2; + RE_LVL_DMOD(100); + } + break; + case SR_RAMPAGEBLASTER: + skillratio += 20 * skill_lv * (sd?sd->spiritball_old:5) - 100; + if( sc && sc->data[SC_EXPLOSIONSPIRITS] ){ + skillratio += sc->data[SC_EXPLOSIONSPIRITS]->val1 * 20; + RE_LVL_DMOD(120); + }else + RE_LVL_DMOD(150); + break; + case SR_KNUCKLEARROW: + if( wflag&4 ){ // ATK [(Skill Level x 150) + (1000 x Target current weight / Maximum weight) + (Target Base Level x 5) x (Caster Base Level / 150)] % + skillratio = 150 * skill_lv + status_get_lv(target) * 5 * (status_get_lv(src) / 100) ; + if( tsd && tsd->weight ) + skillratio += 100 * (tsd->weight / tsd->max_weight); + }else // ATK [(Skill Level x 100 + 500) x Caster Base Level / 100] % + skillratio += 400 + (100 * skill_lv); + RE_LVL_DMOD(100); + break; + case SR_WINDMILL: // ATK [(Caster Base Level + Caster DEX) x Caster Base Level / 100] % + skillratio = status_get_lv(src) + sstatus->dex; + RE_LVL_DMOD(100); + break; + case SR_GATEOFHELL: + if( sc && sc->data[SC_COMBO] + && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) + skillratio += 800 * skill_lv -100; + else + skillratio += 500 * skill_lv -100; + RE_LVL_DMOD(100); + break; + case SR_GENTLETOUCH_QUIET: + skillratio += 100 * skill_lv - 100 + sstatus->dex; + RE_LVL_DMOD(100); + break; + case SR_HOWLINGOFLION: + skillratio += 300 * skill_lv - 100; + RE_LVL_DMOD(150); + break; + case SR_RIDEINLIGHTNING: // ATK [{(Skill Level x 200) + Additional Damage} x Caster Base Level / 100] % + if( (sstatus->rhw.ele) == ELE_WIND || (sstatus->lhw.ele) == ELE_WIND ) + skillratio += skill_lv * 50; + skillratio += -100 + 200 * skill_lv; + RE_LVL_DMOD(100); + break; + case WM_REVERBERATION_MELEE: + // ATK [{(Skill Level x 100) + 300} x Caster Base Level / 100] + skillratio += 200 + 100 * pc_checkskill(sd, WM_REVERBERATION); + RE_LVL_DMOD(100); + break; + case WM_SEVERE_RAINSTORM_MELEE: + skillratio = 50 + 50 * skill_lv; + break; + case WM_GREAT_ECHO: + skillratio += 800 + 100 * skill_lv; + if( sd ) { // Still need official value [pakpil] + short lv = (short)skill_lv; + skillratio += 100 * skill_check_pc_partner(sd,skill_num,&lv,skill_get_splash(skill_num,skill_lv),0); + } + break; + case WM_SOUND_OF_DESTRUCTION: + skillratio += 400; + break; + case GN_CART_TORNADO: + // ATK [( Skill Level x 50 ) + ( Cart Weight / ( 150 - Caster Base STR ))] + ( Cart Remodeling Skill Level x 50 )] % + skillratio = 50 * skill_lv; + if( sd && sd->cart_weight) + skillratio += sd->cart_weight/10 / max(150-sstatus->str,1) + pc_checkskill(sd, GN_REMODELING_CART) * 50; + break; + case GN_CARTCANNON: + // ATK [{( Cart Remodeling Skill Level x 50 ) x ( INT / 40 )} + ( Cart Cannon Skill Level x 60 )] % + skillratio = 60 * skill_lv; + if( sd ) skillratio += pc_checkskill(sd, GN_REMODELING_CART) * 50 * (sstatus->int_ / 40); + break; + case GN_SPORE_EXPLOSION: + skillratio += 200 + 100 * skill_lv; + break; + case GN_CRAZYWEED_ATK: + skillratio += 400 + 100 * skill_lv; + break; + case GN_SLINGITEM_RANGEMELEEATK: + if( sd ) { + switch( sd->itemid ) { + case 13260: // Apple Bomob + case 13261: // Coconut Bomb + case 13262: // Melon Bomb + case 13263: // Pinapple Bomb + skillratio += 400; // Unconfirded + break; + case 13264: // Banana Bomb 2000% + skillratio += 1900; + break; + case 13265: skillratio -= 75; break; // Black Lump 25% + case 13266: skillratio -= 25; break; // Hard Black Lump 75% + case 13267: skillratio += 100; break; // Extremely Hard Black Lump 200% + } + } else + skillratio += 300; // Bombs + break; + case SO_VARETYR_SPEAR: //Assumed Formula. + skillratio += -100 + 200 * ( sd ? pc_checkskill(sd, SA_LIGHTNINGLOADER) : 1 ); + if( sc && sc->data[SC_BLAST_OPTION] ) + skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; + break; + // Physical Elemantal Spirits Attack Skills + case EL_CIRCLE_OF_FIRE: + case EL_FIRE_BOMB_ATK: + case EL_STONE_RAIN: + skillratio += 200; + break; + case EL_FIRE_WAVE_ATK: + skillratio += 500; + break; + case EL_TIDAL_WEAPON: + skillratio += 1400; + break; + case EL_WIND_SLASH: + skillratio += 100; + break; + case EL_HURRICANE: + skillratio += 600; + break; + case EL_TYPOON_MIS: + case EL_WATER_SCREW_ATK: + skillratio += 900; + break; + case EL_STONE_HAMMER: + skillratio += 400; + break; + case EL_ROCK_CRUSHER: + skillratio += 700; + break; + case KO_JYUMONJIKIRI: + if( tsc && tsc->data[SC_JYUMONJIKIRI] ) + wd.div_ = wd.div_ * -1;// needs more info + skillratio += -100 + 150 * skill_lv; + case KO_HUUMARANKA: + skillratio += -100 + 150 * skill_lv + sstatus->dex/2 + sstatus->agi/2; // needs more info + break; + case KO_SETSUDAN: + skillratio += 100 * (skill_lv-1); + break; + case KO_BAKURETSU: + skillratio = 50 * skill_lv * (sd?pc_checkskill(sd,NJ_TOBIDOUGU):10); + break; + case MH_NEEDLE_OF_PARALYZE: + skillratio += 600 + 100 * skill_lv; + break; + case MH_STAHL_HORN: + skillratio += 400 + 100 * skill_lv; + break; + case MH_LAVA_SLIDE: + skillratio = 70 * skill_lv; + break; + case MH_MAGMA_FLOW: + skillratio += -100 + 100 * skill_lv; + break; + } - ATK_RATE(skillratio); - - //Constant/misc additions from skills - switch (skill_num) { - case MO_EXTREMITYFIST: - ATK_ADD(250 + 150*skill_lv); - break; - case TK_DOWNKICK: - case TK_STORMKICK: - case TK_TURNKICK: - case TK_COUNTER: - case TK_JUMPKICK: - //TK_RUN kick damage bonus. - if (sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST) - ATK_ADD(10*pc_checkskill(sd, TK_RUN)); - break; - case GS_MAGICALBULLET: - if (sstatus->matk_max>sstatus->matk_min) { - ATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); - } else { - ATK_ADD(sstatus->matk_min); - } - break; - case NJ_SYURIKEN: - ATK_ADD(4*skill_lv); - break; - case HT_FREEZINGTRAP: - if (sd) - ATK_ADD(40 * pc_checkskill(sd, RA_RESEARCHTRAP)); - break; - case RA_WUGDASH ://(Caster Current Weight x 10 / 8) - if (sd && sd->weight) - ATK_ADD(sd->weight / 8); - case RA_WUGSTRIKE: - case RA_WUGBITE: - if (sd) - ATK_ADD(30*pc_checkskill(sd, RA_TOOTHOFWUG)); - break; - case LG_RAYOFGENESIS: - if (sc && sc->data[SC_BANDING]) { // Increase only if the RG is under Banding. - short lv = (short)skill_lv; - ATK_ADDRATE(190 * ((sd) ? skill_check_pc_partner(sd,(short)skill_num,&lv,skill_get_splash(skill_num,skill_lv),0) : 1)); - } - break; - case SR_GATEOFHELL: - ATK_ADD(sstatus->max_hp - status_get_hp(src)); - if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) { - ATK_ADD((sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status_get_lv(src)); - } else { - ATK_ADD((sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status_get_lv(src)); - } - break; - case SR_TIGERCANNON: // (Tiger Cannon skill level x 240) + (Target Base Level x 40) - ATK_ADD(skill_lv * 240 + status_get_lv(target) * 40); - if (sc && sc->data[SC_COMBO] - && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) // (Tiger Cannon skill level x 500) + (Target Base Level x 40) - ATK_ADD(skill_lv * 500 + status_get_lv(target) * 40); - break; - case SR_FALLENEMPIRE:// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)] - ATK_ADD(((tstatus->size+1)*2 + skill_lv - 1) * sstatus->str); - if (tsd && tsd->weight) { - ATK_ADD((tsd->weight/10) * sstatus->dex / 120); - } else { - ATK_ADD(status_get_lv(target) * 50); //mobs - } - break; - case KO_SETSUDAN: - if (tsc && tsc->data[SC_SPIRIT]) { - ATK_ADDRATE(10*tsc->data[SC_SPIRIT]->val1);// +10% custom value. - status_change_end(target,SC_SPIRIT,INVALID_TIMER); - } - break; - case KO_KAIHOU: - if (sd) { - ARR_FIND(1, 6, i, sd->talisman[i] > 0); - if (i < 5) { - s_ele = i; - ATK_ADDRATE(100 * sd->talisman[i]);// +100% custom value. - pc_del_talisman(sd, sd->talisman[i], i); - } - } - break; - } - } - //Div fix. - damage_div_fix(wd.damage, wd.div_); - - //The following are applied on top of current damage and are stackable. - if (sc) { - if (sc->data[SC_TRUESIGHT]) - ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1); - if (sc->data[SC_GLOOMYDAY_SK] && - (skill_num == LK_SPIRALPIERCE || skill_num == KN_BRANDISHSPEAR || - skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN || - skill_num == LG_SHIELDPRESS)) - ATK_ADDRATE(sc->data[SC_GLOOMYDAY_SK]->val2); - if (sc->data[SC_EDP]) { - switch (skill_num) { - case AS_SPLASHER: - case AS_VENOMKNIFE: - case AS_GRIMTOOTH: - break; + ATK_RATE(skillratio); + + //Constant/misc additions from skills + switch (skill_num) { + case MO_EXTREMITYFIST: + ATK_ADD(250 + 150*skill_lv); + break; + case TK_DOWNKICK: + case TK_STORMKICK: + case TK_TURNKICK: + case TK_COUNTER: + case TK_JUMPKICK: + //TK_RUN kick damage bonus. + if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST) + ATK_ADD(10*pc_checkskill(sd, TK_RUN)); + break; + case GS_MAGICALBULLET: + if(sstatus->matk_max>sstatus->matk_min) { + ATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); + } else { + ATK_ADD(sstatus->matk_min); + } + break; + case NJ_SYURIKEN: + ATK_ADD(4*skill_lv); + break; + case HT_FREEZINGTRAP: + if(sd) + ATK_ADD( 40 * pc_checkskill(sd, RA_RESEARCHTRAP) ); + break; + case RA_WUGDASH ://(Caster Current Weight x 10 / 8) + if( sd && sd->weight ) + ATK_ADD( sd->weight / 8 ); + case RA_WUGSTRIKE: + case RA_WUGBITE: + if(sd) + ATK_ADD(30*pc_checkskill(sd, RA_TOOTHOFWUG)); + break; + case LG_RAYOFGENESIS: + if( sc && sc->data[SC_BANDING] ) {// Increase only if the RG is under Banding. + short lv = (short)skill_lv; + ATK_ADDRATE( 190 * ((sd) ? skill_check_pc_partner(sd,(short)skill_num,&lv,skill_get_splash(skill_num,skill_lv),0) : 1)); + } + break; + case SR_GATEOFHELL: + ATK_ADD (sstatus->max_hp - status_get_hp(src)); + if(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE){ + ATK_ADD ( (sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status_get_lv(src) ); + }else{ + ATK_ADD ( (sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status_get_lv(src) ); + } + break; + case SR_TIGERCANNON: // (Tiger Cannon skill level x 240) + (Target Base Level x 40) + ATK_ADD( skill_lv * 240 + status_get_lv(target) * 40 ); + if( sc && sc->data[SC_COMBO] + && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) // (Tiger Cannon skill level x 500) + (Target Base Level x 40) + ATK_ADD( skill_lv * 500 + status_get_lv(target) * 40 ); + break; + case SR_FALLENEMPIRE:// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)] + ATK_ADD( ((tstatus->size+1)*2 + skill_lv - 1) * sstatus->str); + if( tsd && tsd->weight ){ + ATK_ADD( (tsd->weight/10) * sstatus->dex / 120 ); + }else{ + ATK_ADD( status_get_lv(target) * 50 ); //mobs + } + break; + case KO_SETSUDAN: + if( tsc && tsc->data[SC_SPIRIT] ){ + ATK_ADDRATE(10*tsc->data[SC_SPIRIT]->val1);// +10% custom value. + status_change_end(target,SC_SPIRIT,INVALID_TIMER); + } + break; + case KO_KAIHOU: + if( sd ){ + ARR_FIND(1, 6, i, sd->talisman[i] > 0); + if( i < 5 ){ + s_ele = i; + ATK_ADDRATE(100 * sd->talisman[i]);// +100% custom value. + pc_del_talisman(sd, sd->talisman[i], i); + } + } + break; + } + } + //Div fix. + damage_div_fix(wd.damage, wd.div_); + + //The following are applied on top of current damage and are stackable. + if ( sc ) { + if( sc->data[SC_TRUESIGHT] ) + ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1); + if( sc->data[SC_GLOOMYDAY_SK] && + ( skill_num == LK_SPIRALPIERCE || skill_num == KN_BRANDISHSPEAR || + skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN || + skill_num == LG_SHIELDPRESS ) ) + ATK_ADDRATE(sc->data[SC_GLOOMYDAY_SK]->val2); + if( sc->data[SC_EDP] ){ + switch(skill_num){ + case AS_SPLASHER: case AS_VENOMKNIFE: + case AS_GRIMTOOTH: + break; #ifndef RENEWAL_EDP - case ASC_BREAKER: - case ASC_METEORASSAULT: - break; + case ASC_BREAKER: case ASC_METEORASSAULT: break; #else - case AS_SONICBLOW: - case ASC_BREAKER: - case GC_COUNTERSLASH: - case GC_CROSSIMPACT: - ATK_RATE(50); // only modifier is halved but still benefit with the damage bonus + case AS_SONICBLOW: + case ASC_BREAKER: + case GC_COUNTERSLASH: + case GC_CROSSIMPACT: + ATK_RATE(50); // only modifier is halved but still benefit with the damage bonus #endif - default: - ATK_ADDRATE(sc->data[SC_EDP]->val3); - } - } - if (sc->data[SC_STYLE_CHANGE]) { + default: + ATK_ADDRATE(sc->data[SC_EDP]->val3); + } + } + if(sc->data[SC_STYLE_CHANGE]){ TBL_HOM *hd = BL_CAST(BL_HOM,src); if (hd) ATK_ADD(hd->spiritball * 3); } - } + } - switch (skill_num) { - case AS_SONICBLOW: - if (sc && sc->data[SC_SPIRIT] && - sc->data[SC_SPIRIT]->val2 == SL_ASSASIN) - ATK_ADDRATE(map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe - - if (sd && pc_checkskill(sd,AS_SONICACCEL)>0) - ATK_ADDRATE(10); - break; - case CR_SHIELDBOOMERANG: - if (sc && sc->data[SC_SPIRIT] && - sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) - ATK_ADDRATE(100); - break; - case NC_AXETORNADO: - if ((sstatus->rhw.ele) == ELE_WIND || (sstatus->lhw.ele) == ELE_WIND) - ATK_ADDRATE(50); - break; - } + switch (skill_num) { + case AS_SONICBLOW: + if (sc && sc->data[SC_SPIRIT] && + sc->data[SC_SPIRIT]->val2 == SL_ASSASIN) + ATK_ADDRATE(map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe - if (sd) { - if (skill_num && (i = pc_skillatk_bonus(sd, skill_num))) - ATK_ADDRATE(i); - - if (skill_num != PA_SACRIFICE && skill_num != MO_INVESTIGATE && skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS && skill_num != PA_SHIELDCHAIN && !flag.cri) { - //Elemental/Racial adjustments - if (sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || - sd->right_weapon.def_ratio_atk_race & (1<<tstatus->race) || - sd->right_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) - ) - flag.pdef = 1; - - if (sd->left_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || - sd->left_weapon.def_ratio_atk_race & (1<<tstatus->race) || - sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) - ) { - //Pass effect onto right hand if configured so. [Skotlex] - if (battle_config.left_cardfix_to_right && flag.rh) - flag.pdef = 1; - else - flag.pdef2 = 1; - } - } + if(sd && pc_checkskill(sd,AS_SONICACCEL)>0) + ATK_ADDRATE(10); + break; + case CR_SHIELDBOOMERANG: + if(sc && sc->data[SC_SPIRIT] && + sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) + ATK_ADDRATE(100); + break; + case NC_AXETORNADO: + if( (sstatus->rhw.ele) == ELE_WIND || (sstatus->lhw.ele) == ELE_WIND ) + ATK_ADDRATE(50); + break; + } - if (skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS) { - //Ignore Defense? - if (!flag.idef && ( - sd->right_weapon.ignore_def_ele & (1<<tstatus->def_ele) || - sd->right_weapon.ignore_def_race & (1<<tstatus->race) || - sd->right_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS) - )) - flag.idef = 1; - - if (!flag.idef2 && ( - sd->left_weapon.ignore_def_ele & (1<<tstatus->def_ele) || - sd->left_weapon.ignore_def_race & (1<<tstatus->race) || - sd->left_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS) - )) { - if (battle_config.left_cardfix_to_right && flag.rh) //Move effect to right hand. [Skotlex] - flag.idef = 1; - else - flag.idef2 = 1; - } - } - } + if( sd ) + { + if (skill_num && (i = pc_skillatk_bonus(sd, skill_num))) + ATK_ADDRATE(i); + + if( skill_num != PA_SACRIFICE && skill_num != MO_INVESTIGATE && skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS && skill_num != PA_SHIELDCHAIN && !flag.cri ) + { //Elemental/Racial adjustments + if( sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || + sd->right_weapon.def_ratio_atk_race & (1<<tstatus->race) || + sd->right_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) + ) + flag.pdef = 1; + + if( sd->left_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || + sd->left_weapon.def_ratio_atk_race & (1<<tstatus->race) || + sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) + ) + { //Pass effect onto right hand if configured so. [Skotlex] + if (battle_config.left_cardfix_to_right && flag.rh) + flag.pdef = 1; + else + flag.pdef2 = 1; + } + } - if (!flag.idef || !flag.idef2) { - //Defense reduction - short vit_def; - defType def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions. - short def2 = (short)tstatus->def2; - - if (sd) { - i = sd->ignore_def[is_boss(target)?RC_BOSS:RC_NONBOSS]; - i += sd->ignore_def[tstatus->race]; - if (i) { - if (i > 100) i = 100; - def1 -= def1 * i / 100; - def2 -= def2 * i / 100; - } - } + if (skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS) + { //Ignore Defense? + if (!flag.idef && ( + sd->right_weapon.ignore_def_ele & (1<<tstatus->def_ele) || + sd->right_weapon.ignore_def_race & (1<<tstatus->race) || + sd->right_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS) + )) + flag.idef = 1; + + if (!flag.idef2 && ( + sd->left_weapon.ignore_def_ele & (1<<tstatus->def_ele) || + sd->left_weapon.ignore_def_race & (1<<tstatus->race) || + sd->left_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS) + )) { + if(battle_config.left_cardfix_to_right && flag.rh) //Move effect to right hand. [Skotlex] + flag.idef = 1; + else + flag.idef2 = 1; + } + } + } - if (sc && sc->data[SC_EXPIATIO]) { - i = 5 * sc->data[SC_EXPIATIO]->val1; // 5% per level - def1 -= def1 * i / 100; - def2 -= def2 * i / 100; - } + if (!flag.idef || !flag.idef2) + { //Defense reduction + short vit_def; + defType def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions. + short def2 = (short)tstatus->def2; - if (tsc && tsc->data[SC_GT_REVITALIZE] && tsc->data[SC_GT_REVITALIZE]->val4) - def2 += 2 * tsc->data[SC_GT_REVITALIZE]->val4; + if( sd ) + { + i = sd->ignore_def[is_boss(target)?RC_BOSS:RC_NONBOSS]; + i += sd->ignore_def[tstatus->race]; + if( i ) + { + if( i > 100 ) i = 100; + def1 -= def1 * i / 100; + def2 -= def2 * i / 100; + } + } - if (tsc && tsc->data[SC_CAMOUFLAGE]) { - i = 5 * (10-tsc->data[SC_CAMOUFLAGE]->val4); - def1 -= def1 * i / 100; - def2 -= def2 * i / 100; - } + if( sc && sc->data[SC_EXPIATIO] ){ + i = 5 * sc->data[SC_EXPIATIO]->val1; // 5% per level + def1 -= def1 * i / 100; + def2 -= def2 * i / 100; + } - if (battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type) { - unsigned char target_count; //256 max targets should be a sane max - target_count = unit_counttargeted(target); - if (target_count >= battle_config.vit_penalty_count) { - if (battle_config.vit_penalty_type == 1) { - if (!tsc || !tsc->data[SC_STEELBODY]) - 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; - } else { //Assume type 2 - if (!tsc || !tsc->data[SC_STEELBODY]) - 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; - } - } - if (skill_num == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex] - if (def2 < 1) def2 = 1; - } - //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def - if (tsd) { //Sd vit-eq - //[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1)) - vit_def = def2*(def2-15)/150; - vit_def = def2/2 + (vit_def>0?rnd()%vit_def:0); - - if ((battle_check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesnt work vs players - src->type == BL_MOB && (skill=pc_checkskill(tsd,AL_DP)) > 0) - vit_def += skill*(int)(3 +(tsd->status.base_level+1)*0.04); // submitted by orn - if (src->type == BL_MOB && (skill=pc_checkskill(tsd,RA_RANGERMAIN))>0 && - (sstatus->race == RC_BRUTE || sstatus->race == RC_FISH || sstatus->race == RC_PLANT)) - vit_def += skill*5; - } else { //Mob-Pet vit-eq - //VIT + rnd(0,[VIT/20]^2-1) - vit_def = (def2/20)*(def2/20); - vit_def = def2 + (vit_def>0?rnd()%vit_def:0); - } + if( tsc && tsc->data[SC_GT_REVITALIZE] && tsc->data[SC_GT_REVITALIZE]->val4 ) + def2 += 2 * tsc->data[SC_GT_REVITALIZE]->val4; - if (battle_config.weapon_defense_type) { - vit_def += def1*battle_config.weapon_defense_type; - def1 = 0; - } -#ifdef RENEWAL - /** - * In Renewal 100% damage reduction is 900 DEF - * Formula: (1+(900-def1)/9)% - **/ - if (def1 > 900) def1 = 900; - ATK_RATE2( - flag.idef ?100:(flag.pdef ?(int)(flag.pdef *(def1+vit_def)):(1+(900-def1)/9)), - flag.idef2?100:(flag.pdef2?(int)(flag.pdef2*(def1+vit_def)):(1+(900-def1)/9)) - ); -#else - if (def1 > 100) def1 = 100; - ATK_RATE2( - flag.idef ?100:(flag.pdef ?(int)(flag.pdef *(def1+vit_def)):(100-def1)), - flag.idef2?100:(flag.pdef2?(int)(flag.pdef2*(def1+vit_def)):(100-def1)) - ); -#endif - ATK_ADD2( - flag.idef ||flag.pdef ?0:-vit_def, - flag.idef2||flag.pdef2?0:-vit_def - ); - } + if( tsc && tsc->data[SC_CAMOUFLAGE] ){ + i = 5 * (10-tsc->data[SC_CAMOUFLAGE]->val4); + def1 -= def1 * i / 100; + def2 -= def2 * i / 100; + } + + if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) { + unsigned char target_count; //256 max targets should be a sane max + target_count = unit_counttargeted(target); + if(target_count >= battle_config.vit_penalty_count) { + if(battle_config.vit_penalty_type == 1) { + if( !tsc || !tsc->data[SC_STEELBODY] ) + 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; + } else { //Assume type 2 + if( !tsc || !tsc->data[SC_STEELBODY] ) + 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; + } + } + if(skill_num == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex] + if(def2 < 1) def2 = 1; + } + //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def + if (tsd) //Sd vit-eq + { //[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1)) + vit_def = def2*(def2-15)/150; + vit_def = def2/2 + (vit_def>0?rnd()%vit_def:0); + + if((battle_check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesnt work vs players + src->type == BL_MOB && (skill=pc_checkskill(tsd,AL_DP)) > 0) + vit_def += skill*(int)(3 +(tsd->status.base_level+1)*0.04); // submitted by orn + if( src->type == BL_MOB && (skill=pc_checkskill(tsd,RA_RANGERMAIN))>0 && + (sstatus->race == RC_BRUTE || sstatus->race == RC_FISH || sstatus->race == RC_PLANT) ) + vit_def += skill*5; + } else { //Mob-Pet vit-eq + //VIT + rnd(0,[VIT/20]^2-1) + vit_def = (def2/20)*(def2/20); + vit_def = def2 + (vit_def>0?rnd()%vit_def:0); + } + + if (battle_config.weapon_defense_type) { + vit_def += def1*battle_config.weapon_defense_type; + def1 = 0; + } + #ifdef RENEWAL + /** + * In Renewal 100% damage reduction is 900 DEF + * Formula: (1+(900-def1)/9)% + **/ + if (def1 > 900) def1 = 900; + ATK_RATE2( + flag.idef ?100:(flag.pdef ?(int)(flag.pdef *(def1+vit_def)):(1+(900-def1)/9)), + flag.idef2?100:(flag.pdef2?(int)(flag.pdef2*(def1+vit_def)):(1+(900-def1)/9)) + ); + #else + if (def1 > 100) def1 = 100; + ATK_RATE2( + flag.idef ?100:(flag.pdef ?(int)(flag.pdef *(def1+vit_def)):(100-def1)), + flag.idef2?100:(flag.pdef2?(int)(flag.pdef2*(def1+vit_def)):(100-def1)) + ); + #endif + ATK_ADD2( + flag.idef ||flag.pdef ?0:-vit_def, + flag.idef2||flag.pdef2?0:-vit_def + ); + } - //Post skill/vit reduction damage increases - if (sc) { - //SC skill damages - if (sc->data[SC_AURABLADE] + //Post skill/vit reduction damage increases + if( sc ) + { //SC skill damages + if(sc->data[SC_AURABLADE] #ifndef RENEWAL - && skill_num != LK_SPIRALPIERCE && skill_num != ML_SPIRALPIERCE + && skill_num != LK_SPIRALPIERCE && skill_num != ML_SPIRALPIERCE #endif - ) { - int lv = sc->data[SC_AURABLADE]->val1; + ){ + int lv = sc->data[SC_AURABLADE]->val1; #ifdef RENEWAL - lv *= ((skill_num == LK_SPIRALPIERCE || skill_num == ML_SPIRALPIERCE)?wd.div_:1); // +100 per hit in lv 5 + lv *= ((skill_num == LK_SPIRALPIERCE || skill_num == ML_SPIRALPIERCE)?wd.div_:1); // +100 per hit in lv 5 #endif - ATK_ADD(20*lv); - } + ATK_ADD(20*lv); + } - if (sc->data[SC_GN_CARTBOOST]) - ATK_ADD(10*sc->data[SC_GN_CARTBOOST]->val1); + if(sc->data[SC_GN_CARTBOOST]) + ATK_ADD(10*sc->data[SC_GN_CARTBOOST]->val1); - if (sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val2) { - struct block_list *bl; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] - if ((bl = map_id2bl(sc->data[SC_GT_CHANGE]->val2))) - ATK_ADD((status_get_dex(bl)/4 + status_get_str(bl)/2) * sc->data[SC_GT_CHANGE]->val1 / 5); - } + if(sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val2){ + struct block_list *bl; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] + if( (bl = map_id2bl(sc->data[SC_GT_CHANGE]->val2)) ) + ATK_ADD( ( status_get_dex(bl)/4 + status_get_str(bl)/2 ) * sc->data[SC_GT_CHANGE]->val1 / 5 ); + } - if (sc->data[SC_CAMOUFLAGE]) - ATK_ADD(30 * (10-sc->data[SC_CAMOUFLAGE]->val4)); - } + if(sc->data[SC_CAMOUFLAGE]) + ATK_ADD(30 * (10-sc->data[SC_CAMOUFLAGE]->val4) ); + } - //Refine bonus - if (sd && flag.weapon && skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST) { - // Counts refine bonus multiple times - if (skill_num == MO_FINGEROFFENSIVE) { - ATK_ADD2(wd.div_*sstatus->rhw.atk2, wd.div_*sstatus->lhw.atk2); - } else { - ATK_ADD2(sstatus->rhw.atk2, sstatus->lhw.atk2); - } - } + //Refine bonus + if( sd && flag.weapon && skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST ) + { // Counts refine bonus multiple times + if( skill_num == MO_FINGEROFFENSIVE ) + { + ATK_ADD2(wd.div_*sstatus->rhw.atk2, wd.div_*sstatus->lhw.atk2); + } else { + ATK_ADD2(sstatus->rhw.atk2, sstatus->lhw.atk2); + } + } - //Set to min of 1 - if (flag.rh && wd.damage < 1) wd.damage = 1; - if (flag.lh && wd.damage2 < 1) wd.damage2 = 1; - - if (sd && flag.weapon && - skill_num != MO_INVESTIGATE && - skill_num != MO_EXTREMITYFIST && - skill_num != CR_GRANDCROSS) { - //Add mastery damage - if (skill_num != ASC_BREAKER && sd->status.weapon == W_KATAR && - (skill=pc_checkskill(sd,ASC_KATAR)) > 0) { - //Adv Katar Mastery is does not applies to ASC_BREAKER, - // but other masteries DO apply >_> - ATK_ADDRATE(10+ 2*skill); - } + //Set to min of 1 + if (flag.rh && wd.damage < 1) wd.damage = 1; + if (flag.lh && wd.damage2 < 1) wd.damage2 = 1; + + if (sd && flag.weapon && + skill_num != MO_INVESTIGATE && + skill_num != MO_EXTREMITYFIST && + skill_num != CR_GRANDCROSS) + { //Add mastery damage + if(skill_num != ASC_BREAKER && sd->status.weapon == W_KATAR && + (skill=pc_checkskill(sd,ASC_KATAR)) > 0) + { //Adv Katar Mastery is does not applies to ASC_BREAKER, + // but other masteries DO apply >_> + ATK_ADDRATE(10+ 2*skill); + } - wd.damage = battle_addmastery(sd,target,wd.damage,0); - if (flag.lh) - wd.damage2 = battle_addmastery(sd,target,wd.damage2,1); - - if (sc && sc->data[SC_MIRACLE]) i = 2; //Star anger - else - ARR_FIND(0, MAX_PC_FEELHATE, i, t_class == sd->hate_mob[i]); - if (i < MAX_PC_FEELHATE && (skill=pc_checkskill(sd,sg_info[i].anger_id))) { - skillratio = sd->status.base_level + sstatus->dex + sstatus->luk; - if (i == 2) skillratio += sstatus->str; //Star Anger - if (skill<4) - skillratio /= 12-3*skill; - ATK_ADDRATE(skillratio); - } - if (skill_num == NJ_SYURIKEN && (skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0) - ATK_ADD(3*skill); - if (skill_num == NJ_KUNAI) - ATK_ADD(60); - } - } //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks - else if (wd.div_ < 0) //Since the attack missed... - wd.div_ *= -1; - - if (sd && (skill=pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) - ATK_ADD(skill*2); - - if (skill_num==TF_POISON) - ATK_ADD(15*skill_lv); - - if (!(nk &NK_NO_ELEFIX) && !n_ele) { - //Elemental attribute fix - if (wd.damage > 0) { - wd.damage=battle_attr_fix(src,target,wd.damage,s_ele,tstatus->def_ele, tstatus->ele_lv); - if (skill_num == MC_CARTREVOLUTION) //Cart Revolution applies the element fix once more with neutral element - wd.damage = battle_attr_fix(src,target,wd.damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); - if (skill_num== GS_GROUNDDRIFT) //Additional 50*lv Neutral damage. - wd.damage += battle_attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); - } - if (flag.lh && wd.damage2 > 0) - wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); - if (sc && sc->data[SC_WATK_ELEMENT]) { - // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex] - int damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; - wd.damage += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); - - if (flag.lh) { - damage = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; - wd.damage2 += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); - } - } -#ifdef RENEWAL - /** - * In RE Shield Bommerang takes weapon element only for damage calculation, - * - resist calculation is always against neutral - **/ - if (skill_num == CR_SHIELDBOOMERANG) - s_ele = s_ele_ = ELE_NEUTRAL; + wd.damage = battle_addmastery(sd,target,wd.damage,0); + if (flag.lh) + wd.damage2 = battle_addmastery(sd,target,wd.damage2,1); + + if (sc && sc->data[SC_MIRACLE]) i = 2; //Star anger + else + ARR_FIND(0, MAX_PC_FEELHATE, i, t_class == sd->hate_mob[i]); + if (i < MAX_PC_FEELHATE && (skill=pc_checkskill(sd,sg_info[i].anger_id))) + { + skillratio = sd->status.base_level + sstatus->dex + sstatus->luk; + if (i == 2) skillratio += sstatus->str; //Star Anger + if (skill<4) + skillratio /= 12-3*skill; + ATK_ADDRATE(skillratio); + } + if (skill_num == NJ_SYURIKEN && (skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0) + ATK_ADD(3*skill); + if (skill_num == NJ_KUNAI) + ATK_ADD(60); + } + } //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks + else if(wd.div_ < 0) //Since the attack missed... + wd.div_ *= -1; + + if(sd && (skill=pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) + ATK_ADD(skill*2); + + if(skill_num==TF_POISON) + ATK_ADD(15*skill_lv); + + if( !(nk&NK_NO_ELEFIX) && !n_ele ) + { //Elemental attribute fix + if( wd.damage > 0 ) + { + wd.damage=battle_attr_fix(src,target,wd.damage,s_ele,tstatus->def_ele, tstatus->ele_lv); + if( skill_num == MC_CARTREVOLUTION ) //Cart Revolution applies the element fix once more with neutral element + wd.damage = battle_attr_fix(src,target,wd.damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); + if( skill_num== GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage. + wd.damage += battle_attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); + } + if( flag.lh && wd.damage2 > 0 ) + wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); + if( sc && sc->data[SC_WATK_ELEMENT] ) + { // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex] + int damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; + wd.damage += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); + + if( flag.lh ) + { + damage = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; + wd.damage2 += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); + } + } + #ifdef RENEWAL + /** + * In RE Shield Bommerang takes weapon element only for damage calculation, + * - resist calculation is always against neutral + **/ + if ( skill_num == CR_SHIELDBOOMERANG ) + s_ele = s_ele_ = ELE_NEUTRAL; + #endif + } + + if(skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS) + return wd; //Enough, rest is not needed. + + if (sd) + { + if (skill_num != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus. + ATK_ADD2(wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star); + if (skill_num==MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex] + ATK_ADD(wd.div_*sd->spiritball_old*3); + } else { + ATK_ADD(wd.div_*sd->spiritball*3); + } + + //Card Fix, sd side + if( (wd.damage || wd.damage2) && !(nk&NK_NO_CARDFIX_ATK) ) + { + int cardfix = 1000, cardfix_ = 1000; + int t_race2 = status_get_race2(target); + if(sd->state.arrow_atk) + { + cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) + { + int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele]; + for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { + if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; + if(!(sd->right_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK && + sd->right_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK && + sd->right_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK)) + continue; + ele_fix += sd->right_weapon.addele2[i].rate; + } + cardfix=cardfix*(100+ele_fix)/100; + } + cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN])/100; + } + else + { // Melee attack + if( !battle_config.left_cardfix_to_right ) + { + cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) { + int ele_fix = sd->right_weapon.addele[tstatus->def_ele]; + for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { + if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; + if(!(sd->right_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK && + sd->right_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK && + sd->right_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK)) + continue; + ele_fix += sd->right_weapon.addele2[i].rate; + } + cardfix=cardfix*(100+ele_fix)/100; + } + cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN])/100; + + if( flag.lh ) + { + cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) { + int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele]; + for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) { + if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue; + if(!(sd->left_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK && + sd->left_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK && + sd->left_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK)) + continue; + ele_fix_lh += sd->left_weapon.addele2[i].rate; + } + cardfix=cardfix*(100+ele_fix_lh)/100; + } + cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100; + cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100; + cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix_=cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; + } + } + else + { + int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]; + for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { + if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; + if(!(sd->right_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK && + sd->right_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK && + sd->right_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK)) + continue; + ele_fix += sd->right_weapon.addele2[i].rate; + } + for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) { + if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue; + if(!(sd->left_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK && + sd->left_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK && + sd->left_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK)) + continue; + ele_fix += sd->left_weapon.addele2[i].rate; + } + + cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100; + cardfix=cardfix*(100+ele_fix)/100; + cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; + } + } + + for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ ) + { + if( sd->right_weapon.add_dmg[i].class_ == t_class ) + { + cardfix=cardfix*(100+sd->right_weapon.add_dmg[i].rate)/100; + break; + } + } + + if( flag.lh ) + { + for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ ) + { + if( sd->left_weapon.add_dmg[i].class_ == t_class ) + { + cardfix_=cardfix_*(100+sd->left_weapon.add_dmg[i].rate)/100; + break; + } + } + } + + if( wd.flag&BF_LONG ) + cardfix = cardfix * ( 100 + sd->bonus.long_attack_atk_rate ) / 100; +#ifdef RENEWAL_EDP + if( sc && sc->data[SC_EDP] ){ + cardfix = cardfix * (100 + sc->data[SC_EDP]->val1 * 60 ) / 100; + cardfix_ = cardfix_ * (100 + sc->data[SC_EDP]->val1 * 60 ) / 100; + } #endif - } + if( cardfix != 1000 || cardfix_ != 1000 ) + ATK_RATE2(cardfix/10, cardfix_/10); //What happens if you use right-to-left and there's no right weapon, only left? + } - if (skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS) - return wd; //Enough, rest is not needed. + if( skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN ) + { //Refine bonus applies after cards and elements. + short index= sd->equip_index[EQI_HAND_L]; + if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR ) + ATK_ADD(10*sd->status.inventory[index].refine); + } + } //if (sd) - if (sd) { - if (skill_num != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus. - ATK_ADD2(wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star); - if (skill_num==MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex] - ATK_ADD(wd.div_*sd->spiritball_old*3); - } else { - ATK_ADD(wd.div_*sd->spiritball*3); - } + //Card Fix, tsd sid + if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) + { + short s_race2,s_class; + short cardfix=1000; - //Card Fix, sd side - wd.damage = battle_calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag); - if( flag.lh ) - wd.damage2 = battle_calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag); + s_race2 = status_get_race2(src); + s_class = status_get_class(src); - if (skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN) { - //Refine bonus applies after cards and elements. - short index= sd->equip_index[EQI_HAND_L]; - if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR) - ATK_ADD(10*sd->status.inventory[index].refine); - } - } //if (sd) - - //Card Fix, tsd side - if(tsd) - wd.damage = battle_calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, flag.lh, wd.flag); - - if (flag.infdef) { - //Plants receive 1 damage when hit - short class_ = status_get_class(target); - if (flag.hit || wd.damage > 0) - wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage - if (flag.lh && (flag.hit || wd.damage2 > 0)) - wd.damage2 = wd.div_; - if (flag.hit && class_ == MOBID_EMPERIUM) { - if (wd.damage2 > 0) { - wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); - wd.damage2 = battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); - } else if (wd.damage > 0) { - wd.damage = battle_attr_fix(src,target,wd.damage,s_ele_,tstatus->def_ele, tstatus->ele_lv); - wd.damage = battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); - } - return wd; - } - if (!(battle_config.skill_min_damage&1)) - //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex] - return wd; - } + if( !(nk&NK_NO_ELEFIX) ) + { + int ele_fix = tsd->subele[s_ele]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele) continue; + if(!(tsd->subele2[i].flag&wd.flag&BF_WEAPONMASK && + tsd->subele2[i].flag&wd.flag&BF_RANGEMASK && + tsd->subele2[i].flag&wd.flag&BF_SKILLMASK)) + continue; + ele_fix += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix)/100; + if( flag.lh && s_ele_ != s_ele ) + { + int ele_fix_lh = tsd->subele[s_ele_]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele_) continue; + if(!(tsd->subele2[i].flag&wd.flag&BF_WEAPONMASK && + tsd->subele2[i].flag&wd.flag&BF_RANGEMASK && + tsd->subele2[i].flag&wd.flag&BF_SKILLMASK)) + continue; + ele_fix_lh += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix_lh)/100; + } + } + cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; + cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; + cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; + cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + + for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ) { + if( tsd->add_def[i].class_ == s_class ) { + cardfix=cardfix*(100-tsd->add_def[i].rate)/100; + break; + } + } - if (sd) { - if (!flag.rh && flag.lh) { //Move lh damage to the rh - wd.damage = wd.damage2; - wd.damage2 = 0; - flag.rh=1; - flag.lh=0; - } else if (flag.rh && flag.lh) { //Dual-wield - if (wd.damage) { - if ((skill = pc_checkskill(sd,AS_RIGHT))) - wd.damage = wd.damage * (50 + (skill * 10))/100; - else if ((skill = pc_checkskill(sd,KO_RIGHT))) - wd.damage = wd.damage * (70 + (skill * 10))/100; - if (wd.damage < 1) wd.damage = 1; - } - if (wd.damage2) { - if ((skill = pc_checkskill(sd,AS_LEFT))) - wd.damage2 = wd.damage2 * (30 + (skill * 10))/100; - else if ((skill = pc_checkskill(sd,KO_LEFT))) - wd.damage2 = wd.damage2 * (50 + (skill * 10))/100; - if (wd.damage2 < 1) wd.damage2 = 1; - } - } else if (sd->status.weapon == W_KATAR && !skill_num) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2) - skill = pc_checkskill(sd,TF_DOUBLE); - wd.damage2 = wd.damage * (1 + (skill * 2))/100; + if( wd.flag&BF_SHORT ) + cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; + else // BF_LONG (there's no other choice) + cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; - if (wd.damage && !wd.damage2) wd.damage2 = 1; - flag.lh = 1; - } - } + if( tsd->sc.data[SC_DEF_RATE] ) + cardfix = cardfix * ( 100 - tsd->sc.data[SC_DEF_RATE]->val1 ) / 100; - if (!flag.rh && wd.damage) - wd.damage=0; - - if (!flag.lh && wd.damage2) - wd.damage2=0; - - if (wd.damage + wd.damage2) { - //There is a total damage value - if (!wd.damage2) { - wd.damage = battle_calc_damage(src,target,&wd,wd.damage,skill_num,skill_lv); - if (map_flag_gvg2(target->m)) - wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); - else if (map[target->m].flag.battleground) - wd.damage=battle_calc_bg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); - } else if (!wd.damage) { - wd.damage2 = battle_calc_damage(src,target,&wd,wd.damage2,skill_num,skill_lv); - if (map_flag_gvg2(target->m)) - wd.damage2 = battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); - else if (map[target->m].flag.battleground) - wd.damage = battle_calc_bg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); - } else { - int d1 = wd.damage + wd.damage2,d2 = wd.damage2; - wd.damage = battle_calc_damage(src,target,&wd,d1,skill_num,skill_lv); - if (map_flag_gvg2(target->m)) - wd.damage = battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); - else if (map[target->m].flag.battleground) - wd.damage = battle_calc_bg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); - wd.damage2 = (d2*100/d1)*wd.damage/100; - if (wd.damage > 1 && wd.damage2 < 1) wd.damage2 = 1; - wd.damage-=wd.damage2; - } - } - //Reject Sword bugreport:4493 by Daegaladh - if (wd.damage && tsc && tsc->data[SC_REJECTSWORD] && - (src->type!=BL_PC || ( - ((TBL_PC *)src)->weapontype1 == W_DAGGER || - ((TBL_PC *)src)->weapontype1 == W_1HSWORD || - ((TBL_PC *)src)->status.weapon == W_2HSWORD - )) && - rnd()%100 < tsc->data[SC_REJECTSWORD]->val2 - ) { - wd.damage = wd.damage * 50 / 100; - status_fix_damage(target,src,wd.damage,clif_damage(target,src,gettick(),0,0,wd.damage,0,0,0)); - clif_skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_REJECTSWORD]->val1,1); - if (--(tsc->data[SC_REJECTSWORD]->val3) <= 0) - status_change_end(target, SC_REJECTSWORD, INVALID_TIMER); - } - if (skill_num == ASC_BREAKER) { //Breaker's int-based damage (a misc attack?) - struct Damage md = battle_calc_misc_attack(src, target, skill_num, skill_lv, wflag); - wd.damage += md.damage; - } - if (sc) { - //SG_FUSION hp penalty [Komurka] - if (sc->data[SC_FUSION]) { - int hp= sstatus->max_hp; - if (sd && tsd) { - hp = 8*hp/100; - if (100*sstatus->hp <= 20*sstatus->max_hp) - hp = sstatus->hp; - } else - hp = 2*hp/100; //2% hp loss per hit - status_zap(src, hp, 0); - } - /** - * affecting non-skills - **/ - if (!skill_num) { - /** - * RK Enchant Blade - **/ - if (sc->data[SC_ENCHANTBLADE] && sd && ((flag.rh && sd->weapontype1) || (flag.lh && sd->weapontype2))) { - //[( ( Skill Lv x 20 ) + 100 ) x ( casterBaseLevel / 150 )] + casterInt - ATK_ADD((sc->data[SC_ENCHANTBLADE]->val1*20+100) * status_get_lv(src) / 150 + status_get_int(src)); - } - } - status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); - } - if (skill_num == LG_RAYOFGENESIS) { - struct Damage md = battle_calc_magic_attack(src, target, skill_num, skill_lv, wflag); - wd.damage += md.damage; - } + if( cardfix != 1000 ) + ATK_RATE( cardfix / 10 ); + } + + if( flag.infdef ) + { //Plants receive 1 damage when hit + short class_ = status_get_class(target); + if( flag.hit || wd.damage > 0 ) + wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage + if( flag.lh && (flag.hit || wd.damage2 > 0) ) + wd.damage2 = wd.div_; + if( flag.hit && class_ == MOBID_EMPERIUM ) { + if(wd.damage2 > 0) { + wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); + wd.damage2 = battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); + } + else if(wd.damage > 0) { + wd.damage = battle_attr_fix(src,target,wd.damage,s_ele_,tstatus->def_ele, tstatus->ele_lv); + wd.damage = battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); + } + return wd; + } + if( !(battle_config.skill_min_damage&1) ) + //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex] + return wd; + } + + if (sd) { + if (!flag.rh && flag.lh) { //Move lh damage to the rh + wd.damage = wd.damage2; + wd.damage2 = 0; + flag.rh=1; + flag.lh=0; + } else if(flag.rh && flag.lh) { //Dual-wield + if (wd.damage) { + if( (skill = pc_checkskill(sd,AS_RIGHT)) ) + wd.damage = wd.damage * (50 + (skill * 10))/100; + else if( (skill = pc_checkskill(sd,KO_RIGHT)) ) + wd.damage = wd.damage * (70 + (skill * 10))/100; + if(wd.damage < 1) wd.damage = 1; + } + if (wd.damage2) { + if( (skill = pc_checkskill(sd,AS_LEFT)) ) + wd.damage2 = wd.damage2 * (30 + (skill * 10))/100; + else if( (skill = pc_checkskill(sd,KO_LEFT)) ) + wd.damage2 = wd.damage2 * (50 + (skill * 10))/100; + if(wd.damage2 < 1) wd.damage2 = 1; + } + } else if(sd->status.weapon == W_KATAR && !skill_num) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2) + skill = pc_checkskill(sd,TF_DOUBLE); + wd.damage2 = wd.damage * (1 + (skill * 2))/100; + + if(wd.damage && !wd.damage2) wd.damage2 = 1; + flag.lh = 1; + } + } + + if(!flag.rh && wd.damage) + wd.damage=0; + + if(!flag.lh && wd.damage2) + wd.damage2=0; + + if( wd.damage + wd.damage2 ) + { //There is a total damage value + if(!wd.damage2) + { + wd.damage = battle_calc_damage(src,target,&wd,wd.damage,skill_num,skill_lv); + if( map_flag_gvg2(target->m) ) + wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); + else if( map[target->m].flag.battleground ) + wd.damage=battle_calc_bg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); + } + else if(!wd.damage) + { + wd.damage2 = battle_calc_damage(src,target,&wd,wd.damage2,skill_num,skill_lv); + if( map_flag_gvg2(target->m) ) + wd.damage2 = battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); + else if( map[target->m].flag.battleground ) + wd.damage = battle_calc_bg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag); + } + else + { + int d1 = wd.damage + wd.damage2,d2 = wd.damage2; + wd.damage = battle_calc_damage(src,target,&wd,d1,skill_num,skill_lv); + if( map_flag_gvg2(target->m) ) + wd.damage = battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); + else if( map[target->m].flag.battleground ) + wd.damage = battle_calc_bg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag); + wd.damage2 = (d2*100/d1)*wd.damage/100; + if(wd.damage > 1 && wd.damage2 < 1) wd.damage2 = 1; + wd.damage-=wd.damage2; + } + } + //Reject Sword bugreport:4493 by Daegaladh + if(wd.damage && tsc && tsc->data[SC_REJECTSWORD] && + (src->type!=BL_PC || ( + ((TBL_PC *)src)->weapontype1 == W_DAGGER || + ((TBL_PC *)src)->weapontype1 == W_1HSWORD || + ((TBL_PC *)src)->status.weapon == W_2HSWORD + )) && + rnd()%100 < tsc->data[SC_REJECTSWORD]->val2 + ) { + wd.damage = wd.damage * 50 / 100; + status_fix_damage(target,src,wd.damage,clif_damage(target,src,gettick(),0,0,wd.damage,0,0,0)); + clif_skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_REJECTSWORD]->val1,1); + if( --(tsc->data[SC_REJECTSWORD]->val3) <= 0 ) + status_change_end(target, SC_REJECTSWORD, INVALID_TIMER); + } + if(skill_num == ASC_BREAKER) { //Breaker's int-based damage (a misc attack?) + struct Damage md = battle_calc_misc_attack(src, target, skill_num, skill_lv, wflag); + wd.damage += md.damage; + } + if( sc ) { + //SG_FUSION hp penalty [Komurka] + if (sc->data[SC_FUSION]) { + int hp= sstatus->max_hp; + if (sd && tsd) { + hp = 8*hp/100; + if (100*sstatus->hp <= 20*sstatus->max_hp) + hp = sstatus->hp; + } else + hp = 2*hp/100; //2% hp loss per hit + status_zap(src, hp, 0); + } + /** + * affecting non-skills + **/ + if( !skill_num ) { + /** + * RK Enchant Blade + **/ + if( sc->data[SC_ENCHANTBLADE] && sd && ( (flag.rh && sd->weapontype1) || (flag.lh && sd->weapontype2) ) ) { + //[( ( Skill Lv x 20 ) + 100 ) x ( casterBaseLevel / 150 )] + casterInt + ATK_ADD( ( sc->data[SC_ENCHANTBLADE]->val1*20+100 ) * status_get_lv(src) / 150 + status_get_int(src) ); + } + } + status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); + } + if( skill_num == LG_RAYOFGENESIS ) { + struct Damage md = battle_calc_magic_attack(src, target, skill_num, skill_lv, wflag); + wd.damage += md.damage; + } - return wd; + return wd; } /*========================================== * battle_calc_magic_attack [DracoRPG] *------------------------------------------*/ -struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag) { - int i, nk; - short s_ele = 0; - unsigned int skillratio = 100; //Skill dmg modifiers. - - TBL_PC *sd; -// TBL_PC *tsd; - struct Damage ad; - struct status_data *sstatus = status_get_status_data(src); - struct status_data *tstatus = status_get_status_data(target); - struct { - unsigned imdef : 1; - unsigned infdef : 1; - } flag; - - memset(&ad,0,sizeof(ad)); - memset(&flag,0,sizeof(flag)); - - if (src==NULL || target==NULL) { - nullpo_info(NLP_MARK); - return ad; - } - //Initial Values - ad.div_=skill_get_num(skill_num,skill_lv); - ad.amotion=skill_get_inf(skill_num) &INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills. - ad.dmotion=tstatus->dmotion; - ad.blewcount = skill_get_blewcount(skill_num,skill_lv); - ad.flag=BF_MAGIC|BF_SKILL; - ad.dmg_lv=ATK_DEF; - nk = skill_get_nk(skill_num); - flag.imdef = nk &NK_IGNORE_DEF?1:0; - - sd = BL_CAST(BL_PC, src); -// tsd = BL_CAST(BL_PC, target); - - if (skill_num == SO_PSYCHIC_WAVE) { - struct status_change *sc = status_get_sc(src); - if (sc && sc->count && (sc->data[SC_HEATER_OPTION] || sc->data[SC_COOLER_OPTION] || - sc->data[SC_BLAST_OPTION] || sc->data[SC_CURSED_SOIL_OPTION])) { - if (sc->data[SC_HEATER_OPTION]) s_ele = sc->data[SC_HEATER_OPTION]->val4; - else if (sc->data[SC_COOLER_OPTION]) s_ele = sc->data[SC_COOLER_OPTION]->val4; - else if (sc->data[SC_BLAST_OPTION]) s_ele = sc->data[SC_BLAST_OPTION]->val3; - else if (sc->data[SC_CURSED_SOIL_OPTION]) s_ele = sc->data[SC_CURSED_SOIL_OPTION]->val4; - } else { - //#HALP# I didn't get a clue on how to do this without unnecessary adding a overhead of status_change on every call while this is a per-skill case. - //, - so i duplicated this code. make yourself comfortable to fix if you have any better ideas. - //Initialize variables that will be used afterwards - s_ele = skill_get_ele(skill_num, skill_lv); - - if (s_ele == -1) // pl=-1 : the skill takes the weapon's element - s_ele = sstatus->rhw.ele; - else if (s_ele == -2) //Use status element - s_ele = status_get_attack_sc_element(src,status_get_sc(src)); - else if (s_ele == -3) //Use random element - s_ele = rnd()%ELE_MAX; - } - } else { - //Initialize variables that will be used afterwards - s_ele = skill_get_ele(skill_num, skill_lv); - - if (s_ele == -1) { // pl=-1 : the skill takes the weapon's element - s_ele = sstatus->rhw.ele; - if (sd) { //Summoning 10 talisman will endow your weapon - ARR_FIND(1, 6, i, sd->talisman[i] >= 10); - if (i < 5) s_ele = i; - } - } else if (s_ele == -2) //Use status element - s_ele = status_get_attack_sc_element(src,status_get_sc(src)); - else if (s_ele == -3) //Use random element - s_ele = rnd()%ELE_MAX; - } - //Set miscellaneous data that needs be filled - if (sd) { - sd->state.arrow_atk = 0; - ad.blewcount += battle_blewcount_bonus(sd, skill_num); - } +struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag) +{ + int i, nk; + short s_ele = 0; + unsigned int skillratio = 100; //Skill dmg modifiers. - //Skill Range Criteria - ad.flag |= battle_range_type(src, target, skill_num, skill_lv); - flag.infdef=(tstatus->mode&MD_PLANT?1:0); - if (target->type == BL_SKILL) { - TBL_SKILL *su = (TBL_SKILL *)target; - if (su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD)) - flag.infdef = 1; - } + struct map_session_data *sd, *tsd; + struct Damage ad; + struct status_data *sstatus = status_get_status_data(src); + struct status_data *tstatus = status_get_status_data(target); + struct { + unsigned imdef : 1; + unsigned infdef : 1; + } flag; + + memset(&ad,0,sizeof(ad)); + memset(&flag,0,sizeof(flag)); + + if(src==NULL || target==NULL) + { + nullpo_info(NLP_MARK); + return ad; + } + //Initial Values + ad.damage = 1; + ad.div_=skill_get_num(skill_num,skill_lv); + ad.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills. + ad.dmotion=tstatus->dmotion; + ad.blewcount = skill_get_blewcount(skill_num,skill_lv); + ad.flag=BF_MAGIC|BF_SKILL; + ad.dmg_lv=ATK_DEF; + nk = skill_get_nk(skill_num); + flag.imdef = nk&NK_IGNORE_DEF?1:0; - switch (skill_num) { - case MG_FIREWALL: - case NJ_KAENSIN: - ad.dmotion = 0; //No flinch animation. - if (tstatus->def_ele == ELE_FIRE || battle_check_undead(tstatus->race, tstatus->def_ele)) - ad.blewcount = 0; //No knockback - break; - case PR_SANCTUARY: - ad.dmotion = 0; //No flinch animation. - break; - } + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, target); - if (!flag.infdef) { //No need to do the math for plants + if( skill_num == SO_PSYCHIC_WAVE ) { + struct status_change *sc = status_get_sc(src); + if( sc && sc->count && ( sc->data[SC_HEATER_OPTION] || sc->data[SC_COOLER_OPTION] || + sc->data[SC_BLAST_OPTION] || sc->data[SC_CURSED_SOIL_OPTION] ) ) { + if( sc->data[SC_HEATER_OPTION] ) s_ele = sc->data[SC_HEATER_OPTION]->val4; + else if( sc->data[SC_COOLER_OPTION] ) s_ele = sc->data[SC_COOLER_OPTION]->val4; + else if( sc->data[SC_BLAST_OPTION] ) s_ele = sc->data[SC_BLAST_OPTION]->val3; + else if( sc->data[SC_CURSED_SOIL_OPTION] ) s_ele = sc->data[SC_CURSED_SOIL_OPTION]->val4; + } else { + //#HALP# I didn't get a clue on how to do this without unnecessary adding a overhead of status_change on every call while this is a per-skill case. + //, - so i duplicated this code. make yourself comfortable to fix if you have any better ideas. + //Initialize variables that will be used afterwards + s_ele = skill_get_ele(skill_num, skill_lv); + + if (s_ele == -1) // pl=-1 : the skill takes the weapon's element + s_ele = sstatus->rhw.ele; + else if (s_ele == -2) //Use status element + s_ele = status_get_attack_sc_element(src,status_get_sc(src)); + else if( s_ele == -3 ) //Use random element + s_ele = rnd()%ELE_MAX; + } + } else { + //Initialize variables that will be used afterwards + s_ele = skill_get_ele(skill_num, skill_lv); + + if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element + s_ele = sstatus->rhw.ele; + if( sd ){ //Summoning 10 talisman will endow your weapon + ARR_FIND(1, 6, i, sd->talisman[i] >= 10); + if( i < 5 ) s_ele = i; + } + }else if (s_ele == -2) //Use status element + s_ele = status_get_attack_sc_element(src,status_get_sc(src)); + else if( s_ele == -3 ) //Use random element + s_ele = rnd()%ELE_MAX; + } + //Set miscellaneous data that needs be filled + if(sd) { + sd->state.arrow_atk = 0; + ad.blewcount += battle_blewcount_bonus(sd, skill_num); + } + + //Skill Range Criteria + ad.flag |= battle_range_type(src, target, skill_num, skill_lv); + flag.infdef=(tstatus->mode&MD_PLANT?1:0); + if( target->type == BL_SKILL){ + TBL_SKILL *su = (TBL_SKILL*)target; + if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) + flag.infdef = 1; + } - //MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc + switch(skill_num) + { + case MG_FIREWALL: + case NJ_KAENSIN: + ad.dmotion = 0; //No flinch animation. + if ( tstatus->def_ele == ELE_FIRE || battle_check_undead(tstatus->race, tstatus->def_ele) ) + ad.blewcount = 0; //No knockback + break; + case PR_SANCTUARY: + ad.dmotion = 0; //No flinch animation. + break; + } + + if (!flag.infdef) //No need to do the math for plants + { + +//MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc #define MATK_RATE( a ) { ad.damage= ad.damage*(a)/100; } - //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage +//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage #define MATK_ADDRATE( a ) { ad.damage+= ad.damage*(a)/100; } - //Adds an absolute value to damage. 100 = +100 damage +//Adds an absolute value to damage. 100 = +100 damage #define MATK_ADD( a ) { ad.damage+= a; } - switch (skill_num) { - //Calc base damage according to skill - case AL_HEAL: - case PR_BENEDICTIO: - case PR_SANCTUARY: - /** - * Arch Bishop - **/ - case AB_HIGHNESSHEAL: - ad.damage = skill_calc_heal(src, target, skill_num, skill_lv, false); - break; - case PR_ASPERSIO: - ad.damage = 40; - break; - case ALL_RESURRECTION: - case PR_TURNUNDEAD: - //Undead check is on skill_castend_damageid code. -#ifdef RENEWAL - i = 10*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src) - + 300 - 300*tstatus->hp/tstatus->max_hp; -#else - i = 20*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src) - + 200 - 200*tstatus->hp/tstatus->max_hp; -#endif - if (i > 700) i = 700; - if (rnd()%1000 < i && !(tstatus->mode&MD_BOSS)) - ad.damage = tstatus->hp; - else { -#ifdef RENEWAL - if (sstatus->matk_max > sstatus->matk_min) { - MATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); - } else { - MATK_ADD(sstatus->matk_min); - } - MATK_RATE(skill_lv); -#else - ad.damage = status_get_lv(src) + sstatus->int_ + skill_lv * 10; -#endif - } - break; - case PF_SOULBURN: - ad.damage = tstatus->sp * 2; - break; - /** - * Arch Bishop - **/ - case AB_RENOVATIO: - //Damage calculation from iRO wiki. [Jobbie] - ad.damage = (int)((15 * status_get_lv(src)) + (1.5 * sstatus->int_)); - break; - default: { - if (sstatus->matk_max > sstatus->matk_min) { - MATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); - } else { - MATK_ADD(sstatus->matk_min); - } - - if (nk&NK_SPLASHSPLIT) { // Divide MATK in case of multiple targets skill - if (mflag>0) - ad.damage/= mflag; - else - ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); - } - - switch (skill_num) { - case MG_NAPALMBEAT: - skillratio += skill_lv*10-30; - break; - case MG_FIREBALL: -#ifdef RENEWAL - skillratio += 20*skill_lv; -#else - skillratio += skill_lv*10-30; -#endif - break; - case MG_SOULSTRIKE: - if (battle_check_undead(tstatus->race,tstatus->def_ele)) - skillratio += 5*skill_lv; - break; - case MG_FIREWALL: { - struct status_change *sc = status_get_sc(src); - skillratio -= 50; - if (sc && sc->data[SC_PYROTECHNIC_OPTION]) - skillratio += skillratio * sc->data[SC_PYROTECHNIC_OPTION]->val3 / 100; - } - break; - case MG_COLDBOLT: { - struct status_change *sc = status_get_sc(src); - if (sc && sc->count) { - if (sc->data[SC_SPELLFIST] && mflag&BF_SHORT) { - skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech] - ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax] - ad.flag = BF_WEAPON|BF_SHORT; - ad.type = 0; - } - if (sc->data[SC_AQUAPLAY_OPTION]) - skillratio += skillratio * sc->data[SC_AQUAPLAY_OPTION]->val3 / 100; - } - } - break; - case MG_FIREBOLT: { - struct status_change *sc = status_get_sc(src); - if (sc && sc->count) { - if (sc->data[SC_SPELLFIST] && mflag&BF_SHORT) { - skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100; - ad.div_ = 1; - ad.flag = BF_WEAPON|BF_SHORT; - ad.type = 0; - } - if (sc->data[SC_PYROTECHNIC_OPTION]) - skillratio += skillratio * sc->data[SC_PYROTECHNIC_OPTION]->val3 / 100; - } - } - break; - case MG_LIGHTNINGBOLT: { - struct status_change *sc = status_get_sc(src); - if (sc && sc->count) { - if (sc->data[SC_SPELLFIST] && mflag&BF_SHORT) { - skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100; - ad.div_ = 1; - ad.flag = BF_WEAPON|BF_SHORT; - ad.type = 0; - } - if (sc->data[SC_GUST_OPTION]) - skillratio += skillratio * sc->data[SC_GUST_OPTION]->val2 / 100; - } - } - break; - case MG_THUNDERSTORM: { - struct status_change *sc = status_get_sc(src); - /** - * in Renewal Thunder Storm boost is 100% (in pre-re, 80%) - **/ -#ifndef RENEWAL - skillratio -= 20; -#endif - if (sc && sc->data[SC_GUST_OPTION]) - skillratio += skillratio * sc->data[SC_GUST_OPTION]->val2 / 100; - } - break; - case MG_FROSTDIVER: - skillratio += 10*skill_lv; - break; - case AL_HOLYLIGHT: - skillratio += 25; - if (sd && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_PRIEST) - skillratio *= 5; //Does 5x damage include bonuses from other skills? - break; - case AL_RUWACH: - skillratio += 45; - break; - case WZ_FROSTNOVA: - skillratio += (100+skill_lv*10)*2/3-100; - break; - case WZ_FIREPILLAR: - if (skill_lv > 10) - skillratio += 100; - else - skillratio -= 80; - break; - case WZ_SIGHTRASHER: - skillratio += 20*skill_lv; - break; - case WZ_WATERBALL: - skillratio += 30*skill_lv; - break; - case WZ_STORMGUST: - skillratio += 40*skill_lv; - break; - case HW_NAPALMVULCAN: - skillratio += 10*skill_lv-30; - break; - case SL_STIN: - skillratio += (tstatus->size!=SZ_SMALL?-99:10*skill_lv); //target size must be small (0) for full damage. - break; - case SL_STUN: - skillratio += (tstatus->size!=SZ_BIG?5*skill_lv:-99); //Full damage is dealt on small/medium targets - break; - case SL_SMA: - skillratio += -60 + status_get_lv(src); //Base damage is 40% + lv% - break; - case NJ_KOUENKA: - skillratio -= 10; - break; - case NJ_KAENSIN: - skillratio -= 50; - break; - case NJ_BAKUENRYU: - skillratio += 50*(skill_lv-1); - break; - case NJ_HYOUSYOURAKU: - skillratio += 50*skill_lv; - break; - case NJ_RAIGEKISAI: - skillratio += 60 + 40*skill_lv; - break; - case NJ_KAMAITACHI: - case NPC_ENERGYDRAIN: - skillratio += 100*skill_lv; - break; - case NPC_EARTHQUAKE: - skillratio += 100 +100*skill_lv +100*(skill_lv/2); - break; -#ifdef RENEWAL - case WZ_HEAVENDRIVE: - case WZ_METEOR: - skillratio += 25; - break; - case WZ_VERMILION: { - int interval = 0, per = interval , ratio = per; - while ((per++) < skill_lv) { - ratio += interval; - if (per%3==0) interval += 20; - } - if (skill_lv > 9) - ratio -= 10; - skillratio += ratio; - } - break; - case NJ_HUUJIN: - skillratio += 50; - break; -#else - case WZ_VERMILION: - skillratio += 20*skill_lv-20; - break; -#endif - /** - * Arch Bishop - **/ - case AB_JUDEX: - skillratio += 180 + 20 * skill_lv; - if (skill_lv > 4) skillratio += 20; - RE_LVL_DMOD(100); - break; - case AB_ADORAMUS: - skillratio += 400 + 100 * skill_lv; - RE_LVL_DMOD(100); - break; - case AB_DUPLELIGHT_MAGIC: - skillratio += 100 + 20 * skill_lv; - break; - /** - * Warlock - **/ - case WL_SOULEXPANSION: - skillratio += 300 + 100 * skill_lv + sstatus->int_; - RE_LVL_DMOD(100); - break; - case WL_FROSTMISTY: - skillratio += 100 + 100 * skill_lv; - RE_LVL_DMOD(100); - break; - case WL_JACKFROST: { - struct status_change *tsc = status_get_sc(target); - if (tsc && tsc->data[SC_FREEZING]) { - skillratio += 900 + 300 * skill_lv; - RE_LVL_DMOD(100); - } else { - skillratio += 400 + 100 * skill_lv; - RE_LVL_DMOD(150); - } - } - break; - case WL_DRAINLIFE: - skillratio = 200 * skill_lv + sstatus->int_; - RE_LVL_DMOD(100); - break; - case WL_CRIMSONROCK: - skillratio += 1200 + 300 * skill_lv; - RE_LVL_DMOD(100); - break; - case WL_HELLINFERNO: - skillratio = 300 * skill_lv; - RE_LVL_DMOD(100); - // Shadow: MATK [{( Skill Level x 300 ) x ( Caster Base Level / 100 ) x 4/5 }] % - // Fire : MATK [{( Skill Level x 300 ) x ( Caster Base Level / 100 ) /5 }] % - if (mflag&ELE_DARK) { - skillratio *= 4; - s_ele = ELE_DARK; - } - skillratio /= 5; - break; - case WL_COMET: { - struct status_change *sc = status_get_sc(src); - if (sc) - i = distance_xy(target->x, target->y, sc->comet_x, sc->comet_y); - else - i = 8; - if (i < 2) skillratio = 2500 + 500 * skill_lv; - else if (i < 4) skillratio = 1600 + 400 * skill_lv; - else if (i < 6) skillratio = 1200 + 300 * skill_lv; - else - skillratio = 800 + 200 * skill_lv; - } - break; - case WL_CHAINLIGHTNING_ATK: - skillratio += 100 + 300 * skill_lv; - RE_LVL_DMOD(100); - break; - case WL_EARTHSTRAIN: - skillratio += 1900 + 100 * skill_lv; - RE_LVL_DMOD(100); - break; - case WL_TETRAVORTEX_FIRE: - case WL_TETRAVORTEX_WATER: - case WL_TETRAVORTEX_WIND: - case WL_TETRAVORTEX_GROUND: - skillratio += 400 + 500 * skill_lv; - break; - case WL_SUMMON_ATK_FIRE: - case WL_SUMMON_ATK_WATER: - case WL_SUMMON_ATK_WIND: - case WL_SUMMON_ATK_GROUND: - skillratio = skill_lv * (status_get_lv(src) + (sd ? sd->status.job_level : 50)); // This is close to official, but lacking a little info to finalize. [Rytech] - RE_LVL_DMOD(100); - break; - case LG_RAYOFGENESIS: - skillratio = (skillratio + 200) * skill_lv; - RE_LVL_DMOD(100); - break; - case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield MDEF x 100) + (Casters INT x 2)] % - if (sd) { - skillratio = status_get_lv(src) * 4 + sd->bonus.shieldmdef * 100 + status_get_int(src) * 2; - } else - skillratio += 1900; //2000% - break; - case WM_METALICSOUND: - skillratio += 120 * skill_lv + 60 * (sd? pc_checkskill(sd, WM_LESSON) : 10) - 100; - break; - case WM_SEVERE_RAINSTORM: - skillratio += 50 * skill_lv; - break; - case WM_REVERBERATION_MAGIC: - // MATK [{(Skill Level x 100) + 100} x Casters Base Level / 100] % - skillratio += 100 * (sd ? pc_checkskill(sd, WM_REVERBERATION) : 1); - RE_LVL_DMOD(100); - break; - case SO_FIREWALK: { - struct status_change *sc = status_get_sc(src); - skillratio = 300; - RE_LVL_DMOD(100); - if (sc && sc->data[SC_HEATER_OPTION]) - skillratio += skillratio * sc->data[SC_HEATER_OPTION]->val3 / 100; - } - break; - case SO_ELECTRICWALK: { - struct status_change *sc = status_get_sc(src); - skillratio = 300; - RE_LVL_DMOD(100); - if (sc && sc->data[SC_BLAST_OPTION]) - skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; - } - break; - case SO_EARTHGRAVE: { - struct status_change *sc = status_get_sc(src); - skillratio = (200 * (sd ? pc_checkskill(sd, SA_SEISMICWEAPON) : 10) + sstatus->int_ * skill_lv); - RE_LVL_DMOD(100); - if (sc && sc->data[SC_CURSED_SOIL_OPTION]) - skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100; - } - break; - case SO_DIAMONDDUST: { - struct status_change *sc = status_get_sc(src); - skillratio = (200 * (sd ? pc_checkskill(sd, SA_FROSTWEAPON) : 10) + sstatus->int_ * skill_lv); - RE_LVL_DMOD(100); - if (sc && sc->data[SC_COOLER_OPTION]) - skillratio += skillratio * sc->data[SC_COOLER_OPTION]->val3 / 100; - } - break; - case SO_POISON_BUSTER: { - struct status_change *sc = status_get_sc(src); - skillratio += 1100 + 300 * skill_lv; - if (sc && sc->data[SC_CURSED_SOIL_OPTION]) - skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100; - } - break; - case SO_PSYCHIC_WAVE: { - struct status_change *sc = status_get_sc(src); - skillratio += -100 + skill_lv * 70 + (sstatus->int_ * 3); - RE_LVL_DMOD(100); - if (sc) { - if (sc->data[SC_HEATER_OPTION]) - skillratio += skillratio * sc->data[SC_HEATER_OPTION]->val3 / 100; - else if (sc->data[SC_COOLER_OPTION]) - skillratio += skillratio * sc->data[SC_COOLER_OPTION]->val3 / 100; - else if (sc->data[SC_BLAST_OPTION]) - skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; - else if (sc->data[SC_CURSED_SOIL_OPTION]) - skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val3 / 100; - } - } - break; - case SO_VARETYR_SPEAR: { - struct status_change *sc = status_get_sc(src); - skillratio += -100 + (100 * (sd ? pc_checkskill(sd, SA_LIGHTNINGLOADER) : 10) + sstatus->int_ * skill_lv); - RE_LVL_DMOD(100); - if (sc && sc->data[SC_BLAST_OPTION]) - skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; - } - break; - case SO_CLOUD_KILL: { - struct status_change *sc = status_get_sc(src); - skillratio += -100 + skill_lv * 40; - RE_LVL_DMOD(100); - if (sc && sc->data[SC_CURSED_SOIL_OPTION]) - skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100; - } - break; - case GN_DEMONIC_FIRE: - if (skill_lv > 20) { - // Fire expansion Lv.2 - skillratio += 110 + 20 * (skill_lv - 20) + status_get_int(src) * 3; // Need official INT bonus. [LimitLine] - } else if (skill_lv > 10) { - // Fire expansion Lv.1 - skillratio += 110 + 20 * (skill_lv - 10) / 2; - } else - skillratio += 110 + 20 * skill_lv; - break; - // Magical Elemental Spirits Attack Skills - case EL_FIRE_MANTLE: - case EL_WATER_SCREW: - skillratio += 900; - break; - case EL_FIRE_ARROW: - case EL_ROCK_CRUSHER_ATK: - skillratio += 200; - break; - case EL_FIRE_BOMB: - case EL_ICE_NEEDLE: - case EL_HURRICANE_ATK: - skillratio += 400; - break; - case EL_FIRE_WAVE: - case EL_TYPOON_MIS_ATK: - skillratio += 1100; - break; - case MH_ERASER_CUTTER: - if (skill_lv%2) skillratio += 400; //600:800:1000 - else skillratio += 700; //1000:1200 - skillratio += 100 * skill_lv; - break; - case MH_XENO_SLASHER: - if (skill_lv%2) skillratio += 350 + 50 * skill_lv; //500:600:700 - else skillratio += 400 + 100 * skill_lv; //700:900 - break; - case MH_HEILIGE_STANGE: - skillratio += 400 + 250 * skill_lv; - break; - case MH_POISON_MIST: - skillratio += 100 * skill_lv; - break; - } - - MATK_RATE(skillratio); - - //Constant/misc additions from skills - if (skill_num == WZ_FIREPILLAR) - MATK_ADD(50); - } - } -#ifdef RENEWAL - ad.damage = battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); -#endif - if (sd) { - //Damage bonuses - if ((i = pc_skillatk_bonus(sd, skill_num))) - ad.damage += ad.damage*i/100; - - //Ignore Defense? - if (!flag.imdef && ( - sd->bonus.ignore_mdef_ele & (1 << tstatus->def_ele) || - sd->bonus.ignore_mdef_race & (1 << tstatus->race) || - sd->bonus.ignore_mdef_race & (is_boss(target) ? 1 << RC_BOSS : 1 << RC_NONBOSS) - )) - flag.imdef = 1; - } + switch (skill_num) + { //Calc base damage according to skill + case AL_HEAL: + case PR_BENEDICTIO: + case PR_SANCTUARY: + /** + * Arch Bishop + **/ + case AB_HIGHNESSHEAL: + ad.damage = skill_calc_heal(src, target, skill_num, skill_lv, false); + break; + case PR_ASPERSIO: + ad.damage = 40; + break; + case ALL_RESURRECTION: + case PR_TURNUNDEAD: + //Undead check is on skill_castend_damageid code. + #ifdef RENEWAL + i = 10*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src) + + 300 - 300*tstatus->hp/tstatus->max_hp; + #else + i = 20*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src) + + 200 - 200*tstatus->hp/tstatus->max_hp; + #endif + if(i > 700) i = 700; + if(rnd()%1000 < i && !(tstatus->mode&MD_BOSS)) + ad.damage = tstatus->hp; + else { + #ifdef RENEWAL + ad.damage = skill_lv * (sstatus->matk_min + sstatus->matk_max); + #else + ad.damage = status_get_lv(src) + sstatus->int_ + skill_lv * 10; + #endif + } + break; + case PF_SOULBURN: + ad.damage = tstatus->sp * 2; + break; + /** + * Arch Bishop + **/ + case AB_RENOVATIO: + //Damage calculation from iRO wiki. [Jobbie] + ad.damage = (int)((15 * status_get_lv(src)) + (1.5 * sstatus->int_)); + break; + default: + { + #ifdef RENEWAL //Renewal MATK Appliance according to doddler (?title=Renewal_Changes#Upgrade_MATK) + /** + * min: (weaponMATK+upgradeMATK) * 2 + 1.5 * statusMATK + * max: [weaponMATK+upgradeMATK+(wMatk*wLvl)/10] * 2 + 1.5 * statusMATK + * yes this formula MATCHES their site: matk_max already holds weaponmatk+upgradematk, and + * -> statusMATK holds the %Matk modifier stuff from earlier and lastly: + * -> the mdef part is not applied at this point, but later. + **/ //1:bugreport:5101 //1:bugreport:5101 + MATK_ADD((1+sstatus->matk_max) * 2 + 15/10 * sstatus->matk_min + rnd()% ( sstatus->matk_max + (1 + (sstatus->matk_max*sstatus->wlv) / 10 * 2 + 10/15 * sstatus->matk_min ) )); + #else //Ancient MATK Appliance + if (sstatus->matk_max > sstatus->matk_min) { + MATK_ADD(sstatus->matk_min+rnd()%(1+sstatus->matk_max-sstatus->matk_min)); + } else { + MATK_ADD(sstatus->matk_min); + } + #endif + if(nk&NK_SPLASHSPLIT){ // Divide MATK in case of multiple targets skill + if(mflag>0) + ad.damage/= mflag; + else + ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); + } - if (!flag.imdef) { - defType mdef = tstatus->mdef; - int mdef2= tstatus->mdef2; - if (sd) { - i = sd->ignore_mdef[is_boss(target)?RC_BOSS:RC_NONBOSS]; - i+= sd->ignore_mdef[tstatus->race]; - if (i) { - if (i > 100) i = 100; - mdef -= mdef * i/100; - //mdef2-= mdef2* i/100; - } - } -#ifdef RENEWAL - /** - * RE MDEF Reduction (from doddler:?title=Renewal_Changes#MDEF) - * Damage from magic = Magic Attack * 111.5/(111.5+eMDEF) - * Damage = Magic Attack * 111.5/(111.5+eMDEF) - sMDEF - **/ - if (mdef < -111) mdef = -111; // value smaller -111 brings back the damage to origin up to -223. - ad.damage = ad.damage * 1115 / (1115 + mdef * 10) - mdef2; -#else - if (battle_config.magic_defense_type) - ad.damage = ad.damage - mdef*battle_config.magic_defense_type - mdef2; - else - ad.damage = ad.damage * (100-mdef)/100 - mdef2; -#endif - } + switch(skill_num){ + case MG_NAPALMBEAT: + skillratio += skill_lv*10-30; + break; + case MG_FIREBALL: + #ifdef RENEWAL + skillratio += 20*skill_lv; + #else + skillratio += skill_lv*10-30; + #endif + break; + case MG_SOULSTRIKE: + if (battle_check_undead(tstatus->race,tstatus->def_ele)) + skillratio += 5*skill_lv; + break; + case MG_FIREWALL: { + struct status_change *sc = status_get_sc(src); + skillratio -= 50; + if( sc && sc->data[SC_PYROTECHNIC_OPTION] ) + skillratio += skillratio * sc->data[SC_PYROTECHNIC_OPTION]->val3 / 100; + } + break; + case MG_COLDBOLT: { + struct status_change *sc = status_get_sc(src); + if ( sc && sc->count ) { + if ( sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) { + skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech] + ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax] + ad.flag = BF_WEAPON|BF_SHORT; + ad.type = 0; + } + if( sc->data[SC_AQUAPLAY_OPTION] ) + skillratio += skillratio * sc->data[SC_AQUAPLAY_OPTION]->val3 / 100; + } + } + break; + case MG_FIREBOLT: { + struct status_change *sc = status_get_sc(src); + if ( sc && sc->count ) { + if ( sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) { + skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100; + ad.div_ = 1; + ad.flag = BF_WEAPON|BF_SHORT; + ad.type = 0; + } + if( sc->data[SC_PYROTECHNIC_OPTION] ) + skillratio += skillratio * sc->data[SC_PYROTECHNIC_OPTION]->val3 / 100; + } + } + break; + case MG_LIGHTNINGBOLT: { + struct status_change *sc = status_get_sc(src); + if ( sc && sc->count ) { + if ( sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) { + skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100; + ad.div_ = 1; + ad.flag = BF_WEAPON|BF_SHORT; + ad.type = 0; + } + if( sc->data[SC_GUST_OPTION] ) + skillratio += skillratio * sc->data[SC_GUST_OPTION]->val2 / 100; + } + } + break; + case MG_THUNDERSTORM: { + struct status_change *sc = status_get_sc(src); + /** + * in Renewal Thunder Storm boost is 100% (in pre-re, 80%) + **/ + #ifndef RENEWAL + skillratio -= 20; + #endif + if( sc && sc->data[SC_GUST_OPTION] ) + skillratio += skillratio * sc->data[SC_GUST_OPTION]->val2 / 100; + } + break; + case MG_FROSTDIVER: + skillratio += 10*skill_lv; + break; + case AL_HOLYLIGHT: + skillratio += 25; + if (sd && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_PRIEST) + skillratio *= 5; //Does 5x damage include bonuses from other skills? + break; + case AL_RUWACH: + skillratio += 45; + break; + case WZ_FROSTNOVA: + skillratio += (100+skill_lv*10)*2/3-100; + break; + case WZ_FIREPILLAR: + if (skill_lv > 10) + skillratio += 100; + else + skillratio -= 80; + break; + case WZ_SIGHTRASHER: + skillratio += 20*skill_lv; + break; + case WZ_WATERBALL: + skillratio += 30*skill_lv; + break; + case WZ_STORMGUST: + skillratio += 40*skill_lv; + break; + case HW_NAPALMVULCAN: + skillratio += 10*skill_lv-30; + break; + case SL_STIN: + skillratio += (tstatus->size!=SZ_SMALL?-99:10*skill_lv); //target size must be small (0) for full damage. + break; + case SL_STUN: + skillratio += (tstatus->size!=SZ_BIG?5*skill_lv:-99); //Full damage is dealt on small/medium targets + break; + case SL_SMA: + skillratio += -60 + status_get_lv(src); //Base damage is 40% + lv% + break; + case NJ_KOUENKA: + skillratio -= 10; + break; + case NJ_KAENSIN: + skillratio -= 50; + break; + case NJ_BAKUENRYU: + skillratio += 50*(skill_lv-1); + break; + case NJ_HYOUSYOURAKU: + skillratio += 50*skill_lv; + break; + case NJ_RAIGEKISAI: + skillratio += 60 + 40*skill_lv; + break; + case NJ_KAMAITACHI: + case NPC_ENERGYDRAIN: + skillratio += 100*skill_lv; + break; + case NPC_EARTHQUAKE: + skillratio += 100 +100*skill_lv +100*(skill_lv/2); + break; + #ifdef RENEWAL + case WZ_HEAVENDRIVE: + case WZ_METEOR: + skillratio += 25; + break; + case WZ_VERMILION: + { + int interval = 0, per = interval , ratio = per; + while( (per++) < skill_lv ){ + ratio += interval; + if(per%3==0) interval += 20; + } + if( skill_lv > 9 ) + ratio -= 10; + skillratio += ratio; + } + break; + case NJ_HUUJIN: + skillratio += 50; + break; + #else + case WZ_VERMILION: + skillratio += 20*skill_lv-20; + break; + #endif + /** + * Arch Bishop + **/ + case AB_JUDEX: + skillratio += 180 + 20 * skill_lv; + if (skill_lv > 4) skillratio += 20; + RE_LVL_DMOD(100); + break; + case AB_ADORAMUS: + skillratio += 400 + 100 * skill_lv; + RE_LVL_DMOD(100); + break; + case AB_DUPLELIGHT_MAGIC: + skillratio += 100 + 20 * skill_lv; + break; + /** + * Warlock + **/ + case WL_SOULEXPANSION: + skillratio += 300 + 100 * skill_lv + sstatus->int_; + RE_LVL_DMOD(100); + break; + case WL_FROSTMISTY: + skillratio += 100 + 100 * skill_lv; + RE_LVL_DMOD(100); + break; + case WL_JACKFROST: { + struct status_change *tsc = status_get_sc(target); + if( tsc && tsc->data[SC_FREEZING] ){ + skillratio += 900 + 300 * skill_lv; + RE_LVL_DMOD(100); + }else{ + skillratio += 400 + 100 * skill_lv; + RE_LVL_DMOD(150); + } + } + break; + case WL_DRAINLIFE: + skillratio = 200 * skill_lv + sstatus->int_; + RE_LVL_DMOD(100); + break; + case WL_CRIMSONROCK: + skillratio += 1200 + 300 * skill_lv; + RE_LVL_DMOD(100); + break; + case WL_HELLINFERNO: + skillratio = 300 * skill_lv; + RE_LVL_DMOD(100); + // Shadow: MATK [{( Skill Level x 300 ) x ( Caster Base Level / 100 ) x 4/5 }] % + // Fire : MATK [{( Skill Level x 300 ) x ( Caster Base Level / 100 ) /5 }] % + if( mflag&ELE_DARK ){ skillratio *= 4; s_ele = ELE_DARK; } + skillratio /= 5; + break; + case WL_COMET: { + struct status_change * sc = status_get_sc(src); + if( sc ) + i = distance_xy(target->x, target->y, sc->comet_x, sc->comet_y); + else + i = 8; + if( i < 2 ) skillratio = 2500 + 500 * skill_lv; + else + if( i < 4 ) skillratio = 1600 + 400 * skill_lv; + else + if( i < 6 ) skillratio = 1200 + 300 * skill_lv; + else + skillratio = 800 + 200 * skill_lv; + } + break; + case WL_CHAINLIGHTNING_ATK: + skillratio += 100 + 300 * skill_lv; + RE_LVL_DMOD(100); + break; + case WL_EARTHSTRAIN: + skillratio += 1900 + 100 * skill_lv; + RE_LVL_DMOD(100); + break; + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + skillratio += 400 + 500 * skill_lv; + break; + case WL_SUMMON_ATK_FIRE: + case WL_SUMMON_ATK_WATER: + case WL_SUMMON_ATK_WIND: + case WL_SUMMON_ATK_GROUND: + skillratio = skill_lv * (status_get_lv(src) + ( sd ? sd->status.job_level : 50 ));// This is close to official, but lacking a little info to finalize. [Rytech] + RE_LVL_DMOD(100); + break; + case LG_RAYOFGENESIS: + skillratio = (skillratio + 200) * skill_lv; + RE_LVL_DMOD(100); + break; + case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield MDEF x 100) + (Casters INT x 2)] % + if( sd ) { + skillratio = status_get_lv(src) * 4 + sd->bonus.shieldmdef * 100 + status_get_int(src) * 2; + } else + skillratio += 1900; //2000% + break; + case WM_METALICSOUND: + skillratio += 120 * skill_lv + 60 * ( sd? pc_checkskill(sd, WM_LESSON) : 10 ) - 100; + break; + case WM_SEVERE_RAINSTORM: + skillratio += 50 * skill_lv; + break; + case WM_REVERBERATION_MAGIC: + // MATK [{(Skill Level x 100) + 100} x Casters Base Level / 100] % + skillratio += 100 * (sd ? pc_checkskill(sd, WM_REVERBERATION) : 1); + RE_LVL_DMOD(100); + break; + case SO_FIREWALK: { + struct status_change * sc = status_get_sc(src); + skillratio = 300; + RE_LVL_DMOD(100); + if( sc && sc->data[SC_HEATER_OPTION] ) + skillratio += skillratio * sc->data[SC_HEATER_OPTION]->val3 / 100; + } + break; + case SO_ELECTRICWALK: { + struct status_change * sc = status_get_sc(src); + skillratio = 300; + RE_LVL_DMOD(100); + if( sc && sc->data[SC_BLAST_OPTION] ) + skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; + } + break; + case SO_EARTHGRAVE: { + struct status_change * sc = status_get_sc(src); + skillratio = ( 200 * ( sd ? pc_checkskill(sd, SA_SEISMICWEAPON) : 10 ) + sstatus->int_ * skill_lv ); + RE_LVL_DMOD(100); + if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) + skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100; + } + break; + case SO_DIAMONDDUST: { + struct status_change * sc = status_get_sc(src); + skillratio = ( 200 * ( sd ? pc_checkskill(sd, SA_FROSTWEAPON) : 10 ) + sstatus->int_ * skill_lv ); + RE_LVL_DMOD(100); + if( sc && sc->data[SC_COOLER_OPTION] ) + skillratio += skillratio * sc->data[SC_COOLER_OPTION]->val3 / 100; + } + break; + case SO_POISON_BUSTER: { + struct status_change * sc = status_get_sc(src); + skillratio += 1100 + 300 * skill_lv; + if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) + skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100; + } + break; + case SO_PSYCHIC_WAVE: { + struct status_change * sc = status_get_sc(src); + skillratio += -100 + skill_lv * 70 + (sstatus->int_ * 3); + RE_LVL_DMOD(100); + if( sc ){ + if( sc->data[SC_HEATER_OPTION] ) + skillratio += skillratio * sc->data[SC_HEATER_OPTION]->val3 / 100; + else if(sc->data[SC_COOLER_OPTION] ) + skillratio += skillratio * sc->data[SC_COOLER_OPTION]->val3 / 100; + else if(sc->data[SC_BLAST_OPTION] ) + skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; + else if(sc->data[SC_CURSED_SOIL_OPTION] ) + skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val3 / 100; + } + } + break; + case SO_VARETYR_SPEAR: { + struct status_change * sc = status_get_sc(src); + skillratio += -100 + ( 100 * ( sd ? pc_checkskill(sd, SA_LIGHTNINGLOADER) : 10 ) + sstatus->int_ * skill_lv ); + RE_LVL_DMOD(100); + if( sc && sc->data[SC_BLAST_OPTION] ) + skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; + } + break; + case SO_CLOUD_KILL: { + struct status_change * sc = status_get_sc(src); + skillratio += -100 + skill_lv * 40; + RE_LVL_DMOD(100); + if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) + skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100; + } + break; + case GN_DEMONIC_FIRE: + if( skill_lv > 20) + { // Fire expansion Lv.2 + skillratio += 110 + 20 * (skill_lv - 20) + status_get_int(src) * 3; // Need official INT bonus. [LimitLine] + } + else if( skill_lv > 10 ) + { // Fire expansion Lv.1 + skillratio += 110 + 20 * (skill_lv - 10) / 2; + } + else + skillratio += 110 + 20 * skill_lv; + break; + // Magical Elemental Spirits Attack Skills + case EL_FIRE_MANTLE: + case EL_WATER_SCREW: + skillratio += 900; + break; + case EL_FIRE_ARROW: + case EL_ROCK_CRUSHER_ATK: + skillratio += 200; + break; + case EL_FIRE_BOMB: + case EL_ICE_NEEDLE: + case EL_HURRICANE_ATK: + skillratio += 400; + break; + case EL_FIRE_WAVE: + case EL_TYPOON_MIS_ATK: + skillratio += 1100; + break; + case MH_ERASER_CUTTER: + if(skill_lv%2) skillratio += 400; //600:800:1000 + else skillratio += 700; //1000:1200 + skillratio += 100 * skill_lv; + break; + case MH_XENO_SLASHER: + if(skill_lv%2) skillratio += 350 + 50 * skill_lv; //500:600:700 + else skillratio += 400 + 100 * skill_lv; //700:900 + break; + case MH_HEILIGE_STANGE: + skillratio += 400 + 250 * skill_lv; + break; + case MH_POISON_MIST: + skillratio += 100 * skill_lv; + break; + } - if (skill_num == NPC_EARTHQUAKE) { - //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex] - //Also divide the extra bonuses from atk2 based on the number in range [Kevin] - if (mflag>0) - ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag; - else - ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); - } + MATK_RATE(skillratio); - if (ad.damage<1) - ad.damage=1; - - if (!(nk&NK_NO_ELEFIX)) - ad.damage=battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); - - if (skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS) { - //Apply the physical part of the skill's damage. [Skotlex] - struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); - ad.damage = battle_attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40*skill_lv)/100; - if (src == target) { - if (src->type == BL_PC) - ad.damage = ad.damage/2; - else - ad.damage = 0; - } - } + //Constant/misc additions from skills + if (skill_num == WZ_FIREPILLAR) + MATK_ADD(50); + } + } -#ifndef RENEWAL - ad.damage = battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); -#endif - } + if(sd) { + //Damage bonuses + if ((i = pc_skillatk_bonus(sd, skill_num))) + ad.damage += ad.damage*i/100; + + //Ignore Defense? + if (!flag.imdef && ( + sd->bonus.ignore_mdef_ele & ( 1 << tstatus->def_ele ) || + sd->bonus.ignore_mdef_race & ( 1 << tstatus->race ) || + sd->bonus.ignore_mdef_race & ( is_boss(target) ? 1 << RC_BOSS : 1 << RC_NONBOSS ) + )) + flag.imdef = 1; + } - damage_div_fix(ad.damage, ad.div_); + if(!flag.imdef){ + defType mdef = tstatus->mdef; + int mdef2= tstatus->mdef2; + if(sd) { + i = sd->ignore_mdef[is_boss(target)?RC_BOSS:RC_NONBOSS]; + i+= sd->ignore_mdef[tstatus->race]; + if (i) + { + if (i > 100) i = 100; + mdef -= mdef * i/100; + //mdef2-= mdef2* i/100; + } + } + #ifdef RENEWAL + /** + * RE MDEF Reduction (from doddler:?title=Renewal_Changes#MDEF) + * Damage from magic = Magic Attack * 111.5/(111.5+eMDEF) + * Damage = Magic Attack * 111.5/(111.5+eMDEF) - sMDEF + **/ + if(mdef < -111) mdef = -111; // value smaller -111 brings back the damage to origin up to -223. + ad.damage = ad.damage * 1115 / (1115 + mdef * 10) - mdef2; + #else + if(battle_config.magic_defense_type) + ad.damage = ad.damage - mdef*battle_config.magic_defense_type - mdef2; + else + ad.damage = ad.damage * (100-mdef)/100 - mdef2; + #endif + } - if (flag.infdef && ad.damage) - ad.damage = ad.damage>0?1:-1; + if (skill_num == NPC_EARTHQUAKE) + { //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex] + //Also divide the extra bonuses from atk2 based on the number in range [Kevin] + if(mflag>0) + ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag; + else + ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); + } - ad.damage=battle_calc_damage(src,target,&ad,ad.damage,skill_num,skill_lv); - if (map_flag_gvg2(target->m)) - ad.damage=battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag); - else if (map[target->m].flag.battleground) - ad.damage=battle_calc_bg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag); + if(ad.damage<1) + ad.damage=1; - switch (skill_num) { /* post-calc modifiers */ - case SO_VARETYR_SPEAR: { // Physical damage. - struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); - ad.damage += wd.damage; - break; - } - //case HM_ERASER_CUTTER: - } + if (!(nk&NK_NO_ELEFIX)) + ad.damage=battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); + + if( skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS ) + { //Apply the physical part of the skill's damage. [Skotlex] + struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); + ad.damage = battle_attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40*skill_lv)/100; + if( src == target ) + { + if( src->type == BL_PC ) + ad.damage = ad.damage/2; + else + ad.damage = 0; + } + } + + if (sd && !(nk&NK_NO_CARDFIX_ATK)) { + short t_class = status_get_class(target); + short cardfix=1000; + + cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) + cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100; + cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate;i++) { + if(sd->add_mdmg[i].class_ == t_class) { + cardfix=cardfix*(100+sd->add_mdmg[i].rate)/100; + continue; + } + } + if (cardfix != 1000) + MATK_RATE(cardfix/10); + } + + if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) + { // Target cards. + short s_race2 = status_get_race2(src); + short s_class= status_get_class(src); + int cardfix=1000; + + if (!(nk&NK_NO_ELEFIX)) + { + int ele_fix = tsd->subele[s_ele]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele) continue; + if(!(tsd->subele2[i].flag&ad.flag&BF_WEAPONMASK && + tsd->subele2[i].flag&ad.flag&BF_RANGEMASK && + tsd->subele2[i].flag&ad.flag&BF_SKILLMASK)) + continue; + ele_fix += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix)/100; + } + cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; + cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; + cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; + cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + + for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) { + if(tsd->add_mdef[i].class_ == s_class) { + cardfix=cardfix*(100-tsd->add_mdef[i].rate)/100; + break; + } + } + //It was discovered that ranged defense also counts vs magic! [Skotlex] + if ( ad.flag&BF_SHORT ) + cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; + else + cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; + + cardfix = cardfix * ( 100 - tsd->bonus.magic_def_rate ) / 100; - return ad; + if( tsd->sc.data[SC_MDEF_RATE] ) + cardfix = cardfix * ( 100 - tsd->sc.data[SC_MDEF_RATE]->val1 ) / 100; + + if (cardfix != 1000) + MATK_RATE( cardfix / 10 ); + } + } + + damage_div_fix(ad.damage, ad.div_); + + if (flag.infdef && ad.damage) + ad.damage = ad.damage>0?1:-1; + + ad.damage=battle_calc_damage(src,target,&ad,ad.damage,skill_num,skill_lv); + if( map_flag_gvg2(target->m) ) + ad.damage=battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag); + else if( map[target->m].flag.battleground ) + ad.damage=battle_calc_bg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag); + + switch( skill_num ) { /* post-calc modifiers */ + case SO_VARETYR_SPEAR: { // Physical damage. + struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); + ad.damage += wd.damage; + break; + } + //case HM_ERASER_CUTTER: + } + + return ad; } /*========================================== * Calculate Misc dammage for skillid *------------------------------------------*/ -struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag) { - int skill; - short i, nk; - short s_ele; +struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag) +{ + int skill; + short i, nk; + short s_ele; - struct map_session_data *sd, *tsd; - struct Damage md; //DO NOT CONFUSE with md of mob_data! - struct status_data *sstatus = status_get_status_data(src); - struct status_data *tstatus = status_get_status_data(target); + struct map_session_data *sd, *tsd; + struct Damage md; //DO NOT CONFUSE with md of mob_data! + struct status_data *sstatus = status_get_status_data(src); + struct status_data *tstatus = status_get_status_data(target); - memset(&md,0,sizeof(md)); + memset(&md,0,sizeof(md)); - if (src == NULL || target == NULL) { - nullpo_info(NLP_MARK); - return md; - } + if( src == NULL || target == NULL ){ + nullpo_info(NLP_MARK); + return md; + } - //Some initial values - md.amotion=skill_get_inf(skill_num) &INF_GROUND_SKILL?0:sstatus->amotion; - md.dmotion=tstatus->dmotion; - md.div_=skill_get_num(skill_num,skill_lv); - md.blewcount=skill_get_blewcount(skill_num,skill_lv); - md.dmg_lv=ATK_DEF; - md.flag=BF_MISC|BF_SKILL; + //Some initial values + md.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion; + md.dmotion=tstatus->dmotion; + md.div_=skill_get_num( skill_num,skill_lv ); + md.blewcount=skill_get_blewcount(skill_num,skill_lv); + md.dmg_lv=ATK_DEF; + md.flag=BF_MISC|BF_SKILL; - nk = skill_get_nk(skill_num); + nk = skill_get_nk(skill_num); - sd = BL_CAST(BL_PC, src); - tsd = BL_CAST(BL_PC, target); + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, target); - if (sd) { - sd->state.arrow_atk = 0; - md.blewcount += battle_blewcount_bonus(sd, skill_num); - } + if(sd) { + sd->state.arrow_atk = 0; + md.blewcount += battle_blewcount_bonus(sd, skill_num); + } - s_ele = skill_get_ele(skill_num, skill_lv); - if (s_ele < 0 && s_ele != -3) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex] - s_ele = ELE_NEUTRAL; - else if (s_ele == -3) //Use random element - s_ele = rnd()%ELE_MAX; + s_ele = skill_get_ele(skill_num, skill_lv); + if (s_ele < 0 && s_ele != -3) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex] + s_ele = ELE_NEUTRAL; + else if (s_ele == -3) //Use random element + s_ele = rnd()%ELE_MAX; - //Skill Range Criteria - md.flag |= battle_range_type(src, target, skill_num, skill_lv); + //Skill Range Criteria + md.flag |= battle_range_type(src, target, skill_num, skill_lv); - switch (skill_num) { + switch( skill_num ) + { #ifdef RENEWAL - case HT_LANDMINE: - case MA_LANDMINE: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - md.damage = skill_lv * sstatus->dex * (3+status_get_lv(src)/100) * (1+sstatus->int_/35); - md.damage += md.damage * (rnd()%20-10) / 100; - md.damage += 40 * (sd?pc_checkskill(sd,RA_RESEARCHTRAP):0); - break; + case HT_LANDMINE: + case MA_LANDMINE: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + md.damage = skill_lv * sstatus->dex * (3+status_get_lv(src)/100) * (1+sstatus->int_/35); + md.damage += md.damage * (rnd()%20-10) / 100; + md.damage += 40 * (sd?pc_checkskill(sd,RA_RESEARCHTRAP):0); + break; #else - case HT_LANDMINE: - case MA_LANDMINE: - md.damage=skill_lv*(sstatus->dex+75)*(100+sstatus->int_)/100; - break; - case HT_BLASTMINE: - md.damage=skill_lv*(sstatus->dex/2+50)*(100+sstatus->int_)/100; - break; - case HT_CLAYMORETRAP: - md.damage=skill_lv*(sstatus->dex/2+75)*(100+sstatus->int_)/100; - break; + case HT_LANDMINE: + case MA_LANDMINE: + md.damage=skill_lv*(sstatus->dex+75)*(100+sstatus->int_)/100; + break; + case HT_BLASTMINE: + md.damage=skill_lv*(sstatus->dex/2+50)*(100+sstatus->int_)/100; + break; + case HT_CLAYMORETRAP: + md.damage=skill_lv*(sstatus->dex/2+75)*(100+sstatus->int_)/100; + break; #endif - case HT_BLITZBEAT: - case SN_FALCONASSAULT: - //Blitz-beat Damage. - if (!sd || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0) - skill=0; - md.damage=(sstatus->dex/10+sstatus->int_/2+skill*3+40)*2; - if (mflag > 1) //Autocasted Blitz. - nk|=NK_SPLASHSPLIT; - - if (skill_num == SN_FALCONASSAULT) { - //Div fix of Blitzbeat - skill = skill_get_num(HT_BLITZBEAT, 5); - damage_div_fix(md.damage, skill); - - //Falcon Assault Modifier - md.damage=md.damage*(150+70*skill_lv)/100; - } - break; - case TF_THROWSTONE: - md.damage=50; - break; - case BA_DISSONANCE: - md.damage=30+skill_lv*10; - if (sd) - md.damage+= 3*pc_checkskill(sd,BA_MUSICALLESSON); - break; - case NPC_SELFDESTRUCTION: - md.damage = sstatus->hp; - break; - case NPC_SMOKING: - md.damage=3; - break; - case NPC_DARKBREATH: - md.damage = 500 + (skill_lv-1)*1000 + rnd()%1000; - if (md.damage > 9999) md.damage = 9999; - break; - case PA_PRESSURE: - md.damage=500+300*skill_lv; - break; - case PA_GOSPEL: - md.damage = 1+rnd()%9999; - break; - case CR_ACIDDEMONSTRATION: // updated the formula based on a Japanese formula found to be exact [Reddozen] - if (tstatus->vit+sstatus->int_) //crash fix - md.damage = (int)((int64)7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_))); - else - md.damage = 0; - if (tsd) md.damage>>=1; - if (md.damage < 0 || md.damage > INT_MAX>>1) - //Overflow prevention, will anyone whine if I cap it to a few billion? - //Not capped to INT_MAX to give some room for further damage increase. - md.damage = INT_MAX>>1; - break; - case NJ_ZENYNAGE: - case KO_MUCHANAGE: - md.damage = skill_get_zeny(skill_num ,skill_lv); - if (!md.damage) md.damage = 2; - md.damage = rand()%md.damage + md.damage / (skill_num==NJ_ZENYNAGE?1:2) ; - if (is_boss(target)) - md.damage=md.damage / (skill_num==NJ_ZENYNAGE?3:2); - else if (tsd) // need confirmation for KO_MUCHANAGE - md.damage=md.damage/2; - break; - case GS_FLING: - md.damage = sd?sd->status.job_level:status_get_lv(src); - break; - case HVAN_EXPLOSION: //[orn] - md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100 ; - break ; - case ASC_BREAKER: - md.damage = 500+rnd()%500 + 5*skill_lv * sstatus->int_; - nk|=NK_IGNORE_FLEE|NK_NO_ELEFIX; //These two are not properties of the weapon based part. - break; - case HW_GRAVITATION: - md.damage = 200+200*skill_lv; - md.dmotion = 0; //No flinch animation. - break; - case NPC_EVILLAND: - md.damage = skill_calc_heal(src,target,skill_num,skill_lv,false); - break; - case RK_DRAGONBREATH: - md.damage = ((status_get_hp(src) / 50) + (status_get_max_sp(src) / 4)) * skill_lv; - RE_LVL_MDMOD(150); - if (sd) md.damage = md.damage * (100 + 5 * (pc_checkskill(sd,RK_DRAGONTRAINING) - 1)) / 100; - md.flag |= BF_LONG|BF_WEAPON; - break; - /** - * Ranger - **/ - case RA_CLUSTERBOMB: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - md.damage = skill_lv * sstatus->dex + sstatus->int_ * 5 ; - RE_LVL_TMDMOD(); - md.damage = md.damage * (20 * (sd ? pc_checkskill(sd,RA_RESEARCHTRAP) : 10)); - md.damage = (md.damage?md.damage:1) / (skill_num == RA_CLUSTERBOMB?50:100); - break; - /** - * Mechanic - **/ - case NC_SELFDESTRUCTION: { - short totaldef = tstatus->def2 + (short)status_get_def(target); - md.damage = ((sd?pc_checkskill(sd,NC_MAINFRAME):10) + 8) * (skill_lv + 1) * (status_get_sp(src) + sstatus->vit); - RE_LVL_MDMOD(100); - md.damage += status_get_hp(src) - totaldef; - } - break; - case GN_THORNS_TRAP: - md.damage = 100 + 200 * skill_lv + sstatus->int_; - break; - case GN_HELLS_PLANT_ATK: - //[{( Hell Plant Skill Level x Casters Base Level ) x 10 } + {( Casters INT x 7 ) / 2 } x { 18 + ( Casters Job Level / 4 )] x ( 5 / ( 10 - Summon Flora Skill Level )) - md.damage = (skill_lv * status_get_lv(src) * 10) + (sstatus->int_ * 7 / 2) * (18 + (sd?sd->status.job_level:0) / 4) * (5 / (10 - (sd?pc_checkskill(sd,AM_CANNIBALIZE):0))); - break; - case KO_HAPPOKUNAI: { - struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); - short totaldef = tstatus->def2 + (short)status_get_def(target); - md.damage = wd.damage * 60 * (5 + skill_lv) / 100; - md.damage -= totaldef; - } - break; - case KO_MAKIBISHI: - md.damage = 20 * skill_lv; - break; - } - - if (nk &NK_SPLASHSPLIT) { // Divide ATK among targets - if (mflag>0) - md.damage/= mflag; - else - ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); - } + case HT_BLITZBEAT: + case SN_FALCONASSAULT: + //Blitz-beat Damage. + if(!sd || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0) + skill=0; + md.damage=(sstatus->dex/10+sstatus->int_/2+skill*3+40)*2; + if(mflag > 1) //Autocasted Blitz. + nk|=NK_SPLASHSPLIT; + + if (skill_num == SN_FALCONASSAULT) + { + //Div fix of Blitzbeat + skill = skill_get_num(HT_BLITZBEAT, 5); + damage_div_fix(md.damage, skill); + + //Falcon Assault Modifier + md.damage=md.damage*(150+70*skill_lv)/100; + } + break; + case TF_THROWSTONE: + md.damage=50; + break; + case BA_DISSONANCE: + md.damage=30+skill_lv*10; + if (sd) + md.damage+= 3*pc_checkskill(sd,BA_MUSICALLESSON); + break; + case NPC_SELFDESTRUCTION: + md.damage = sstatus->hp; + break; + case NPC_SMOKING: + md.damage=3; + break; + case NPC_DARKBREATH: + md.damage = 500 + (skill_lv-1)*1000 + rnd()%1000; + if(md.damage > 9999) md.damage = 9999; + break; + case PA_PRESSURE: + md.damage=500+300*skill_lv; + break; + case PA_GOSPEL: + md.damage = 1+rnd()%9999; + break; + case CR_ACIDDEMONSTRATION: // updated the formula based on a Japanese formula found to be exact [Reddozen] + if(tstatus->vit+sstatus->int_) //crash fix + md.damage = (int)((int64)7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_))); + else + md.damage = 0; + if (tsd) md.damage>>=1; + if (md.damage < 0 || md.damage > INT_MAX>>1) + //Overflow prevention, will anyone whine if I cap it to a few billion? + //Not capped to INT_MAX to give some room for further damage increase. + md.damage = INT_MAX>>1; + break; + case NJ_ZENYNAGE: + case KO_MUCHANAGE: + md.damage = skill_get_zeny(skill_num ,skill_lv); + if (!md.damage) md.damage = 2; + md.damage = rand()%md.damage + md.damage / (skill_num==NJ_ZENYNAGE?1:2) ; + if (is_boss(target)) + md.damage=md.damage / (skill_num==NJ_ZENYNAGE?3:2); + else if (tsd) // need confirmation for KO_MUCHANAGE + md.damage=md.damage/2; + break; + case GS_FLING: + md.damage = sd?sd->status.job_level:status_get_lv(src); + break; + case HVAN_EXPLOSION: //[orn] + md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100 ; + break ; + case ASC_BREAKER: + md.damage = 500+rnd()%500 + 5*skill_lv * sstatus->int_; + nk|=NK_IGNORE_FLEE|NK_NO_ELEFIX; //These two are not properties of the weapon based part. + break; + case HW_GRAVITATION: + md.damage = 200+200*skill_lv; + md.dmotion = 0; //No flinch animation. + break; + case NPC_EVILLAND: + md.damage = skill_calc_heal(src,target,skill_num,skill_lv,false); + break; + case RK_DRAGONBREATH: + md.damage = ((status_get_hp(src) / 50) + (status_get_max_sp(src) / 4)) * skill_lv; + RE_LVL_MDMOD(150); + if (sd) md.damage = md.damage * (100 + 5 * (pc_checkskill(sd,RK_DRAGONTRAINING) - 1)) / 100; + md.flag |= BF_LONG|BF_WEAPON; + break; + /** + * Ranger + **/ + case RA_CLUSTERBOMB: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + md.damage = skill_lv * sstatus->dex + sstatus->int_ * 5 ; + RE_LVL_TMDMOD(); + md.damage = md.damage * (20 * ( sd ? pc_checkskill(sd,RA_RESEARCHTRAP) : 10 ) ); + md.damage = (md.damage?md.damage:1) / (skill_num == RA_CLUSTERBOMB?50:100); + break; + /** + * Mechanic + **/ + case NC_SELFDESTRUCTION: + { + short totaldef = tstatus->def2 + (short)status_get_def(target); + md.damage = ( (sd?pc_checkskill(sd,NC_MAINFRAME):10) + 8 ) * ( skill_lv + 1 ) * ( status_get_sp(src) + sstatus->vit ); + RE_LVL_MDMOD(100); + md.damage += status_get_hp(src) - totaldef; + } + break; + case GN_THORNS_TRAP: + md.damage = 100 + 200 * skill_lv + sstatus->int_; + break; + case GN_HELLS_PLANT_ATK: + //[{( Hell Plant Skill Level x Casters Base Level ) x 10 } + {( Casters INT x 7 ) / 2 } x { 18 + ( Casters Job Level / 4 )] x ( 5 / ( 10 - Summon Flora Skill Level )) + md.damage = ( skill_lv * status_get_lv(src) * 10 ) + ( sstatus->int_ * 7 / 2 ) * ( 18 + (sd?sd->status.job_level:0) / 4 ) * ( 5 / (10 - (sd?pc_checkskill(sd,AM_CANNIBALIZE):0)) ); + break; + case KO_HAPPOKUNAI: + { + struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); + short totaldef = tstatus->def2 + (short)status_get_def(target); + md.damage = wd.damage * 60 * (5 + skill_lv) / 100; + md.damage -= totaldef; + } + break; + case KO_MAKIBISHI: + md.damage = 20 * skill_lv; + break; + } - damage_div_fix(md.damage, md.div_); + if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets + if(mflag>0) + md.damage/= mflag; + else + ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num)); + } - if (!(nk &NK_IGNORE_FLEE)) { - struct status_change *sc = status_get_sc(target); - i = 0; //Temp for "hit or no hit" - if (sc && sc->opt1 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING) - i = 1; - else { - short - flee = tstatus->flee, + damage_div_fix(md.damage, md.div_); + + if (!(nk&NK_IGNORE_FLEE)) + { + struct status_change *sc = status_get_sc(target); + i = 0; //Temp for "hit or no hit" + if(sc && sc->opt1 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING) + i = 1; + else { + short + flee = tstatus->flee, #ifdef RENEWAL - hitrate = 0; //Default hitrate + hitrate = 0; //Default hitrate #else - hitrate = 80; //Default hitrate + hitrate = 80; //Default hitrate #endif - if (battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) { - unsigned char attacker_count; //256 max targets should be a sane max - attacker_count = unit_counttargeted(target); - if (attacker_count >= battle_config.agi_penalty_count) { - if (battle_config.agi_penalty_type == 1) - flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; - else //asume type 2: absolute reduction - flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; - if (flee < 1) flee = 1; - } - } + if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) { + unsigned char attacker_count; //256 max targets should be a sane max + attacker_count = unit_counttargeted(target); + if(attacker_count >= battle_config.agi_penalty_count) + { + if (battle_config.agi_penalty_type == 1) + flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; + else //asume type 2: absolute reduction + flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; + if(flee < 1) flee = 1; + } + } - hitrate+= sstatus->hit - flee; + hitrate+= sstatus->hit - flee; #ifdef RENEWAL - if (sd) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window - hitrate += pc_checkskill(sd,AC_VULTURE); + if( sd ) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window + hitrate += pc_checkskill(sd,AC_VULTURE); #endif - hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); - - if (rnd()%100 < hitrate) - i = 1; - } - if (!i) { - md.damage = 0; - md.dmg_lv=ATK_FLEE; - } - } + hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); - md.damage = battle_calc_cardfix(BF_MISC, src, target, nk, s_ele, 0, md.damage, 0, md.flag); + if(rnd()%100 < hitrate) + i = 1; + } + if (!i) { + md.damage = 0; + md.dmg_lv=ATK_FLEE; + } + } - if (sd && (i = pc_skillatk_bonus(sd, skill_num))) - md.damage += md.damage *i/100; + if( md.damage && tsd && !(nk&NK_NO_CARDFIX_DEF) ) + {// misc damage reduction from equipment + int cardfix = 10000; + int race2 = status_get_race2(src); + if (!(nk&NK_NO_ELEFIX)) + { + int ele_fix = tsd->subele[s_ele]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele) continue; + if(!(tsd->subele2[i].flag&md.flag&BF_WEAPONMASK && + tsd->subele2[i].flag&md.flag&BF_RANGEMASK && + tsd->subele2[i].flag&md.flag&BF_SKILLMASK)) + continue; + ele_fix += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix)/100; + } + cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; + cardfix=cardfix*(100-tsd->subrace2[race2])/100; + cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; + cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + + cardfix = cardfix * ( 100 - tsd->bonus.misc_def_rate ) / 100; + if( md.flag&BF_SHORT ) + cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; + else // BF_LONG (there's no other choice) + cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; + + if (cardfix != 10000) + md.damage= (int)( (int64)md.damage * cardfix / 10000 ); + } - if (md.damage < 0) - md.damage = 0; - else if (md.damage && tstatus->mode &MD_PLANT) { - switch (skill_num) { - case HT_LANDMINE: - case MA_LANDMINE: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case RA_CLUSTERBOMB: + if (sd && (i = pc_skillatk_bonus(sd, skill_num))) + md.damage += md.damage*i/100; + + if(md.damage < 0) + md.damage = 0; + else if(md.damage && tstatus->mode&MD_PLANT){ + switch(skill_num){ + case HT_LANDMINE: + case MA_LANDMINE: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + case RA_CLUSTERBOMB: #ifdef RENEWAL - break; + break; #endif - default: - md.damage = 1; - } - } else if (target->type == BL_SKILL) { - TBL_SKILL *su = (TBL_SKILL *)target; - if (su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD)) - md.damage = 1; - } + default: + md.damage = 1; + } + }else if( target->type == BL_SKILL ){ + TBL_SKILL *su = (TBL_SKILL*)target; + if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) + md.damage = 1; + } - if (!(nk &NK_NO_ELEFIX)) - md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); - - md.damage=battle_calc_damage(src,target,&md,md.damage,skill_num,skill_lv); - if (map_flag_gvg2(target->m)) - md.damage=battle_calc_gvg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag); - else if (map[target->m].flag.battleground) - md.damage=battle_calc_bg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag); - - switch (skill_num) { - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - if (md.damage == 1) break; - case RA_CLUSTERBOMB: { - struct Damage wd; - wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); - md.damage += wd.damage; - } - break; - case NJ_ZENYNAGE: - if (sd) { - if (md.damage > sd->status.zeny) - md.damage = sd->status.zeny; - pc_payzeny(sd, md.damage,LOG_TYPE_STEAL,NULL); - } - break; - } + if(!(nk&NK_NO_ELEFIX)) + md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); + + md.damage=battle_calc_damage(src,target,&md,md.damage,skill_num,skill_lv); + if( map_flag_gvg2(target->m) ) + md.damage=battle_calc_gvg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag); + else if( map[target->m].flag.battleground ) + md.damage=battle_calc_bg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag); + + switch( skill_num ) { + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + if( md.damage == 1 ) break; + case RA_CLUSTERBOMB: + { + struct Damage wd; + wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); + md.damage += wd.damage; + } + break; + case NJ_ZENYNAGE: + if( sd ) { + if ( md.damage > sd->status.zeny ) + md.damage = sd->status.zeny; + pc_payzeny(sd, md.damage,LOG_TYPE_STEAL,NULL); + } + break; + } - return md; + return md; } /*========================================== * Battle main entry, from skill_attack *------------------------------------------*/ -struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int count) { - struct Damage d; - switch (attack_type) { - case BF_WEAPON: - d = battle_calc_weapon_attack(bl,target,skill_num,skill_lv,count); - break; - case BF_MAGIC: - d = battle_calc_magic_attack(bl,target,skill_num,skill_lv,count); - break; - case BF_MISC: - d = battle_calc_misc_attack(bl,target,skill_num,skill_lv,count); - break; - default: - ShowError("battle_calc_attack: unknown attack type! %d\n",attack_type); - memset(&d,0,sizeof(d)); - break; - } - if (d.damage + d.damage2 < 1) { - //Miss/Absorbed - //Weapon attacks should go through to cause additional effects. - if (d.dmg_lv == ATK_DEF /*&& attack_type&(BF_MAGIC|BF_MISC)*/) // Isn't it that additional effects don't apply if miss? - d.dmg_lv = ATK_MISS; - d.dmotion = 0; - } else // Some skills like Weaponry Research will cause damage even if attack is dodged - d.dmg_lv = ATK_DEF; - return d; +struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int count) +{ + struct Damage d; + switch(attack_type) { + case BF_WEAPON: d = battle_calc_weapon_attack(bl,target,skill_num,skill_lv,count); break; + case BF_MAGIC: d = battle_calc_magic_attack(bl,target,skill_num,skill_lv,count); break; + case BF_MISC: d = battle_calc_misc_attack(bl,target,skill_num,skill_lv,count); break; + default: + ShowError("battle_calc_attack: unknown attack type! %d\n",attack_type); + memset(&d,0,sizeof(d)); + break; + } + if( d.damage + d.damage2 < 1 ) + { //Miss/Absorbed + //Weapon attacks should go through to cause additional effects. + if (d.dmg_lv == ATK_DEF /*&& attack_type&(BF_MAGIC|BF_MISC)*/) // Isn't it that additional effects don't apply if miss? + d.dmg_lv = ATK_MISS; + d.dmotion = 0; + } + else // Some skills like Weaponry Research will cause damage even if attack is dodged + d.dmg_lv = ATK_DEF; + return d; } //Calculates BF_WEAPON returned damage. -int battle_calc_return_damage(struct block_list *bl, struct block_list *src, int *dmg, int flag, int skillid) -{ - struct map_session_data *sd = NULL; - int rdamage = 0, damage = *dmg; - struct status_change *sc; - - sd = BL_CAST(BL_PC, bl); - sc = status_get_sc(bl); - - if (sc && sc->data[SC_REFLECTDAMAGE]) { - int max_damage = status_get_max_hp(bl) * status_get_lv(bl) / 100; - rdamage = (*dmg) * sc->data[SC_REFLECTDAMAGE]->val2 / 100; - if (rdamage > max_damage) rdamage = max_damage; - } else if (sc && sc->data[SC_CRESCENTELBOW] && !is_boss(src) && rnd()%100 < sc->data[SC_CRESCENTELBOW]->val2) { - //ATK [{(Target HP / 100) x Skill Level} x Caster Base Level / 125] % + [Received damage x {1 + (Skill Level x 0.2)}] - int ratio = (status_get_hp(src) / 100) * sc->data[SC_CRESCENTELBOW]->val1 * status_get_lv(bl) / 125; - if (ratio > 5000) ratio = 5000; // Maximum of 5000% ATK - rdamage = rdamage * ratio / 100 + (*dmg) * (10 + sc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10; - skill_blown(bl, src, skill_get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1), unit_getdir(src), 0); - clif_skill_damage(bl, src, gettick(), status_get_amotion(src), 0, rdamage, - 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does - clif_damage(src, bl, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, 0, 0); - status_damage(src, bl, status_damage(bl, src, rdamage, 0, 0, 1)/10, 0, 0, 1); - status_change_end(bl, SC_CRESCENTELBOW, INVALID_TIMER); - return 0; // Just put here to minimize redundancy - } else if (flag & BF_SHORT) {//Bounces back part of the damage. - if (sd && sd->bonus.short_weapon_damage_return) { - rdamage += damage * sd->bonus.short_weapon_damage_return / 100; - if (rdamage < 1) rdamage = 1; - } - if (sc && sc->count) { - if (sc->data[SC_REFLECTSHIELD] && skillid != WS_CARTTERMINATION) { - rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100; - if (rdamage < 1) rdamage = 1; - } - if (sc->data[SC_DEATHBOUND] && skillid != WS_CARTTERMINATION && !(src->type == BL_MOB && is_boss(src))) { - int dir = map_calc_dir(bl,src->x,src->y), - t_dir = unit_getdir(bl), rd1 = 0; - - if (distance_bl(src,bl) <= 0 || !map_check_dir(dir,t_dir)) { - rd1 = min(damage,status_get_max_hp(bl)) * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. - *dmg = rd1 * 30 / 100; // Received damge = 30% of amplifly damage. - clif_skill_damage(src,bl,gettick(), status_get_amotion(src), 0, -30000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1,6); - status_change_end(bl,SC_DEATHBOUND,INVALID_TIMER); - rdamage += rd1; - if (rdamage < 1) rdamage = 1; - } - } - } - } else { - if (sd && sd->bonus.long_weapon_damage_return) { - rdamage += damage * sd->bonus.long_weapon_damage_return / 100; - if (rdamage < 1) rdamage = 1; - } - } +int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int *dmg, int flag, int skillid){ + struct map_session_data* sd = NULL; + int rdamage = 0, damage = *dmg; + struct status_change* sc; + + sd = BL_CAST(BL_PC, bl); + sc = status_get_sc(bl); + + if( sc && sc->data[SC_REFLECTDAMAGE] ) { + int max_damage = status_get_max_hp(bl) * status_get_lv(bl) / 100; + rdamage = (*dmg) * sc->data[SC_REFLECTDAMAGE]->val2 / 100; + if( rdamage > max_damage ) rdamage = max_damage; + }else if( sc && sc->data[SC_CRESCENTELBOW] && !is_boss(src) && rnd()%100 < sc->data[SC_CRESCENTELBOW]->val2 ){ + //ATK [{(Target HP / 100) x Skill Level} x Caster Base Level / 125] % + [Received damage x {1 + (Skill Level x 0.2)}] + int ratio = (status_get_hp(src) / 100) * sc->data[SC_CRESCENTELBOW]->val1 * status_get_lv(bl) / 125; + if (ratio > 5000) ratio = 5000; // Maximum of 5000% ATK + rdamage = rdamage * ratio / 100 + (*dmg) * (10 + sc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10; + skill_blown(bl, src, skill_get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1), unit_getdir(src), 0); + clif_skill_damage(bl, src, gettick(), status_get_amotion(src), 0, rdamage, + 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does + clif_damage(src, bl, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, 0, 0); + status_damage(src, bl, status_damage(bl, src, rdamage, 0, 0, 1)/10, 0, 0, 1); + status_change_end(bl, SC_CRESCENTELBOW, INVALID_TIMER); + return 0; // Just put here to minimize redundancy + }else if (flag & BF_SHORT) {//Bounces back part of the damage. + if ( sd && sd->bonus.short_weapon_damage_return ) { + rdamage += damage * sd->bonus.short_weapon_damage_return / 100; + if(rdamage < 1) rdamage = 1; + } + if( sc && sc->count ) { + if ( sc->data[SC_REFLECTSHIELD] && skillid != WS_CARTTERMINATION ) { + rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100; + if (rdamage < 1) rdamage = 1; + } + if(sc->data[SC_DEATHBOUND] && skillid != WS_CARTTERMINATION && !(src->type == BL_MOB && is_boss(src)) ) { + int dir = map_calc_dir(bl,src->x,src->y), + t_dir = unit_getdir(bl), rd1 = 0; + + if( distance_bl(src,bl) <= 0 || !map_check_dir(dir,t_dir) ) { + rd1 = min(damage,status_get_max_hp(bl)) * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. + *dmg = rd1 * 30 / 100; // Received damge = 30% of amplifly damage. + clif_skill_damage(src,bl,gettick(), status_get_amotion(src), 0, -30000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1,6); + status_change_end(bl,SC_DEATHBOUND,INVALID_TIMER); + rdamage += rd1; + if (rdamage < 1) rdamage = 1; + } + } + } + } else { + if (sd && sd->bonus.long_weapon_damage_return) { + rdamage += damage * sd->bonus.long_weapon_damage_return / 100; + if (rdamage < 1) rdamage = 1; + } + } - if (sc && sc->data[SC_KYOMU]) // Nullify reflecting ability - rdamage = 0; + if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability + rdamage = 0; - return rdamage; + return rdamage; } void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss) { - struct weapon_data *wd; - int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i, *damage; - for (i = 0; i < 4; i++) { - //First two iterations: Right hand - if (i < 2) { - wd = &sd->right_weapon; - damage = &rdamage; - } else { - wd = &sd->left_weapon; - damage = &ldamage; - } - if (*damage <= 0) continue; - //First and Third iterations: race, other two boss/nonboss state - if (i == 0 || i == 2) - type = race; - else - type = boss?RC_BOSS:RC_NONBOSS; - - hp = wd->hp_drain[type].value; - if (wd->hp_drain[type].rate) - hp += battle_calc_drain(*damage, wd->hp_drain[type].rate, wd->hp_drain[type].per); - - sp = wd->sp_drain[type].value; - if (wd->sp_drain[type].rate) - sp += battle_calc_drain(*damage, wd->sp_drain[type].rate, wd->sp_drain[type].per); - - if (hp) { - if (wd->hp_drain[type].type) - rhp += hp; - thp += hp; - } - if (sp) { - if (wd->sp_drain[type].type) - rsp += sp; - tsp += sp; - } - } + struct weapon_data *wd; + int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i, *damage; + for (i = 0; i < 4; i++) { + //First two iterations: Right hand + if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; } + else { wd = &sd->left_weapon; damage = &ldamage; } + if (*damage <= 0) continue; + //First and Third iterations: race, other two boss/nonboss state + if (i == 0 || i == 2) + type = race; + else + type = boss?RC_BOSS:RC_NONBOSS; + + hp = wd->hp_drain[type].value; + if (wd->hp_drain[type].rate) + hp += battle_calc_drain(*damage, wd->hp_drain[type].rate, wd->hp_drain[type].per); + + sp = wd->sp_drain[type].value; + if (wd->sp_drain[type].rate) + sp += battle_calc_drain(*damage, wd->sp_drain[type].rate, wd->sp_drain[type].per); + + if (hp) { + if (wd->hp_drain[type].type) + rhp += hp; + thp += hp; + } + if (sp) { + if (wd->sp_drain[type].type) + rsp += sp; + tsp += sp; + } + } - if (sd->bonus.sp_vanish_rate && rnd()%1000 < sd->bonus.sp_vanish_rate) - status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->bonus.sp_vanish_per, false); + if (sd->bonus.sp_vanish_rate && rnd()%1000 < sd->bonus.sp_vanish_rate) + status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->bonus.sp_vanish_per, false); - if (sd->sp_gain_race_attack[race]) - tsp += sd->sp_gain_race_attack[race]; - if (sd->hp_gain_race_attack[race]) - thp += sd->hp_gain_race_attack[race]; + if( sd->sp_gain_race_attack[race] ) + tsp += sd->sp_gain_race_attack[race]; + if( sd->hp_gain_race_attack[race] ) + thp += sd->hp_gain_race_attack[race]; - if (!thp && !tsp) return; + if (!thp && !tsp) return; - status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1); + status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1); - if (rhp || rsp) - status_zap(tbl, rhp, rsp); + if (rhp || rsp) + status_zap(tbl, rhp, rsp); } // Deals the same damage to targets in area. [pakpil] -int battle_damage_area(struct block_list *bl, va_list ap) -{ - unsigned int tick; - int amotion, dmotion, damage; - struct block_list *src; - - nullpo_ret(bl); - - tick=va_arg(ap, unsigned int); - src=va_arg(ap,struct block_list *); - amotion=va_arg(ap,int); - dmotion=va_arg(ap,int); - damage=va_arg(ap,int); - if (bl->type == BL_MOB && ((TBL_MOB *)bl)->class_ == MOBID_EMPERIUM) - return 0; - if (bl != src && battle_check_target(src,bl,BCT_ENEMY) > 0) { - map_freeblock_lock(); - if (src->type == BL_PC) - battle_drain((TBL_PC *)src, bl, damage, damage, status_get_race(bl), is_boss(bl)); - if (amotion) - battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0); - else - status_fix_damage(src,bl,damage,0); - clif_damage(bl,bl,tick,amotion,dmotion,damage,1,ATK_BLOCK,0); - skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); - map_freeblock_unlock(); - } +int battle_damage_area( struct block_list *bl, va_list ap) { + unsigned int tick; + int amotion, dmotion, damage; + struct block_list *src; + + nullpo_ret(bl); + + tick=va_arg(ap, unsigned int); + src=va_arg(ap,struct block_list *); + amotion=va_arg(ap,int); + dmotion=va_arg(ap,int); + damage=va_arg(ap,int); + if( bl->type == BL_MOB && ((TBL_MOB*)bl)->class_ == MOBID_EMPERIUM ) + return 0; + if( bl != src && battle_check_target(src,bl,BCT_ENEMY) > 0 ) { + map_freeblock_lock(); + if( src->type == BL_PC ) + battle_drain((TBL_PC*)src, bl, damage, damage, status_get_race(bl), is_boss(bl)); + if( amotion ) + battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0); + else + status_fix_damage(src,bl,damage,0); + clif_damage(bl,bl,tick,amotion,dmotion,damage,1,ATK_BLOCK,0); + skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); + map_freeblock_unlock(); + } - return 0; + return 0; } /*========================================== * Do a basic physical attack (call trough unit_attack_timer) *------------------------------------------*/ -enum damage_lv battle_weapon_attack(struct block_list *src, struct block_list *target, unsigned int tick, int flag) -{ - struct map_session_data *sd = NULL, *tsd = NULL; - struct status_data *sstatus, *tstatus; - struct status_change *sc, *tsc; - int damage,rdamage=0,rdelay=0; - int skillv; - struct Damage wd; - - nullpo_retr(ATK_NONE, src); - nullpo_retr(ATK_NONE, target); - - if (src->prev == NULL || target->prev == NULL) - return ATK_NONE; - - sd = BL_CAST(BL_PC, src); - tsd = BL_CAST(BL_PC, target); - - sstatus = status_get_status_data(src); - tstatus = status_get_status_data(target); - - sc = status_get_sc(src); - tsc = status_get_sc(target); - - if (sc && !sc->count) //Avoid sc checks when there's none to check for. [Skotlex] - sc = NULL; - if (tsc && !tsc->count) - tsc = NULL; - - if (sd) { - sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)); - if (sd->state.arrow_atk) { - int index = sd->equip_index[EQI_AMMO]; - if (index<0) { - clif_arrow_fail(sd,0); - return ATK_NONE; - } - //Ammo check by Ishizu-chan - if (sd->inventory_data[index]) - switch (sd->status.weapon) { - case W_BOW: - if (sd->inventory_data[index]->look != A_ARROW) { - clif_arrow_fail(sd,0); - return ATK_NONE; - } - break; - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - if (sd->inventory_data[index]->look != A_BULLET) { - clif_arrow_fail(sd,0); - return ATK_NONE; - } - break; - case W_GRENADE: - if (sd->inventory_data[index]->look != A_GRENADE) { - clif_arrow_fail(sd,0); - return ATK_NONE; - } - break; - } - } - } +enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, unsigned int tick, int flag) { + struct map_session_data *sd = NULL, *tsd = NULL; + struct status_data *sstatus, *tstatus; + struct status_change *sc, *tsc; + int damage,rdamage=0,rdelay=0; + int skillv; + struct Damage wd; + + nullpo_retr(ATK_NONE, src); + nullpo_retr(ATK_NONE, target); + + if (src->prev == NULL || target->prev == NULL) + return ATK_NONE; + + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, target); + + sstatus = status_get_status_data(src); + tstatus = status_get_status_data(target); + + sc = status_get_sc(src); + tsc = status_get_sc(target); + + if (sc && !sc->count) //Avoid sc checks when there's none to check for. [Skotlex] + sc = NULL; + if (tsc && !tsc->count) + tsc = NULL; + + if (sd) + { + sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)); + if (sd->state.arrow_atk) + { + int index = sd->equip_index[EQI_AMMO]; + if (index<0) { + clif_arrow_fail(sd,0); + return ATK_NONE; + } + //Ammo check by Ishizu-chan + if (sd->inventory_data[index]) + switch (sd->status.weapon) { + case W_BOW: + if (sd->inventory_data[index]->look != A_ARROW) { + clif_arrow_fail(sd,0); + return ATK_NONE; + } + break; + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + if (sd->inventory_data[index]->look != A_BULLET) { + clif_arrow_fail(sd,0); + return ATK_NONE; + } + break; + case W_GRENADE: + if (sd->inventory_data[index]->look != A_GRENADE) { + clif_arrow_fail(sd,0); + return ATK_NONE; + } + break; + } + } + } if (sc && sc->count) { if (sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4 & 2)) status_change_end(src, SC_CLOAKING, INVALID_TIMER); else if (sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4 & 2)) status_change_end(src, SC_CLOAKINGEXCEED, INVALID_TIMER); } - if (tsc && tsc->data[SC_AUTOCOUNTER] && status_check_skilluse(target, src, KN_AUTOCOUNTER, 1)) { - int dir = map_calc_dir(target,src->x,src->y); - int t_dir = unit_getdir(target); - int dist = distance_bl(src, target); - if (dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) { - int skilllv = tsc->data[SC_AUTOCOUNTER]->val1; - clif_skillcastcancel(target); //Remove the casting bar. [Skotlex] - clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. - status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER); - skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skilllv,tick,0); - return ATK_BLOCK; - } - } + if( tsc && tsc->data[SC_AUTOCOUNTER] && status_check_skilluse(target, src, KN_AUTOCOUNTER, 1) ) + { + int dir = map_calc_dir(target,src->x,src->y); + int t_dir = unit_getdir(target); + int dist = distance_bl(src, target); + if(dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) + { + int skilllv = tsc->data[SC_AUTOCOUNTER]->val1; + clif_skillcastcancel(target); //Remove the casting bar. [Skotlex] + clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. + status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER); + skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skilllv,tick,0); + return ATK_BLOCK; + } + } - if (tsc && tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src) && (src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->status.weapon == W_FIST ? 1 : 2))) { - int skilllv = tsc->data[SC_BLADESTOP_WAIT]->val1; - int duration = skill_get_time2(MO_BLADESTOP,skilllv); - status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER); - if (sc_start4(src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) { - //Target locked. - clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. - clif_bladestop(target, src->id, 1); - sc_start4(target, SC_BLADESTOP, 100, skilllv, 0, 0, src->id, duration); - return ATK_BLOCK; - } - } + if( tsc && tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src) && (src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->status.weapon == W_FIST ? 1 : 2)) ) + { + int skilllv = tsc->data[SC_BLADESTOP_WAIT]->val1; + int duration = skill_get_time2(MO_BLADESTOP,skilllv); + status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER); + if(sc_start4(src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) + { //Target locked. + clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. + clif_bladestop(target, src->id, 1); + sc_start4(target, SC_BLADESTOP, 100, skilllv, 0, 0, src->id, duration); + return ATK_BLOCK; + } + } - if (sd && (skillv = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0) { - int triple_rate= 30 - skillv; //Base Rate - if (sc && sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK) { - triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100; - status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); - } - if (rnd()%100 < triple_rate) { - if (skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0)) - return ATK_DEF; - return ATK_MISS; - } - } + if(sd && (skillv = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0) { + int triple_rate= 30 - skillv; //Base Rate + if (sc && sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK) { + triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100; + status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); + } + if (rnd()%100 < triple_rate) { + if( skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0) ) + return ATK_DEF; + return ATK_MISS; + } + } - if (sc) { - if (sc->data[SC_SACRIFICE]) { - int skilllv = sc->data[SC_SACRIFICE]->val1; - damage_lv ret_val; + if (sc) { + if (sc->data[SC_SACRIFICE]) { + int skilllv = sc->data[SC_SACRIFICE]->val1; + damage_lv ret_val; - if (--sc->data[SC_SACRIFICE]->val2 <= 0) - status_change_end(src, SC_SACRIFICE, INVALID_TIMER); + if( --sc->data[SC_SACRIFICE]->val2 <= 0 ) + status_change_end(src, SC_SACRIFICE, INVALID_TIMER); - /** - * We need to calculate the DMG before the hp reduction, because it can kill the source. - * For futher information: bugreport:4950 - **/ - ret_val = (damage_lv)skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,skilllv,tick,0); + /** + * We need to calculate the DMG before the hp reduction, because it can kill the source. + * For futher information: bugreport:4950 + **/ + ret_val = (damage_lv)skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,skilllv,tick,0); - status_zap(src, sstatus->max_hp*9/100, 0);//Damage to self is always 9% - if (ret_val == ATK_NONE) - return ATK_MISS; - return ret_val; - } - if (sc->data[SC_MAGICALATTACK]) { - if (skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0)) - return ATK_DEF; - return ATK_MISS; - } - if (sc->data[SC_GT_ENERGYGAIN]) { - if (sd && rnd()%100 < 10 + 5 * sc->data[SC_GT_ENERGYGAIN]->val1) - pc_addspiritball(sd, - skill_get_time(MO_CALLSPIRITS, sc->data[SC_GT_ENERGYGAIN]->val1), - sc->data[SC_GT_ENERGYGAIN]->val1); - } - if (tsc && tsc->data[SC_GT_ENERGYGAIN]) { - if (tsd && rnd()%100 < 10 + 5 * tsc->data[SC_GT_ENERGYGAIN]->val1) - pc_addspiritball(tsd, - skill_get_time(MO_CALLSPIRITS, tsc->data[SC_GT_ENERGYGAIN]->val1), - tsc->data[SC_GT_ENERGYGAIN]->val1); - } + status_zap(src, sstatus->max_hp*9/100, 0);//Damage to self is always 9% + if( ret_val == ATK_NONE ) + return ATK_MISS; + return ret_val; + } + if (sc->data[SC_MAGICALATTACK]) { + if( skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0) ) + return ATK_DEF; + return ATK_MISS; + } + if( sc->data[SC_GT_ENERGYGAIN] ) { + if( sd && rnd()%100 < 10 + 5 * sc->data[SC_GT_ENERGYGAIN]->val1) + pc_addspiritball(sd, + skill_get_time(MO_CALLSPIRITS, sc->data[SC_GT_ENERGYGAIN]->val1), + sc->data[SC_GT_ENERGYGAIN]->val1); + } + if( tsc && tsc->data[SC_GT_ENERGYGAIN] ) { + if( tsd && rnd()%100 < 10 + 5 * tsc->data[SC_GT_ENERGYGAIN]->val1) + pc_addspiritball(tsd, + skill_get_time(MO_CALLSPIRITS, tsc->data[SC_GT_ENERGYGAIN]->val1), + tsc->data[SC_GT_ENERGYGAIN]->val1); + } - } + } - if (tsc && tsc->data[SC_KAAHI] && tsc->data[SC_KAAHI]->val4 == INVALID_TIMER && tstatus->hp < tstatus->max_hp) - tsc->data[SC_KAAHI]->val4 = add_timer(tick + skill_get_time2(SL_KAAHI,tsc->data[SC_KAAHI]->val1), kaahi_heal_timer, target->id, SC_KAAHI); //Activate heal. + if(tsc && tsc->data[SC_KAAHI] && tsc->data[SC_KAAHI]->val4 == INVALID_TIMER && tstatus->hp < tstatus->max_hp) + tsc->data[SC_KAAHI]->val4 = add_timer(tick + skill_get_time2(SL_KAAHI,tsc->data[SC_KAAHI]->val1), kaahi_heal_timer, target->id, SC_KAAHI); //Activate heal. - wd = battle_calc_attack(BF_WEAPON, src, target, 0, 0, flag); + wd = battle_calc_attack(BF_WEAPON, src, target, 0, 0, flag); - if (sc && sc->count) { - if (sc->data[SC_EXEEDBREAK]) { - wd.damage = wd.damage * sc->data[SC_EXEEDBREAK]->val1 / 100; - status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER); - } - if (sc->data[SC_SPELLFIST]) { - if (--(sc->data[SC_SPELLFIST]->val1) >= 0) { - struct Damage ad = battle_calc_attack(BF_MAGIC,src,target,sc->data[SC_SPELLFIST]->val3,sc->data[SC_SPELLFIST]->val4,flag|BF_SHORT); - wd.damage = ad.damage; - } else - status_change_end(src,SC_SPELLFIST,INVALID_TIMER); - } - if (sc->data[SC_GIANTGROWTH] && (wd.flag&BF_SHORT) && rnd()%100 < sc->data[SC_GIANTGROWTH]->val2) - wd.damage *= 3; // Triple Damage + if( sc && sc->count ) { + if (sc->data[SC_EXEEDBREAK]) { + wd.damage = wd.damage * sc->data[SC_EXEEDBREAK]->val1 / 100; + status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER); + } + if( sc->data[SC_SPELLFIST] ) { + if( --(sc->data[SC_SPELLFIST]->val1) >= 0 ){ + struct Damage ad = battle_calc_attack(BF_MAGIC,src,target,sc->data[SC_SPELLFIST]->val3,sc->data[SC_SPELLFIST]->val4,flag|BF_SHORT); + wd.damage = ad.damage; + }else + status_change_end(src,SC_SPELLFIST,INVALID_TIMER); + } + if( sc->data[SC_GIANTGROWTH] && (wd.flag&BF_SHORT) && rnd()%100 < sc->data[SC_GIANTGROWTH]->val2 ) + wd.damage *= 3; // Triple Damage - if (sd && sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0 && sd->status.inventory[sd->equip_index[EQI_AMMO]].amount >= sc->data[SC_FEARBREEZE]->val4 && battle_config.arrow_decrement) { - pc_delitem(sd,sd->equip_index[EQI_AMMO],sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME); - sc->data[SC_FEARBREEZE]->val4 = 0; - } - } - if (sd && sd->state.arrow_atk) //Consume arrow. - battle_consume_ammo(sd, 0, 0); - - damage = wd.damage + wd.damage2; - if (damage > 0 && src != target) { - if (sc && sc->data[SC_DUPLELIGHT] && (wd.flag&BF_SHORT) && rnd()%100 <= 10+2*sc->data[SC_DUPLELIGHT]->val1) { - // Activates it only from melee damage - int skillid; - if (rnd()%2 == 1) - skillid = AB_DUPLELIGHT_MELEE; - else - skillid = AB_DUPLELIGHT_MAGIC; - skill_attack(skill_get_type(skillid), src, src, target, skillid, sc->data[SC_DUPLELIGHT]->val1, tick, SD_LEVEL); - } + if( sd && sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0 && sd->status.inventory[sd->equip_index[EQI_AMMO]].amount >= sc->data[SC_FEARBREEZE]->val4 && battle_config.arrow_decrement){ + pc_delitem(sd,sd->equip_index[EQI_AMMO],sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME); + sc->data[SC_FEARBREEZE]->val4 = 0; + } + } + if (sd && sd->state.arrow_atk) //Consume arrow. + battle_consume_ammo(sd, 0, 0); + + damage = wd.damage + wd.damage2; + if( damage > 0 && src != target ) + { + if( sc && sc->data[SC_DUPLELIGHT] && (wd.flag&BF_SHORT) && rnd()%100 <= 10+2*sc->data[SC_DUPLELIGHT]->val1 ) + { // Activates it only from melee damage + int skillid; + if( rnd()%2 == 1 ) + skillid = AB_DUPLELIGHT_MELEE; + else + skillid = AB_DUPLELIGHT_MAGIC; + skill_attack(skill_get_type(skillid), src, src, target, skillid, sc->data[SC_DUPLELIGHT]->val1, tick, SD_LEVEL); + } - rdamage = battle_calc_return_damage(target,src, &damage, wd.flag, 0); - if (rdamage > 0) { - if (tsc && tsc->data[SC_REFLECTDAMAGE]) { - if (src != target) // Don't reflect your own damage (Grand Cross) - map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd.amotion,wd.dmotion,rdamage,tstatus->race,0); - } else { - rdelay = clif_damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0); - //Use Reflect Shield to signal this kind of skill trigger. [Skotlex] - skill_additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); - } - } - } + rdamage = battle_calc_return_damage(target,src, &damage, wd.flag, 0); + if( rdamage > 0 ) { + if( tsc && tsc->data[SC_REFLECTDAMAGE] ) { + if( src != target )// Don't reflect your own damage (Grand Cross) + map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd.amotion,wd.dmotion,rdamage,tstatus->race,0); + } else { + rdelay = clif_damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0); + //Use Reflect Shield to signal this kind of skill trigger. [Skotlex] + skill_additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); + } + } + } - wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2); + wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2); - if (sd && sd->bonus.splash_range > 0 && damage > 0) - skill_castend_damage_id(src, target, 0, 1, tick, 0); - if (target->type == BL_SKILL && damage > 0) { - TBL_SKILL *su = (TBL_SKILL *)target; - if (su->group && su->group->skill_id == HT_BLASTMINE) - skill_blown(src, target, 3, -1, 0); - } - map_freeblock_lock(); - - battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion); - if (tsc) { - if (tsc->data[SC_DEVOTION]) { - struct status_change_entry *sce = tsc->data[SC_DEVOTION]; - struct block_list *d_bl = map_id2bl(sce->val1); - - if (d_bl && ( - (d_bl->type == BL_MER && ((TBL_MER *)d_bl)->master && ((TBL_MER *)d_bl)->master->bl.id == target->id) || - (d_bl->type == BL_PC && ((TBL_PC *)d_bl)->devotion[sce->val2] == target->id) - ) && check_distance_bl(target, d_bl, sce->val3)) { - clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, 0, 0); - status_fix_damage(NULL, d_bl, damage, 0); - } else - status_change_end(target, SC_DEVOTION, INVALID_TIMER); - } else if (tsc->data[SC_CIRCLE_OF_FIRE_OPTION] && (wd.flag&BF_SHORT) && target->type == BL_PC) { - struct elemental_data *ed = ((TBL_PC *)target)->ed; - if (ed) { - clif_skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, 6); - skill_attack(BF_MAGIC,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag); - } - } else if (tsc->data[SC_WATER_SCREEN_OPTION] && tsc->data[SC_WATER_SCREEN_OPTION]->val1) { - struct block_list *e_bl = map_id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1); - if (e_bl && !status_isdead(e_bl)) { - clif_damage(e_bl,e_bl,tick,wd.amotion,wd.dmotion,damage,wd.div_,wd.type,wd.damage2); - status_damage(target,e_bl,damage,0,0,0); - // Just show damage in target. - clif_damage(src, target, tick, wd.amotion, wd.dmotion, damage, wd.div_, wd.type, wd.damage2); - map_freeblock_unlock(); - return ATK_NONE; - } - } - } - if (sc && sc->data[SC_AUTOSPELL] && rnd()%100 < sc->data[SC_AUTOSPELL]->val4) { - int sp = 0; - int skillid = sc->data[SC_AUTOSPELL]->val2; - int skilllv = sc->data[SC_AUTOSPELL]->val3; - int i = rnd()%100; - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_SAGE) - i = 0; //Max chance, no skilllv reduction. [Skotlex] - if (i >= 50) skilllv -= 2; - else if (i >= 15) skilllv--; - if (skilllv < 1) skilllv = 1; - sp = skill_get_sp(skillid,skilllv) * 2 / 3; - - if (status_charge(src, 0, sp)) { - switch (skill_get_casttype(skillid)) { - case CAST_GROUND: - skill_castend_pos2(src, target->x, target->y, skillid, skilllv, tick, flag); - break; - case CAST_NODAMAGE: - skill_castend_nodamage_id(src, target, skillid, skilllv, tick, flag); - break; - case CAST_DAMAGE: - skill_castend_damage_id(src, target, skillid, skilllv, tick, flag); - break; - } - } - } - if (sd) { - if (wd.flag&BF_SHORT && sc && sc->data[SC__AUTOSHADOWSPELL] && rnd()%100 < sc->data[SC__AUTOSHADOWSPELL]->val3 && - sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id != 0 && sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].flag == SKILL_FLAG_PLAGIARIZED) { - int r_skill = sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id, - r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2, type; - - if (r_skill != AL_HOLYLIGHT && r_skill != PR_MAGNUS) { - if ((type = skill_get_casttype(r_skill)) == CAST_GROUND) { - int maxcount = 0; - - if (!(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(r_skill)&UF_NOREITERATION) - type = -1; - - if (BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(r_skill)&UF_NOFOOTSET) - type = -1; - - if (BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(r_skill, r_lv)) > 0 - ) { - int v; - for (v=0; v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount; v++) { - if (sd->ud.skillunit[v]->skill_id == r_skill) - maxcount--; - } - if (maxcount == 0) - type = -1; - } - - if (type != CAST_GROUND) { - clif_skill_fail(sd,r_skill,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return wd.dmg_lv; - } - } - - sd->state.autocast = 1; - skill_consume_requirement(sd,r_skill,r_lv,3); - switch (type) { - case CAST_GROUND: - skill_castend_pos2(src, target->x, target->y, r_skill, r_lv, tick, flag); - break; - case CAST_NODAMAGE: - skill_castend_nodamage_id(src, target, r_skill, r_lv, tick, flag); - break; - case CAST_DAMAGE: - skill_castend_damage_id(src, target, r_skill, r_lv, tick, flag); - break; - } - sd->state.autocast = 0; + if (sd && sd->bonus.splash_range > 0 && damage > 0) + skill_castend_damage_id(src, target, 0, 1, tick, 0); + if ( target->type == BL_SKILL && damage > 0 ){ + TBL_SKILL *su = (TBL_SKILL*)target; + if( su->group && su->group->skill_id == HT_BLASTMINE) + skill_blown(src, target, 3, -1, 0); + } + map_freeblock_lock(); + + battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion); + if( tsc ) { + if( tsc->data[SC_DEVOTION] ) { + struct status_change_entry *sce = tsc->data[SC_DEVOTION]; + struct block_list *d_bl = map_id2bl(sce->val1); + + if( d_bl && ( + (d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == target->id) || + (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id) + ) && check_distance_bl(target, d_bl, sce->val3) ) + { + clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, 0, 0); + status_fix_damage(NULL, d_bl, damage, 0); + } + else + status_change_end(target, SC_DEVOTION, INVALID_TIMER); + } else if( tsc->data[SC_CIRCLE_OF_FIRE_OPTION] && (wd.flag&BF_SHORT) && target->type == BL_PC ) { + struct elemental_data *ed = ((TBL_PC*)target)->ed; + if( ed ) { + clif_skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, 6); + skill_attack(BF_MAGIC,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag); + } + } else if( tsc->data[SC_WATER_SCREEN_OPTION] && tsc->data[SC_WATER_SCREEN_OPTION]->val1 ) { + struct block_list *e_bl = map_id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1); + if( e_bl && !status_isdead(e_bl) ) { + clif_damage(e_bl,e_bl,tick,wd.amotion,wd.dmotion,damage,wd.div_,wd.type,wd.damage2); + status_damage(target,e_bl,damage,0,0,0); + // Just show damage in target. + clif_damage(src, target, tick, wd.amotion, wd.dmotion, damage, wd.div_, wd.type, wd.damage2 ); + map_freeblock_unlock(); + return ATK_NONE; + } + } + } + if (sc && sc->data[SC_AUTOSPELL] && rnd()%100 < sc->data[SC_AUTOSPELL]->val4) { + int sp = 0; + int skillid = sc->data[SC_AUTOSPELL]->val2; + int skilllv = sc->data[SC_AUTOSPELL]->val3; + int i = rnd()%100; + if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_SAGE) + i = 0; //Max chance, no skilllv reduction. [Skotlex] + if (i >= 50) skilllv -= 2; + else if (i >= 15) skilllv--; + if (skilllv < 1) skilllv = 1; + sp = skill_get_sp(skillid,skilllv) * 2 / 3; + + if (status_charge(src, 0, sp)) { + switch (skill_get_casttype(skillid)) { + case CAST_GROUND: + skill_castend_pos2(src, target->x, target->y, skillid, skilllv, tick, flag); + break; + case CAST_NODAMAGE: + skill_castend_nodamage_id(src, target, skillid, skilllv, tick, flag); + break; + case CAST_DAMAGE: + skill_castend_damage_id(src, target, skillid, skilllv, tick, flag); + break; + } + } + } + if (sd) { + if( wd.flag&BF_SHORT && sc && sc->data[SC__AUTOSHADOWSPELL] && rnd()%100 < sc->data[SC__AUTOSHADOWSPELL]->val3 && + sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id != 0 && sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].flag == SKILL_FLAG_PLAGIARIZED ) + { + int r_skill = sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id, + r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2, type; + + if (r_skill != AL_HOLYLIGHT && r_skill != PR_MAGNUS) { + if( (type = skill_get_casttype(r_skill)) == CAST_GROUND ) { + int maxcount = 0; + + if( !(BL_PC&battle_config.skill_reiteration) && + skill_get_unit_flag(r_skill)&UF_NOREITERATION ) + type = -1; + + if( BL_PC&battle_config.skill_nofootset && + skill_get_unit_flag(r_skill)&UF_NOFOOTSET ) + type = -1; + + if( BL_PC&battle_config.land_skill_limit && + (maxcount = skill_get_maxcount(r_skill, r_lv)) > 0 + ) { + int v; + for(v=0;v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount;v++) { + if(sd->ud.skillunit[v]->skill_id == r_skill) + maxcount--; + } + if( maxcount == 0 ) + type = -1; + } - sd->ud.canact_tick = tick + skill_delayfix(src, r_skill, r_lv); - clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, r_skill, r_lv), 0, 0, 1); - } - } + if( type != CAST_GROUND ){ + clif_skill_fail(sd,r_skill,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return wd.dmg_lv; + } + } - if (wd.flag & BF_WEAPON && src != target && damage > 0) { - if (battle_config.left_cardfix_to_right) - battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, is_boss(target)); - else - battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, is_boss(target)); - } - } - if (rdamage > 0 && !(tsc && tsc->data[SC_REFLECTDAMAGE])) { //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex] - if (tsd && src != target) - battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); - battle_delay_damage(tick, wd.amotion, target, src, 0, CR_REFLECTSHIELD, 0, rdamage, ATK_DEF, rdelay); - } + sd->state.autocast = 1; + skill_consume_requirement(sd,r_skill,r_lv,3); + switch( type ) { + case CAST_GROUND: + skill_castend_pos2(src, target->x, target->y, r_skill, r_lv, tick, flag); + break; + case CAST_NODAMAGE: + skill_castend_nodamage_id(src, target, r_skill, r_lv, tick, flag); + break; + case CAST_DAMAGE: + skill_castend_damage_id(src, target, r_skill, r_lv, tick, flag); + break; + } + sd->state.autocast = 0; - if (tsc) { - if (tsc->data[SC_POISONREACT] && - (rnd()%100 < tsc->data[SC_POISONREACT]->val3 - || sstatus->def_ele == ELE_POISON) && - // check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O; - status_check_skilluse(target, src, TF_POISON, 0) - ) { //Poison React - struct status_change_entry *sce = tsc->data[SC_POISONREACT]; - if (sstatus->def_ele == ELE_POISON) { - sce->val2 = 0; - skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0); - } else { - skill_attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, 0); - --sce->val2; - } - if (sce->val2 <= 0) - status_change_end(target, SC_POISONREACT, INVALID_TIMER); - } - } - map_freeblock_unlock(); - return wd.dmg_lv; + sd->ud.canact_tick = tick + skill_delayfix(src, r_skill, r_lv); + clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, r_skill, r_lv), 0, 0, 1); + } + } + + if (wd.flag & BF_WEAPON && src != target && damage > 0) { + if (battle_config.left_cardfix_to_right) + battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, is_boss(target)); + else + battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, is_boss(target)); + } + } + if (rdamage > 0 && !(tsc && tsc->data[SC_REFLECTDAMAGE])) { //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex] + if(tsd && src != target) + battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); + battle_delay_damage(tick, wd.amotion, target, src, 0, CR_REFLECTSHIELD, 0, rdamage, ATK_DEF, rdelay); + } + + if (tsc) { + if (tsc->data[SC_POISONREACT] && + (rnd()%100 < tsc->data[SC_POISONREACT]->val3 + || sstatus->def_ele == ELE_POISON) && +// check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O; + status_check_skilluse(target, src, TF_POISON, 0) + ) { //Poison React + struct status_change_entry *sce = tsc->data[SC_POISONREACT]; + if (sstatus->def_ele == ELE_POISON) { + sce->val2 = 0; + skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0); + } else { + skill_attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, 0); + --sce->val2; + } + if (sce->val2 <= 0) + status_change_end(target, SC_POISONREACT, INVALID_TIMER); + } + } + map_freeblock_unlock(); + return wd.dmg_lv; } int battle_check_undead(int race,int element) { - if (battle_config.undead_detect_type == 0) { - if (element == ELE_UNDEAD) - return 1; - } else if (battle_config.undead_detect_type == 1) { - if (race == RC_UNDEAD) - return 1; - } else { - if (element == ELE_UNDEAD || race == RC_UNDEAD) - return 1; - } - return 0; + if(battle_config.undead_detect_type == 0) { + if(element == ELE_UNDEAD) + return 1; + } + else if(battle_config.undead_detect_type == 1) { + if(race == RC_UNDEAD) + return 1; + } + else { + if(element == ELE_UNDEAD || race == RC_UNDEAD) + return 1; + } + return 0; } //Returns the upmost level master starting with the given object -struct block_list *battle_get_master(struct block_list *src) { - struct block_list *prev; //Used for infinite loop check (master of yourself?) - do { - prev = src; - switch (src->type) { - case BL_PET: - if (((TBL_PET *)src)->msd) - src = (struct block_list *)((TBL_PET *)src)->msd; - break; - case BL_MOB: - if (((TBL_MOB *)src)->master_id) - src = map_id2bl(((TBL_MOB *)src)->master_id); - break; - case BL_HOM: - if (((TBL_HOM *)src)->master) - src = (struct block_list *)((TBL_HOM *)src)->master; - break; - case BL_MER: - if (((TBL_MER *)src)->master) - src = (struct block_list *)((TBL_MER *)src)->master; - break; - case BL_ELEM: - if (((TBL_ELEM *)src)->master) - src = (struct block_list *)((TBL_ELEM *)src)->master; - break; - case BL_SKILL: - if (((TBL_SKILL *)src)->group && ((TBL_SKILL *)src)->group->src_id) - src = map_id2bl(((TBL_SKILL *)src)->group->src_id); - break; - } - } while (src && src != prev); - return prev; +struct block_list* battle_get_master(struct block_list *src) +{ + struct block_list *prev; //Used for infinite loop check (master of yourself?) + do { + prev = src; + switch (src->type) { + case BL_PET: + if (((TBL_PET*)src)->msd) + src = (struct block_list*)((TBL_PET*)src)->msd; + break; + case BL_MOB: + if (((TBL_MOB*)src)->master_id) + src = map_id2bl(((TBL_MOB*)src)->master_id); + break; + case BL_HOM: + if (((TBL_HOM*)src)->master) + src = (struct block_list*)((TBL_HOM*)src)->master; + break; + case BL_MER: + if (((TBL_MER*)src)->master) + src = (struct block_list*)((TBL_MER*)src)->master; + break; + case BL_ELEM: + if (((TBL_ELEM*)src)->master) + src = (struct block_list*)((TBL_ELEM*)src)->master; + break; + case BL_SKILL: + if (((TBL_SKILL*)src)->group && ((TBL_SKILL*)src)->group->src_id) + src = map_id2bl(((TBL_SKILL*)src)->group->src_id); + break; + } + } while (src && src != prev); + return prev; } /*========================================== @@ -5044,309 +5071,324 @@ struct block_list *battle_get_master(struct block_list *src) { * -1: flag fails * 0: Invalid target (non-targetable ever) *------------------------------------------*/ -int battle_check_target(struct block_list *src, struct block_list *target,int flag) +int battle_check_target( struct block_list *src, struct block_list *target,int flag) { - int m,state = 0; //Initial state none - int strip_enemy = 1; //Flag which marks whether to remove the BCT_ENEMY status if it's also friend/ally. - struct block_list *s_bl = src, *t_bl = target; - - nullpo_ret(src); - nullpo_ret(target); - - m = target->m; - - //t_bl/s_bl hold the 'master' of the attack, while src/target are the actual - //objects involved. - if ((t_bl = battle_get_master(target)) == NULL) - t_bl = target; - - if ((s_bl = battle_get_master(src)) == NULL) - s_bl = src; - - if (s_bl->type == BL_PC) { - switch (t_bl->type) { - case BL_MOB: // Source => PC, Target => MOB - if (pc_has_permission((TBL_PC *)s_bl, PC_PERM_DISABLE_PVM)) - return 0; - break; - case BL_PC: - if (pc_has_permission((TBL_PC *)s_bl, PC_PERM_DISABLE_PVP)) - return 0; - break; - default:/* anything else goes */ - break; - } - } + int m,state = 0; //Initial state none + int strip_enemy = 1; //Flag which marks whether to remove the BCT_ENEMY status if it's also friend/ally. + struct block_list *s_bl = src, *t_bl = target; + + nullpo_ret(src); + nullpo_ret(target); + + m = target->m; + + //t_bl/s_bl hold the 'master' of the attack, while src/target are the actual + //objects involved. + if( (t_bl = battle_get_master(target)) == NULL ) + t_bl = target; + + if( (s_bl = battle_get_master(src)) == NULL ) + s_bl = src; + + if ( s_bl->type == BL_PC ) { + switch( t_bl->type ) { + case BL_MOB: // Source => PC, Target => MOB + if ( pc_has_permission((TBL_PC*)s_bl, PC_PERM_DISABLE_PVM) ) + return 0; + break; + case BL_PC: + if (pc_has_permission((TBL_PC*)s_bl, PC_PERM_DISABLE_PVP)) + return 0; + break; + default:/* anything else goes */ + break; + } + } - switch (target->type) { // Checks on actual target - case BL_PC: { - struct status_change *sc = status_get_sc(src); - if (((TBL_PC *)target)->invincible_timer != INVALID_TIMER || pc_isinvisible((TBL_PC *)target)) - return -1; //Cannot be targeted yet. - if (sc && sc->count) { - if (sc->data[SC_VOICEOFSIREN] && sc->data[SC_VOICEOFSIREN]->val2 == target->id) - return -1; - } - } - break; - case BL_MOB: - if (((((TBL_MOB *)target)->special_state.ai == 2 || //Marine Spheres - (((TBL_MOB *)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras - s_bl->type == BL_PC && src->type != BL_MOB) || ((TBL_MOB *)target)->special_state.ai == 4) { //Zanzoe - //Targettable by players - state |= BCT_ENEMY; - strip_enemy = 0; - } - break; - case BL_SKILL: { - TBL_SKILL *su = (TBL_SKILL *)target; - if (!su->group) - return 0; - if (skill_get_inf2(su->group->skill_id)&INF2_TRAP) { //Only a few skills can target traps... - switch (battle_getcurrentskill(src)) { - case RK_DRAGONBREATH:// it can only hit traps in pvp/gvg maps - if (!map[m].flag.pvp && !map[m].flag.gvg) - break; - case 0://you can hit them without skills - case MA_REMOVETRAP: - case HT_REMOVETRAP: - case AC_SHOWER: - case MA_SHOWER: - case WZ_SIGHTRASHER: - case WZ_SIGHTBLASTER: - case SM_MAGNUM: - case MS_MAGNUM: - case RA_DETONATOR: - case RA_SENSITIVEKEEN: - case GN_CRAZYWEED_ATK: - case RK_STORMBLAST: - case RK_PHANTOMTHRUST: - case SR_RAMPAGEBLASTER: - case NC_COLDSLOWER: - case NC_SELFDESTRUCTION: + switch( target->type ) { // Checks on actual target + case BL_PC: { + struct status_change* sc = status_get_sc(src); + if (((TBL_PC*)target)->invincible_timer != INVALID_TIMER || pc_isinvisible((TBL_PC*)target)) + return -1; //Cannot be targeted yet. + if( sc && sc->count ) { + if( sc->data[SC_VOICEOFSIREN] && sc->data[SC_VOICEOFSIREN]->val2 == target->id ) + return -1; + } + } + break; + case BL_MOB: + if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres + (((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras + s_bl->type == BL_PC && src->type != BL_MOB) || ((TBL_MOB*)target)->special_state.ai == 4) //Zanzoe + { //Targettable by players + state |= BCT_ENEMY; + strip_enemy = 0; + } + break; + case BL_SKILL: + { + TBL_SKILL *su = (TBL_SKILL*)target; + if( !su->group ) + return 0; + if( skill_get_inf2(su->group->skill_id)&INF2_TRAP ) { //Only a few skills can target traps... + switch( battle_getcurrentskill(src) ) { + case RK_DRAGONBREATH:// it can only hit traps in pvp/gvg maps + if( !map[m].flag.pvp && !map[m].flag.gvg ) + break; + case 0://you can hit them without skills + case MA_REMOVETRAP: + case HT_REMOVETRAP: + case AC_SHOWER: + case MA_SHOWER: + case WZ_SIGHTRASHER: + case WZ_SIGHTBLASTER: + case SM_MAGNUM: + case MS_MAGNUM: + case RA_DETONATOR: + case RA_SENSITIVEKEEN: + case GN_CRAZYWEED_ATK: + case RK_STORMBLAST: + case RK_PHANTOMTHRUST: + case SR_RAMPAGEBLASTER: + case NC_COLDSLOWER: + case NC_SELFDESTRUCTION: #ifdef RENEWAL - case KN_BOWLINGBASH: - case KN_SPEARSTAB: - case LK_SPIRALPIERCE: - case ML_SPIRALPIERCE: - case MO_FINGEROFFENSIVE: - case MO_INVESTIGATE: - case MO_TRIPLEATTACK: - case MO_EXTREMITYFIST: - case CR_HOLYCROSS: - case ASC_METEORASSAULT: - case RG_RAID: - case MC_CARTREVOLUTION: + case KN_BOWLINGBASH: + case KN_SPEARSTAB: + case LK_SPIRALPIERCE: + case ML_SPIRALPIERCE: + case MO_FINGEROFFENSIVE: + case MO_INVESTIGATE: + case MO_TRIPLEATTACK: + case MO_EXTREMITYFIST: + case CR_HOLYCROSS: + case ASC_METEORASSAULT: + case RG_RAID: + case MC_CARTREVOLUTION: #endif - state |= BCT_ENEMY; - strip_enemy = 0; - break; - default: - if (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) { - state |= BCT_ENEMY; - strip_enemy = 0; - } else - return 0; - } - } else if (su->group->skill_id==WZ_ICEWALL || - su->group->skill_id == GN_WALLOFTHORN) { - state |= BCT_ENEMY; - strip_enemy = 0; - } else //Excepting traps and icewall, you should not be able to target skills. - return 0; - } - break; - //Valid targets with no special checks here. - case BL_MER: - case BL_HOM: - case BL_ELEM: - break; - //All else not specified is an invalid target. - default: - return 0; + state |= BCT_ENEMY; + strip_enemy = 0; + break; + default: + if(su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD){ + state |= BCT_ENEMY; + strip_enemy = 0; + }else + return 0; + } + } else if (su->group->skill_id==WZ_ICEWALL || + su->group->skill_id == GN_WALLOFTHORN) { + state |= BCT_ENEMY; + strip_enemy = 0; + } else //Excepting traps and icewall, you should not be able to target skills. + return 0; + } + break; + //Valid targets with no special checks here. + case BL_MER: + case BL_HOM: + case BL_ELEM: + break; + //All else not specified is an invalid target. + default: + return 0; } //end switch actual target - switch (t_bl->type) { - //Checks on target master - case BL_PC: { - struct map_session_data *sd; - if (t_bl == s_bl) break; - sd = BL_CAST(BL_PC, t_bl); - - if (sd->state.monster_ignore && flag&BCT_ENEMY) - return 0; // Global inminuty only to Attacks - if (sd->status.karma && s_bl->type == BL_PC && ((TBL_PC *)s_bl)->status.karma) - state |= BCT_ENEMY; // Characters with bad karma may fight amongst them - if (sd->state.killable) { - state |= BCT_ENEMY; // Everything can kill it - strip_enemy = 0; - } - break; - } - case BL_MOB: { - struct mob_data *md = BL_CAST(BL_MOB, t_bl); + switch( t_bl->type ) + { //Checks on target master + case BL_PC: + { + struct map_session_data *sd; + if( t_bl == s_bl ) break; + sd = BL_CAST(BL_PC, t_bl); + + if( sd->state.monster_ignore && flag&BCT_ENEMY ) + return 0; // Global inminuty only to Attacks + if( sd->status.karma && s_bl->type == BL_PC && ((TBL_PC*)s_bl)->status.karma ) + state |= BCT_ENEMY; // Characters with bad karma may fight amongst them + if( sd->state.killable ) { + state |= BCT_ENEMY; // Everything can kill it + strip_enemy = 0; + } + break; + } + case BL_MOB: + { + struct mob_data *md = BL_CAST(BL_MOB, t_bl); - if (!((agit_flag || agit2_flag) && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id) - return 0; // Disable guardians/emperiums owned by Guilds on non-woe times. - break; - } - default: - break; //other type doesn't have slave yet + if( !((agit_flag || agit2_flag) && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id ) + return 0; // Disable guardians/emperiums owned by Guilds on non-woe times. + break; + } + default: break; //other type doesn't have slave yet } //end switch master target - switch (src->type) { //Checks on actual src type - case BL_PET: - if (t_bl->type != BL_MOB && flag&BCT_ENEMY) - return 0; //Pet may not attack non-mobs. - if (t_bl->type == BL_MOB && ((TBL_MOB *)t_bl)->guardian_data && flag&BCT_ENEMY) - return 0; //pet may not attack Guardians/Emperium - break; - case BL_SKILL: { - struct skill_unit *su = (struct skill_unit *)src; - if (!su->group) - return 0; - - if (su->group->src_id == target->id) { - int inf2 = skill_get_inf2(su->group->skill_id); - if (inf2&INF2_NO_TARGET_SELF) - return -1; - if (inf2&INF2_TARGET_SELF) - return 1; - } - } - break; - case BL_MER: - if (t_bl->type == BL_MOB && ((TBL_MOB *)t_bl)->class_ == MOBID_EMPERIUM && flag&BCT_ENEMY) - return 0; //mercenary may not attack Emperium - break; + switch( src->type ) { //Checks on actual src type + case BL_PET: + if (t_bl->type != BL_MOB && flag&BCT_ENEMY) + return 0; //Pet may not attack non-mobs. + if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data && flag&BCT_ENEMY) + return 0; //pet may not attack Guardians/Emperium + break; + case BL_SKILL: { + struct skill_unit *su = (struct skill_unit *)src; + if (!su->group) + return 0; + + if (su->group->src_id == target->id) { + int inf2 = skill_get_inf2(su->group->skill_id); + if (inf2&INF2_NO_TARGET_SELF) + return -1; + if (inf2&INF2_TARGET_SELF) + return 1; + } + } + break; + case BL_MER: + if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->class_ == MOBID_EMPERIUM && flag&BCT_ENEMY) + return 0; //mercenary may not attack Emperium + break; } //end switch actual src - switch (s_bl->type) { - //Checks on source master - case BL_PC: { - struct map_session_data *sd = BL_CAST(BL_PC, s_bl); - if (s_bl != t_bl) { - if (sd->state.killer) { - state |= BCT_ENEMY; // Can kill anything - strip_enemy = 0; - } else if (sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m)))) { - if (t_bl->type == BL_PC && (sd->duel_group == ((TBL_PC *)t_bl)->duel_group)) - return (BCT_ENEMY&flag)?1:-1; // Duel targets can ONLY be your enemy, nothing else. - else - return 0; // You can't target anything out of your duel - } - } - if (map_flag_gvg(m) && !sd->status.guild_id && t_bl->type == BL_MOB && ((TBL_MOB *)t_bl)->class_ == MOBID_EMPERIUM) - return 0; //If you don't belong to a guild, can't target emperium. - if (t_bl->type != BL_PC) - state |= BCT_ENEMY; //Natural enemy. - break; - } - case BL_MOB: { - struct mob_data *md = BL_CAST(BL_MOB, s_bl); - if (!((agit_flag || agit2_flag) && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id) - return 0; // Disable guardians/emperium owned by Guilds on non-woe times. - - if (!md->special_state.ai) { - //Normal mobs - if ( - (target->type == BL_MOB && t_bl->type == BL_PC && (((TBL_MOB *)target)->special_state.ai != 4 && ((TBL_MOB *)target)->special_state.ai != 1)) || - (t_bl->type == BL_MOB && !((TBL_MOB *)t_bl)->special_state.ai) - ) - state |= BCT_PARTY; //Normal mobs with no ai are friends. - else - state |= BCT_ENEMY; //However, all else are enemies. - } else { - if (t_bl->type == BL_MOB && !((TBL_MOB *)t_bl)->special_state.ai) - state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs. - } - break; - } - default: - //Need some sort of default behaviour for unhandled types. - if (t_bl->type != s_bl->type) - state |= BCT_ENEMY; - break; + switch( s_bl->type ) + { //Checks on source master + case BL_PC: + { + struct map_session_data *sd = BL_CAST(BL_PC, s_bl); + if( s_bl != t_bl ) + { + if( sd->state.killer ) + { + state |= BCT_ENEMY; // Can kill anything + strip_enemy = 0; + } + else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) ) + { + if( t_bl->type == BL_PC && (sd->duel_group == ((TBL_PC*)t_bl)->duel_group) ) + return (BCT_ENEMY&flag)?1:-1; // Duel targets can ONLY be your enemy, nothing else. + else + return 0; // You can't target anything out of your duel + } + } + if( map_flag_gvg(m) && !sd->status.guild_id && t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->class_ == MOBID_EMPERIUM ) + return 0; //If you don't belong to a guild, can't target emperium. + if( t_bl->type != BL_PC ) + state |= BCT_ENEMY; //Natural enemy. + break; + } + case BL_MOB: + { + struct mob_data *md = BL_CAST(BL_MOB, s_bl); + if( !((agit_flag || agit2_flag) && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id ) + return 0; // Disable guardians/emperium owned by Guilds on non-woe times. + + if( !md->special_state.ai ) + { //Normal mobs + if( + ( target->type == BL_MOB && t_bl->type == BL_PC && ( ((TBL_MOB*)target)->special_state.ai != 4 && ((TBL_MOB*)target)->special_state.ai != 1 ) ) || + ( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai ) + ) + state |= BCT_PARTY; //Normal mobs with no ai are friends. + else + state |= BCT_ENEMY; //However, all else are enemies. + } + else + { + if( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai ) + state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs. + } + break; + } + default: + //Need some sort of default behaviour for unhandled types. + if (t_bl->type != s_bl->type) + state |= BCT_ENEMY; + break; } //end switch on src master - if ((flag&BCT_ALL) == BCT_ALL) { - //All actually stands for all attackable chars - if (target->type&BL_CHAR) - return 1; - else - return -1; - } - if (flag == BCT_NOONE) //Why would someone use this? no clue. - return -1; - - if (t_bl == s_bl) { - //No need for further testing. - state |= BCT_SELF|BCT_PARTY|BCT_GUILD; - if (state&BCT_ENEMY && strip_enemy) - state&=~BCT_ENEMY; - return (flag&state)?1:-1; - } + if( (flag&BCT_ALL) == BCT_ALL ) + { //All actually stands for all attackable chars + if( target->type&BL_CHAR ) + return 1; + else + return -1; + } + if( flag == BCT_NOONE ) //Why would someone use this? no clue. + return -1; + + if( t_bl == s_bl ) + { //No need for further testing. + state |= BCT_SELF|BCT_PARTY|BCT_GUILD; + if( state&BCT_ENEMY && strip_enemy ) + state&=~BCT_ENEMY; + return (flag&state)?1:-1; + } - if (map_flag_vs(m)) { - //Check rivalry settings. - int sbg_id = 0, tbg_id = 0; - if (map[m].flag.battleground) { - sbg_id = bg_team_get_id(s_bl); - tbg_id = bg_team_get_id(t_bl); - } - if (flag&(BCT_PARTY|BCT_ENEMY)) { - int s_party = status_get_party_id(s_bl); - if (s_party && s_party == status_get_party_id(t_bl) && !(map[m].flag.pvp && map[m].flag.pvp_noparty) && !(map_flag_gvg(m) && map[m].flag.gvg_noparty) && (!map[m].flag.battleground || sbg_id == tbg_id)) - state |= BCT_PARTY; - else - state |= BCT_ENEMY; - } - if (flag&(BCT_GUILD|BCT_ENEMY)) { - int s_guild = status_get_guild_id(s_bl); - int t_guild = status_get_guild_id(t_bl); - if (!(map[m].flag.pvp && map[m].flag.pvp_noguild) && s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)) && (!map[m].flag.battleground || sbg_id == tbg_id)) - state |= BCT_GUILD; - else - state |= BCT_ENEMY; - } - if (state&BCT_ENEMY && map[m].flag.battleground && sbg_id && sbg_id == tbg_id) - state &= ~BCT_ENEMY; - - if (state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) && s_bl->type == BL_PC && t_bl->type == BL_PC) { - // Prevent novice engagement on pk_mode (feature by Valaris) - TBL_PC *sd = (TBL_PC *)s_bl, *sd2 = (TBL_PC *)t_bl; - if ( - (sd->class_&MAPID_UPPERMASK) == MAPID_NOVICE || - (sd2->class_&MAPID_UPPERMASK) == MAPID_NOVICE || - (int)sd->status.base_level < battle_config.pk_min_level || - (int)sd2->status.base_level < battle_config.pk_min_level || - (battle_config.pk_level_range && abs((int)sd->status.base_level - (int)sd2->status.base_level) > battle_config.pk_level_range) - ) - state &= ~BCT_ENEMY; - } + if( map_flag_vs(m) ) + { //Check rivalry settings. + int sbg_id = 0, tbg_id = 0; + if( map[m].flag.battleground ) + { + sbg_id = bg_team_get_id(s_bl); + tbg_id = bg_team_get_id(t_bl); + } + if( flag&(BCT_PARTY|BCT_ENEMY) ) + { + int s_party = status_get_party_id(s_bl); + if( s_party && s_party == status_get_party_id(t_bl) && !(map[m].flag.pvp && map[m].flag.pvp_noparty) && !(map_flag_gvg(m) && map[m].flag.gvg_noparty) && (!map[m].flag.battleground || sbg_id == tbg_id) ) + state |= BCT_PARTY; + else + state |= BCT_ENEMY; + } + if( flag&(BCT_GUILD|BCT_ENEMY) ) + { + int s_guild = status_get_guild_id(s_bl); + int t_guild = status_get_guild_id(t_bl); + if( !(map[m].flag.pvp && map[m].flag.pvp_noguild) && s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)) && (!map[m].flag.battleground || sbg_id == tbg_id) ) + state |= BCT_GUILD; + else + state |= BCT_ENEMY; + } + if( state&BCT_ENEMY && map[m].flag.battleground && sbg_id && sbg_id == tbg_id ) + state &= ~BCT_ENEMY; + + if( state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) && s_bl->type == BL_PC && t_bl->type == BL_PC ) + { // Prevent novice engagement on pk_mode (feature by Valaris) + TBL_PC *sd = (TBL_PC*)s_bl, *sd2 = (TBL_PC*)t_bl; + if ( + (sd->class_&MAPID_UPPERMASK) == MAPID_NOVICE || + (sd2->class_&MAPID_UPPERMASK) == MAPID_NOVICE || + (int)sd->status.base_level < battle_config.pk_min_level || + (int)sd2->status.base_level < battle_config.pk_min_level || + (battle_config.pk_level_range && abs((int)sd->status.base_level - (int)sd2->status.base_level) > battle_config.pk_level_range) + ) + state &= ~BCT_ENEMY; + } }//end map_flag_vs chk rivality - else { - //Non pvp/gvg, check party/guild settings. - if (flag&BCT_PARTY || state&BCT_ENEMY) { - int s_party = status_get_party_id(s_bl); - if (s_party && s_party == status_get_party_id(t_bl)) - state |= BCT_PARTY; - } - if (flag&BCT_GUILD || state&BCT_ENEMY) { - int s_guild = status_get_guild_id(s_bl); - int t_guild = status_get_guild_id(t_bl); - if (s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild))) - state |= BCT_GUILD; - } + else + { //Non pvp/gvg, check party/guild settings. + if( flag&BCT_PARTY || state&BCT_ENEMY ) + { + int s_party = status_get_party_id(s_bl); + if(s_party && s_party == status_get_party_id(t_bl)) + state |= BCT_PARTY; + } + if( flag&BCT_GUILD || state&BCT_ENEMY ) + { + int s_guild = status_get_guild_id(s_bl); + int t_guild = status_get_guild_id(t_bl); + if(s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild))) + state |= BCT_GUILD; + } } //end non pvp/gvg chk rivality - if (!state) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral. - state = BCT_NEUTRAL; - //Alliance state takes precedence over enemy one. - else if (state&BCT_ENEMY && strip_enemy && state&(BCT_SELF|BCT_PARTY|BCT_GUILD)) - state&=~BCT_ENEMY; + if( !state ) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral. + state = BCT_NEUTRAL; + //Alliance state takes precedence over enemy one. + else if( state&BCT_ENEMY && strip_enemy && state&(BCT_SELF|BCT_PARTY|BCT_GUILD) ) + state&=~BCT_ENEMY; - return (flag&state)?1:-1; + return (flag&state)?1:-1; } /*========================================== * Check if can attack from this range @@ -5354,687 +5396,689 @@ int battle_check_target(struct block_list *src, struct block_list *target,int fl *------------------------------------------*/ bool battle_check_range(struct block_list *src, struct block_list *bl, int range) { - int d; - nullpo_retr(false, src); - nullpo_retr(false, bl); + int d; + nullpo_retr(false, src); + nullpo_retr(false, bl); - if (src->m != bl->m) - return false; + if( src->m != bl->m ) + return false; #ifndef CIRCULAR_AREA - if (src->type == BL_PC) { // Range for players' attacks and skills should always have a circular check. [Angezerus] - int dx = src->x - bl->x, dy = src->y - bl->y; - if (!check_distance(dx, dy, range)) - return false; - } else + if( src->type == BL_PC ) { // Range for players' attacks and skills should always have a circular check. [Angezerus] + int dx = src->x - bl->x, dy = src->y - bl->y; + if( !check_distance(dx, dy, range) ) + return false; + } else #endif - if (!check_distance_bl(src, bl, range)) - return false; + if( !check_distance_bl(src, bl, range) ) + return false; - if ((d = distance_bl(src, bl)) < 2) - return true; // No need for path checking. + if( (d = distance_bl(src, bl)) < 2 ) + return true; // No need for path checking. - if (d > AREA_SIZE) - return false; // Avoid targetting objects beyond your range of sight. + if( d > AREA_SIZE ) + return false; // Avoid targetting objects beyond your range of sight. - return path_search_long(NULL,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL); + return path_search_long(NULL,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL); } static const struct _battle_data { - const char *str; - int *val; - int defval; - int min; - int max; + const char* str; + int* val; + int defval; + int min; + int max; } battle_data[] = { - { "warp_point_debug", &battle_config.warp_point_debug, 0, 0, 1, }, - { "enable_critical", &battle_config.enable_critical, BL_PC, BL_NUL, BL_ALL, }, - { "mob_critical_rate", &battle_config.mob_critical_rate, 100, 0, INT_MAX, }, - { "critical_rate", &battle_config.critical_rate, 100, 0, INT_MAX, }, - { "enable_baseatk", &battle_config.enable_baseatk, BL_PC|BL_HOM, BL_NUL, BL_ALL, }, - { "enable_perfect_flee", &battle_config.enable_perfect_flee, BL_PC|BL_PET, BL_NUL, BL_ALL, }, - { "casting_rate", &battle_config.cast_rate, 100, 0, INT_MAX, }, - { "delay_rate", &battle_config.delay_rate, 100, 0, INT_MAX, }, - { "delay_dependon_dex", &battle_config.delay_dependon_dex, 0, 0, 1, }, - { "delay_dependon_agi", &battle_config.delay_dependon_agi, 0, 0, 1, }, - { "skill_delay_attack_enable", &battle_config.sdelay_attack_enable, 0, 0, 1, }, - { "left_cardfix_to_right", &battle_config.left_cardfix_to_right, 0, 0, 1, }, - { "skill_add_range", &battle_config.skill_add_range, 0, 0, INT_MAX, }, - { "skill_out_range_consume", &battle_config.skill_out_range_consume, 1, 0, 1, }, - { "skillrange_by_distance", &battle_config.skillrange_by_distance, ~BL_PC, BL_NUL, BL_ALL, }, - { "skillrange_from_weapon", &battle_config.use_weapon_skill_range, ~BL_PC, BL_NUL, BL_ALL, }, - { "player_damage_delay_rate", &battle_config.pc_damage_delay_rate, 100, 0, INT_MAX, }, - { "defunit_not_enemy", &battle_config.defnotenemy, 0, 0, 1, }, - { "gvg_traps_target_all", &battle_config.vs_traps_bctall, BL_PC, BL_NUL, BL_ALL, }, - { "traps_setting", &battle_config.traps_setting, 0, 0, 1, }, - { "summon_flora_setting", &battle_config.summon_flora, 1|2, 0, 1|2, }, - { "clear_skills_on_death", &battle_config.clear_unit_ondeath, BL_NUL, BL_NUL, BL_ALL, }, - { "clear_skills_on_warp", &battle_config.clear_unit_onwarp, BL_ALL, BL_NUL, BL_ALL, }, - { "random_monster_checklv", &battle_config.random_monster_checklv, 0, 0, 1, }, - { "attribute_recover", &battle_config.attr_recover, 1, 0, 1, }, - { "flooritem_lifetime", &battle_config.flooritem_lifetime, 60000, 1000, INT_MAX, }, - { "item_auto_get", &battle_config.item_auto_get, 0, 0, 1, }, - { "item_first_get_time", &battle_config.item_first_get_time, 3000, 0, INT_MAX, }, - { "item_second_get_time", &battle_config.item_second_get_time, 1000, 0, INT_MAX, }, - { "item_third_get_time", &battle_config.item_third_get_time, 1000, 0, INT_MAX, }, - { "mvp_item_first_get_time", &battle_config.mvp_item_first_get_time, 10000, 0, INT_MAX, }, - { "mvp_item_second_get_time", &battle_config.mvp_item_second_get_time, 10000, 0, INT_MAX, }, - { "mvp_item_third_get_time", &battle_config.mvp_item_third_get_time, 2000, 0, INT_MAX, }, - { "drop_rate0item", &battle_config.drop_rate0item, 0, 0, 1, }, - { "base_exp_rate", &battle_config.base_exp_rate, 100, 0, INT_MAX, }, - { "job_exp_rate", &battle_config.job_exp_rate, 100, 0, INT_MAX, }, - { "pvp_exp", &battle_config.pvp_exp, 1, 0, 1, }, - { "death_penalty_type", &battle_config.death_penalty_type, 0, 0, 2, }, - { "death_penalty_base", &battle_config.death_penalty_base, 0, 0, INT_MAX, }, - { "death_penalty_job", &battle_config.death_penalty_job, 0, 0, INT_MAX, }, - { "zeny_penalty", &battle_config.zeny_penalty, 0, 0, INT_MAX, }, - { "hp_rate", &battle_config.hp_rate, 100, 1, INT_MAX, }, - { "sp_rate", &battle_config.sp_rate, 100, 1, INT_MAX, }, - { "restart_hp_rate", &battle_config.restart_hp_rate, 0, 0, 100, }, - { "restart_sp_rate", &battle_config.restart_sp_rate, 0, 0, 100, }, - { "guild_aura", &battle_config.guild_aura, 31, 0, 31, }, - { "mvp_hp_rate", &battle_config.mvp_hp_rate, 100, 1, INT_MAX, }, - { "mvp_exp_rate", &battle_config.mvp_exp_rate, 100, 0, INT_MAX, }, - { "monster_hp_rate", &battle_config.monster_hp_rate, 100, 1, INT_MAX, }, - { "monster_max_aspd", &battle_config.monster_max_aspd, 199, 100, 199, }, - { "view_range_rate", &battle_config.view_range_rate, 100, 0, INT_MAX, }, - { "chase_range_rate", &battle_config.chase_range_rate, 100, 0, INT_MAX, }, - { "gtb_sc_immunity", &battle_config.gtb_sc_immunity, 50, 0, INT_MAX, }, - { "guild_max_castles", &battle_config.guild_max_castles, 0, 0, INT_MAX, }, - { "guild_skill_relog_delay", &battle_config.guild_skill_relog_delay, 0, 0, 1, }, - { "emergency_call", &battle_config.emergency_call, 11, 0, 31, }, - { "atcommand_spawn_quantity_limit", &battle_config.atc_spawn_quantity_limit, 100, 0, INT_MAX, }, - { "atcommand_slave_clone_limit", &battle_config.atc_slave_clone_limit, 25, 0, INT_MAX, }, - { "partial_name_scan", &battle_config.partial_name_scan, 0, 0, 1, }, - { "player_skillfree", &battle_config.skillfree, 0, 0, 1, }, - { "player_skillup_limit", &battle_config.skillup_limit, 1, 0, 1, }, - { "weapon_produce_rate", &battle_config.wp_rate, 100, 0, INT_MAX, }, - { "potion_produce_rate", &battle_config.pp_rate, 100, 0, INT_MAX, }, - { "monster_active_enable", &battle_config.monster_active_enable, 1, 0, 1, }, - { "monster_damage_delay_rate", &battle_config.monster_damage_delay_rate, 100, 0, INT_MAX, }, - { "monster_loot_type", &battle_config.monster_loot_type, 0, 0, 1, }, - // { "mob_skill_use", &battle_config.mob_skill_use, 1, 0, 1, }, //Deprecated - { "mob_skill_rate", &battle_config.mob_skill_rate, 100, 0, INT_MAX, }, - { "mob_skill_delay", &battle_config.mob_skill_delay, 100, 0, INT_MAX, }, - { "mob_count_rate", &battle_config.mob_count_rate, 100, 0, INT_MAX, }, - { "mob_spawn_delay", &battle_config.mob_spawn_delay, 100, 0, INT_MAX, }, - { "plant_spawn_delay", &battle_config.plant_spawn_delay, 100, 0, INT_MAX, }, - { "boss_spawn_delay", &battle_config.boss_spawn_delay, 100, 0, INT_MAX, }, - { "no_spawn_on_player", &battle_config.no_spawn_on_player, 0, 0, 100, }, - { "force_random_spawn", &battle_config.force_random_spawn, 0, 0, 1, }, - { "slaves_inherit_mode", &battle_config.slaves_inherit_mode, 2, 0, 3, }, - { "slaves_inherit_speed", &battle_config.slaves_inherit_speed, 3, 0, 3, }, - { "summons_trigger_autospells", &battle_config.summons_trigger_autospells, 1, 0, 1, }, - { "pc_damage_walk_delay_rate", &battle_config.pc_walk_delay_rate, 20, 0, INT_MAX, }, - { "damage_walk_delay_rate", &battle_config.walk_delay_rate, 100, 0, INT_MAX, }, - { "multihit_delay", &battle_config.multihit_delay, 80, 0, INT_MAX, }, - { "quest_skill_learn", &battle_config.quest_skill_learn, 0, 0, 1, }, - { "quest_skill_reset", &battle_config.quest_skill_reset, 0, 0, 1, }, - { "basic_skill_check", &battle_config.basic_skill_check, 1, 0, 1, }, - { "guild_emperium_check", &battle_config.guild_emperium_check, 1, 0, 1, }, - { "guild_exp_limit", &battle_config.guild_exp_limit, 50, 0, 99, }, - { "player_invincible_time", &battle_config.pc_invincible_time, 5000, 0, INT_MAX, }, - { "pet_catch_rate", &battle_config.pet_catch_rate, 100, 0, INT_MAX, }, - { "pet_rename", &battle_config.pet_rename, 0, 0, 1, }, - { "pet_friendly_rate", &battle_config.pet_friendly_rate, 100, 0, INT_MAX, }, - { "pet_hungry_delay_rate", &battle_config.pet_hungry_delay_rate, 100, 10, INT_MAX, }, - { "pet_hungry_friendly_decrease", &battle_config.pet_hungry_friendly_decrease, 5, 0, INT_MAX, }, - { "pet_status_support", &battle_config.pet_status_support, 0, 0, 1, }, - { "pet_attack_support", &battle_config.pet_attack_support, 0, 0, 1, }, - { "pet_damage_support", &battle_config.pet_damage_support, 0, 0, 1, }, - { "pet_support_min_friendly", &battle_config.pet_support_min_friendly, 900, 0, 950, }, - { "pet_equip_min_friendly", &battle_config.pet_equip_min_friendly, 900, 0, 950, }, - { "pet_support_rate", &battle_config.pet_support_rate, 100, 0, INT_MAX, }, - { "pet_attack_exp_to_master", &battle_config.pet_attack_exp_to_master, 0, 0, 1, }, - { "pet_attack_exp_rate", &battle_config.pet_attack_exp_rate, 100, 0, INT_MAX, }, - { "pet_lv_rate", &battle_config.pet_lv_rate, 0, 0, INT_MAX, }, - { "pet_max_stats", &battle_config.pet_max_stats, 99, 0, INT_MAX, }, - { "pet_max_atk1", &battle_config.pet_max_atk1, 750, 0, INT_MAX, }, - { "pet_max_atk2", &battle_config.pet_max_atk2, 1000, 0, INT_MAX, }, - { "pet_disable_in_gvg", &battle_config.pet_no_gvg, 0, 0, 1, }, - { "skill_min_damage", &battle_config.skill_min_damage, 2|4, 0, 1|2|4, }, - { "finger_offensive_type", &battle_config.finger_offensive_type, 0, 0, 1, }, - { "heal_exp", &battle_config.heal_exp, 0, 0, INT_MAX, }, - { "resurrection_exp", &battle_config.resurrection_exp, 0, 0, INT_MAX, }, - { "shop_exp", &battle_config.shop_exp, 0, 0, INT_MAX, }, - { "max_heal_lv", &battle_config.max_heal_lv, 11, 1, INT_MAX, }, - { "max_heal", &battle_config.max_heal, 9999, 0, INT_MAX, }, - { "combo_delay_rate", &battle_config.combo_delay_rate, 100, 0, INT_MAX, }, - { "item_check", &battle_config.item_check, 0, 0, 1, }, - { "item_use_interval", &battle_config.item_use_interval, 100, 0, INT_MAX, }, - { "cashfood_use_interval", &battle_config.cashfood_use_interval, 60000, 0, INT_MAX, }, - { "wedding_modifydisplay", &battle_config.wedding_modifydisplay, 0, 0, 1, }, - { "wedding_ignorepalette", &battle_config.wedding_ignorepalette, 0, 0, 1, }, - { "xmas_ignorepalette", &battle_config.xmas_ignorepalette, 0, 0, 1, }, - { "summer_ignorepalette", &battle_config.summer_ignorepalette, 0, 0, 1, }, - { "natural_healhp_interval", &battle_config.natural_healhp_interval, 6000, NATURAL_HEAL_INTERVAL, INT_MAX, }, - { "natural_healsp_interval", &battle_config.natural_healsp_interval, 8000, NATURAL_HEAL_INTERVAL, INT_MAX, }, - { "natural_heal_skill_interval", &battle_config.natural_heal_skill_interval, 10000, NATURAL_HEAL_INTERVAL, INT_MAX, }, - { "natural_heal_weight_rate", &battle_config.natural_heal_weight_rate, 50, 50, 101 }, - { "arrow_decrement", &battle_config.arrow_decrement, 1, 0, 2, }, - { "max_aspd", &battle_config.max_aspd, 190, 100, 199, }, - { "max_third_aspd", &battle_config.max_third_aspd, 193, 100, 199, }, - { "max_walk_speed", &battle_config.max_walk_speed, 300, 100, 100*DEFAULT_WALK_SPEED, }, - { "max_lv", &battle_config.max_lv, 99, 0, MAX_LEVEL, }, - { "aura_lv", &battle_config.aura_lv, 99, 0, INT_MAX, }, - { "max_hp", &battle_config.max_hp, 32500, 100, 1000000000, }, - { "max_sp", &battle_config.max_sp, 32500, 100, 1000000000, }, - { "max_cart_weight", &battle_config.max_cart_weight, 8000, 100, 1000000, }, - { "max_parameter", &battle_config.max_parameter, 99, 10, 10000, }, - { "max_baby_parameter", &battle_config.max_baby_parameter, 80, 10, 10000, }, - { "max_def", &battle_config.max_def, 99, 0, INT_MAX, }, - { "over_def_bonus", &battle_config.over_def_bonus, 0, 0, 1000, }, - { "skill_log", &battle_config.skill_log, BL_NUL, BL_NUL, BL_ALL, }, - { "battle_log", &battle_config.battle_log, 0, 0, 1, }, - { "etc_log", &battle_config.etc_log, 1, 0, 1, }, - { "save_clothcolor", &battle_config.save_clothcolor, 1, 0, 1, }, - { "undead_detect_type", &battle_config.undead_detect_type, 0, 0, 2, }, - { "auto_counter_type", &battle_config.auto_counter_type, BL_ALL, BL_NUL, BL_ALL, }, - { "min_hitrate", &battle_config.min_hitrate, 5, 0, 100, }, - { "max_hitrate", &battle_config.max_hitrate, 100, 0, 100, }, - { "agi_penalty_target", &battle_config.agi_penalty_target, BL_PC, BL_NUL, BL_ALL, }, - { "agi_penalty_type", &battle_config.agi_penalty_type, 1, 0, 2, }, - { "agi_penalty_count", &battle_config.agi_penalty_count, 3, 2, INT_MAX, }, - { "agi_penalty_num", &battle_config.agi_penalty_num, 10, 0, INT_MAX, }, - { "vit_penalty_target", &battle_config.vit_penalty_target, BL_PC, BL_NUL, BL_ALL, }, - { "vit_penalty_type", &battle_config.vit_penalty_type, 1, 0, 2, }, - { "vit_penalty_count", &battle_config.vit_penalty_count, 3, 2, INT_MAX, }, - { "vit_penalty_num", &battle_config.vit_penalty_num, 5, 0, INT_MAX, }, - { "weapon_defense_type", &battle_config.weapon_defense_type, 0, 0, INT_MAX, }, - { "magic_defense_type", &battle_config.magic_defense_type, 0, 0, INT_MAX, }, - { "skill_reiteration", &battle_config.skill_reiteration, BL_NUL, BL_NUL, BL_ALL, }, - { "skill_nofootset", &battle_config.skill_nofootset, BL_PC, BL_NUL, BL_ALL, }, - { "player_cloak_check_type", &battle_config.pc_cloak_check_type, 1, 0, 1|2|4, }, - { "monster_cloak_check_type", &battle_config.monster_cloak_check_type, 4, 0, 1|2|4, }, - { "sense_type", &battle_config.estimation_type, 1|2, 0, 1|2, }, - { "gvg_short_attack_damage_rate", &battle_config.gvg_short_damage_rate, 80, 0, INT_MAX, }, - { "gvg_long_attack_damage_rate", &battle_config.gvg_long_damage_rate, 80, 0, INT_MAX, }, - { "gvg_weapon_attack_damage_rate", &battle_config.gvg_weapon_damage_rate, 60, 0, INT_MAX, }, - { "gvg_magic_attack_damage_rate", &battle_config.gvg_magic_damage_rate, 60, 0, INT_MAX, }, - { "gvg_misc_attack_damage_rate", &battle_config.gvg_misc_damage_rate, 60, 0, INT_MAX, }, - { "gvg_flee_penalty", &battle_config.gvg_flee_penalty, 20, 0, INT_MAX, }, - { "pk_short_attack_damage_rate", &battle_config.pk_short_damage_rate, 80, 0, INT_MAX, }, - { "pk_long_attack_damage_rate", &battle_config.pk_long_damage_rate, 70, 0, INT_MAX, }, - { "pk_weapon_attack_damage_rate", &battle_config.pk_weapon_damage_rate, 60, 0, INT_MAX, }, - { "pk_magic_attack_damage_rate", &battle_config.pk_magic_damage_rate, 60, 0, INT_MAX, }, - { "pk_misc_attack_damage_rate", &battle_config.pk_misc_damage_rate, 60, 0, INT_MAX, }, - { "mob_changetarget_byskill", &battle_config.mob_changetarget_byskill, 0, 0, 1, }, - { "attack_direction_change", &battle_config.attack_direction_change, BL_ALL, BL_NUL, BL_ALL, }, - { "land_skill_limit", &battle_config.land_skill_limit, BL_ALL, BL_NUL, BL_ALL, }, - { "monster_class_change_full_recover", &battle_config.monster_class_change_recover, 1, 0, 1, }, - { "produce_item_name_input", &battle_config.produce_item_name_input, 0x1|0x2, 0, 0x9F, }, - { "display_skill_fail", &battle_config.display_skill_fail, 2, 0, 1|2|4|8, }, - { "chat_warpportal", &battle_config.chat_warpportal, 0, 0, 1, }, - { "mob_warp", &battle_config.mob_warp, 0, 0, 1|2|4, }, - { "dead_branch_active", &battle_config.dead_branch_active, 1, 0, 1, }, - { "vending_max_value", &battle_config.vending_max_value, 10000000, 1, MAX_ZENY, }, - { "vending_over_max", &battle_config.vending_over_max, 1, 0, 1, }, - { "show_steal_in_same_party", &battle_config.show_steal_in_same_party, 0, 0, 1, }, - { "party_hp_mode", &battle_config.party_hp_mode, 0, 0, 1, }, - { "show_party_share_picker", &battle_config.party_show_share_picker, 1, 0, 1, }, - { "show_picker.item_type", &battle_config.show_picker_item_type, 112, 0, INT_MAX, }, - { "party_update_interval", &battle_config.party_update_interval, 1000, 100, INT_MAX, }, - { "party_item_share_type", &battle_config.party_share_type, 0, 0, 1|2|3, }, - { "attack_attr_none", &battle_config.attack_attr_none, ~BL_PC, BL_NUL, BL_ALL, }, - { "gx_allhit", &battle_config.gx_allhit, 0, 0, 1, }, - { "gx_disptype", &battle_config.gx_disptype, 1, 0, 1, }, - { "devotion_level_difference", &battle_config.devotion_level_difference, 10, 0, INT_MAX, }, - { "player_skill_partner_check", &battle_config.player_skill_partner_check, 1, 0, 1, }, - { "invite_request_check", &battle_config.invite_request_check, 1, 0, 1, }, - { "skill_removetrap_type", &battle_config.skill_removetrap_type, 0, 0, 1, }, - { "disp_experience", &battle_config.disp_experience, 0, 0, 1, }, - { "disp_zeny", &battle_config.disp_zeny, 0, 0, 1, }, - { "castle_defense_rate", &battle_config.castle_defense_rate, 100, 0, 100, }, - { "bone_drop", &battle_config.bone_drop, 0, 0, 2, }, - { "buyer_name", &battle_config.buyer_name, 1, 0, 1, }, - { "skill_wall_check", &battle_config.skill_wall_check, 1, 0, 1, }, - { "cell_stack_limit", &battle_config.cell_stack_limit, 1, 1, 255, }, - { "dancing_weaponswitch_fix", &battle_config.dancing_weaponswitch_fix, 1, 0, 1, }, - - // eAthena additions - { "item_logarithmic_drops", &battle_config.logarithmic_drops, 0, 0, 1, }, - { "item_drop_common_min", &battle_config.item_drop_common_min, 1, 1, 10000, }, - { "item_drop_common_max", &battle_config.item_drop_common_max, 10000, 1, 10000, }, - { "item_drop_equip_min", &battle_config.item_drop_equip_min, 1, 1, 10000, }, - { "item_drop_equip_max", &battle_config.item_drop_equip_max, 10000, 1, 10000, }, - { "item_drop_card_min", &battle_config.item_drop_card_min, 1, 1, 10000, }, - { "item_drop_card_max", &battle_config.item_drop_card_max, 10000, 1, 10000, }, - { "item_drop_mvp_min", &battle_config.item_drop_mvp_min, 1, 1, 10000, }, - { "item_drop_mvp_max", &battle_config.item_drop_mvp_max, 10000, 1, 10000, }, - { "item_drop_heal_min", &battle_config.item_drop_heal_min, 1, 1, 10000, }, - { "item_drop_heal_max", &battle_config.item_drop_heal_max, 10000, 1, 10000, }, - { "item_drop_use_min", &battle_config.item_drop_use_min, 1, 1, 10000, }, - { "item_drop_use_max", &battle_config.item_drop_use_max, 10000, 1, 10000, }, - { "item_drop_add_min", &battle_config.item_drop_adddrop_min, 1, 1, 10000, }, - { "item_drop_add_max", &battle_config.item_drop_adddrop_max, 10000, 1, 10000, }, - { "item_drop_treasure_min", &battle_config.item_drop_treasure_min, 1, 1, 10000, }, - { "item_drop_treasure_max", &battle_config.item_drop_treasure_max, 10000, 1, 10000, }, - { "item_rate_mvp", &battle_config.item_rate_mvp, 100, 0, 1000000, }, - { "item_rate_common", &battle_config.item_rate_common, 100, 0, 1000000, }, - { "item_rate_common_boss", &battle_config.item_rate_common_boss, 100, 0, 1000000, }, - { "item_rate_equip", &battle_config.item_rate_equip, 100, 0, 1000000, }, - { "item_rate_equip_boss", &battle_config.item_rate_equip_boss, 100, 0, 1000000, }, - { "item_rate_card", &battle_config.item_rate_card, 100, 0, 1000000, }, - { "item_rate_card_boss", &battle_config.item_rate_card_boss, 100, 0, 1000000, }, - { "item_rate_heal", &battle_config.item_rate_heal, 100, 0, 1000000, }, - { "item_rate_heal_boss", &battle_config.item_rate_heal_boss, 100, 0, 1000000, }, - { "item_rate_use", &battle_config.item_rate_use, 100, 0, 1000000, }, - { "item_rate_use_boss", &battle_config.item_rate_use_boss, 100, 0, 1000000, }, - { "item_rate_adddrop", &battle_config.item_rate_adddrop, 100, 0, 1000000, }, - { "item_rate_treasure", &battle_config.item_rate_treasure, 100, 0, 1000000, }, - { "prevent_logout", &battle_config.prevent_logout, 10000, 0, 60000, }, - { "alchemist_summon_reward", &battle_config.alchemist_summon_reward, 1, 0, 2, }, - { "drops_by_luk", &battle_config.drops_by_luk, 0, 0, INT_MAX, }, - { "drops_by_luk2", &battle_config.drops_by_luk2, 0, 0, INT_MAX, }, - { "equip_natural_break_rate", &battle_config.equip_natural_break_rate, 0, 0, INT_MAX, }, - { "equip_self_break_rate", &battle_config.equip_self_break_rate, 100, 0, INT_MAX, }, - { "equip_skill_break_rate", &battle_config.equip_skill_break_rate, 100, 0, INT_MAX, }, - { "pk_mode", &battle_config.pk_mode, 0, 0, 2, }, - { "pk_level_range", &battle_config.pk_level_range, 0, 0, INT_MAX, }, - { "manner_system", &battle_config.manner_system, 0xFFF, 0, 0xFFF, }, - { "pet_equip_required", &battle_config.pet_equip_required, 0, 0, 1, }, - { "multi_level_up", &battle_config.multi_level_up, 0, 0, 1, }, - { "max_exp_gain_rate", &battle_config.max_exp_gain_rate, 0, 0, INT_MAX, }, - { "backstab_bow_penalty", &battle_config.backstab_bow_penalty, 0, 0, 1, }, - { "night_at_start", &battle_config.night_at_start, 0, 0, 1, }, - { "show_mob_info", &battle_config.show_mob_info, 0, 0, 1|2|4, }, - { "ban_hack_trade", &battle_config.ban_hack_trade, 0, 0, INT_MAX, }, - { "packet_ver_flag", &battle_config.packet_ver_flag, 0xFFFFFF,0x0000,INT_MAX, }, - { "min_hair_style", &battle_config.min_hair_style, 0, 0, INT_MAX, }, - { "max_hair_style", &battle_config.max_hair_style, 23, 0, INT_MAX, }, - { "min_hair_color", &battle_config.min_hair_color, 0, 0, INT_MAX, }, - { "max_hair_color", &battle_config.max_hair_color, 9, 0, INT_MAX, }, - { "min_cloth_color", &battle_config.min_cloth_color, 0, 0, INT_MAX, }, - { "max_cloth_color", &battle_config.max_cloth_color, 4, 0, INT_MAX, }, - { "pet_hair_style", &battle_config.pet_hair_style, 100, 0, INT_MAX, }, - { "castrate_dex_scale", &battle_config.castrate_dex_scale, 150, 1, INT_MAX, }, - { "vcast_stat_scale", &battle_config.vcast_stat_scale, 530, 1, INT_MAX, }, - { "area_size", &battle_config.area_size, 14, 0, INT_MAX, }, - { "zeny_from_mobs", &battle_config.zeny_from_mobs, 0, 0, 1, }, - { "mobs_level_up", &battle_config.mobs_level_up, 0, 0, 1, }, - { "mobs_level_up_exp_rate", &battle_config.mobs_level_up_exp_rate, 1, 1, INT_MAX, }, - { "pk_min_level", &battle_config.pk_min_level, 55, 1, INT_MAX, }, - { "skill_steal_max_tries", &battle_config.skill_steal_max_tries, 0, 0, UCHAR_MAX, }, - { "motd_type", &battle_config.motd_type, 0, 0, 1, }, - { "finding_ore_rate", &battle_config.finding_ore_rate, 100, 0, INT_MAX, }, - { "exp_calc_type", &battle_config.exp_calc_type, 0, 0, 1, }, - { "exp_bonus_attacker", &battle_config.exp_bonus_attacker, 25, 0, INT_MAX, }, - { "exp_bonus_max_attacker", &battle_config.exp_bonus_max_attacker, 12, 2, INT_MAX, }, - { "min_skill_delay_limit", &battle_config.min_skill_delay_limit, 100, 10, INT_MAX, }, - { "default_walk_delay", &battle_config.default_walk_delay, 300, 0, INT_MAX, }, - { "no_skill_delay", &battle_config.no_skill_delay, BL_MOB, BL_NUL, BL_ALL, }, - { "attack_walk_delay", &battle_config.attack_walk_delay, BL_ALL, BL_NUL, BL_ALL, }, - { "require_glory_guild", &battle_config.require_glory_guild, 0, 0, 1, }, - { "idle_no_share", &battle_config.idle_no_share, 0, 0, INT_MAX, }, - { "party_even_share_bonus", &battle_config.party_even_share_bonus, 0, 0, INT_MAX, }, - { "delay_battle_damage", &battle_config.delay_battle_damage, 1, 0, 1, }, - { "hide_woe_damage", &battle_config.hide_woe_damage, 0, 0, 1, }, - { "display_version", &battle_config.display_version, 1, 0, 1, }, - { "display_hallucination", &battle_config.display_hallucination, 1, 0, 1, }, - { "use_statpoint_table", &battle_config.use_statpoint_table, 1, 0, 1, }, - { "ignore_items_gender", &battle_config.ignore_items_gender, 1, 0, 1, }, - { "copyskill_restrict", &battle_config.copyskill_restrict, 2, 0, 2, }, - { "berserk_cancels_buffs", &battle_config.berserk_cancels_buffs, 0, 0, 1, }, - { "debuff_on_logout", &battle_config.debuff_on_logout, 1|2, 0, 1|2, }, - { "monster_ai", &battle_config.mob_ai, 0x000, 0x000, 0x77F, }, - { "hom_setting", &battle_config.hom_setting, 0xFFFF, 0x0000, 0xFFFF, }, - { "dynamic_mobs", &battle_config.dynamic_mobs, 1, 0, 1, }, - { "mob_remove_damaged", &battle_config.mob_remove_damaged, 1, 0, 1, }, - { "show_hp_sp_drain", &battle_config.show_hp_sp_drain, 0, 0, 1, }, - { "show_hp_sp_gain", &battle_config.show_hp_sp_gain, 1, 0, 1, }, - { "mob_npc_event_type", &battle_config.mob_npc_event_type, 1, 0, 1, }, - { "character_size", &battle_config.character_size, 1|2, 0, 1|2, }, - { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, MAX_SKILL_LEVEL, 1, MAX_SKILL_LEVEL, }, - { "retaliate_to_master", &battle_config.retaliate_to_master, 1, 0, 1, }, - { "rare_drop_announce", &battle_config.rare_drop_announce, 0, 0, 10000, }, - { "duel_allow_pvp", &battle_config.duel_allow_pvp, 0, 0, 1, }, - { "duel_allow_gvg", &battle_config.duel_allow_gvg, 0, 0, 1, }, - { "duel_allow_teleport", &battle_config.duel_allow_teleport, 0, 0, 1, }, - { "duel_autoleave_when_die", &battle_config.duel_autoleave_when_die, 1, 0, 1, }, - { "duel_time_interval", &battle_config.duel_time_interval, 60, 0, INT_MAX, }, - { "duel_only_on_same_map", &battle_config.duel_only_on_same_map, 0, 0, 1, }, - { "skip_teleport_lv1_menu", &battle_config.skip_teleport_lv1_menu, 0, 0, 1, }, - { "allow_skill_without_day", &battle_config.allow_skill_without_day, 0, 0, 1, }, - { "allow_es_magic_player", &battle_config.allow_es_magic_pc, 0, 0, 1, }, - { "skill_caster_check", &battle_config.skill_caster_check, 1, 0, 1, }, - { "status_cast_cancel", &battle_config.sc_castcancel, BL_NUL, BL_NUL, BL_ALL, }, - { "pc_status_def_rate", &battle_config.pc_sc_def_rate, 100, 0, INT_MAX, }, - { "mob_status_def_rate", &battle_config.mob_sc_def_rate, 100, 0, INT_MAX, }, - { "pc_luk_status_def", &battle_config.pc_luk_sc_def, 300, 1, INT_MAX, }, - { "mob_luk_status_def", &battle_config.mob_luk_sc_def, 300, 1, INT_MAX, }, - { "pc_max_status_def", &battle_config.pc_max_sc_def, 100, 0, INT_MAX, }, - { "mob_max_status_def", &battle_config.mob_max_sc_def, 100, 0, INT_MAX, }, - { "sg_miracle_skill_ratio", &battle_config.sg_miracle_skill_ratio, 1, 0, 10000, }, - { "sg_angel_skill_ratio", &battle_config.sg_angel_skill_ratio, 10, 0, 10000, }, - { "autospell_stacking", &battle_config.autospell_stacking, 0, 0, 1, }, - { "override_mob_names", &battle_config.override_mob_names, 0, 0, 2, }, - { "min_chat_delay", &battle_config.min_chat_delay, 0, 0, INT_MAX, }, - { "friend_auto_add", &battle_config.friend_auto_add, 1, 0, 1, }, - { "hom_rename", &battle_config.hom_rename, 0, 0, 1, }, - { "homunculus_show_growth", &battle_config.homunculus_show_growth, 0, 0, 1, }, - { "homunculus_friendly_rate", &battle_config.homunculus_friendly_rate, 100, 0, INT_MAX, }, - { "vending_tax", &battle_config.vending_tax, 0, 0, 10000, }, - { "day_duration", &battle_config.day_duration, 0, 0, INT_MAX, }, - { "night_duration", &battle_config.night_duration, 0, 0, INT_MAX, }, - { "mob_remove_delay", &battle_config.mob_remove_delay, 60000, 1000, INT_MAX, }, - { "mob_active_time", &battle_config.mob_active_time, 0, 0, INT_MAX, }, - { "boss_active_time", &battle_config.boss_active_time, 0, 0, INT_MAX, }, - { "sg_miracle_skill_duration", &battle_config.sg_miracle_skill_duration, 3600000, 0, INT_MAX, }, - { "hvan_explosion_intimate", &battle_config.hvan_explosion_intimate, 45000, 0, 100000, }, - { "quest_exp_rate", &battle_config.quest_exp_rate, 100, 0, INT_MAX, }, - { "at_mapflag", &battle_config.autotrade_mapflag, 0, 0, 1, }, - { "at_timeout", &battle_config.at_timeout, 0, 0, INT_MAX, }, - { "homunculus_autoloot", &battle_config.homunculus_autoloot, 0, 0, 1, }, - { "idle_no_autoloot", &battle_config.idle_no_autoloot, 0, 0, INT_MAX, }, - { "max_guild_alliance", &battle_config.max_guild_alliance, 3, 0, 3, }, - { "ksprotection", &battle_config.ksprotection, 5000, 0, INT_MAX, }, - { "auction_feeperhour", &battle_config.auction_feeperhour, 12000, 0, INT_MAX, }, - { "auction_maximumprice", &battle_config.auction_maximumprice, 500000000, 0, MAX_ZENY, }, - { "homunculus_auto_vapor", &battle_config.homunculus_auto_vapor, 1, 0, 1, }, - { "display_status_timers", &battle_config.display_status_timers, 1, 0, 1, }, - { "skill_add_heal_rate", &battle_config.skill_add_heal_rate, 7, 0, INT_MAX, }, - { "eq_single_target_reflectable", &battle_config.eq_single_target_reflectable, 1, 0, 1, }, - { "invincible.nodamage", &battle_config.invincible_nodamage, 0, 0, 1, }, - { "mob_slave_keep_target", &battle_config.mob_slave_keep_target, 0, 0, 1, }, - { "autospell_check_range", &battle_config.autospell_check_range, 0, 0, 1, }, - { "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, }, - { "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, }, - { "feature.buying_store", &battle_config.feature_buying_store, 1, 0, 1, }, - { "feature.search_stores", &battle_config.feature_search_stores, 1, 0, 1, }, - { "searchstore_querydelay", &battle_config.searchstore_querydelay, 10, 0, INT_MAX, }, - { "searchstore_maxresults", &battle_config.searchstore_maxresults, 30, 1, INT_MAX, }, - { "display_party_name", &battle_config.display_party_name, 0, 0, 1, }, - { "cashshop_show_points", &battle_config.cashshop_show_points, 0, 0, 1, }, - { "mail_show_status", &battle_config.mail_show_status, 0, 0, 2, }, - { "client_limit_unit_lv", &battle_config.client_limit_unit_lv, 0, 0, BL_ALL, }, - // BattleGround Settings - { "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, }, - { "bg_short_attack_damage_rate", &battle_config.bg_short_damage_rate, 80, 0, INT_MAX, }, - { "bg_long_attack_damage_rate", &battle_config.bg_long_damage_rate, 80, 0, INT_MAX, }, - { "bg_weapon_attack_damage_rate", &battle_config.bg_weapon_damage_rate, 60, 0, INT_MAX, }, - { "bg_magic_attack_damage_rate", &battle_config.bg_magic_damage_rate, 60, 0, INT_MAX, }, - { "bg_misc_attack_damage_rate", &battle_config.bg_misc_damage_rate, 60, 0, INT_MAX, }, - { "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, }, - /** - * rAthena - **/ - { "max_third_parameter", &battle_config.max_third_parameter, 120, 10, 10000, }, - { "max_baby_third_parameter", &battle_config.max_baby_third_parameter, 108, 10, 10000, }, - { "atcommand_max_stat_bypass", &battle_config.atcommand_max_stat_bypass, 0, 0, 100, }, - { "skill_amotion_leniency", &battle_config.skill_amotion_leniency, 90, 0, 100 }, - { "mvp_tomb_enabled", &battle_config.mvp_tomb_enabled, 1, 0, 1 }, - { "feature.atcommand_suggestions", &battle_config.atcommand_suggestions_enabled, 0, 0, 1 }, - { "min_npc_vending_distance", &battle_config.min_npc_vending_distance, 3, 0, 100 }, - { "atcommand_mobinfo_type", &battle_config.atcommand_mobinfo_type, 0, 0, 1 }, - { "homunculus_max_level", &battle_config.hom_max_level, 99, 0, MAX_LEVEL, }, - { "homunculus_S_max_level", &battle_config.hom_S_max_level, 150, 0, MAX_LEVEL, }, - { "mob_size_influence", &battle_config.mob_size_influence, 0, 0, 1, }, + { "warp_point_debug", &battle_config.warp_point_debug, 0, 0, 1, }, + { "enable_critical", &battle_config.enable_critical, BL_PC, BL_NUL, BL_ALL, }, + { "mob_critical_rate", &battle_config.mob_critical_rate, 100, 0, INT_MAX, }, + { "critical_rate", &battle_config.critical_rate, 100, 0, INT_MAX, }, + { "enable_baseatk", &battle_config.enable_baseatk, BL_PC|BL_HOM, BL_NUL, BL_ALL, }, + { "enable_perfect_flee", &battle_config.enable_perfect_flee, BL_PC|BL_PET, BL_NUL, BL_ALL, }, + { "casting_rate", &battle_config.cast_rate, 100, 0, INT_MAX, }, + { "delay_rate", &battle_config.delay_rate, 100, 0, INT_MAX, }, + { "delay_dependon_dex", &battle_config.delay_dependon_dex, 0, 0, 1, }, + { "delay_dependon_agi", &battle_config.delay_dependon_agi, 0, 0, 1, }, + { "skill_delay_attack_enable", &battle_config.sdelay_attack_enable, 0, 0, 1, }, + { "left_cardfix_to_right", &battle_config.left_cardfix_to_right, 0, 0, 1, }, + { "skill_add_range", &battle_config.skill_add_range, 0, 0, INT_MAX, }, + { "skill_out_range_consume", &battle_config.skill_out_range_consume, 1, 0, 1, }, + { "skillrange_by_distance", &battle_config.skillrange_by_distance, ~BL_PC, BL_NUL, BL_ALL, }, + { "skillrange_from_weapon", &battle_config.use_weapon_skill_range, ~BL_PC, BL_NUL, BL_ALL, }, + { "player_damage_delay_rate", &battle_config.pc_damage_delay_rate, 100, 0, INT_MAX, }, + { "defunit_not_enemy", &battle_config.defnotenemy, 0, 0, 1, }, + { "gvg_traps_target_all", &battle_config.vs_traps_bctall, BL_PC, BL_NUL, BL_ALL, }, + { "traps_setting", &battle_config.traps_setting, 0, 0, 1, }, + { "summon_flora_setting", &battle_config.summon_flora, 1|2, 0, 1|2, }, + { "clear_skills_on_death", &battle_config.clear_unit_ondeath, BL_NUL, BL_NUL, BL_ALL, }, + { "clear_skills_on_warp", &battle_config.clear_unit_onwarp, BL_ALL, BL_NUL, BL_ALL, }, + { "random_monster_checklv", &battle_config.random_monster_checklv, 0, 0, 1, }, + { "attribute_recover", &battle_config.attr_recover, 1, 0, 1, }, + { "flooritem_lifetime", &battle_config.flooritem_lifetime, 60000, 1000, INT_MAX, }, + { "item_auto_get", &battle_config.item_auto_get, 0, 0, 1, }, + { "item_first_get_time", &battle_config.item_first_get_time, 3000, 0, INT_MAX, }, + { "item_second_get_time", &battle_config.item_second_get_time, 1000, 0, INT_MAX, }, + { "item_third_get_time", &battle_config.item_third_get_time, 1000, 0, INT_MAX, }, + { "mvp_item_first_get_time", &battle_config.mvp_item_first_get_time, 10000, 0, INT_MAX, }, + { "mvp_item_second_get_time", &battle_config.mvp_item_second_get_time, 10000, 0, INT_MAX, }, + { "mvp_item_third_get_time", &battle_config.mvp_item_third_get_time, 2000, 0, INT_MAX, }, + { "drop_rate0item", &battle_config.drop_rate0item, 0, 0, 1, }, + { "base_exp_rate", &battle_config.base_exp_rate, 100, 0, INT_MAX, }, + { "job_exp_rate", &battle_config.job_exp_rate, 100, 0, INT_MAX, }, + { "pvp_exp", &battle_config.pvp_exp, 1, 0, 1, }, + { "death_penalty_type", &battle_config.death_penalty_type, 0, 0, 2, }, + { "death_penalty_base", &battle_config.death_penalty_base, 0, 0, INT_MAX, }, + { "death_penalty_job", &battle_config.death_penalty_job, 0, 0, INT_MAX, }, + { "zeny_penalty", &battle_config.zeny_penalty, 0, 0, INT_MAX, }, + { "hp_rate", &battle_config.hp_rate, 100, 1, INT_MAX, }, + { "sp_rate", &battle_config.sp_rate, 100, 1, INT_MAX, }, + { "restart_hp_rate", &battle_config.restart_hp_rate, 0, 0, 100, }, + { "restart_sp_rate", &battle_config.restart_sp_rate, 0, 0, 100, }, + { "guild_aura", &battle_config.guild_aura, 31, 0, 31, }, + { "mvp_hp_rate", &battle_config.mvp_hp_rate, 100, 1, INT_MAX, }, + { "mvp_exp_rate", &battle_config.mvp_exp_rate, 100, 0, INT_MAX, }, + { "monster_hp_rate", &battle_config.monster_hp_rate, 100, 1, INT_MAX, }, + { "monster_max_aspd", &battle_config.monster_max_aspd, 199, 100, 199, }, + { "view_range_rate", &battle_config.view_range_rate, 100, 0, INT_MAX, }, + { "chase_range_rate", &battle_config.chase_range_rate, 100, 0, INT_MAX, }, + { "gtb_sc_immunity", &battle_config.gtb_sc_immunity, 50, 0, INT_MAX, }, + { "guild_max_castles", &battle_config.guild_max_castles, 0, 0, INT_MAX, }, + { "guild_skill_relog_delay", &battle_config.guild_skill_relog_delay, 0, 0, 1, }, + { "emergency_call", &battle_config.emergency_call, 11, 0, 31, }, + { "atcommand_spawn_quantity_limit", &battle_config.atc_spawn_quantity_limit, 100, 0, INT_MAX, }, + { "atcommand_slave_clone_limit", &battle_config.atc_slave_clone_limit, 25, 0, INT_MAX, }, + { "partial_name_scan", &battle_config.partial_name_scan, 0, 0, 1, }, + { "player_skillfree", &battle_config.skillfree, 0, 0, 1, }, + { "player_skillup_limit", &battle_config.skillup_limit, 1, 0, 1, }, + { "weapon_produce_rate", &battle_config.wp_rate, 100, 0, INT_MAX, }, + { "potion_produce_rate", &battle_config.pp_rate, 100, 0, INT_MAX, }, + { "monster_active_enable", &battle_config.monster_active_enable, 1, 0, 1, }, + { "monster_damage_delay_rate", &battle_config.monster_damage_delay_rate, 100, 0, INT_MAX, }, + { "monster_loot_type", &battle_config.monster_loot_type, 0, 0, 1, }, +// { "mob_skill_use", &battle_config.mob_skill_use, 1, 0, 1, }, //Deprecated + { "mob_skill_rate", &battle_config.mob_skill_rate, 100, 0, INT_MAX, }, + { "mob_skill_delay", &battle_config.mob_skill_delay, 100, 0, INT_MAX, }, + { "mob_count_rate", &battle_config.mob_count_rate, 100, 0, INT_MAX, }, + { "mob_spawn_delay", &battle_config.mob_spawn_delay, 100, 0, INT_MAX, }, + { "plant_spawn_delay", &battle_config.plant_spawn_delay, 100, 0, INT_MAX, }, + { "boss_spawn_delay", &battle_config.boss_spawn_delay, 100, 0, INT_MAX, }, + { "no_spawn_on_player", &battle_config.no_spawn_on_player, 0, 0, 100, }, + { "force_random_spawn", &battle_config.force_random_spawn, 0, 0, 1, }, + { "slaves_inherit_mode", &battle_config.slaves_inherit_mode, 2, 0, 3, }, + { "slaves_inherit_speed", &battle_config.slaves_inherit_speed, 3, 0, 3, }, + { "summons_trigger_autospells", &battle_config.summons_trigger_autospells, 1, 0, 1, }, + { "pc_damage_walk_delay_rate", &battle_config.pc_walk_delay_rate, 20, 0, INT_MAX, }, + { "damage_walk_delay_rate", &battle_config.walk_delay_rate, 100, 0, INT_MAX, }, + { "multihit_delay", &battle_config.multihit_delay, 80, 0, INT_MAX, }, + { "quest_skill_learn", &battle_config.quest_skill_learn, 0, 0, 1, }, + { "quest_skill_reset", &battle_config.quest_skill_reset, 0, 0, 1, }, + { "basic_skill_check", &battle_config.basic_skill_check, 1, 0, 1, }, + { "guild_emperium_check", &battle_config.guild_emperium_check, 1, 0, 1, }, + { "guild_exp_limit", &battle_config.guild_exp_limit, 50, 0, 99, }, + { "player_invincible_time", &battle_config.pc_invincible_time, 5000, 0, INT_MAX, }, + { "pet_catch_rate", &battle_config.pet_catch_rate, 100, 0, INT_MAX, }, + { "pet_rename", &battle_config.pet_rename, 0, 0, 1, }, + { "pet_friendly_rate", &battle_config.pet_friendly_rate, 100, 0, INT_MAX, }, + { "pet_hungry_delay_rate", &battle_config.pet_hungry_delay_rate, 100, 10, INT_MAX, }, + { "pet_hungry_friendly_decrease", &battle_config.pet_hungry_friendly_decrease, 5, 0, INT_MAX, }, + { "pet_status_support", &battle_config.pet_status_support, 0, 0, 1, }, + { "pet_attack_support", &battle_config.pet_attack_support, 0, 0, 1, }, + { "pet_damage_support", &battle_config.pet_damage_support, 0, 0, 1, }, + { "pet_support_min_friendly", &battle_config.pet_support_min_friendly, 900, 0, 950, }, + { "pet_equip_min_friendly", &battle_config.pet_equip_min_friendly, 900, 0, 950, }, + { "pet_support_rate", &battle_config.pet_support_rate, 100, 0, INT_MAX, }, + { "pet_attack_exp_to_master", &battle_config.pet_attack_exp_to_master, 0, 0, 1, }, + { "pet_attack_exp_rate", &battle_config.pet_attack_exp_rate, 100, 0, INT_MAX, }, + { "pet_lv_rate", &battle_config.pet_lv_rate, 0, 0, INT_MAX, }, + { "pet_max_stats", &battle_config.pet_max_stats, 99, 0, INT_MAX, }, + { "pet_max_atk1", &battle_config.pet_max_atk1, 750, 0, INT_MAX, }, + { "pet_max_atk2", &battle_config.pet_max_atk2, 1000, 0, INT_MAX, }, + { "pet_disable_in_gvg", &battle_config.pet_no_gvg, 0, 0, 1, }, + { "skill_min_damage", &battle_config.skill_min_damage, 2|4, 0, 1|2|4, }, + { "finger_offensive_type", &battle_config.finger_offensive_type, 0, 0, 1, }, + { "heal_exp", &battle_config.heal_exp, 0, 0, INT_MAX, }, + { "resurrection_exp", &battle_config.resurrection_exp, 0, 0, INT_MAX, }, + { "shop_exp", &battle_config.shop_exp, 0, 0, INT_MAX, }, + { "max_heal_lv", &battle_config.max_heal_lv, 11, 1, INT_MAX, }, + { "max_heal", &battle_config.max_heal, 9999, 0, INT_MAX, }, + { "combo_delay_rate", &battle_config.combo_delay_rate, 100, 0, INT_MAX, }, + { "item_check", &battle_config.item_check, 0, 0, 1, }, + { "item_use_interval", &battle_config.item_use_interval, 100, 0, INT_MAX, }, + { "cashfood_use_interval", &battle_config.cashfood_use_interval, 60000, 0, INT_MAX, }, + { "wedding_modifydisplay", &battle_config.wedding_modifydisplay, 0, 0, 1, }, + { "wedding_ignorepalette", &battle_config.wedding_ignorepalette, 0, 0, 1, }, + { "xmas_ignorepalette", &battle_config.xmas_ignorepalette, 0, 0, 1, }, + { "summer_ignorepalette", &battle_config.summer_ignorepalette, 0, 0, 1, }, + { "natural_healhp_interval", &battle_config.natural_healhp_interval, 6000, NATURAL_HEAL_INTERVAL, INT_MAX, }, + { "natural_healsp_interval", &battle_config.natural_healsp_interval, 8000, NATURAL_HEAL_INTERVAL, INT_MAX, }, + { "natural_heal_skill_interval", &battle_config.natural_heal_skill_interval, 10000, NATURAL_HEAL_INTERVAL, INT_MAX, }, + { "natural_heal_weight_rate", &battle_config.natural_heal_weight_rate, 50, 50, 101 }, + { "arrow_decrement", &battle_config.arrow_decrement, 1, 0, 2, }, + { "max_aspd", &battle_config.max_aspd, 190, 100, 199, }, + { "max_third_aspd", &battle_config.max_third_aspd, 193, 100, 199, }, + { "max_walk_speed", &battle_config.max_walk_speed, 300, 100, 100*DEFAULT_WALK_SPEED, }, + { "max_lv", &battle_config.max_lv, 99, 0, MAX_LEVEL, }, + { "aura_lv", &battle_config.aura_lv, 99, 0, INT_MAX, }, + { "max_hp", &battle_config.max_hp, 32500, 100, 1000000000, }, + { "max_sp", &battle_config.max_sp, 32500, 100, 1000000000, }, + { "max_cart_weight", &battle_config.max_cart_weight, 8000, 100, 1000000, }, + { "max_parameter", &battle_config.max_parameter, 99, 10, 10000, }, + { "max_baby_parameter", &battle_config.max_baby_parameter, 80, 10, 10000, }, + { "max_def", &battle_config.max_def, 99, 0, INT_MAX, }, + { "over_def_bonus", &battle_config.over_def_bonus, 0, 0, 1000, }, + { "skill_log", &battle_config.skill_log, BL_NUL, BL_NUL, BL_ALL, }, + { "battle_log", &battle_config.battle_log, 0, 0, 1, }, + { "etc_log", &battle_config.etc_log, 1, 0, 1, }, + { "save_clothcolor", &battle_config.save_clothcolor, 1, 0, 1, }, + { "undead_detect_type", &battle_config.undead_detect_type, 0, 0, 2, }, + { "auto_counter_type", &battle_config.auto_counter_type, BL_ALL, BL_NUL, BL_ALL, }, + { "min_hitrate", &battle_config.min_hitrate, 5, 0, 100, }, + { "max_hitrate", &battle_config.max_hitrate, 100, 0, 100, }, + { "agi_penalty_target", &battle_config.agi_penalty_target, BL_PC, BL_NUL, BL_ALL, }, + { "agi_penalty_type", &battle_config.agi_penalty_type, 1, 0, 2, }, + { "agi_penalty_count", &battle_config.agi_penalty_count, 3, 2, INT_MAX, }, + { "agi_penalty_num", &battle_config.agi_penalty_num, 10, 0, INT_MAX, }, + { "vit_penalty_target", &battle_config.vit_penalty_target, BL_PC, BL_NUL, BL_ALL, }, + { "vit_penalty_type", &battle_config.vit_penalty_type, 1, 0, 2, }, + { "vit_penalty_count", &battle_config.vit_penalty_count, 3, 2, INT_MAX, }, + { "vit_penalty_num", &battle_config.vit_penalty_num, 5, 0, INT_MAX, }, + { "weapon_defense_type", &battle_config.weapon_defense_type, 0, 0, INT_MAX, }, + { "magic_defense_type", &battle_config.magic_defense_type, 0, 0, INT_MAX, }, + { "skill_reiteration", &battle_config.skill_reiteration, BL_NUL, BL_NUL, BL_ALL, }, + { "skill_nofootset", &battle_config.skill_nofootset, BL_PC, BL_NUL, BL_ALL, }, + { "player_cloak_check_type", &battle_config.pc_cloak_check_type, 1, 0, 1|2|4, }, + { "monster_cloak_check_type", &battle_config.monster_cloak_check_type, 4, 0, 1|2|4, }, + { "sense_type", &battle_config.estimation_type, 1|2, 0, 1|2, }, + { "gvg_short_attack_damage_rate", &battle_config.gvg_short_damage_rate, 80, 0, INT_MAX, }, + { "gvg_long_attack_damage_rate", &battle_config.gvg_long_damage_rate, 80, 0, INT_MAX, }, + { "gvg_weapon_attack_damage_rate", &battle_config.gvg_weapon_damage_rate, 60, 0, INT_MAX, }, + { "gvg_magic_attack_damage_rate", &battle_config.gvg_magic_damage_rate, 60, 0, INT_MAX, }, + { "gvg_misc_attack_damage_rate", &battle_config.gvg_misc_damage_rate, 60, 0, INT_MAX, }, + { "gvg_flee_penalty", &battle_config.gvg_flee_penalty, 20, 0, INT_MAX, }, + { "pk_short_attack_damage_rate", &battle_config.pk_short_damage_rate, 80, 0, INT_MAX, }, + { "pk_long_attack_damage_rate", &battle_config.pk_long_damage_rate, 70, 0, INT_MAX, }, + { "pk_weapon_attack_damage_rate", &battle_config.pk_weapon_damage_rate, 60, 0, INT_MAX, }, + { "pk_magic_attack_damage_rate", &battle_config.pk_magic_damage_rate, 60, 0, INT_MAX, }, + { "pk_misc_attack_damage_rate", &battle_config.pk_misc_damage_rate, 60, 0, INT_MAX, }, + { "mob_changetarget_byskill", &battle_config.mob_changetarget_byskill, 0, 0, 1, }, + { "attack_direction_change", &battle_config.attack_direction_change, BL_ALL, BL_NUL, BL_ALL, }, + { "land_skill_limit", &battle_config.land_skill_limit, BL_ALL, BL_NUL, BL_ALL, }, + { "monster_class_change_full_recover", &battle_config.monster_class_change_recover, 1, 0, 1, }, + { "produce_item_name_input", &battle_config.produce_item_name_input, 0x1|0x2, 0, 0x9F, }, + { "display_skill_fail", &battle_config.display_skill_fail, 2, 0, 1|2|4|8, }, + { "chat_warpportal", &battle_config.chat_warpportal, 0, 0, 1, }, + { "mob_warp", &battle_config.mob_warp, 0, 0, 1|2|4, }, + { "dead_branch_active", &battle_config.dead_branch_active, 1, 0, 1, }, + { "vending_max_value", &battle_config.vending_max_value, 10000000, 1, MAX_ZENY, }, + { "vending_over_max", &battle_config.vending_over_max, 1, 0, 1, }, + { "show_steal_in_same_party", &battle_config.show_steal_in_same_party, 0, 0, 1, }, + { "party_hp_mode", &battle_config.party_hp_mode, 0, 0, 1, }, + { "show_party_share_picker", &battle_config.party_show_share_picker, 1, 0, 1, }, + { "show_picker.item_type", &battle_config.show_picker_item_type, 112, 0, INT_MAX, }, + { "party_update_interval", &battle_config.party_update_interval, 1000, 100, INT_MAX, }, + { "party_item_share_type", &battle_config.party_share_type, 0, 0, 1|2|3, }, + { "attack_attr_none", &battle_config.attack_attr_none, ~BL_PC, BL_NUL, BL_ALL, }, + { "gx_allhit", &battle_config.gx_allhit, 0, 0, 1, }, + { "gx_disptype", &battle_config.gx_disptype, 1, 0, 1, }, + { "devotion_level_difference", &battle_config.devotion_level_difference, 10, 0, INT_MAX, }, + { "player_skill_partner_check", &battle_config.player_skill_partner_check, 1, 0, 1, }, + { "invite_request_check", &battle_config.invite_request_check, 1, 0, 1, }, + { "skill_removetrap_type", &battle_config.skill_removetrap_type, 0, 0, 1, }, + { "disp_experience", &battle_config.disp_experience, 0, 0, 1, }, + { "disp_zeny", &battle_config.disp_zeny, 0, 0, 1, }, + { "castle_defense_rate", &battle_config.castle_defense_rate, 100, 0, 100, }, + { "bone_drop", &battle_config.bone_drop, 0, 0, 2, }, + { "buyer_name", &battle_config.buyer_name, 1, 0, 1, }, + { "skill_wall_check", &battle_config.skill_wall_check, 1, 0, 1, }, + { "cell_stack_limit", &battle_config.cell_stack_limit, 1, 1, 255, }, + { "dancing_weaponswitch_fix", &battle_config.dancing_weaponswitch_fix, 1, 0, 1, }, + +// eAthena additions + { "item_logarithmic_drops", &battle_config.logarithmic_drops, 0, 0, 1, }, + { "item_drop_common_min", &battle_config.item_drop_common_min, 1, 1, 10000, }, + { "item_drop_common_max", &battle_config.item_drop_common_max, 10000, 1, 10000, }, + { "item_drop_equip_min", &battle_config.item_drop_equip_min, 1, 1, 10000, }, + { "item_drop_equip_max", &battle_config.item_drop_equip_max, 10000, 1, 10000, }, + { "item_drop_card_min", &battle_config.item_drop_card_min, 1, 1, 10000, }, + { "item_drop_card_max", &battle_config.item_drop_card_max, 10000, 1, 10000, }, + { "item_drop_mvp_min", &battle_config.item_drop_mvp_min, 1, 1, 10000, }, + { "item_drop_mvp_max", &battle_config.item_drop_mvp_max, 10000, 1, 10000, }, + { "item_drop_heal_min", &battle_config.item_drop_heal_min, 1, 1, 10000, }, + { "item_drop_heal_max", &battle_config.item_drop_heal_max, 10000, 1, 10000, }, + { "item_drop_use_min", &battle_config.item_drop_use_min, 1, 1, 10000, }, + { "item_drop_use_max", &battle_config.item_drop_use_max, 10000, 1, 10000, }, + { "item_drop_add_min", &battle_config.item_drop_adddrop_min, 1, 1, 10000, }, + { "item_drop_add_max", &battle_config.item_drop_adddrop_max, 10000, 1, 10000, }, + { "item_drop_treasure_min", &battle_config.item_drop_treasure_min, 1, 1, 10000, }, + { "item_drop_treasure_max", &battle_config.item_drop_treasure_max, 10000, 1, 10000, }, + { "item_rate_mvp", &battle_config.item_rate_mvp, 100, 0, 1000000, }, + { "item_rate_common", &battle_config.item_rate_common, 100, 0, 1000000, }, + { "item_rate_common_boss", &battle_config.item_rate_common_boss, 100, 0, 1000000, }, + { "item_rate_equip", &battle_config.item_rate_equip, 100, 0, 1000000, }, + { "item_rate_equip_boss", &battle_config.item_rate_equip_boss, 100, 0, 1000000, }, + { "item_rate_card", &battle_config.item_rate_card, 100, 0, 1000000, }, + { "item_rate_card_boss", &battle_config.item_rate_card_boss, 100, 0, 1000000, }, + { "item_rate_heal", &battle_config.item_rate_heal, 100, 0, 1000000, }, + { "item_rate_heal_boss", &battle_config.item_rate_heal_boss, 100, 0, 1000000, }, + { "item_rate_use", &battle_config.item_rate_use, 100, 0, 1000000, }, + { "item_rate_use_boss", &battle_config.item_rate_use_boss, 100, 0, 1000000, }, + { "item_rate_adddrop", &battle_config.item_rate_adddrop, 100, 0, 1000000, }, + { "item_rate_treasure", &battle_config.item_rate_treasure, 100, 0, 1000000, }, + { "prevent_logout", &battle_config.prevent_logout, 10000, 0, 60000, }, + { "alchemist_summon_reward", &battle_config.alchemist_summon_reward, 1, 0, 2, }, + { "drops_by_luk", &battle_config.drops_by_luk, 0, 0, INT_MAX, }, + { "drops_by_luk2", &battle_config.drops_by_luk2, 0, 0, INT_MAX, }, + { "equip_natural_break_rate", &battle_config.equip_natural_break_rate, 0, 0, INT_MAX, }, + { "equip_self_break_rate", &battle_config.equip_self_break_rate, 100, 0, INT_MAX, }, + { "equip_skill_break_rate", &battle_config.equip_skill_break_rate, 100, 0, INT_MAX, }, + { "pk_mode", &battle_config.pk_mode, 0, 0, 2, }, + { "pk_level_range", &battle_config.pk_level_range, 0, 0, INT_MAX, }, + { "manner_system", &battle_config.manner_system, 0xFFF, 0, 0xFFF, }, + { "pet_equip_required", &battle_config.pet_equip_required, 0, 0, 1, }, + { "multi_level_up", &battle_config.multi_level_up, 0, 0, 1, }, + { "max_exp_gain_rate", &battle_config.max_exp_gain_rate, 0, 0, INT_MAX, }, + { "backstab_bow_penalty", &battle_config.backstab_bow_penalty, 0, 0, 1, }, + { "night_at_start", &battle_config.night_at_start, 0, 0, 1, }, + { "show_mob_info", &battle_config.show_mob_info, 0, 0, 1|2|4, }, + { "ban_hack_trade", &battle_config.ban_hack_trade, 0, 0, INT_MAX, }, + { "packet_ver_flag", &battle_config.packet_ver_flag, 0xFFFFFF,0x0000,INT_MAX, }, + { "min_hair_style", &battle_config.min_hair_style, 0, 0, INT_MAX, }, + { "max_hair_style", &battle_config.max_hair_style, 23, 0, INT_MAX, }, + { "min_hair_color", &battle_config.min_hair_color, 0, 0, INT_MAX, }, + { "max_hair_color", &battle_config.max_hair_color, 9, 0, INT_MAX, }, + { "min_cloth_color", &battle_config.min_cloth_color, 0, 0, INT_MAX, }, + { "max_cloth_color", &battle_config.max_cloth_color, 4, 0, INT_MAX, }, + { "pet_hair_style", &battle_config.pet_hair_style, 100, 0, INT_MAX, }, + { "castrate_dex_scale", &battle_config.castrate_dex_scale, 150, 1, INT_MAX, }, + { "vcast_stat_scale", &battle_config.vcast_stat_scale, 530, 1, INT_MAX, }, + { "area_size", &battle_config.area_size, 14, 0, INT_MAX, }, + { "zeny_from_mobs", &battle_config.zeny_from_mobs, 0, 0, 1, }, + { "mobs_level_up", &battle_config.mobs_level_up, 0, 0, 1, }, + { "mobs_level_up_exp_rate", &battle_config.mobs_level_up_exp_rate, 1, 1, INT_MAX, }, + { "pk_min_level", &battle_config.pk_min_level, 55, 1, INT_MAX, }, + { "skill_steal_max_tries", &battle_config.skill_steal_max_tries, 0, 0, UCHAR_MAX, }, + { "motd_type", &battle_config.motd_type, 0, 0, 1, }, + { "finding_ore_rate", &battle_config.finding_ore_rate, 100, 0, INT_MAX, }, + { "exp_calc_type", &battle_config.exp_calc_type, 0, 0, 1, }, + { "exp_bonus_attacker", &battle_config.exp_bonus_attacker, 25, 0, INT_MAX, }, + { "exp_bonus_max_attacker", &battle_config.exp_bonus_max_attacker, 12, 2, INT_MAX, }, + { "min_skill_delay_limit", &battle_config.min_skill_delay_limit, 100, 10, INT_MAX, }, + { "default_walk_delay", &battle_config.default_walk_delay, 300, 0, INT_MAX, }, + { "no_skill_delay", &battle_config.no_skill_delay, BL_MOB, BL_NUL, BL_ALL, }, + { "attack_walk_delay", &battle_config.attack_walk_delay, BL_ALL, BL_NUL, BL_ALL, }, + { "require_glory_guild", &battle_config.require_glory_guild, 0, 0, 1, }, + { "idle_no_share", &battle_config.idle_no_share, 0, 0, INT_MAX, }, + { "party_even_share_bonus", &battle_config.party_even_share_bonus, 0, 0, INT_MAX, }, + { "delay_battle_damage", &battle_config.delay_battle_damage, 1, 0, 1, }, + { "hide_woe_damage", &battle_config.hide_woe_damage, 0, 0, 1, }, + { "display_version", &battle_config.display_version, 1, 0, 1, }, + { "display_hallucination", &battle_config.display_hallucination, 1, 0, 1, }, + { "use_statpoint_table", &battle_config.use_statpoint_table, 1, 0, 1, }, + { "ignore_items_gender", &battle_config.ignore_items_gender, 1, 0, 1, }, + { "copyskill_restrict", &battle_config.copyskill_restrict, 2, 0, 2, }, + { "berserk_cancels_buffs", &battle_config.berserk_cancels_buffs, 0, 0, 1, }, + { "debuff_on_logout", &battle_config.debuff_on_logout, 1|2, 0, 1|2, }, + { "monster_ai", &battle_config.mob_ai, 0x000, 0x000, 0x77F, }, + { "hom_setting", &battle_config.hom_setting, 0xFFFF, 0x0000, 0xFFFF, }, + { "dynamic_mobs", &battle_config.dynamic_mobs, 1, 0, 1, }, + { "mob_remove_damaged", &battle_config.mob_remove_damaged, 1, 0, 1, }, + { "show_hp_sp_drain", &battle_config.show_hp_sp_drain, 0, 0, 1, }, + { "show_hp_sp_gain", &battle_config.show_hp_sp_gain, 1, 0, 1, }, + { "mob_npc_event_type", &battle_config.mob_npc_event_type, 1, 0, 1, }, + { "character_size", &battle_config.character_size, 1|2, 0, 1|2, }, + { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, MAX_SKILL_LEVEL, 1, MAX_SKILL_LEVEL, }, + { "retaliate_to_master", &battle_config.retaliate_to_master, 1, 0, 1, }, + { "rare_drop_announce", &battle_config.rare_drop_announce, 0, 0, 10000, }, + { "duel_allow_pvp", &battle_config.duel_allow_pvp, 0, 0, 1, }, + { "duel_allow_gvg", &battle_config.duel_allow_gvg, 0, 0, 1, }, + { "duel_allow_teleport", &battle_config.duel_allow_teleport, 0, 0, 1, }, + { "duel_autoleave_when_die", &battle_config.duel_autoleave_when_die, 1, 0, 1, }, + { "duel_time_interval", &battle_config.duel_time_interval, 60, 0, INT_MAX, }, + { "duel_only_on_same_map", &battle_config.duel_only_on_same_map, 0, 0, 1, }, + { "skip_teleport_lv1_menu", &battle_config.skip_teleport_lv1_menu, 0, 0, 1, }, + { "allow_skill_without_day", &battle_config.allow_skill_without_day, 0, 0, 1, }, + { "allow_es_magic_player", &battle_config.allow_es_magic_pc, 0, 0, 1, }, + { "skill_caster_check", &battle_config.skill_caster_check, 1, 0, 1, }, + { "status_cast_cancel", &battle_config.sc_castcancel, BL_NUL, BL_NUL, BL_ALL, }, + { "pc_status_def_rate", &battle_config.pc_sc_def_rate, 100, 0, INT_MAX, }, + { "mob_status_def_rate", &battle_config.mob_sc_def_rate, 100, 0, INT_MAX, }, + { "pc_luk_status_def", &battle_config.pc_luk_sc_def, 300, 1, INT_MAX, }, + { "mob_luk_status_def", &battle_config.mob_luk_sc_def, 300, 1, INT_MAX, }, + { "pc_max_status_def", &battle_config.pc_max_sc_def, 100, 0, INT_MAX, }, + { "mob_max_status_def", &battle_config.mob_max_sc_def, 100, 0, INT_MAX, }, + { "sg_miracle_skill_ratio", &battle_config.sg_miracle_skill_ratio, 1, 0, 10000, }, + { "sg_angel_skill_ratio", &battle_config.sg_angel_skill_ratio, 10, 0, 10000, }, + { "autospell_stacking", &battle_config.autospell_stacking, 0, 0, 1, }, + { "override_mob_names", &battle_config.override_mob_names, 0, 0, 2, }, + { "min_chat_delay", &battle_config.min_chat_delay, 0, 0, INT_MAX, }, + { "friend_auto_add", &battle_config.friend_auto_add, 1, 0, 1, }, + { "hom_rename", &battle_config.hom_rename, 0, 0, 1, }, + { "homunculus_show_growth", &battle_config.homunculus_show_growth, 0, 0, 1, }, + { "homunculus_friendly_rate", &battle_config.homunculus_friendly_rate, 100, 0, INT_MAX, }, + { "vending_tax", &battle_config.vending_tax, 0, 0, 10000, }, + { "day_duration", &battle_config.day_duration, 0, 0, INT_MAX, }, + { "night_duration", &battle_config.night_duration, 0, 0, INT_MAX, }, + { "mob_remove_delay", &battle_config.mob_remove_delay, 60000, 1000, INT_MAX, }, + { "mob_active_time", &battle_config.mob_active_time, 0, 0, INT_MAX, }, + { "boss_active_time", &battle_config.boss_active_time, 0, 0, INT_MAX, }, + { "sg_miracle_skill_duration", &battle_config.sg_miracle_skill_duration, 3600000, 0, INT_MAX, }, + { "hvan_explosion_intimate", &battle_config.hvan_explosion_intimate, 45000, 0, 100000, }, + { "quest_exp_rate", &battle_config.quest_exp_rate, 100, 0, INT_MAX, }, + { "at_mapflag", &battle_config.autotrade_mapflag, 0, 0, 1, }, + { "at_timeout", &battle_config.at_timeout, 0, 0, INT_MAX, }, + { "homunculus_autoloot", &battle_config.homunculus_autoloot, 0, 0, 1, }, + { "idle_no_autoloot", &battle_config.idle_no_autoloot, 0, 0, INT_MAX, }, + { "max_guild_alliance", &battle_config.max_guild_alliance, 3, 0, 3, }, + { "ksprotection", &battle_config.ksprotection, 5000, 0, INT_MAX, }, + { "auction_feeperhour", &battle_config.auction_feeperhour, 12000, 0, INT_MAX, }, + { "auction_maximumprice", &battle_config.auction_maximumprice, 500000000, 0, MAX_ZENY, }, + { "homunculus_auto_vapor", &battle_config.homunculus_auto_vapor, 1, 0, 1, }, + { "display_status_timers", &battle_config.display_status_timers, 1, 0, 1, }, + { "skill_add_heal_rate", &battle_config.skill_add_heal_rate, 7, 0, INT_MAX, }, + { "eq_single_target_reflectable", &battle_config.eq_single_target_reflectable, 1, 0, 1, }, + { "invincible.nodamage", &battle_config.invincible_nodamage, 0, 0, 1, }, + { "mob_slave_keep_target", &battle_config.mob_slave_keep_target, 0, 0, 1, }, + { "autospell_check_range", &battle_config.autospell_check_range, 0, 0, 1, }, + { "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, }, + { "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, }, + { "feature.buying_store", &battle_config.feature_buying_store, 1, 0, 1, }, + { "feature.search_stores", &battle_config.feature_search_stores, 1, 0, 1, }, + { "searchstore_querydelay", &battle_config.searchstore_querydelay, 10, 0, INT_MAX, }, + { "searchstore_maxresults", &battle_config.searchstore_maxresults, 30, 1, INT_MAX, }, + { "display_party_name", &battle_config.display_party_name, 0, 0, 1, }, + { "cashshop_show_points", &battle_config.cashshop_show_points, 0, 0, 1, }, + { "mail_show_status", &battle_config.mail_show_status, 0, 0, 2, }, + { "client_limit_unit_lv", &battle_config.client_limit_unit_lv, 0, 0, BL_ALL, }, +// BattleGround Settings + { "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, }, + { "bg_short_attack_damage_rate", &battle_config.bg_short_damage_rate, 80, 0, INT_MAX, }, + { "bg_long_attack_damage_rate", &battle_config.bg_long_damage_rate, 80, 0, INT_MAX, }, + { "bg_weapon_attack_damage_rate", &battle_config.bg_weapon_damage_rate, 60, 0, INT_MAX, }, + { "bg_magic_attack_damage_rate", &battle_config.bg_magic_damage_rate, 60, 0, INT_MAX, }, + { "bg_misc_attack_damage_rate", &battle_config.bg_misc_damage_rate, 60, 0, INT_MAX, }, + { "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, }, + /** + * rAthena + **/ + { "max_third_parameter", &battle_config.max_third_parameter, 120, 10, 10000, }, + { "max_baby_third_parameter", &battle_config.max_baby_third_parameter, 108, 10, 10000, }, + { "atcommand_max_stat_bypass", &battle_config.atcommand_max_stat_bypass, 0, 0, 100, }, + { "skill_amotion_leniency", &battle_config.skill_amotion_leniency, 90, 0, 100 }, + { "mvp_tomb_enabled", &battle_config.mvp_tomb_enabled, 1, 0, 1 }, + { "feature.atcommand_suggestions", &battle_config.atcommand_suggestions_enabled, 0, 0, 1 }, + { "min_npc_vending_distance", &battle_config.min_npc_vending_distance, 3, 0, 100 }, + { "atcommand_mobinfo_type", &battle_config.atcommand_mobinfo_type, 0, 0, 1 }, + { "homunculus_max_level", &battle_config.hom_max_level, 99, 0, MAX_LEVEL, }, + { "homunculus_S_max_level", &battle_config.hom_S_max_level, 150, 0, MAX_LEVEL, }, + { "mob_size_influence", &battle_config.mob_size_influence, 0, 0, 1, }, }; #ifndef STATS_OPT_OUT /** * rAthena anonymous statistic usage report -- packet is built here, and sent to char server to report. **/ -void rAthena_report(char *date, char *time_c) -{ - int i, rev = 0, bd_size = ARRAYLENGTH(battle_data); - unsigned int config = 0; - const char *rev_str; - char timestring[25]; - time_t curtime; - char *buf; - - enum config_table { - C_CIRCULAR_AREA = 0x0001, - C_CELLNOSTACK = 0x0002, - C_BETA_THREAD_TEST = 0x0004, - C_SCRIPT_CALLFUNC_CHECK = 0x0008, - C_OFFICIAL_WALKPATH = 0x0010, - C_RENEWAL = 0x0020, - C_RENEWAL_CAST = 0x0040, - C_RENEWAL_DROP = 0x0080, - C_RENEWAL_EXP = 0x0100, - C_RENEWAL_LVDMG = 0x0200, - C_RENEWAL_EDP = 0x0400, - C_RENEWAL_ASPD = 0x0800, - C_SECURE_NPCTIMEOUT = 0x1000, - C_SQL_DBS = 0x2000, - C_SQL_LOGS = 0x4000, - }; - - if ((rev_str = get_svn_revision()) != 0) - rev = atoi(rev_str); - - /* we get the current time */ - time(&curtime); - strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", localtime(&curtime)); +void rAthena_report(char* date, char *time_c) { + int i, rev = 0, bd_size = ARRAYLENGTH(battle_data); + unsigned int config = 0; + const char* rev_str; + char timestring[25]; + time_t curtime; + char* buf; + + enum config_table { + C_CIRCULAR_AREA = 0x0001, + C_CELLNOSTACK = 0x0002, + C_BETA_THREAD_TEST = 0x0004, + C_SCRIPT_CALLFUNC_CHECK = 0x0008, + C_OFFICIAL_WALKPATH = 0x0010, + C_RENEWAL = 0x0020, + C_RENEWAL_CAST = 0x0040, + C_RENEWAL_DROP = 0x0080, + C_RENEWAL_EXP = 0x0100, + C_RENEWAL_LVDMG = 0x0200, + C_RENEWAL_EDP = 0x0400, + C_RENEWAL_ASPD = 0x0800, + C_SECURE_NPCTIMEOUT = 0x1000, + C_SQL_DBS = 0x2000, + C_SQL_LOGS = 0x4000, + }; + + if( (rev_str = get_svn_revision()) != 0 ) + rev = atoi(rev_str); + + /* we get the current time */ + time(&curtime); + strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", localtime(&curtime)); #ifdef CIRCULAR_AREA - config |= C_CIRCULAR_AREA; + config |= C_CIRCULAR_AREA; #endif #ifdef CELL_NOSTACK - config |= C_CELLNOSTACK; + config |= C_CELLNOSTACK; #endif #ifdef BETA_THREAD_TEST - config |= C_BETA_THREAD_TEST; + config |= C_BETA_THREAD_TEST; #endif #ifdef SCRIPT_CALLFUNC_CHECK - config |= C_SCRIPT_CALLFUNC_CHECK; + config |= C_SCRIPT_CALLFUNC_CHECK; #endif #ifdef OFFICIAL_WALKPATH - config |= C_OFFICIAL_WALKPATH; + config |= C_OFFICIAL_WALKPATH; #endif #ifdef RENEWAL - config |= C_RENEWAL; + config |= C_RENEWAL; #endif #ifdef RENEWAL_CAST - config |= C_RENEWAL_CAST; + config |= C_RENEWAL_CAST; #endif #ifdef RENEWAL_DROP - config |= C_RENEWAL_DROP; + config |= C_RENEWAL_DROP; #endif #ifdef RENEWAL_EXP - config |= C_RENEWAL_EXP; + config |= C_RENEWAL_EXP; #endif #ifdef RENEWAL_LVDMG - config |= C_RENEWAL_LVDMG; + config |= C_RENEWAL_LVDMG; #endif #ifdef RENEWAL_EDP - config |= C_RENEWAL_EDP; + config |= C_RENEWAL_EDP; #endif #ifdef RENEWAL_ASPD - config |= C_RENEWAL_ASPD; + config |= C_RENEWAL_ASPD; #endif - /* not a ifdef because SECURE_NPCTIMEOUT is always defined, but either as 0 or higher */ +/* not a ifdef because SECURE_NPCTIMEOUT is always defined, but either as 0 or higher */ #if SECURE_NPCTIMEOUT - config |= C_SECURE_NPCTIMEOUT; + config |= C_SECURE_NPCTIMEOUT; #endif - /* non-define part */ - if (db_use_sqldbs) - config |= C_SQL_DBS; + /* non-define part */ + if( db_use_sqldbs ) + config |= C_SQL_DBS; - if (log_config.sql_logs) - config |= C_SQL_LOGS; + if( log_config.sql_logs ) + config |= C_SQL_LOGS; #define BFLAG_LENGTH 35 - CREATE(buf, char, 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + (bd_size * (BFLAG_LENGTH + 4)) + 1); + CREATE(buf, char, 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) + 1 ); - /* build packet */ + /* build packet */ - WBUFW(buf,0) = 0x3000; - WBUFW(buf,2) = 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + (bd_size * (BFLAG_LENGTH + 4)); - WBUFW(buf,4) = 0x9c; + WBUFW(buf,0) = 0x3000; + WBUFW(buf,2) = 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ); + WBUFW(buf,4) = 0x9c; - safestrncpy((char *)WBUFP(buf,6), date, 12); - safestrncpy((char *)WBUFP(buf,6 + 12), time_c, 9); - safestrncpy((char *)WBUFP(buf,6 + 12 + 9), timestring, 24); + safestrncpy((char*)WBUFP(buf,6), date, 12); + safestrncpy((char*)WBUFP(buf,6 + 12), time_c, 9); + safestrncpy((char*)WBUFP(buf,6 + 12 + 9), timestring, 24); - WBUFL(buf,6 + 12 + 9 + 24) = rev; - WBUFL(buf,6 + 12 + 9 + 24 + 4) = map_getusers(); + WBUFL(buf,6 + 12 + 9 + 24) = rev; + WBUFL(buf,6 + 12 + 9 + 24 + 4) = map_getusers(); - WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4) = config; - WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4 + 4) = bd_size; + WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4) = config; + WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4 + 4) = bd_size; - for (i = 0; i < bd_size; i++) { - safestrncpy((char *)WBUFP(buf,6 + 12 + 9+ 24 + 4 + 4 + 4 + 4 + (i * (BFLAG_LENGTH + 4))), battle_data[i].str, 35); - WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + BFLAG_LENGTH + (i * (BFLAG_LENGTH + 4))) = *battle_data[i].val; - } + for( i = 0; i < bd_size; i++ ) { + safestrncpy((char*)WBUFP(buf,6 + 12 + 9+ 24 + 4 + 4 + 4 + 4 + ( i * ( BFLAG_LENGTH + 4 ) ) ), battle_data[i].str, 35); + WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + BFLAG_LENGTH + ( i * ( BFLAG_LENGTH + 4 ) ) ) = *battle_data[i].val; + } - chrif_send_report(buf, 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + (bd_size * (BFLAG_LENGTH + 4))); + chrif_send_report(buf, 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) ); - aFree(buf); + aFree(buf); #undef BFLAG_LENGTH } -static int rAthena_report_timer(int tid, unsigned int tick, int id, intptr_t data) -{ - if (chrif_isconnected()) { /* char server relays it, so it must be online. */ - rAthena_report(__DATE__,__TIME__); - } - return 0; +static int rAthena_report_timer(int tid, unsigned int tick, int id, intptr_t data) { + if( chrif_isconnected() ) {/* char server relays it, so it must be online. */ + rAthena_report(__DATE__,__TIME__); + } + return 0; } #endif -int battle_set_value(const char *w1, const char *w2) +int battle_set_value(const char* w1, const char* w2) { - int val = config_switch(w2); - - int i; - ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); - if (i == ARRAYLENGTH(battle_data)) - return 0; // not found + int val = config_switch(w2); - if (val < battle_data[i].min || val > battle_data[i].max) { - ShowWarning("Value for setting '%s': %s is invalid (min:%i max:%i)! Defaulting to %i...\n", w1, w2, battle_data[i].min, battle_data[i].max, battle_data[i].defval); - val = battle_data[i].defval; - } + int i; + ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); + if (i == ARRAYLENGTH(battle_data)) + return 0; // not found + + if (val < battle_data[i].min || val > battle_data[i].max) + { + ShowWarning("Value for setting '%s': %s is invalid (min:%i max:%i)! Defaulting to %i...\n", w1, w2, battle_data[i].min, battle_data[i].max, battle_data[i].defval); + val = battle_data[i].defval; + } - *battle_data[i].val = val; - return 1; + *battle_data[i].val = val; + return 1; } -int battle_get_value(const char *w1) +int battle_get_value(const char* w1) { - int i; - ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); - if (i == ARRAYLENGTH(battle_data)) - return 0; // not found - else - return *battle_data[i].val; + int i; + ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); + if (i == ARRAYLENGTH(battle_data)) + return 0; // not found + else + return *battle_data[i].val; } void battle_set_defaults() { - int i; - for (i = 0; i < ARRAYLENGTH(battle_data); i++) - *battle_data[i].val = battle_data[i].defval; + int i; + for (i = 0; i < ARRAYLENGTH(battle_data); i++) + *battle_data[i].val = battle_data[i].defval; } void battle_adjust_conf() { - battle_config.monster_max_aspd = 2000 - battle_config.monster_max_aspd*10; - battle_config.max_aspd = 2000 - battle_config.max_aspd*10; - battle_config.max_third_aspd = 2000 - battle_config.max_third_aspd*10; - battle_config.max_walk_speed = 100*DEFAULT_WALK_SPEED/battle_config.max_walk_speed; - battle_config.max_cart_weight *= 10; + battle_config.monster_max_aspd = 2000 - battle_config.monster_max_aspd*10; + battle_config.max_aspd = 2000 - battle_config.max_aspd*10; + battle_config.max_third_aspd = 2000 - battle_config.max_third_aspd*10; + battle_config.max_walk_speed = 100*DEFAULT_WALK_SPEED/battle_config.max_walk_speed; + battle_config.max_cart_weight *= 10; - if (battle_config.max_def > 100 && !battle_config.weapon_defense_type) // added by [Skotlex] - battle_config.max_def = 100; + if(battle_config.max_def > 100 && !battle_config.weapon_defense_type) // added by [Skotlex] + battle_config.max_def = 100; - if (battle_config.min_hitrate > battle_config.max_hitrate) - battle_config.min_hitrate = battle_config.max_hitrate; + if(battle_config.min_hitrate > battle_config.max_hitrate) + battle_config.min_hitrate = battle_config.max_hitrate; - if (battle_config.pet_max_atk1 > battle_config.pet_max_atk2) //Skotlex - battle_config.pet_max_atk1 = battle_config.pet_max_atk2; + if(battle_config.pet_max_atk1 > battle_config.pet_max_atk2) //Skotlex + battle_config.pet_max_atk1 = battle_config.pet_max_atk2; - if (battle_config.day_duration && battle_config.day_duration < 60000) // added by [Yor] - battle_config.day_duration = 60000; - if (battle_config.night_duration && battle_config.night_duration < 60000) // added by [Yor] - battle_config.night_duration = 60000; + if (battle_config.day_duration && battle_config.day_duration < 60000) // added by [Yor] + battle_config.day_duration = 60000; + if (battle_config.night_duration && battle_config.night_duration < 60000) // added by [Yor] + battle_config.night_duration = 60000; #if PACKETVER < 20100427 - if (battle_config.feature_buying_store) { - ShowWarning("conf/battle/feature.conf buying_store is enabled but it requires PACKETVER 2010-04-27 or newer, disabling...\n"); - battle_config.feature_buying_store = 0; - } + if( battle_config.feature_buying_store ) { + ShowWarning("conf/battle/feature.conf buying_store is enabled but it requires PACKETVER 2010-04-27 or newer, disabling...\n"); + battle_config.feature_buying_store = 0; + } #endif #if PACKETVER < 20100803 - if (battle_config.feature_search_stores) { - ShowWarning("conf/battle/feature.conf search_stores is enabled but it requires PACKETVER 2010-08-03 or newer, disabling...\n"); - battle_config.feature_search_stores = 0; - } + if( battle_config.feature_search_stores ) { + ShowWarning("conf/battle/feature.conf search_stores is enabled but it requires PACKETVER 2010-08-03 or newer, disabling...\n"); + battle_config.feature_search_stores = 0; + } #endif #ifndef CELL_NOSTACK - if (battle_config.cell_stack_limit != 1) - ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n"); + if (battle_config.cell_stack_limit != 1) + ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n"); #endif } -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) - battle_set_defaults(); - - count++; - - fp = fopen(cfgName,"r"); - if (fp == NULL) - ShowError("File not found: %s\n", cfgName); - else { - while (fgets(line, sizeof(line), fp)) { - if (line[0] == '/' && line[1] == '/') - continue; - if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2) - continue; - if (strcmpi(w1, "import") == 0) - battle_config_read(w2); - else if (battle_set_value(w1, w2) == 0) - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); - } + char line[1024], w1[1024], w2[1024]; + FILE* fp; + static int count = 0; + + if (count == 0) + battle_set_defaults(); + + count++; + + fp = fopen(cfgName,"r"); + if (fp == NULL) + ShowError("File not found: %s\n", cfgName); + else + { + while(fgets(line, sizeof(line), fp)) + { + if (line[0] == '/' && line[1] == '/') + continue; + if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2) + continue; + if (strcmpi(w1, "import") == 0) + battle_config_read(w2); + else + if (battle_set_value(w1, w2) == 0) + ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); + } - fclose(fp); - } + fclose(fp); + } - count--; + count--; - if (count == 0) - battle_adjust_conf(); + if (count == 0) + battle_adjust_conf(); - return 0; + return 0; } void do_init_battle(void) { - delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR); - add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub"); + delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR); + add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub"); #ifndef STATS_OPT_OUT - add_timer_func_list(rAthena_report_timer, "rAthena_report_timer"); - add_timer_interval(gettick()+30000, rAthena_report_timer, 0, 0, 60000 * 30); + add_timer_func_list(rAthena_report_timer, "rAthena_report_timer"); + add_timer_interval(gettick()+30000, rAthena_report_timer, 0, 0, 60000 * 30); #endif } void do_final_battle(void) { - ers_destroy(delay_damage_ers); + ers_destroy(delay_damage_ers); } diff --git a/src/map/battle.h b/src/map/battle.h index 17d7bd28e..b901644de 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -6,22 +6,22 @@ // state of a single attack attempt; used in flee/def penalty calculations when mobbed typedef enum damage_lv { - ATK_NONE, // not an attack - ATK_LUCKY, // attack was lucky-dodged - ATK_FLEE, // attack was dodged - ATK_MISS, // attack missed because of element/race modifier. - ATK_BLOCK, // attack was blocked by some skills. - ATK_DEF // attack connected + ATK_NONE, // not an attack + ATK_LUCKY, // attack was lucky-dodged + ATK_FLEE, // attack was dodged + ATK_MISS, // attack missed because of element/race modifier. + ATK_BLOCK, // attack was blocked by some skills. + ATK_DEF // attack connected } damage_lv; // dammage structure struct Damage { - int damage,damage2; //right, left dmg - int type,div_; //chk clif_damage for type @TODO add an enum ? ; nb of hit - int amotion,dmotion; - int blewcount; //nb of knockback - int flag; //chk BF_* flag, (enum below) - enum damage_lv dmg_lv; //ATK_LUCKY,ATK_FLEE,ATK_DEF + int damage,damage2; //right, left dmg + int type,div_; //chk clif_damage for type @TODO add an enum ? ; nb of hit + int amotion,dmotion; + int blewcount; //nb of knockback + int flag; //chk BF_* flag, (enum below) + enum damage_lv dmg_lv; //ATK_LUCKY,ATK_FLEE,ATK_DEF }; //(Used in read pc.c,) attribute table (battle_attr_fix) @@ -41,59 +41,58 @@ void battle_drain(struct map_session_data *sd, struct block_list *tbl, int rdama int battle_attr_ratio(int atk_elem,int def_type, int def_lv); int battle_attr_fix(struct block_list *src, struct block_list *target, int damage,int atk_elem,int def_type, int def_lv); -int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag); // Final calculation Damage int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int damage,int skill_num,int skill_lv); int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag); int battle_calc_bg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag); -enum { // Flag of the final calculation - BF_WEAPON = 0x0001, - BF_MAGIC = 0x0002, - BF_MISC = 0x0004, - BF_SHORT = 0x0010, - BF_LONG = 0x0040, - BF_SKILL = 0x0100, - BF_NORMAL = 0x0200, - BF_WEAPONMASK=0x000f, - BF_RANGEMASK= 0x00f0, - BF_SKILLMASK= 0x0f00, +enum { // Flag of the final calculation + BF_WEAPON = 0x0001, + BF_MAGIC = 0x0002, + BF_MISC = 0x0004, + BF_SHORT = 0x0010, + BF_LONG = 0x0040, + BF_SKILL = 0x0100, + BF_NORMAL = 0x0200, + BF_WEAPONMASK=0x000f, + BF_RANGEMASK= 0x00f0, + BF_SKILLMASK= 0x0f00, }; -int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, int skill_id, int skill_lv, int damage, enum damage_lv dmg_lv, int ddelay); +int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, int skill_id, int skill_lv, int damage, enum damage_lv dmg_lv, int ddelay); // Summary normal attack treatment (basic attack) -enum damage_lv battle_weapon_attack(struct block_list *bl,struct block_list *target,unsigned int tick,int flag); +enum damage_lv battle_weapon_attack( struct block_list *bl,struct block_list *target,unsigned int tick,int flag); // Accessors -struct block_list *battle_get_master(struct block_list *src); -struct block_list *battle_gettargeted(struct block_list *target); -struct block_list *battle_getenemy(struct block_list *target, int type, int range); +struct block_list* battle_get_master(struct block_list *src); +struct block_list* battle_gettargeted(struct block_list *target); +struct block_list* battle_getenemy(struct block_list *target, int type, int range); int battle_gettarget(struct block_list *bl); int battle_getcurrentskill(struct block_list *bl); -enum e_battle_check_target { - //New definitions [Skotlex] - BCT_ENEMY = 0x020000, - BCT_NOENEMY = 0x1d0000, //This should be (~BCT_ENEMY&BCT_ALL) - BCT_PARTY = 0x040000, - BCT_NOPARTY = 0x1b0000, //This should be (~BCT_PARTY&BCT_ALL) - BCT_GUILD = 0x080000, - BCT_NOGUILD = 0x170000, //This should be (~BCT_GUILD&BCT_ALL) - BCT_ALL = 0x1f0000, - BCT_NOONE = 0x000000, - BCT_SELF = 0x010000, - BCT_NEUTRAL = 0x100000, +enum e_battle_check_target +{//New definitions [Skotlex] + BCT_ENEMY = 0x020000, + BCT_NOENEMY = 0x1d0000, //This should be (~BCT_ENEMY&BCT_ALL) + BCT_PARTY = 0x040000, + BCT_NOPARTY = 0x1b0000, //This should be (~BCT_PARTY&BCT_ALL) + BCT_GUILD = 0x080000, + BCT_NOGUILD = 0x170000, //This should be (~BCT_GUILD&BCT_ALL) + BCT_ALL = 0x1f0000, + BCT_NOONE = 0x000000, + BCT_SELF = 0x010000, + BCT_NEUTRAL = 0x100000, }; -#define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru] +#define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru] int battle_check_undead(int race,int element); int battle_check_target(struct block_list *src, struct block_list *target,int flag); bool battle_check_range(struct block_list *src,struct block_list *bl,int range); -void battle_consume_ammo(struct map_session_data *sd, int skill, int lv); +void battle_consume_ammo(struct map_session_data* sd, int skill, int lv); // Settings #define MIN_HAIR_STYLE battle_config.min_hair_style @@ -103,385 +102,386 @@ void battle_consume_ammo(struct map_session_data *sd, int skill, int lv); #define MIN_CLOTH_COLOR battle_config.min_cloth_color #define MAX_CLOTH_COLOR battle_config.max_cloth_color -extern struct Battle_Config { - int warp_point_debug; - int enable_critical; - int mob_critical_rate; - int critical_rate; - int enable_baseatk; - int enable_perfect_flee; - int cast_rate, delay_rate; - int delay_dependon_dex, delay_dependon_agi; - int sdelay_attack_enable; - int left_cardfix_to_right; - int skill_add_range; - int skill_out_range_consume; - int skill_amotion_leniency; - int skillrange_by_distance; //[Skotlex] - int use_weapon_skill_range; //[Skotlex] - int pc_damage_delay_rate; - int defnotenemy; - int vs_traps_bctall; - int traps_setting; - int summon_flora; //[Skotlex] - int clear_unit_ondeath; //[Skotlex] - int clear_unit_onwarp; //[Skotlex] - int random_monster_checklv; - int attr_recover; - int item_auto_get; - int flooritem_lifetime; - int item_first_get_time; - int item_second_get_time; - int item_third_get_time; - int mvp_item_first_get_time; - int mvp_item_second_get_time; - int mvp_item_third_get_time; - int base_exp_rate,job_exp_rate; - int drop_rate0item; - int death_penalty_type; - int death_penalty_base,death_penalty_job; - int pvp_exp; // [MouseJstr] - int gtb_sc_immunity; - int zeny_penalty; - int restart_hp_rate; - int restart_sp_rate; - int mvp_exp_rate; - int mvp_hp_rate; - int monster_hp_rate; - int monster_max_aspd; - int view_range_rate; - int chase_range_rate; - int atc_spawn_quantity_limit; - int atc_slave_clone_limit; - int partial_name_scan; - int skillfree; - int skillup_limit; - int wp_rate; - int pp_rate; - int monster_active_enable; - int monster_damage_delay_rate; - int monster_loot_type; - int mob_skill_rate; //[Skotlex] - int mob_skill_delay; //[Skotlex] - int mob_count_rate; - int no_spawn_on_player; //[Skotlex] - int force_random_spawn; //[Skotlex] - int mob_spawn_delay, plant_spawn_delay, boss_spawn_delay; // [Skotlex] - int slaves_inherit_mode; - int slaves_inherit_speed; - int summons_trigger_autospells; - int pc_walk_delay_rate; //Adjusts can't walk delay after being hit for players. [Skotlex] - int walk_delay_rate; //Adjusts can't walk delay after being hit. [Skotlex] - int multihit_delay; //Adjusts can't walk delay per hit on multi-hitting skills. [Skotlex] - int quest_skill_learn; - int quest_skill_reset; - int basic_skill_check; - int guild_emperium_check; - int guild_exp_limit; - int guild_max_castles; - int guild_skill_relog_delay; - int emergency_call; - int guild_aura; - int pc_invincible_time; - - int pet_catch_rate; - int pet_rename; - int pet_friendly_rate; - int pet_hungry_delay_rate; - int pet_hungry_friendly_decrease; - int pet_status_support; - int pet_attack_support; - int pet_damage_support; - int pet_support_min_friendly; //[Skotlex] - int pet_equip_min_friendly; - int pet_support_rate; - int pet_attack_exp_to_master; - int pet_attack_exp_rate; - int pet_lv_rate; //[Skotlex] - int pet_max_stats; //[Skotlex] - int pet_max_atk1; //[Skotlex] - int pet_max_atk2; //[Skotlex] - int pet_no_gvg; //Disables pets in gvg. [Skotlex] - int pet_equip_required; - - int skill_min_damage; - int finger_offensive_type; - int heal_exp; - int max_heal_lv; - int max_heal; //Mitternacht - int resurrection_exp; - int shop_exp; - int combo_delay_rate; - int item_check; - int item_use_interval; //[Skotlex] - int cashfood_use_interval; - int wedding_modifydisplay; - int wedding_ignorepalette; //[Skotlex] - int xmas_ignorepalette; // [Valaris] - int summer_ignorepalette; // [Zephyrus] - int natural_healhp_interval; - int natural_healsp_interval; - int natural_heal_skill_interval; - int natural_heal_weight_rate; - int arrow_decrement; - int max_aspd; - int max_walk_speed; //Maximum walking speed after buffs [Skotlex] - int max_hp; - int max_sp; - int max_lv, aura_lv; - int max_parameter, max_baby_parameter; - int max_cart_weight; - int skill_log; - int battle_log; - int etc_log; - int save_clothcolor; - int undead_detect_type; - int auto_counter_type; - int min_hitrate; //[Skotlex] - int max_hitrate; //[Skotlex] - int agi_penalty_target; - int agi_penalty_type; - int agi_penalty_count; - int agi_penalty_num; - int vit_penalty_target; - int vit_penalty_type; - int vit_penalty_count; - int vit_penalty_num; - int weapon_defense_type; - int magic_defense_type; - int skill_reiteration; - int skill_nofootset; - int pc_cloak_check_type; - int monster_cloak_check_type; - int estimation_type; - int gvg_short_damage_rate; - int gvg_long_damage_rate; - int gvg_weapon_damage_rate; - int gvg_magic_damage_rate; - int gvg_misc_damage_rate; - int gvg_flee_penalty; - int pk_short_damage_rate; - int pk_long_damage_rate; - int pk_weapon_damage_rate; - int pk_magic_damage_rate; - int pk_misc_damage_rate; - int mob_changetarget_byskill; - int attack_direction_change; - int land_skill_limit; - int monster_class_change_recover; - int produce_item_name_input; - int display_skill_fail; - int chat_warpportal; - int mob_warp; - int dead_branch_active; - int vending_max_value; - int vending_over_max; - int vending_tax; - int show_steal_in_same_party; - int party_share_type; - int party_hp_mode; - int party_show_share_picker; - int show_picker_item_type; - int attack_attr_none; - int item_rate_mvp, item_rate_common, item_rate_common_boss, item_rate_card, item_rate_card_boss, - item_rate_equip, item_rate_equip_boss, item_rate_heal, item_rate_heal_boss, item_rate_use, - item_rate_use_boss, item_rate_treasure, item_rate_adddrop; - - int logarithmic_drops; - int item_drop_common_min,item_drop_common_max; // Added by TyrNemesis^ - int item_drop_card_min,item_drop_card_max; - int item_drop_equip_min,item_drop_equip_max; - int item_drop_mvp_min,item_drop_mvp_max; // End Addition - int item_drop_heal_min,item_drop_heal_max; // Added by Valatris - int item_drop_use_min,item_drop_use_max; //End - int item_drop_treasure_min,item_drop_treasure_max; //by [Skotlex] - int item_drop_adddrop_min,item_drop_adddrop_max; //[Skotlex] - - int prevent_logout; // Added by RoVeRT - - int alchemist_summon_reward; // [Valaris] - int drops_by_luk; - int drops_by_luk2; - int equip_natural_break_rate; //Base Natural break rate for attacks. - int equip_self_break_rate; //Natural & Penalty skills break rate - int equip_skill_break_rate; //Offensive skills break rate - int multi_level_up; - int max_exp_gain_rate; //Max amount of exp bar % you can get in one go. - int pk_mode; - int pk_level_range; - - int manner_system; // end additions [Valaris] - int show_mob_info; - - int gx_allhit; - int gx_disptype; - int devotion_level_difference; - int player_skill_partner_check; - int invite_request_check; - int skill_removetrap_type; - int disp_experience; - int disp_zeny; - int castle_defense_rate; - int backstab_bow_penalty; - int hp_rate; - int sp_rate; - int bone_drop; - int buyer_name; - int dancing_weaponswitch_fix; - - // eAthena additions - int night_at_start; // added by [Yor] - int day_duration; // added by [Yor] - int night_duration; // added by [Yor] - int ban_hack_trade; // added by [Yor] - int packet_ver_flag; // added by [Yor] - - int min_hair_style; // added by [MouseJstr] - int max_hair_style; // added by [MouseJstr] - int min_hair_color; // added by [MouseJstr] - int max_hair_color; // added by [MouseJstr] - int min_cloth_color; // added by [MouseJstr] - int max_cloth_color; // added by [MouseJstr] - int pet_hair_style; // added by [Skotlex] - - int castrate_dex_scale; // added by [MouseJstr] - int area_size; // added by [MouseJstr] - - int max_def, over_def_bonus; //added by [Skotlex] - - int zeny_from_mobs; // [Valaris] - int mobs_level_up; // [Valaris] - int mobs_level_up_exp_rate; // [Valaris] - int pk_min_level; // [celest] - int skill_steal_max_tries; //max steal skill tries on a mob. if 0, then w/o limit [Lupus] - int motd_type; // [celest] - int finding_ore_rate; // orn - int exp_calc_type; - int exp_bonus_attacker; - int exp_bonus_max_attacker; - int min_skill_delay_limit; - int default_walk_delay; - int no_skill_delay; - int attack_walk_delay; - int require_glory_guild; - int idle_no_share; - int party_update_interval; - int party_even_share_bonus; - int delay_battle_damage; - int hide_woe_damage; - int display_version; - - int display_hallucination; // [Skotlex] - int use_statpoint_table; // [Skotlex] - - int ignore_items_gender; //[Lupus] - - int copyskill_restrict; // [Aru] - int berserk_cancels_buffs; // [Aru] - int debuff_on_logout; // Removes a few "official" negative Scs on logout. [Skotlex] - int mob_ai; //Configures various mob_ai settings to make them smarter or dumber(official). [Skotlex] - int hom_setting; //Configures various homunc settings which make them behave unlike normal characters.. [Skotlex] - int dynamic_mobs; // Dynamic Mobs [Wizputer] - battle_athena flag implemented by [random] - int mob_remove_damaged; // Dynamic Mobs - Remove mobs even if damaged [Wizputer] - int mob_remove_delay; // Dynamic Mobs - delay before removing mobs from a map [Skotlex] - int mob_active_time; //Duration through which mobs execute their Hard AI after players leave their area of sight. - int boss_active_time; - - int show_hp_sp_drain, show_hp_sp_gain; //[Skotlex] - - int mob_npc_event_type; //Determines on who the npc_event is executed. [Skotlex] - - int character_size; // if riders have size=2, and baby class riders size=1 [Lupus] - int mob_max_skilllvl; // Max possible skill level [Lupus] - int rare_drop_announce; // chance <= to show rare drops global announces - - int retaliate_to_master; //Whether when a mob is attacked by another mob, it will retaliate versus the mob or the mob's master. [Skotlex] - - int duel_allow_pvp; // [LuzZza] - int duel_allow_gvg; // [LuzZza] - int duel_allow_teleport; // [LuzZza] - int duel_autoleave_when_die; // [LuzZza] - int duel_time_interval; // [LuzZza] - int duel_only_on_same_map; // [Toms] - - int skip_teleport_lv1_menu; // possibility to disable (skip) Teleport Lv1 menu, that have only two lines `Random` and `Cancel` [LuzZza] - - int allow_skill_without_day; // [Komurka] - int allow_es_magic_pc; // [Skotlex] - int skill_wall_check; // [Skotlex] - int cell_stack_limit; // [Skotlex] - int skill_caster_check; // [Skotlex] - int sc_castcancel; // [Skotlex] - int pc_sc_def_rate; // [Skotlex] - int mob_sc_def_rate; - int pc_luk_sc_def; - int mob_luk_sc_def; - int pc_max_sc_def; - int mob_max_sc_def; - - int sg_angel_skill_ratio; - int sg_miracle_skill_ratio; - int sg_miracle_skill_duration; - int autospell_stacking; //Enables autospell cards to stack. [Skotlex] - int override_mob_names; //Enables overriding spawn mob names with the mob_db names. [Skotlex] - int min_chat_delay; //Minimum time between client messages. [Skotlex] - int friend_auto_add; //When accepting friends, both get friended. [Skotlex] - int hvan_explosion_intimate; // fix [albator] - int hom_rename; - int homunculus_show_growth ; //[orn] - int homunculus_friendly_rate; - int quest_exp_rate; - int autotrade_mapflag; - int at_timeout; - int homunculus_autoloot; - int idle_no_autoloot; - int max_guild_alliance; - int ksprotection; - int auction_feeperhour; - int auction_maximumprice; - int homunculus_auto_vapor; //Keep Homunculus from Vaporizing when master dies. [L0ne_W0lf] - int display_status_timers; //Show or hide skill buff/delay timers in recent clients [Sara] - int skill_add_heal_rate; //skills that bHealPower has effect on [Inkfish] - int eq_single_target_reflectable; - int invincible_nodamage; - int mob_slave_keep_target; - int autospell_check_range; //Enable range check for autospell bonus. [L0ne_W0lf] - int client_reshuffle_dice; // Reshuffle /dice - int client_sort_storage; - int feature_buying_store; - int feature_search_stores; - int searchstore_querydelay; - int searchstore_maxresults; - int display_party_name; - int cashshop_show_points; - int mail_show_status; - int client_limit_unit_lv; - int hom_max_level; - int hom_S_max_level; - - // [BattleGround Settings] - int bg_update_interval; - int bg_short_damage_rate; - int bg_long_damage_rate; - int bg_weapon_damage_rate; - int bg_magic_damage_rate; - int bg_misc_damage_rate; - int bg_flee_penalty; - - // rAthena - int max_third_parameter; - int max_baby_third_parameter; - int atcommand_max_stat_bypass; - int max_third_aspd; - int vcast_stat_scale; - - int mvp_tomb_enabled; - - int atcommand_suggestions_enabled; +extern struct Battle_Config +{ + int warp_point_debug; + int enable_critical; + int mob_critical_rate; + int critical_rate; + int enable_baseatk; + int enable_perfect_flee; + int cast_rate, delay_rate; + int delay_dependon_dex, delay_dependon_agi; + int sdelay_attack_enable; + int left_cardfix_to_right; + int skill_add_range; + int skill_out_range_consume; + int skill_amotion_leniency; + int skillrange_by_distance; //[Skotlex] + int use_weapon_skill_range; //[Skotlex] + int pc_damage_delay_rate; + int defnotenemy; + int vs_traps_bctall; + int traps_setting; + int summon_flora; //[Skotlex] + int clear_unit_ondeath; //[Skotlex] + int clear_unit_onwarp; //[Skotlex] + int random_monster_checklv; + int attr_recover; + int item_auto_get; + int flooritem_lifetime; + int item_first_get_time; + int item_second_get_time; + int item_third_get_time; + int mvp_item_first_get_time; + int mvp_item_second_get_time; + int mvp_item_third_get_time; + int base_exp_rate,job_exp_rate; + int drop_rate0item; + int death_penalty_type; + int death_penalty_base,death_penalty_job; + int pvp_exp; // [MouseJstr] + int gtb_sc_immunity; + int zeny_penalty; + int restart_hp_rate; + int restart_sp_rate; + int mvp_exp_rate; + int mvp_hp_rate; + int monster_hp_rate; + int monster_max_aspd; + int view_range_rate; + int chase_range_rate; + int atc_spawn_quantity_limit; + int atc_slave_clone_limit; + int partial_name_scan; + int skillfree; + int skillup_limit; + int wp_rate; + int pp_rate; + int monster_active_enable; + int monster_damage_delay_rate; + int monster_loot_type; + int mob_skill_rate; //[Skotlex] + int mob_skill_delay; //[Skotlex] + int mob_count_rate; + int no_spawn_on_player; //[Skotlex] + int force_random_spawn; //[Skotlex] + int mob_spawn_delay, plant_spawn_delay, boss_spawn_delay; // [Skotlex] + int slaves_inherit_mode; + int slaves_inherit_speed; + int summons_trigger_autospells; + int pc_walk_delay_rate; //Adjusts can't walk delay after being hit for players. [Skotlex] + int walk_delay_rate; //Adjusts can't walk delay after being hit. [Skotlex] + int multihit_delay; //Adjusts can't walk delay per hit on multi-hitting skills. [Skotlex] + int quest_skill_learn; + int quest_skill_reset; + int basic_skill_check; + int guild_emperium_check; + int guild_exp_limit; + int guild_max_castles; + int guild_skill_relog_delay; + int emergency_call; + int guild_aura; + int pc_invincible_time; + + int pet_catch_rate; + int pet_rename; + int pet_friendly_rate; + int pet_hungry_delay_rate; + int pet_hungry_friendly_decrease; + int pet_status_support; + int pet_attack_support; + int pet_damage_support; + int pet_support_min_friendly; //[Skotlex] + int pet_equip_min_friendly; + int pet_support_rate; + int pet_attack_exp_to_master; + int pet_attack_exp_rate; + int pet_lv_rate; //[Skotlex] + int pet_max_stats; //[Skotlex] + int pet_max_atk1; //[Skotlex] + int pet_max_atk2; //[Skotlex] + int pet_no_gvg; //Disables pets in gvg. [Skotlex] + int pet_equip_required; + + int skill_min_damage; + int finger_offensive_type; + int heal_exp; + int max_heal_lv; + int max_heal; //Mitternacht + int resurrection_exp; + int shop_exp; + int combo_delay_rate; + int item_check; + int item_use_interval; //[Skotlex] + int cashfood_use_interval; + int wedding_modifydisplay; + int wedding_ignorepalette; //[Skotlex] + int xmas_ignorepalette; // [Valaris] + int summer_ignorepalette; // [Zephyrus] + int natural_healhp_interval; + int natural_healsp_interval; + int natural_heal_skill_interval; + int natural_heal_weight_rate; + int arrow_decrement; + int max_aspd; + int max_walk_speed; //Maximum walking speed after buffs [Skotlex] + int max_hp; + int max_sp; + int max_lv, aura_lv; + int max_parameter, max_baby_parameter; + int max_cart_weight; + int skill_log; + int battle_log; + int etc_log; + int save_clothcolor; + int undead_detect_type; + int auto_counter_type; + int min_hitrate; //[Skotlex] + int max_hitrate; //[Skotlex] + int agi_penalty_target; + int agi_penalty_type; + int agi_penalty_count; + int agi_penalty_num; + int vit_penalty_target; + int vit_penalty_type; + int vit_penalty_count; + int vit_penalty_num; + int weapon_defense_type; + int magic_defense_type; + int skill_reiteration; + int skill_nofootset; + int pc_cloak_check_type; + int monster_cloak_check_type; + int estimation_type; + int gvg_short_damage_rate; + int gvg_long_damage_rate; + int gvg_weapon_damage_rate; + int gvg_magic_damage_rate; + int gvg_misc_damage_rate; + int gvg_flee_penalty; + int pk_short_damage_rate; + int pk_long_damage_rate; + int pk_weapon_damage_rate; + int pk_magic_damage_rate; + int pk_misc_damage_rate; + int mob_changetarget_byskill; + int attack_direction_change; + int land_skill_limit; + int monster_class_change_recover; + int produce_item_name_input; + int display_skill_fail; + int chat_warpportal; + int mob_warp; + int dead_branch_active; + int vending_max_value; + int vending_over_max; + int vending_tax; + int show_steal_in_same_party; + int party_share_type; + int party_hp_mode; + int party_show_share_picker; + int show_picker_item_type; + int attack_attr_none; + int item_rate_mvp, item_rate_common, item_rate_common_boss, item_rate_card, item_rate_card_boss, + item_rate_equip, item_rate_equip_boss, item_rate_heal, item_rate_heal_boss, item_rate_use, + item_rate_use_boss, item_rate_treasure, item_rate_adddrop; + + int logarithmic_drops; + int item_drop_common_min,item_drop_common_max; // Added by TyrNemesis^ + int item_drop_card_min,item_drop_card_max; + int item_drop_equip_min,item_drop_equip_max; + int item_drop_mvp_min,item_drop_mvp_max; // End Addition + int item_drop_heal_min,item_drop_heal_max; // Added by Valatris + int item_drop_use_min,item_drop_use_max; //End + int item_drop_treasure_min,item_drop_treasure_max; //by [Skotlex] + int item_drop_adddrop_min,item_drop_adddrop_max; //[Skotlex] + + int prevent_logout; // Added by RoVeRT + + int alchemist_summon_reward; // [Valaris] + int drops_by_luk; + int drops_by_luk2; + int equip_natural_break_rate; //Base Natural break rate for attacks. + int equip_self_break_rate; //Natural & Penalty skills break rate + int equip_skill_break_rate; //Offensive skills break rate + int multi_level_up; + int max_exp_gain_rate; //Max amount of exp bar % you can get in one go. + int pk_mode; + int pk_level_range; + + int manner_system; // end additions [Valaris] + int show_mob_info; + + int gx_allhit; + int gx_disptype; + int devotion_level_difference; + int player_skill_partner_check; + int invite_request_check; + int skill_removetrap_type; + int disp_experience; + int disp_zeny; + int castle_defense_rate; + int backstab_bow_penalty; + int hp_rate; + int sp_rate; + int bone_drop; + int buyer_name; + int dancing_weaponswitch_fix; + +// eAthena additions + int night_at_start; // added by [Yor] + int day_duration; // added by [Yor] + int night_duration; // added by [Yor] + int ban_hack_trade; // added by [Yor] + int packet_ver_flag; // added by [Yor] + + int min_hair_style; // added by [MouseJstr] + int max_hair_style; // added by [MouseJstr] + int min_hair_color; // added by [MouseJstr] + int max_hair_color; // added by [MouseJstr] + int min_cloth_color; // added by [MouseJstr] + int max_cloth_color; // added by [MouseJstr] + int pet_hair_style; // added by [Skotlex] + + int castrate_dex_scale; // added by [MouseJstr] + int area_size; // added by [MouseJstr] + + int max_def, over_def_bonus; //added by [Skotlex] + + int zeny_from_mobs; // [Valaris] + int mobs_level_up; // [Valaris] + int mobs_level_up_exp_rate; // [Valaris] + int pk_min_level; // [celest] + int skill_steal_max_tries; //max steal skill tries on a mob. if 0, then w/o limit [Lupus] + int motd_type; // [celest] + int finding_ore_rate; // orn + int exp_calc_type; + int exp_bonus_attacker; + int exp_bonus_max_attacker; + int min_skill_delay_limit; + int default_walk_delay; + int no_skill_delay; + int attack_walk_delay; + int require_glory_guild; + int idle_no_share; + int party_update_interval; + int party_even_share_bonus; + int delay_battle_damage; + int hide_woe_damage; + int display_version; + + int display_hallucination; // [Skotlex] + int use_statpoint_table; // [Skotlex] + + int ignore_items_gender; //[Lupus] + + int copyskill_restrict; // [Aru] + int berserk_cancels_buffs; // [Aru] + int debuff_on_logout; // Removes a few "official" negative Scs on logout. [Skotlex] + int mob_ai; //Configures various mob_ai settings to make them smarter or dumber(official). [Skotlex] + int hom_setting; //Configures various homunc settings which make them behave unlike normal characters.. [Skotlex] + int dynamic_mobs; // Dynamic Mobs [Wizputer] - battle_athena flag implemented by [random] + int mob_remove_damaged; // Dynamic Mobs - Remove mobs even if damaged [Wizputer] + int mob_remove_delay; // Dynamic Mobs - delay before removing mobs from a map [Skotlex] + int mob_active_time; //Duration through which mobs execute their Hard AI after players leave their area of sight. + int boss_active_time; + + int show_hp_sp_drain, show_hp_sp_gain; //[Skotlex] + + int mob_npc_event_type; //Determines on who the npc_event is executed. [Skotlex] + + int character_size; // if riders have size=2, and baby class riders size=1 [Lupus] + int mob_max_skilllvl; // Max possible skill level [Lupus] + int rare_drop_announce; // chance <= to show rare drops global announces + + int retaliate_to_master; //Whether when a mob is attacked by another mob, it will retaliate versus the mob or the mob's master. [Skotlex] + + int duel_allow_pvp; // [LuzZza] + int duel_allow_gvg; // [LuzZza] + int duel_allow_teleport; // [LuzZza] + int duel_autoleave_when_die; // [LuzZza] + int duel_time_interval; // [LuzZza] + int duel_only_on_same_map; // [Toms] + + int skip_teleport_lv1_menu; // possibility to disable (skip) Teleport Lv1 menu, that have only two lines `Random` and `Cancel` [LuzZza] + + int allow_skill_without_day; // [Komurka] + int allow_es_magic_pc; // [Skotlex] + int skill_wall_check; // [Skotlex] + int cell_stack_limit; // [Skotlex] + int skill_caster_check; // [Skotlex] + int sc_castcancel; // [Skotlex] + int pc_sc_def_rate; // [Skotlex] + int mob_sc_def_rate; + int pc_luk_sc_def; + int mob_luk_sc_def; + int pc_max_sc_def; + int mob_max_sc_def; + + int sg_angel_skill_ratio; + int sg_miracle_skill_ratio; + int sg_miracle_skill_duration; + int autospell_stacking; //Enables autospell cards to stack. [Skotlex] + int override_mob_names; //Enables overriding spawn mob names with the mob_db names. [Skotlex] + int min_chat_delay; //Minimum time between client messages. [Skotlex] + int friend_auto_add; //When accepting friends, both get friended. [Skotlex] + int hvan_explosion_intimate; // fix [albator] + int hom_rename; + int homunculus_show_growth ; //[orn] + int homunculus_friendly_rate; + int quest_exp_rate; + int autotrade_mapflag; + int at_timeout; + int homunculus_autoloot; + int idle_no_autoloot; + int max_guild_alliance; + int ksprotection; + int auction_feeperhour; + int auction_maximumprice; + int homunculus_auto_vapor; //Keep Homunculus from Vaporizing when master dies. [L0ne_W0lf] + int display_status_timers; //Show or hide skill buff/delay timers in recent clients [Sara] + int skill_add_heal_rate; //skills that bHealPower has effect on [Inkfish] + int eq_single_target_reflectable; + int invincible_nodamage; + int mob_slave_keep_target; + int autospell_check_range; //Enable range check for autospell bonus. [L0ne_W0lf] + int client_reshuffle_dice; // Reshuffle /dice + int client_sort_storage; + int feature_buying_store; + int feature_search_stores; + int searchstore_querydelay; + int searchstore_maxresults; + int display_party_name; + int cashshop_show_points; + int mail_show_status; + int client_limit_unit_lv; + int hom_max_level; + int hom_S_max_level; + + // [BattleGround Settings] + int bg_update_interval; + int bg_short_damage_rate; + int bg_long_damage_rate; + int bg_weapon_damage_rate; + int bg_magic_damage_rate; + int bg_misc_damage_rate; + int bg_flee_penalty; + + // rAthena + int max_third_parameter; + int max_baby_third_parameter; + int atcommand_max_stat_bypass; + int max_third_aspd; + int vcast_stat_scale; + + int mvp_tomb_enabled; + + int atcommand_suggestions_enabled; int min_npc_vending_distance; - int atcommand_mobinfo_type; - - int mob_size_influence; // Enable modifications on earned experience, drop rates and monster status depending on monster size. [mkbu95] + int atcommand_mobinfo_type; + + int mob_size_influence; // Enable modifications on earned experience, drop rates and monster status depending on monster size. [mkbu95] } battle_config; void do_init_battle(void); @@ -489,14 +489,14 @@ void do_final_battle(void); extern int battle_config_read(const char *cfgName); extern void battle_validate_conf(void); extern void battle_set_defaults(void); -int battle_set_value(const char *w1, const char *w2); -int battle_get_value(const char *w1); +int battle_set_value(const char* w1, const char* w2); +int battle_get_value(const char* w1); // -struct block_list *battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id); +struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id); /** * Royal Guard **/ -int battle_damage_area(struct block_list *bl, va_list ap); +int battle_damage_area( struct block_list *bl, va_list ap); #endif /* _BATTLE_H_ */ diff --git a/src/map/battleground.c b/src/map/battleground.c index fc1653e03..7b605066d 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -22,198 +22,198 @@ #include <string.h> #include <stdio.h> -static DBMap *bg_team_db; // int bg_id -> struct battleground_data* +static DBMap* bg_team_db; // int bg_id -> struct battleground_data* static unsigned int bg_team_counter = 0; // Next bg_id -struct battleground_data *bg_team_search(int bg_id) { - // Search a BG Team using bg_id - if (!bg_id) return NULL; - return (struct battleground_data *)idb_get(bg_team_db, bg_id); +struct battleground_data* bg_team_search(int bg_id) +{ // Search a BG Team using bg_id + if( !bg_id ) return NULL; + return (struct battleground_data *)idb_get(bg_team_db, bg_id); } -struct map_session_data *bg_getavailablesd(struct battleground_data *bg) { - int i; - nullpo_retr(NULL, bg); - ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd != NULL); - return(i < MAX_BG_MEMBERS) ? bg->members[i].sd : NULL; +struct map_session_data* bg_getavailablesd(struct battleground_data *bg) +{ + int i; + nullpo_retr(NULL, bg); + ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd != NULL); + return( i < MAX_BG_MEMBERS ) ? bg->members[i].sd : NULL; } int bg_team_delete(int bg_id) -{ - // Deletes BG Team from db - int i; - struct map_session_data *sd; - struct battleground_data *bg = bg_team_search(bg_id); - - if (bg == NULL) return 0; - for (i = 0; i < MAX_BG_MEMBERS; i++) { - if ((sd = bg->members[i].sd) == NULL) - continue; - - bg_send_dot_remove(sd); - sd->bg_id = 0; - } - idb_remove(bg_team_db, bg_id); - return 1; +{ // Deletes BG Team from db + int i; + struct map_session_data *sd; + struct battleground_data *bg = bg_team_search(bg_id); + + if( bg == NULL ) return 0; + for( i = 0; i < MAX_BG_MEMBERS; i++ ) + { + if( (sd = bg->members[i].sd) == NULL ) + continue; + + bg_send_dot_remove(sd); + sd->bg_id = 0; + } + idb_remove(bg_team_db, bg_id); + return 1; } int bg_team_warp(int bg_id, unsigned short mapindex, short x, short y) -{ - // Warps a Team - int i; - struct battleground_data *bg = bg_team_search(bg_id); - if (bg == NULL) return 0; - for (i = 0; i < MAX_BG_MEMBERS; i++) - if (bg->members[i].sd != NULL) pc_setpos(bg->members[i].sd, mapindex, x, y, CLR_TELEPORT); - return 1; +{ // Warps a Team + int i; + struct battleground_data *bg = bg_team_search(bg_id); + if( bg == NULL ) return 0; + for( i = 0; i < MAX_BG_MEMBERS; i++ ) + if( bg->members[i].sd != NULL ) pc_setpos(bg->members[i].sd, mapindex, x, y, CLR_TELEPORT); + return 1; } int bg_send_dot_remove(struct map_session_data *sd) { - if (sd && sd->bg_id) - clif_bg_xy_remove(sd); - return 0; + if( sd && sd->bg_id ) + clif_bg_xy_remove(sd); + return 0; } int bg_team_join(int bg_id, struct map_session_data *sd) -{ - // Player joins team - int i; - struct battleground_data *bg = bg_team_search(bg_id); - struct map_session_data *pl_sd; +{ // Player joins team + int i; + struct battleground_data *bg = bg_team_search(bg_id); + struct map_session_data *pl_sd; - if (bg == NULL || sd == NULL || sd->bg_id) return 0; + if( bg == NULL || sd == NULL || sd->bg_id ) return 0; - ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == NULL); - if (i == MAX_BG_MEMBERS) return 0; // No free slots + ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == NULL); + if( i == MAX_BG_MEMBERS ) return 0; // No free slots - sd->bg_id = bg_id; - bg->members[i].sd = sd; - bg->members[i].x = sd->bl.x; - bg->members[i].y = sd->bl.y; - bg->count++; + sd->bg_id = bg_id; + bg->members[i].sd = sd; + bg->members[i].x = sd->bl.x; + bg->members[i].y = sd->bl.y; + bg->count++; - guild_send_dot_remove(sd); + guild_send_dot_remove(sd); - for (i = 0; i < MAX_BG_MEMBERS; i++) { - if ((pl_sd = bg->members[i].sd) != NULL && pl_sd != sd) - clif_hpmeter_single(sd->fd, pl_sd->bl.id, pl_sd->battle_status.hp, pl_sd->battle_status.max_hp); - } + for( i = 0; i < MAX_BG_MEMBERS; i++ ) + { + if( (pl_sd = bg->members[i].sd) != NULL && pl_sd != sd ) + clif_hpmeter_single(sd->fd, pl_sd->bl.id, pl_sd->battle_status.hp, pl_sd->battle_status.max_hp); + } - clif_bg_hp(sd); - clif_bg_xy(sd); - return 1; + clif_bg_hp(sd); + clif_bg_xy(sd); + return 1; } int bg_team_leave(struct map_session_data *sd, int flag) -{ - // Single Player leaves team - int i, bg_id; - struct battleground_data *bg; - char output[128]; +{ // Single Player leaves team + int i, bg_id; + struct battleground_data *bg; + char output[128]; - if (sd == NULL || !sd->bg_id) - return 0; + if( sd == NULL || !sd->bg_id ) + return 0; - bg_send_dot_remove(sd); - bg_id = sd->bg_id; - sd->bg_id = 0; + bg_send_dot_remove(sd); + bg_id = sd->bg_id; + sd->bg_id = 0; - if ((bg = bg_team_search(bg_id)) == NULL) - return 0; + if( (bg = bg_team_search(bg_id)) == NULL ) + return 0; - ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == sd); - if (i < MAX_BG_MEMBERS) // Removes member from BG - memset(&bg->members[i], 0, sizeof(bg->members[0])); - bg->count--; + ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == sd); + if( i < MAX_BG_MEMBERS ) // Removes member from BG + memset(&bg->members[i], 0, sizeof(bg->members[0])); + bg->count--; - if (flag) - sprintf(output, "Server : %s has quit the game...", sd->status.name); - else - sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name); - clif_bg_message(bg, 0, "Server", output, strlen(output) + 1); + if( flag ) + sprintf(output, "Server : %s has quit the game...", sd->status.name); + else + sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name); + clif_bg_message(bg, 0, "Server", output, strlen(output) + 1); - if (bg->logout_event[0] && flag) - npc_event(sd, bg->logout_event, 0); + if( bg->logout_event[0] && flag ) + npc_event(sd, bg->logout_event, 0); - return bg->count; + return bg->count; } int bg_member_respawn(struct map_session_data *sd) -{ - // Respawn after killed - struct battleground_data *bg; - if (sd == NULL || !pc_isdead(sd) || !sd->bg_id || (bg = bg_team_search(sd->bg_id)) == NULL) - return 0; - if (bg->mapindex == 0) - return 0; // Respawn not handled by Core - pc_setpos(sd, bg->mapindex, bg->x, bg->y, CLR_OUTSIGHT); - status_revive(&sd->bl, 1, 100); - - return 1; // Warped +{ // Respawn after killed + struct battleground_data *bg; + if( sd == NULL || !pc_isdead(sd) || !sd->bg_id || (bg = bg_team_search(sd->bg_id)) == NULL ) + return 0; + if( bg->mapindex == 0 ) + return 0; // Respawn not handled by Core + pc_setpos(sd, bg->mapindex, bg->x, bg->y, CLR_OUTSIGHT); + status_revive(&sd->bl, 1, 100); + + return 1; // Warped } int bg_create(unsigned short mapindex, short rx, short ry, const char *ev, const char *dev) { - struct battleground_data *bg; - bg_team_counter++; - - CREATE(bg, struct battleground_data, 1); - bg->bg_id = bg_team_counter; - bg->count = 0; - bg->mapindex = mapindex; - bg->x = rx; - bg->y = ry; - safestrncpy(bg->logout_event, ev, sizeof(bg->logout_event)); - safestrncpy(bg->die_event, dev, sizeof(bg->die_event)); - - memset(&bg->members, 0, sizeof(bg->members)); - idb_put(bg_team_db, bg_team_counter, bg); - - return bg->bg_id; + struct battleground_data *bg; + bg_team_counter++; + + CREATE(bg, struct battleground_data, 1); + bg->bg_id = bg_team_counter; + bg->count = 0; + bg->mapindex = mapindex; + bg->x = rx; + bg->y = ry; + safestrncpy(bg->logout_event, ev, sizeof(bg->logout_event)); + safestrncpy(bg->die_event, dev, sizeof(bg->die_event)); + + memset(&bg->members, 0, sizeof(bg->members)); + idb_put(bg_team_db, bg_team_counter, bg); + + return bg->bg_id; } int bg_team_get_id(struct block_list *bl) { - nullpo_ret(bl); - switch (bl->type) { - case BL_PC: - return ((TBL_PC *)bl)->bg_id; - case BL_PET: - if (((TBL_PET *)bl)->msd) - return ((TBL_PET *)bl)->msd->bg_id; - break; - case BL_MOB: { - struct map_session_data *msd; - struct mob_data *md = (TBL_MOB *)bl; - if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL) - return msd->bg_id; - return md->bg_id; - } - case BL_HOM: - if (((TBL_HOM *)bl)->master) - return ((TBL_HOM *)bl)->master->bg_id; - break; - case BL_MER: - if (((TBL_MER *)bl)->master) - return ((TBL_MER *)bl)->master->bg_id; - break; - case BL_SKILL: - return ((TBL_SKILL *)bl)->group->bg_id; - } - - return 0; + nullpo_ret(bl); + switch( bl->type ) + { + case BL_PC: + return ((TBL_PC*)bl)->bg_id; + case BL_PET: + if( ((TBL_PET*)bl)->msd ) + return ((TBL_PET*)bl)->msd->bg_id; + break; + case BL_MOB: + { + struct map_session_data *msd; + struct mob_data *md = (TBL_MOB*)bl; + if( md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL ) + return msd->bg_id; + return md->bg_id; + } + case BL_HOM: + if( ((TBL_HOM*)bl)->master ) + return ((TBL_HOM*)bl)->master->bg_id; + break; + case BL_MER: + if( ((TBL_MER*)bl)->master ) + return ((TBL_MER*)bl)->master->bg_id; + break; + case BL_SKILL: + return ((TBL_SKILL*)bl)->group->bg_id; + } + + return 0; } int bg_send_message(struct map_session_data *sd, const char *mes, int len) { - struct battleground_data *bg; + struct battleground_data *bg; - nullpo_ret(sd); - if (sd->bg_id == 0 || (bg = bg_team_search(sd->bg_id)) == NULL) - return 0; - clif_bg_message(bg, sd->bl.id, sd->status.name, mes, len); - return 0; + nullpo_ret(sd); + if( sd->bg_id == 0 || (bg = bg_team_search(sd->bg_id)) == NULL ) + return 0; + clif_bg_message(bg, sd->bl.id, sd->status.name, mes, len); + return 0; } /** @@ -221,37 +221,38 @@ int bg_send_message(struct map_session_data *sd, const char *mes, int len) */ int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) { - struct battleground_data *bg = db_data2ptr(data); - struct map_session_data *sd; - int i; - nullpo_ret(bg); - for (i = 0; i < MAX_BG_MEMBERS; i++) { - if ((sd = bg->members[i].sd) == NULL) - continue; - if (sd->bl.x != bg->members[i].x || sd->bl.y != bg->members[i].y) { - // xy update - bg->members[i].x = sd->bl.x; - bg->members[i].y = sd->bl.y; - clif_bg_xy(sd); - } - } - return 0; + struct battleground_data *bg = db_data2ptr(data); + struct map_session_data *sd; + int i; + nullpo_ret(bg); + for( i = 0; i < MAX_BG_MEMBERS; i++ ) + { + if( (sd = bg->members[i].sd) == NULL ) + continue; + if( sd->bl.x != bg->members[i].x || sd->bl.y != bg->members[i].y ) + { // xy update + bg->members[i].x = sd->bl.x; + bg->members[i].y = sd->bl.y; + clif_bg_xy(sd); + } + } + return 0; } int bg_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) { - bg_team_db->foreach(bg_team_db, bg_send_xy_timer_sub, tick); - return 0; + bg_team_db->foreach(bg_team_db, bg_send_xy_timer_sub, tick); + return 0; } void do_init_battleground(void) { - bg_team_db = idb_alloc(DB_OPT_RELEASE_DATA); - add_timer_func_list(bg_send_xy_timer, "bg_send_xy_timer"); - add_timer_interval(gettick() + battle_config.bg_update_interval, bg_send_xy_timer, 0, 0, battle_config.bg_update_interval); + bg_team_db = idb_alloc(DB_OPT_RELEASE_DATA); + add_timer_func_list(bg_send_xy_timer, "bg_send_xy_timer"); + add_timer_interval(gettick() + battle_config.bg_update_interval, bg_send_xy_timer, 0, 0, battle_config.bg_update_interval); } void do_final_battleground(void) { - bg_team_db->destroy(bg_team_db, NULL); + bg_team_db->destroy(bg_team_db, NULL); } diff --git a/src/map/battleground.h b/src/map/battleground.h index c3efc30a2..c2b74a534 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -10,29 +10,29 @@ #define MAX_BG_MEMBERS 30 struct battleground_member_data { - unsigned short x, y; - struct map_session_data *sd; - unsigned afk : 1; + unsigned short x, y; + struct map_session_data *sd; + unsigned afk : 1; }; struct battleground_data { - unsigned int bg_id; - unsigned char count; - struct battleground_member_data members[MAX_BG_MEMBERS]; - // BG Cementery - unsigned short mapindex, x, y; - // Logout Event - char logout_event[EVENT_NAME_LENGTH]; - char die_event[EVENT_NAME_LENGTH]; + unsigned int bg_id; + unsigned char count; + struct battleground_member_data members[MAX_BG_MEMBERS]; + // BG Cementery + unsigned short mapindex, x, y; + // Logout Event + char logout_event[EVENT_NAME_LENGTH]; + char die_event[EVENT_NAME_LENGTH]; }; void do_init_battleground(void); void do_final_battleground(void); -struct battleground_data *bg_team_search(int bg_id); +struct battleground_data* bg_team_search(int bg_id); int bg_send_dot_remove(struct map_session_data *sd); int bg_team_get_id(struct block_list *bl); -struct map_session_data *bg_getavailablesd(struct battleground_data *bg); +struct map_session_data* bg_getavailablesd(struct battleground_data *bg); int bg_create(unsigned short mapindex, short rx, short ry, const char *ev, const char *dev); int bg_team_join(int bg_id, struct map_session_data *sd); diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c index 796c6cd7d..8e3c21bd4 100644 --- a/src/map/buyingstore.c +++ b/src/map/buyingstore.c @@ -20,15 +20,16 @@ /// failure constants for clif functions -enum e_buyingstore_failure { - BUYINGSTORE_CREATE = 1, // "Failed to open buying store." - BUYINGSTORE_CREATE_OVERWEIGHT = 2, // "Total amount of then possessed items exceeds the weight limit by %d. Please re-enter." - BUYINGSTORE_TRADE_BUYER_ZENY = 3, // "All items within the buy limit were purchased." - BUYINGSTORE_TRADE_BUYER_NO_ITEMS = 4, // "All items were purchased." - BUYINGSTORE_TRADE_SELLER_FAILED = 5, // "The deal has failed." - BUYINGSTORE_TRADE_SELLER_COUNT = 6, // "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy." - BUYINGSTORE_TRADE_SELLER_ZENY = 7, // "The trade failed, because the buyer is lacking required balance." - BUYINGSTORE_CREATE_NO_INFO = 8, // "No sale (purchase) information available." +enum e_buyingstore_failure +{ + BUYINGSTORE_CREATE = 1, // "Failed to open buying store." + BUYINGSTORE_CREATE_OVERWEIGHT = 2, // "Total amount of then possessed items exceeds the weight limit by %d. Please re-enter." + BUYINGSTORE_TRADE_BUYER_ZENY = 3, // "All items within the buy limit were purchased." + BUYINGSTORE_TRADE_BUYER_NO_ITEMS = 4, // "All items were purchased." + BUYINGSTORE_TRADE_SELLER_FAILED = 5, // "The deal has failed." + BUYINGSTORE_TRADE_SELLER_COUNT = 6, // "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy." + BUYINGSTORE_TRADE_SELLER_ZENY = 7, // "The trade failed, because the buyer is lacking required balance." + BUYINGSTORE_CREATE_NO_INFO = 8, // "No sale (purchase) information available." }; @@ -39,427 +40,434 @@ static const short buyingstore_blankslots[MAX_SLOTS] = { 0 }; // used when chec /// Returns unique buying store id static unsigned int buyingstore_getuid(void) { - return buyingstore_nextid++; + return buyingstore_nextid++; } -bool buyingstore_setup(struct map_session_data *sd, unsigned char slots) +bool buyingstore_setup(struct map_session_data* sd, unsigned char slots) { - if (!battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0) { - return false; - } - - if (sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM)) { - // custom: mute limitation - return false; - } - - if (map[sd->bl.m].flag.novending) { - // custom: no vending maps - clif_displaymessage(sd->fd, msg_txt(276)); // "You can't open a shop on this map" - return false; - } - - if (map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING)) { - // custom: no vending cells - clif_displaymessage(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." - return false; - } - - if (slots > MAX_BUYINGSTORE_SLOTS) { - ShowWarning("buyingstore_setup: Requested %d slots, but server supports only %d slots.\n", (int)slots, MAX_BUYINGSTORE_SLOTS); - slots = MAX_BUYINGSTORE_SLOTS; - } - - sd->buyingstore.slots = slots; - clif_buyingstore_open(sd); - - return true; + if( !battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0 ) + { + return false; + } + + if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) ) + {// custom: mute limitation + return false; + } + + if( map[sd->bl.m].flag.novending ) + {// custom: no vending maps + clif_displaymessage(sd->fd, msg_txt(276)); // "You can't open a shop on this map" + return false; + } + + if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) ) + {// custom: no vending cells + clif_displaymessage(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." + return false; + } + + if( slots > MAX_BUYINGSTORE_SLOTS ) + { + ShowWarning("buyingstore_setup: Requested %d slots, but server supports only %d slots.\n", (int)slots, MAX_BUYINGSTORE_SLOTS); + slots = MAX_BUYINGSTORE_SLOTS; + } + + sd->buyingstore.slots = slots; + clif_buyingstore_open(sd); + + return true; } -void buyingstore_create(struct map_session_data *sd, int zenylimit, unsigned char result, const char *storename, const uint8 *itemlist, unsigned int count) +void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count) { - unsigned int i, weight, listidx; - struct item_data *id; - - if (!result || count == 0) { - // canceled, or no items - return; - } - - if (!battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0]) { - // disabled or invalid input - sd->buyingstore.slots = 0; - clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); - return; - } - - if (!pc_can_give_items(sd)) { - // custom: GM is not allowed to buy (give zeny) - sd->buyingstore.slots = 0; - clif_displaymessage(sd->fd, msg_txt(246)); - clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); - return; - } - - if (sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM)) { - // custom: mute limitation - return; - } - - if (map[sd->bl.m].flag.novending) { - // custom: no vending maps - clif_displaymessage(sd->fd, msg_txt(276)); // "You can't open a shop on this map" - return; - } - - if (map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING)) { - // custom: no vending cells - clif_displaymessage(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." - return; - } - - weight = sd->weight; - - // check item list - for (i = 0; i < count; i++) { - // itemlist: <name id>.W <amount>.W <price>.L - unsigned short nameid, amount; - int price, idx; - - nameid = RBUFW(itemlist,i*8+0); - amount = RBUFW(itemlist,i*8+2); - price = RBUFL(itemlist,i*8+4); - - if ((id = itemdb_exists(nameid)) == NULL || amount == 0) { - // invalid input - break; - } - - if (price <= 0 || price > BUYINGSTORE_MAX_PRICE) { - // invalid price: unlike vending, items cannot be bought at 0 Zeny - break; - } - - if (!id->flag.buyingstore || !itemdb_cantrade_sub(id, pc_get_group_level(sd), pc_get_group_level(sd)) || (idx = pc_search_inventory(sd, nameid)) == -1) { - // restrictions: allowed, no character-bound items and at least one must be owned - break; - } - - if (sd->status.inventory[idx].amount+amount > BUYINGSTORE_MAX_AMOUNT) { - // too many items of same kind - break; - } - - if (i) { - // duplicate check. as the client does this too, only malicious intent should be caught here - ARR_FIND(0, i, listidx, sd->buyingstore.items[listidx].nameid == nameid); - if (listidx != i) { - // duplicate - ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id); - break; - } - } - - weight+= id->weight*amount; - sd->buyingstore.items[i].nameid = nameid; - sd->buyingstore.items[i].amount = amount; - sd->buyingstore.items[i].price = price; - } - - if (i != count) { - // invalid item/amount/price - sd->buyingstore.slots = 0; - clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); - return; - } - - if ((sd->max_weight*90)/100 < weight) { - // not able to carry all wanted items without getting overweight (90%) - sd->buyingstore.slots = 0; - clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight); - return; - } - - // success - sd->state.buyingstore = true; - sd->buyer_id = buyingstore_getuid(); - sd->buyingstore.zenylimit = zenylimit; - sd->buyingstore.slots = i; // store actual amount of items - safestrncpy(sd->message, storename, sizeof(sd->message)); - clif_buyingstore_myitemlist(sd); - clif_buyingstore_entry(sd); + unsigned int i, weight, listidx; + struct item_data* id; + + if( !result || count == 0 ) + {// canceled, or no items + return; + } + + if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] ) + {// disabled or invalid input + sd->buyingstore.slots = 0; + clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); + return; + } + + if( !pc_can_give_items(sd) ) + {// custom: GM is not allowed to buy (give zeny) + sd->buyingstore.slots = 0; + clif_displaymessage(sd->fd, msg_txt(246)); + clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); + return; + } + + if( sd->sc.data[SC_NOCHAT] && (sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) ) + {// custom: mute limitation + return; + } + + if( map[sd->bl.m].flag.novending ) + {// custom: no vending maps + clif_displaymessage(sd->fd, msg_txt(276)); // "You can't open a shop on this map" + return; + } + + if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) ) + {// custom: no vending cells + clif_displaymessage(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." + return; + } + + weight = sd->weight; + + // check item list + for( i = 0; i < count; i++ ) + {// itemlist: <name id>.W <amount>.W <price>.L + unsigned short nameid, amount; + int price, idx; + + nameid = RBUFW(itemlist,i*8+0); + amount = RBUFW(itemlist,i*8+2); + price = RBUFL(itemlist,i*8+4); + + if( ( id = itemdb_exists(nameid) ) == NULL || amount == 0 ) + {// invalid input + break; + } + + if( price <= 0 || price > BUYINGSTORE_MAX_PRICE ) + {// invalid price: unlike vending, items cannot be bought at 0 Zeny + break; + } + + if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc_get_group_level(sd), pc_get_group_level(sd)) || ( idx = pc_search_inventory(sd, nameid) ) == -1 ) + {// restrictions: allowed, no character-bound items and at least one must be owned + break; + } + + if( sd->status.inventory[idx].amount+amount > BUYINGSTORE_MAX_AMOUNT ) + {// too many items of same kind + break; + } + + if( i ) + {// duplicate check. as the client does this too, only malicious intent should be caught here + ARR_FIND( 0, i, listidx, sd->buyingstore.items[listidx].nameid == nameid ); + if( listidx != i ) + {// duplicate + ShowWarning("buyingstore_create: Found duplicate item on buying list (nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", nameid, amount, sd->status.account_id, sd->status.char_id); + break; + } + } + + weight+= id->weight*amount; + sd->buyingstore.items[i].nameid = nameid; + sd->buyingstore.items[i].amount = amount; + sd->buyingstore.items[i].price = price; + } + + if( i != count ) + {// invalid item/amount/price + sd->buyingstore.slots = 0; + clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); + return; + } + + if( (sd->max_weight*90)/100 < weight ) + {// not able to carry all wanted items without getting overweight (90%) + sd->buyingstore.slots = 0; + clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight); + return; + } + + // success + sd->state.buyingstore = true; + sd->buyer_id = buyingstore_getuid(); + sd->buyingstore.zenylimit = zenylimit; + sd->buyingstore.slots = i; // store actual amount of items + safestrncpy(sd->message, storename, sizeof(sd->message)); + clif_buyingstore_myitemlist(sd); + clif_buyingstore_entry(sd); } -void buyingstore_close(struct map_session_data *sd) +void buyingstore_close(struct map_session_data* sd) { - if (sd->state.buyingstore) { - // invalidate data - sd->state.buyingstore = false; - memset(&sd->buyingstore, 0, sizeof(sd->buyingstore)); - - // notify other players - clif_buyingstore_disappear_entry(sd); - } + if( sd->state.buyingstore ) + { + // invalidate data + sd->state.buyingstore = false; + memset(&sd->buyingstore, 0, sizeof(sd->buyingstore)); + + // notify other players + clif_buyingstore_disappear_entry(sd); + } } -void buyingstore_open(struct map_session_data *sd, int account_id) +void buyingstore_open(struct map_session_data* sd, int account_id) { - struct map_session_data *pl_sd; - - if (!battle_config.feature_buying_store || pc_istrading(sd)) { - // not allowed to sell - return; - } - - if (!pc_can_give_items(sd)) { - // custom: GM is not allowed to sell - clif_displaymessage(sd->fd, msg_txt(246)); - return; - } - - if ((pl_sd = map_id2sd(account_id)) == NULL || !pl_sd->state.buyingstore) { - // not online or not buying - return; - } - - if (!searchstore_queryremote(sd, account_id) && (sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE))) { - // out of view range - return; - } - - // success - clif_buyingstore_itemlist(sd, pl_sd); + struct map_session_data* pl_sd; + + if( !battle_config.feature_buying_store || pc_istrading(sd) ) + {// not allowed to sell + return; + } + + if( !pc_can_give_items(sd) ) + {// custom: GM is not allowed to sell + clif_displaymessage(sd->fd, msg_txt(246)); + return; + } + + if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore ) + {// not online or not buying + return; + } + + if( !searchstore_queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) ) + {// out of view range + return; + } + + // success + clif_buyingstore_itemlist(sd, pl_sd); } -void buyingstore_trade(struct map_session_data *sd, int account_id, unsigned int buyer_id, const uint8 *itemlist, unsigned int count) +void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count) { - int zeny = 0; - unsigned int i, weight, listidx, k; - struct map_session_data *pl_sd; - - if (count == 0) { - // nothing to do - return; - } - - if (!battle_config.feature_buying_store || pc_istrading(sd)) { - // not allowed to sell - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); - return; - } - - if (!pc_can_give_items(sd)) { - // custom: GM is not allowed to sell - clif_displaymessage(sd->fd, msg_txt(246)); - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); - return; - } - - if ((pl_sd = map_id2sd(account_id)) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id) { - // not online, not buying or not same store - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); - return; - } - - if (!searchstore_queryremote(sd, account_id) && (sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE))) { - // out of view range - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); - return; - } - - searchstore_clearremote(sd); - - if (pl_sd->status.zeny < pl_sd->buyingstore.zenylimit) { - // buyer lost zeny in the mean time? fix the limit - pl_sd->buyingstore.zenylimit = pl_sd->status.zeny; - } - weight = pl_sd->weight; - - // check item list - for (i = 0; i < count; i++) { - // itemlist: <index>.W <name id>.W <amount>.W - unsigned short nameid, amount; - int index; - - index = RBUFW(itemlist,i*6+0)-2; - nameid = RBUFW(itemlist,i*6+2); - amount = RBUFW(itemlist,i*6+4); - - if (i) { - // duplicate check. as the client does this too, only malicious intent should be caught here - ARR_FIND(0, i, k, RBUFW(itemlist,k*6+0)-2 == index); - if (k != i) { - // duplicate - ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%hu, prevamount=%hu, nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", - RBUFW(itemlist,k*6+2), RBUFW(itemlist,k*6+4), nameid, amount, sd->status.account_id, sd->status.char_id); - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); - return; - } - } - - if (index < 0 || index >= ARRAYLENGTH(sd->status.inventory) || sd->inventory_data[index] == NULL || sd->status.inventory[index].nameid != nameid || sd->status.inventory[index].amount < amount) { - // invalid input - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); - return; - } - - if (sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc_get_group_level(sd), pc_get_group_level(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots))) { - // non-tradable item - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); - return; - } - - ARR_FIND(0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid); - if (listidx == pl_sd->buyingstore.slots || pl_sd->buyingstore.items[listidx].amount == 0) { - // there is no such item or the buyer has already bought all of them - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); - return; - } - - if (pl_sd->buyingstore.items[listidx].amount < amount) { - // buyer does not need that much of the item - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_COUNT, nameid); - return; - } - - if (pc_checkadditem(pl_sd, nameid, amount) == ADDITEM_OVERAMOUNT) { - // buyer does not have enough space for this item - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); - return; - } - - if (amount*(unsigned int)sd->inventory_data[index]->weight > pl_sd->max_weight-weight) { - // normally this is not supposed to happen, as the total weight is - // checked upon creation, but the buyer could have gained items - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); - return; - } - weight+= amount*sd->inventory_data[index]->weight; - - if (amount*pl_sd->buyingstore.items[listidx].price > pl_sd->buyingstore.zenylimit-zeny) { - // buyer does not have enough zeny - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_ZENY, nameid); - return; - } - zeny+= amount*pl_sd->buyingstore.items[listidx].price; - } - - // process item list - for (i = 0; i < count; i++) { - // itemlist: <index>.W <name id>.W <amount>.W - unsigned short nameid, amount; - int index; - - index = RBUFW(itemlist,i*6+0)-2; - nameid = RBUFW(itemlist,i*6+2); - amount = RBUFW(itemlist,i*6+4); - - ARR_FIND(0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid); - zeny = amount*pl_sd->buyingstore.items[listidx].price; - - // move item - pc_additem(pl_sd, &sd->status.inventory[index], amount, LOG_TYPE_BUYING_STORE); - pc_delitem(sd, index, amount, 1, 0, LOG_TYPE_BUYING_STORE); - pl_sd->buyingstore.items[listidx].amount-= amount; - - // pay up - pc_payzeny(pl_sd, zeny, LOG_TYPE_BUYING_STORE, sd); - pc_getzeny(sd, zeny, LOG_TYPE_BUYING_STORE, pl_sd); - pl_sd->buyingstore.zenylimit-= zeny; - - // notify clients - clif_buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price); - clif_buyingstore_update_item(pl_sd, nameid, amount); - } - - // check whether or not there is still something to buy - ARR_FIND(0, pl_sd->buyingstore.slots, i, pl_sd->buyingstore.items[i].amount != 0); - if (i == pl_sd->buyingstore.slots) { - // everything was bought - clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_NO_ITEMS); - } else if (pl_sd->buyingstore.zenylimit == 0) { - // zeny limit reached - clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_ZENY); - } else { - // continue buying - return; - } - - // cannot continue buying - buyingstore_close(pl_sd); - - // remove auto-trader - if (pl_sd->state.autotrade) { - map_quit(pl_sd); - } + int zeny = 0; + unsigned int i, weight, listidx, k; + struct map_session_data* pl_sd; + + if( count == 0 ) + {// nothing to do + return; + } + + if( !battle_config.feature_buying_store || pc_istrading(sd) ) + {// not allowed to sell + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + return; + } + + if( !pc_can_give_items(sd) ) + {// custom: GM is not allowed to sell + clif_displaymessage(sd->fd, msg_txt(246)); + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + return; + } + + if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id ) + {// not online, not buying or not same store + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + return; + } + + if( !searchstore_queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) ) + {// out of view range + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + return; + } + + searchstore_clearremote(sd); + + if( pl_sd->status.zeny < pl_sd->buyingstore.zenylimit ) + {// buyer lost zeny in the mean time? fix the limit + pl_sd->buyingstore.zenylimit = pl_sd->status.zeny; + } + weight = pl_sd->weight; + + // check item list + for( i = 0; i < count; i++ ) + {// itemlist: <index>.W <name id>.W <amount>.W + unsigned short nameid, amount; + int index; + + index = RBUFW(itemlist,i*6+0)-2; + nameid = RBUFW(itemlist,i*6+2); + amount = RBUFW(itemlist,i*6+4); + + if( i ) + {// duplicate check. as the client does this too, only malicious intent should be caught here + ARR_FIND( 0, i, k, RBUFW(itemlist,k*6+0)-2 == index ); + if( k != i ) + {// duplicate + ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%hu, prevamount=%hu, nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", + RBUFW(itemlist,k*6+2), RBUFW(itemlist,k*6+4), nameid, amount, sd->status.account_id, sd->status.char_id); + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + } + + if( index < 0 || index >= ARRAYLENGTH(sd->status.inventory) || sd->inventory_data[index] == NULL || sd->status.inventory[index].nameid != nameid || sd->status.inventory[index].amount < amount ) + {// invalid input + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + + if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc_get_group_level(sd), pc_get_group_level(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) ) + {// non-tradable item + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + + ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid ); + if( listidx == pl_sd->buyingstore.slots || pl_sd->buyingstore.items[listidx].amount == 0 ) + {// there is no such item or the buyer has already bought all of them + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + + if( pl_sd->buyingstore.items[listidx].amount < amount ) + {// buyer does not need that much of the item + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_COUNT, nameid); + return; + } + + if( pc_checkadditem(pl_sd, nameid, amount) == ADDITEM_OVERAMOUNT ) + {// buyer does not have enough space for this item + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + + if( amount*(unsigned int)sd->inventory_data[index]->weight > pl_sd->max_weight-weight ) + {// normally this is not supposed to happen, as the total weight is + // checked upon creation, but the buyer could have gained items + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + return; + } + weight+= amount*sd->inventory_data[index]->weight; + + if( amount*pl_sd->buyingstore.items[listidx].price > pl_sd->buyingstore.zenylimit-zeny ) + {// buyer does not have enough zeny + clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_ZENY, nameid); + return; + } + zeny+= amount*pl_sd->buyingstore.items[listidx].price; + } + + // process item list + for( i = 0; i < count; i++ ) + {// itemlist: <index>.W <name id>.W <amount>.W + unsigned short nameid, amount; + int index; + + index = RBUFW(itemlist,i*6+0)-2; + nameid = RBUFW(itemlist,i*6+2); + amount = RBUFW(itemlist,i*6+4); + + ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid ); + zeny = amount*pl_sd->buyingstore.items[listidx].price; + + // move item + pc_additem(pl_sd, &sd->status.inventory[index], amount, LOG_TYPE_BUYING_STORE); + pc_delitem(sd, index, amount, 1, 0, LOG_TYPE_BUYING_STORE); + pl_sd->buyingstore.items[listidx].amount-= amount; + + // pay up + pc_payzeny(pl_sd, zeny, LOG_TYPE_BUYING_STORE, sd); + pc_getzeny(sd, zeny, LOG_TYPE_BUYING_STORE, pl_sd); + pl_sd->buyingstore.zenylimit-= zeny; + + // notify clients + clif_buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price); + clif_buyingstore_update_item(pl_sd, nameid, amount); + } + + // check whether or not there is still something to buy + ARR_FIND( 0, pl_sd->buyingstore.slots, i, pl_sd->buyingstore.items[i].amount != 0 ); + if( i == pl_sd->buyingstore.slots ) + {// everything was bought + clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_NO_ITEMS); + } + else if( pl_sd->buyingstore.zenylimit == 0 ) + {// zeny limit reached + clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_ZENY); + } + else + {// continue buying + return; + } + + // cannot continue buying + buyingstore_close(pl_sd); + + // remove auto-trader + if( pl_sd->state.autotrade ) + { + map_quit(pl_sd); + } } /// Checks if an item is being bought in given player's buying store. -bool buyingstore_search(struct map_session_data *sd, unsigned short nameid) +bool buyingstore_search(struct map_session_data* sd, unsigned short nameid) { - unsigned int i; + unsigned int i; - if (!sd->state.buyingstore) { - // not buying - return false; - } + if( !sd->state.buyingstore ) + {// not buying + return false; + } - ARR_FIND(0, sd->buyingstore.slots, i, sd->buyingstore.items[i].nameid == nameid && sd->buyingstore.items[i].amount); - if (i == sd->buyingstore.slots) { - // not found - return false; - } + ARR_FIND( 0, sd->buyingstore.slots, i, sd->buyingstore.items[i].nameid == nameid && sd->buyingstore.items[i].amount ); + if( i == sd->buyingstore.slots ) + {// not found + return false; + } - return true; + return true; } /// Searches for all items in a buyingstore, that match given ids, price and possible cards. /// @return Whether or not the search should be continued. -bool buyingstore_searchall(struct map_session_data *sd, const struct s_search_store_search *s) +bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_store_search* s) { - unsigned int i, idx; - struct s_buyingstore_item *it; - - if (!sd->state.buyingstore) { - // not buying - return true; - } - - for (idx = 0; idx < s->item_count; idx++) { - ARR_FIND(0, sd->buyingstore.slots, i, sd->buyingstore.items[i].nameid == s->itemlist[idx] && sd->buyingstore.items[i].amount); - if (i == sd->buyingstore.slots) { - // not found - continue; - } - it = &sd->buyingstore.items[i]; - - if (s->min_price && s->min_price > (unsigned int)it->price) { - // too low price - continue; - } - - if (s->max_price && s->max_price < (unsigned int)it->price) { - // too high price - continue; - } - - if (s->card_count) { - // ignore cards, as there cannot be any - ; - } - - if (!searchstore_result(s->search_sd, sd->buyer_id, sd->status.account_id, sd->message, it->nameid, it->amount, it->price, buyingstore_blankslots, 0)) { - // result set full - return false; - } - } - - return true; + unsigned int i, idx; + struct s_buyingstore_item* it; + + if( !sd->state.buyingstore ) + {// not buying + return true; + } + + for( idx = 0; idx < s->item_count; idx++ ) + { + ARR_FIND( 0, sd->buyingstore.slots, i, sd->buyingstore.items[i].nameid == s->itemlist[idx] && sd->buyingstore.items[i].amount ); + if( i == sd->buyingstore.slots ) + {// not found + continue; + } + it = &sd->buyingstore.items[i]; + + if( s->min_price && s->min_price > (unsigned int)it->price ) + {// too low price + continue; + } + + if( s->max_price && s->max_price < (unsigned int)it->price ) + {// too high price + continue; + } + + if( s->card_count ) + {// ignore cards, as there cannot be any + ; + } + + if( !searchstore_result(s->search_sd, sd->buyer_id, sd->status.account_id, sd->message, it->nameid, it->amount, it->price, buyingstore_blankslots, 0) ) + {// result set full + return false; + } + } + + return true; } diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h index 52e7a664a..0ed6e5457 100644 --- a/src/map/buyingstore.h +++ b/src/map/buyingstore.h @@ -8,24 +8,26 @@ struct s_search_store_search; #define MAX_BUYINGSTORE_SLOTS 5 -struct s_buyingstore_item { - int price; - unsigned short amount; - unsigned short nameid; +struct s_buyingstore_item +{ + int price; + unsigned short amount; + unsigned short nameid; }; -struct s_buyingstore { - struct s_buyingstore_item items[MAX_BUYINGSTORE_SLOTS]; - int zenylimit; - unsigned char slots; +struct s_buyingstore +{ + struct s_buyingstore_item items[MAX_BUYINGSTORE_SLOTS]; + int zenylimit; + unsigned char slots; }; -bool buyingstore_setup(struct map_session_data *sd, unsigned char slots); -void buyingstore_create(struct map_session_data *sd, int zenylimit, unsigned char result, const char *storename, const uint8 *itemlist, unsigned int count); -void buyingstore_close(struct map_session_data *sd); -void buyingstore_open(struct map_session_data *sd, int account_id); -void buyingstore_trade(struct map_session_data *sd, int account_id, unsigned int buyer_id, const uint8 *itemlist, unsigned int count); -bool buyingstore_search(struct map_session_data *sd, unsigned short nameid); -bool buyingstore_searchall(struct map_session_data *sd, const struct s_search_store_search *s); +bool buyingstore_setup(struct map_session_data* sd, unsigned char slots); +void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count); +void buyingstore_close(struct map_session_data* sd); +void buyingstore_open(struct map_session_data* sd, int account_id); +void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count); +bool buyingstore_search(struct map_session_data* sd, unsigned short nameid); +bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_store_search* s); #endif // _BUYINGSTORE_H_ diff --git a/src/map/chat.c b/src/map/chat.c index a65714ce1..dfeb16cad 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -24,136 +24,144 @@ int chat_triggerevent(struct chat_data *cd); // forward declaration /// Initializes a chatroom object (common functionality for both pc and npc chatrooms). /// Returns a chatroom object on success, or NULL on failure. -static struct chat_data *chat_createchat(struct block_list *bl, const char *title, const char *pass, int limit, bool pub, int trigger, const char *ev, int zeny, int minLvl, int maxLvl) { - struct chat_data *cd; - nullpo_retr(NULL, bl); - - cd = (struct chat_data *) aMalloc(sizeof(struct chat_data)); - - safestrncpy(cd->title, title, sizeof(cd->title)); - safestrncpy(cd->pass, pass, sizeof(cd->pass)); - cd->pub = pub; - cd->users = 0; - cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); - cd->trigger = trigger; - cd->zeny = zeny; - cd->minLvl = minLvl; - cd->maxLvl = maxLvl; - memset(cd->usersd, 0, sizeof(cd->usersd)); - cd->owner = bl; - safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event)); - - cd->bl.id = map_get_new_object_id(); - cd->bl.m = bl->m; - cd->bl.x = bl->x; - cd->bl.y = bl->y; - cd->bl.type = BL_CHAT; - cd->bl.next = cd->bl.prev = NULL; - - if (cd->bl.id == 0) { - aFree(cd); - cd = NULL; - } - - map_addiddb(&cd->bl); - - if (bl->type != BL_NPC) - cd->kick_list = idb_alloc(DB_OPT_BASE); - - return cd; +static struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl) +{ + struct chat_data* cd; + nullpo_retr(NULL, bl); + + cd = (struct chat_data *) aMalloc(sizeof(struct chat_data)); + + safestrncpy(cd->title, title, sizeof(cd->title)); + safestrncpy(cd->pass, pass, sizeof(cd->pass)); + cd->pub = pub; + cd->users = 0; + cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); + cd->trigger = trigger; + cd->zeny = zeny; + cd->minLvl = minLvl; + cd->maxLvl = maxLvl; + memset(cd->usersd, 0, sizeof(cd->usersd)); + cd->owner = bl; + safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event)); + + cd->bl.id = map_get_new_object_id(); + cd->bl.m = bl->m; + cd->bl.x = bl->x; + cd->bl.y = bl->y; + cd->bl.type = BL_CHAT; + cd->bl.next = cd->bl.prev = NULL; + + if( cd->bl.id == 0 ) + { + aFree(cd); + cd = NULL; + } + + map_addiddb(&cd->bl); + + if( bl->type != BL_NPC ) + cd->kick_list = idb_alloc(DB_OPT_BASE); + + return cd; } /*========================================== * player chatroom creation *------------------------------------------*/ -int chat_createpcchat(struct map_session_data *sd, const char *title, const char *pass, int limit, bool pub) +int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) { - struct chat_data *cd; - nullpo_ret(sd); - - if (sd->chatID) - return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex] - - if (sd->state.vending || sd->state.buyingstore) { - // not chat, when you already have a store open - return 0; - } - - if (map[sd->bl.m].flag.nochat) { - clif_displaymessage(sd->fd, msg_txt(281)); - return 0; //Can't create chatrooms on this map. - } - - if (map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOCHAT)) { - clif_displaymessage(sd->fd, msg_txt(665)); - return 0; - } - - pc_stop_walking(sd,1); - - cd = chat_createchat(&sd->bl, title, pass, limit, pub, 0, "", 0, 1, MAX_LEVEL); - if (cd) { - cd->users = 1; - cd->usersd[0] = sd; - pc_setchatid(sd,cd->bl.id); - clif_createchat(sd,0); - clif_dispchat(cd,0); - } else - clif_createchat(sd,1); - - return 0; + struct chat_data* cd; + nullpo_ret(sd); + + if( sd->chatID ) + return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex] + + if( sd->state.vending || sd->state.buyingstore ) + {// not chat, when you already have a store open + return 0; + } + + if( map[sd->bl.m].flag.nochat ) + { + clif_displaymessage(sd->fd, msg_txt(281)); + return 0; //Can't create chatrooms on this map. + } + + if( map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOCHAT) ) + { + clif_displaymessage (sd->fd, msg_txt(665)); + return 0; + } + + pc_stop_walking(sd,1); + + cd = chat_createchat(&sd->bl, title, pass, limit, pub, 0, "", 0, 1, MAX_LEVEL); + if( cd ) + { + cd->users = 1; + cd->usersd[0] = sd; + pc_setchatid(sd,cd->bl.id); + clif_createchat(sd,0); + clif_dispchat(cd,0); + } + else + clif_createchat(sd,1); + + return 0; } /*========================================== * join an existing chatroom *------------------------------------------*/ -int chat_joinchat(struct map_session_data *sd, int chatid, const char *pass) +int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) { - struct chat_data *cd; + struct chat_data* cd; - nullpo_ret(sd); - cd = (struct chat_data *)map_id2bl(chatid); + nullpo_ret(sd); + cd = (struct chat_data*)map_id2bl(chatid); - if (cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit) { - clif_joinchatfail(sd,0); - return 0; - } + if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit ) + { + clif_joinchatfail(sd,0); + return 0; + } - if (!cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !pc_has_permission(sd, PC_PERM_JOIN_ALL_CHAT)) { - clif_joinchatfail(sd,1); - return 0; - } + if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !pc_has_permission(sd, PC_PERM_JOIN_ALL_CHAT) ) + { + clif_joinchatfail(sd,1); + return 0; + } - if (sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl) { - if (sd->status.base_level < cd->minLvl) - clif_joinchatfail(sd,5); - else - clif_joinchatfail(sd,6); + if( sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl ) { + if(sd->status.base_level < cd->minLvl) + clif_joinchatfail(sd,5); + else + clif_joinchatfail(sd,6); - return 0; - } + return 0; + } - if (sd->status.zeny < cd->zeny) { - clif_joinchatfail(sd,4); - return 0; - } + if( sd->status.zeny < cd->zeny ) { + clif_joinchatfail(sd,4); + return 0; + } - if (cd->owner->type != BL_NPC && idb_exists(cd->kick_list,sd->status.char_id)) { - clif_joinchatfail(sd,2);//You have been kicked out of the room. - return 0; - } + if( cd->owner->type != BL_NPC && idb_exists(cd->kick_list,sd->status.char_id) ) { + clif_joinchatfail(sd,2);//You have been kicked out of the room. + return 0; + } - pc_stop_walking(sd,1); - cd->usersd[cd->users] = sd; - cd->users++; + pc_stop_walking(sd,1); + cd->usersd[cd->users] = sd; + cd->users++; - pc_setchatid(sd,cd->bl.id); + pc_setchatid(sd,cd->bl.id); clif_joinchatok(sd, cd); //To the person who newly joined the list of all - clif_addchat(cd, sd); //Reports To the person who already in the chat - clif_dispchat(cd, 0); //Reported number of changes to the people around + clif_addchat(cd, sd); //Reports To the person who already in the chat + clif_dispchat(cd, 0); //Reported number of changes to the people around - chat_triggerevent(cd); //Event + chat_triggerevent(cd); //Event return 0; } @@ -162,213 +170,215 @@ int chat_joinchat(struct map_session_data *sd, int chatid, const char *pass) /*========================================== * leave a chatroom *------------------------------------------*/ -int chat_leavechat(struct map_session_data *sd, bool kicked) +int chat_leavechat(struct map_session_data* sd, bool kicked) { - struct chat_data *cd; - int i; - int leavechar; - - nullpo_retr(1, sd); - - cd = (struct chat_data *)map_id2bl(sd->chatID); - if (cd == NULL) { - pc_setchatid(sd, 0); - return 1; - } - - ARR_FIND(0, cd->users, i, cd->usersd[i] == sd); - if (i == cd->users) { - // Not found in the chatroom? - pc_setchatid(sd, 0); - return -1; - } - - clif_leavechat(cd, sd, kicked); - pc_setchatid(sd, 0); - cd->users--; - - leavechar = i; - - for (i = leavechar; i < cd->users; i++) - cd->usersd[i] = cd->usersd[i+1]; - - - if (cd->users == 0 && cd->owner->type == BL_PC) { // Delete empty chatroom - struct skill_unit *unit = NULL; - struct skill_unit_group *group = NULL; - - clif_clearchat(cd, 0); - db_destroy(cd->kick_list); - map_deliddb(&cd->bl); - map_delblock(&cd->bl); - map_freeblock(&cd->bl); - - unit = map_find_skill_unit_oncell(&sd->bl, sd->bl.x, sd->bl.y, AL_WARP, NULL, 0); - group = (unit != NULL) ? unit->group : NULL; - if (group != NULL) - ext_skill_unit_onplace(unit, &sd->bl, group->tick); - - return 1; - } - - if (leavechar == 0 && cd->owner->type == BL_PC) { - // Set and announce new owner - cd->owner = (struct block_list *) cd->usersd[0]; - clif_changechatowner(cd, cd->usersd[0]); - clif_clearchat(cd, 0); - - //Adjust Chat location after owner has been changed. - map_delblock(&cd->bl); - cd->bl.x=cd->usersd[0]->bl.x; - cd->bl.y=cd->usersd[0]->bl.y; - map_addblock(&cd->bl); - - clif_dispchat(cd,0); - } else - clif_dispchat(cd,0); // refresh chatroom - - return 0; + struct chat_data* cd; + int i; + int leavechar; + + nullpo_retr(1, sd); + + cd = (struct chat_data*)map_id2bl(sd->chatID); + if( cd == NULL ) + { + pc_setchatid(sd, 0); + return 1; + } + + ARR_FIND( 0, cd->users, i, cd->usersd[i] == sd ); + if ( i == cd->users ) + { // Not found in the chatroom? + pc_setchatid(sd, 0); + return -1; + } + + clif_leavechat(cd, sd, kicked); + pc_setchatid(sd, 0); + cd->users--; + + leavechar = i; + + for( i = leavechar; i < cd->users; i++ ) + cd->usersd[i] = cd->usersd[i+1]; + + + if( cd->users == 0 && cd->owner->type == BL_PC ) { // Delete empty chatroom + struct skill_unit* unit = NULL; + struct skill_unit_group* group = NULL; + + clif_clearchat(cd, 0); + db_destroy(cd->kick_list); + map_deliddb(&cd->bl); + map_delblock(&cd->bl); + map_freeblock(&cd->bl); + + unit = map_find_skill_unit_oncell(&sd->bl, sd->bl.x, sd->bl.y, AL_WARP, NULL, 0); + group = (unit != NULL) ? unit->group : NULL; + if (group != NULL) + ext_skill_unit_onplace(unit, &sd->bl, group->tick); + + return 1; + } + + if( leavechar == 0 && cd->owner->type == BL_PC ) + { // Set and announce new owner + cd->owner = (struct block_list*) cd->usersd[0]; + clif_changechatowner(cd, cd->usersd[0]); + clif_clearchat(cd, 0); + + //Adjust Chat location after owner has been changed. + map_delblock( &cd->bl ); + cd->bl.x=cd->usersd[0]->bl.x; + cd->bl.y=cd->usersd[0]->bl.y; + map_addblock( &cd->bl ); + + clif_dispchat(cd,0); + } + else + clif_dispchat(cd,0); // refresh chatroom + + return 0; } /*========================================== * change a chatroom's owner *------------------------------------------*/ -int chat_changechatowner(struct map_session_data *sd, const char *nextownername) +int chat_changechatowner(struct map_session_data* sd, const char* nextownername) { - struct chat_data *cd; - struct map_session_data *tmpsd; - int i; + struct chat_data* cd; + struct map_session_data* tmpsd; + int i; - nullpo_retr(1, sd); + nullpo_retr(1, sd); - cd = (struct chat_data *)map_id2bl(sd->chatID); - if (cd == NULL || (struct block_list *) sd != cd->owner) - return 1; + cd = (struct chat_data*)map_id2bl(sd->chatID); + if( cd == NULL || (struct block_list*) sd != cd->owner ) + return 1; - ARR_FIND(1, cd->users, i, strncmp(cd->usersd[i]->status.name, nextownername, NAME_LENGTH) == 0); - if (i == cd->users) - return -1; // name not found + ARR_FIND( 1, cd->users, i, strncmp(cd->usersd[i]->status.name, nextownername, NAME_LENGTH) == 0 ); + if( i == cd->users ) + return -1; // name not found - // erase temporarily - clif_clearchat(cd,0); + // erase temporarily + clif_clearchat(cd,0); - // set new owner - cd->owner = (struct block_list *) cd->usersd[i]; - clif_changechatowner(cd,cd->usersd[i]); + // set new owner + cd->owner = (struct block_list*) cd->usersd[i]; + clif_changechatowner(cd,cd->usersd[i]); - // swap the old and new owners' positions - tmpsd = cd->usersd[i]; - cd->usersd[i] = cd->usersd[0]; - cd->usersd[0] = tmpsd; + // swap the old and new owners' positions + tmpsd = cd->usersd[i]; + cd->usersd[i] = cd->usersd[0]; + cd->usersd[0] = tmpsd; - // set the new chatroom position - map_delblock(&cd->bl); - cd->bl.x = cd->owner->x; - cd->bl.y = cd->owner->y; - map_addblock(&cd->bl); + // set the new chatroom position + map_delblock( &cd->bl ); + cd->bl.x = cd->owner->x; + cd->bl.y = cd->owner->y; + map_addblock( &cd->bl ); - // and display again - clif_dispchat(cd,0); + // and display again + clif_dispchat(cd,0); - return 0; + return 0; } /*========================================== * change a chatroom's status (title, etc) *------------------------------------------*/ -int chat_changechatstatus(struct map_session_data *sd, const char *title, const char *pass, int limit, bool pub) +int chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) { - struct chat_data *cd; + struct chat_data* cd; - nullpo_retr(1, sd); + nullpo_retr(1, sd); - cd = (struct chat_data *)map_id2bl(sd->chatID); - if (cd==NULL || (struct block_list *)sd != cd->owner) - return 1; + cd = (struct chat_data*)map_id2bl(sd->chatID); + if( cd==NULL || (struct block_list *)sd != cd->owner ) + return 1; - safestrncpy(cd->title, title, CHATROOM_TITLE_SIZE); - safestrncpy(cd->pass, pass, CHATROOM_PASS_SIZE); - cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); - cd->pub = pub; + safestrncpy(cd->title, title, CHATROOM_TITLE_SIZE); + safestrncpy(cd->pass, pass, CHATROOM_PASS_SIZE); + cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); + cd->pub = pub; - clif_changechatstatus(cd); - clif_dispchat(cd,0); + clif_changechatstatus(cd); + clif_dispchat(cd,0); - return 0; + return 0; } /*========================================== * kick an user from a chatroom *------------------------------------------*/ -int chat_kickchat(struct map_session_data *sd, const char *kickusername) +int chat_kickchat(struct map_session_data* sd, const char* kickusername) { - struct chat_data *cd; - int i; + struct chat_data* cd; + int i; - nullpo_retr(1, sd); + nullpo_retr(1, sd); - cd = (struct chat_data *)map_id2bl(sd->chatID); + cd = (struct chat_data *)map_id2bl(sd->chatID); + + if( cd==NULL || (struct block_list *)sd != cd->owner ) + return -1; - if (cd==NULL || (struct block_list *)sd != cd->owner) - return -1; + ARR_FIND( 0, cd->users, i, strncmp(cd->usersd[i]->status.name, kickusername, NAME_LENGTH) == 0 ); + if( i == cd->users ) + return -1; - ARR_FIND(0, cd->users, i, strncmp(cd->usersd[i]->status.name, kickusername, NAME_LENGTH) == 0); - if (i == cd->users) - return -1; + if (pc_has_permission(cd->usersd[i], PC_PERM_NO_CHAT_KICK)) + return 0; //gm kick protection [Valaris] + + idb_put(cd->kick_list,cd->usersd[i]->status.char_id,(void*)1); - if (pc_has_permission(cd->usersd[i], PC_PERM_NO_CHAT_KICK)) - return 0; //gm kick protection [Valaris] - - idb_put(cd->kick_list,cd->usersd[i]->status.char_id,(void *)1); - - chat_leavechat(cd->usersd[i],1); - return 0; + chat_leavechat(cd->usersd[i],1); + return 0; } /// Creates a chat room for the npc. -int chat_createnpcchat(struct npc_data *nd, const char *title, int limit, bool pub, int trigger, const char *ev, int zeny, int minLvl, int maxLvl) +int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl) { - struct chat_data *cd; - nullpo_ret(nd); + struct chat_data* cd; + nullpo_ret(nd); - if (nd->chat_id) { - ShowError("chat_createnpcchat: npc '%s' already has a chatroom, cannot create new one!\n", nd->exname); - return 0; - } + if( nd->chat_id ) { + ShowError("chat_createnpcchat: npc '%s' already has a chatroom, cannot create new one!\n", nd->exname); + return 0; + } - if (zeny > MAX_ZENY || maxLvl > MAX_LEVEL) { - ShowError("chat_createnpcchat: npc '%s' has a required lvl or amount of zeny over the max limit!\n", nd->exname); - return 0; - } + if( zeny > MAX_ZENY || maxLvl > MAX_LEVEL ) { + ShowError("chat_createnpcchat: npc '%s' has a required lvl or amount of zeny over the max limit!\n", nd->exname); + return 0; + } - cd = chat_createchat(&nd->bl, title, "", limit, pub, trigger, ev, zeny, minLvl, maxLvl); + cd = chat_createchat(&nd->bl, title, "", limit, pub, trigger, ev, zeny, minLvl, maxLvl); - if (cd) { - nd->chat_id = cd->bl.id; - clif_dispchat(cd,0); - } + if( cd ) { + nd->chat_id = cd->bl.id; + clif_dispchat(cd,0); + } - return 0; + return 0; } /// Removes the chatroom from the npc. -int chat_deletenpcchat(struct npc_data *nd) +int chat_deletenpcchat(struct npc_data* nd) { - struct chat_data *cd; - nullpo_ret(nd); - - cd = (struct chat_data *)map_id2bl(nd->chat_id); - if (cd == NULL) - return 0; - - chat_npckickall(cd); - clif_clearchat(cd, 0); - map_deliddb(&cd->bl); - map_delblock(&cd->bl); - map_freeblock(&cd->bl); - nd->chat_id = 0; - - return 0; + struct chat_data *cd; + nullpo_ret(nd); + + cd = (struct chat_data*)map_id2bl(nd->chat_id); + if( cd == NULL ) + return 0; + + chat_npckickall(cd); + clif_clearchat(cd, 0); + map_deliddb(&cd->bl); + map_delblock(&cd->bl); + map_freeblock(&cd->bl); + nd->chat_id = 0; + + return 0; } /*========================================== @@ -376,40 +386,40 @@ int chat_deletenpcchat(struct npc_data *nd) *------------------------------------------*/ int chat_triggerevent(struct chat_data *cd) { - nullpo_ret(cd); + nullpo_ret(cd); - if (cd->users >= cd->trigger && cd->npc_event[0]) - npc_event_do(cd->npc_event); - return 0; + if( cd->users >= cd->trigger && cd->npc_event[0] ) + npc_event_do(cd->npc_event); + return 0; } /// Enables the event of the chat room. /// At most, 127 users are needed to trigger the event. -int chat_enableevent(struct chat_data *cd) +int chat_enableevent(struct chat_data* cd) { - nullpo_ret(cd); + nullpo_ret(cd); - cd->trigger &= 0x7f; - chat_triggerevent(cd); - return 0; + cd->trigger &= 0x7f; + chat_triggerevent(cd); + return 0; } /// Disables the event of the chat room -int chat_disableevent(struct chat_data *cd) +int chat_disableevent(struct chat_data* cd) { - nullpo_ret(cd); + nullpo_ret(cd); - cd->trigger |= 0x80; - return 0; + cd->trigger |= 0x80; + return 0; } /// Kicks all the users from the chat room. -int chat_npckickall(struct chat_data *cd) +int chat_npckickall(struct chat_data* cd) { - nullpo_ret(cd); + nullpo_ret(cd); - while (cd->users > 0) - chat_leavechat(cd->usersd[cd->users-1],0); + while( cd->users > 0 ) + chat_leavechat(cd->usersd[cd->users-1],0); - return 0; + return 0; } diff --git a/src/map/chat.h b/src/map/chat.h index 3e7d0d283..cb2e6ecd9 100644 --- a/src/map/chat.h +++ b/src/map/chat.h @@ -10,34 +10,34 @@ struct chat_data; struct chat_data { - struct block_list bl; // data for this map object - char title[CHATROOM_TITLE_SIZE]; // room title - char pass[CHATROOM_PASS_SIZE]; // password - bool pub; // private/public flag - uint8 users; // current user count - uint8 limit; // join limit - uint8 trigger; // number of users needed to trigger event - uint32 zeny; // required zeny to join - uint32 minLvl; // minimum base level to join - uint32 maxLvl; // maximum base level allowed to join - struct map_session_data *usersd[20]; - struct block_list *owner; - char npc_event[EVENT_NAME_LENGTH]; - DBMap *kick_list; //DBMap of users who were kicked from this chat + struct block_list bl; // data for this map object + char title[CHATROOM_TITLE_SIZE]; // room title + char pass[CHATROOM_PASS_SIZE]; // password + bool pub; // private/public flag + uint8 users; // current user count + uint8 limit; // join limit + uint8 trigger; // number of users needed to trigger event + uint32 zeny; // required zeny to join + uint32 minLvl; // minimum base level to join + uint32 maxLvl; // maximum base level allowed to join + struct map_session_data* usersd[20]; + struct block_list* owner; + char npc_event[EVENT_NAME_LENGTH]; + DBMap* kick_list; //DBMap of users who were kicked from this chat }; -int chat_createpcchat(struct map_session_data *sd, const char *title, const char *pass, int limit, bool pub); -int chat_joinchat(struct map_session_data *sd, int chatid, const char *pass); -int chat_leavechat(struct map_session_data *sd, bool kicked); -int chat_changechatowner(struct map_session_data *sd, const char *nextownername); -int chat_changechatstatus(struct map_session_data *sd, const char *title, const char *pass, int limit, bool pub); -int chat_kickchat(struct map_session_data *sd, const char *kickusername); +int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub); +int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass); +int chat_leavechat(struct map_session_data* sd, bool kicked); +int chat_changechatowner(struct map_session_data* sd, const char* nextownername); +int chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub); +int chat_kickchat(struct map_session_data* sd, const char* kickusername); -int chat_createnpcchat(struct npc_data *nd, const char *title, int limit, bool pub, int trigger, const char *ev, int zeny, int minLvl, int maxLvl); -int chat_deletenpcchat(struct npc_data *nd); -int chat_enableevent(struct chat_data *cd); -int chat_disableevent(struct chat_data *cd); -int chat_npckickall(struct chat_data *cd); +int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl); +int chat_deletenpcchat(struct npc_data* nd); +int chat_enableevent(struct chat_data* cd); +int chat_disableevent(struct chat_data* cd); +int chat_npckickall(struct chat_data* cd); #endif /* _CHAT_H_ */ diff --git a/src/map/chrif.c b/src/map/chrif.c index 8ba47a601..1575e11f4 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -36,15 +36,15 @@ static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data); static struct eri *auth_db_ers; //For reutilizing player login structures. -static DBMap *auth_db; // int id -> struct auth_node* +static DBMap* auth_db; // int id -> struct auth_node* static const int packet_len_table[0x3d] = { // U - used, F - free - 60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff - 6,-1,18, 7,-1,39,30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07 - 6,30, 0, 0,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, F->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f - 11,10,10, 0,11, 0,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, F->2b15, U->2b16, U->2b17 - 2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f - -1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27 + 60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff + 6,-1,18, 7,-1,39,30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07 + 6,30, 0, 0,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, F->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f + 11,10,10, 0,11, 0,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, F->2b15, U->2b16, U->2b17 + 2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f + -1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27 }; //Used Packets: @@ -116,163 +116,151 @@ int other_mapserver_count=0; //Holds count of how many other map servers are onl /// Resets all the data. -void chrif_reset(void) -{ - // TODO kick everyone out and reset everything [FlavioJS] - exit(EXIT_FAILURE); +void chrif_reset(void) { + // TODO kick everyone out and reset everything [FlavioJS] + exit(EXIT_FAILURE); } /// Checks the conditions for the server to stop. /// Releases the cookie when all characters are saved. /// If all the conditions are met, it stops the core loop. -void chrif_check_shutdown(void) -{ - if (runflag != MAPSERVER_ST_SHUTDOWN) - return; - if (auth_db->size(auth_db) > 0) - return; - runflag = CORE_ST_STOP; -} - -struct auth_node *chrif_search(int account_id) { - return (struct auth_node *)idb_get(auth_db, account_id); -} - -struct auth_node *chrif_auth_check(int account_id, int char_id, enum sd_state state) { - struct auth_node *node = chrif_search(account_id); - - return (node && node->char_id == char_id && node->state == state) ? node : NULL; -} - -bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) -{ - struct auth_node *node; - - if ((node = chrif_auth_check(account_id, char_id, state))) { - int fd = node->sd ? node->sd->fd : node->fd; - - if (session[fd] && session[fd]->session_data == node->sd) - session[fd]->session_data = NULL; - - if (node->char_dat) - aFree(node->char_dat); - - if (node->sd) - aFree(node->sd); - - ers_free(auth_db_ers, node); - idb_remove(auth_db,account_id); - - return true; - } - return false; +void chrif_check_shutdown(void) { + if( runflag != MAPSERVER_ST_SHUTDOWN ) + return; + if( auth_db->size(auth_db) > 0 ) + return; + runflag = CORE_ST_STOP; +} + +struct auth_node* chrif_search(int account_id) { + return (struct auth_node*)idb_get(auth_db, account_id); +} + +struct auth_node* chrif_auth_check(int account_id, int char_id, enum sd_state state) { + struct auth_node *node = chrif_search(account_id); + + return ( node && node->char_id == char_id && node->state == state ) ? node : NULL; +} + +bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) { + struct auth_node *node; + + if ( (node = chrif_auth_check(account_id, char_id, state) ) ) { + int fd = node->sd ? node->sd->fd : node->fd; + + if ( session[fd] && session[fd]->session_data == node->sd ) + session[fd]->session_data = NULL; + + if ( node->char_dat ) + aFree(node->char_dat); + + if ( node->sd ) + aFree(node->sd); + + ers_free(auth_db_ers, node); + idb_remove(auth_db,account_id); + + return true; + } + return false; } //Moves the sd character to the auth_db structure. -static bool chrif_sd_to_auth(TBL_PC *sd, enum sd_state state) -{ - struct auth_node *node; - - if (chrif_search(sd->status.account_id)) - return false; //Already exists? - - node = ers_alloc(auth_db_ers, struct auth_node); - - memset(node, 0, sizeof(struct auth_node)); - - node->account_id = sd->status.account_id; - node->char_id = sd->status.char_id; - node->login_id1 = sd->login_id1; - node->login_id2 = sd->login_id2; - node->sex = sd->status.sex; - node->fd = sd->fd; - node->sd = sd; //Data from logged on char. - node->node_created = gettick(); //timestamp for node timeouts - node->state = state; - - sd->state.active = 0; - - idb_put(auth_db, node->account_id, node); - - return true; -} - -static bool chrif_auth_logout(TBL_PC *sd, enum sd_state state) -{ - - if (sd->fd && state == ST_LOGOUT) { //Disassociate player, and free it after saving ack returns. [Skotlex] - //fd info must not be lost for ST_MAPCHANGE as a final packet needs to be sent to the player. - if (session[sd->fd]) - session[sd->fd]->session_data = NULL; - sd->fd = 0; - } - - return chrif_sd_to_auth(sd, state); -} - -bool chrif_auth_finished(TBL_PC *sd) -{ - struct auth_node *node= chrif_search(sd->status.account_id); - - if (node && node->sd == sd && node->state == ST_LOGIN) { - node->sd = NULL; - - return chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN); - } - - return false; +static bool chrif_sd_to_auth(TBL_PC* sd, enum sd_state state) { + struct auth_node *node; + + if ( chrif_search(sd->status.account_id) ) + return false; //Already exists? + + node = ers_alloc(auth_db_ers, struct auth_node); + + memset(node, 0, sizeof(struct auth_node)); + + node->account_id = sd->status.account_id; + node->char_id = sd->status.char_id; + node->login_id1 = sd->login_id1; + node->login_id2 = sd->login_id2; + node->sex = sd->status.sex; + node->fd = sd->fd; + node->sd = sd; //Data from logged on char. + node->node_created = gettick(); //timestamp for node timeouts + node->state = state; + + sd->state.active = 0; + + idb_put(auth_db, node->account_id, node); + + return true; +} + +static bool chrif_auth_logout(TBL_PC* sd, enum sd_state state) { + + if(sd->fd && state == ST_LOGOUT) { //Disassociate player, and free it after saving ack returns. [Skotlex] + //fd info must not be lost for ST_MAPCHANGE as a final packet needs to be sent to the player. + if ( session[sd->fd] ) + session[sd->fd]->session_data = NULL; + sd->fd = 0; + } + + return chrif_sd_to_auth(sd, state); +} + +bool chrif_auth_finished(TBL_PC* sd) { + struct auth_node *node= chrif_search(sd->status.account_id); + + if ( node && node->sd == sd && node->state == ST_LOGIN ) { + node->sd = NULL; + + return chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN); + } + + return false; } // sets char-server's user id -void chrif_setuserid(char *id) -{ - memcpy(userid, id, NAME_LENGTH); +void chrif_setuserid(char *id) { + memcpy(userid, id, NAME_LENGTH); } // sets char-server's password -void chrif_setpasswd(char *pwd) -{ - memcpy(passwd, pwd, NAME_LENGTH); +void chrif_setpasswd(char *pwd) { + memcpy(passwd, pwd, NAME_LENGTH); } // security check, prints warning if using default password -void chrif_checkdefaultlogin(void) -{ - if (strcmp(userid, "s1")==0 && strcmp(passwd, "p1")==0) { - ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n"); - ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n"); - ShowNotice("and then edit your user/password in conf/map_athena.conf (or conf/import/map_conf.txt)\n"); - } +void chrif_checkdefaultlogin(void) { + if (strcmp(userid, "s1")==0 && strcmp(passwd, "p1")==0) { + ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n"); + ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n"); + ShowNotice("and then edit your user/password in conf/map_athena.conf (or conf/import/map_conf.txt)\n"); + } } // sets char-server's ip address -int chrif_setip(const char *ip) -{ - char ip_str[16]; - - if (!(char_ip = host2ip(ip))) { - ShowWarning("Failed to Resolve Char Server Address! (%s)\n", ip); - - return 0; - } - - strncpy(char_ip_str, ip, sizeof(char_ip_str)); - - ShowInfo("Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(char_ip, ip_str)); - - return 1; +int chrif_setip(const char* ip) { + char ip_str[16]; + + if ( !( char_ip = host2ip(ip) ) ) { + ShowWarning("Failed to Resolve Char Server Address! (%s)\n", ip); + + return 0; + } + + strncpy(char_ip_str, ip, sizeof(char_ip_str)); + + ShowInfo("Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(char_ip, ip_str)); + + return 1; } // sets char-server's port number -void chrif_setport(uint16 port) -{ - char_port = port; +void chrif_setport(uint16 port) { + char_port = port; } // says whether the char-server is connected or not -int chrif_isconnected(void) -{ - return (char_fd > 0 && session[char_fd] != NULL && chrif_state == 2); +int chrif_isconnected(void) { + return (char_fd > 0 && session[char_fd] != NULL && chrif_state == 2); } /*========================================== @@ -280,429 +268,413 @@ int chrif_isconnected(void) * Flag = 1: Character is quitting * Flag = 2: Character is changing map-servers *------------------------------------------*/ -int chrif_save(struct map_session_data *sd, int flag) -{ - nullpo_retr(-1, sd); - - pc_makesavestatus(sd); - - if (flag && sd->state.active) { //Store player data which is quitting - //FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex] - if (chrif_isconnected()) - chrif_save_scdata(sd); - if (!chrif_auth_logout(sd,flag == 1 ? ST_LOGOUT : ST_MAPCHANGE)) - ShowError("chrif_save: Failed to set up player %d:%d for proper quitting!\n", sd->status.account_id, sd->status.char_id); - } - - chrif_check(-1); //Character is saved on reconnect. - - //For data sync - if (sd->state.storage_flag == 2) - storage_guild_storagesave(sd->status.account_id, sd->status.guild_id, flag); - - if (flag) - sd->state.storage_flag = 0; //Force close it. - - //Saving of registry values. - if (sd->state.reg_dirty&4) - intif_saveregistry(sd, 3); //Save char regs - if (sd->state.reg_dirty&2) - intif_saveregistry(sd, 2); //Save account regs - if (sd->state.reg_dirty&1) - intif_saveregistry(sd, 1); //Save account2 regs - - WFIFOHEAD(char_fd, sizeof(sd->status) + 13); - WFIFOW(char_fd,0) = 0x2b01; - WFIFOW(char_fd,2) = sizeof(sd->status) + 13; - WFIFOL(char_fd,4) = sd->status.account_id; - WFIFOL(char_fd,8) = sd->status.char_id; - WFIFOB(char_fd,12) = (flag==1)?1:0; //Flag to tell char-server this character is quitting. - memcpy(WFIFOP(char_fd,13), &sd->status, sizeof(sd->status)); - WFIFOSET(char_fd, WFIFOW(char_fd,2)); - - if (sd->status.pet_id > 0 && sd->pd) - intif_save_petdata(sd->status.account_id,&sd->pd->pet); - if (sd->hd && merc_is_hom_active(sd->hd)) - merc_save(sd->hd); - if (sd->md && mercenary_get_lifetime(sd->md) > 0) - mercenary_save(sd->md); - if (sd->ed && elemental_get_lifetime(sd->ed) > 0) - elemental_save(sd->ed); - if (sd->save_quest) - intif_quest_save(sd); - - return 0; +int chrif_save(struct map_session_data *sd, int flag) { + nullpo_retr(-1, sd); + + pc_makesavestatus(sd); + + if (flag && sd->state.active) { //Store player data which is quitting + //FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex] + if ( chrif_isconnected() ) + chrif_save_scdata(sd); + if ( !chrif_auth_logout(sd,flag == 1 ? ST_LOGOUT : ST_MAPCHANGE) ) + ShowError("chrif_save: Failed to set up player %d:%d for proper quitting!\n", sd->status.account_id, sd->status.char_id); + } + + chrif_check(-1); //Character is saved on reconnect. + + //For data sync + if (sd->state.storage_flag == 2) + storage_guild_storagesave(sd->status.account_id, sd->status.guild_id, flag); + + if (flag) + sd->state.storage_flag = 0; //Force close it. + + //Saving of registry values. + if (sd->state.reg_dirty&4) + intif_saveregistry(sd, 3); //Save char regs + if (sd->state.reg_dirty&2) + intif_saveregistry(sd, 2); //Save account regs + if (sd->state.reg_dirty&1) + intif_saveregistry(sd, 1); //Save account2 regs + + WFIFOHEAD(char_fd, sizeof(sd->status) + 13); + WFIFOW(char_fd,0) = 0x2b01; + WFIFOW(char_fd,2) = sizeof(sd->status) + 13; + WFIFOL(char_fd,4) = sd->status.account_id; + WFIFOL(char_fd,8) = sd->status.char_id; + WFIFOB(char_fd,12) = (flag==1)?1:0; //Flag to tell char-server this character is quitting. + memcpy(WFIFOP(char_fd,13), &sd->status, sizeof(sd->status)); + WFIFOSET(char_fd, WFIFOW(char_fd,2)); + + if( sd->status.pet_id > 0 && sd->pd ) + intif_save_petdata(sd->status.account_id,&sd->pd->pet); + if( sd->hd && merc_is_hom_active(sd->hd) ) + merc_save(sd->hd); + if( sd->md && mercenary_get_lifetime(sd->md) > 0 ) + mercenary_save(sd->md); + if( sd->ed && elemental_get_lifetime(sd->ed) > 0 ) + elemental_save(sd->ed); + if( sd->save_quest ) + intif_quest_save(sd); + + return 0; } // connects to char-server (plaintext) -int chrif_connect(int fd) -{ - ShowStatus("Logging in to char server...\n", char_fd); - WFIFOHEAD(fd,60); - WFIFOW(fd,0) = 0x2af8; - memcpy(WFIFOP(fd,2), userid, NAME_LENGTH); - memcpy(WFIFOP(fd,26), passwd, NAME_LENGTH); - WFIFOL(fd,50) = 0; - WFIFOL(fd,54) = htonl(clif_getip()); - WFIFOW(fd,58) = htons(clif_getport()); - WFIFOSET(fd,60); +int chrif_connect(int fd) { + ShowStatus("Logging in to char server...\n", char_fd); + WFIFOHEAD(fd,60); + WFIFOW(fd,0) = 0x2af8; + memcpy(WFIFOP(fd,2), userid, NAME_LENGTH); + memcpy(WFIFOP(fd,26), passwd, NAME_LENGTH); + WFIFOL(fd,50) = 0; + WFIFOL(fd,54) = htonl(clif_getip()); + WFIFOW(fd,58) = htons(clif_getport()); + WFIFOSET(fd,60); - return 0; + return 0; } // sends maps to char-server -int chrif_sendmap(int fd) -{ - int i; - - ShowStatus("Sending maps to char server...\n"); - - // Sending normal maps, not instances - WFIFOHEAD(fd, 4 + instance_start * 4); - WFIFOW(fd,0) = 0x2afa; - for (i = 0; i < instance_start; i++) - WFIFOW(fd,4+i*4) = map[i].index; - WFIFOW(fd,2) = 4 + i * 4; - WFIFOSET(fd,WFIFOW(fd,2)); - - return 0; +int chrif_sendmap(int fd) { + int i; + + ShowStatus("Sending maps to char server...\n"); + + // Sending normal maps, not instances + WFIFOHEAD(fd, 4 + instance_start * 4); + WFIFOW(fd,0) = 0x2afa; + for(i = 0; i < instance_start; i++) + WFIFOW(fd,4+i*4) = map[i].index; + WFIFOW(fd,2) = 4 + i * 4; + WFIFOSET(fd,WFIFOW(fd,2)); + + return 0; } // receive maps from some other map-server (relayed via char-server) -int chrif_recvmap(int fd) -{ - int i, j; - uint32 ip = ntohl(RFIFOL(fd,4)); - uint16 port = ntohs(RFIFOW(fd,8)); - - for (i = 10, j = 0; i < RFIFOW(fd,2); i += 4, j++) { - map_setipport(RFIFOW(fd,i), ip, port); - } +int chrif_recvmap(int fd) { + int i, j; + uint32 ip = ntohl(RFIFOL(fd,4)); + uint16 port = ntohs(RFIFOW(fd,8)); - if (battle_config.etc_log) - ShowStatus("Received maps from %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j); + for(i = 10, j = 0; i < RFIFOW(fd,2); i += 4, j++) { + map_setipport(RFIFOW(fd,i), ip, port); + } + + if (battle_config.etc_log) + ShowStatus("Received maps from %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j); - other_mapserver_count++; - - return 0; + other_mapserver_count++; + + return 0; } // remove specified maps (used when some other map-server disconnects) -int chrif_removemap(int fd) -{ - int i, j; - uint32 ip = RFIFOL(fd,4); - uint16 port = RFIFOW(fd,8); - - for (i = 10, j = 0; i < RFIFOW(fd, 2); i += 4, j++) - map_eraseipport(RFIFOW(fd, i), ip, port); +int chrif_removemap(int fd) { + int i, j; + uint32 ip = RFIFOL(fd,4); + uint16 port = RFIFOW(fd,8); - other_mapserver_count--; + for(i = 10, j = 0; i < RFIFOW(fd, 2); i += 4, j++) + map_eraseipport(RFIFOW(fd, i), ip, port); - if (battle_config.etc_log) - ShowStatus("remove map of server %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j); - - return 0; + other_mapserver_count--; + + if(battle_config.etc_log) + ShowStatus("remove map of server %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j); + + return 0; } // received after a character has been "final saved" on the char-server -static void chrif_save_ack(int fd) -{ - chrif_auth_delete(RFIFOL(fd,2), RFIFOL(fd,6), ST_LOGOUT); - chrif_check_shutdown(); +static void chrif_save_ack(int fd) { + chrif_auth_delete(RFIFOL(fd,2), RFIFOL(fd,6), ST_LOGOUT); + chrif_check_shutdown(); } // request to move a character between mapservers -int chrif_changemapserver(struct map_session_data *sd, uint32 ip, uint16 port) -{ - nullpo_retr(-1, sd); - - if (other_mapserver_count < 1) {//No other map servers are online! - clif_authfail_fd(sd->fd, 0); - return -1; - } - - chrif_check(-1); - - WFIFOHEAD(char_fd,35); - WFIFOW(char_fd, 0) = 0x2b05; - WFIFOL(char_fd, 2) = sd->bl.id; - WFIFOL(char_fd, 6) = sd->login_id1; - WFIFOL(char_fd,10) = sd->login_id2; - WFIFOL(char_fd,14) = sd->status.char_id; - WFIFOW(char_fd,18) = sd->mapindex; - WFIFOW(char_fd,20) = sd->bl.x; - WFIFOW(char_fd,22) = sd->bl.y; - WFIFOL(char_fd,24) = htonl(ip); - WFIFOW(char_fd,28) = htons(port); - WFIFOB(char_fd,30) = sd->status.sex; - WFIFOL(char_fd,31) = htonl(session[sd->fd]->client_addr); - WFIFOL(char_fd,35) = sd->group_id; - WFIFOSET(char_fd,39); - - return 0; +int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port) { + nullpo_retr(-1, sd); + + if (other_mapserver_count < 1) {//No other map servers are online! + clif_authfail_fd(sd->fd, 0); + return -1; + } + + chrif_check(-1); + + WFIFOHEAD(char_fd,35); + WFIFOW(char_fd, 0) = 0x2b05; + WFIFOL(char_fd, 2) = sd->bl.id; + WFIFOL(char_fd, 6) = sd->login_id1; + WFIFOL(char_fd,10) = sd->login_id2; + WFIFOL(char_fd,14) = sd->status.char_id; + WFIFOW(char_fd,18) = sd->mapindex; + WFIFOW(char_fd,20) = sd->bl.x; + WFIFOW(char_fd,22) = sd->bl.y; + WFIFOL(char_fd,24) = htonl(ip); + WFIFOW(char_fd,28) = htons(port); + WFIFOB(char_fd,30) = sd->status.sex; + WFIFOL(char_fd,31) = htonl(session[sd->fd]->client_addr); + WFIFOL(char_fd,35) = sd->group_id; + WFIFOSET(char_fd,39); + + return 0; } /// map-server change request acknowledgement (positive or negative) /// R 2b06 <account_id>.L <login_id1>.L <login_id2>.L <char_id>.L <map_index>.W <x>.W <y>.W <ip>.L <port>.W -int chrif_changemapserverack(int account_id, int login_id1, int login_id2, int char_id, short map_index, short x, short y, uint32 ip, uint16 port) -{ - struct auth_node *node; - - if (!(node = chrif_auth_check(account_id, char_id, ST_MAPCHANGE))) - return -1; +int chrif_changemapserverack(int account_id, int login_id1, int login_id2, int char_id, short map_index, short x, short y, uint32 ip, uint16 port) { + struct auth_node *node; + + if ( !( node = chrif_auth_check(account_id, char_id, ST_MAPCHANGE) ) ) + return -1; - if (!login_id1) { - ShowError("map server change failed.\n"); - clif_authfail_fd(node->fd, 0); - } else - clif_changemapserver(node->sd, map_index, x, y, ntohl(ip), ntohs(port)); + if ( !login_id1 ) { + ShowError("map server change failed.\n"); + clif_authfail_fd(node->fd, 0); + } else + clif_changemapserver(node->sd, map_index, x, y, ntohl(ip), ntohs(port)); - //Player has been saved already, remove him from memory. [Skotlex] - chrif_auth_delete(account_id, char_id, ST_MAPCHANGE); + //Player has been saved already, remove him from memory. [Skotlex] + chrif_auth_delete(account_id, char_id, ST_MAPCHANGE); - return 0; + return 0; } /*========================================== * *------------------------------------------*/ -int chrif_connectack(int fd) -{ - static bool char_init_done = false; +int chrif_connectack(int fd) { + static bool char_init_done = false; - if (RFIFOB(fd,2)) { - ShowFatalError("Connection to char-server failed %d.\n", RFIFOB(fd,2)); - exit(EXIT_FAILURE); - } + if (RFIFOB(fd,2)) { + ShowFatalError("Connection to char-server failed %d.\n", RFIFOB(fd,2)); + exit(EXIT_FAILURE); + } - ShowStatus("Successfully logged on to Char Server (Connection: '"CL_WHITE"%d"CL_RESET"').\n",fd); - chrif_state = 1; - chrif_connected = 1; + ShowStatus("Successfully logged on to Char Server (Connection: '"CL_WHITE"%d"CL_RESET"').\n",fd); + chrif_state = 1; + chrif_connected = 1; - chrif_sendmap(fd); + chrif_sendmap(fd); - ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit")); - if (!char_init_done) { - char_init_done = true; - ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce")); - guild_castle_map_init(); - } + ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit")); + if( !char_init_done ) { + char_init_done = true; + ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce")); + guild_castle_map_init(); + } - return 0; + return 0; } /** * @see DBApply */ -static int chrif_reconnect(DBKey key, DBData *data, va_list ap) -{ - struct auth_node *node = db_data2ptr(data); - - switch (node->state) { - case ST_LOGIN: - if (node->sd && node->char_dat == NULL) { //Since there is no way to request the char auth, make it fail. - pc_authfail(node->sd); - chrif_char_offline(node->sd); - chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN); - } - break; - case ST_LOGOUT: - //Re-send final save - chrif_save(node->sd, 1); - break; - case ST_MAPCHANGE: { //Re-send map-change request. - struct map_session_data *sd = node->sd; - uint32 ip; - uint16 port; - - if (map_mapname2ipport(sd->mapindex,&ip,&port) == 0) - chrif_changemapserver(sd, ip, port); - else //too much lag/timeout is the closest explanation for this error. - clif_authfail_fd(sd->fd, 3); - - break; - } - } - - return 0; +static int chrif_reconnect(DBKey key, DBData *data, va_list ap) { + struct auth_node *node = db_data2ptr(data); + + switch (node->state) { + case ST_LOGIN: + if ( node->sd && node->char_dat == NULL ) {//Since there is no way to request the char auth, make it fail. + pc_authfail(node->sd); + chrif_char_offline(node->sd); + chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN); + } + break; + case ST_LOGOUT: + //Re-send final save + chrif_save(node->sd, 1); + break; + case ST_MAPCHANGE: { //Re-send map-change request. + struct map_session_data *sd = node->sd; + uint32 ip; + uint16 port; + + if( map_mapname2ipport(sd->mapindex,&ip,&port) == 0 ) + chrif_changemapserver(sd, ip, port); + else //too much lag/timeout is the closest explanation for this error. + clif_authfail_fd(sd->fd, 3); + + break; + } + } + + return 0; } /// Called when all the connection steps are completed. -void chrif_on_ready(void) -{ - ShowStatus("Map Server is now online.\n"); - - chrif_state = 2; - - chrif_check_shutdown(); +void chrif_on_ready(void) { + ShowStatus("Map Server is now online.\n"); + + chrif_state = 2; + + chrif_check_shutdown(); - //If there are players online, send them to the char-server. [Skotlex] - send_users_tochar(); + //If there are players online, send them to the char-server. [Skotlex] + send_users_tochar(); - //Auth db reconnect handling - auth_db->foreach(auth_db,chrif_reconnect); + //Auth db reconnect handling + auth_db->foreach(auth_db,chrif_reconnect); - //Re-save any storages that were modified in the disconnection time. [Skotlex] - do_reconnect_storage(); + //Re-save any storages that were modified in the disconnection time. [Skotlex] + do_reconnect_storage(); - //Re-save any guild castles that were modified in the disconnection time. - guild_castle_reconnect(-1, 0, 0); + //Re-save any guild castles that were modified in the disconnection time. + guild_castle_reconnect(-1, 0, 0); } /*========================================== * *------------------------------------------*/ -int chrif_sendmapack(int fd) -{ +int chrif_sendmapack(int fd) { + + if (RFIFOB(fd,2)) { + ShowFatalError("chrif : send map list to char server failed %d\n", RFIFOB(fd,2)); + exit(EXIT_FAILURE); + } - if (RFIFOB(fd,2)) { - ShowFatalError("chrif : send map list to char server failed %d\n", RFIFOB(fd,2)); - exit(EXIT_FAILURE); - } - - memcpy(wisp_server_name, RFIFOP(fd,3), NAME_LENGTH); - - chrif_on_ready(); - - return 0; + memcpy(wisp_server_name, RFIFOP(fd,3), NAME_LENGTH); + + chrif_on_ready(); + + return 0; } /*========================================== * Request sc_data from charserver [Skotlex] *------------------------------------------*/ -int chrif_scdata_request(int account_id, int char_id) -{ - +int chrif_scdata_request(int account_id, int char_id) { + #ifdef ENABLE_SC_SAVING - chrif_check(-1); + chrif_check(-1); - WFIFOHEAD(char_fd,10); - WFIFOW(char_fd,0) = 0x2afc; - WFIFOL(char_fd,2) = account_id; - WFIFOL(char_fd,6) = char_id; - WFIFOSET(char_fd,10); + WFIFOHEAD(char_fd,10); + WFIFOW(char_fd,0) = 0x2afc; + WFIFOL(char_fd,2) = account_id; + WFIFOL(char_fd,6) = char_id; + WFIFOSET(char_fd,10); #endif - - return 0; + + return 0; } /*========================================== * Request auth confirmation *------------------------------------------*/ -void chrif_authreq(struct map_session_data *sd) -{ - struct auth_node *node= chrif_search(sd->bl.id); - - if (node != NULL || !chrif_isconnected()) { - set_eof(sd->fd); - return; - } - - WFIFOHEAD(char_fd,19); - WFIFOW(char_fd,0) = 0x2b26; - WFIFOL(char_fd,2) = sd->status.account_id; - WFIFOL(char_fd,6) = sd->status.char_id; - WFIFOL(char_fd,10) = sd->login_id1; - WFIFOB(char_fd,14) = sd->status.sex; - WFIFOL(char_fd,15) = htonl(session[sd->fd]->client_addr); - WFIFOSET(char_fd,19); - chrif_sd_to_auth(sd, ST_LOGIN); +void chrif_authreq(struct map_session_data *sd) { + struct auth_node *node= chrif_search(sd->bl.id); + + if( node != NULL || !chrif_isconnected() ) { + set_eof(sd->fd); + return; + } + + WFIFOHEAD(char_fd,19); + WFIFOW(char_fd,0) = 0x2b26; + WFIFOL(char_fd,2) = sd->status.account_id; + WFIFOL(char_fd,6) = sd->status.char_id; + WFIFOL(char_fd,10) = sd->login_id1; + WFIFOB(char_fd,14) = sd->status.sex; + WFIFOL(char_fd,15) = htonl(session[sd->fd]->client_addr); + WFIFOSET(char_fd,19); + chrif_sd_to_auth(sd, ST_LOGIN); } /*========================================== * Auth confirmation ack *------------------------------------------*/ -void chrif_authok(int fd) -{ - int account_id, group_id, char_id; - uint32 login_id1,login_id2; - time_t expiration_time; - struct mmo_charstatus *status; - struct auth_node *node; - bool changing_mapservers; - TBL_PC *sd; - - //Check if both servers agree on the struct's size - if (RFIFOW(fd,2) - 25 != sizeof(struct mmo_charstatus)) { - ShowError("chrif_authok: Data size mismatch! %d != %d\n", RFIFOW(fd,2) - 25, sizeof(struct mmo_charstatus)); - return; - } - - account_id = RFIFOL(fd,4); - login_id1 = RFIFOL(fd,8); - login_id2 = RFIFOL(fd,12); - expiration_time = (time_t)(int32)RFIFOL(fd,16); - group_id = RFIFOL(fd,20); - changing_mapservers = (RFIFOB(fd,24)); - status = (struct mmo_charstatus *)RFIFOP(fd,25); - char_id = status->char_id; - - //Check if we don't already have player data in our server - //Causes problems if the currently connected player tries to quit or this data belongs to an already connected player which is trying to re-auth. - if ((sd = map_id2sd(account_id)) != NULL) - return; - - if ((node = chrif_search(account_id)) == NULL) - return; // should not happen - - if (node->state != ST_LOGIN) - return; //character in logout phase, do not touch that data. - - if (node->sd == NULL) { - /* - //When we receive double login info and the client has not connected yet, - //discard the older one and keep the new one. - chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN); - */ - return; // should not happen - } - - sd = node->sd; - - if (runflag == MAPSERVER_ST_RUNNING && - node->char_dat == NULL && - node->account_id == account_id && - node->char_id == char_id && - node->login_id1 == login_id1) { - //Auth Ok - if (pc_authok(sd, login_id2, expiration_time, group_id, status, changing_mapservers)) - return; - } else { //Auth Failed - pc_authfail(sd); - } - - chrif_char_offline(sd); //Set him offline, the char server likely has it set as online already. - chrif_auth_delete(account_id, char_id, ST_LOGIN); +void chrif_authok(int fd) { + int account_id, group_id, char_id; + uint32 login_id1,login_id2; + time_t expiration_time; + struct mmo_charstatus* status; + struct auth_node *node; + bool changing_mapservers; + TBL_PC* sd; + + //Check if both servers agree on the struct's size + if( RFIFOW(fd,2) - 25 != sizeof(struct mmo_charstatus) ) { + ShowError("chrif_authok: Data size mismatch! %d != %d\n", RFIFOW(fd,2) - 25, sizeof(struct mmo_charstatus)); + return; + } + + account_id = RFIFOL(fd,4); + login_id1 = RFIFOL(fd,8); + login_id2 = RFIFOL(fd,12); + expiration_time = (time_t)(int32)RFIFOL(fd,16); + group_id = RFIFOL(fd,20); + changing_mapservers = (RFIFOB(fd,24)); + status = (struct mmo_charstatus*)RFIFOP(fd,25); + char_id = status->char_id; + + //Check if we don't already have player data in our server + //Causes problems if the currently connected player tries to quit or this data belongs to an already connected player which is trying to re-auth. + if ( ( sd = map_id2sd(account_id) ) != NULL ) + return; + + if ( ( node = chrif_search(account_id) ) == NULL ) + return; // should not happen + + if ( node->state != ST_LOGIN ) + return; //character in logout phase, do not touch that data. + + if ( node->sd == NULL ) { + /* + //When we receive double login info and the client has not connected yet, + //discard the older one and keep the new one. + chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN); + */ + return; // should not happen + } + + sd = node->sd; + + if( runflag == MAPSERVER_ST_RUNNING && + node->char_dat == NULL && + node->account_id == account_id && + node->char_id == char_id && + node->login_id1 == login_id1 ) + { //Auth Ok + if (pc_authok(sd, login_id2, expiration_time, group_id, status, changing_mapservers)) + return; + } else { //Auth Failed + pc_authfail(sd); + } + + chrif_char_offline(sd); //Set him offline, the char server likely has it set as online already. + chrif_auth_delete(account_id, char_id, ST_LOGIN); } // client authentication failed -void chrif_authfail(int fd) /* HELLO WORLD. ip in RFIFOL 15 is not being used (but is available) */ -{ - int account_id, char_id; - uint32 login_id1; - char sex; - struct auth_node *node; - - account_id = RFIFOL(fd,2); - char_id = RFIFOL(fd,6); - login_id1 = RFIFOL(fd,10); - sex = RFIFOB(fd,14); - - node = chrif_search(account_id); - - if (node != NULL && - node->account_id == account_id && - node->char_id == char_id && - node->login_id1 == login_id1 && - node->sex == sex && - node->state == ST_LOGIN) { - // found a match - clif_authfail_fd(node->fd, 0); - chrif_auth_delete(account_id, char_id, ST_LOGIN); - } +void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used (but is available) */ + int account_id, char_id; + uint32 login_id1; + char sex; + struct auth_node* node; + + account_id = RFIFOL(fd,2); + char_id = RFIFOL(fd,6); + login_id1 = RFIFOL(fd,10); + sex = RFIFOB(fd,14); + + node = chrif_search(account_id); + + if( node != NULL && + node->account_id == account_id && + node->char_id == char_id && + node->login_id1 == login_id1 && + node->sex == sex && + node->state == ST_LOGIN ) + {// found a match + clif_authfail_fd(node->fd, 0); + chrif_auth_delete(account_id, char_id, ST_LOGIN); + } } @@ -710,98 +682,93 @@ void chrif_authfail(int fd) /* HELLO WORLD. ip in RFIFOL 15 is not being used ( * This can still happen (client times out while waiting for char to confirm auth data) * @see DBApply */ -int auth_db_cleanup_sub(DBKey key, DBData *data, va_list ap) -{ - struct auth_node *node = db_data2ptr(data); - const char *states[] = { "Login", "Logout", "Map change" }; - - if (DIFF_TICK(gettick(),node->node_created)>60000) { - switch (node->state) { - case ST_LOGOUT: - //Re-save attempt (->sd should never be null here). - node->node_created = gettick(); //Refresh tick (avoid char-server load if connection is really bad) - chrif_save(node->sd, 1); - break; - default: - //Clear data. any connected players should have timed out by now. - ShowInfo("auth_db: Node (state %s) timed out for %d:%d\n", states[node->state], node->account_id, node->char_id); - chrif_char_offline_nsd(node->account_id, node->char_id); - chrif_auth_delete(node->account_id, node->char_id, node->state); - break; - } - return 1; - } - return 0; -} - -int auth_db_cleanup(int tid, unsigned int tick, int id, intptr_t data) -{ - chrif_check(0); - auth_db->foreach(auth_db, auth_db_cleanup_sub); - return 0; +int auth_db_cleanup_sub(DBKey key, DBData *data, va_list ap) { + struct auth_node *node = db_data2ptr(data); + const char* states[] = { "Login", "Logout", "Map change" }; + + if(DIFF_TICK(gettick(),node->node_created)>60000) { + switch (node->state) { + case ST_LOGOUT: + //Re-save attempt (->sd should never be null here). + node->node_created = gettick(); //Refresh tick (avoid char-server load if connection is really bad) + chrif_save(node->sd, 1); + break; + default: + //Clear data. any connected players should have timed out by now. + ShowInfo("auth_db: Node (state %s) timed out for %d:%d\n", states[node->state], node->account_id, node->char_id); + chrif_char_offline_nsd(node->account_id, node->char_id); + chrif_auth_delete(node->account_id, node->char_id, node->state); + break; + } + return 1; + } + return 0; +} + +int auth_db_cleanup(int tid, unsigned int tick, int id, intptr_t data) { + chrif_check(0); + auth_db->foreach(auth_db, auth_db_cleanup_sub); + return 0; } /*========================================== * *------------------------------------------*/ -int chrif_charselectreq(struct map_session_data *sd, uint32 s_ip) -{ - nullpo_retr(-1, sd); - - if (!sd || !sd->bl.id || !sd->login_id1) - return -1; +int chrif_charselectreq(struct map_session_data* sd, uint32 s_ip) { + nullpo_retr(-1, sd); - chrif_check(-1); + if( !sd || !sd->bl.id || !sd->login_id1 ) + return -1; + + chrif_check(-1); - WFIFOHEAD(char_fd,18); - WFIFOW(char_fd, 0) = 0x2b02; - WFIFOL(char_fd, 2) = sd->bl.id; - WFIFOL(char_fd, 6) = sd->login_id1; - WFIFOL(char_fd,10) = sd->login_id2; - WFIFOL(char_fd,14) = htonl(s_ip); - WFIFOSET(char_fd,18); + WFIFOHEAD(char_fd,18); + WFIFOW(char_fd, 0) = 0x2b02; + WFIFOL(char_fd, 2) = sd->bl.id; + WFIFOL(char_fd, 6) = sd->login_id1; + WFIFOL(char_fd,10) = sd->login_id2; + WFIFOL(char_fd,14) = htonl(s_ip); + WFIFOSET(char_fd,18); - return 0; + return 0; } /*========================================== * Search Char trough id on char serv *------------------------------------------*/ -int chrif_searchcharid(int char_id) -{ - - if (!char_id) - return -1; - - chrif_check(-1); +int chrif_searchcharid(int char_id) { + + if( !char_id ) + return -1; + + chrif_check(-1); - WFIFOHEAD(char_fd,6); - WFIFOW(char_fd,0) = 0x2b08; - WFIFOL(char_fd,2) = char_id; - WFIFOSET(char_fd,6); + WFIFOHEAD(char_fd,6); + WFIFOW(char_fd,0) = 0x2b08; + WFIFOL(char_fd,2) = char_id; + WFIFOSET(char_fd,6); - return 0; + return 0; } /*========================================== * 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) + ShowInfo("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n", id, actual_email, new_email); - if (battle_config.etc_log) - ShowInfo("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n", id, actual_email, new_email); + chrif_check(-1); - chrif_check(-1); + WFIFOHEAD(char_fd,86); + WFIFOW(char_fd,0) = 0x2b0c; + WFIFOL(char_fd,2) = id; + memcpy(WFIFOP(char_fd,6), actual_email, 40); + memcpy(WFIFOP(char_fd,46), new_email, 40); + WFIFOSET(char_fd,86); - WFIFOHEAD(char_fd,86); - WFIFOW(char_fd,0) = 0x2b0c; - WFIFOL(char_fd,2) = id; - memcpy(WFIFOP(char_fd,6), actual_email, 40); - memcpy(WFIFOP(char_fd,46), new_email, 40); - WFIFOSET(char_fd,86); - - return 0; + return 0; } /*========================================== @@ -810,48 +777,46 @@ int chrif_changeemail(int id, const char *actual_email, const char *new_email) * type of operation: * 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex (use next function for 5) *------------------------------------------*/ -int chrif_char_ask_name(int acc, const char *character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second) -{ - - chrif_check(-1); - - WFIFOHEAD(char_fd,44); - WFIFOW(char_fd,0) = 0x2b0e; - WFIFOL(char_fd,2) = acc; - safestrncpy((char *)WFIFOP(char_fd,6), character_name, NAME_LENGTH); - WFIFOW(char_fd,30) = operation_type; - - if (operation_type == 2) { - WFIFOW(char_fd,32) = year; - WFIFOW(char_fd,34) = month; - WFIFOW(char_fd,36) = day; - WFIFOW(char_fd,38) = hour; - WFIFOW(char_fd,40) = minute; - WFIFOW(char_fd,42) = second; - } - - WFIFOSET(char_fd,44); - return 0; -} - -int chrif_changesex(struct map_session_data *sd) -{ - chrif_check(-1); - - WFIFOHEAD(char_fd,44); - WFIFOW(char_fd,0) = 0x2b0e; - WFIFOL(char_fd,2) = sd->status.account_id; - safestrncpy((char *)WFIFOP(char_fd,6), sd->status.name, NAME_LENGTH); - WFIFOW(char_fd,30) = 5; - WFIFOSET(char_fd,44); - - clif_displaymessage(sd->fd, msg_txt(408)); //"Need disconnection to perform change-sex request..." - - if (sd->fd) - clif_authfail_fd(sd->fd, 15); - else - map_quit(sd); - return 0; +int chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second) { + + chrif_check(-1); + + WFIFOHEAD(char_fd,44); + WFIFOW(char_fd,0) = 0x2b0e; + WFIFOL(char_fd,2) = acc; + safestrncpy((char*)WFIFOP(char_fd,6), character_name, NAME_LENGTH); + WFIFOW(char_fd,30) = operation_type; + + if ( operation_type == 2 ) { + WFIFOW(char_fd,32) = year; + WFIFOW(char_fd,34) = month; + WFIFOW(char_fd,36) = day; + WFIFOW(char_fd,38) = hour; + WFIFOW(char_fd,40) = minute; + WFIFOW(char_fd,42) = second; + } + + WFIFOSET(char_fd,44); + return 0; +} + +int chrif_changesex(struct map_session_data *sd) { + chrif_check(-1); + + WFIFOHEAD(char_fd,44); + WFIFOW(char_fd,0) = 0x2b0e; + WFIFOL(char_fd,2) = sd->status.account_id; + safestrncpy((char*)WFIFOP(char_fd,6), sd->status.name, NAME_LENGTH); + WFIFOW(char_fd,30) = 5; + WFIFOSET(char_fd,44); + + clif_displaymessage(sd->fd, msg_txt(408)); //"Need disconnection to perform change-sex request..." + + if (sd->fd) + clif_authfail_fd(sd->fd, 15); + else + map_quit(sd); + return 0; } /*========================================== @@ -865,844 +830,737 @@ int chrif_changesex(struct map_session_data *sd) * 2: gm level too low * 3: login-server offline *------------------------------------------*/ -static void chrif_char_ask_name_answer(int acc, const char *player_name, uint16 type, uint16 answer) -{ - struct map_session_data *sd; - char action[25]; - char output[256]; - - sd = map_id2sd(acc); - - if (acc < 0 || sd == NULL) { - ShowError("chrif_char_ask_name_answer failed - player not online.\n"); - return; - } - - if (type > 0 && type <= 5) - snprintf(action,25,"%s",msg_txt(427+type)); //block|ban|unblock|unban|change the sex of - else - snprintf(action,25,"???"); - - switch (answer) { - case 0 : - sprintf(output, msg_txt(424), action, NAME_LENGTH, player_name); - break; - case 1 : - sprintf(output, msg_txt(425), NAME_LENGTH, player_name); - break; - case 2 : - sprintf(output, msg_txt(426), action, NAME_LENGTH, player_name); - break; - case 3 : - sprintf(output, msg_txt(427), action, NAME_LENGTH, player_name); - break; - default: - output[0] = '\0'; - break; - } - - clif_displaymessage(sd->fd, output); +static void chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, uint16 answer) { + struct map_session_data* sd; + char action[25]; + char output[256]; + + sd = map_id2sd(acc); + + if( acc < 0 || sd == NULL ) { + ShowError("chrif_char_ask_name_answer failed - player not online.\n"); + return; + } + + if( type > 0 && type <= 5 ) + snprintf(action,25,"%s",msg_txt(427+type)); //block|ban|unblock|unban|change the sex of + else + snprintf(action,25,"???"); + + switch( answer ) { + case 0 : sprintf(output, msg_txt(424), action, NAME_LENGTH, player_name); break; + case 1 : sprintf(output, msg_txt(425), NAME_LENGTH, player_name); break; + case 2 : sprintf(output, msg_txt(426), action, NAME_LENGTH, player_name); break; + case 3 : sprintf(output, msg_txt(427), action, NAME_LENGTH, player_name); break; + default: output[0] = '\0'; break; + } + + clif_displaymessage(sd->fd, output); } /*========================================== * Request char server to change sex of char (modified by Yor) *------------------------------------------*/ -int chrif_changedsex(int fd) -{ - int acc, sex, i; - struct map_session_data *sd; - - acc = RFIFOL(fd,2); - sex = RFIFOL(fd,6); - - if (battle_config.etc_log) - ShowNotice("chrif_changedsex %d.\n", acc); - - sd = map_id2sd(acc); - if (sd) { //Normally there should not be a char logged on right now! - if (sd->status.sex == sex) - return 0; //Do nothing? Likely safe. - sd->status.sex = !sd->status.sex; - - // reset skill of some job - if ((sd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER) { - // remove specifical skills of Bard classes - for (i = 315; i <= 322; i++) { - if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) { - sd->status.skill_point += sd->status.skill[i].lv; - sd->status.skill[i].id = 0; - sd->status.skill[i].lv = 0; - } - } - // remove specifical skills of Dancer classes - for (i = 323; i <= 330; i++) { - if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) { - sd->status.skill_point += sd->status.skill[i].lv; - sd->status.skill[i].id = 0; - sd->status.skill[i].lv = 0; - } - } - clif_updatestatus(sd, SP_SKILLPOINT); - // change job if necessary - if (sd->status.sex) //Changed from Dancer - sd->status.class_ -= 1; - else //Changed from Bard - sd->status.class_ += 1; - //sd->class_ needs not be updated as both Dancer/Bard are the same. - } - // save character - 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, msg_txt(409)); //"Your sex has been changed (need disconnection by the server)..." - set_eof(sd->fd); // forced to disconnect for the change - map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X] - } - return 0; +int chrif_changedsex(int fd) { + int acc, sex, i; + struct map_session_data *sd; + + acc = RFIFOL(fd,2); + sex = RFIFOL(fd,6); + + if ( battle_config.etc_log ) + ShowNotice("chrif_changedsex %d.\n", acc); + + sd = map_id2sd(acc); + if ( sd ) { //Normally there should not be a char logged on right now! + if ( sd->status.sex == sex ) + return 0; //Do nothing? Likely safe. + sd->status.sex = !sd->status.sex; + + // reset skill of some job + if ((sd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER) { + // remove specifical skills of Bard classes + for(i = 315; i <= 322; i++) { + if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) { + sd->status.skill_point += sd->status.skill[i].lv; + sd->status.skill[i].id = 0; + sd->status.skill[i].lv = 0; + } + } + // remove specifical skills of Dancer classes + for(i = 323; i <= 330; i++) { + if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) { + sd->status.skill_point += sd->status.skill[i].lv; + sd->status.skill[i].id = 0; + sd->status.skill[i].lv = 0; + } + } + clif_updatestatus(sd, SP_SKILLPOINT); + // change job if necessary + if (sd->status.sex) //Changed from Dancer + sd->status.class_ -= 1; + else //Changed from Bard + sd->status.class_ += 1; + //sd->class_ needs not be updated as both Dancer/Bard are the same. + } + // save character + 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, msg_txt(409)); //"Your sex has been changed (need disconnection by the server)..." + set_eof(sd->fd); // forced to disconnect for the change + map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X] + } + return 0; } /*========================================== * Request Char Server to Divorce Players *------------------------------------------*/ -int chrif_divorce(int partner_id1, int partner_id2) -{ - chrif_check(-1); +int chrif_divorce(int partner_id1, int partner_id2) { + chrif_check(-1); - WFIFOHEAD(char_fd,10); - WFIFOW(char_fd,0) = 0x2b11; - WFIFOL(char_fd,2) = partner_id1; - WFIFOL(char_fd,6) = partner_id2; - WFIFOSET(char_fd,10); + WFIFOHEAD(char_fd,10); + WFIFOW(char_fd,0) = 0x2b11; + WFIFOL(char_fd,2) = partner_id1; + WFIFOL(char_fd,6) = partner_id2; + WFIFOSET(char_fd,10); - return 0; + return 0; } /*========================================== * Divorce players * only used if 'partner_id' is offline *------------------------------------------*/ -int chrif_divorceack(int char_id, int partner_id) -{ - struct map_session_data *sd; - int i; - - if (!char_id || !partner_id) - return 0; - - if ((sd = map_charid2sd(char_id)) != NULL && sd->status.partner_id == partner_id) { - sd->status.partner_id = 0; - for (i = 0; i < MAX_INVENTORY; i++) - if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) - pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); - } - - if ((sd = map_charid2sd(partner_id)) != NULL && sd->status.partner_id == char_id) { - sd->status.partner_id = 0; - for (i = 0; i < MAX_INVENTORY; i++) - if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) - pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); - } - - return 0; +int chrif_divorceack(int char_id, int partner_id) { + struct map_session_data* sd; + int i; + + if( !char_id || !partner_id ) + return 0; + + if( ( sd = map_charid2sd(char_id) ) != NULL && sd->status.partner_id == partner_id ) { + sd->status.partner_id = 0; + for(i = 0; i < MAX_INVENTORY; i++) + if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) + pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); + } + + if( ( sd = map_charid2sd(partner_id) ) != NULL && sd->status.partner_id == char_id ) { + sd->status.partner_id = 0; + for(i = 0; i < MAX_INVENTORY; i++) + if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) + pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); + } + + return 0; } /*========================================== * Removes Baby from parents *------------------------------------------*/ -int chrif_deadopt(int father_id, int mother_id, int child_id) -{ - struct map_session_data *sd; +int chrif_deadopt(int father_id, int mother_id, int child_id) { + struct map_session_data* sd; - if (father_id && (sd = map_charid2sd(father_id)) != NULL && sd->status.child == child_id) { - sd->status.child = 0; - sd->status.skill[WE_CALLBABY].id = 0; - sd->status.skill[WE_CALLBABY].lv = 0; - sd->status.skill[WE_CALLBABY].flag = 0; - clif_deleteskill(sd,WE_CALLBABY); - } + if( father_id && ( sd = map_charid2sd(father_id) ) != NULL && sd->status.child == child_id ) { + sd->status.child = 0; + sd->status.skill[WE_CALLBABY].id = 0; + sd->status.skill[WE_CALLBABY].lv = 0; + sd->status.skill[WE_CALLBABY].flag = 0; + clif_deleteskill(sd,WE_CALLBABY); + } - if (mother_id && (sd = map_charid2sd(mother_id)) != NULL && sd->status.child == child_id) { - sd->status.child = 0; - sd->status.skill[WE_CALLBABY].id = 0; - sd->status.skill[WE_CALLBABY].lv = 0; - sd->status.skill[WE_CALLBABY].flag = 0; - clif_deleteskill(sd,WE_CALLBABY); - } + if( mother_id && ( sd = map_charid2sd(mother_id) ) != NULL && sd->status.child == child_id ) { + sd->status.child = 0; + sd->status.skill[WE_CALLBABY].id = 0; + sd->status.skill[WE_CALLBABY].lv = 0; + sd->status.skill[WE_CALLBABY].flag = 0; + clif_deleteskill(sd,WE_CALLBABY); + } - return 0; + return 0; } /*========================================== * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor] *------------------------------------------*/ -int chrif_accountban(int fd) -{ - int acc; - struct map_session_data *sd; - - acc = RFIFOL(fd,2); - - if (battle_config.etc_log) - ShowNotice("chrif_accountban %d.\n", acc); - - sd = map_id2sd(acc); - - if (acc < 0 || sd == NULL) { - ShowError("chrif_accountban failed - player not online.\n"); - return 0; - } - - sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters - if (RFIFOB(fd,6) == 0) { // 0: change of statut, 1: ban - int ret_status = RFIFOL(fd,7); // status or final date of a banishment - if (0<ret_status && ret_status<=9) - clif_displaymessage(sd->fd, msg_txt(411+ret_status)); - else if (ret_status==100) - clif_displaymessage(sd->fd, msg_txt(421)); - else - clif_displaymessage(sd->fd, msg_txt(420)); //"Your account has not more authorised." - } else if (RFIFOB(fd,6) == 1) { // 0: change of statut, 1: ban - time_t timestamp; - char tmpstr[2048]; - timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment - strcpy(tmpstr, msg_txt(423)); //"Your account has been banished until " - strftime(tmpstr + strlen(tmpstr), 24, "%d-%m-%Y %H:%M:%S", localtime(×tamp)); - clif_displaymessage(sd->fd, tmpstr); - } - - set_eof(sd->fd); // forced to disconnect for the change - map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X] - return 0; +int chrif_accountban(int fd) { + int acc; + struct map_session_data *sd; + + acc = RFIFOL(fd,2); + + if ( battle_config.etc_log ) + ShowNotice("chrif_accountban %d.\n", acc); + + sd = map_id2sd(acc); + + if ( acc < 0 || sd == NULL ) { + ShowError("chrif_accountban failed - player not online.\n"); + return 0; + } + + sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters + if (RFIFOB(fd,6) == 0) { // 0: change of statut, 1: ban + int ret_status = RFIFOL(fd,7); // status or final date of a banishment + if(0<ret_status && ret_status<=9) + clif_displaymessage(sd->fd, msg_txt(411+ret_status)); + else if(ret_status==100) + clif_displaymessage(sd->fd, msg_txt(421)); + else + clif_displaymessage(sd->fd, msg_txt(420)); //"Your account has not more authorised." + } else if (RFIFOB(fd,6) == 1) { // 0: change of statut, 1: ban + time_t timestamp; + char tmpstr[2048]; + timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment + strcpy(tmpstr, msg_txt(423)); //"Your account has been banished until " + strftime(tmpstr + strlen(tmpstr), 24, "%d-%m-%Y %H:%M:%S", localtime(×tamp)); + clif_displaymessage(sd->fd, tmpstr); + } + + set_eof(sd->fd); // forced to disconnect for the change + map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X] + return 0; } //Disconnect the player out of the game, simple packet //packet.w AID.L WHY.B 2+4+1 = 7byte -int chrif_disconnectplayer(int fd) -{ - struct map_session_data *sd; - int account_id = RFIFOL(fd, 2); - - sd = map_id2sd(account_id); - if (sd == NULL) { - struct auth_node *auth = chrif_search(account_id); - - if (auth != NULL && chrif_auth_delete(account_id, auth->char_id, ST_LOGIN)) - return 0; - - return -1; - } - - if (!sd->fd) { //No connection - if (sd->state.autotrade) - map_quit(sd); //Remove it. - //Else we don't remove it because the char should have a timer to remove the player because it force-quit before, - //and we don't want them kicking their previous instance before the 10 secs penalty time passes. [Skotlex] - return 0; - } - - switch (RFIFOB(fd, 6)) { - case 1: - clif_authfail_fd(sd->fd, 1); - break; //server closed - case 2: - clif_authfail_fd(sd->fd, 2); - break; //someone else logged in - case 3: - clif_authfail_fd(sd->fd, 4); - break; //server overpopulated - case 4: - clif_authfail_fd(sd->fd, 10); - break; //out of available time paid for - case 5: - clif_authfail_fd(sd->fd, 15); - break; //forced to dc by gm - } - return 0; +int chrif_disconnectplayer(int fd) { + struct map_session_data* sd; + int account_id = RFIFOL(fd, 2); + + sd = map_id2sd(account_id); + if( sd == NULL ) { + struct auth_node* auth = chrif_search(account_id); + + if( auth != NULL && chrif_auth_delete(account_id, auth->char_id, ST_LOGIN) ) + return 0; + + return -1; + } + + if (!sd->fd) { //No connection + if (sd->state.autotrade) + map_quit(sd); //Remove it. + //Else we don't remove it because the char should have a timer to remove the player because it force-quit before, + //and we don't want them kicking their previous instance before the 10 secs penalty time passes. [Skotlex] + return 0; + } + + switch(RFIFOB(fd, 6)) { + case 1: clif_authfail_fd(sd->fd, 1); break; //server closed + case 2: clif_authfail_fd(sd->fd, 2); break; //someone else logged in + case 3: clif_authfail_fd(sd->fd, 4); break; //server overpopulated + case 4: clif_authfail_fd(sd->fd, 10); break; //out of available time paid for + case 5: clif_authfail_fd(sd->fd, 15); break; //forced to dc by gm + } + return 0; } /*========================================== * Request/Receive top 10 Fame character list *------------------------------------------*/ -int chrif_updatefamelist(struct map_session_data *sd) -{ - char type; - - chrif_check(-1); - - switch (sd->class_ & MAPID_UPPERMASK) { - case MAPID_BLACKSMITH: - type = 1; - break; - case MAPID_ALCHEMIST: - type = 2; - break; - case MAPID_TAEKWON: - type = 3; - break; - default: - return 0; - } - - WFIFOHEAD(char_fd, 11); - WFIFOW(char_fd,0) = 0x2b10; - WFIFOL(char_fd,2) = sd->status.char_id; - WFIFOL(char_fd,6) = sd->status.fame; - WFIFOB(char_fd,10) = type; - WFIFOSET(char_fd,11); - - return 0; -} - -int chrif_buildfamelist(void) -{ - chrif_check(-1); - - WFIFOHEAD(char_fd,2); - WFIFOW(char_fd,0) = 0x2b1a; - WFIFOSET(char_fd,2); - - return 0; -} - -int chrif_recvfamelist(int fd) -{ - int num, size; - int total = 0, len = 8; - - memset(smith_fame_list, 0, sizeof(smith_fame_list)); - memset(chemist_fame_list, 0, sizeof(chemist_fame_list)); - memset(taekwon_fame_list, 0, sizeof(taekwon_fame_list)); - - size = RFIFOW(fd, 6); //Blacksmith block size - - for (num = 0; len < size && num < MAX_FAME_LIST; num++) { - memcpy(&smith_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list)); - len += sizeof(struct fame_list); - } - - total += num; - - size = RFIFOW(fd, 4); //Alchemist block size - - for (num = 0; len < size && num < MAX_FAME_LIST; num++) { - memcpy(&chemist_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list)); - len += sizeof(struct fame_list); - } - - total += num; - - size = RFIFOW(fd, 2); //Total packet length - - for (num = 0; len < size && num < MAX_FAME_LIST; num++) { - memcpy(&taekwon_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list)); - len += sizeof(struct fame_list); - } - - total += num; - - ShowInfo("Received Fame List of '"CL_WHITE"%d"CL_RESET"' characters.\n", total); - - return 0; +int chrif_updatefamelist(struct map_session_data* sd) { + char type; + + chrif_check(-1); + + switch(sd->class_ & MAPID_UPPERMASK) { + case MAPID_BLACKSMITH: type = 1; break; + case MAPID_ALCHEMIST: type = 2; break; + case MAPID_TAEKWON: type = 3; break; + default: + return 0; + } + + WFIFOHEAD(char_fd, 11); + WFIFOW(char_fd,0) = 0x2b10; + WFIFOL(char_fd,2) = sd->status.char_id; + WFIFOL(char_fd,6) = sd->status.fame; + WFIFOB(char_fd,10) = type; + WFIFOSET(char_fd,11); + + return 0; +} + +int chrif_buildfamelist(void) { + chrif_check(-1); + + WFIFOHEAD(char_fd,2); + WFIFOW(char_fd,0) = 0x2b1a; + WFIFOSET(char_fd,2); + + return 0; +} + +int chrif_recvfamelist(int fd) { + int num, size; + int total = 0, len = 8; + + memset (smith_fame_list, 0, sizeof(smith_fame_list)); + memset (chemist_fame_list, 0, sizeof(chemist_fame_list)); + memset (taekwon_fame_list, 0, sizeof(taekwon_fame_list)); + + size = RFIFOW(fd, 6); //Blacksmith block size + + for (num = 0; len < size && num < MAX_FAME_LIST; num++) { + memcpy(&smith_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list)); + len += sizeof(struct fame_list); + } + + total += num; + + size = RFIFOW(fd, 4); //Alchemist block size + + for (num = 0; len < size && num < MAX_FAME_LIST; num++) { + memcpy(&chemist_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list)); + len += sizeof(struct fame_list); + } + + total += num; + + size = RFIFOW(fd, 2); //Total packet length + + for (num = 0; len < size && num < MAX_FAME_LIST; num++) { + memcpy(&taekwon_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list)); + len += sizeof(struct fame_list); + } + + total += num; + + ShowInfo("Received Fame List of '"CL_WHITE"%d"CL_RESET"' characters.\n", total); + + return 0; } /// fame ranking update confirmation /// R 2b22 <table>.B <index>.B <value>.L -int chrif_updatefamelist_ack(int fd) -{ - struct fame_list *list; - uint8 index; - - switch (RFIFOB(fd,2)) { - case 1: - list = smith_fame_list; - break; - case 2: - list = chemist_fame_list; - break; - case 3: - list = taekwon_fame_list; - break; - default: - return 0; - } - - index = RFIFOB(fd, 3); - - if (index >= MAX_FAME_LIST) - return 0; - - list[index].fame = RFIFOL(fd,4); - - return 1; -} - -int chrif_save_scdata(struct map_session_data *sd) //parses the sc_data of the player and sends it to the char-server for saving. [Skotlex] -{ +int chrif_updatefamelist_ack(int fd) { + struct fame_list* list; + uint8 index; + + switch (RFIFOB(fd,2)) { + case 1: list = smith_fame_list; break; + case 2: list = chemist_fame_list; break; + case 3: list = taekwon_fame_list; break; + default: return 0; + } + + index = RFIFOB(fd, 3); + + if (index >= MAX_FAME_LIST) + return 0; + + list[index].fame = RFIFOL(fd,4); + + return 1; +} + +int chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the player and sends it to the char-server for saving. [Skotlex] #ifdef ENABLE_SC_SAVING - int i, count=0; - unsigned int tick; - struct status_change_data data; - struct status_change *sc = &sd->sc; - const struct TimerData *timer; - - chrif_check(-1); - tick = gettick(); - - WFIFOHEAD(char_fd, 14 + SC_MAX*sizeof(struct status_change_data)); - WFIFOW(char_fd,0) = 0x2b1c; - WFIFOL(char_fd,4) = sd->status.account_id; - WFIFOL(char_fd,8) = sd->status.char_id; - - for (i = 0; i < SC_MAX; i++) { - if (!sc->data[i]) - continue; - if (sc->data[i]->timer != INVALID_TIMER) { - timer = get_timer(sc->data[i]->timer); - if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0) - continue; - data.tick = DIFF_TICK(timer->tick,tick); //Duration that is left before ending. - } else - data.tick = -1; //Infinite duration - data.type = i; - data.val1 = sc->data[i]->val1; - data.val2 = sc->data[i]->val2; - data.val3 = sc->data[i]->val3; - data.val4 = sc->data[i]->val4; - memcpy(WFIFOP(char_fd,14 +count*sizeof(struct status_change_data)), - &data, sizeof(struct status_change_data)); - count++; - } - - if (count == 0) - return 0; //Nothing to save. - - WFIFOW(char_fd,12) = count; - WFIFOW(char_fd,2) = 14 +count*sizeof(struct status_change_data); //Total packet size - WFIFOSET(char_fd,WFIFOW(char_fd,2)); + int i, count=0; + unsigned int tick; + struct status_change_data data; + struct status_change *sc = &sd->sc; + const struct TimerData *timer; + + chrif_check(-1); + tick = gettick(); + + WFIFOHEAD(char_fd, 14 + SC_MAX*sizeof(struct status_change_data)); + WFIFOW(char_fd,0) = 0x2b1c; + WFIFOL(char_fd,4) = sd->status.account_id; + WFIFOL(char_fd,8) = sd->status.char_id; + + for (i = 0; i < SC_MAX; i++) { + if (!sc->data[i]) + continue; + if (sc->data[i]->timer != INVALID_TIMER) { + timer = get_timer(sc->data[i]->timer); + if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0) + continue; + data.tick = DIFF_TICK(timer->tick,tick); //Duration that is left before ending. + } else + data.tick = -1; //Infinite duration + data.type = i; + data.val1 = sc->data[i]->val1; + data.val2 = sc->data[i]->val2; + data.val3 = sc->data[i]->val3; + data.val4 = sc->data[i]->val4; + memcpy(WFIFOP(char_fd,14 +count*sizeof(struct status_change_data)), + &data, sizeof(struct status_change_data)); + count++; + } + + if (count == 0) + return 0; //Nothing to save. + + WFIFOW(char_fd,12) = count; + WFIFOW(char_fd,2) = 14 +count*sizeof(struct status_change_data); //Total packet size + WFIFOSET(char_fd,WFIFOW(char_fd,2)); #endif - - return 0; + + return 0; } //Retrieve and load sc_data for a player. [Skotlex] -int chrif_load_scdata(int fd) -{ +int chrif_load_scdata(int fd) { #ifdef ENABLE_SC_SAVING - struct map_session_data *sd; - struct status_change_data *data; - int aid, cid, i, count; - - aid = RFIFOL(fd,4); //Player Account ID - cid = RFIFOL(fd,8); //Player Char ID - - sd = map_id2sd(aid); - - if (!sd) { - ShowError("chrif_load_scdata: Player of AID %d not found!\n", aid); - return -1; - } - - if (sd->status.char_id != cid) { - ShowError("chrif_load_scdata: Receiving data for account %d, char id does not matches (%d != %d)!\n", aid, sd->status.char_id, cid); - return -1; - } - - count = RFIFOW(fd,12); //sc_count - - for (i = 0; i < count; i++) { - data = (struct status_change_data *)RFIFOP(fd,14 + i*sizeof(struct status_change_data)); - status_change_start(&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15); - } + struct map_session_data *sd; + struct status_change_data *data; + int aid, cid, i, count; + + aid = RFIFOL(fd,4); //Player Account ID + cid = RFIFOL(fd,8); //Player Char ID + + sd = map_id2sd(aid); + + if ( !sd ) { + ShowError("chrif_load_scdata: Player of AID %d not found!\n", aid); + return -1; + } + + if ( sd->status.char_id != cid ) { + ShowError("chrif_load_scdata: Receiving data for account %d, char id does not matches (%d != %d)!\n", aid, sd->status.char_id, cid); + return -1; + } + + count = RFIFOW(fd,12); //sc_count + + for (i = 0; i < count; i++) { + data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data)); + status_change_start(&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15); + } #endif - - return 0; + + return 0; } /*========================================== * Send rates and motd to char server [Wizputer] * S 2b16 <base rate>.L <job rate>.L <drop rate>.L *------------------------------------------*/ -int chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) -{ - chrif_check(-1); - - WFIFOHEAD(char_fd,14); - WFIFOW(char_fd,0) = 0x2b16; - WFIFOL(char_fd,2) = base_rate; - WFIFOL(char_fd,6) = job_rate; - WFIFOL(char_fd,10) = drop_rate; - WFIFOSET(char_fd,14); +int chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) { + chrif_check(-1); - return 0; + WFIFOHEAD(char_fd,14); + WFIFOW(char_fd,0) = 0x2b16; + WFIFOL(char_fd,2) = base_rate; + WFIFOL(char_fd,6) = job_rate; + WFIFOL(char_fd,10) = drop_rate; + WFIFOSET(char_fd,14); + + return 0; } /*========================================= * Tell char-server charcter disconnected [Wizputer] *-----------------------------------------*/ -int chrif_char_offline(struct map_session_data *sd) -{ - chrif_check(-1); +int chrif_char_offline(struct map_session_data *sd) { + chrif_check(-1); - WFIFOHEAD(char_fd,10); - WFIFOW(char_fd,0) = 0x2b17; - WFIFOL(char_fd,2) = sd->status.char_id; - WFIFOL(char_fd,6) = sd->status.account_id; - WFIFOSET(char_fd,10); + WFIFOHEAD(char_fd,10); + WFIFOW(char_fd,0) = 0x2b17; + WFIFOL(char_fd,2) = sd->status.char_id; + WFIFOL(char_fd,6) = sd->status.account_id; + WFIFOSET(char_fd,10); - return 0; + return 0; } -int chrif_char_offline_nsd(int account_id, int char_id) -{ - chrif_check(-1); +int chrif_char_offline_nsd(int account_id, int char_id) { + chrif_check(-1); - WFIFOHEAD(char_fd,10); - WFIFOW(char_fd,0) = 0x2b17; - WFIFOL(char_fd,2) = char_id; - WFIFOL(char_fd,6) = account_id; - WFIFOSET(char_fd,10); + WFIFOHEAD(char_fd,10); + WFIFOW(char_fd,0) = 0x2b17; + WFIFOL(char_fd,2) = char_id; + WFIFOL(char_fd,6) = account_id; + WFIFOSET(char_fd,10); - return 0; + return 0; } /*========================================= * Tell char-server to reset all chars offline [Wizputer] *-----------------------------------------*/ -int chrif_flush_fifo(void) -{ - chrif_check(-1); +int chrif_flush_fifo(void) { + chrif_check(-1); - set_nonblocking(char_fd, 0); - flush_fifos(); - set_nonblocking(char_fd, 1); + set_nonblocking(char_fd, 0); + flush_fifos(); + set_nonblocking(char_fd, 1); - return 0; + return 0; } /*========================================= * Tell char-server to reset all chars offline [Wizputer] *-----------------------------------------*/ -int chrif_char_reset_offline(void) -{ - chrif_check(-1); +int chrif_char_reset_offline(void) { + chrif_check(-1); - WFIFOHEAD(char_fd,2); - WFIFOW(char_fd,0) = 0x2b18; - WFIFOSET(char_fd,2); + WFIFOHEAD(char_fd,2); + WFIFOW(char_fd,0) = 0x2b18; + WFIFOSET(char_fd,2); - return 0; + return 0; } /*========================================= * Tell char-server charcter is online [Wizputer] *-----------------------------------------*/ -int chrif_char_online(struct map_session_data *sd) -{ - chrif_check(-1); +int chrif_char_online(struct map_session_data *sd) { + chrif_check(-1); - WFIFOHEAD(char_fd,10); - 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); + WFIFOHEAD(char_fd,10); + 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; + return 0; } /// Called when the connection to Char Server is disconnected. -void chrif_on_disconnect(void) -{ - if (chrif_connected != 1) - ShowWarning("Connection to Char Server lost.\n\n"); - chrif_connected = 0; - - other_mapserver_count = 0; //Reset counter. We receive ALL maps from all map-servers on reconnect. - map_eraseallipport(); - - //Attempt to reconnect in a second. [Skotlex] - add_timer(gettick() + 1000, check_connect_char_server, 0, 0); -} - - -void chrif_update_ip(int fd) -{ - uint32 new_ip; - - WFIFOHEAD(fd,6); - - new_ip = host2ip(char_ip_str); - - if (new_ip && new_ip != char_ip) - char_ip = new_ip; //Update char_ip - - new_ip = clif_refresh_ip(); - - if (!new_ip) - return; //No change - - WFIFOW(fd,0) = 0x2736; - WFIFOL(fd,2) = htonl(new_ip); - WFIFOSET(fd,6); +void chrif_on_disconnect(void) { + if( chrif_connected != 1 ) + ShowWarning("Connection to Char Server lost.\n\n"); + chrif_connected = 0; + + other_mapserver_count = 0; //Reset counter. We receive ALL maps from all map-servers on reconnect. + map_eraseallipport(); + + //Attempt to reconnect in a second. [Skotlex] + add_timer(gettick() + 1000, check_connect_char_server, 0, 0); +} + + +void chrif_update_ip(int fd) { + uint32 new_ip; + + WFIFOHEAD(fd,6); + + new_ip = host2ip(char_ip_str); + + if (new_ip && new_ip != char_ip) + char_ip = new_ip; //Update char_ip + + new_ip = clif_refresh_ip(); + + if (!new_ip) + return; //No change + + WFIFOW(fd,0) = 0x2736; + WFIFOL(fd,2) = htonl(new_ip); + WFIFOSET(fd,6); } // pings the charserver -void chrif_keepalive(int fd) -{ - WFIFOHEAD(fd,2); - WFIFOW(fd,0) = 0x2b23; - WFIFOSET(fd,2); +void chrif_keepalive(int fd) { + WFIFOHEAD(fd,2); + WFIFOW(fd,0) = 0x2b23; + WFIFOSET(fd,2); } -void chrif_keepalive_ack(int fd) -{ - session[fd]->flag.ping = 0;/* reset ping state, we received a packet */ +void chrif_keepalive_ack(int fd) { + session[fd]->flag.ping = 0;/* reset ping state, we received a packet */ } /*========================================== * *------------------------------------------*/ -int chrif_parse(int fd) -{ - int packet_len, cmd; - - // only process data from the char-server - if (fd != char_fd) { - ShowDebug("chrif_parse: Disconnecting invalid session #%d (is not the char-server)\n", fd); - do_close(fd); - return 0; - } - - if (session[fd]->flag.eof) { - do_close(fd); - char_fd = -1; - chrif_on_disconnect(); - return 0; - } else if (session[fd]->flag.ping) { /* we've reached stall time */ - if (DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2)) { /* we can't wait any longer */ - set_eof(fd); - return 0; - } else if (session[fd]->flag.ping != 2) { /* we haven't sent ping out yet */ - chrif_keepalive(fd); - session[fd]->flag.ping = 2; - } - } - - while (RFIFOREST(fd) >= 2) { - cmd = RFIFOW(fd,0); - if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) { - int r = intif_parse(fd); // Passed on to the intif - - if (r == 1) continue; // Treated in intif - if (r == 2) return 0; // Didn't have enough data (len==-1) - - ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd); - set_eof(fd); - return 0; - } - - if ((packet_len = packet_len_table[cmd-0x2af8]) == -1) { // dynamic-length packet, second WORD holds the length - if (RFIFOREST(fd) < 4) - return 0; - packet_len = RFIFOW(fd,2); - } - - if ((int)RFIFOREST(fd) < packet_len) - return 0; - - //ShowDebug("Received packet 0x%4x (%d bytes) from char-server (connection %d)\n", RFIFOW(fd,0), packet_len, fd); - - switch (cmd) { - case 0x2af9: - chrif_connectack(fd); - break; - case 0x2afb: - chrif_sendmapack(fd); - break; - case 0x2afd: - chrif_authok(fd); - break; - case 0x2b00: - map_setusers(RFIFOL(fd,2)); - chrif_keepalive(fd); - break; - case 0x2b03: - clif_charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); - break; - case 0x2b04: - chrif_recvmap(fd); - break; - case 0x2b06: - chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); - break; - case 0x2b09: - map_addnickdb(RFIFOL(fd,2), (char *)RFIFOP(fd,6)); - break; - case 0x2b0d: - chrif_changedsex(fd); - break; - case 0x2b0f: - chrif_char_ask_name_answer(RFIFOL(fd,2), (char *)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); - break; - case 0x2b12: - chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); - break; - case 0x2b14: - chrif_accountban(fd); - break; - case 0x2b1b: - chrif_recvfamelist(fd); - break; - case 0x2b1d: - chrif_load_scdata(fd); - break; - case 0x2b1e: - chrif_update_ip(fd); - break; - case 0x2b1f: - chrif_disconnectplayer(fd); - break; - case 0x2b20: - chrif_removemap(fd); - break; - case 0x2b21: - chrif_save_ack(fd); - break; - case 0x2b22: - chrif_updatefamelist_ack(fd); - break; - case 0x2b24: - chrif_keepalive_ack(fd); - break; - case 0x2b25: - chrif_deadopt(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); - break; - case 0x2b27: - chrif_authfail(fd); - break; - default: - ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd); - set_eof(fd); - return 0; - } - if (fd == char_fd) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex] - RFIFOSKIP(fd, packet_len); - } - - return 0; +int chrif_parse(int fd) { + int packet_len, cmd; + + // only process data from the char-server + if ( fd != char_fd ) { + ShowDebug("chrif_parse: Disconnecting invalid session #%d (is not the char-server)\n", fd); + do_close(fd); + return 0; + } + + if ( session[fd]->flag.eof ) { + do_close(fd); + char_fd = -1; + chrif_on_disconnect(); + return 0; + } else if ( session[fd]->flag.ping ) {/* we've reached stall time */ + if( DIFF_TICK(last_tick, session[fd]->rdata_tick) > (stall_time * 2) ) {/* we can't wait any longer */ + set_eof(fd); + return 0; + } else if( session[fd]->flag.ping != 2 ) { /* we haven't sent ping out yet */ + chrif_keepalive(fd); + session[fd]->flag.ping = 2; + } + } + + while ( RFIFOREST(fd) >= 2 ) { + cmd = RFIFOW(fd,0); + if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) { + int r = intif_parse(fd); // Passed on to the intif + + if (r == 1) continue; // Treated in intif + if (r == 2) return 0; // Didn't have enough data (len==-1) + + ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd); + set_eof(fd); + return 0; + } + + if ( ( packet_len = packet_len_table[cmd-0x2af8] ) == -1) { // dynamic-length packet, second WORD holds the length + if (RFIFOREST(fd) < 4) + return 0; + packet_len = RFIFOW(fd,2); + } + + if ((int)RFIFOREST(fd) < packet_len) + return 0; + + //ShowDebug("Received packet 0x%4x (%d bytes) from char-server (connection %d)\n", RFIFOW(fd,0), packet_len, fd); + + switch(cmd) { + case 0x2af9: chrif_connectack(fd); break; + case 0x2afb: chrif_sendmapack(fd); break; + case 0x2afd: chrif_authok(fd); break; + case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break; + case 0x2b03: clif_charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break; + case 0x2b04: chrif_recvmap(fd); break; + case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break; + case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; + case 0x2b0d: chrif_changedsex(fd); break; + case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break; + case 0x2b12: chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break; + case 0x2b14: chrif_accountban(fd); break; + case 0x2b1b: chrif_recvfamelist(fd); break; + case 0x2b1d: chrif_load_scdata(fd); break; + case 0x2b1e: chrif_update_ip(fd); break; + case 0x2b1f: chrif_disconnectplayer(fd); break; + case 0x2b20: chrif_removemap(fd); break; + case 0x2b21: chrif_save_ack(fd); break; + case 0x2b22: chrif_updatefamelist_ack(fd); break; + case 0x2b24: chrif_keepalive_ack(fd); break; + case 0x2b25: chrif_deadopt(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break; + case 0x2b27: chrif_authfail(fd); break; + default: + ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd); + set_eof(fd); + return 0; + } + if ( fd == char_fd ) //There's the slight chance we lost the connection during parse, in which case this would segfault if not checked [Skotlex] + RFIFOSKIP(fd, packet_len); + } + + return 0; } // unused -int send_usercount_tochar(int tid, unsigned int tick, int id, intptr_t data) -{ - chrif_check(-1); +int send_usercount_tochar(int tid, unsigned int tick, int id, intptr_t data) { + chrif_check(-1); - WFIFOHEAD(char_fd,4); - WFIFOW(char_fd,0) = 0x2afe; - WFIFOW(char_fd,2) = map_usercount(); - WFIFOSET(char_fd,4); - return 0; + WFIFOHEAD(char_fd,4); + WFIFOW(char_fd,0) = 0x2afe; + WFIFOW(char_fd,2) = map_usercount(); + WFIFOSET(char_fd,4); + return 0; } /*========================================== * timerFunction * Send to char the number of client connected to map *------------------------------------------*/ -int send_users_tochar(void) -{ - int users = 0, i = 0; - struct map_session_data *sd; - struct s_mapiterator *iter; - - chrif_check(-1); - - users = map_usercount(); - - WFIFOHEAD(char_fd, 6+8*users); - WFIFOW(char_fd,0) = 0x2aff; - - iter = mapit_getallusers(); - - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) { - WFIFOL(char_fd,6+8*i) = sd->status.account_id; - WFIFOL(char_fd,6+8*i+4) = sd->status.char_id; - i++; - } - - mapit_free(iter); - - WFIFOW(char_fd,2) = 6 + 8*users; - WFIFOW(char_fd,4) = users; - WFIFOSET(char_fd, 6+8*users); - - return 0; +int send_users_tochar(void) { + int users = 0, i = 0; + struct map_session_data* sd; + struct s_mapiterator* iter; + + chrif_check(-1); + + users = map_usercount(); + + WFIFOHEAD(char_fd, 6+8*users); + WFIFOW(char_fd,0) = 0x2aff; + + iter = mapit_getallusers(); + + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) { + WFIFOL(char_fd,6+8*i) = sd->status.account_id; + WFIFOL(char_fd,6+8*i+4) = sd->status.char_id; + i++; + } + + mapit_free(iter); + + WFIFOW(char_fd,2) = 6 + 8*users; + WFIFOW(char_fd,4) = users; + WFIFOSET(char_fd, 6+8*users); + + return 0; } /*========================================== * timerFunction * Chk the connection to char server, (if it down) *------------------------------------------*/ -static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data) -{ - static int displayed = 0; - if (char_fd <= 0 || session[char_fd] == NULL) { - 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,false); - - if (char_fd == -1)//Attempt to connect later. [Skotlex] - return 0; - - session[char_fd]->func_parse = chrif_parse; - session[char_fd]->flag.server = 1; - realloc_fifo(char_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - - chrif_connect(char_fd); - chrif_connected = (chrif_state == 2); - srvinfo = 0; - } else { - if (srvinfo == 0) { - chrif_ragsrvinfo(battle_config.base_exp_rate, battle_config.job_exp_rate, battle_config.item_rate_common); - srvinfo = 1; - } - } - if (chrif_isconnected()) - displayed = 0; - return 0; +static int check_connect_char_server(int tid, unsigned int tick, int id, intptr_t data) { + static int displayed = 0; + if ( char_fd <= 0 || session[char_fd] == NULL ) { + 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,false); + + if (char_fd == -1)//Attempt to connect later. [Skotlex] + return 0; + + session[char_fd]->func_parse = chrif_parse; + session[char_fd]->flag.server = 1; + realloc_fifo(char_fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + + chrif_connect(char_fd); + chrif_connected = (chrif_state == 2); + srvinfo = 0; + } else { + if (srvinfo == 0) { + chrif_ragsrvinfo(battle_config.base_exp_rate, battle_config.job_exp_rate, battle_config.item_rate_common); + srvinfo = 1; + } + } + if ( chrif_isconnected() ) + displayed = 0; + return 0; } /*========================================== * Asks char server to remove friend_id from the friend list of char_id *------------------------------------------*/ -int chrif_removefriend(int char_id, int friend_id) -{ - - chrif_check(-1); +int chrif_removefriend(int char_id, int friend_id) { - WFIFOHEAD(char_fd,10); - WFIFOW(char_fd,0) = 0x2b07; - WFIFOL(char_fd,2) = char_id; - WFIFOL(char_fd,6) = friend_id; - WFIFOSET(char_fd,10); + chrif_check(-1); - return 0; + WFIFOHEAD(char_fd,10); + WFIFOW(char_fd,0) = 0x2b07; + WFIFOL(char_fd,2) = char_id; + WFIFOL(char_fd,6) = friend_id; + WFIFOSET(char_fd,10); + + return 0; } -void chrif_send_report(char *buf, int len) -{ +void chrif_send_report(char* buf, int len) { #ifndef STATS_OPT_OUT - WFIFOHEAD(char_fd,len + 2); - - WFIFOW(char_fd,0) = 0x3008; - - memcpy(WFIFOP(char_fd,2), buf, len); - - WFIFOSET(char_fd,len + 2); - - flush_fifo(char_fd); /* ensure it's sent now. */ + WFIFOHEAD(char_fd,len + 2); + + WFIFOW(char_fd,0) = 0x3008; + + memcpy(WFIFOP(char_fd,2), buf, len); + + WFIFOSET(char_fd,len + 2); + + flush_fifo(char_fd); /* ensure it's sent now. */ #endif } @@ -1710,59 +1568,56 @@ void chrif_send_report(char *buf, int len) /** * @see DBApply */ -int auth_db_final(DBKey key, DBData *data, va_list ap) -{ - struct auth_node *node = db_data2ptr(data); - - if (node->char_dat) - aFree(node->char_dat); - - if (node->sd) - aFree(node->sd); - - ers_free(auth_db_ers, node); - - return 0; +int auth_db_final(DBKey key, DBData *data, va_list ap) { + struct auth_node *node = db_data2ptr(data); + + if (node->char_dat) + aFree(node->char_dat); + + if (node->sd) + aFree(node->sd); + + ers_free(auth_db_ers, node); + + return 0; } /*========================================== * Destructor *------------------------------------------*/ -int do_final_chrif(void) -{ +int do_final_chrif(void) { + + if( char_fd != -1 ) { + do_close(char_fd); + char_fd = -1; + } - if (char_fd != -1) { - do_close(char_fd); - char_fd = -1; - } - - auth_db->destroy(auth_db, auth_db_final); - - ers_destroy(auth_db_ers); - - return 0; + auth_db->destroy(auth_db, auth_db_final); + + ers_destroy(auth_db_ers); + + return 0; } /*========================================== * *------------------------------------------*/ -int do_init_chrif(void) -{ - - auth_db = idb_alloc(DB_OPT_BASE); - auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE); +int do_init_chrif(void) { + + auth_db = idb_alloc(DB_OPT_BASE); + auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE); - add_timer_func_list(check_connect_char_server, "check_connect_char_server"); - add_timer_func_list(auth_db_cleanup, "auth_db_cleanup"); + add_timer_func_list(check_connect_char_server, "check_connect_char_server"); + add_timer_func_list(auth_db_cleanup, "auth_db_cleanup"); - // establish map-char connection if not present - add_timer_interval(gettick() + 1000, check_connect_char_server, 0, 0, 10 * 1000); + // establish map-char connection if not present + add_timer_interval(gettick() + 1000, check_connect_char_server, 0, 0, 10 * 1000); - // wipe stale data for timed-out client connection requests - add_timer_interval(gettick() + 1000, auth_db_cleanup, 0, 0, 30 * 1000); + // wipe stale data for timed-out client connection requests + add_timer_interval(gettick() + 1000, auth_db_cleanup, 0, 0, 30 * 1000); - // send the user count every 10 seconds, to hide the charserver's online counting problem - add_timer_interval(gettick() + 1000, send_usercount_tochar, 0, 0, UPDATE_INTERVAL); + // send the user count every 10 seconds, to hide the charserver's online counting problem + add_timer_interval(gettick() + 1000, send_usercount_tochar, 0, 0, UPDATE_INTERVAL); - return 0; + return 0; } diff --git a/src/map/chrif.h b/src/map/chrif.h index f4dc98acd..0aadb1a7b 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -9,19 +9,19 @@ enum sd_state { ST_LOGIN, ST_LOGOUT, ST_MAPCHANGE }; struct auth_node { - int account_id, char_id; - int login_id1, login_id2, sex, fd; - time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) - struct map_session_data *sd; //Data from logged on char. - struct mmo_charstatus *char_dat; //Data from char server. - unsigned int node_created; //timestamp for node timeouts - enum sd_state state; //To track whether player was login in/out or changing maps. + int account_id, char_id; + int login_id1, login_id2, sex, fd; + time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) + struct map_session_data *sd; //Data from logged on char. + struct mmo_charstatus *char_dat; //Data from char server. + unsigned int node_created; //timestamp for node timeouts + enum sd_state state; //To track whether player was login in/out or changing maps. }; -void chrif_setuserid(char *id); -void chrif_setpasswd(char *pwd); +void chrif_setuserid(char* id); +void chrif_setpasswd(char* pwd); void chrif_checkdefaultlogin(void); -int chrif_setip(const char *ip); +int chrif_setip(const char* ip); void chrif_setport(uint16 port); int chrif_isconnected(void); @@ -30,21 +30,21 @@ void chrif_check_shutdown(void); extern int chrif_connected; extern int other_mapserver_count; -struct auth_node *chrif_search(int account_id); -struct auth_node *chrif_auth_check(int account_id, int char_id, enum sd_state state); +struct auth_node* chrif_search(int account_id); +struct auth_node* chrif_auth_check(int account_id, int char_id, enum sd_state state); bool chrif_auth_delete(int account_id, int char_id, enum sd_state state); -bool chrif_auth_finished(struct map_session_data *sd); +bool chrif_auth_finished(struct map_session_data* sd); -void chrif_authreq(struct map_session_data *sd); +void chrif_authreq(struct map_session_data* sd); void chrif_authok(int fd); int chrif_scdata_request(int account_id, int char_id); -int chrif_save(struct map_session_data *sd, int flag); -int chrif_charselectreq(struct map_session_data *sd, uint32 s_ip); -int chrif_changemapserver(struct map_session_data *sd, uint32 ip, uint16 port); +int chrif_save(struct map_session_data* sd, int flag); +int chrif_charselectreq(struct map_session_data* sd, uint32 s_ip); +int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port); int chrif_searchcharid(int char_id); int chrif_changeemail(int id, const char *actual_email, const char *new_email); -int chrif_char_ask_name(int acc, const char *character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second); +int chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second); int chrif_updatefamelist(struct map_session_data *sd); int chrif_buildfamelist(void); int chrif_save_scdata(struct map_session_data *sd); @@ -59,7 +59,7 @@ int chrif_chardisconnect(struct map_session_data *sd); int chrif_divorce(int partner_id1, int partner_id2); int chrif_removefriend(int char_id, int friend_id); -void chrif_send_report(char *buf, int len); +void chrif_send_report(char* buf, int len); int do_final_chrif(void); int do_init_chrif(void); diff --git a/src/map/clif.c b/src/map/clif.c index 362930b84..5e7c7f9bf 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -56,8 +56,8 @@ static struct eri *delay_clearunit_ers; //#define DUMP_INVALID_PACKET struct Clif_Config { - int packet_db_ver; //Preferred packet version. - int connect_cmd[MAX_PACKET_VER + 1]; //Store the connect command for all versions. [Skotlex] + int packet_db_ver; //Preferred packet version. + int connect_cmd[MAX_PACKET_VER + 1]; //Store the connect command for all versions. [Skotlex] } clif_config; struct s_packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB + 1]; @@ -65,120 +65,120 @@ struct s_packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB + 1]; //Converts item type in case of pet eggs. static inline int itemtype(int type) { - return (type == IT_PETEGG) ? IT_WEAPON : type; + return ( type == IT_PETEGG ) ? IT_WEAPON : type; } -static inline void WBUFPOS(uint8 *p, unsigned short pos, short x, short y, unsigned char dir) +static inline void WBUFPOS(uint8* p, unsigned short pos, short x, short y, unsigned char dir) { - p += pos; - p[0] = (uint8)(x>>2); - p[1] = (uint8)((x<<6) | ((y>>4)&0x3f)); - p[2] = (uint8)((y<<4) | (dir&0xf)); + p += pos; + p[0] = (uint8)(x>>2); + p[1] = (uint8)((x<<6) | ((y>>4)&0x3f)); + p[2] = (uint8)((y<<4) | (dir&0xf)); } // client-side: x0+=sx0*0.0625-0.5 and y0+=sy0*0.0625-0.5 -static inline void WBUFPOS2(uint8 *p, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) +static inline void WBUFPOS2(uint8* p, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) { - p += pos; - p[0] = (uint8)(x0>>2); - p[1] = (uint8)((x0<<6) | ((y0>>4)&0x3f)); - p[2] = (uint8)((y0<<4) | ((x1>>6)&0x0f)); - p[3] = (uint8)((x1<<2) | ((y1>>8)&0x03)); - p[4] = (uint8)y1; - p[5] = (uint8)((sx0<<4) | (sy0&0x0f)); + p += pos; + p[0] = (uint8)(x0>>2); + p[1] = (uint8)((x0<<6) | ((y0>>4)&0x3f)); + p[2] = (uint8)((y0<<4) | ((x1>>6)&0x0f)); + p[3] = (uint8)((x1<<2) | ((y1>>8)&0x03)); + p[4] = (uint8)y1; + p[5] = (uint8)((sx0<<4) | (sy0&0x0f)); } static inline void WFIFOPOS(int fd, unsigned short pos, short x, short y, unsigned char dir) { - WBUFPOS(WFIFOP(fd,pos), 0, x, y, dir); + WBUFPOS(WFIFOP(fd,pos), 0, x, y, dir); } static inline void WFIFOPOS2(int fd, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) { - WBUFPOS2(WFIFOP(fd,pos), 0, x0, y0, x1, y1, sx0, sy0); + WBUFPOS2(WFIFOP(fd,pos), 0, x0, y0, x1, y1, sx0, sy0); } -static inline void RBUFPOS(const uint8 *p, unsigned short pos, short *x, short *y, unsigned char *dir) +static inline void RBUFPOS(const uint8* p, unsigned short pos, short* x, short* y, unsigned char* dir) { - p += pos; + p += pos; - if (x) { - x[0] = ((p[0] & 0xff) << 2) | (p[1] >> 6); - } + if( x ) { + x[0] = ( ( p[0] & 0xff ) << 2 ) | ( p[1] >> 6 ); + } - if (y) { - y[0] = ((p[1] & 0x3f) << 4) | (p[2] >> 4); - } + if( y ) { + y[0] = ( ( p[1] & 0x3f ) << 4 ) | ( p[2] >> 4 ); + } - if (dir) { - dir[0] = (p[2] & 0x0f); - } + if( dir ) { + dir[0] = ( p[2] & 0x0f ); + } } -static inline void RBUFPOS2(const uint8 *p, unsigned short pos, short *x0, short *y0, short *x1, short *y1, unsigned char *sx0, unsigned char *sy0) +static inline void RBUFPOS2(const uint8* p, unsigned short pos, short* x0, short* y0, short* x1, short* y1, unsigned char* sx0, unsigned char* sy0) { - p += pos; + p += pos; - if (x0) { - x0[0] = ((p[0] & 0xff) << 2) | (p[1] >> 6); - } + if( x0 ) { + x0[0] = ( ( p[0] & 0xff ) << 2 ) | ( p[1] >> 6 ); + } - if (y0) { - y0[0] = ((p[1] & 0x3f) << 4) | (p[2] >> 4); - } + if( y0 ) { + y0[0] = ( ( p[1] & 0x3f ) << 4 ) | ( p[2] >> 4 ); + } - if (x1) { - x1[0] = ((p[2] & 0x0f) << 6) | (p[3] >> 2); - } + if( x1 ) { + x1[0] = ( ( p[2] & 0x0f ) << 6 ) | ( p[3] >> 2 ); + } - if (y1) { - y1[0] = ((p[3] & 0x03) << 8) | (p[4] >> 0); - } + if( y1 ) { + y1[0] = ( ( p[3] & 0x03 ) << 8 ) | ( p[4] >> 0 ); + } - if (sx0) { - sx0[0] = (p[5] & 0xf0) >> 4; - } + if( sx0 ) { + sx0[0] = ( p[5] & 0xf0 ) >> 4; + } - if (sy0) { - sy0[0] = (p[5] & 0x0f) >> 0; - } + if( sy0 ) { + sy0[0] = ( p[5] & 0x0f ) >> 0; + } } -static inline void RFIFOPOS(int fd, unsigned short pos, short *x, short *y, unsigned char *dir) +static inline void RFIFOPOS(int fd, unsigned short pos, short* x, short* y, unsigned char* dir) { - RBUFPOS(RFIFOP(fd,pos), 0, x, y, dir); + RBUFPOS(RFIFOP(fd,pos), 0, x, y, dir); } -static inline void RFIFOPOS2(int fd, unsigned short pos, short *x0, short *y0, short *x1, short *y1, unsigned char *sx0, unsigned char *sy0) +static inline void RFIFOPOS2(int fd, unsigned short pos, short* x0, short* y0, short* x1, short* y1, unsigned char* sx0, unsigned char* sy0) { - RBUFPOS2(WFIFOP(fd,pos), 0, x0, y0, x1, y1, sx0, sy0); + RBUFPOS2(WFIFOP(fd,pos), 0, x0, y0, x1, y1, sx0, sy0); } //To idenfity disguised characters. -static inline bool disguised(struct block_list *bl) +static inline bool disguised(struct block_list* bl) { - return (bool)(bl->type == BL_PC && ((TBL_PC *)bl)->disguise); + return (bool)( bl->type == BL_PC && ((TBL_PC*)bl)->disguise ); } //Guarantees that the given string does not exceeds the allowed size, as well as making sure it's null terminated. [Skotlex] -static inline unsigned int mes_len_check(char *mes, unsigned int len, unsigned int max) +static inline unsigned int mes_len_check(char* mes, unsigned int len, unsigned int max) { - if (len > max) - len = max; + if( len > max ) + len = max; - mes[len-1] = '\0'; + mes[len-1] = '\0'; - return len; + return len; } @@ -188,34 +188,34 @@ static uint32 bind_ip = INADDR_ANY; static uint16 map_port = 5121; int map_fd; -static int clif_parse(int fd); +static int clif_parse (int fd); /*========================================== * Ip setting of map-server *------------------------------------------*/ -int clif_setip(const char *ip) +int clif_setip(const char* ip) { - char ip_str[16]; - map_ip = host2ip(ip); - if (!map_ip) { - ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip); - return 0; - } + char ip_str[16]; + map_ip = host2ip(ip); + if (!map_ip) { + ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip); + return 0; + } - strncpy(map_ip_str, ip, sizeof(map_ip_str)); - ShowInfo("Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(map_ip, ip_str)); - return 1; + strncpy(map_ip_str, ip, sizeof(map_ip_str)); + ShowInfo("Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(map_ip, ip_str)); + return 1; } -void clif_setbindip(const char *ip) +void clif_setbindip(const char* ip) { - char ip_str[16]; - bind_ip = host2ip(ip); - if (bind_ip) { - ShowInfo("Map Server Bind IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(bind_ip, ip_str)); - } else { - ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip); - } + char ip_str[16]; + bind_ip = host2ip(ip); + if (bind_ip) { + ShowInfo("Map Server Bind IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(bind_ip, ip_str)); + } else { + ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip); + } } /*========================================== @@ -224,7 +224,7 @@ void clif_setbindip(const char *ip) *------------------------------------------*/ void clif_setport(uint16 port) { - map_port = port; + map_port = port; } /*========================================== @@ -232,21 +232,21 @@ void clif_setport(uint16 port) *------------------------------------------*/ uint32 clif_getip(void) { - return map_ip; + return map_ip; } //Refreshes map_server ip, returns the new ip if the ip changed, otherwise it returns 0. uint32 clif_refresh_ip(void) { - uint32 new_ip; + uint32 new_ip; - new_ip = host2ip(map_ip_str); - if (new_ip && new_ip != map_ip) { - map_ip = new_ip; - ShowInfo("Updating IP resolution of [%s].\n", map_ip_str); - return map_ip; - } - return 0; + new_ip = host2ip(map_ip_str); + if (new_ip && new_ip != map_ip) { + map_ip = new_ip; + ShowInfo("Updating IP resolution of [%s].\n", map_ip_str); + return map_ip; + } + return 0; } /*========================================== @@ -254,36 +254,24 @@ uint32 clif_refresh_ip(void) *------------------------------------------*/ uint16 clif_getport(void) { - return map_port; + return map_port; } #if PACKETVER >= 20071106 -static inline unsigned char clif_bl_type(struct block_list *bl) -{ - switch (bl->type) { - case BL_PC: - return disguised(bl)?0x1:0x0; //PC_TYPE - case BL_ITEM: - return 0x2; //ITEM_TYPE - case BL_SKILL: - return 0x3; //SKILL_TYPE - case BL_CHAT: - return 0x4; //UNKNOWN_TYPE - case BL_MOB: - return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE - case BL_NPC: - return 0x6; //NPC_EVT_TYPE - case BL_PET: - return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE - case BL_HOM: - return 0x8; //NPC_HOM_TYPE - case BL_MER: - return 0x9; //NPC_MERSOL_TYPE - case BL_ELEM: - return 0xa; //NPC_ELEMENTAL_TYPE - default: - return 0x1; //NPC_TYPE - } +static inline unsigned char clif_bl_type(struct block_list *bl) { + switch (bl->type) { + case BL_PC: return disguised(bl)?0x1:0x0; //PC_TYPE + case BL_ITEM: return 0x2; //ITEM_TYPE + case BL_SKILL: return 0x3; //SKILL_TYPE + case BL_CHAT: return 0x4; //UNKNOWN_TYPE + case BL_MOB: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE + case BL_NPC: return 0x6; //NPC_EVT_TYPE + case BL_PET: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE + case BL_HOM: return 0x8; //NPC_HOM_TYPE + case BL_MER: return 0x9; //NPC_MERSOL_TYPE + case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE + default: return 0x1; //NPC_TYPE + } } #endif @@ -299,338 +287,352 @@ static inline unsigned char clif_bl_type(struct block_list *bl) *------------------------------------------*/ static int clif_send_sub(struct block_list *bl, va_list ap) { - struct block_list *src_bl; - struct map_session_data *sd; - unsigned char *buf; - int len, type, fd; - - nullpo_ret(bl); - nullpo_ret(sd = (struct map_session_data *)bl); - - fd = sd->fd; - if (!fd) //Don't send to disconnected clients. - return 0; - - buf = va_arg(ap,unsigned char *); - len = va_arg(ap,int); - nullpo_ret(src_bl = va_arg(ap,struct block_list *)); - type = va_arg(ap,int); - - switch (type) { - case AREA_WOS: - if (bl == src_bl) - return 0; - break; - case AREA_WOC: - if (sd->chatID || bl == src_bl) - return 0; - break; - case AREA_WOSC: { - if (src_bl->type == BL_PC) { - struct map_session_data *ssd = (struct map_session_data *)src_bl; - if (ssd && sd->chatID && (sd->chatID == ssd->chatID)) - return 0; - } else if (src_bl->type == BL_NPC) { - struct npc_data *nd = (struct npc_data *)src_bl; - if (nd && sd->chatID && (sd->chatID == nd->chat_id)) - return 0; - } - } - break; - } - - if (session[fd] == NULL) - return 0; - - WFIFOHEAD(fd, len); - if (WFIFOP(fd,0) == buf) { - ShowError("WARNING: Invalid use of clif_send function\n"); - ShowError(" Packet x%4x use a WFIFO of a player instead of to use a buffer.\n", WBUFW(buf,0)); - ShowError(" Please correct your code.\n"); - // don't send to not move the pointer of the packet for next sessions in the loop - //WFIFOSET(fd,0);//## TODO is this ok? - //NO. It is not ok. There is the chance WFIFOSET actually sends the buffer data, and shifts elements around, which will corrupt the buffer. - return 0; - } - - if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - } - - return 0; + struct block_list *src_bl; + struct map_session_data *sd; + unsigned char *buf; + int len, type, fd; + + nullpo_ret(bl); + nullpo_ret(sd = (struct map_session_data *)bl); + + fd = sd->fd; + if (!fd) //Don't send to disconnected clients. + return 0; + + buf = va_arg(ap,unsigned char*); + len = va_arg(ap,int); + nullpo_ret(src_bl = va_arg(ap,struct block_list*)); + type = va_arg(ap,int); + + switch(type) + { + case AREA_WOS: + if (bl == src_bl) + return 0; + break; + case AREA_WOC: + if (sd->chatID || bl == src_bl) + return 0; + break; + case AREA_WOSC: + { + if(src_bl->type == BL_PC){ + struct map_session_data *ssd = (struct map_session_data *)src_bl; + if (ssd && sd->chatID && (sd->chatID == ssd->chatID)) + return 0; + } + else if(src_bl->type == BL_NPC) { + struct npc_data *nd = (struct npc_data *)src_bl; + if (nd && sd->chatID && (sd->chatID == nd->chat_id)) + return 0; + } + } + break; + } + + if (session[fd] == NULL) + return 0; + + WFIFOHEAD(fd, len); + if (WFIFOP(fd,0) == buf) { + ShowError("WARNING: Invalid use of clif_send function\n"); + ShowError(" Packet x%4x use a WFIFO of a player instead of to use a buffer.\n", WBUFW(buf,0)); + ShowError(" Please correct your code.\n"); + // don't send to not move the pointer of the packet for next sessions in the loop + //WFIFOSET(fd,0);//## TODO is this ok? + //NO. It is not ok. There is the chance WFIFOSET actually sends the buffer data, and shifts elements around, which will corrupt the buffer. + return 0; + } + + if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + } + + return 0; } /*========================================== * Packet Delegation (called on all packets that require data to be sent to more than one client) * functions that are sent solely to one use whose ID it posses use WFIFOSET *------------------------------------------*/ -int clif_send(const uint8 *buf, int len, struct block_list *bl, enum send_target type) -{ - int i; - struct map_session_data *sd, *tsd; - struct party_data *p = NULL; - struct guild *g = NULL; - struct battleground_data *bg = NULL; - int x0 = 0, x1 = 0, y0 = 0, y1 = 0, fd; - struct s_mapiterator *iter; - - if (type != ALL_CLIENT && type != CHAT_MAINCHAT) - nullpo_ret(bl); - - sd = BL_CAST(BL_PC, bl); - - switch (type) { - - case ALL_CLIENT: //All player clients. - iter = mapit_getallusers(); - while ((tsd = (TBL_PC *)mapit_next(iter)) != NULL) { - if (packet_db[tsd->packet_ver][RBUFW(buf,0)].len) { - // packet must exist for the client version - WFIFOHEAD(tsd->fd, len); - memcpy(WFIFOP(tsd->fd,0), buf, len); - WFIFOSET(tsd->fd,len); - } - } - mapit_free(iter); - break; - - case ALL_SAMEMAP: //All players on the same map - iter = mapit_getallusers(); - while ((tsd = (TBL_PC *)mapit_next(iter)) != NULL) { - if (bl->m == tsd->bl.m && packet_db[tsd->packet_ver][RBUFW(buf,0)].len) { - // packet must exist for the client version - WFIFOHEAD(tsd->fd, len); - memcpy(WFIFOP(tsd->fd,0), buf, len); - WFIFOSET(tsd->fd,len); - } - } - mapit_free(iter); - break; - - case AREA: - case AREA_WOSC: - if (sd && bl->prev == NULL) //Otherwise source misses the packet.[Skotlex] - clif_send(buf, len, bl, SELF); - case AREA_WOC: - case AREA_WOS: - map_foreachinarea(clif_send_sub, bl->m, bl->x-AREA_SIZE, bl->y-AREA_SIZE, bl->x+AREA_SIZE, bl->y+AREA_SIZE, - BL_PC, buf, len, bl, type); - break; - case AREA_CHAT_WOC: - map_foreachinarea(clif_send_sub, bl->m, bl->x-(AREA_SIZE-5), bl->y-(AREA_SIZE-5), - bl->x+(AREA_SIZE-5), bl->y+(AREA_SIZE-5), BL_PC, buf, len, bl, AREA_WOC); - break; - - case CHAT: - case CHAT_WOS: { - 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 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 ((fd=cd->usersd[i]->fd) >0 && session[fd]) { // Added check to see if session exists [PoW] - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - } - } - } - } - break; - - case CHAT_MAINCHAT: //[LuzZza] - iter = mapit_getallusers(); - while ((tsd = (TBL_PC *)mapit_next(iter)) != NULL) { - if (tsd->state.mainchat && tsd->chatID == 0 && packet_db[tsd->packet_ver][RBUFW(buf,0)].len) { - // packet must exist for the client version - WFIFOHEAD(tsd->fd, len); - memcpy(WFIFOP(tsd->fd,0), buf, len); - WFIFOSET(tsd->fd,len); - } - } - mapit_free(iter); - break; - - case PARTY_AREA: - case PARTY_AREA_WOS: - x0 = bl->x - AREA_SIZE; - y0 = bl->y - AREA_SIZE; - x1 = bl->x + AREA_SIZE; - y1 = bl->y + AREA_SIZE; - case PARTY: - case PARTY_WOS: - case PARTY_SAMEMAP: - case PARTY_SAMEMAP_WOS: - if (sd && sd->status.party_id) - p = party_search(sd->status.party_id); - - if (p) { - for (i=0; i<MAX_PARTY; i++) { - if ((sd = p->data[i].sd) == NULL) - continue; - - if (!(fd=sd->fd)) - continue; - - if (sd->bl.id == bl->id && (type == PARTY_WOS || type == PARTY_SAMEMAP_WOS || type == PARTY_AREA_WOS)) - continue; - - if (type != PARTY && type != PARTY_WOS && bl->m != sd->bl.m) - continue; - - if ((type == PARTY_AREA || type == PARTY_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1)) - continue; - - if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { - // packet must exist for the client version - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - } - } - if (!enable_spy) //Skip unnecessary parsing. [Skotlex] - break; - - iter = mapit_getallusers(); - while ((tsd = (TBL_PC *)mapit_next(iter)) != NULL) { - if (tsd->partyspy == p->party.party_id && packet_db[tsd->packet_ver][RBUFW(buf,0)].len) { - // packet must exist for the client version - WFIFOHEAD(tsd->fd, len); - memcpy(WFIFOP(tsd->fd,0), buf, len); - WFIFOSET(tsd->fd,len); - } - } - mapit_free(iter); - } - break; - - case DUEL: - case DUEL_WOS: - if (!sd || !sd->duel_group) break; //Invalid usage. - - iter = mapit_getallusers(); - while ((tsd = (TBL_PC *)mapit_next(iter)) != NULL) { - if (type == DUEL_WOS && bl->id == tsd->bl.id) - continue; - if (sd->duel_group == tsd->duel_group && packet_db[tsd->packet_ver][RBUFW(buf,0)].len) { - // packet must exist for the client version - WFIFOHEAD(tsd->fd, len); - memcpy(WFIFOP(tsd->fd,0), buf, len); - WFIFOSET(tsd->fd,len); - } - } - mapit_free(iter); - break; - - case SELF: - if (sd && (fd=sd->fd) && packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - } - break; - - // New definitions for guilds [Valaris] - Cleaned up and reorganized by [Skotlex] - case GUILD_AREA: - case GUILD_AREA_WOS: - x0 = bl->x - AREA_SIZE; - y0 = bl->y - AREA_SIZE; - x1 = bl->x + AREA_SIZE; - y1 = bl->y + AREA_SIZE; - case GUILD_SAMEMAP: - case GUILD_SAMEMAP_WOS: - case GUILD: - case GUILD_WOS: - case GUILD_NOBG: - if (sd && sd->status.guild_id) - g = guild_search(sd->status.guild_id); - - if (g) { - for (i = 0; i < g->max_member; i++) { - if ((sd = g->member[i].sd) != NULL) { - if (!(fd=sd->fd)) - continue; - - if (type == GUILD_NOBG && sd->bg_id) - continue; - - if (sd->bl.id == bl->id && (type == GUILD_WOS || type == GUILD_SAMEMAP_WOS || type == GUILD_AREA_WOS)) - continue; - - if (type != GUILD && type != GUILD_NOBG && type != GUILD_WOS && sd->bl.m != bl->m) - continue; - - if ((type == GUILD_AREA || type == GUILD_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1)) - continue; - - if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { - // packet must exist for the client version - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - } - } - } - if (!enable_spy) //Skip unnecessary parsing. [Skotlex] - break; - - iter = mapit_getallusers(); - while ((tsd = (TBL_PC *)mapit_next(iter)) != NULL) { - if (tsd->guildspy == g->guild_id && packet_db[tsd->packet_ver][RBUFW(buf,0)].len) { - // packet must exist for the client version - WFIFOHEAD(tsd->fd, len); - memcpy(WFIFOP(tsd->fd,0), buf, len); - WFIFOSET(tsd->fd,len); - } - } - mapit_free(iter); - } - break; - - case BG_AREA: - case BG_AREA_WOS: - x0 = bl->x - AREA_SIZE; - y0 = bl->y - AREA_SIZE; - x1 = bl->x + AREA_SIZE; - y1 = bl->y + AREA_SIZE; - case BG_SAMEMAP: - case BG_SAMEMAP_WOS: - case BG: - case BG_WOS: - if (sd && sd->bg_id && (bg = bg_team_search(sd->bg_id)) != NULL) { - for (i = 0; i < MAX_BG_MEMBERS; i++) { - if ((sd = bg->members[i].sd) == NULL || !(fd = sd->fd)) - continue; - if (sd->bl.id == bl->id && (type == BG_WOS || type == BG_SAMEMAP_WOS || type == BG_AREA_WOS)) - continue; - if (type != BG && type != BG_WOS && sd->bl.m != bl->m) - continue; - if ((type == BG_AREA || type == BG_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1)) - continue; - if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { - // packet must exist for the client version - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - } - } - } - break; - - default: - ShowError("clif_send: Unrecognized type %d\n",type); - return -1; - } - - return 0; +int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type) +{ + int i; + struct map_session_data *sd, *tsd; + struct party_data *p = NULL; + struct guild *g = NULL; + struct battleground_data *bg = NULL; + int x0 = 0, x1 = 0, y0 = 0, y1 = 0, fd; + struct s_mapiterator* iter; + + if( type != ALL_CLIENT && type != CHAT_MAINCHAT ) + nullpo_ret(bl); + + sd = BL_CAST(BL_PC, bl); + + switch(type) { + + case ALL_CLIENT: //All player clients. + iter = mapit_getallusers(); + while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) + { + if( packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) + { // packet must exist for the client version + WFIFOHEAD(tsd->fd, len); + memcpy(WFIFOP(tsd->fd,0), buf, len); + WFIFOSET(tsd->fd,len); + } + } + mapit_free(iter); + break; + + case ALL_SAMEMAP: //All players on the same map + iter = mapit_getallusers(); + while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) + { + if( bl->m == tsd->bl.m && packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) + { // packet must exist for the client version + WFIFOHEAD(tsd->fd, len); + memcpy(WFIFOP(tsd->fd,0), buf, len); + WFIFOSET(tsd->fd,len); + } + } + mapit_free(iter); + break; + + case AREA: + case AREA_WOSC: + if (sd && bl->prev == NULL) //Otherwise source misses the packet.[Skotlex] + clif_send (buf, len, bl, SELF); + case AREA_WOC: + case AREA_WOS: + map_foreachinarea(clif_send_sub, bl->m, bl->x-AREA_SIZE, bl->y-AREA_SIZE, bl->x+AREA_SIZE, bl->y+AREA_SIZE, + BL_PC, buf, len, bl, type); + break; + case AREA_CHAT_WOC: + map_foreachinarea(clif_send_sub, bl->m, bl->x-(AREA_SIZE-5), bl->y-(AREA_SIZE-5), + bl->x+(AREA_SIZE-5), bl->y+(AREA_SIZE-5), BL_PC, buf, len, bl, AREA_WOC); + break; + + case CHAT: + case CHAT_WOS: + { + 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 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 ((fd=cd->usersd[i]->fd) >0 && session[fd]) // Added check to see if session exists [PoW] + { + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + } + } + } + } + break; + + case CHAT_MAINCHAT: //[LuzZza] + iter = mapit_getallusers(); + while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) + { + if( tsd->state.mainchat && tsd->chatID == 0 && packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) + { // packet must exist for the client version + WFIFOHEAD(tsd->fd, len); + memcpy(WFIFOP(tsd->fd,0), buf, len); + WFIFOSET(tsd->fd,len); + } + } + mapit_free(iter); + break; + + case PARTY_AREA: + case PARTY_AREA_WOS: + x0 = bl->x - AREA_SIZE; + y0 = bl->y - AREA_SIZE; + x1 = bl->x + AREA_SIZE; + y1 = bl->y + AREA_SIZE; + case PARTY: + case PARTY_WOS: + case PARTY_SAMEMAP: + case PARTY_SAMEMAP_WOS: + if (sd && sd->status.party_id) + p = party_search(sd->status.party_id); + + if (p) { + for(i=0;i<MAX_PARTY;i++){ + if( (sd = p->data[i].sd) == NULL ) + continue; + + if( !(fd=sd->fd) ) + continue; + + if( sd->bl.id == bl->id && (type == PARTY_WOS || type == PARTY_SAMEMAP_WOS || type == PARTY_AREA_WOS) ) + continue; + + if( type != PARTY && type != PARTY_WOS && bl->m != sd->bl.m ) + continue; + + if( (type == PARTY_AREA || type == PARTY_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) ) + continue; + + if( packet_db[sd->packet_ver][RBUFW(buf,0)].len ) + { // packet must exist for the client version + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + } + } + if (!enable_spy) //Skip unnecessary parsing. [Skotlex] + break; + + iter = mapit_getallusers(); + while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) + { + if( tsd->partyspy == p->party.party_id && packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) + { // packet must exist for the client version + WFIFOHEAD(tsd->fd, len); + memcpy(WFIFOP(tsd->fd,0), buf, len); + WFIFOSET(tsd->fd,len); + } + } + mapit_free(iter); + } + break; + + case DUEL: + case DUEL_WOS: + if (!sd || !sd->duel_group) break; //Invalid usage. + + iter = mapit_getallusers(); + while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) + { + if( type == DUEL_WOS && bl->id == tsd->bl.id ) + continue; + if( sd->duel_group == tsd->duel_group && packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) + { // packet must exist for the client version + WFIFOHEAD(tsd->fd, len); + memcpy(WFIFOP(tsd->fd,0), buf, len); + WFIFOSET(tsd->fd,len); + } + } + mapit_free(iter); + break; + + case SELF: + if (sd && (fd=sd->fd) && packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + } + break; + + // New definitions for guilds [Valaris] - Cleaned up and reorganized by [Skotlex] + case GUILD_AREA: + case GUILD_AREA_WOS: + x0 = bl->x - AREA_SIZE; + y0 = bl->y - AREA_SIZE; + x1 = bl->x + AREA_SIZE; + y1 = bl->y + AREA_SIZE; + case GUILD_SAMEMAP: + case GUILD_SAMEMAP_WOS: + case GUILD: + case GUILD_WOS: + case GUILD_NOBG: + if (sd && sd->status.guild_id) + g = guild_search(sd->status.guild_id); + + if (g) { + for(i = 0; i < g->max_member; i++) { + if( (sd = g->member[i].sd) != NULL ) + { + if( !(fd=sd->fd) ) + continue; + + if( type == GUILD_NOBG && sd->bg_id ) + continue; + + if( sd->bl.id == bl->id && (type == GUILD_WOS || type == GUILD_SAMEMAP_WOS || type == GUILD_AREA_WOS) ) + continue; + + if( type != GUILD && type != GUILD_NOBG && type != GUILD_WOS && sd->bl.m != bl->m ) + continue; + + if( (type == GUILD_AREA || type == GUILD_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) ) + continue; + + if( packet_db[sd->packet_ver][RBUFW(buf,0)].len ) + { // packet must exist for the client version + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + } + } + } + if (!enable_spy) //Skip unnecessary parsing. [Skotlex] + break; + + iter = mapit_getallusers(); + while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) + { + if( tsd->guildspy == g->guild_id && packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) + { // packet must exist for the client version + WFIFOHEAD(tsd->fd, len); + memcpy(WFIFOP(tsd->fd,0), buf, len); + WFIFOSET(tsd->fd,len); + } + } + mapit_free(iter); + } + break; + + case BG_AREA: + case BG_AREA_WOS: + x0 = bl->x - AREA_SIZE; + y0 = bl->y - AREA_SIZE; + x1 = bl->x + AREA_SIZE; + y1 = bl->y + AREA_SIZE; + case BG_SAMEMAP: + case BG_SAMEMAP_WOS: + case BG: + case BG_WOS: + if( sd && sd->bg_id && (bg = bg_team_search(sd->bg_id)) != NULL ) + { + for( i = 0; i < MAX_BG_MEMBERS; i++ ) + { + if( (sd = bg->members[i].sd) == NULL || !(fd = sd->fd) ) + continue; + if( sd->bl.id == bl->id && (type == BG_WOS || type == BG_SAMEMAP_WOS || type == BG_AREA_WOS) ) + continue; + if( type != BG && type != BG_WOS && sd->bl.m != bl->m ) + continue; + if( (type == BG_AREA || type == BG_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) ) + continue; + if( packet_db[sd->packet_ver][RBUFW(buf,0)].len ) + { // packet must exist for the client version + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); + } + } + } + break; + + default: + ShowError("clif_send: Unrecognized type %d\n",type); + return -1; + } + + return 0; } @@ -640,22 +642,22 @@ int clif_send(const uint8 *buf, int len, struct block_list *bl, enum send_target void clif_authok(struct map_session_data *sd) { #if PACKETVER < 20080102 - const int cmd = 0x73; + const int cmd = 0x73; #else - const int cmd = 0x2eb; + const int cmd = 0x2eb; #endif - int fd = sd->fd; - - WFIFOHEAD(fd,packet_len(cmd)); - WFIFOW(fd, 0) = cmd; - WFIFOL(fd, 2) = gettick(); - WFIFOPOS(fd, 6, sd->bl.x, sd->bl.y, sd->ud.dir); - WFIFOB(fd, 9) = 5; // ignored - WFIFOB(fd,10) = 5; // ignored + int fd = sd->fd; + + WFIFOHEAD(fd,packet_len(cmd)); + WFIFOW(fd, 0) = cmd; + WFIFOL(fd, 2) = gettick(); + WFIFOPOS(fd, 6, sd->bl.x, sd->bl.y, sd->ud.dir); + WFIFOB(fd, 9) = 5; // ignored + WFIFOB(fd,10) = 5; // ignored #if PACKETVER >= 20080102 - WFIFOW(fd,11) = sd->user_font; // FIXME: Font is currently not saved. + WFIFOW(fd,11) = sd->user_font; // FIXME: Font is currently not saved. #endif - WFIFOSET(fd,packet_len(cmd)); + WFIFOSET(fd,packet_len(cmd)); } @@ -669,10 +671,10 @@ void clif_authok(struct map_session_data *sd) /// 4 = mobile - waiting state void clif_authrefuse(int fd, uint8 error_code) { - WFIFOHEAD(fd,packet_len(0x74)); - WFIFOW(fd,0) = 0x74; - WFIFOB(fd,2) = error_code; - WFIFOSET(fd,packet_len(0x74)); + WFIFOHEAD(fd,packet_len(0x74)); + WFIFOW(fd,0) = 0x74; + WFIFOB(fd,2) = error_code; + WFIFOSET(fd,packet_len(0x74)); } @@ -710,14 +712,14 @@ void clif_authrefuse(int fd, uint8 error_code) /// ? = disconnected -> MsgStringTable[3] void clif_authfail_fd(int fd, int type) { - if (!fd || !session[fd] || session[fd]->func_parse != clif_parse) //clif_authfail should only be invoked on players! - return; + if (!fd || !session[fd] || session[fd]->func_parse != clif_parse) //clif_authfail should only be invoked on players! + return; - WFIFOHEAD(fd, packet_len(0x81)); - WFIFOW(fd,0) = 0x81; - WFIFOB(fd,2) = type; - WFIFOSET(fd,packet_len(0x81)); - set_eof(fd); + WFIFOHEAD(fd, packet_len(0x81)); + WFIFOW(fd,0) = 0x81; + WFIFOB(fd,2) = type; + WFIFOSET(fd,packet_len(0x81)); + set_eof(fd); } @@ -728,43 +730,43 @@ void clif_authfail_fd(int fd, int type) /// ? = nothing void clif_charselectok(int id, uint8 ok) { - struct map_session_data *sd; - int fd; + struct map_session_data* sd; + int fd; - if ((sd = map_id2sd(id)) == NULL || !sd->fd) - return; + if ((sd = map_id2sd(id)) == NULL || !sd->fd) + return; - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xb3)); - WFIFOW(fd,0) = 0xb3; - WFIFOB(fd,2) = ok; - WFIFOSET(fd,packet_len(0xb3)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0xb3)); + WFIFOW(fd,0) = 0xb3; + WFIFOB(fd,2) = ok; + WFIFOSET(fd,packet_len(0xb3)); } /// Makes an item appear on the ground. /// 009e <id>.L <name id>.W <identified>.B <x>.W <y>.W <subX>.B <subY>.B <amount>.W (ZC_ITEM_FALL_ENTRY) /// 084b (ZC_ITEM_FALL_ENTRY4) -void clif_dropflooritem(struct flooritem_data *fitem) +void clif_dropflooritem(struct flooritem_data* fitem) { - uint8 buf[17]; - int view; + uint8 buf[17]; + int view; - nullpo_retv(fitem); + nullpo_retv(fitem); - if (fitem->item_data.nameid <= 0) - return; + if (fitem->item_data.nameid <= 0) + return; - WBUFW(buf, 0) = 0x9e; - WBUFL(buf, 2) = fitem->bl.id; - WBUFW(buf, 6) = ((view = itemdb_viewid(fitem->item_data.nameid)) > 0) ? view : fitem->item_data.nameid; - WBUFB(buf, 8) = fitem->item_data.identify; - WBUFW(buf, 9) = fitem->bl.x; - WBUFW(buf,11) = fitem->bl.y; - WBUFB(buf,13) = fitem->subx; - WBUFB(buf,14) = fitem->suby; - WBUFW(buf,15) = fitem->item_data.amount; + WBUFW(buf, 0) = 0x9e; + WBUFL(buf, 2) = fitem->bl.id; + WBUFW(buf, 6) = ((view = itemdb_viewid(fitem->item_data.nameid)) > 0) ? view : fitem->item_data.nameid; + WBUFB(buf, 8) = fitem->item_data.identify; + WBUFW(buf, 9) = fitem->bl.x; + WBUFW(buf,11) = fitem->bl.y; + WBUFB(buf,13) = fitem->subx; + WBUFB(buf,14) = fitem->suby; + WBUFW(buf,15) = fitem->item_data.amount; - clif_send(buf, packet_len(0x9e), &fitem->bl, AREA); + clif_send(buf, packet_len(0x9e), &fitem->bl, AREA); } @@ -773,20 +775,20 @@ void clif_dropflooritem(struct flooritem_data *fitem) /// 00a1 <id>.L (ZC_ITEM_DISAPPEAR) void clif_clearflooritem(struct flooritem_data *fitem, int fd) { - unsigned char buf[16]; + unsigned char buf[16]; - nullpo_retv(fitem); + nullpo_retv(fitem); - WBUFW(buf,0) = 0xa1; - WBUFL(buf,2) = fitem->bl.id; + WBUFW(buf,0) = 0xa1; + WBUFL(buf,2) = fitem->bl.id; - if (fd == 0) { - clif_send(buf, packet_len(0xa1), &fitem->bl, AREA); - } else { - WFIFOHEAD(fd,packet_len(0xa1)); - memcpy(WFIFOP(fd,0), buf, packet_len(0xa1)); - WFIFOSET(fd,packet_len(0xa1)); - } + if (fd == 0) { + clif_send(buf, packet_len(0xa1), &fitem->bl, AREA); + } else { + WFIFOHEAD(fd,packet_len(0xa1)); + memcpy(WFIFOP(fd,0), buf, packet_len(0xa1)); + WFIFOSET(fd,packet_len(0xa1)); + } } @@ -800,11 +802,11 @@ void clif_clearflooritem(struct flooritem_data *fitem, int fd) /// 4 = trickdead void clif_clearunit_single(int id, clr_type type, int fd) { - WFIFOHEAD(fd, packet_len(0x80)); - WFIFOW(fd,0) = 0x80; - WFIFOL(fd,2) = id; - WFIFOB(fd,6) = type; - WFIFOSET(fd, packet_len(0x80)); + WFIFOHEAD(fd, packet_len(0x80)); + WFIFOW(fd,0) = 0x80; + WFIFOL(fd,2) = id; + WFIFOB(fd,6) = type; + WFIFOSET(fd, packet_len(0x80)); } /// Makes a unit (char, npc, mob, homun) disappear to all clients in area (ZC_NOTIFY_VANISH). @@ -815,22 +817,22 @@ void clif_clearunit_single(int id, clr_type type, int fd) /// 2 = logged out /// 3 = teleport /// 4 = trickdead -void clif_clearunit_area(struct block_list *bl, clr_type type) +void clif_clearunit_area(struct block_list* bl, clr_type type) { - unsigned char buf[8]; + unsigned char buf[8]; - nullpo_retv(bl); + nullpo_retv(bl); - WBUFW(buf,0) = 0x80; - WBUFL(buf,2) = bl->id; - WBUFB(buf,6) = type; + WBUFW(buf,0) = 0x80; + WBUFL(buf,2) = bl->id; + WBUFB(buf,6) = type; - clif_send(buf, packet_len(0x80), bl, type == CLR_DEAD ? AREA : AREA_WOS); + clif_send(buf, packet_len(0x80), bl, type == CLR_DEAD ? AREA : AREA_WOS); - if (disguised(bl)) { - WBUFL(buf,2) = -bl->id; - clif_send(buf, packet_len(0x80), bl, SELF); - } + if(disguised(bl)) { + WBUFL(buf,2) = -bl->id; + clif_send(buf, packet_len(0x80), bl, SELF); + } } @@ -839,352 +841,361 @@ void clif_clearunit_area(struct block_list *bl, clr_type type) /// automatically. static int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *bl = (struct block_list *)data; - clif_clearunit_area(bl, (clr_type) id); - ers_free(delay_clearunit_ers,bl); - return 0; + struct block_list *bl = (struct block_list *)data; + clif_clearunit_area(bl, (clr_type) id); + ers_free(delay_clearunit_ers,bl); + return 0; } -void clif_clearunit_delayed(struct block_list *bl, clr_type type, unsigned int tick) +void clif_clearunit_delayed(struct block_list* bl, clr_type type, unsigned int tick) { - struct block_list *tbl = ers_alloc(delay_clearunit_ers, struct block_list); - memcpy(tbl, bl, sizeof(struct block_list)); - add_timer(tick, clif_clearunit_delayed_sub, (int)type, (intptr_t)tbl); + struct block_list *tbl = ers_alloc(delay_clearunit_ers, struct block_list); + memcpy (tbl, bl, sizeof (struct block_list)); + add_timer(tick, clif_clearunit_delayed_sub, (int)type, (intptr_t)tbl); } -void clif_get_weapon_view(struct map_session_data *sd, unsigned short *rhand, unsigned short *lhand) +void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, unsigned short *lhand) { - if (sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER)) { - *rhand = *lhand = 0; - return; - } + if(sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER)) + { + *rhand = *lhand = 0; + return; + } #if PACKETVER < 4 - *rhand = sd->status.weapon; - *lhand = sd->status.shield; + *rhand = sd->status.weapon; + *lhand = sd->status.shield; #else - if (sd->equip_index[EQI_HAND_R] >= 0 && - sd->inventory_data[sd->equip_index[EQI_HAND_R]]) { - struct item_data *id = sd->inventory_data[sd->equip_index[EQI_HAND_R]]; - if (id->view_id > 0) - *rhand = id->view_id; - else - *rhand = id->nameid; - } else - *rhand = 0; - - if (sd->equip_index[EQI_HAND_L] >= 0 && - sd->equip_index[EQI_HAND_L] != sd->equip_index[EQI_HAND_R] && - sd->inventory_data[sd->equip_index[EQI_HAND_L]]) { - struct item_data *id = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; - if (id->view_id > 0) - *lhand = id->view_id; - else - *lhand = id->nameid; - } else - *lhand = 0; + if (sd->equip_index[EQI_HAND_R] >= 0 && + sd->inventory_data[sd->equip_index[EQI_HAND_R]]) + { + struct item_data* id = sd->inventory_data[sd->equip_index[EQI_HAND_R]]; + if (id->view_id > 0) + *rhand = id->view_id; + else + *rhand = id->nameid; + } else + *rhand = 0; + + if (sd->equip_index[EQI_HAND_L] >= 0 && + sd->equip_index[EQI_HAND_L] != sd->equip_index[EQI_HAND_R] && + sd->inventory_data[sd->equip_index[EQI_HAND_L]]) + { + struct item_data* id = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; + if (id->view_id > 0) + *lhand = id->view_id; + else + *lhand = id->nameid; + } else + *lhand = 0; #endif } //To make the assignation of the level based on limits clearer/easier. [Skotlex] static int clif_setlevel_sub(int lv) { - if (lv < battle_config.max_lv) { - ; - } else if (lv < battle_config.aura_lv) { - lv = battle_config.max_lv - 1; - } else { - lv = battle_config.max_lv; - } - - return lv; -} - -static int clif_setlevel(struct block_list *bl) -{ - int lv = status_get_lv(bl); - if (battle_config.client_limit_unit_lv&bl->type) - return clif_setlevel_sub(lv); - switch (bl->type) { - case BL_NPC: - case BL_PET: - // npcs and pets do not have level - return 0; - } - return lv; + if( lv < battle_config.max_lv ) + { + ; + } + else if( lv < battle_config.aura_lv ) + { + lv = battle_config.max_lv - 1; + } + else + { + lv = battle_config.max_lv; + } + + return lv; +} + +static int clif_setlevel(struct block_list* bl) +{ + int lv = status_get_lv(bl); + if( battle_config.client_limit_unit_lv&bl->type ) + return clif_setlevel_sub(lv); + switch( bl->type ) + { + case BL_NPC: + case BL_PET: + // npcs and pets do not have level + return 0; + } + return lv; } /*========================================== * Prepares 'unit standing/spawning' packet *------------------------------------------*/ -static int clif_set_unit_idle(struct block_list *bl, unsigned char *buffer, bool spawn) +static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn) { - struct map_session_data *sd; - struct status_change *sc = status_get_sc(bl); - struct view_data *vd = status_get_viewdata(bl); - unsigned char *buf = WBUFP(buffer,0); + struct map_session_data* sd; + struct status_change* sc = status_get_sc(bl); + struct view_data* vd = status_get_viewdata(bl); + unsigned char *buf = WBUFP(buffer,0); #if PACKETVER < 20091103 - bool type = !pcdb_checkid(vd->class_); + bool type = !pcdb_checkid(vd->class_); #endif #if PACKETVER >= 7 - unsigned short offset = 0; + unsigned short offset = 0; #endif #if PACKETVER >= 20091103 - const char *name; + const char *name; #endif - sd = BL_CAST(BL_PC, bl); + sd = BL_CAST(BL_PC, bl); #if PACKETVER < 20091103 - if (type) - WBUFW(buf,0) = spawn?0x7c:0x78; - else + if(type) + WBUFW(buf,0) = spawn?0x7c:0x78; + else #endif #if PACKETVER < 4 - WBUFW(buf,0) = spawn?0x79:0x78; + WBUFW(buf,0) = spawn?0x79:0x78; #elif PACKETVER < 7 - WBUFW(buf,0) = spawn?0x1d9:0x1d8; + WBUFW(buf,0) = spawn?0x1d9:0x1d8; #elif PACKETVER < 20080102 - WBUFW(buf,0) = spawn?0x22b:0x22a; + WBUFW(buf,0) = spawn?0x22b:0x22a; #elif PACKETVER < 20091103 - WBUFW(buf,0) = spawn?0x2ed:0x2ee; + WBUFW(buf,0) = spawn?0x2ed:0x2ee; #elif PACKETVER < 20101124 - WBUFW(buf,0) = spawn?0x7f8:0x7f9; + WBUFW(buf,0) = spawn?0x7f8:0x7f9; #else - WBUFW(buf,0) = spawn?0x858:0x857; + WBUFW(buf,0) = spawn?0x858:0x857; #endif #if PACKETVER >= 20091103 - name = status_get_name(bl); + name = status_get_name(bl); #if PACKETVER < 20110111 - WBUFW(buf,2) = (spawn?62:63)+strlen(name); + WBUFW(buf,2) = (spawn?62:63)+strlen(name); #else - WBUFW(buf,2) = (spawn?64:65)+strlen(name); + WBUFW(buf,2) = (spawn?64:65)+strlen(name); #endif - WBUFB(buf,4) = clif_bl_type(bl); - offset+=3; - buf = WBUFP(buffer,offset); + WBUFB(buf,4) = clif_bl_type(bl); + offset+=3; + buf = WBUFP(buffer,offset); #elif PACKETVER >= 20071106 - if (type) { //Non-player packets - WBUFB(buf,2) = clif_bl_type(bl); - offset++; - buf = WBUFP(buffer,offset); - } + if (type) { //Non-player packets + WBUFB(buf,2) = clif_bl_type(bl); + offset++; + buf = WBUFP(buffer,offset); + } #endif - WBUFL(buf, 2) = bl->id; - WBUFW(buf, 6) = status_get_speed(bl); - WBUFW(buf, 8) = (sc)? sc->opt1 : 0; - WBUFW(buf,10) = (sc)? sc->opt2 : 0; + WBUFL(buf, 2) = bl->id; + WBUFW(buf, 6) = status_get_speed(bl); + WBUFW(buf, 8) = (sc)? sc->opt1 : 0; + WBUFW(buf,10) = (sc)? sc->opt2 : 0; #if PACKETVER < 20091103 - if (type&&spawn) { //uses an older and different packet structure - WBUFW(buf,12) = (sc)? sc->option : 0; - WBUFW(buf,14) = vd->hair_style; - WBUFW(buf,16) = vd->weapon; - WBUFW(buf,18) = vd->head_bottom; - WBUFW(buf,20) = vd->class_; //Pet armor (ignored by client) - WBUFW(buf,22) = vd->shield; - } else { + if (type&&spawn) { //uses an older and different packet structure + WBUFW(buf,12) = (sc)? sc->option : 0; + WBUFW(buf,14) = vd->hair_style; + WBUFW(buf,16) = vd->weapon; + WBUFW(buf,18) = vd->head_bottom; + WBUFW(buf,20) = vd->class_; //Pet armor (ignored by client) + WBUFW(buf,22) = vd->shield; + } else { #endif #if PACKETVER >= 20091103 - WBUFL(buf,12) = (sc)? sc->option : 0; - offset+=2; - buf = WBUFP(buffer,offset); + WBUFL(buf,12) = (sc)? sc->option : 0; + offset+=2; + buf = WBUFP(buffer,offset); #elif PACKETVER >= 7 - if (!type) { - WBUFL(buf,12) = (sc)? sc->option : 0; - offset+=2; - buf = WBUFP(buffer,offset); - } else - WBUFW(buf,12) = (sc)? sc->option : 0; + if (!type) { + WBUFL(buf,12) = (sc)? sc->option : 0; + offset+=2; + buf = WBUFP(buffer,offset); + } else + WBUFW(buf,12) = (sc)? sc->option : 0; #else - WBUFW(buf,12) = (sc)? sc->option : 0; + WBUFW(buf,12) = (sc)? sc->option : 0; #endif - WBUFW(buf,14) = vd->class_; - WBUFW(buf,16) = vd->hair_style; - WBUFW(buf,18) = vd->weapon; + WBUFW(buf,14) = vd->class_; + WBUFW(buf,16) = vd->hair_style; + WBUFW(buf,18) = vd->weapon; #if PACKETVER < 4 - WBUFW(buf,20) = vd->head_bottom; - WBUFW(buf,22) = vd->shield; + WBUFW(buf,20) = vd->head_bottom; + WBUFW(buf,22) = vd->shield; #else - WBUFW(buf,20) = vd->shield; - WBUFW(buf,22) = vd->head_bottom; + WBUFW(buf,20) = vd->shield; + WBUFW(buf,22) = vd->head_bottom; #endif #if PACKETVER < 20091103 - } + } #endif - WBUFW(buf,24) = vd->head_top; - WBUFW(buf,26) = vd->head_mid; - - if (bl->type == BL_NPC && vd->class_ == FLAG_CLASS) { - //The hell, why flags work like this? - WBUFW(buf,22) = status_get_emblem_id(bl); - WBUFW(buf,24) = GetWord(status_get_guild_id(bl), 1); - WBUFW(buf,26) = GetWord(status_get_guild_id(bl), 0); - } - - WBUFW(buf,28) = vd->hair_color; - WBUFW(buf,30) = vd->cloth_color; - WBUFW(buf,32) = (sd)? sd->head_dir : 0; + WBUFW(buf,24) = vd->head_top; + WBUFW(buf,26) = vd->head_mid; + + if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) + { //The hell, why flags work like this? + WBUFW(buf,22) = status_get_emblem_id(bl); + WBUFW(buf,24) = GetWord(status_get_guild_id(bl), 1); + WBUFW(buf,26) = GetWord(status_get_guild_id(bl), 0); + } + + WBUFW(buf,28) = vd->hair_color; + WBUFW(buf,30) = vd->cloth_color; + WBUFW(buf,32) = (sd)? sd->head_dir : 0; #if PACKETVER < 20091103 - if (type&&spawn) { //End of packet 0x7c - WBUFB(buf,34) = (sd)?sd->status.karma:0; // karma - WBUFB(buf,35) = vd->sex; - WBUFPOS(buf,36,bl->x,bl->y,unit_getdir(bl)); - WBUFB(buf,39) = 0; - WBUFB(buf,40) = 0; - return packet_len(0x7c); - } + if (type&&spawn) { //End of packet 0x7c + WBUFB(buf,34) = (sd)?sd->status.karma:0; // karma + WBUFB(buf,35) = vd->sex; + WBUFPOS(buf,36,bl->x,bl->y,unit_getdir(bl)); + WBUFB(buf,39) = 0; + WBUFB(buf,40) = 0; + return packet_len(0x7c); + } #endif #if PACKETVER >= 20110111 - WBUFW(buf,34) = vd->robe; - offset+= 2; - buf = WBUFP(buffer,offset); + WBUFW(buf,34) = vd->robe; + offset+= 2; + buf = WBUFP(buffer,offset); #endif - WBUFL(buf,34) = status_get_guild_id(bl); - WBUFW(buf,38) = status_get_emblem_id(bl); - WBUFW(buf,40) = (sd)? sd->status.manner : 0; + WBUFL(buf,34) = status_get_guild_id(bl); + WBUFW(buf,38) = status_get_emblem_id(bl); + WBUFW(buf,40) = (sd)? sd->status.manner : 0; #if PACKETVER >= 20091103 - WBUFL(buf,42) = (sc)? sc->opt3 : 0; - offset+=2; - buf = WBUFP(buffer,offset); + WBUFL(buf,42) = (sc)? sc->opt3 : 0; + offset+=2; + buf = WBUFP(buffer,offset); #elif PACKETVER >= 7 - if (!type) { - WBUFL(buf,42) = (sc)? sc->opt3 : 0; - offset+=2; - buf = WBUFP(buffer,offset); - } else - WBUFW(buf,42) = (sc)? sc->opt3 : 0; + if (!type) { + WBUFL(buf,42) = (sc)? sc->opt3 : 0; + offset+=2; + buf = WBUFP(buffer,offset); + } else + WBUFW(buf,42) = (sc)? sc->opt3 : 0; #else - WBUFW(buf,42) = (sc)? sc->opt3 : 0; + WBUFW(buf,42) = (sc)? sc->opt3 : 0; #endif - WBUFB(buf,44) = (sd)? sd->status.karma : 0; - WBUFB(buf,45) = vd->sex; - WBUFPOS(buf,46,bl->x,bl->y,unit_getdir(bl)); - WBUFB(buf,49) = (sd)? 5 : 0; - WBUFB(buf,50) = (sd)? 5 : 0; - if (!spawn) { - WBUFB(buf,51) = vd->dead_sit; - offset++; - buf = WBUFP(buffer,offset); - } - WBUFW(buf,51) = clif_setlevel(bl); + WBUFB(buf,44) = (sd)? sd->status.karma : 0; + WBUFB(buf,45) = vd->sex; + WBUFPOS(buf,46,bl->x,bl->y,unit_getdir(bl)); + WBUFB(buf,49) = (sd)? 5 : 0; + WBUFB(buf,50) = (sd)? 5 : 0; + if (!spawn) { + WBUFB(buf,51) = vd->dead_sit; + offset++; + buf = WBUFP(buffer,offset); + } + WBUFW(buf,51) = clif_setlevel(bl); #if PACKETVER < 20091103 - if (type) //End for non-player packet - return packet_len(WBUFW(buffer,0)); + if (type) //End for non-player packet + return packet_len(WBUFW(buffer,0)); #endif #if PACKETVER >= 20080102 - WBUFW(buf,53) = sd?sd->user_font:0; + WBUFW(buf,53) = sd?sd->user_font:0; #endif #if PACKETVER >= 20091103 - memcpy((char *)WBUFP(buf,55), name, NAME_LENGTH); - return WBUFW(buffer,2); + memcpy((char*)WBUFP(buf,55), name, NAME_LENGTH); + return WBUFW(buffer,2); #else - return packet_len(WBUFW(buffer,0)); + return packet_len(WBUFW(buffer,0)); #endif } /*========================================== * Prepares 'unit walking' packet *------------------------------------------*/ -static int clif_set_unit_walking(struct block_list *bl, struct unit_data *ud, unsigned char *buffer) +static int clif_set_unit_walking(struct block_list* bl, struct unit_data* ud, unsigned char* buffer) { - struct map_session_data *sd; - struct status_change *sc = status_get_sc(bl); - struct view_data *vd = status_get_viewdata(bl); - unsigned char *buf = WBUFP(buffer,0); + struct map_session_data* sd; + struct status_change* sc = status_get_sc(bl); + struct view_data* vd = status_get_viewdata(bl); + unsigned char* buf = WBUFP(buffer,0); #if PACKETVER >= 7 - unsigned short offset = 0; + unsigned short offset = 0; #endif #if PACKETVER >= 20091103 - const char *name; + const char *name; #endif - sd = BL_CAST(BL_PC, bl); + sd = BL_CAST(BL_PC, bl); #if PACKETVER < 4 - WBUFW(buf, 0) = 0x7b; + WBUFW(buf, 0) = 0x7b; #elif PACKETVER < 7 - WBUFW(buf, 0) = 0x1da; + WBUFW(buf, 0) = 0x1da; #elif PACKETVER < 20080102 - WBUFW(buf, 0) = 0x22c; + WBUFW(buf, 0) = 0x22c; #elif PACKETVER < 20091103 - WBUFW(buf, 0) = 0x2ec; + WBUFW(buf, 0) = 0x2ec; #elif PACKETVER < 20101124 - WBUFW(buf, 0) = 0x7f7; + WBUFW(buf, 0) = 0x7f7; #else - WBUFW(buf, 0) = 0x856; + WBUFW(buf, 0) = 0x856; #endif #if PACKETVER >= 20091103 - name = status_get_name(bl); + name = status_get_name(bl); #if PACKETVER < 20110111 - WBUFW(buf, 2) = 69+strlen(name); + WBUFW(buf, 2) = 69+strlen(name); #else - WBUFW(buf, 2) = 71+strlen(name); + WBUFW(buf, 2) = 71+strlen(name); #endif - offset+=2; - buf = WBUFP(buffer,offset); + offset+=2; + buf = WBUFP(buffer,offset); #endif #if PACKETVER >= 20071106 - WBUFB(buf, 2) = clif_bl_type(bl); - offset++; - buf = WBUFP(buffer,offset); + WBUFB(buf, 2) = clif_bl_type(bl); + offset++; + buf = WBUFP(buffer,offset); #endif - WBUFL(buf, 2) = bl->id; - WBUFW(buf, 6) = status_get_speed(bl); - WBUFW(buf, 8) = (sc)? sc->opt1 : 0; - WBUFW(buf,10) = (sc)? sc->opt2 : 0; + WBUFL(buf, 2) = bl->id; + WBUFW(buf, 6) = status_get_speed(bl); + WBUFW(buf, 8) = (sc)? sc->opt1 : 0; + WBUFW(buf,10) = (sc)? sc->opt2 : 0; #if PACKETVER < 7 - WBUFW(buf,12) = (sc)? sc->option : 0; + WBUFW(buf,12) = (sc)? sc->option : 0; #else - WBUFL(buf,12) = (sc)? sc->option : 0; - offset+=2; //Shift the rest of elements by 2 bytes. - buf = WBUFP(buffer,offset); + WBUFL(buf,12) = (sc)? sc->option : 0; + offset+=2; //Shift the rest of elements by 2 bytes. + buf = WBUFP(buffer,offset); #endif - WBUFW(buf,14) = vd->class_; - WBUFW(buf,16) = vd->hair_style; - WBUFW(buf,18) = vd->weapon; + WBUFW(buf,14) = vd->class_; + WBUFW(buf,16) = vd->hair_style; + WBUFW(buf,18) = vd->weapon; #if PACKETVER < 4 - WBUFW(buf,20) = vd->head_bottom; - WBUFL(buf,22) = gettick(); - WBUFW(buf,26) = vd->shield; + WBUFW(buf,20) = vd->head_bottom; + WBUFL(buf,22) = gettick(); + WBUFW(buf,26) = vd->shield; #else - WBUFW(buf,20) = vd->shield; - WBUFW(buf,22) = vd->head_bottom; - WBUFL(buf,24) = gettick(); + WBUFW(buf,20) = vd->shield; + WBUFW(buf,22) = vd->head_bottom; + WBUFL(buf,24) = gettick(); #endif - WBUFW(buf,28) = vd->head_top; - WBUFW(buf,30) = vd->head_mid; - WBUFW(buf,32) = vd->hair_color; - WBUFW(buf,34) = vd->cloth_color; - WBUFW(buf,36) = (sd)? sd->head_dir : 0; + WBUFW(buf,28) = vd->head_top; + WBUFW(buf,30) = vd->head_mid; + WBUFW(buf,32) = vd->hair_color; + WBUFW(buf,34) = vd->cloth_color; + WBUFW(buf,36) = (sd)? sd->head_dir : 0; #if PACKETVER >= 20110111 - WBUFW(buf,38) = vd->robe; - offset+= 2; - buf = WBUFP(buffer,offset); + WBUFW(buf,38) = vd->robe; + offset+= 2; + buf = WBUFP(buffer,offset); #endif - WBUFL(buf,38) = status_get_guild_id(bl); - WBUFW(buf,42) = status_get_emblem_id(bl); - WBUFW(buf,44) = (sd)? sd->status.manner : 0; + WBUFL(buf,38) = status_get_guild_id(bl); + WBUFW(buf,42) = status_get_emblem_id(bl); + WBUFW(buf,44) = (sd)? sd->status.manner : 0; #if PACKETVER < 7 - WBUFW(buf,46) = (sc)? sc->opt3 : 0; + WBUFW(buf,46) = (sc)? sc->opt3 : 0; #else - WBUFL(buf,46) = (sc)? sc->opt3 : 0; - offset+=2; //Shift the rest of elements by 2 bytes. - buf = WBUFP(buffer,offset); + WBUFL(buf,46) = (sc)? sc->opt3 : 0; + offset+=2; //Shift the rest of elements by 2 bytes. + buf = WBUFP(buffer,offset); #endif - WBUFB(buf,48) = (sd)? sd->status.karma : 0; - WBUFB(buf,49) = vd->sex; - WBUFPOS2(buf,50,bl->x,bl->y,ud->to_x,ud->to_y,8,8); - WBUFB(buf,56) = (sd)? 5 : 0; - WBUFB(buf,57) = (sd)? 5 : 0; - WBUFW(buf,58) = clif_setlevel(bl); + WBUFB(buf,48) = (sd)? sd->status.karma : 0; + WBUFB(buf,49) = vd->sex; + WBUFPOS2(buf,50,bl->x,bl->y,ud->to_x,ud->to_y,8,8); + WBUFB(buf,56) = (sd)? 5 : 0; + WBUFB(buf,57) = (sd)? 5 : 0; + WBUFW(buf,58) = clif_setlevel(bl); #if PACKETVER >= 20080102 - WBUFW(buf,60) = sd?sd->user_font:0; + WBUFW(buf,60) = sd?sd->user_font:0; #endif #if PACKETVER >= 20091103 - memcpy((char *)WBUFP(buf,62), name, NAME_LENGTH); - return WBUFW(buffer,2); + memcpy((char*)WBUFP(buf,62), name, NAME_LENGTH); + return WBUFW(buffer,2); #else - return packet_len(WBUFW(buffer,0)); + return packet_len(WBUFW(buffer,0)); #endif } @@ -1193,15 +1204,15 @@ static int clif_set_unit_walking(struct block_list *bl, struct unit_data *ud, un static void clif_setdisguise(struct block_list *bl, unsigned char *buf,int len) { #if PACKETVER >= 20091103 - WBUFB(buf,4)= pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE - WBUFL(buf,5)=-bl->id; + WBUFB(buf,4)= pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + WBUFL(buf,5)=-bl->id; #elif PACKETVER >= 20071106 - WBUFB(buf,2)= pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE - WBUFL(buf,3)=-bl->id; + WBUFB(buf,2)= pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + WBUFL(buf,3)=-bl->id; #else - WBUFL(buf,2)=-bl->id; + WBUFL(buf,2)=-bl->id; #endif - clif_send(buf, len, bl, SELF); + clif_send(buf, len, bl, SELF); } @@ -1211,18 +1222,18 @@ static void clif_setdisguise(struct block_list *bl, unsigned char *buf,int len) /// unused void clif_class_change(struct block_list *bl,int class_,int type) { - unsigned char buf[16]; + unsigned char buf[16]; - nullpo_retv(bl); + nullpo_retv(bl); - if (!pcdb_checkid(class_)) { - // player classes yield missing sprites - WBUFW(buf,0)=0x1b0; - WBUFL(buf,2)=bl->id; - WBUFB(buf,6)=type; - WBUFL(buf,7)=class_; - clif_send(buf,packet_len(0x1b0),bl,AREA); - } + if(!pcdb_checkid(class_)) + {// player classes yield missing sprites + WBUFW(buf,0)=0x1b0; + WBUFL(buf,2)=bl->id; + WBUFB(buf,6)=type; + WBUFL(buf,7)=class_; + clif_send(buf,packet_len(0x1b0),bl,AREA); + } } @@ -1231,11 +1242,11 @@ void clif_class_change(struct block_list *bl,int class_,int type) /// 01e1 <id>.L <amount>.W (ZC_SPIRITS2) static void clif_spiritball_single(int fd, struct map_session_data *sd) { - WFIFOHEAD(fd, packet_len(0x1e1)); - WFIFOW(fd,0)=0x1e1; - WFIFOL(fd,2)=sd->bl.id; - WFIFOW(fd,6)=sd->spiritball; - WFIFOSET(fd, packet_len(0x1e1)); + WFIFOHEAD(fd, packet_len(0x1e1)); + WFIFOW(fd,0)=0x1e1; + WFIFOL(fd,2)=sd->bl.id; + WFIFOW(fd,6)=sd->spiritball; + WFIFOSET(fd, packet_len(0x1e1)); } /*========================================== @@ -1243,12 +1254,12 @@ static void clif_spiritball_single(int fd, struct map_session_data *sd) *------------------------------------------*/ static void clif_talisman_single(int fd, struct map_session_data *sd, short type) { - WFIFOHEAD(fd, packet_len(0x08cf)); - WFIFOW(fd,0)=0x08cf; - WFIFOL(fd,2)=sd->bl.id; - WFIFOW(fd,6)=type; - WFIFOW(fd,8)=sd->talisman[type]; - WFIFOSET(fd, packet_len(0x08cf)); + WFIFOHEAD(fd, packet_len(0x08cf)); + WFIFOW(fd,0)=0x08cf; + WFIFOL(fd,2)=sd->bl.id; + WFIFOW(fd,6)=type; + WFIFOW(fd,8)=sd->talisman[type]; + WFIFOSET(fd, packet_len(0x08cf)); } /*========================================== @@ -1257,194 +1268,200 @@ static void clif_talisman_single(int fd, struct map_session_data *sd, short type *------------------------------------------*/ static void clif_weather_check(struct map_session_data *sd) { - int m = sd->bl.m, fd = sd->fd; - - if (map[m].flag.snow - || map[m].flag.clouds - || map[m].flag.fog - || map[m].flag.fireworks - || map[m].flag.sakura - || map[m].flag.leaves - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //|| map[m].flag.rain - || map[m].flag.clouds2) { - if (map[m].flag.snow) - clif_specialeffect_single(&sd->bl, 162, fd); - if (map[m].flag.clouds) - clif_specialeffect_single(&sd->bl, 233, fd); - if (map[m].flag.clouds2) - clif_specialeffect_single(&sd->bl, 516, fd); - if (map[m].flag.fog) - clif_specialeffect_single(&sd->bl, 515, fd); - if (map[m].flag.fireworks) { - clif_specialeffect_single(&sd->bl, 297, fd); - clif_specialeffect_single(&sd->bl, 299, fd); - clif_specialeffect_single(&sd->bl, 301, fd); - } - if (map[m].flag.sakura) - clif_specialeffect_single(&sd->bl, 163, fd); - if (map[m].flag.leaves) - clif_specialeffect_single(&sd->bl, 333, fd); - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //if (map[m].flag.rain) - // clif_specialeffect_single(&sd->bl, 161, fd); - } + int m = sd->bl.m, fd = sd->fd; + + if (map[m].flag.snow + || map[m].flag.clouds + || map[m].flag.fog + || map[m].flag.fireworks + || map[m].flag.sakura + || map[m].flag.leaves + /** + * No longer available, keeping here just in case it's back someday. [Ind] + **/ + //|| map[m].flag.rain + || map[m].flag.clouds2) + { + if (map[m].flag.snow) + clif_specialeffect_single(&sd->bl, 162, fd); + if (map[m].flag.clouds) + clif_specialeffect_single(&sd->bl, 233, fd); + if (map[m].flag.clouds2) + clif_specialeffect_single(&sd->bl, 516, fd); + if (map[m].flag.fog) + clif_specialeffect_single(&sd->bl, 515, fd); + if (map[m].flag.fireworks) { + clif_specialeffect_single(&sd->bl, 297, fd); + clif_specialeffect_single(&sd->bl, 299, fd); + clif_specialeffect_single(&sd->bl, 301, fd); + } + if (map[m].flag.sakura) + clif_specialeffect_single(&sd->bl, 163, fd); + if (map[m].flag.leaves) + clif_specialeffect_single(&sd->bl, 333, fd); + /** + * No longer available, keeping here just in case it's back someday. [Ind] + **/ + //if (map[m].flag.rain) + // clif_specialeffect_single(&sd->bl, 161, fd); + } } /** * Run when the weather on a map changes, throws all players in map id 'm' to clif_weather_check function **/ void clif_weather(int m) { - struct s_mapiterator *iter; - struct map_session_data *sd=NULL; + struct s_mapiterator* iter; + struct map_session_data *sd=NULL; - iter = mapit_getallusers(); - for (sd = (struct map_session_data *)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data *)mapit_next(iter)) { - if (sd->bl.m == m) - clif_weather_check(sd); - } - mapit_free(iter); + iter = mapit_getallusers(); + for( sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data*)mapit_next(iter) ) + { + if( sd->bl.m == m ) + clif_weather_check(sd); + } + mapit_free(iter); } /** * Main function to spawn a unit on the client (player/mob/pet/etc) **/ int clif_spawn(struct block_list *bl) { - unsigned char buf[128]; - struct view_data *vd; - int len; - - vd = status_get_viewdata(bl); - if (!vd || vd->class_ == INVISIBLE_CLASS) - return 0; - - /** - * Hide NPC from maya purple card. - **/ - if (bl->type == BL_NPC && !((TBL_NPC *)bl)->chat_id && (((TBL_NPC *)bl)->sc.option&OPTION_INVISIBLE)) - return 0; - - len = clif_set_unit_idle(bl, buf,true); - clif_send(buf, len, bl, AREA_WOS); - if (disguised(bl)) - clif_setdisguise(bl, buf, len); - - if (vd->cloth_color) - clif_refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); - - switch (bl->type) { - case BL_PC: { - TBL_PC *sd = ((TBL_PC *)bl); - int i; - if (sd->spiritball > 0) - clif_spiritball(&sd->bl); - if (sd->state.size==SZ_BIG) // tiny/big players [Valaris] - clif_specialeffect(bl,423,AREA); - else if (sd->state.size==SZ_MEDIUM) - clif_specialeffect(bl,421,AREA); - if (sd->bg_id && map[sd->bl.m].flag.battleground) - clif_sendbgemblem_area(sd); - if (sd->sc.option&OPTION_MOUNTING) { - //New Mounts are not complaint to the original method, so we gotta tell this guy that he is mounting. - clif_status_load_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0); - } - for (i = 1; i < 5; i++) { - if (sd->talisman[i] > 0) - clif_talisman(sd, i); - } -#ifdef NEW_CARTS - if (sd->sc.data[SC_PUSH_CART]) - clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2, sd->sc.data[SC_PUSH_CART]->val1, 0, 0); -#endif -#if PACKETVER <= 20120207 - if (sd->status.robe) - clif_refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); -#endif - } - break; - case BL_MOB: { - TBL_MOB *md = ((TBL_MOB *)bl); - if (md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] - clif_specialeffect(&md->bl,423,AREA); - else if (md->special_state.size==SZ_MEDIUM) - clif_specialeffect(&md->bl,421,AREA); - } - break; - case BL_NPC: { - TBL_NPC *nd = ((TBL_NPC *)bl); - if (nd->size == SZ_BIG) - clif_specialeffect(&nd->bl,423,AREA); - else if (nd->size == SZ_MEDIUM) - clif_specialeffect(&nd->bl,421,AREA); - } - break; - case BL_PET: - if (vd->head_bottom) - clif_pet_equip_area((TBL_PET *)bl); // needed to display pet equip properly - break; - } - return 0; + unsigned char buf[128]; + struct view_data *vd; + int len; + + vd = status_get_viewdata(bl); + if( !vd || vd->class_ == INVISIBLE_CLASS ) + return 0; + + /** + * Hide NPC from maya purple card. + **/ + if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE)) + return 0; + + len = clif_set_unit_idle(bl, buf,true); + clif_send(buf, len, bl, AREA_WOS); + if (disguised(bl)) + clif_setdisguise(bl, buf, len); + + if (vd->cloth_color) + clif_refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); + + switch (bl->type) + { + case BL_PC: + { + TBL_PC *sd = ((TBL_PC*)bl); + int i; + if (sd->spiritball > 0) + clif_spiritball(&sd->bl); + if(sd->state.size==SZ_BIG) // tiny/big players [Valaris] + clif_specialeffect(bl,423,AREA); + else if(sd->state.size==SZ_MEDIUM) + clif_specialeffect(bl,421,AREA); + if( sd->bg_id && map[sd->bl.m].flag.battleground ) + clif_sendbgemblem_area(sd); + if( sd->sc.option&OPTION_MOUNTING ) { + //New Mounts are not complaint to the original method, so we gotta tell this guy that he is mounting. + clif_status_load_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0); + } + for(i = 1; i < 5; i++){ + if( sd->talisman[i] > 0 ) + clif_talisman(sd, i); + } + #ifdef NEW_CARTS + if( sd->sc.data[SC_PUSH_CART] ) + clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2, sd->sc.data[SC_PUSH_CART]->val1, 0, 0); + #endif + #if PACKETVER <= 20120207 + if (sd->status.robe) + clif_refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); + #endif + } + break; + case BL_MOB: + { + TBL_MOB *md = ((TBL_MOB*)bl); + if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] + clif_specialeffect(&md->bl,423,AREA); + else if(md->special_state.size==SZ_MEDIUM) + clif_specialeffect(&md->bl,421,AREA); + } + break; + case BL_NPC: + { + TBL_NPC *nd = ((TBL_NPC*)bl); + if( nd->size == SZ_BIG ) + clif_specialeffect(&nd->bl,423,AREA); + else if( nd->size == SZ_MEDIUM ) + clif_specialeffect(&nd->bl,421,AREA); + } + break; + case BL_PET: + if (vd->head_bottom) + clif_pet_equip_area((TBL_PET*)bl); // needed to display pet equip properly + break; + } + return 0; } /// Sends information about owned homunculus to the client (ZC_PROPERTY_HOMUN). [orn] /// 022e <name>.24B <modified>.B <level>.W <hunger>.W <intimacy>.W <equip id>.W <atk>.W <matk>.W <hit>.W <crit>.W <def>.W <mdef>.W <flee>.W <aspd>.W <hp>.W <max hp>.W <sp>.W <max sp>.W <exp>.L <max exp>.L <skill points>.W <atk range>.W void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) { - struct status_data *status; - unsigned char buf[128]; - int m_class; - - nullpo_retv(hd); - - status = &hd->battle_status; - m_class = hom_class2mapid(hd->homunculus.class_); - - memset(buf,0,packet_len(0x22e)); - WBUFW(buf,0)=0x22e; - memcpy(WBUFP(buf,2),hd->homunculus.name,NAME_LENGTH); - // Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true) - WBUFB(buf,26)=(battle_config.hom_rename?0:hd->homunculus.rename_flag) | (hd->homunculus.vaporize << 1) | (hd->homunculus.hp?0:4); - WBUFW(buf,27)=hd->homunculus.level; - WBUFW(buf,29)=hd->homunculus.hunger; - WBUFW(buf,31)=(unsigned short)(hd->homunculus.intimacy / 100) ; - WBUFW(buf,33)=0; // equip id - WBUFW(buf,35)=cap_value(status->rhw.atk2+status->batk, 0, INT16_MAX); - WBUFW(buf,37)=cap_value(status->matk_max, 0, INT16_MAX); - WBUFW(buf,39)=status->hit; - if (battle_config.hom_setting&0x10) - WBUFW(buf,41)=status->luk/3 + 1; //crit is a +1 decimal value! Just display purpose.[Vicious] - else - WBUFW(buf,41)=status->cri/10; - WBUFW(buf,43)=status->def + status->vit ; - WBUFW(buf,45)=status->mdef; - WBUFW(buf,47)=status->flee; - WBUFW(buf,49)=(flag)?0:status->amotion; - if (status->max_hp > INT16_MAX) { - WBUFW(buf,51) = status->hp/(status->max_hp/100); - WBUFW(buf,53) = 100; - } else { - WBUFW(buf,51)=status->hp; - WBUFW(buf,53)=status->max_hp; - } - if (status->max_sp > INT16_MAX) { - WBUFW(buf,55) = status->sp/(status->max_sp/100); - WBUFW(buf,57) = 100; - } else { - WBUFW(buf,55)=status->sp; - WBUFW(buf,57)=status->max_sp; - } - WBUFL(buf,59)=hd->homunculus.exp; - if (((m_class&HOM_REG) && hd->homunculus.level >= battle_config.hom_max_level) || ((m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level)) - WBUFL(buf,63)=0; - else - WBUFL(buf,63)=hd->exp_next; - WBUFW(buf,67)=hd->homunculus.skillpts; - WBUFW(buf,69)=status_get_range(&hd->bl); - clif_send(buf,packet_len(0x22e),&sd->bl,SELF); + struct status_data *status; + unsigned char buf[128]; + int m_class; + + nullpo_retv(hd); + + status = &hd->battle_status; + m_class = hom_class2mapid(hd->homunculus.class_); + + memset(buf,0,packet_len(0x22e)); + WBUFW(buf,0)=0x22e; + memcpy(WBUFP(buf,2),hd->homunculus.name,NAME_LENGTH); + // Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true) + WBUFB(buf,26)=(battle_config.hom_rename?0:hd->homunculus.rename_flag) | (hd->homunculus.vaporize << 1) | (hd->homunculus.hp?0:4); + WBUFW(buf,27)=hd->homunculus.level; + WBUFW(buf,29)=hd->homunculus.hunger; + WBUFW(buf,31)=(unsigned short) (hd->homunculus.intimacy / 100) ; + WBUFW(buf,33)=0; // equip id + WBUFW(buf,35)=cap_value(status->rhw.atk2+status->batk, 0, INT16_MAX); + WBUFW(buf,37)=cap_value(status->matk_max, 0, INT16_MAX); + WBUFW(buf,39)=status->hit; + if (battle_config.hom_setting&0x10) + WBUFW(buf,41)=status->luk/3 + 1; //crit is a +1 decimal value! Just display purpose.[Vicious] + else + WBUFW(buf,41)=status->cri/10; + WBUFW(buf,43)=status->def + status->vit ; + WBUFW(buf,45)=status->mdef; + WBUFW(buf,47)=status->flee; + WBUFW(buf,49)=(flag)?0:status->amotion; + if (status->max_hp > INT16_MAX) { + WBUFW(buf,51) = status->hp/(status->max_hp/100); + WBUFW(buf,53) = 100; + } else { + WBUFW(buf,51)=status->hp; + WBUFW(buf,53)=status->max_hp; + } + if (status->max_sp > INT16_MAX) { + WBUFW(buf,55) = status->sp/(status->max_sp/100); + WBUFW(buf,57) = 100; + } else { + WBUFW(buf,55)=status->sp; + WBUFW(buf,57)=status->max_sp; + } + WBUFL(buf,59)=hd->homunculus.exp; + if( ((m_class&HOM_REG) && hd->homunculus.level >= battle_config.hom_max_level) || ((m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level) ) + WBUFL(buf,63)=0; + else + WBUFL(buf,63)=hd->exp_next; + WBUFW(buf,67)=hd->homunculus.skillpts; + WBUFW(buf,69)=status_get_range(&hd->bl); + clif_send(buf,packet_len(0x22e),&sd->bl,SELF); } @@ -1459,87 +1476,84 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) /// 3 = accessory? /// ? = ignored void clif_send_homdata(struct map_session_data *sd, int state, int param) -{ - //[orn] - int fd = sd->fd; +{ //[orn] + int fd = sd->fd; - if ((state == SP_INTIMATE) && (param >= 910) && (sd->hd->homunculus.class_ == sd->hd->homunculusDB->evo_class)) - merc_hom_calc_skilltree(sd->hd, 0); + if ( (state == SP_INTIMATE) && (param >= 910) && (sd->hd->homunculus.class_ == sd->hd->homunculusDB->evo_class) ) + merc_hom_calc_skilltree(sd->hd, 0); - WFIFOHEAD(fd, packet_len(0x230)); - WFIFOW(fd,0)=0x230; - WFIFOB(fd,2)=0; - WFIFOB(fd,3)=state; - WFIFOL(fd,4)=sd->hd->bl.id; - WFIFOL(fd,8)=param; - WFIFOSET(fd,packet_len(0x230)); + WFIFOHEAD(fd, packet_len(0x230)); + WFIFOW(fd,0)=0x230; + WFIFOB(fd,2)=0; + WFIFOB(fd,3)=state; + WFIFOL(fd,4)=sd->hd->bl.id; + WFIFOL(fd,8)=param; + WFIFOSET(fd,packet_len(0x230)); } int clif_homskillinfoblock(struct map_session_data *sd) -{ - //[orn] - struct homun_data *hd; - int fd = sd->fd; - int i,j,len=4,id; - WFIFOHEAD(fd, 4+37*MAX_HOMUNSKILL); - - hd = sd->hd; - if (!hd) - return 0 ; - - WFIFOW(fd,0)=0x235; - for (i = 0; i < MAX_HOMUNSKILL; i++) { - if ((id = hd->homunculus.hskill[i].id) != 0) { - j = id - HM_SKILLBASE; - WFIFOW(fd,len) = id; - WFIFOW(fd,len+2) = skill_get_inf(id); - WFIFOW(fd,len+4) = 0; - WFIFOW(fd,len+6) = hd->homunculus.hskill[j].lv; - WFIFOW(fd,len+8) = skill_get_sp(id,hd->homunculus.hskill[j].lv); - WFIFOW(fd,len+10)= skill_get_range2(&sd->hd->bl, id,hd->homunculus.hskill[j].lv); - safestrncpy((char *)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); - WFIFOB(fd,len+36) = (hd->homunculus.hskill[j].lv < merc_skill_tree_get_max(id, hd->homunculus.class_))?1:0; - len+=37; - } - } - WFIFOW(fd,2)=len; - WFIFOSET(fd,len); - - return 0; +{ //[orn] + struct homun_data *hd; + int fd = sd->fd; + int i,j,len=4,id; + WFIFOHEAD(fd, 4+37*MAX_HOMUNSKILL); + + hd = sd->hd; + if ( !hd ) + return 0 ; + + WFIFOW(fd,0)=0x235; + for ( i = 0; i < MAX_HOMUNSKILL; i++){ + if( (id = hd->homunculus.hskill[i].id) != 0 ){ + j = id - HM_SKILLBASE; + WFIFOW(fd,len ) = id; + WFIFOW(fd,len+2) = skill_get_inf(id); + WFIFOW(fd,len+4) = 0; + WFIFOW(fd,len+6) = hd->homunculus.hskill[j].lv; + WFIFOW(fd,len+8) = skill_get_sp(id,hd->homunculus.hskill[j].lv); + WFIFOW(fd,len+10)= skill_get_range2(&sd->hd->bl, id,hd->homunculus.hskill[j].lv); + safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); + WFIFOB(fd,len+36) = (hd->homunculus.hskill[j].lv < merc_skill_tree_get_max(id, hd->homunculus.class_))?1:0; + len+=37; + } + } + WFIFOW(fd,2)=len; + WFIFOSET(fd,len); + + return 0; } void clif_homskillup(struct map_session_data *sd, int skill_num) -{ - //[orn] - struct homun_data *hd; - int fd, skillid; - nullpo_retv(sd); - skillid = skill_num - HM_SKILLBASE; +{ //[orn] + struct homun_data *hd; + int fd, skillid; + nullpo_retv(sd); + skillid = skill_num - HM_SKILLBASE; - fd=sd->fd; - hd=sd->hd; + fd=sd->fd; + hd=sd->hd; - WFIFOHEAD(fd, packet_len(0x239)); - WFIFOW(fd,0) = 0x239; - WFIFOW(fd,2) = skill_num; - WFIFOW(fd,4) = hd->homunculus.hskill[skillid].lv; - WFIFOW(fd,6) = skill_get_sp(skill_num,hd->homunculus.hskill[skillid].lv); - WFIFOW(fd,8) = skill_get_range2(&hd->bl, skill_num,hd->homunculus.hskill[skillid].lv); - WFIFOB(fd,10) = (hd->homunculus.hskill[skillid].lv < skill_get_max(hd->homunculus.hskill[skillid].id)) ? 1 : 0; - WFIFOSET(fd,packet_len(0x239)); + WFIFOHEAD(fd, packet_len(0x239)); + WFIFOW(fd,0) = 0x239; + WFIFOW(fd,2) = skill_num; + WFIFOW(fd,4) = hd->homunculus.hskill[skillid].lv; + WFIFOW(fd,6) = skill_get_sp(skill_num,hd->homunculus.hskill[skillid].lv); + WFIFOW(fd,8) = skill_get_range2(&hd->bl, skill_num,hd->homunculus.hskill[skillid].lv); + WFIFOB(fd,10) = (hd->homunculus.hskill[skillid].lv < skill_get_max(hd->homunculus.hskill[skillid].id)) ? 1 : 0; + WFIFOSET(fd,packet_len(0x239)); } -int clif_hom_food(struct map_session_data *sd,int foodid,int fail) //[orn] +int clif_hom_food(struct map_session_data *sd,int foodid,int fail) //[orn] { - int fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x22f)); - WFIFOW(fd,0)=0x22f; - WFIFOB(fd,2)=fail; - WFIFOW(fd,3)=foodid; - WFIFOSET(fd,packet_len(0x22f)); + int fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x22f)); + WFIFOW(fd,0)=0x22f; + WFIFOB(fd,2)=fail; + WFIFOW(fd,3)=foodid; + WFIFOSET(fd,packet_len(0x22f)); - return 0; + return 0; } @@ -1547,54 +1561,57 @@ int clif_hom_food(struct map_session_data *sd,int foodid,int fail) //[orn] /// 0087 <walk start time>.L <walk data>.6B void clif_walkok(struct map_session_data *sd) { - int fd=sd->fd; + int fd=sd->fd; - WFIFOHEAD(fd, packet_len(0x87)); - WFIFOW(fd,0)=0x87; - WFIFOL(fd,2)=gettick(); - WFIFOPOS2(fd,6,sd->bl.x,sd->bl.y,sd->ud.to_x,sd->ud.to_y,8,8); - WFIFOSET(fd,packet_len(0x87)); + WFIFOHEAD(fd, packet_len(0x87)); + WFIFOW(fd,0)=0x87; + WFIFOL(fd,2)=gettick(); + WFIFOPOS2(fd,6,sd->bl.x,sd->bl.y,sd->ud.to_x,sd->ud.to_y,8,8); + WFIFOSET(fd,packet_len(0x87)); } static void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *ud) { - uint8 buf[128]; - int len; - - len = clif_set_unit_walking(bl,ud,buf); - clif_send(buf,len,bl,AREA_WOS); - if (disguised(bl)) - clif_setdisguise(bl, buf, len); - - if (vd->cloth_color) - clif_refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); - - switch (bl->type) { - case BL_PC: { - TBL_PC *sd = ((TBL_PC *)bl); - // clif_movepc(sd); - if (sd->state.size==SZ_BIG) // tiny/big players [Valaris] - clif_specialeffect(&sd->bl,423,AREA); - else if (sd->state.size==SZ_MEDIUM) - clif_specialeffect(&sd->bl,421,AREA); - } - break; - case BL_MOB: { - TBL_MOB *md = ((TBL_MOB *)bl); - if (md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] - clif_specialeffect(&md->bl,423,AREA); - else if (md->special_state.size==SZ_MEDIUM) - clif_specialeffect(&md->bl,421,AREA); - } - break; - case BL_PET: - if (vd->head_bottom) { - // needed to display pet equip properly - clif_pet_equip_area((TBL_PET *)bl); - } - break; - } + uint8 buf[128]; + int len; + + len = clif_set_unit_walking(bl,ud,buf); + clif_send(buf,len,bl,AREA_WOS); + if (disguised(bl)) + clif_setdisguise(bl, buf, len); + + if(vd->cloth_color) + clif_refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); + + switch(bl->type) + { + case BL_PC: + { + TBL_PC *sd = ((TBL_PC*)bl); +// clif_movepc(sd); + if(sd->state.size==SZ_BIG) // tiny/big players [Valaris] + clif_specialeffect(&sd->bl,423,AREA); + else if(sd->state.size==SZ_MEDIUM) + clif_specialeffect(&sd->bl,421,AREA); + } + break; + case BL_MOB: + { + TBL_MOB *md = ((TBL_MOB*)bl); + if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] + clif_specialeffect(&md->bl,423,AREA); + else if(md->special_state.size==SZ_MEDIUM) + clif_specialeffect(&md->bl,421,AREA); + } + break; + case BL_PET: + if( vd->head_bottom ) + {// needed to display pet equip properly + clif_pet_equip_area((TBL_PET*)bl); + } + break; + } } @@ -1603,37 +1620,38 @@ static void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_ /// Note: unit must not be self void clif_move(struct unit_data *ud) { - unsigned char buf[16]; - struct view_data *vd; - struct block_list *bl = ud->bl; - - vd = status_get_viewdata(bl); - if (!vd || vd->class_ == INVISIBLE_CLASS) - return; //This performance check is needed to keep GM-hidden objects from being notified to bots. - - /** - * Hide NPC from maya purple card. - **/ - if (bl->type == BL_NPC && !((TBL_NPC *)bl)->chat_id && (((TBL_NPC *)bl)->sc.option&OPTION_INVISIBLE)) - return; - - if (ud->state.speed_changed) { - // Since we don't know how to update the speed of other objects, - // use the old walk packet to update the data. - ud->state.speed_changed = 0; - clif_move2(bl, vd, ud); - return; - } - - WBUFW(buf,0)=0x86; - WBUFL(buf,2)=bl->id; - WBUFPOS2(buf,6,bl->x,bl->y,ud->to_x,ud->to_y,8,8); - WBUFL(buf,12)=gettick(); - clif_send(buf, packet_len(0x86), bl, AREA_WOS); - if (disguised(bl)) { - WBUFL(buf,2)=-bl->id; - clif_send(buf, packet_len(0x86), bl, SELF); - } + unsigned char buf[16]; + struct view_data* vd; + struct block_list* bl = ud->bl; + + vd = status_get_viewdata(bl); + if (!vd || vd->class_ == INVISIBLE_CLASS) + return; //This performance check is needed to keep GM-hidden objects from being notified to bots. + + /** + * Hide NPC from maya purple card. + **/ + if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE)) + return; + + if (ud->state.speed_changed) { + // Since we don't know how to update the speed of other objects, + // use the old walk packet to update the data. + ud->state.speed_changed = 0; + clif_move2(bl, vd, ud); + return; + } + + WBUFW(buf,0)=0x86; + WBUFL(buf,2)=bl->id; + WBUFPOS2(buf,6,bl->x,bl->y,ud->to_x,ud->to_y,8,8); + WBUFL(buf,12)=gettick(); + clif_send(buf, packet_len(0x86), bl, AREA_WOS); + if (disguised(bl)) + { + WBUFL(buf,2)=-bl->id; + clif_send(buf, packet_len(0x86), bl, SELF); + } } @@ -1642,12 +1660,12 @@ void clif_move(struct unit_data *ud) *------------------------------------------*/ static int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd = NULL; + struct map_session_data *sd = NULL; - //Remove player from map server - if ((sd = map_id2sd(id)) != NULL && sd->fd == 0) //Should be a disconnected player. - map_quit(sd); - return 0; + //Remove player from map server + if ((sd = map_id2sd(id)) != NULL && sd->fd == 0) //Should be a disconnected player. + map_quit(sd); + return 0; } /*========================================== @@ -1655,59 +1673,59 @@ static int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ void clif_quitsave(int fd,struct map_session_data *sd) { - if (!battle_config.prevent_logout || - DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) - map_quit(sd); - else if (sd->fd) { - //Disassociate session from player (session is deleted after this function was called) - //And set a timer to make him quit later. - session[sd->fd]->session_data = NULL; - sd->fd = 0; - add_timer(gettick() + 10000, clif_delayquit, sd->bl.id, 0); - } + if (!battle_config.prevent_logout || + DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) + map_quit(sd); + else if (sd->fd) + { //Disassociate session from player (session is deleted after this function was called) + //And set a timer to make him quit later. + session[sd->fd]->session_data = NULL; + sd->fd = 0; + add_timer(gettick() + 10000, clif_delayquit, sd->bl.id, 0); + } } /// Notifies the client of a position change to coordinates on given map (ZC_NPCACK_MAPMOVE). /// 0091 <map name>.16B <x>.W <y>.W void clif_changemap(struct map_session_data *sd, short map, int x, int y) { - int fd; - nullpo_retv(sd); - fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x91)); - WFIFOW(fd,0) = 0x91; - mapindex_getmapname_ext(mapindex_id2name(map), (char *)WFIFOP(fd,2)); - WFIFOW(fd,18) = x; - WFIFOW(fd,20) = y; - WFIFOSET(fd,packet_len(0x91)); + WFIFOHEAD(fd,packet_len(0x91)); + WFIFOW(fd,0) = 0x91; + mapindex_getmapname_ext(mapindex_id2name(map), (char*)WFIFOP(fd,2)); + WFIFOW(fd,18) = x; + WFIFOW(fd,20) = y; + WFIFOSET(fd,packet_len(0x91)); } /// Notifies the client of a position change to coordinates on given map, which is on another map-server (ZC_NPCACK_SERVERMOVE). /// 0092 <map name>.16B <x>.W <y>.W <ip>.L <port>.W -void clif_changemapserver(struct map_session_data *sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port) +void clif_changemapserver(struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port) { - int fd; - nullpo_retv(sd); - fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x92)); - WFIFOW(fd,0) = 0x92; - mapindex_getmapname_ext(mapindex_id2name(map_index), (char *)WFIFOP(fd,2)); - WFIFOW(fd,18) = x; - WFIFOW(fd,20) = y; - WFIFOL(fd,22) = htonl(ip); - WFIFOW(fd,26) = ntows(htons(port)); // [!] LE byte order here [!] - WFIFOSET(fd,packet_len(0x92)); + WFIFOHEAD(fd,packet_len(0x92)); + WFIFOW(fd,0) = 0x92; + mapindex_getmapname_ext(mapindex_id2name(map_index), (char*)WFIFOP(fd,2)); + WFIFOW(fd,18) = x; + WFIFOW(fd,20) = y; + WFIFOL(fd,22) = htonl(ip); + WFIFOW(fd,26) = ntows(htons(port)); // [!] LE byte order here [!] + WFIFOSET(fd,packet_len(0x92)); } void clif_blown(struct block_list *bl) { - //Aegis packets says fixpos, but it's unsure whether slide works better or not. - // clif_fixpos(bl); - clif_slide(bl, bl->x, bl->y); +//Aegis packets says fixpos, but it's unsure whether slide works better or not. +// clif_fixpos(bl); + clif_slide(bl, bl->x, bl->y); } @@ -1717,35 +1735,36 @@ void clif_blown(struct block_list *bl) /// 0088 <id>.L <x>.W <y>.W void clif_fixpos(struct block_list *bl) { - unsigned char buf[10]; - nullpo_retv(bl); + unsigned char buf[10]; + nullpo_retv(bl); - WBUFW(buf,0) = 0x88; - WBUFL(buf,2) = bl->id; - WBUFW(buf,6) = bl->x; - WBUFW(buf,8) = bl->y; - clif_send(buf, packet_len(0x88), bl, AREA); + WBUFW(buf,0) = 0x88; + WBUFL(buf,2) = bl->id; + WBUFW(buf,6) = bl->x; + WBUFW(buf,8) = bl->y; + clif_send(buf, packet_len(0x88), bl, AREA); - if (disguised(bl)) { - WBUFL(buf,2) = -bl->id; - clif_send(buf, packet_len(0x88), bl, SELF); - } + if( disguised(bl) ) + { + WBUFL(buf,2) = -bl->id; + clif_send(buf, packet_len(0x88), bl, SELF); + } } /// Displays the buy/sell dialog of an NPC shop (ZC_SELECT_DEALTYPE). /// 00c4 <shop id>.L -void clif_npcbuysell(struct map_session_data *sd, int id) +void clif_npcbuysell(struct map_session_data* sd, int id) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd, packet_len(0xc4)); - WFIFOW(fd,0)=0xc4; - WFIFOL(fd,2)=id; - WFIFOSET(fd,packet_len(0xc4)); + fd=sd->fd; + WFIFOHEAD(fd, packet_len(0xc4)); + WFIFOW(fd,0)=0xc4; + WFIFOL(fd,2)=id; + WFIFOSET(fd,packet_len(0xc4)); } @@ -1753,30 +1772,31 @@ void clif_npcbuysell(struct map_session_data *sd, int id) /// 00c6 <packet len>.W { <price>.L <discount price>.L <item type>.B <name id>.W }* void clif_buylist(struct map_session_data *sd, struct npc_data *nd) { - int fd,i,c; + int fd,i,c; - nullpo_retv(sd); - nullpo_retv(nd); - - fd = sd->fd; - WFIFOHEAD(fd, 4 + nd->u.shop.count * 11); - WFIFOW(fd,0) = 0xc6; - - c = 0; - for (i = 0; i < nd->u.shop.count; i++) { - struct item_data *id = itemdb_exists(nd->u.shop.shop_item[i].nameid); - int val = nd->u.shop.shop_item[i].value; - if (id == NULL) - continue; - WFIFOL(fd, 4+c*11) = val; - WFIFOL(fd, 8+c*11) = pc_modifybuyvalue(sd,val); - WFIFOB(fd,12+c*11) = itemtype(id->type); - WFIFOW(fd,13+c*11) = (id->view_id > 0) ? id->view_id : id->nameid; - c++; - } + nullpo_retv(sd); + nullpo_retv(nd); - WFIFOW(fd,2) = 4 + c*11; - WFIFOSET(fd,WFIFOW(fd,2)); + fd = sd->fd; + WFIFOHEAD(fd, 4 + nd->u.shop.count * 11); + WFIFOW(fd,0) = 0xc6; + + c = 0; + for( i = 0; i < nd->u.shop.count; i++ ) + { + struct item_data* id = itemdb_exists(nd->u.shop.shop_item[i].nameid); + int val = nd->u.shop.shop_item[i].value; + if( id == NULL ) + continue; + WFIFOL(fd, 4+c*11) = val; + WFIFOL(fd, 8+c*11) = pc_modifybuyvalue(sd,val); + WFIFOB(fd,12+c*11) = itemtype(id->type); + WFIFOW(fd,13+c*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid; + c++; + } + + WFIFOW(fd,2) = 4 + c*11; + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -1784,32 +1804,34 @@ void clif_buylist(struct map_session_data *sd, struct npc_data *nd) /// 00c7 <packet len>.W { <index>.W <price>.L <overcharge price>.L }* void clif_selllist(struct map_session_data *sd) { - int fd,i,c=0,val; + int fd,i,c=0,val; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd, MAX_INVENTORY * 10 + 4); - WFIFOW(fd,0)=0xc7; - for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i]) { - if (!itemdb_cansell(&sd->status.inventory[i], pc_get_group_level(sd))) - continue; - - if (sd->status.inventory[i].expire_time) - continue; // Cannot Sell Rental Items - - val=sd->inventory_data[i]->value_sell; - if (val < 0) - continue; - WFIFOW(fd,4+c*10)=i+2; - WFIFOL(fd,6+c*10)=val; - WFIFOL(fd,10+c*10)=pc_modifysellvalue(sd,val); - c++; - } - } - WFIFOW(fd,2)=c*10+4; - WFIFOSET(fd,WFIFOW(fd,2)); + fd=sd->fd; + WFIFOHEAD(fd, MAX_INVENTORY * 10 + 4); + WFIFOW(fd,0)=0xc7; + for( i = 0; i < MAX_INVENTORY; i++ ) + { + if( sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] ) + { + if( !itemdb_cansell(&sd->status.inventory[i], pc_get_group_level(sd)) ) + continue; + + if( sd->status.inventory[i].expire_time ) + continue; // Cannot Sell Rental Items + + val=sd->inventory_data[i]->value_sell; + if( val < 0 ) + continue; + WFIFOW(fd,4+c*10)=i+2; + WFIFOL(fd,6+c*10)=val; + WFIFOL(fd,10+c*10)=pc_modifysellvalue(sd,val); + c++; + } + } + WFIFOW(fd,2)=c*10+4; + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -1823,15 +1845,15 @@ void clif_selllist(struct map_session_data *sd) /// - append this text void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) { - int fd = sd->fd; - int slen = strlen(mes) + 9; + int fd = sd->fd; + int slen = strlen(mes) + 9; - WFIFOHEAD(fd, slen); - WFIFOW(fd,0)=0xb4; - WFIFOW(fd,2)=slen; - WFIFOL(fd,4)=npcid; - memcpy((char *)WFIFOP(fd,8), mes, slen-8); - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOHEAD(fd, slen); + WFIFOW(fd,0)=0xb4; + WFIFOW(fd,2)=slen; + WFIFOL(fd,4)=npcid; + memcpy((char*)WFIFOP(fd,8), mes, slen-8); + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -1847,15 +1869,15 @@ void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) /// - remove 'next' button void clif_scriptnext(struct map_session_data *sd,int npcid) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd, packet_len(0xb5)); - WFIFOW(fd,0)=0xb5; - WFIFOL(fd,2)=npcid; - WFIFOSET(fd,packet_len(0xb5)); + fd=sd->fd; + WFIFOHEAD(fd, packet_len(0xb5)); + WFIFOW(fd,0)=0xb5; + WFIFOL(fd,2)=npcid; + WFIFOSET(fd,packet_len(0xb5)); } @@ -1876,15 +1898,15 @@ void clif_scriptnext(struct map_session_data *sd,int npcid) /// - 0146 <npcid of dialog window>.L void clif_scriptclose(struct map_session_data *sd, int npcid) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd, packet_len(0xb6)); - WFIFOW(fd,0)=0xb6; - WFIFOL(fd,2)=npcid; - WFIFOSET(fd,packet_len(0xb6)); + fd=sd->fd; + WFIFOHEAD(fd, packet_len(0xb6)); + WFIFOW(fd,0)=0xb6; + WFIFOL(fd,2)=npcid; + WFIFOSET(fd,packet_len(0xb6)); } /*========================================== @@ -1892,24 +1914,24 @@ void clif_scriptclose(struct map_session_data *sd, int npcid) *------------------------------------------*/ void clif_sendfakenpc(struct map_session_data *sd, int npcid) { - unsigned char *buf; - int fd = sd->fd; - sd->state.using_fake_npc = 1; + unsigned char *buf; + int fd = sd->fd; + sd->state.using_fake_npc = 1; - WFIFOHEAD(fd, packet_len(0x78)); - buf = WFIFOP(fd,0); - memset(WBUFP(buf,0), 0, packet_len(0x78)); - WBUFW(buf,0)=0x78; + WFIFOHEAD(fd, packet_len(0x78)); + buf = WFIFOP(fd,0); + memset(WBUFP(buf,0), 0, packet_len(0x78)); + WBUFW(buf,0)=0x78; #if PACKETVER >= 20071106 - WBUFB(buf,2) = 0; // object type - buf = WFIFOP(fd,1); + WBUFB(buf,2) = 0; // object type + buf = WFIFOP(fd,1); #endif - WBUFL(buf,2)=npcid; - WBUFW(buf,14)=111; - WBUFPOS(buf,46,sd->bl.x,sd->bl.y,sd->ud.dir); - WBUFB(buf,49)=5; - WBUFB(buf,50)=5; - WFIFOSET(fd, packet_len(0x78)); + WBUFL(buf,2)=npcid; + WBUFW(buf,14)=111; + WBUFPOS(buf,46,sd->bl.x,sd->bl.y,sd->ud.dir); + WBUFB(buf,49)=5; + WBUFB(buf,50)=5; + WFIFOSET(fd, packet_len(0x78)); } @@ -1933,23 +1955,23 @@ void clif_sendfakenpc(struct map_session_data *sd, int npcid) /// WARNING: the 'cancel' button closes other windows besides the dialog window and the menu window. /// Which suggests their have intertwined behavior. (probably the mouse targeting) /// TODO investigate behavior of other windows [FlavioJS] -void clif_scriptmenu(struct map_session_data *sd, int npcid, const char *mes) +void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes) { - int fd = sd->fd; - int slen = strlen(mes) + 9; - struct block_list *bl = NULL; + int fd = sd->fd; + int slen = strlen(mes) + 9; + struct block_list *bl = NULL; - if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = map_id2bl(npcid)) && (bl->m!=sd->bl.m || - bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || - bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)))) - clif_sendfakenpc(sd, npcid); + if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = map_id2bl(npcid)) && (bl->m!=sd->bl.m || + bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || + bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)))) + clif_sendfakenpc(sd, npcid); - WFIFOHEAD(fd, slen); - WFIFOW(fd,0)=0xb7; - WFIFOW(fd,2)=slen; - WFIFOL(fd,4)=npcid; - memcpy((char *)WFIFOP(fd,8), mes, slen-8); - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOHEAD(fd, slen); + WFIFOW(fd,0)=0xb7; + WFIFOW(fd,2)=slen; + WFIFOL(fd,4)=npcid; + memcpy((char*)WFIFOP(fd,8), mes, slen-8); + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -1966,21 +1988,21 @@ void clif_scriptmenu(struct map_session_data *sd, int npcid, const char *mes) /// - close inputnum window void clif_scriptinput(struct map_session_data *sd, int npcid) { - int fd; - struct block_list *bl = NULL; + int fd; + struct block_list *bl = NULL; - nullpo_retv(sd); + nullpo_retv(sd); - if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = map_id2bl(npcid)) && (bl->m!=sd->bl.m || - bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || - bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)))) - clif_sendfakenpc(sd, npcid); + if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = map_id2bl(npcid)) && (bl->m!=sd->bl.m || + bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || + bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)))) + clif_sendfakenpc(sd, npcid); - fd=sd->fd; - WFIFOHEAD(fd, packet_len(0x142)); - WFIFOW(fd,0)=0x142; - WFIFOL(fd,2)=npcid; - WFIFOSET(fd,packet_len(0x142)); + fd=sd->fd; + WFIFOHEAD(fd, packet_len(0x142)); + WFIFOW(fd,0)=0x142; + WFIFOL(fd,2)=npcid; + WFIFOSET(fd,packet_len(0x142)); } @@ -1997,21 +2019,21 @@ void clif_scriptinput(struct map_session_data *sd, int npcid) /// - close inputstr window void clif_scriptinputstr(struct map_session_data *sd, int npcid) { - int fd; - struct block_list *bl = NULL; + int fd; + struct block_list *bl = NULL; - nullpo_retv(sd); + nullpo_retv(sd); - if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = map_id2bl(npcid)) && (bl->m!=sd->bl.m || - bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || - bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)))) - clif_sendfakenpc(sd, npcid); + if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = map_id2bl(npcid)) && (bl->m!=sd->bl.m || + bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || + bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)))) + clif_sendfakenpc(sd, npcid); - fd=sd->fd; - WFIFOHEAD(fd, packet_len(0x1d4)); - WFIFOW(fd,0)=0x1d4; - WFIFOL(fd,2)=npcid; - WFIFOSET(fd,packet_len(0x1d4)); + fd=sd->fd; + WFIFOHEAD(fd, packet_len(0x1d4)); + WFIFOW(fd,0)=0x1d4; + WFIFOL(fd,2)=npcid; + WFIFOSET(fd,packet_len(0x1d4)); } @@ -2027,20 +2049,20 @@ void clif_scriptinputstr(struct map_session_data *sd, int npcid) /// 0x00RRGGBB void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, int y, int id, int color) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd, packet_len(0x144)); - WFIFOW(fd,0)=0x144; - WFIFOL(fd,2)=npc_id; - WFIFOL(fd,6)=type; - WFIFOL(fd,10)=x; - WFIFOL(fd,14)=y; - WFIFOB(fd,18)=id; - WFIFOL(fd,19)=color; - WFIFOSET(fd,packet_len(0x144)); + fd=sd->fd; + WFIFOHEAD(fd, packet_len(0x144)); + WFIFOW(fd,0)=0x144; + WFIFOL(fd,2)=npc_id; + WFIFOL(fd,6)=type; + WFIFOL(fd,10)=x; + WFIFOL(fd,14)=y; + WFIFOB(fd,18)=id; + WFIFOL(fd,19)=color; + WFIFOSET(fd,packet_len(0x144)); } @@ -2053,72 +2075,72 @@ void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, in /// 2 = bottom right corner /// 3 = middle of screen, inside a movable window /// 4 = middle of screen, movable with a close button, chrome-less -void clif_cutin(struct map_session_data *sd, const char *image, int type) +void clif_cutin(struct map_session_data* sd, const char* image, int type) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd, packet_len(0x1b3)); - WFIFOW(fd,0)=0x1b3; - strncpy((char *)WFIFOP(fd,2),image,64); - WFIFOB(fd,66)=type; - WFIFOSET(fd,packet_len(0x1b3)); + fd=sd->fd; + WFIFOHEAD(fd, packet_len(0x1b3)); + WFIFOW(fd,0)=0x1b3; + strncpy((char*)WFIFOP(fd,2),image,64); + WFIFOB(fd,66)=type; + WFIFOSET(fd,packet_len(0x1b3)); } /*========================================== * Fills in card data from the given item and into the buffer. [Skotlex] *------------------------------------------*/ -static void clif_addcards(unsigned char *buf, struct item *item) -{ - int i=0,j; - if (item == NULL) { //Blank data - WBUFW(buf,0) = 0; - WBUFW(buf,2) = 0; - WBUFW(buf,4) = 0; - WBUFW(buf,6) = 0; - return; - } - if (item->card[0] == CARD0_PET) { //pet eggs - WBUFW(buf,0) = 0; - WBUFW(buf,2) = 0; - WBUFW(buf,4) = 0; - WBUFW(buf,6) = item->card[3]; //Pet renamed flag. - return; - } - if (item->card[0] == CARD0_FORGE || item->card[0] == CARD0_CREATE) { //Forged/created items - WBUFW(buf,0) = item->card[0]; - WBUFW(buf,2) = item->card[1]; - WBUFW(buf,4) = item->card[2]; - WBUFW(buf,6) = item->card[3]; - return; - } - //Client only receives four cards.. so randomly send them a set of cards. [Skotlex] - if (MAX_SLOTS > 4 && (j = itemdb_slot(item->nameid)) > 4) - i = rnd()%(j-3); //eg: 6 slots, possible i values: 0->3, 1->4, 2->5 => i = rnd()%3; - - //Normal items. - if (item->card[i] > 0 && (j=itemdb_viewid(item->card[i])) > 0) - WBUFW(buf,0) = j; - else - WBUFW(buf,0) = item->card[i]; - - if (item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0) - WBUFW(buf,2) = j; - else - WBUFW(buf,2) = item->card[i]; - - if (item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0) - WBUFW(buf,4) = j; - else - WBUFW(buf,4) = item->card[i]; - - if (item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0) - WBUFW(buf,6) = j; - else - WBUFW(buf,6) = item->card[i]; +static void clif_addcards(unsigned char* buf, struct item* item) +{ + int i=0,j; + if( item == NULL ) { //Blank data + WBUFW(buf,0) = 0; + WBUFW(buf,2) = 0; + WBUFW(buf,4) = 0; + WBUFW(buf,6) = 0; + return; + } + if( item->card[0] == CARD0_PET ) { //pet eggs + WBUFW(buf,0) = 0; + WBUFW(buf,2) = 0; + WBUFW(buf,4) = 0; + WBUFW(buf,6) = item->card[3]; //Pet renamed flag. + return; + } + if( item->card[0] == CARD0_FORGE || item->card[0] == CARD0_CREATE ) { //Forged/created items + WBUFW(buf,0) = item->card[0]; + WBUFW(buf,2) = item->card[1]; + WBUFW(buf,4) = item->card[2]; + WBUFW(buf,6) = item->card[3]; + return; + } + //Client only receives four cards.. so randomly send them a set of cards. [Skotlex] + if( MAX_SLOTS > 4 && (j = itemdb_slot(item->nameid)) > 4 ) + i = rnd()%(j-3); //eg: 6 slots, possible i values: 0->3, 1->4, 2->5 => i = rnd()%3; + + //Normal items. + if( item->card[i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + WBUFW(buf,0) = j; + else + WBUFW(buf,0) = item->card[i]; + + if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + WBUFW(buf,2) = j; + else + WBUFW(buf,2) = item->card[i]; + + if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + WBUFW(buf,4) = j; + else + WBUFW(buf,4) = item->card[i]; + + if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + WBUFW(buf,6) = j; + else + WBUFW(buf,6) = item->card[i]; } @@ -2128,69 +2150,72 @@ static void clif_addcards(unsigned char *buf, struct item *item) /// 02d4 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK3) void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { - int fd; + int fd; #if PACKETVER < 20061218 - const int cmd = 0xa0; + const int cmd = 0xa0; #elif PACKETVER < 20071002 - const int cmd = 0x29a; + const int cmd = 0x29a; #else - const int cmd = 0x2d4; + const int cmd = 0x2d4; #endif - nullpo_retv(sd); - - fd = sd->fd; - if (!session_isActive(fd)) //Sasuke- - return; - - WFIFOHEAD(fd,packet_len(cmd)); - if (fail) { - WFIFOW(fd,0)=cmd; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=amount; - WFIFOW(fd,6)=0; - WFIFOB(fd,8)=0; - WFIFOB(fd,9)=0; - WFIFOB(fd,10)=0; - WFIFOW(fd,11)=0; - WFIFOW(fd,13)=0; - WFIFOW(fd,15)=0; - WFIFOW(fd,17)=0; - WFIFOW(fd,19)=0; - WFIFOB(fd,21)=0; - WFIFOB(fd,22)=fail; + nullpo_retv(sd); + + fd = sd->fd; + if( !session_isActive(fd) ) //Sasuke- + return; + + WFIFOHEAD(fd,packet_len(cmd)); + if( fail ) + { + WFIFOW(fd,0)=cmd; + WFIFOW(fd,2)=n+2; + WFIFOW(fd,4)=amount; + WFIFOW(fd,6)=0; + WFIFOB(fd,8)=0; + WFIFOB(fd,9)=0; + WFIFOB(fd,10)=0; + WFIFOW(fd,11)=0; + WFIFOW(fd,13)=0; + WFIFOW(fd,15)=0; + WFIFOW(fd,17)=0; + WFIFOW(fd,19)=0; + WFIFOB(fd,21)=0; + WFIFOB(fd,22)=fail; #if PACKETVER >= 20061218 - WFIFOL(fd,23)=0; + WFIFOL(fd,23)=0; #endif #if PACKETVER >= 20071002 - WFIFOW(fd,27)=0; // unknown + WFIFOW(fd,27)=0; // unknown #endif - } else { - if (n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <=0 || sd->inventory_data[n] == NULL) - return; - - WFIFOW(fd,0)=cmd; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=amount; - if (sd->inventory_data[n]->view_id > 0) - WFIFOW(fd,6)=sd->inventory_data[n]->view_id; - else - WFIFOW(fd,6)=sd->status.inventory[n].nameid; - WFIFOB(fd,8)=sd->status.inventory[n].identify; - WFIFOB(fd,9)=sd->status.inventory[n].attribute; - WFIFOB(fd,10)=sd->status.inventory[n].refine; - clif_addcards(WFIFOP(fd,11), &sd->status.inventory[n]); - WFIFOW(fd,19)=pc_equippoint(sd,n); - WFIFOB(fd,21)=itemtype(sd->inventory_data[n]->type); - WFIFOB(fd,22)=fail; + } + else + { + if( n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <=0 || sd->inventory_data[n] == NULL ) + return; + + WFIFOW(fd,0)=cmd; + WFIFOW(fd,2)=n+2; + WFIFOW(fd,4)=amount; + if (sd->inventory_data[n]->view_id > 0) + WFIFOW(fd,6)=sd->inventory_data[n]->view_id; + else + WFIFOW(fd,6)=sd->status.inventory[n].nameid; + WFIFOB(fd,8)=sd->status.inventory[n].identify; + WFIFOB(fd,9)=sd->status.inventory[n].attribute; + WFIFOB(fd,10)=sd->status.inventory[n].refine; + clif_addcards(WFIFOP(fd,11), &sd->status.inventory[n]); + WFIFOW(fd,19)=pc_equippoint(sd,n); + WFIFOB(fd,21)=itemtype(sd->inventory_data[n]->type); + WFIFOB(fd,22)=fail; #if PACKETVER >= 20061218 - WFIFOL(fd,23)=sd->status.inventory[n].expire_time; + WFIFOL(fd,23)=sd->status.inventory[n].expire_time; #endif #if PACKETVER >= 20071002 - WFIFOW(fd,27)=0; // unknown + WFIFOW(fd,27)=0; // unknown #endif - } + } - WFIFOSET(fd,packet_len(cmd)); + WFIFOSET(fd,packet_len(cmd)); } @@ -2198,16 +2223,16 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) /// 00af <index>.W <amount>.W void clif_dropitem(struct map_session_data *sd,int n,int amount) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd, packet_len(0xaf)); - WFIFOW(fd,0)=0xaf; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=amount; - WFIFOSET(fd,packet_len(0xaf)); + fd=sd->fd; + WFIFOHEAD(fd, packet_len(0xaf)); + WFIFOW(fd,0)=0xaf; + WFIFOW(fd,2)=n+2; + WFIFOW(fd,4)=amount; + WFIFOSET(fd,packet_len(0xaf)); } @@ -2225,20 +2250,20 @@ void clif_dropitem(struct map_session_data *sd,int n,int amount) void clif_delitem(struct map_session_data *sd,int n,int amount, short reason) { #if PACKETVER < 20091117 - clif_dropitem(sd,n,amount); + clif_dropitem(sd,n,amount); #else - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; + fd=sd->fd; - WFIFOHEAD(fd, packet_len(0x7fa)); - WFIFOW(fd,0)=0x7fa; - WFIFOW(fd,2)=reason; - WFIFOW(fd,4)=n+2; - WFIFOW(fd,6)=amount; - WFIFOSET(fd,packet_len(0x7fa)); + WFIFOHEAD(fd, packet_len(0x7fa)); + WFIFOW(fd,0)=0x7fa; + WFIFOW(fd,2)=reason; + WFIFOW(fd,4)=n+2; + WFIFOW(fd,6)=amount; + WFIFOSET(fd,packet_len(0x7fa)); #endif } @@ -2248,323 +2273,335 @@ void clif_delitem(struct map_session_data *sd,int n,int amount, short reason) // armor/egg) -1 for stackable items, -2 for stackable items where arrows must send in the equip-point. void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data *id, int equip) { - if (id->view_id > 0) - WBUFW(buf,n)=id->view_id; - else - WBUFW(buf,n)=i->nameid; - WBUFB(buf,n+2)=itemtype(id->type); - WBUFB(buf,n+3)=i->identify; - if (equip >= 0) { //Equippable item - WBUFW(buf,n+4)=equip; - WBUFW(buf,n+6)=i->equip; - WBUFB(buf,n+8)=i->attribute; - WBUFB(buf,n+9)=i->refine; - } else { //Stackable item. - WBUFW(buf,n+4)=i->amount; - if (equip == -2 && id->equip == EQP_AMMO) - WBUFW(buf,n+6)=EQP_AMMO; - else - WBUFW(buf,n+6)=0; - } - -} -void clif_favorite_item(struct map_session_data *sd, unsigned short index); + if (id->view_id > 0) + WBUFW(buf,n)=id->view_id; + else + WBUFW(buf,n)=i->nameid; + WBUFB(buf,n+2)=itemtype(id->type); + WBUFB(buf,n+3)=i->identify; + if (equip >= 0) { //Equippable item + WBUFW(buf,n+4)=equip; + WBUFW(buf,n+6)=i->equip; + WBUFB(buf,n+8)=i->attribute; + WBUFB(buf,n+9)=i->refine; + } else { //Stackable item. + WBUFW(buf,n+4)=i->amount; + if (equip == -2 && id->equip == EQP_AMMO) + WBUFW(buf,n+6)=EQP_AMMO; + else + WBUFW(buf,n+6)=0; + } + +} +void clif_favorite_item(struct map_session_data* sd, unsigned short index); //Unified inventory function which sends all of the inventory (requires two packets, one for equipable items and one for stackable ones. [Skotlex] void clif_inventorylist(struct map_session_data *sd) { - int i,n,ne,arrow=-1; - unsigned char *buf; - unsigned char *bufe; + int i,n,ne,arrow=-1; + unsigned char *buf; + unsigned char *bufe; #if PACKETVER < 5 - const int s = 10; //Entry size. + const int s = 10; //Entry size. #elif PACKETVER < 20080102 - const int s = 18; + const int s = 18; #else - const int s = 22; + const int s = 22; #endif #if PACKETVER < 20071002 - const int se = 20; + const int se = 20; #elif PACKETVER < 20100629 - const int se = 26; + const int se = 26; #else - const int se = 28; + const int se = 28; #endif - buf = (unsigned char *)aMalloc(MAX_INVENTORY * s + 4); - bufe = (unsigned char *)aMalloc(MAX_INVENTORY * se + 4); + buf = (unsigned char*)aMalloc(MAX_INVENTORY * s + 4); + bufe = (unsigned char*)aMalloc(MAX_INVENTORY * se + 4); - for (i = 0, n = 0, ne = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid <=0 || sd->inventory_data[i] == NULL) - continue; + for( i = 0, n = 0, ne = 0; i < MAX_INVENTORY; i++ ) + { + if( sd->status.inventory[i].nameid <=0 || sd->inventory_data[i] == NULL ) + continue; - if (!itemdb_isstackable2(sd->inventory_data[i])) { - //Non-stackable (Equippable) - WBUFW(bufe,ne*se+4)=i+2; - clif_item_sub(bufe, ne*se+6, &sd->status.inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); - clif_addcards(WBUFP(bufe, ne*se+16), &sd->status.inventory[i]); + if( !itemdb_isstackable2(sd->inventory_data[i]) ) + { //Non-stackable (Equippable) + WBUFW(bufe,ne*se+4)=i+2; + clif_item_sub(bufe, ne*se+6, &sd->status.inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); + clif_addcards(WBUFP(bufe, ne*se+16), &sd->status.inventory[i]); #if PACKETVER >= 20071002 - WBUFL(bufe,ne*se+24)=sd->status.inventory[i].expire_time; - WBUFW(bufe,ne*se+28)=0; //Unknown + WBUFL(bufe,ne*se+24)=sd->status.inventory[i].expire_time; + WBUFW(bufe,ne*se+28)=0; //Unknown #endif #if PACKETVER >= 20100629 - if (sd->inventory_data[i]->equip&EQP_VISIBLE) - WBUFW(bufe,ne*se+30)= sd->inventory_data[i]->look; - else - WBUFW(bufe,ne*se+30)=0; + if (sd->inventory_data[i]->equip&EQP_VISIBLE) + WBUFW(bufe,ne*se+30)= sd->inventory_data[i]->look; + else + WBUFW(bufe,ne*se+30)=0; #endif - ne++; - } else { - //Stackable. - WBUFW(buf,n*s+4)=i+2; - clif_item_sub(buf, n*s+6, &sd->status.inventory[i], sd->inventory_data[i], -2); - if (sd->inventory_data[i]->equip == EQP_AMMO && sd->status.inventory[i].equip) - arrow=i; + ne++; + } + else + { //Stackable. + WBUFW(buf,n*s+4)=i+2; + clif_item_sub(buf, n*s+6, &sd->status.inventory[i], sd->inventory_data[i], -2); + if( sd->inventory_data[i]->equip == EQP_AMMO && sd->status.inventory[i].equip ) + arrow=i; #if PACKETVER >= 5 - clif_addcards(WBUFP(buf, n*s+14), &sd->status.inventory[i]); + clif_addcards(WBUFP(buf, n*s+14), &sd->status.inventory[i]); #endif #if PACKETVER >= 20080102 - WBUFL(buf,n*s+22)=sd->status.inventory[i].expire_time; + WBUFL(buf,n*s+22)=sd->status.inventory[i].expire_time; #endif - n++; - } - } - if (n) { + n++; + } + } + if( n ) + { #if PACKETVER < 5 - WBUFW(buf,0)=0xa3; + WBUFW(buf,0)=0xa3; #elif PACKETVER < 20080102 - WBUFW(buf,0)=0x1ee; + WBUFW(buf,0)=0x1ee; #else - WBUFW(buf,0)=0x2e8; + WBUFW(buf,0)=0x2e8; #endif - WBUFW(buf,2)=4+n*s; - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); - } - if (arrow >= 0) - clif_arrowequip(sd,arrow); - - if (ne) { + WBUFW(buf,2)=4+n*s; + clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + } + if( arrow >= 0 ) + clif_arrowequip(sd,arrow); + + if( ne ) + { #if PACKETVER < 20071002 - WBUFW(bufe,0)=0xa4; + WBUFW(bufe,0)=0xa4; #else - WBUFW(bufe,0)=0x2d0; + WBUFW(bufe,0)=0x2d0; #endif - WBUFW(bufe,2)=4+ne*se; - clif_send(bufe, WBUFW(bufe,2), &sd->bl, SELF); - } + WBUFW(bufe,2)=4+ne*se; + clif_send(bufe, WBUFW(bufe,2), &sd->bl, SELF); + } #if PACKETVER >= 20111122 - for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL) - continue; + for( i = 0; i < MAX_INVENTORY; i++ ) { + if( sd->status.inventory[i].nameid <= 0 || sd->inventory_data[i] == NULL ) + continue; - if (sd->status.inventory[i].favorite) - clif_favorite_item(sd, i); - } + if ( sd->status.inventory[i].favorite ) + clif_favorite_item(sd, i); + } #endif - if (buf) aFree(buf); - if (bufe) aFree(bufe); + if( buf ) aFree(buf); + if( bufe ) aFree(bufe); } //Required when items break/get-repaired. Only sends equippable item list. void clif_equiplist(struct map_session_data *sd) { - int i,n,fd = sd->fd; - unsigned char *buf; + int i,n,fd = sd->fd; + unsigned char *buf; #if PACKETVER < 20071002 - const int cmd = 20; + const int cmd = 20; #elif PACKETVER < 20100629 - const int cmd = 26; + const int cmd = 26; #else - const int cmd = 28; + const int cmd = 28; #endif - WFIFOHEAD(fd, MAX_INVENTORY * cmd + 4); - buf = WFIFOP(fd,0); + WFIFOHEAD(fd, MAX_INVENTORY * cmd + 4); + buf = WFIFOP(fd,0); - for (i=0,n=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid <=0 || sd->inventory_data[i] == NULL) - continue; + for(i=0,n=0;i<MAX_INVENTORY;i++){ + if (sd->status.inventory[i].nameid <=0 || sd->inventory_data[i] == NULL) + continue; - if (itemdb_isstackable2(sd->inventory_data[i])) - continue; - //Equippable - WBUFW(buf,n*cmd+4)=i+2; - clif_item_sub(buf, n*cmd+6, &sd->status.inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); - clif_addcards(WBUFP(buf, n*cmd+16), &sd->status.inventory[i]); + if(itemdb_isstackable2(sd->inventory_data[i])) + continue; + //Equippable + WBUFW(buf,n*cmd+4)=i+2; + clif_item_sub(buf, n*cmd+6, &sd->status.inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); + clif_addcards(WBUFP(buf, n*cmd+16), &sd->status.inventory[i]); #if PACKETVER >= 20071002 - WBUFL(buf,n*cmd+24)=sd->status.inventory[i].expire_time; - WBUFW(buf,n*cmd+28)=0; //Unknown + WBUFL(buf,n*cmd+24)=sd->status.inventory[i].expire_time; + WBUFW(buf,n*cmd+28)=0; //Unknown #endif #if PACKETVER >= 20100629 - if (sd->inventory_data[i]->equip&EQP_VISIBLE) - WBUFW(buf,n*cmd+30)= sd->inventory_data[i]->look; - else - WBUFW(buf,n*cmd+30)=0; + if (sd->inventory_data[i]->equip&EQP_VISIBLE) + WBUFW(buf,n*cmd+30)= sd->inventory_data[i]->look; + else + WBUFW(buf,n*cmd+30)=0; #endif - n++; - } - if (n) { + n++; + } + if (n) { #if PACKETVER < 20071002 - WBUFW(buf,0)=0xa4; + WBUFW(buf,0)=0xa4; #else - WBUFW(buf,0)=0x2d0; + WBUFW(buf,0)=0x2d0; #endif - WBUFW(buf,2)=4+n*cmd; - WFIFOSET(fd,WFIFOW(fd,2)); - } + WBUFW(buf,2)=4+n*cmd; + WFIFOSET(fd,WFIFOW(fd,2)); + } } -void clif_storagelist(struct map_session_data *sd, struct item *items, int items_length) +void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length) { - struct item_data *id; - int i,n,ne; - unsigned char *buf; - unsigned char *bufe; + struct item_data *id; + int i,n,ne; + unsigned char *buf; + unsigned char *bufe; #if PACKETVER < 5 - const int s = 10; //Entry size. + const int s = 10; //Entry size. #elif PACKETVER < 20080102 - const int s = 18; + const int s = 18; #else - const int s = 22; + const int s = 22; #endif #if PACKETVER < 20071002 - const int cmd = 20; + const int cmd = 20; #elif PACKETVER < 20100629 - const int cmd = 26; + const int cmd = 26; #else - const int cmd = 28; + const int cmd = 28; #endif - buf = (unsigned char *)aMalloc(items_length * s + 4); - bufe = (unsigned char *)aMalloc(items_length * cmd + 4); - - for (i = 0, n = 0, ne = 0; i < items_length; i++) { - if (items[i].nameid <= 0) - continue; - id = itemdb_search(items[i].nameid); - if (!itemdb_isstackable2(id)) { - //Equippable - WBUFW(bufe,ne*cmd+4)=i+1; - clif_item_sub(bufe, ne*cmd+6, &items[i], id, id->equip); - clif_addcards(WBUFP(bufe, ne*cmd+16), &items[i]); + buf = (unsigned char*)aMalloc(items_length * s + 4); + bufe = (unsigned char*)aMalloc(items_length * cmd + 4); + + for( i = 0, n = 0, ne = 0; i < items_length; i++ ) + { + if( items[i].nameid <= 0 ) + continue; + id = itemdb_search(items[i].nameid); + if( !itemdb_isstackable2(id) ) + { //Equippable + WBUFW(bufe,ne*cmd+4)=i+1; + clif_item_sub(bufe, ne*cmd+6, &items[i], id, id->equip); + clif_addcards(WBUFP(bufe, ne*cmd+16), &items[i]); #if PACKETVER >= 20071002 - WBUFL(bufe,ne*cmd+24)=items[i].expire_time; - WBUFW(bufe,ne*cmd+28)=0; //Unknown + WBUFL(bufe,ne*cmd+24)=items[i].expire_time; + WBUFW(bufe,ne*cmd+28)=0; //Unknown #endif - ne++; - } else { - //Stackable - WBUFW(buf,n*s+4)=i+1; - clif_item_sub(buf, n*s+6, &items[i], id,-1); + ne++; + } + else + { //Stackable + WBUFW(buf,n*s+4)=i+1; + clif_item_sub(buf, n*s+6, &items[i], id,-1); #if PACKETVER >= 5 - clif_addcards(WBUFP(buf,n*s+14), &items[i]); + clif_addcards(WBUFP(buf,n*s+14), &items[i]); #endif #if PACKETVER >= 20080102 - WBUFL(buf,n*s+22)=items[i].expire_time; + WBUFL(buf,n*s+22)=items[i].expire_time; #endif - n++; - } - } - if (n) { + n++; + } + } + if( n ) + { #if PACKETVER < 5 - WBUFW(buf,0)=0xa5; + WBUFW(buf,0)=0xa5; #elif PACKETVER < 20080102 - WBUFW(buf,0)=0x1f0; + WBUFW(buf,0)=0x1f0; #else - WBUFW(buf,0)=0x2ea; + WBUFW(buf,0)=0x2ea; #endif - WBUFW(buf,2)=4+n*s; - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); - } - if (ne) { + WBUFW(buf,2)=4+n*s; + clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + } + if( ne ) + { #if PACKETVER < 20071002 - WBUFW(bufe,0)=0xa6; + WBUFW(bufe,0)=0xa6; #else - WBUFW(bufe,0)=0x2d1; + WBUFW(bufe,0)=0x2d1; #endif - WBUFW(bufe,2)=4+ne*cmd; - clif_send(bufe, WBUFW(bufe,2), &sd->bl, SELF); - } + WBUFW(bufe,2)=4+ne*cmd; + clif_send(bufe, WBUFW(bufe,2), &sd->bl, SELF); + } - if (buf) aFree(buf); - if (bufe) aFree(bufe); + if( buf ) aFree(buf); + if( bufe ) aFree(bufe); } void clif_cartlist(struct map_session_data *sd) { - struct item_data *id; - int i,n,ne; - unsigned char *buf; - unsigned char *bufe; + struct item_data *id; + int i,n,ne; + unsigned char *buf; + unsigned char *bufe; #if PACKETVER < 5 - const int s = 10; //Entry size. + const int s = 10; //Entry size. #elif PACKETVER < 20080102 - const int s = 18; + const int s = 18; #else - const int s = 22; + const int s = 22; #endif #if PACKETVER < 20071002 - const int cmd = 20; + const int cmd = 20; #elif PACKETVER < 20100629 - const int cmd = 26; + const int cmd = 26; #else - const int cmd = 28; + const int cmd = 28; #endif - buf = (unsigned char *)aMalloc(MAX_CART * s + 4); - bufe = (unsigned char *)aMalloc(MAX_CART * cmd + 4); - - for (i = 0, n = 0, ne = 0; i < MAX_CART; i++) { - if (sd->status.cart[i].nameid <= 0) - continue; - id = itemdb_search(sd->status.cart[i].nameid); - if (!itemdb_isstackable2(id)) { - //Equippable - WBUFW(bufe,ne*cmd+4)=i+2; - clif_item_sub(bufe, ne*cmd+6, &sd->status.cart[i], id, id->equip); - clif_addcards(WBUFP(bufe, ne*cmd+16), &sd->status.cart[i]); + buf = (unsigned char*)aMalloc(MAX_CART * s + 4); + bufe = (unsigned char*)aMalloc(MAX_CART * cmd + 4); + + for( i = 0, n = 0, ne = 0; i < MAX_CART; i++ ) + { + if( sd->status.cart[i].nameid <= 0 ) + continue; + id = itemdb_search(sd->status.cart[i].nameid); + if( !itemdb_isstackable2(id) ) + { //Equippable + WBUFW(bufe,ne*cmd+4)=i+2; + clif_item_sub(bufe, ne*cmd+6, &sd->status.cart[i], id, id->equip); + clif_addcards(WBUFP(bufe, ne*cmd+16), &sd->status.cart[i]); #if PACKETVER >= 20071002 - WBUFL(bufe,ne*cmd+24)=sd->status.cart[i].expire_time; - WBUFW(bufe,ne*cmd+28)=0; //Unknown + WBUFL(bufe,ne*cmd+24)=sd->status.cart[i].expire_time; + WBUFW(bufe,ne*cmd+28)=0; //Unknown #endif - ne++; - } else { - //Stackable - WBUFW(buf,n*s+4)=i+2; - clif_item_sub(buf, n*s+6, &sd->status.cart[i], id,-1); + ne++; + } + else + { //Stackable + WBUFW(buf,n*s+4)=i+2; + clif_item_sub(buf, n*s+6, &sd->status.cart[i], id,-1); #if PACKETVER >= 5 - clif_addcards(WBUFP(buf,n*s+14), &sd->status.cart[i]); + clif_addcards(WBUFP(buf,n*s+14), &sd->status.cart[i]); #endif #if PACKETVER >= 20080102 - WBUFL(buf,n*s+22)=sd->status.cart[i].expire_time; + WBUFL(buf,n*s+22)=sd->status.cart[i].expire_time; #endif - n++; - } - } - if (n) { + n++; + } + } + if( n ) + { #if PACKETVER < 5 - WBUFW(buf,0)=0x123; + WBUFW(buf,0)=0x123; #elif PACKETVER < 20080102 - WBUFW(buf,0)=0x1ef; + WBUFW(buf,0)=0x1ef; #else - WBUFW(buf,0)=0x2e9; + WBUFW(buf,0)=0x2e9; #endif - WBUFW(buf,2)=4+n*s; - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); - } - if (ne) { + WBUFW(buf,2)=4+n*s; + clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + } + if( ne ) + { #if PACKETVER < 20071002 - WBUFW(bufe,0)=0x122; + WBUFW(bufe,0)=0x122; #else - WBUFW(bufe,0)=0x2d2; + WBUFW(bufe,0)=0x2d2; #endif - WBUFW(bufe,2)=4+ne*cmd; - clif_send(bufe, WBUFW(bufe,2), &sd->bl, SELF); - } + WBUFW(bufe,2)=4+ne*cmd; + clif_send(bufe, WBUFW(bufe,2), &sd->bl, SELF); + } - if (buf) aFree(buf); - if (bufe) aFree(bufe); + if( buf ) aFree(buf); + if( bufe ) aFree(bufe); } @@ -2575,9 +2612,9 @@ void clif_cartlist(struct map_session_data *sd) /// The Num & Weight values of the cart are left untouched and the cart is NOT removed. void clif_clearcart(int fd) { - WFIFOHEAD(fd, packet_len(0x12b)); - WFIFOW(fd,0) = 0x12b; - WFIFOSET(fd, packet_len(0x12b)); + WFIFOHEAD(fd, packet_len(0x12b)); + WFIFOW(fd,0) = 0x12b; + WFIFOSET(fd, packet_len(0x12b)); } @@ -2586,15 +2623,15 @@ void clif_clearcart(int fd) /// 01eb <account id>.L <x>.W <y>.W void clif_guild_xy(struct map_session_data *sd) { - unsigned char buf[10]; + unsigned char buf[10]; - nullpo_retv(sd); + nullpo_retv(sd); - WBUFW(buf,0)=0x1eb; - WBUFL(buf,2)=sd->status.account_id; - WBUFW(buf,6)=sd->bl.x; - WBUFW(buf,8)=sd->bl.y; - clif_send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS); + WBUFW(buf,0)=0x1eb; + WBUFL(buf,2)=sd->status.account_id; + WBUFW(buf,6)=sd->bl.x; + WBUFW(buf,8)=sd->bl.y; + clif_send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS); } /*========================================== @@ -2602,29 +2639,29 @@ void clif_guild_xy(struct map_session_data *sd) *------------------------------------------*/ void clif_guild_xy_single(int fd, struct map_session_data *sd) { - if (sd->bg_id) - return; + if( sd->bg_id ) + return; - WFIFOHEAD(fd,packet_len(0x1eb)); - WFIFOW(fd,0)=0x1eb; - WFIFOL(fd,2)=sd->status.account_id; - WFIFOW(fd,6)=sd->bl.x; - WFIFOW(fd,8)=sd->bl.y; - WFIFOSET(fd,packet_len(0x1eb)); + WFIFOHEAD(fd,packet_len(0x1eb)); + WFIFOW(fd,0)=0x1eb; + WFIFOL(fd,2)=sd->status.account_id; + WFIFOW(fd,6)=sd->bl.x; + WFIFOW(fd,8)=sd->bl.y; + WFIFOSET(fd,packet_len(0x1eb)); } // Guild XY locators [Valaris] void clif_guild_xy_remove(struct map_session_data *sd) { - unsigned char buf[10]; + unsigned char buf[10]; - nullpo_retv(sd); + nullpo_retv(sd); - WBUFW(buf,0)=0x1eb; - WBUFL(buf,2)=sd->status.account_id; - WBUFW(buf,6)=-1; - WBUFW(buf,8)=-1; - clif_send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS); + WBUFW(buf,0)=0x1eb; + WBUFL(buf,2)=sd->status.account_id; + WBUFW(buf,6)=-1; + WBUFW(buf,8)=-1; + clif_send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS); } /*========================================== @@ -2632,42 +2669,42 @@ void clif_guild_xy_remove(struct map_session_data *sd) *------------------------------------------*/ static int clif_hpmeter_sub(struct block_list *bl, va_list ap) { - struct map_session_data *sd, *tsd; + struct map_session_data *sd, *tsd; #if PACKETVER < 20100126 - const int cmd = 0x106; + const int cmd = 0x106; #else - const int cmd = 0x80e; + const int cmd = 0x80e; #endif - sd = va_arg(ap, struct map_session_data *); - tsd = (TBL_PC *)bl; + sd = va_arg(ap, struct map_session_data *); + tsd = (TBL_PC *)bl; - nullpo_ret(sd); - nullpo_ret(tsd); + nullpo_ret(sd); + nullpo_ret(tsd); - if (!tsd->fd || tsd == sd) - return 0; + if( !tsd->fd || tsd == sd ) + return 0; - if (!pc_has_permission(tsd, PC_PERM_VIEW_HPMETER)) - return 0; - WFIFOHEAD(tsd->fd,packet_len(cmd)); - WFIFOW(tsd->fd,0) = cmd; - WFIFOL(tsd->fd,2) = sd->status.account_id; + if( !pc_has_permission(tsd, PC_PERM_VIEW_HPMETER) ) + return 0; + WFIFOHEAD(tsd->fd,packet_len(cmd)); + WFIFOW(tsd->fd,0) = cmd; + WFIFOL(tsd->fd,2) = sd->status.account_id; #if PACKETVER < 20100126 - if (sd->battle_status.max_hp > INT16_MAX) { - //To correctly display the %hp bar. [Skotlex] - WFIFOW(tsd->fd,6) = sd->battle_status.hp/(sd->battle_status.max_hp/100); - WFIFOW(tsd->fd,8) = 100; - } else { - WFIFOW(tsd->fd,6) = sd->battle_status.hp; - WFIFOW(tsd->fd,8) = sd->battle_status.max_hp; - } + if( sd->battle_status.max_hp > INT16_MAX ) + { //To correctly display the %hp bar. [Skotlex] + WFIFOW(tsd->fd,6) = sd->battle_status.hp/(sd->battle_status.max_hp/100); + WFIFOW(tsd->fd,8) = 100; + } else { + WFIFOW(tsd->fd,6) = sd->battle_status.hp; + WFIFOW(tsd->fd,8) = sd->battle_status.max_hp; + } #else - WFIFOL(tsd->fd,6) = sd->battle_status.hp; - WFIFOL(tsd->fd,10) = sd->battle_status.max_hp; + WFIFOL(tsd->fd,6) = sd->battle_status.hp; + WFIFOL(tsd->fd,10) = sd->battle_status.max_hp; #endif - WFIFOSET(tsd->fd,packet_len(cmd)); - return 0; + WFIFOSET(tsd->fd,packet_len(cmd)); + return 0; } /*========================================== @@ -2676,9 +2713,9 @@ static int clif_hpmeter_sub(struct block_list *bl, va_list ap) *------------------------------------------*/ static int clif_hpmeter(struct map_session_data *sd) { - nullpo_ret(sd); - map_foreachinarea(clif_hpmeter_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_PC, sd); - return 0; + nullpo_ret(sd); + map_foreachinarea(clif_hpmeter_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_PC, sd); + return 0; } /// Notifies client of a character parameter change. @@ -2692,245 +2729,246 @@ static int clif_hpmeter(struct map_session_data *sd) /// FIXME: Packet lengths from packet_len(cmd) void clif_updatestatus(struct map_session_data *sd,int type) { - int fd,len=8; - - nullpo_retv(sd); - - fd=sd->fd; - - if (!session_isActive(fd)) // Invalid pointer fix, by sasuke [Kevin] - return; - - WFIFOHEAD(fd, 14); - WFIFOW(fd,0)=0xb0; - WFIFOW(fd,2)=type; - switch (type) { - // 00b0 - case SP_WEIGHT: - pc_updateweightstatus(sd); - WFIFOHEAD(fd,14); - WFIFOW(fd,0)=0xb0; //Need to re-set as pc_updateweightstatus can alter the buffer. [Skotlex] - WFIFOW(fd,2)=type; - WFIFOL(fd,4)=sd->weight; - break; - case SP_MAXWEIGHT: - WFIFOL(fd,4)=sd->max_weight; - break; - case SP_SPEED: - WFIFOL(fd,4)=sd->battle_status.speed; - break; - case SP_BASELEVEL: - WFIFOL(fd,4)=sd->status.base_level; - break; - case SP_JOBLEVEL: - WFIFOL(fd,4)=sd->status.job_level; - break; - case SP_KARMA: // Adding this back, I wonder if the client intercepts this - [Lance] - WFIFOL(fd,4)=sd->status.karma; - break; - case SP_MANNER: - WFIFOL(fd,4)=sd->status.manner; - break; - case SP_STATUSPOINT: - WFIFOL(fd,4)=sd->status.status_point; - break; - case SP_SKILLPOINT: - WFIFOL(fd,4)=sd->status.skill_point; - break; - case SP_HIT: - WFIFOL(fd,4)=sd->battle_status.hit; - break; - case SP_FLEE1: - WFIFOL(fd,4)=sd->battle_status.flee; - break; - case SP_FLEE2: - WFIFOL(fd,4)=sd->battle_status.flee2/10; - break; - case SP_MAXHP: - WFIFOL(fd,4)=sd->battle_status.max_hp; - break; - case SP_MAXSP: - WFIFOL(fd,4)=sd->battle_status.max_sp; - break; - case SP_HP: - WFIFOL(fd,4)=sd->battle_status.hp; - // TODO: Won't these overwrite the current packet? - clif_hpmeter(sd); - if (!battle_config.party_hp_mode && sd->status.party_id) - clif_party_hp(sd); - if (sd->bg_id) - clif_bg_hp(sd); - break; - case SP_SP: - WFIFOL(fd,4)=sd->battle_status.sp; - break; - case SP_ASPD: - WFIFOL(fd,4)=sd->battle_status.amotion; - break; - case SP_ATK1: - WFIFOL(fd,4)=pc_leftside_atk(sd); - break; - case SP_DEF1: - WFIFOL(fd,4)=pc_leftside_def(sd); - break; - case SP_MDEF1: - WFIFOL(fd,4)=pc_leftside_mdef(sd); - break; - case SP_ATK2: - WFIFOL(fd,4)=pc_rightside_atk(sd); - break; - case SP_DEF2: - WFIFOL(fd,4)=pc_rightside_def(sd); - break; - case SP_MDEF2: { - //negative check (in case you have something like Berserk active) - int mdef2 = pc_rightside_mdef(sd); - - WFIFOL(fd,4)= + int fd,len=8; + + nullpo_retv(sd); + + fd=sd->fd; + + if ( !session_isActive(fd) ) // Invalid pointer fix, by sasuke [Kevin] + return; + + WFIFOHEAD(fd, 14); + WFIFOW(fd,0)=0xb0; + WFIFOW(fd,2)=type; + switch(type){ + // 00b0 + case SP_WEIGHT: + pc_updateweightstatus(sd); + WFIFOHEAD(fd,14); + WFIFOW(fd,0)=0xb0; //Need to re-set as pc_updateweightstatus can alter the buffer. [Skotlex] + WFIFOW(fd,2)=type; + WFIFOL(fd,4)=sd->weight; + break; + case SP_MAXWEIGHT: + WFIFOL(fd,4)=sd->max_weight; + break; + case SP_SPEED: + WFIFOL(fd,4)=sd->battle_status.speed; + break; + case SP_BASELEVEL: + WFIFOL(fd,4)=sd->status.base_level; + break; + case SP_JOBLEVEL: + WFIFOL(fd,4)=sd->status.job_level; + break; + case SP_KARMA: // Adding this back, I wonder if the client intercepts this - [Lance] + WFIFOL(fd,4)=sd->status.karma; + break; + case SP_MANNER: + WFIFOL(fd,4)=sd->status.manner; + break; + case SP_STATUSPOINT: + WFIFOL(fd,4)=sd->status.status_point; + break; + case SP_SKILLPOINT: + WFIFOL(fd,4)=sd->status.skill_point; + break; + case SP_HIT: + WFIFOL(fd,4)=sd->battle_status.hit; + break; + case SP_FLEE1: + WFIFOL(fd,4)=sd->battle_status.flee; + break; + case SP_FLEE2: + WFIFOL(fd,4)=sd->battle_status.flee2/10; + break; + case SP_MAXHP: + WFIFOL(fd,4)=sd->battle_status.max_hp; + break; + case SP_MAXSP: + WFIFOL(fd,4)=sd->battle_status.max_sp; + break; + case SP_HP: + WFIFOL(fd,4)=sd->battle_status.hp; + // TODO: Won't these overwrite the current packet? + clif_hpmeter(sd); + if( !battle_config.party_hp_mode && sd->status.party_id ) + clif_party_hp(sd); + if( sd->bg_id ) + clif_bg_hp(sd); + break; + case SP_SP: + WFIFOL(fd,4)=sd->battle_status.sp; + break; + case SP_ASPD: + WFIFOL(fd,4)=sd->battle_status.amotion; + break; + case SP_ATK1: + WFIFOL(fd,4)=pc_leftside_atk(sd); + break; + case SP_DEF1: + WFIFOL(fd,4)=pc_leftside_def(sd); + break; + case SP_MDEF1: + WFIFOL(fd,4)=pc_leftside_mdef(sd); + break; + case SP_ATK2: + WFIFOL(fd,4)=pc_rightside_atk(sd); + break; + case SP_DEF2: + WFIFOL(fd,4)=pc_rightside_def(sd); + break; + case SP_MDEF2: { + //negative check (in case you have something like Berserk active) + int mdef2 = pc_rightside_mdef(sd); + + WFIFOL(fd,4)= #ifndef RENEWAL - (mdef2 < 0) ? 0 : + ( mdef2 < 0 ) ? 0 : #endif - mdef2; - - } - break; - case SP_CRITICAL: - WFIFOL(fd,4)=sd->battle_status.cri/10; - break; - case SP_MATK1: - WFIFOL(fd,4)=pc_rightside_matk(sd); - break; - case SP_MATK2: - WFIFOL(fd,4)=pc_leftside_matk(sd); - break; - - - case SP_ZENY: - WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=sd->status.zeny; - break; - case SP_BASEEXP: - WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=sd->status.base_exp; - break; - case SP_JOBEXP: - WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=sd->status.job_exp; - break; - case SP_NEXTBASEEXP: - WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=pc_nextbaseexp(sd); - break; - case SP_NEXTJOBEXP: - WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=pc_nextjobexp(sd); - break; - - /** - * SP_U<STAT> are used to update the amount of points necessary to increase that stat - **/ - case SP_USTR: - case SP_UAGI: - case SP_UVIT: - case SP_UINT: - case SP_UDEX: - case SP_ULUK: - WFIFOW(fd,0)=0xbe; - WFIFOB(fd,4)=pc_need_status_point(sd,type-SP_USTR+SP_STR,1); - len=5; - break; - - /** - * Tells the client how far it is allowed to attack (weapon range) - **/ - case SP_ATTACKRANGE: - WFIFOW(fd,0)=0x13a; - WFIFOW(fd,2)=sd->battle_status.rhw.range; - len=4; - break; - - case SP_STR: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.str; - WFIFOL(fd,10)=sd->battle_status.str - sd->status.str; - len=14; - break; - case SP_AGI: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.agi; - WFIFOL(fd,10)=sd->battle_status.agi - sd->status.agi; - len=14; - break; - case SP_VIT: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.vit; - WFIFOL(fd,10)=sd->battle_status.vit - sd->status.vit; - len=14; - break; - case SP_INT: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.int_; - WFIFOL(fd,10)=sd->battle_status.int_ - sd->status.int_; - len=14; - break; - case SP_DEX: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.dex; - WFIFOL(fd,10)=sd->battle_status.dex - sd->status.dex; - len=14; - break; - case SP_LUK: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.luk; - WFIFOL(fd,10)=sd->battle_status.luk - sd->status.luk; - len=14; - break; - - case SP_CARTINFO: - WFIFOW(fd,0)=0x121; - WFIFOW(fd,2)=sd->cart_num; - WFIFOW(fd,4)=MAX_CART; - WFIFOL(fd,6)=sd->cart_weight; - WFIFOL(fd,10)=sd->cart_weight_max; - len=14; - break; - - default: - ShowError("clif_updatestatus : unrecognized type %d\n",type); - return; - } - WFIFOSET(fd,len); + mdef2; + + } + break; + case SP_CRITICAL: + WFIFOL(fd,4)=sd->battle_status.cri/10; + break; + case SP_MATK1: + WFIFOL(fd,4)=sd->battle_status.matk_max; + break; + case SP_MATK2: + WFIFOL(fd,4)=sd->battle_status.matk_min; + break; + + + case SP_ZENY: + WFIFOW(fd,0)=0xb1; + WFIFOL(fd,4)=sd->status.zeny; + break; + case SP_BASEEXP: + WFIFOW(fd,0)=0xb1; + WFIFOL(fd,4)=sd->status.base_exp; + break; + case SP_JOBEXP: + WFIFOW(fd,0)=0xb1; + WFIFOL(fd,4)=sd->status.job_exp; + break; + case SP_NEXTBASEEXP: + WFIFOW(fd,0)=0xb1; + WFIFOL(fd,4)=pc_nextbaseexp(sd); + break; + case SP_NEXTJOBEXP: + WFIFOW(fd,0)=0xb1; + WFIFOL(fd,4)=pc_nextjobexp(sd); + break; + + /** + * SP_U<STAT> are used to update the amount of points necessary to increase that stat + **/ + case SP_USTR: + case SP_UAGI: + case SP_UVIT: + case SP_UINT: + case SP_UDEX: + case SP_ULUK: + WFIFOW(fd,0)=0xbe; + WFIFOB(fd,4)=pc_need_status_point(sd,type-SP_USTR+SP_STR,1); + len=5; + break; + + /** + * Tells the client how far it is allowed to attack (weapon range) + **/ + case SP_ATTACKRANGE: + WFIFOW(fd,0)=0x13a; + WFIFOW(fd,2)=sd->battle_status.rhw.range; + len=4; + break; + + case SP_STR: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.str; + WFIFOL(fd,10)=sd->battle_status.str - sd->status.str; + len=14; + break; + case SP_AGI: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.agi; + WFIFOL(fd,10)=sd->battle_status.agi - sd->status.agi; + len=14; + break; + case SP_VIT: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.vit; + WFIFOL(fd,10)=sd->battle_status.vit - sd->status.vit; + len=14; + break; + case SP_INT: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.int_; + WFIFOL(fd,10)=sd->battle_status.int_ - sd->status.int_; + len=14; + break; + case SP_DEX: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.dex; + WFIFOL(fd,10)=sd->battle_status.dex - sd->status.dex; + len=14; + break; + case SP_LUK: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.luk; + WFIFOL(fd,10)=sd->battle_status.luk - sd->status.luk; + len=14; + break; + + case SP_CARTINFO: + WFIFOW(fd,0)=0x121; + WFIFOW(fd,2)=sd->cart_num; + WFIFOW(fd,4)=MAX_CART; + WFIFOL(fd,6)=sd->cart_weight; + WFIFOL(fd,10)=sd->cart_weight_max; + len=14; + break; + + default: + ShowError("clif_updatestatus : unrecognized type %d\n",type); + return; + } + WFIFOSET(fd,len); } /// Notifies client of a parameter change of an another player (ZC_PAR_CHANGE_USER). /// 01ab <account id>.L <var id>.W <value>.L -void clif_changestatus(struct map_session_data *sd,int type,int val) +void clif_changestatus(struct map_session_data* sd,int type,int val) { - unsigned char buf[12]; + unsigned char buf[12]; - nullpo_retv(sd); + nullpo_retv(sd); - WBUFW(buf,0)=0x1ab; - WBUFL(buf,2)=sd->bl.id; - WBUFW(buf,6)=type; + WBUFW(buf,0)=0x1ab; + WBUFL(buf,2)=sd->bl.id; + WBUFW(buf,6)=type; - switch (type) { - case SP_MANNER: - WBUFL(buf,8)=val; - break; - default: - ShowError("clif_changestatus : unrecognized type %d.\n",type); - return; - } + switch(type) + { + case SP_MANNER: + WBUFL(buf,8)=val; + break; + default: + ShowError("clif_changestatus : unrecognized type %d.\n",type); + return; + } - clif_send(buf,packet_len(0x1ab),&sd->bl,AREA_WOS); + clif_send(buf,packet_len(0x1ab),&sd->bl,AREA_WOS); } @@ -2939,156 +2977,161 @@ void clif_changestatus(struct map_session_data *sd,int type,int val) /// 01d7 <id>.L <type>.B <value>.L (ZC_SPRITE_CHANGE2) void clif_changelook(struct block_list *bl,int type,int val) { - unsigned char buf[16]; - struct map_session_data *sd = NULL; - struct status_change *sc; - struct view_data *vd; - enum send_target target = AREA; - nullpo_retv(bl); - - sd = BL_CAST(BL_PC, bl); - sc = status_get_sc(bl); - vd = status_get_viewdata(bl); - //nullpo_ret(vd); - if (vd) //temp hack to let Warp Portal change appearance - switch (type) { - case LOOK_WEAPON: - if (sd) { - clif_get_weapon_view(sd, &vd->weapon, &vd->shield); - val = vd->weapon; - } else vd->weapon = val; - break; - case LOOK_SHIELD: - if (sd) { - clif_get_weapon_view(sd, &vd->weapon, &vd->shield); - val = vd->shield; - } else vd->shield = val; - break; - case LOOK_BASE: - vd->class_ = val; - if (vd->class_ == JOB_WEDDING || vd->class_ == JOB_XMAS || vd->class_ == JOB_SUMMER) - vd->weapon = vd->shield = 0; - if (vd->cloth_color && ( - (vd->class_ == JOB_WEDDING && battle_config.wedding_ignorepalette) || - (vd->class_ == JOB_XMAS && battle_config.xmas_ignorepalette) || - (vd->class_ == JOB_SUMMER && battle_config.summer_ignorepalette) - )) - clif_changelook(bl,LOOK_CLOTHES_COLOR,0); - break; - case LOOK_HAIR: - vd->hair_style = val; - break; - case LOOK_HEAD_BOTTOM: - vd->head_bottom = val; - break; - case LOOK_HEAD_TOP: - vd->head_top = val; - break; - case LOOK_HEAD_MID: - vd->head_mid = val; - break; - case LOOK_HAIR_COLOR: - vd->hair_color = val; - break; - case LOOK_CLOTHES_COLOR: - if (val && ( - (vd->class_ == JOB_WEDDING && battle_config.wedding_ignorepalette) || - (vd->class_ == JOB_XMAS && battle_config.xmas_ignorepalette) || - (vd->class_ == JOB_SUMMER && battle_config.summer_ignorepalette) - )) - val = 0; - vd->cloth_color = val; - break; - case LOOK_SHOES: + unsigned char buf[16]; + struct map_session_data* sd = NULL; + struct status_change* sc; + struct view_data* vd; + enum send_target target = AREA; + nullpo_retv(bl); + + sd = BL_CAST(BL_PC, bl); + sc = status_get_sc(bl); + vd = status_get_viewdata(bl); + //nullpo_ret(vd); + if( vd ) //temp hack to let Warp Portal change appearance + switch(type) + { + case LOOK_WEAPON: + if (sd) + { + clif_get_weapon_view(sd, &vd->weapon, &vd->shield); + val = vd->weapon; + } + else vd->weapon = val; + break; + case LOOK_SHIELD: + if (sd) + { + clif_get_weapon_view(sd, &vd->weapon, &vd->shield); + val = vd->shield; + } + else vd->shield = val; + break; + case LOOK_BASE: + vd->class_ = val; + if (vd->class_ == JOB_WEDDING || vd->class_ == JOB_XMAS || vd->class_ == JOB_SUMMER) + vd->weapon = vd->shield = 0; + if (vd->cloth_color && ( + (vd->class_ == JOB_WEDDING && battle_config.wedding_ignorepalette) || + (vd->class_ == JOB_XMAS && battle_config.xmas_ignorepalette) || + (vd->class_ == JOB_SUMMER && battle_config.summer_ignorepalette) + )) + clif_changelook(bl,LOOK_CLOTHES_COLOR,0); + break; + case LOOK_HAIR: + vd->hair_style = val; + break; + case LOOK_HEAD_BOTTOM: + vd->head_bottom = val; + break; + case LOOK_HEAD_TOP: + vd->head_top = val; + break; + case LOOK_HEAD_MID: + vd->head_mid = val; + break; + case LOOK_HAIR_COLOR: + vd->hair_color = val; + break; + case LOOK_CLOTHES_COLOR: + if (val && ( + (vd->class_ == JOB_WEDDING && battle_config.wedding_ignorepalette) || + (vd->class_ == JOB_XMAS && battle_config.xmas_ignorepalette) || + (vd->class_ == JOB_SUMMER && battle_config.summer_ignorepalette) + )) + val = 0; + vd->cloth_color = val; + break; + case LOOK_SHOES: #if PACKETVER > 3 - if (sd) { - int n; - if ((n = sd->equip_index[2]) >= 0 && sd->inventory_data[n]) { - if (sd->inventory_data[n]->view_id > 0) - val = sd->inventory_data[n]->view_id; - else - val = sd->status.inventory[n].nameid; - } else - val = 0; - } + if (sd) { + int n; + if((n = sd->equip_index[2]) >= 0 && sd->inventory_data[n]) { + if(sd->inventory_data[n]->view_id > 0) + val = sd->inventory_data[n]->view_id; + else + val = sd->status.inventory[n].nameid; + } else + val = 0; + } #endif - //Shoes? No packet uses this.... - break; - case LOOK_BODY: - case LOOK_FLOOR: - // unknown purpose - break; - case LOOK_ROBE: + //Shoes? No packet uses this.... + break; + case LOOK_BODY: + case LOOK_FLOOR: + // unknown purpose + break; + case LOOK_ROBE: #if PACKETVER < 20110111 - return; + return; #else - vd->robe = val; + vd->robe = val; #endif - break; - } + break; + } - // prevent leaking the presence of GM-hidden objects - if (sc && sc->option&OPTION_INVISIBLE) - target = SELF; + // prevent leaking the presence of GM-hidden objects + if( sc && sc->option&OPTION_INVISIBLE ) + target = SELF; #if PACKETVER < 4 - WBUFW(buf,0)=0xc3; - WBUFL(buf,2)=bl->id; - WBUFB(buf,6)=type; - WBUFB(buf,7)=val; - clif_send(buf,packet_len(0xc3),bl,target); + WBUFW(buf,0)=0xc3; + WBUFL(buf,2)=bl->id; + WBUFB(buf,6)=type; + WBUFB(buf,7)=val; + clif_send(buf,packet_len(0xc3),bl,target); #else - WBUFW(buf,0)=0x1d7; - WBUFL(buf,2)=bl->id; - if (type == LOOK_WEAPON || type == LOOK_SHIELD) { - WBUFB(buf,6)=LOOK_WEAPON; - WBUFW(buf,7)=vd->weapon; - WBUFW(buf,9)=vd->shield; - } else { - WBUFB(buf,6)=type; - WBUFL(buf,7)=val; - } - clif_send(buf,packet_len(0x1d7),bl,target); + WBUFW(buf,0)=0x1d7; + WBUFL(buf,2)=bl->id; + if(type == LOOK_WEAPON || type == LOOK_SHIELD) { + WBUFB(buf,6)=LOOK_WEAPON; + WBUFW(buf,7)=vd->weapon; + WBUFW(buf,9)=vd->shield; + } else { + WBUFB(buf,6)=type; + WBUFL(buf,7)=val; + } + clif_send(buf,packet_len(0x1d7),bl,target); #endif } //Sends a change-base-look packet required for traps as they are triggered. void clif_changetraplook(struct block_list *bl,int val) { - unsigned char buf[32]; + unsigned char buf[32]; #if PACKETVER < 4 - WBUFW(buf,0)=0xc3; - WBUFL(buf,2)=bl->id; - WBUFB(buf,6)=LOOK_BASE; - WBUFB(buf,7)=val; - clif_send(buf,packet_len(0xc3),bl,AREA); + WBUFW(buf,0)=0xc3; + WBUFL(buf,2)=bl->id; + WBUFB(buf,6)=LOOK_BASE; + WBUFB(buf,7)=val; + clif_send(buf,packet_len(0xc3),bl,AREA); #else - WBUFW(buf,0)=0x1d7; - WBUFL(buf,2)=bl->id; - WBUFB(buf,6)=LOOK_BASE; - WBUFW(buf,7)=val; - WBUFW(buf,9)=0; - clif_send(buf,packet_len(0x1d7),bl,AREA); + WBUFW(buf,0)=0x1d7; + WBUFL(buf,2)=bl->id; + WBUFB(buf,6)=LOOK_BASE; + WBUFW(buf,7)=val; + WBUFW(buf,9)=0; + clif_send(buf,packet_len(0x1d7),bl,AREA); #endif } //For the stupid cloth-dye bug. Resends the given view data to the area specified by bl. void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_target target) { - unsigned char buf[32]; + unsigned char buf[32]; #if PACKETVER < 4 - WBUFW(buf,0)=0xc3; - WBUFL(buf,2)=id; - WBUFB(buf,6)=type; - WBUFB(buf,7)=val; - clif_send(buf,packet_len(0xc3),bl,target); + WBUFW(buf,0)=0xc3; + WBUFL(buf,2)=id; + WBUFB(buf,6)=type; + WBUFB(buf,7)=val; + clif_send(buf,packet_len(0xc3),bl,target); #else - WBUFW(buf,0)=0x1d7; - WBUFL(buf,2)=id; - WBUFB(buf,6)=type; - WBUFW(buf,7)=val; - WBUFW(buf,9)=0; - clif_send(buf,packet_len(0x1d7),bl,target); + WBUFW(buf,0)=0x1d7; + WBUFL(buf,2)=id; + WBUFB(buf,6)=type; + WBUFW(buf,7)=val; + WBUFW(buf,9)=0; + clif_send(buf,packet_len(0x1d7),bl,target); #endif } @@ -3100,61 +3143,61 @@ void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_ta /// <flee>.W <flee2>.W <crit>.W <aspd>.W <aspd2>.W void clif_initialstatus(struct map_session_data *sd) { - int fd, mdef2; - unsigned char *buf; - - nullpo_retv(sd); - - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xbd)); - buf=WFIFOP(fd,0); - - WBUFW(buf,0)=0xbd; - WBUFW(buf,2)=min(sd->status.status_point, INT16_MAX); - WBUFB(buf,4)=min(sd->status.str, UINT8_MAX); - WBUFB(buf,5)=pc_need_status_point(sd,SP_STR,1); - WBUFB(buf,6)=min(sd->status.agi, UINT8_MAX); - WBUFB(buf,7)=pc_need_status_point(sd,SP_AGI,1); - WBUFB(buf,8)=min(sd->status.vit, UINT8_MAX); - WBUFB(buf,9)=pc_need_status_point(sd,SP_VIT,1); - WBUFB(buf,10)=min(sd->status.int_, UINT8_MAX); - WBUFB(buf,11)=pc_need_status_point(sd,SP_INT,1); - WBUFB(buf,12)=min(sd->status.dex, UINT8_MAX); - WBUFB(buf,13)=pc_need_status_point(sd,SP_DEX,1); - WBUFB(buf,14)=min(sd->status.luk, UINT8_MAX); - WBUFB(buf,15)=pc_need_status_point(sd,SP_LUK,1); - - WBUFW(buf,16) = pc_leftside_atk(sd); - WBUFW(buf,18) = pc_rightside_atk(sd); - WBUFW(buf,20) = pc_rightside_matk(sd); - WBUFW(buf,22) = pc_leftside_matk(sd); - WBUFW(buf,24) = pc_leftside_def(sd); - WBUFW(buf,26) = pc_rightside_def(sd); - WBUFW(buf,28) = pc_leftside_mdef(sd); - mdef2 = pc_rightside_mdef(sd); - WBUFW(buf,30) = + int fd, mdef2; + unsigned char *buf; + + nullpo_retv(sd); + + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xbd)); + buf=WFIFOP(fd,0); + + WBUFW(buf,0)=0xbd; + WBUFW(buf,2)=min(sd->status.status_point, INT16_MAX); + WBUFB(buf,4)=min(sd->status.str, UINT8_MAX); + WBUFB(buf,5)=pc_need_status_point(sd,SP_STR,1); + WBUFB(buf,6)=min(sd->status.agi, UINT8_MAX); + WBUFB(buf,7)=pc_need_status_point(sd,SP_AGI,1); + WBUFB(buf,8)=min(sd->status.vit, UINT8_MAX); + WBUFB(buf,9)=pc_need_status_point(sd,SP_VIT,1); + WBUFB(buf,10)=min(sd->status.int_, UINT8_MAX); + WBUFB(buf,11)=pc_need_status_point(sd,SP_INT,1); + WBUFB(buf,12)=min(sd->status.dex, UINT8_MAX); + WBUFB(buf,13)=pc_need_status_point(sd,SP_DEX,1); + WBUFB(buf,14)=min(sd->status.luk, UINT8_MAX); + WBUFB(buf,15)=pc_need_status_point(sd,SP_LUK,1); + + WBUFW(buf,16) = pc_leftside_atk(sd); + WBUFW(buf,18) = pc_rightside_atk(sd); + WBUFW(buf,20) = sd->battle_status.matk_max; + WBUFW(buf,22) = sd->battle_status.matk_min; + WBUFW(buf,24) = pc_leftside_def(sd); + WBUFW(buf,26) = pc_rightside_def(sd); + WBUFW(buf,28) = pc_leftside_mdef(sd); + mdef2 = pc_rightside_mdef(sd); + WBUFW(buf,30) = #ifndef RENEWAL - (mdef2 < 0) ? 0 : //Negative check for Frenzy'ed characters. + ( mdef2 < 0 ) ? 0 : //Negative check for Frenzy'ed characters. #endif - mdef2; - WBUFW(buf,32) = sd->battle_status.hit; - WBUFW(buf,34) = sd->battle_status.flee; - WBUFW(buf,36) = sd->battle_status.flee2/10; - WBUFW(buf,38) = sd->battle_status.cri/10; - WBUFW(buf,40) = sd->battle_status.amotion; // aspd - WBUFW(buf,42) = 0; // always 0 (plusASPD) + mdef2; + WBUFW(buf,32) = sd->battle_status.hit; + WBUFW(buf,34) = sd->battle_status.flee; + WBUFW(buf,36) = sd->battle_status.flee2/10; + WBUFW(buf,38) = sd->battle_status.cri/10; + WBUFW(buf,40) = sd->battle_status.amotion; // aspd + WBUFW(buf,42) = 0; // always 0 (plusASPD) - WFIFOSET(fd,packet_len(0xbd)); + WFIFOSET(fd,packet_len(0xbd)); - clif_updatestatus(sd,SP_STR); - clif_updatestatus(sd,SP_AGI); - clif_updatestatus(sd,SP_VIT); - clif_updatestatus(sd,SP_INT); - clif_updatestatus(sd,SP_DEX); - clif_updatestatus(sd,SP_LUK); + clif_updatestatus(sd,SP_STR); + clif_updatestatus(sd,SP_AGI); + clif_updatestatus(sd,SP_VIT); + clif_updatestatus(sd,SP_INT); + clif_updatestatus(sd,SP_DEX); + clif_updatestatus(sd,SP_LUK); - clif_updatestatus(sd,SP_ATTACKRANGE); - clif_updatestatus(sd,SP_ASPD); + clif_updatestatus(sd,SP_ATTACKRANGE); + clif_updatestatus(sd,SP_ASPD); } @@ -3162,17 +3205,17 @@ void clif_initialstatus(struct map_session_data *sd) /// 013c <index>.W void clif_arrowequip(struct map_session_data *sd,int val) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - pc_stop_attack(sd); // [Valaris] + pc_stop_attack(sd); // [Valaris] - fd=sd->fd; - WFIFOHEAD(fd, packet_len(0x013c)); - WFIFOW(fd,0)=0x013c; - WFIFOW(fd,2)=val+2; //Item ID of the arrow - WFIFOSET(fd,packet_len(0x013c)); + fd=sd->fd; + WFIFOHEAD(fd, packet_len(0x013c)); + WFIFOW(fd,0)=0x013c; + WFIFOW(fd,2)=val+2; //Item ID of the arrow + WFIFOSET(fd,packet_len(0x013c)); } @@ -3187,15 +3230,15 @@ void clif_arrowequip(struct map_session_data *sd,int val) /// NOT ninja => MsgStringTable[245]="Ammunition has been equipped." void clif_arrow_fail(struct map_session_data *sd,int type) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd, packet_len(0x013b)); - WFIFOW(fd,0)=0x013b; - WFIFOW(fd,2)=type; - WFIFOSET(fd,packet_len(0x013b)); + fd=sd->fd; + WFIFOHEAD(fd, packet_len(0x013b)); + WFIFOW(fd,0)=0x013b; + WFIFOW(fd,2)=type; + WFIFOSET(fd,packet_len(0x013b)); } @@ -3203,32 +3246,33 @@ void clif_arrow_fail(struct map_session_data *sd,int type) /// 01ad <packet len>.W { <name id>.W }* void clif_arrow_create_list(struct map_session_data *sd) { - int i, c, j; - int fd; + int i, c, j; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd, MAX_SKILL_ARROW_DB*2+4); - WFIFOW(fd,0) = 0x1ad; - - for (i = 0, c = 0; i < MAX_SKILL_ARROW_DB; i++) { - if (skill_arrow_db[i].nameid > 0 && - (j = pc_search_inventory(sd, skill_arrow_db[i].nameid)) >= 0 && - !sd->status.inventory[j].equip && sd->status.inventory[j].identify) { - if ((j = itemdb_viewid(skill_arrow_db[i].nameid)) > 0) - WFIFOW(fd,c*2+4) = j; - else - WFIFOW(fd,c*2+4) = skill_arrow_db[i].nameid; - c++; - } - } - WFIFOW(fd,2) = c*2+4; - WFIFOSET(fd, WFIFOW(fd,2)); - if (c > 0) { - sd->menuskill_id = AC_MAKINGARROW; - sd->menuskill_val = c; - } + fd = sd->fd; + WFIFOHEAD(fd, MAX_SKILL_ARROW_DB*2+4); + WFIFOW(fd,0) = 0x1ad; + + for (i = 0, c = 0; i < MAX_SKILL_ARROW_DB; i++) { + if (skill_arrow_db[i].nameid > 0 && + (j = pc_search_inventory(sd, skill_arrow_db[i].nameid)) >= 0 && + !sd->status.inventory[j].equip && sd->status.inventory[j].identify) + { + if ((j = itemdb_viewid(skill_arrow_db[i].nameid)) > 0) + WFIFOW(fd,c*2+4) = j; + else + WFIFOW(fd,c*2+4) = skill_arrow_db[i].nameid; + c++; + } + } + WFIFOW(fd,2) = c*2+4; + WFIFOSET(fd, WFIFOW(fd,2)); + if (c > 0) { + sd->menuskill_id = AC_MAKINGARROW; + sd->menuskill_val = c; + } } @@ -3241,17 +3285,17 @@ void clif_arrow_create_list(struct map_session_data *sd) /// 1 = success void clif_statusupack(struct map_session_data *sd,int type,int ok,int val) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xbc)); - WFIFOW(fd,0)=0xbc; - WFIFOW(fd,2)=type; - WFIFOB(fd,4)=ok; - WFIFOB(fd,5)=cap_value(val,0,UINT8_MAX); - WFIFOSET(fd,packet_len(0xbc)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xbc)); + WFIFOW(fd,0)=0xbc; + WFIFOW(fd,2)=type; + WFIFOB(fd,4)=ok; + WFIFOB(fd,5)=cap_value(val,0,UINT8_MAX); + WFIFOSET(fd,packet_len(0xbc)); } @@ -3264,25 +3308,25 @@ void clif_statusupack(struct map_session_data *sd,int type,int ok,int val) /// 2 = failure due to low level void clif_equipitemack(struct map_session_data *sd,int n,int pos,int ok) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xaa)); - WFIFOW(fd,0)=0xaa; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=pos; + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xaa)); + WFIFOW(fd,0)=0xaa; + WFIFOW(fd,2)=n+2; + WFIFOW(fd,4)=pos; #if PACKETVER < 20100629 - WFIFOB(fd,6)=ok; + WFIFOB(fd,6)=ok; #else - if (ok && sd->inventory_data[n]->equip&EQP_VISIBLE) - WFIFOW(fd,6)=sd->inventory_data[n]->look; - else - WFIFOW(fd,6)=0; - WFIFOB(fd,8)=ok; + if (ok && sd->inventory_data[n]->equip&EQP_VISIBLE) + WFIFOW(fd,6)=sd->inventory_data[n]->look; + else + WFIFOW(fd,6)=0; + WFIFOB(fd,8)=ok; #endif - WFIFOSET(fd,packet_len(0xaa)); + WFIFOSET(fd,packet_len(0xaa)); } @@ -3293,17 +3337,17 @@ void clif_equipitemack(struct map_session_data *sd,int n,int pos,int ok) /// 1 = success void clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xac)); - WFIFOW(fd,0)=0xac; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=pos; - WFIFOB(fd,6)=ok; - WFIFOSET(fd,packet_len(0xac)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xac)); + WFIFOW(fd,0)=0xac; + WFIFOW(fd,2)=n+2; + WFIFOW(fd,4)=pos; + WFIFOB(fd,6)=ok; + WFIFOSET(fd,packet_len(0xac)); } @@ -3320,94 +3364,94 @@ void clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok) /// 7 = base level up (super novice) /// 8 = job level up (super novice) /// 9 = base level up (taekwon) -void clif_misceffect(struct block_list *bl,int type) +void clif_misceffect(struct block_list* bl,int type) { - unsigned char buf[32]; + unsigned char buf[32]; - nullpo_retv(bl); + nullpo_retv(bl); - WBUFW(buf,0) = 0x19b; - WBUFL(buf,2) = bl->id; - WBUFL(buf,6) = type; + WBUFW(buf,0) = 0x19b; + WBUFL(buf,2) = bl->id; + WBUFL(buf,6) = type; - clif_send(buf,packet_len(0x19b),bl,AREA); + clif_send(buf,packet_len(0x19b),bl,AREA); } /// Notifies clients in the area of a state change. /// 0119 <id>.L <body state>.W <health state>.W <effect state>.W <pk mode>.B (ZC_STATE_CHANGE) /// 0229 <id>.L <body state>.W <health state>.W <effect state>.L <pk mode>.B (ZC_STATE_CHANGE3) -void clif_changeoption(struct block_list *bl) +void clif_changeoption(struct block_list* bl) { - unsigned char buf[32]; - struct status_change *sc; - struct map_session_data *sd; + unsigned char buf[32]; + struct status_change *sc; + struct map_session_data* sd; - nullpo_retv(bl); - sc = status_get_sc(bl); - if (!sc) return; //How can an option change if there's no sc? - sd = BL_CAST(BL_PC, bl); + nullpo_retv(bl); + sc = status_get_sc(bl); + if (!sc) return; //How can an option change if there's no sc? + sd = BL_CAST(BL_PC, bl); #if PACKETVER >= 7 - WBUFW(buf,0) = 0x229; - WBUFL(buf,2) = bl->id; - WBUFW(buf,6) = sc->opt1; - WBUFW(buf,8) = sc->opt2; - WBUFL(buf,10) = sc->option; - WBUFB(buf,14) = (sd)? sd->status.karma : 0; - if (disguised(bl)) { - clif_send(buf,packet_len(0x229),bl,AREA_WOS); - WBUFL(buf,2) = -bl->id; - clif_send(buf,packet_len(0x229),bl,SELF); - WBUFL(buf,2) = bl->id; - WBUFL(buf,10) = OPTION_INVISIBLE; - clif_send(buf,packet_len(0x229),bl,SELF); - } else - clif_send(buf,packet_len(0x229),bl,AREA); + WBUFW(buf,0) = 0x229; + WBUFL(buf,2) = bl->id; + WBUFW(buf,6) = sc->opt1; + WBUFW(buf,8) = sc->opt2; + WBUFL(buf,10) = sc->option; + WBUFB(buf,14) = (sd)? sd->status.karma : 0; + if(disguised(bl)) { + clif_send(buf,packet_len(0x229),bl,AREA_WOS); + WBUFL(buf,2) = -bl->id; + clif_send(buf,packet_len(0x229),bl,SELF); + WBUFL(buf,2) = bl->id; + WBUFL(buf,10) = OPTION_INVISIBLE; + clif_send(buf,packet_len(0x229),bl,SELF); + } else + clif_send(buf,packet_len(0x229),bl,AREA); #else - WBUFW(buf,0) = 0x119; - WBUFL(buf,2) = bl->id; - WBUFW(buf,6) = sc->opt1; - WBUFW(buf,8) = sc->opt2; - WBUFW(buf,10) = sc->option; - WBUFB(buf,12) = (sd)? sd->status.karma : 0; - if (disguised(bl)) { - clif_send(buf,packet_len(0x119),bl,AREA_WOS); - WBUFL(buf,2) = -bl->id; - clif_send(buf,packet_len(0x119),bl,SELF); - WBUFL(buf,2) = bl->id; - WBUFW(buf,10) = OPTION_INVISIBLE; - clif_send(buf,packet_len(0x119),bl,SELF); - } else - clif_send(buf,packet_len(0x119),bl,AREA); + WBUFW(buf,0) = 0x119; + WBUFL(buf,2) = bl->id; + WBUFW(buf,6) = sc->opt1; + WBUFW(buf,8) = sc->opt2; + WBUFW(buf,10) = sc->option; + WBUFB(buf,12) = (sd)? sd->status.karma : 0; + if(disguised(bl)) { + clif_send(buf,packet_len(0x119),bl,AREA_WOS); + WBUFL(buf,2) = -bl->id; + clif_send(buf,packet_len(0x119),bl,SELF); + WBUFL(buf,2) = bl->id; + WBUFW(buf,10) = OPTION_INVISIBLE; + clif_send(buf,packet_len(0x119),bl,SELF); + } else + clif_send(buf,packet_len(0x119),bl,AREA); #endif } /// Displays status change effects on NPCs/monsters (ZC_NPC_SHOWEFST_UPDATE). /// 028a <id>.L <effect state>.L <level>.L <showEFST>.L -void clif_changeoption2(struct block_list *bl) +void clif_changeoption2(struct block_list* bl) { - unsigned char buf[20]; - struct status_change *sc; + unsigned char buf[20]; + struct status_change *sc; - sc = status_get_sc(bl); - if (!sc) return; //How can an option change if there's no sc? + sc = status_get_sc(bl); + if (!sc) return; //How can an option change if there's no sc? - WBUFW(buf,0) = 0x28a; - WBUFL(buf,2) = bl->id; - WBUFL(buf,6) = sc->option; - WBUFL(buf,10) = clif_setlevel(bl); - WBUFL(buf,14) = sc->opt3; - if (disguised(bl)) { - clif_send(buf,packet_len(0x28a),bl,AREA_WOS); - WBUFL(buf,2) = -bl->id; - clif_send(buf,packet_len(0x28a),bl,SELF); - WBUFL(buf,2) = bl->id; - WBUFL(buf,6) = OPTION_INVISIBLE; - clif_send(buf,packet_len(0x28a),bl,SELF); - } else - clif_send(buf,packet_len(0x28a),bl,AREA); + WBUFW(buf,0) = 0x28a; + WBUFL(buf,2) = bl->id; + WBUFL(buf,6) = sc->option; + WBUFL(buf,10) = clif_setlevel(bl); + WBUFL(buf,14) = sc->opt3; + if(disguised(bl)) { + clif_send(buf,packet_len(0x28a),bl,AREA_WOS); + WBUFL(buf,2) = -bl->id; + clif_send(buf,packet_len(0x28a),bl,SELF); + WBUFL(buf,2) = bl->id; + WBUFL(buf,6) = OPTION_INVISIBLE; + clif_send(buf,packet_len(0x28a),bl,SELF); + } else + clif_send(buf,packet_len(0x28a),bl,AREA); } @@ -3416,40 +3460,41 @@ void clif_changeoption2(struct block_list *bl) /// 01c8 <index>.W <name id>.W <id>.L <amount>.W <result>.B (ZC_USE_ITEM_ACK2) void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok) { - nullpo_retv(sd); - - if (!ok) { - int fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xa8)); - WFIFOW(fd,0)=0xa8; - WFIFOW(fd,2)=index+2; - WFIFOW(fd,4)=amount; - WFIFOB(fd,6)=ok; - WFIFOSET(fd,packet_len(0xa8)); - } else { + nullpo_retv(sd); + + if(!ok) { + int fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xa8)); + WFIFOW(fd,0)=0xa8; + WFIFOW(fd,2)=index+2; + WFIFOW(fd,4)=amount; + WFIFOB(fd,6)=ok; + WFIFOSET(fd,packet_len(0xa8)); + } + else { #if PACKETVER < 3 - int fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xa8)); - WFIFOW(fd,0)=0xa8; - WFIFOW(fd,2)=index+2; - WFIFOW(fd,4)=amount; - WFIFOB(fd,6)=ok; - WFIFOSET(fd,packet_len(0xa8)); + int fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xa8)); + WFIFOW(fd,0)=0xa8; + WFIFOW(fd,2)=index+2; + WFIFOW(fd,4)=amount; + WFIFOB(fd,6)=ok; + WFIFOSET(fd,packet_len(0xa8)); #else - unsigned char buf[32]; - - WBUFW(buf,0)=0x1c8; - WBUFW(buf,2)=index+2; - if (sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0) - WBUFW(buf,4)=sd->inventory_data[index]->view_id; - else - WBUFW(buf,4)=sd->status.inventory[index].nameid; - WBUFL(buf,6)=sd->bl.id; - WBUFW(buf,10)=amount; - WBUFB(buf,12)=ok; - clif_send(buf,packet_len(0x1c8),&sd->bl,AREA); + unsigned char buf[32]; + + WBUFW(buf,0)=0x1c8; + WBUFW(buf,2)=index+2; + if(sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0) + WBUFW(buf,4)=sd->inventory_data[index]->view_id; + else + WBUFW(buf,4)=sd->status.inventory[index].nameid; + WBUFL(buf,6)=sd->bl.id; + WBUFW(buf,10)=amount; + WBUFB(buf,12)=ok; + clif_send(buf,packet_len(0x1c8),&sd->bl,AREA); #endif - } + } } @@ -3459,17 +3504,17 @@ void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok) /// 0 = Room has been successfully created (opens chat room) /// 1 = Room limit exceeded /// 2 = Same room already exists -void clif_createchat(struct map_session_data *sd, int flag) +void clif_createchat(struct map_session_data* sd, int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xd6)); - WFIFOW(fd,0) = 0xd6; - WFIFOB(fd,2) = flag; - WFIFOSET(fd,packet_len(0xd6)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0xd6)); + WFIFOW(fd,0) = 0xd6; + WFIFOB(fd,2) = flag; + WFIFOSET(fd,packet_len(0xd6)); } @@ -3480,34 +3525,34 @@ void clif_createchat(struct map_session_data *sd, int flag) /// 1 = public /// 2 = arena (npc waiting room) /// 3 = PK zone (non-clickable) -void clif_dispchat(struct chat_data *cd, int fd) -{ - unsigned char buf[128]; - uint8 type; - - if (cd == NULL || cd->owner == NULL) - return; - - type = (cd->owner->type == BL_PC) ? (cd->pub) ? 1 : 0 - : (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3 - : 1; - - WBUFW(buf, 0) = 0xd7; - WBUFW(buf, 2) = 17 + strlen(cd->title); - WBUFL(buf, 4) = cd->owner->id; - WBUFL(buf, 8) = cd->bl.id; - WBUFW(buf,12) = cd->limit; - WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users; - WBUFB(buf,16) = type; - memcpy((char *)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated - - if (fd) { - WFIFOHEAD(fd,WBUFW(buf,2)); - memcpy(WFIFOP(fd,0),buf,WBUFW(buf,2)); - WFIFOSET(fd,WBUFW(buf,2)); - } else { - clif_send(buf,WBUFW(buf,2),cd->owner,AREA_WOSC); - } +void clif_dispchat(struct chat_data* cd, int fd) +{ + unsigned char buf[128]; + uint8 type; + + if( cd == NULL || cd->owner == NULL ) + return; + + type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0 + : (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3 + : 1; + + WBUFW(buf, 0) = 0xd7; + WBUFW(buf, 2) = 17 + strlen(cd->title); + WBUFL(buf, 4) = cd->owner->id; + WBUFL(buf, 8) = cd->bl.id; + WBUFW(buf,12) = cd->limit; + WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users; + WBUFB(buf,16) = type; + memcpy((char*)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated + + if( fd ) { + WFIFOHEAD(fd,WBUFW(buf,2)); + memcpy(WFIFOP(fd,0),buf,WBUFW(buf,2)); + WFIFOSET(fd,WBUFW(buf,2)); + } else { + clif_send(buf,WBUFW(buf,2),cd->owner,AREA_WOSC); + } } @@ -3518,28 +3563,28 @@ void clif_dispchat(struct chat_data *cd, int fd) /// 1 = public /// 2 = arena (npc waiting room) /// 3 = PK zone (non-clickable) -void clif_changechatstatus(struct chat_data *cd) +void clif_changechatstatus(struct chat_data* cd) { - unsigned char buf[128]; - uint8 type; + unsigned char buf[128]; + uint8 type; - if (cd == NULL || cd->usersd[0] == NULL) - return; + if( cd == NULL || cd->usersd[0] == NULL ) + return; - type = (cd->owner->type == BL_PC) ? (cd->pub) ? 1 : 0 - : (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3 - : 1; + type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0 + : (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3 + : 1; - WBUFW(buf, 0) = 0xdf; - WBUFW(buf, 2) = 17 + strlen(cd->title); - WBUFL(buf, 4) = cd->owner->id; - WBUFL(buf, 8) = cd->bl.id; - WBUFW(buf,12) = cd->limit; - WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users; - WBUFB(buf,16) = type; - memcpy((char *)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated + WBUFW(buf, 0) = 0xdf; + WBUFW(buf, 2) = 17 + strlen(cd->title); + WBUFL(buf, 4) = cd->owner->id; + WBUFL(buf, 8) = cd->bl.id; + WBUFW(buf,12) = cd->limit; + WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users; + WBUFB(buf,16) = type; + memcpy((char*)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated - clif_send(buf,WBUFW(buf,2),cd->owner,CHAT); + clif_send(buf,WBUFW(buf,2),cd->owner,CHAT); } @@ -3547,19 +3592,19 @@ void clif_changechatstatus(struct chat_data *cd) /// 00d8 <chat id>.L void clif_clearchat(struct chat_data *cd,int fd) { - unsigned char buf[32]; + unsigned char buf[32]; - nullpo_retv(cd); + nullpo_retv(cd); - WBUFW(buf,0) = 0xd8; - WBUFL(buf,2) = cd->bl.id; - if (fd) { - WFIFOHEAD(fd,packet_len(0xd8)); - memcpy(WFIFOP(fd,0),buf,packet_len(0xd8)); - WFIFOSET(fd,packet_len(0xd8)); - } else { - clif_send(buf,packet_len(0xd8),cd->owner,AREA_WOSC); - } + WBUFW(buf,0) = 0xd8; + WBUFL(buf,2) = cd->bl.id; + if( fd ) { + WFIFOHEAD(fd,packet_len(0xd8)); + memcpy(WFIFOP(fd,0),buf,packet_len(0xd8)); + WFIFOSET(fd,packet_len(0xd8)); + } else { + clif_send(buf,packet_len(0xd8),cd->owner,AREA_WOSC); + } } @@ -3576,16 +3621,16 @@ void clif_clearchat(struct chat_data *cd,int fd) /// 7 = unsuitable job class void clif_joinchatfail(struct map_session_data *sd,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; + fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xda)); - WFIFOW(fd,0) = 0xda; - WFIFOB(fd,2) = flag; - WFIFOSET(fd,packet_len(0xda)); + WFIFOHEAD(fd,packet_len(0xda)); + WFIFOW(fd,0) = 0xda; + WFIFOB(fd,2) = flag; + WFIFOSET(fd,packet_len(0xda)); } @@ -3594,53 +3639,53 @@ void clif_joinchatfail(struct map_session_data *sd,int flag) /// role: /// 0 = owner (menu) /// 1 = normal -void clif_joinchatok(struct map_session_data *sd,struct chat_data *cd) -{ - int fd; - int i,t; - - nullpo_retv(sd); - nullpo_retv(cd); - - fd = sd->fd; - if (!session_isActive(fd)) - return; - t = (int)(cd->owner->type == BL_NPC); - WFIFOHEAD(fd, 8 + (28*(cd->users+t))); - WFIFOW(fd, 0) = 0xdb; - WFIFOW(fd, 2) = 8 + (28*(cd->users+t)); - WFIFOL(fd, 4) = cd->bl.id; - - if (cd->owner->type == BL_NPC) { - WFIFOL(fd, 30) = 1; - WFIFOL(fd, 8) = 0; - memcpy(WFIFOP(fd, 12), ((struct npc_data *)cd->owner)->name, NAME_LENGTH); - for (i = 0; i < cd->users; i++) { - WFIFOL(fd, 8+(i+1)*28) = 1; - memcpy(WFIFOP(fd, 8+(i+t)*28+4), cd->usersd[i]->status.name, NAME_LENGTH); - } - } else - for (i = 0; i < cd->users; i++) { - WFIFOL(fd, 8+i*28) = (i != 0 || cd->owner->type == BL_NPC); - memcpy(WFIFOP(fd, 8+(i+t)*28+4), cd->usersd[i]->status.name, NAME_LENGTH); - } - WFIFOSET(fd, WFIFOW(fd, 2)); +void clif_joinchatok(struct map_session_data *sd,struct chat_data* cd) +{ + int fd; + int i,t; + + nullpo_retv(sd); + nullpo_retv(cd); + + fd = sd->fd; + if (!session_isActive(fd)) + return; + t = (int)(cd->owner->type == BL_NPC); + WFIFOHEAD(fd, 8 + (28*(cd->users+t))); + WFIFOW(fd, 0) = 0xdb; + WFIFOW(fd, 2) = 8 + (28*(cd->users+t)); + WFIFOL(fd, 4) = cd->bl.id; + + if(cd->owner->type == BL_NPC){ + WFIFOL(fd, 30) = 1; + WFIFOL(fd, 8) = 0; + memcpy(WFIFOP(fd, 12), ((struct npc_data *)cd->owner)->name, NAME_LENGTH); + for (i = 0; i < cd->users; i++) { + WFIFOL(fd, 8+(i+1)*28) = 1; + memcpy(WFIFOP(fd, 8+(i+t)*28+4), cd->usersd[i]->status.name, NAME_LENGTH); + } + } else + for (i = 0; i < cd->users; i++) { + WFIFOL(fd, 8+i*28) = (i != 0 || cd->owner->type == BL_NPC); + memcpy(WFIFOP(fd, 8+(i+t)*28+4), cd->usersd[i]->status.name, NAME_LENGTH); + } + WFIFOSET(fd, WFIFOW(fd, 2)); } /// Notifies clients in a chat about a new member (ZC_MEMBER_NEWENTRY). /// 00dc <users>.W <name>.24B -void clif_addchat(struct chat_data *cd,struct map_session_data *sd) +void clif_addchat(struct chat_data* cd,struct map_session_data *sd) { - unsigned char buf[32]; + unsigned char buf[32]; - nullpo_retv(sd); - nullpo_retv(cd); + nullpo_retv(sd); + nullpo_retv(cd); - WBUFW(buf, 0) = 0xdc; - WBUFW(buf, 2) = cd->users; - memcpy(WBUFP(buf, 4),sd->status.name,NAME_LENGTH); - clif_send(buf,packet_len(0xdc),&sd->bl,CHAT_WOS); + WBUFW(buf, 0) = 0xdc; + WBUFW(buf, 2) = cd->users; + memcpy(WBUFP(buf, 4),sd->status.name,NAME_LENGTH); + clif_send(buf,packet_len(0xdc),&sd->bl,CHAT_WOS); } @@ -3649,22 +3694,22 @@ void clif_addchat(struct chat_data *cd,struct map_session_data *sd) /// role: /// 0 = owner (menu) /// 1 = normal -void clif_changechatowner(struct chat_data *cd, struct map_session_data *sd) +void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd) { - unsigned char buf[64]; + unsigned char buf[64]; - nullpo_retv(sd); - nullpo_retv(cd); + nullpo_retv(sd); + nullpo_retv(cd); - WBUFW(buf, 0) = 0xe1; - WBUFL(buf, 2) = 1; - memcpy(WBUFP(buf,6),cd->usersd[0]->status.name,NAME_LENGTH); + WBUFW(buf, 0) = 0xe1; + WBUFL(buf, 2) = 1; + memcpy(WBUFP(buf,6),cd->usersd[0]->status.name,NAME_LENGTH); - WBUFW(buf,30) = 0xe1; - WBUFL(buf,32) = 0; - memcpy(WBUFP(buf,36),sd->status.name,NAME_LENGTH); + WBUFW(buf,30) = 0xe1; + WBUFL(buf,32) = 0; + memcpy(WBUFP(buf,36),sd->status.name,NAME_LENGTH); - clif_send(buf,packet_len(0xe1)*2,&sd->bl,CHAT); + clif_send(buf,packet_len(0xe1)*2,&sd->bl,CHAT); } @@ -3673,44 +3718,44 @@ void clif_changechatowner(struct chat_data *cd, struct map_session_data *sd) /// flag: /// 0 = left /// 1 = kicked -void clif_leavechat(struct chat_data *cd, struct map_session_data *sd, bool flag) +void clif_leavechat(struct chat_data* cd, struct map_session_data* sd, bool flag) { - unsigned char buf[32]; + unsigned char buf[32]; - nullpo_retv(sd); - nullpo_retv(cd); + nullpo_retv(sd); + nullpo_retv(cd); - WBUFW(buf, 0) = 0xdd; - WBUFW(buf, 2) = cd->users-1; - memcpy(WBUFP(buf,4),sd->status.name,NAME_LENGTH); - WBUFB(buf,28) = flag; + WBUFW(buf, 0) = 0xdd; + WBUFW(buf, 2) = cd->users-1; + memcpy(WBUFP(buf,4),sd->status.name,NAME_LENGTH); + WBUFB(buf,28) = flag; - clif_send(buf,packet_len(0xdd),&sd->bl,CHAT); + clif_send(buf,packet_len(0xdd),&sd->bl,CHAT); } /// Opens a trade request window from char 'name'. /// 00e5 <nick>.24B (ZC_REQ_EXCHANGE_ITEM) /// 01f4 <nick>.24B <charid>.L <baselvl>.W (ZC_REQ_EXCHANGE_ITEM2) -void clif_traderequest(struct map_session_data *sd, const char *name) +void clif_traderequest(struct map_session_data* sd, const char* name) { - int fd = sd->fd; + int fd = sd->fd; #if PACKETVER < 6 - WFIFOHEAD(fd,packet_len(0xe5)); - WFIFOW(fd,0) = 0xe5; - safestrncpy((char *)WFIFOP(fd,2), name, NAME_LENGTH); - WFIFOSET(fd,packet_len(0xe5)); + WFIFOHEAD(fd,packet_len(0xe5)); + WFIFOW(fd,0) = 0xe5; + safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + WFIFOSET(fd,packet_len(0xe5)); #else - struct map_session_data *tsd = map_id2sd(sd->trade_partner); - if (!tsd) return; - - WFIFOHEAD(fd,packet_len(0x1f4)); - WFIFOW(fd,0) = 0x1f4; - safestrncpy((char *)WFIFOP(fd,2), name, NAME_LENGTH); - WFIFOL(fd,26) = tsd->status.char_id; - WFIFOW(fd,30) = tsd->status.base_level; - WFIFOSET(fd,packet_len(0x1f4)); + struct map_session_data* tsd = map_id2sd(sd->trade_partner); + if( !tsd ) return; + + WFIFOHEAD(fd,packet_len(0x1f4)); + WFIFOW(fd,0) = 0x1f4; + safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + WFIFOL(fd,26) = tsd->status.char_id; + WFIFOW(fd,30) = tsd->status.base_level; + WFIFOSET(fd,packet_len(0x1f4)); #endif } @@ -3725,85 +3770,88 @@ void clif_traderequest(struct map_session_data *sd, const char *name) /// 3 = Accept /// 4 = Cancel /// 5 = Busy -void clif_tradestart(struct map_session_data *sd, uint8 type) -{ - int fd = sd->fd; - struct map_session_data *tsd = map_id2sd(sd->trade_partner); - if (PACKETVER < 6 || !tsd) { - WFIFOHEAD(fd,packet_len(0xe7)); - WFIFOW(fd,0) = 0xe7; - WFIFOB(fd,2) = type; - WFIFOSET(fd,packet_len(0xe7)); - } else { - WFIFOHEAD(fd,packet_len(0x1f5)); - WFIFOW(fd,0) = 0x1f5; - WFIFOB(fd,2) = type; - WFIFOL(fd,3) = tsd->status.char_id; - WFIFOW(fd,7) = tsd->status.base_level; - WFIFOSET(fd,packet_len(0x1f5)); - } +void clif_tradestart(struct map_session_data* sd, uint8 type) +{ + int fd = sd->fd; + struct map_session_data* tsd = map_id2sd(sd->trade_partner); + if( PACKETVER < 6 || !tsd ) { + WFIFOHEAD(fd,packet_len(0xe7)); + WFIFOW(fd,0) = 0xe7; + WFIFOB(fd,2) = type; + WFIFOSET(fd,packet_len(0xe7)); + } else { + WFIFOHEAD(fd,packet_len(0x1f5)); + WFIFOW(fd,0) = 0x1f5; + WFIFOB(fd,2) = type; + WFIFOL(fd,3) = tsd->status.char_id; + WFIFOW(fd,7) = tsd->status.base_level; + WFIFOSET(fd,packet_len(0x1f5)); + } } /// Notifies the client about an item from other player in current trade. /// 00e9 <amount>.L <nameid>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_EXCHANGE_ITEM) /// 080f <nameid>.W <item type>.B <amount>.L <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_EXCHANGE_ITEM2) -void clif_tradeadditem(struct map_session_data *sd, struct map_session_data *tsd, int index, int amount) +void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd, int index, int amount) { - int fd; - unsigned char *buf; + int fd; + unsigned char *buf; #if PACKETVER < 20100223 - const int cmd = 0xe9; + const int cmd = 0xe9; #else - const int cmd = 0x80f; + const int cmd = 0x80f; #endif - nullpo_retv(sd); - nullpo_retv(tsd); - - fd = tsd->fd; - buf = WFIFOP(fd,0); - WFIFOHEAD(fd,packet_len(cmd)); - WBUFW(buf,0) = cmd; - if (index == 0) { + nullpo_retv(sd); + nullpo_retv(tsd); + + fd = tsd->fd; + buf = WFIFOP(fd,0); + WFIFOHEAD(fd,packet_len(cmd)); + WBUFW(buf,0) = cmd; + if( index == 0 ) + { #if PACKETVER < 20100223 - WBUFL(buf,2) = amount; //amount - WBUFW(buf,6) = 0; // type id + WBUFL(buf,2) = amount; //amount + WBUFW(buf,6) = 0; // type id #else - WBUFW(buf,2) = 0; // type id - WBUFB(buf,4) = 0; // item type - WBUFL(buf,5) = amount; // amount - buf = WBUFP(buf,1); //Advance 1B + WBUFW(buf,2) = 0; // type id + WBUFB(buf,4) = 0; // item type + WBUFL(buf,5) = amount; // amount + buf = WBUFP(buf,1); //Advance 1B #endif - WBUFB(buf,8) = 0; //identify flag - WBUFB(buf,9) = 0; // attribute - WBUFB(buf,10)= 0; //refine - WBUFW(buf,11)= 0; //card (4w) - WBUFW(buf,13)= 0; //card (4w) - WBUFW(buf,15)= 0; //card (4w) - WBUFW(buf,17)= 0; //card (4w) - } else { - index -= 2; //index fix + WBUFB(buf,8) = 0; //identify flag + WBUFB(buf,9) = 0; // attribute + WBUFB(buf,10)= 0; //refine + WBUFW(buf,11)= 0; //card (4w) + WBUFW(buf,13)= 0; //card (4w) + WBUFW(buf,15)= 0; //card (4w) + WBUFW(buf,17)= 0; //card (4w) + } + else + { + index -= 2; //index fix #if PACKETVER < 20100223 - WBUFL(buf,2) = amount; //amount - if (sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0) - WBUFW(buf,6) = sd->inventory_data[index]->view_id; - else - WBUFW(buf,6) = sd->status.inventory[index].nameid; // type id + WBUFL(buf,2) = amount; //amount + if(sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0) + WBUFW(buf,6) = sd->inventory_data[index]->view_id; + else + WBUFW(buf,6) = sd->status.inventory[index].nameid; // type id #else - if (sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0) - WBUFW(buf,2) = sd->inventory_data[index]->view_id; - else - WBUFW(buf,2) = sd->status.inventory[index].nameid; // type id - WBUFB(buf,4) = sd->inventory_data[index]->type; // item type - WBUFL(buf,5) = amount; // amount - buf = WBUFP(buf,1); //Advance 1B + if(sd->inventory_data[index] && sd->inventory_data[index]->view_id > 0) + WBUFW(buf,2) = sd->inventory_data[index]->view_id; + else + WBUFW(buf,2) = sd->status.inventory[index].nameid; // type id + WBUFB(buf,4) = sd->inventory_data[index]->type; // item type + WBUFL(buf,5) = amount; // amount + buf = WBUFP(buf,1); //Advance 1B #endif - WBUFB(buf,8) = sd->status.inventory[index].identify; //identify flag - WBUFB(buf,9) = sd->status.inventory[index].attribute; // attribute - WBUFB(buf,10)= sd->status.inventory[index].refine; //refine - clif_addcards(WBUFP(buf, 11), &sd->status.inventory[index]); - } - WFIFOSET(fd,packet_len(cmd)); + WBUFB(buf,8) = sd->status.inventory[index].identify; //identify flag + WBUFB(buf,9) = sd->status.inventory[index].attribute; // attribute + WBUFB(buf,10)= sd->status.inventory[index].refine; //refine + clif_addcards(WBUFP(buf, 11), &sd->status.inventory[index]); + } + WFIFOSET(fd,packet_len(cmd)); } @@ -3813,17 +3861,17 @@ void clif_tradeadditem(struct map_session_data *sd, struct map_session_data *tsd /// 0 = success /// 1 = overweight /// 2 = trade canceled -void clif_tradeitemok(struct map_session_data *sd, int index, int fail) +void clif_tradeitemok(struct map_session_data* sd, int index, int fail) { - int fd; - nullpo_retv(sd); + int fd; + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xea)); - WFIFOW(fd,0) = 0xea; - WFIFOW(fd,2) = index; - WFIFOB(fd,4) = fail; - WFIFOSET(fd,packet_len(0xea)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0xea)); + WFIFOW(fd,0) = 0xea; + WFIFOW(fd,2) = index; + WFIFOB(fd,4) = fail; + WFIFOSET(fd,packet_len(0xea)); } @@ -3832,30 +3880,30 @@ void clif_tradeitemok(struct map_session_data *sd, int index, int fail) /// who: /// 0 = self /// 1 = other player -void clif_tradedeal_lock(struct map_session_data *sd, int fail) +void clif_tradedeal_lock(struct map_session_data* sd, int fail) { - int fd; - nullpo_retv(sd); + int fd; + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xec)); - WFIFOW(fd,0) = 0xec; - WFIFOB(fd,2) = fail; - WFIFOSET(fd,packet_len(0xec)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0xec)); + WFIFOW(fd,0) = 0xec; + WFIFOB(fd,2) = fail; + WFIFOSET(fd,packet_len(0xec)); } /// Notifies the client about the trade being canceled (ZC_CANCEL_EXCHANGE_ITEM). /// 00ee -void clif_tradecancelled(struct map_session_data *sd) +void clif_tradecancelled(struct map_session_data* sd) { - int fd; - nullpo_retv(sd); + int fd; + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xee)); - WFIFOW(fd,0) = 0xee; - WFIFOSET(fd,packet_len(0xee)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0xee)); + WFIFOW(fd,0) = 0xee; + WFIFOSET(fd,packet_len(0xee)); } @@ -3864,16 +3912,16 @@ void clif_tradecancelled(struct map_session_data *sd) /// result: /// 0 = success /// 1 = failure -void clif_tradecompleted(struct map_session_data *sd, int fail) +void clif_tradecompleted(struct map_session_data* sd, int fail) { - int fd; - nullpo_retv(sd); + int fd; + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xf0)); - WFIFOW(fd,0) = 0xf0; - WFIFOB(fd,2) = fail; - WFIFOSET(fd,packet_len(0xf0)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0xf0)); + WFIFOW(fd,0) = 0xf0; + WFIFOB(fd,2) = fail; + WFIFOSET(fd,packet_len(0xf0)); } @@ -3881,231 +3929,235 @@ void clif_tradecompleted(struct map_session_data *sd, int fail) /// 00f1 /// NOTE: Unknown purpose. Items are not removed until the window is /// refreshed (ex. by putting another item in there). -void clif_tradeundo(struct map_session_data *sd) +void clif_tradeundo(struct map_session_data* sd) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xf1)); - WFIFOW(fd,0) = 0xf1; - WFIFOSET(fd,packet_len(0xf1)); + WFIFOHEAD(fd,packet_len(0xf1)); + WFIFOW(fd,0) = 0xf1; + WFIFOSET(fd,packet_len(0xf1)); } /// Updates storage total amount (ZC_NOTIFY_STOREITEM_COUNTINFO). /// 00f2 <current count>.W <max count>.W -void clif_updatestorageamount(struct map_session_data *sd, int amount, int max_amount) +void clif_updatestorageamount(struct map_session_data* sd, int amount, int max_amount) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xf2)); - WFIFOW(fd,0) = 0xf2; - WFIFOW(fd,2) = amount; - WFIFOW(fd,4) = max_amount; - WFIFOSET(fd,packet_len(0xf2)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xf2)); + WFIFOW(fd,0) = 0xf2; + WFIFOW(fd,2) = amount; + WFIFOW(fd,4) = max_amount; + WFIFOSET(fd,packet_len(0xf2)); } /// Notifies the client of an item being added to the storage. /// 00f4 <index>.W <amount>.L <nameid>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_ITEM_TO_STORE) /// 01c4 <index>.W <amount>.L <nameid>.W <type>.B <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_ITEM_TO_STORE2) -void clif_storageitemadded(struct map_session_data *sd, struct item *i, int index, int amount) +void clif_storageitemadded(struct map_session_data* sd, struct item* i, int index, int amount) { - int view,fd; + int view,fd; - nullpo_retv(sd); - nullpo_retv(i); - fd=sd->fd; - view = itemdb_viewid(i->nameid); + nullpo_retv(sd); + nullpo_retv(i); + fd=sd->fd; + view = itemdb_viewid(i->nameid); #if PACKETVER < 5 - WFIFOHEAD(fd,packet_len(0xf4)); - WFIFOW(fd, 0) = 0xf4; // Storage item added - WFIFOW(fd, 2) = index+1; // index - WFIFOL(fd, 4) = amount; // amount - WFIFOW(fd, 8) = (view > 0) ? view : i->nameid; // id - WFIFOB(fd,10) = i->identify; //identify flag - WFIFOB(fd,11) = i->attribute; // attribute - WFIFOB(fd,12) = i->refine; //refine - clif_addcards(WFIFOP(fd,13), i); - WFIFOSET(fd,packet_len(0xf4)); + WFIFOHEAD(fd,packet_len(0xf4)); + WFIFOW(fd, 0) = 0xf4; // Storage item added + WFIFOW(fd, 2) = index+1; // index + WFIFOL(fd, 4) = amount; // amount + WFIFOW(fd, 8) = ( view > 0 ) ? view : i->nameid; // id + WFIFOB(fd,10) = i->identify; //identify flag + WFIFOB(fd,11) = i->attribute; // attribute + WFIFOB(fd,12) = i->refine; //refine + clif_addcards(WFIFOP(fd,13), i); + WFIFOSET(fd,packet_len(0xf4)); #else - WFIFOHEAD(fd,packet_len(0x1c4)); - WFIFOW(fd, 0) = 0x1c4; // Storage item added - WFIFOW(fd, 2) = index+1; // index - WFIFOL(fd, 4) = amount; // amount - WFIFOW(fd, 8) = (view > 0) ? view : i->nameid; // id - WFIFOB(fd,10) = itemdb_type(i->nameid); //type - WFIFOB(fd,11) = i->identify; //identify flag - WFIFOB(fd,12) = i->attribute; // attribute - WFIFOB(fd,13) = i->refine; //refine - clif_addcards(WFIFOP(fd,14), i); - WFIFOSET(fd,packet_len(0x1c4)); + WFIFOHEAD(fd,packet_len(0x1c4)); + WFIFOW(fd, 0) = 0x1c4; // Storage item added + WFIFOW(fd, 2) = index+1; // index + WFIFOL(fd, 4) = amount; // amount + WFIFOW(fd, 8) = ( view > 0 ) ? view : i->nameid; // id + WFIFOB(fd,10) = itemdb_type(i->nameid); //type + WFIFOB(fd,11) = i->identify; //identify flag + WFIFOB(fd,12) = i->attribute; // attribute + WFIFOB(fd,13) = i->refine; //refine + clif_addcards(WFIFOP(fd,14), i); + WFIFOSET(fd,packet_len(0x1c4)); #endif } /// Notifies the client of an item being deleted from the storage (ZC_DELETE_ITEM_FROM_STORE). /// 00f6 <index>.W <amount>.L -void clif_storageitemremoved(struct map_session_data *sd, int index, int amount) +void clif_storageitemremoved(struct map_session_data* sd, int index, int amount) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xf6)); - WFIFOW(fd,0)=0xf6; // Storage item removed - WFIFOW(fd,2)=index+1; - WFIFOL(fd,4)=amount; - WFIFOSET(fd,packet_len(0xf6)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xf6)); + WFIFOW(fd,0)=0xf6; // Storage item removed + WFIFOW(fd,2)=index+1; + WFIFOL(fd,4)=amount; + WFIFOSET(fd,packet_len(0xf6)); } /// Closes storage (ZC_CLOSE_STORE). /// 00f8 -void clif_storageclose(struct map_session_data *sd) +void clif_storageclose(struct map_session_data* sd) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xf8)); - WFIFOW(fd,0) = 0xf8; // Storage Closed - WFIFOSET(fd,packet_len(0xf8)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xf8)); + WFIFOW(fd,0) = 0xf8; // Storage Closed + WFIFOSET(fd,packet_len(0xf8)); } /*========================================== * Server tells 'sd' player client the abouts of 'dstsd' player *------------------------------------------*/ -static void clif_getareachar_pc(struct map_session_data *sd,struct map_session_data *dstsd) -{ - struct block_list *d_bl; - int i; - - if (dstsd->chatID) { - struct chat_data *cd = NULL; - if ((cd = (struct chat_data *)map_id2bl(dstsd->chatID)) && cd->usersd[0]==dstsd) - clif_dispchat(cd,sd->fd); - } else if (dstsd->state.vending) - clif_showvendingboard(&dstsd->bl,dstsd->message,sd->fd); - else if (dstsd->state.buyingstore) - clif_buyingstore_entry_single(sd, dstsd); - - if (dstsd->spiritball > 0) - clif_spiritball_single(sd->fd, dstsd); - for (i = 1; i < 5; i++) { - if (dstsd->talisman[i] > 0) - clif_talisman_single(sd->fd, dstsd, i); - } - if (dstsd->sc.option&OPTION_MOUNTING) { - //New Mounts are not complaint to the original method, so we gotta tell this guy that I'm mounting. - clif_status_load_single(sd->fd,dstsd->bl.id,SI_ALL_RIDING,2,1,0,0); - } +static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* dstsd) +{ + struct block_list *d_bl; + int i; + + if( dstsd->chatID ) { + struct chat_data *cd = NULL; + if( (cd = (struct chat_data*)map_id2bl(dstsd->chatID)) && cd->usersd[0]==dstsd) + clif_dispchat(cd,sd->fd); + } else if( dstsd->state.vending ) + clif_showvendingboard(&dstsd->bl,dstsd->message,sd->fd); + else if( dstsd->state.buyingstore ) + clif_buyingstore_entry_single(sd, dstsd); + + if(dstsd->spiritball > 0) + clif_spiritball_single(sd->fd, dstsd); + for(i = 1; i < 5; i++){ + if( dstsd->talisman[i] > 0 ) + clif_talisman_single(sd->fd, dstsd, i); + } + if( dstsd->sc.option&OPTION_MOUNTING ) { + //New Mounts are not complaint to the original method, so we gotta tell this guy that I'm mounting. + clif_status_load_single(sd->fd,dstsd->bl.id,SI_ALL_RIDING,2,1,0,0); + } #ifdef NEW_CARTS - if (dstsd->sc.data[SC_PUSH_CART]) - clif_status_load_single(sd->fd, dstsd->bl.id, SI_ON_PUSH_CART, 2, dstsd->sc.data[SC_PUSH_CART]->val1, 0, 0); + if( dstsd->sc.data[SC_PUSH_CART] ) + clif_status_load_single(sd->fd, dstsd->bl.id, SI_ON_PUSH_CART, 2, dstsd->sc.data[SC_PUSH_CART]->val1, 0, 0); #endif - if ((sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting. - (sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround - pc_has_permission(sd, PC_PERM_VIEW_HPMETER) - ) - clif_hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp); - - // display link (sd - dstsd) to sd - ARR_FIND(0, 5, i, sd->devotion[i] == dstsd->bl.id); - if (i < 5) clif_devotion(&sd->bl, sd); - // display links (dstsd - devotees) to sd - ARR_FIND(0, 5, i, dstsd->devotion[i] > 0); - if (i < 5) clif_devotion(&dstsd->bl, sd); - // display link (dstsd - crusader) to sd - if (dstsd->sc.data[SC_DEVOTION] && (d_bl = map_id2bl(dstsd->sc.data[SC_DEVOTION]->val1)) != NULL) - clif_devotion(d_bl, sd); -} - -void clif_getareachar_unit(struct map_session_data *sd,struct block_list *bl) -{ - uint8 buf[128]; - struct unit_data *ud; - struct view_data *vd; - int len; - - vd = status_get_viewdata(bl); - if (!vd || vd->class_ == INVISIBLE_CLASS) - return; - - /** - * Hide NPC from maya purple card. - **/ - if (bl->type == BL_NPC && !((TBL_NPC *)bl)->chat_id && (((TBL_NPC *)bl)->sc.option&OPTION_INVISIBLE)) - return; - - ud = unit_bl2ud(bl); - len = (ud && ud->walktimer != INVALID_TIMER) ? clif_set_unit_walking(bl,ud,buf) : clif_set_unit_idle(bl,buf,false); - clif_send(buf,len,&sd->bl,SELF); - - if (vd->cloth_color) - clif_refreshlook(&sd->bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,SELF); - - switch (bl->type) { - case BL_PC: { - TBL_PC *tsd = (TBL_PC *)bl; - clif_getareachar_pc(sd, tsd); - if (tsd->state.size==SZ_BIG) // tiny/big players [Valaris] - clif_specialeffect_single(bl,423,sd->fd); - else if (tsd->state.size==SZ_MEDIUM) - clif_specialeffect_single(bl,421,sd->fd); - if (tsd->bg_id && map[tsd->bl.m].flag.battleground) - clif_sendbgemblem_single(sd->fd,tsd); - if (tsd->sc.data[SC_CAMOUFLAGE]) - clif_status_load(bl,SI_CAMOUFLAGE,1); - } - break; - case BL_MER: // Devotion Effects - if (((TBL_MER *)bl)->devotion_flag) - clif_devotion(bl, sd); - break; - case BL_NPC: { - TBL_NPC *nd = (TBL_NPC *)bl; - if (nd->chat_id) - clif_dispchat((struct chat_data *)map_id2bl(nd->chat_id),sd->fd); - if (nd->size == SZ_BIG) - clif_specialeffect_single(bl,423,sd->fd); - else if (nd->size == SZ_MEDIUM) - clif_specialeffect_single(bl,421,sd->fd); - } - break; - case BL_MOB: { - TBL_MOB *md = (TBL_MOB *)bl; - if (md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] - clif_specialeffect_single(bl,423,sd->fd); - else if (md->special_state.size==SZ_MEDIUM) - clif_specialeffect_single(bl,421,sd->fd); + if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting. + (sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround + pc_has_permission(sd, PC_PERM_VIEW_HPMETER) + ) + clif_hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp); + + // display link (sd - dstsd) to sd + ARR_FIND( 0, 5, i, sd->devotion[i] == dstsd->bl.id ); + if( i < 5 ) clif_devotion(&sd->bl, sd); + // display links (dstsd - devotees) to sd + ARR_FIND( 0, 5, i, dstsd->devotion[i] > 0 ); + if( i < 5 ) clif_devotion(&dstsd->bl, sd); + // display link (dstsd - crusader) to sd + if( dstsd->sc.data[SC_DEVOTION] && (d_bl = map_id2bl(dstsd->sc.data[SC_DEVOTION]->val1)) != NULL ) + clif_devotion(d_bl, sd); +} + +void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) +{ + uint8 buf[128]; + struct unit_data *ud; + struct view_data *vd; + int len; + + vd = status_get_viewdata(bl); + if (!vd || vd->class_ == INVISIBLE_CLASS) + return; + + /** + * Hide NPC from maya purple card. + **/ + if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE)) + return; + + ud = unit_bl2ud(bl); + len = ( ud && ud->walktimer != INVALID_TIMER ) ? clif_set_unit_walking(bl,ud,buf) : clif_set_unit_idle(bl,buf,false); + clif_send(buf,len,&sd->bl,SELF); + + if (vd->cloth_color) + clif_refreshlook(&sd->bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,SELF); + + switch (bl->type) + { + case BL_PC: + { + TBL_PC* tsd = (TBL_PC*)bl; + clif_getareachar_pc(sd, tsd); + if(tsd->state.size==SZ_BIG) // tiny/big players [Valaris] + clif_specialeffect_single(bl,423,sd->fd); + else if(tsd->state.size==SZ_MEDIUM) + clif_specialeffect_single(bl,421,sd->fd); + if( tsd->bg_id && map[tsd->bl.m].flag.battleground ) + clif_sendbgemblem_single(sd->fd,tsd); + if( tsd->sc.data[SC_CAMOUFLAGE] ) + clif_status_load(bl,SI_CAMOUFLAGE,1); + } + break; + case BL_MER: // Devotion Effects + if( ((TBL_MER*)bl)->devotion_flag ) + clif_devotion(bl, sd); + break; + case BL_NPC: + { + TBL_NPC* nd = (TBL_NPC*)bl; + if( nd->chat_id ) + clif_dispchat((struct chat_data*)map_id2bl(nd->chat_id),sd->fd); + if( nd->size == SZ_BIG ) + clif_specialeffect_single(bl,423,sd->fd); + else if( nd->size == SZ_MEDIUM ) + clif_specialeffect_single(bl,421,sd->fd); + } + break; + case BL_MOB: + { + TBL_MOB* md = (TBL_MOB*)bl; + if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] + clif_specialeffect_single(bl,423,sd->fd); + else if(md->special_state.size==SZ_MEDIUM) + clif_specialeffect_single(bl,421,sd->fd); #if PACKETVER >= 20120404 - if (!(md->status.mode&MD_BOSS)) { - int i; - for (i = 0; i < DAMAGELOG_SIZE; i++) // must show hp bar to all char who already hit the mob. - if (md->dmglog[i].id == sd->status.char_id) - clif_monster_hp_bar(md, sd->fd); - } + if( !(md->status.mode&MD_BOSS) ){ + int i; + for(i = 0; i < DAMAGELOG_SIZE; i++)// must show hp bar to all char who already hit the mob. + if( md->dmglog[i].id == sd->status.char_id ) + clif_monster_hp_bar(md, sd->fd); + } #endif - } - break; - case BL_PET: - if (vd->head_bottom) - clif_pet_equip(sd, (TBL_PET *)bl); // needed to display pet equip properly - break; - } + } + break; + case BL_PET: + if (vd->head_bottom) + clif_pet_equip(sd, (TBL_PET*)bl); // needed to display pet equip properly + break; + } } //Modifies the type of damage according to status changes [Skotlex] //Aegis data specifies that: 4 endure against single hit sources, 9 against multi-hit. static inline int clif_calc_delay(int type, int div, int damage, int delay) { - return (delay == 0 && damage > 0) ? (div > 1 ? 9 : 4) : type; + return ( delay == 0 && damage > 0 ) ? ( div > 1 ? 9 : 4 ) : type; } /*========================================== @@ -4113,19 +4165,20 @@ static inline int clif_calc_delay(int type, int div, int damage, int delay) *------------------------------------------*/ static int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, int div_) { - if (type == 4 || type == 9 || damage <=0) - return 0; + if (type == 4 || type == 9 || damage <=0) + return 0; - if (bl->type == BL_PC) { - if (battle_config.pc_walk_delay_rate != 100) - delay = delay*battle_config.pc_walk_delay_rate/100; - } else if (battle_config.walk_delay_rate != 100) - delay = delay*battle_config.walk_delay_rate/100; + if (bl->type == BL_PC) { + if (battle_config.pc_walk_delay_rate != 100) + delay = delay*battle_config.pc_walk_delay_rate/100; + } else + if (battle_config.walk_delay_rate != 100) + delay = delay*battle_config.walk_delay_rate/100; - if (div_ > 1) //Multi-hit skills mean higher delays. - delay += battle_config.multihit_delay*(div_-1); + if (div_ > 1) //Multi-hit skills mean higher delays. + delay += battle_config.multihit_delay*(div_-1); - return delay>0?delay:1; //Return 1 to specify there should be no noticeable delay, but you should stop walking. + return delay>0?delay:1; //Return 1 to specify there should be no noticeable delay, but you should stop walking. } @@ -4146,138 +4199,138 @@ static int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int da /// 10 = critical hit /// 11 = lucky dodge /// 12 = (touch skill?) -int clif_damage(struct block_list *src, struct block_list *dst, unsigned int tick, int sdelay, int ddelay, int damage, int div, int type, int damage2) +int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int damage, int div, int type, int damage2) { - unsigned char buf[33]; - struct status_change *sc; + unsigned char buf[33]; + struct status_change *sc; #if PACKETVER < 20071113 - const int cmd = 0x8a; + const int cmd = 0x8a; #else - const int cmd = 0x2e1; + const int cmd = 0x2e1; #endif - nullpo_ret(src); - nullpo_ret(dst); - - type = clif_calc_delay(type,div,damage+damage2,ddelay); - sc = status_get_sc(dst); - if (sc && sc->count) { - if (sc->data[SC_HALLUCINATION]) { - if (damage) damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; - if (damage2) damage2 = damage2*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; - } - } - - WBUFW(buf,0)=cmd; - WBUFL(buf,2)=src->id; - WBUFL(buf,6)=dst->id; - WBUFL(buf,10)=tick; - WBUFL(buf,14)=sdelay; - WBUFL(buf,18)=ddelay; + nullpo_ret(src); + nullpo_ret(dst); + + type = clif_calc_delay(type,div,damage+damage2,ddelay); + sc = status_get_sc(dst); + if(sc && sc->count) { + if(sc->data[SC_HALLUCINATION]) { + if(damage) damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; + if(damage2) damage2 = damage2*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; + } + } + + WBUFW(buf,0)=cmd; + WBUFL(buf,2)=src->id; + WBUFL(buf,6)=dst->id; + WBUFL(buf,10)=tick; + WBUFL(buf,14)=sdelay; + WBUFL(buf,18)=ddelay; #if PACKETVER < 20071113 - if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) { - WBUFW(buf,22)=damage?div:0; - WBUFW(buf,27)=damage2?div:0; - } else { - WBUFW(buf,22)=min(damage, INT16_MAX); - WBUFW(buf,27)=damage2; - } - WBUFW(buf,24)=div; - WBUFB(buf,26)=type; + if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) { + WBUFW(buf,22)=damage?div:0; + WBUFW(buf,27)=damage2?div:0; + } else { + WBUFW(buf,22)=min(damage, INT16_MAX); + WBUFW(buf,27)=damage2; + } + WBUFW(buf,24)=div; + WBUFB(buf,26)=type; #else - if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) { - WBUFL(buf,22)=damage?div:0; - WBUFL(buf,29)=damage2?div:0; - } else { - WBUFL(buf,22)=damage; - WBUFL(buf,29)=damage2; - } - WBUFW(buf,26)=div; - WBUFB(buf,28)=type; + if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) { + WBUFL(buf,22)=damage?div:0; + WBUFL(buf,29)=damage2?div:0; + } else { + WBUFL(buf,22)=damage; + WBUFL(buf,29)=damage2; + } + WBUFW(buf,26)=div; + WBUFB(buf,28)=type; #endif - if (disguised(dst)) { - clif_send(buf,packet_len(cmd),dst,AREA_WOS); - WBUFL(buf,6) = -dst->id; - clif_send(buf,packet_len(cmd),dst,SELF); - } else - clif_send(buf,packet_len(cmd),dst,AREA); - - if (disguised(src)) { - WBUFL(buf,2) = -src->id; - if (disguised(dst)) - WBUFL(buf,6) = dst->id; + if(disguised(dst)) { + clif_send(buf,packet_len(cmd),dst,AREA_WOS); + WBUFL(buf,6) = -dst->id; + clif_send(buf,packet_len(cmd),dst,SELF); + } else + clif_send(buf,packet_len(cmd),dst,AREA); + + if(disguised(src)) { + WBUFL(buf,2) = -src->id; + if (disguised(dst)) + WBUFL(buf,6) = dst->id; #if PACKETVER < 20071113 - if (damage > 0) WBUFW(buf,22) = -1; - if (damage2 > 0) WBUFW(buf,27) = -1; + if(damage > 0) WBUFW(buf,22) = -1; + if(damage2 > 0) WBUFW(buf,27) = -1; #else - if (damage > 0) WBUFL(buf,22) = -1; - if (damage2 > 0) WBUFL(buf,29) = -1; + if(damage > 0) WBUFL(buf,22) = -1; + if(damage2 > 0) WBUFL(buf,29) = -1; #endif - clif_send(buf,packet_len(cmd),src,SELF); - } + clif_send(buf,packet_len(cmd),src,SELF); + } - if (src == dst) { - unit_setdir(src,unit_getdir(src)); - } - //Return adjusted can't walk delay for further processing. - return clif_calc_walkdelay(dst,ddelay,type,damage+damage2,div); + if(src == dst) { + unit_setdir(src,unit_getdir(src)); + } + //Return adjusted can't walk delay for further processing. + return clif_calc_walkdelay(dst,ddelay,type,damage+damage2,div); } /*========================================== * src picks up dst *------------------------------------------*/ -void clif_takeitem(struct block_list *src, struct block_list *dst) +void clif_takeitem(struct block_list* src, struct block_list* dst) { - //clif_damage(src,dst,0,0,0,0,0,1,0); - unsigned char buf[32]; + //clif_damage(src,dst,0,0,0,0,0,1,0); + unsigned char buf[32]; - nullpo_retv(src); - nullpo_retv(dst); + nullpo_retv(src); + nullpo_retv(dst); - WBUFW(buf, 0) = 0x8a; - WBUFL(buf, 2) = src->id; - WBUFL(buf, 6) = dst->id; - WBUFB(buf,26) = 1; - clif_send(buf, packet_len(0x8a), src, AREA); + WBUFW(buf, 0) = 0x8a; + WBUFL(buf, 2) = src->id; + WBUFL(buf, 6) = dst->id; + WBUFB(buf,26) = 1; + clif_send(buf, packet_len(0x8a), src, AREA); } /*========================================== * inform clients in area that `bl` is sitting *------------------------------------------*/ -void clif_sitting(struct block_list *bl) +void clif_sitting(struct block_list* bl) { - unsigned char buf[32]; - nullpo_retv(bl); + unsigned char buf[32]; + nullpo_retv(bl); - WBUFW(buf, 0) = 0x8a; - WBUFL(buf, 2) = bl->id; - WBUFB(buf,26) = 2; - clif_send(buf, packet_len(0x8a), bl, AREA); + WBUFW(buf, 0) = 0x8a; + WBUFL(buf, 2) = bl->id; + WBUFB(buf,26) = 2; + clif_send(buf, packet_len(0x8a), bl, AREA); - if (disguised(bl)) { - WBUFL(buf, 2) = - bl->id; - clif_send(buf, packet_len(0x8a), bl, SELF); - } + if(disguised(bl)) { + WBUFL(buf, 2) = - bl->id; + clif_send(buf, packet_len(0x8a), bl, SELF); + } } /*========================================== * inform clients in area that `bl` is standing *------------------------------------------*/ -void clif_standing(struct block_list *bl) +void clif_standing(struct block_list* bl) { - unsigned char buf[32]; - nullpo_retv(bl); + unsigned char buf[32]; + nullpo_retv(bl); - WBUFW(buf, 0) = 0x8a; - WBUFL(buf, 2) = bl->id; - WBUFB(buf,26) = 3; - clif_send(buf, packet_len(0x8a), bl, AREA); + WBUFW(buf, 0) = 0x8a; + WBUFL(buf, 2) = bl->id; + WBUFB(buf,26) = 3; + clif_send(buf, packet_len(0x8a), bl, AREA); - if (disguised(bl)) { - WBUFL(buf, 2) = - bl->id; - clif_send(buf, packet_len(0x8a), bl, SELF); - } + if(disguised(bl)) { + WBUFL(buf, 2) = - bl->id; + clif_send(buf, packet_len(0x8a), bl, SELF); + } } @@ -4285,50 +4338,53 @@ void clif_standing(struct block_list *bl) /// 0192 <x>.W <y>.W <type>.W <map name>.16B void clif_changemapcell(int fd, int m, int x, int y, int type, enum send_target target) { - unsigned char buf[32]; - - WBUFW(buf,0) = 0x192; - WBUFW(buf,2) = x; - WBUFW(buf,4) = y; - WBUFW(buf,6) = type; - mapindex_getmapname_ext(map[m].name,(char *)WBUFP(buf,8)); - - if (fd) { - WFIFOHEAD(fd,packet_len(0x192)); - memcpy(WFIFOP(fd,0), buf, packet_len(0x192)); - WFIFOSET(fd,packet_len(0x192)); - } else { - struct block_list dummy_bl; - dummy_bl.type = BL_NUL; - dummy_bl.x = x; - dummy_bl.y = y; - dummy_bl.m = m; - clif_send(buf,packet_len(0x192),&dummy_bl,target); - } + unsigned char buf[32]; + + WBUFW(buf,0) = 0x192; + WBUFW(buf,2) = x; + WBUFW(buf,4) = y; + WBUFW(buf,6) = type; + mapindex_getmapname_ext(map[m].name,(char*)WBUFP(buf,8)); + + if( fd ) + { + WFIFOHEAD(fd,packet_len(0x192)); + memcpy(WFIFOP(fd,0), buf, packet_len(0x192)); + WFIFOSET(fd,packet_len(0x192)); + } + else + { + struct block_list dummy_bl; + dummy_bl.type = BL_NUL; + dummy_bl.x = x; + dummy_bl.y = y; + dummy_bl.m = m; + clif_send(buf,packet_len(0x192),&dummy_bl,target); + } } /// Notifies the client about an item on floor (ZC_ITEM_ENTRY). /// 009d <id>.L <name id>.W <identified>.B <x>.W <y>.W <amount>.W <subX>.B <subY>.B -void clif_getareachar_item(struct map_session_data *sd,struct flooritem_data *fitem) +void clif_getareachar_item(struct map_session_data* sd,struct flooritem_data* fitem) { - int view,fd; - fd=sd->fd; + int view,fd; + fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x9d)); - WFIFOW(fd,0)=0x9d; - WFIFOL(fd,2)=fitem->bl.id; - if ((view = itemdb_viewid(fitem->item_data.nameid)) > 0) - WFIFOW(fd,6)=view; - else - WFIFOW(fd,6)=fitem->item_data.nameid; - WFIFOB(fd,8)=fitem->item_data.identify; - WFIFOW(fd,9)=fitem->bl.x; - WFIFOW(fd,11)=fitem->bl.y; - WFIFOW(fd,13)=fitem->item_data.amount; - WFIFOB(fd,15)=fitem->subx; - WFIFOB(fd,16)=fitem->suby; - WFIFOSET(fd,packet_len(0x9d)); + WFIFOHEAD(fd,packet_len(0x9d)); + WFIFOW(fd,0)=0x9d; + WFIFOL(fd,2)=fitem->bl.id; + if((view = itemdb_viewid(fitem->item_data.nameid)) > 0) + WFIFOW(fd,6)=view; + else + WFIFOW(fd,6)=fitem->item_data.nameid; + WFIFOB(fd,8)=fitem->item_data.identify; + WFIFOW(fd,9)=fitem->bl.x; + WFIFOW(fd,11)=fitem->bl.y; + WFIFOW(fd,13)=fitem->item_data.amount; + WFIFOB(fd,15)=fitem->subx; + WFIFOB(fd,16)=fitem->suby; + WFIFOSET(fd,packet_len(0x9d)); } @@ -4337,44 +4393,44 @@ void clif_getareachar_item(struct map_session_data *sd,struct flooritem_data *fi /// 01c9 <id>.L <creator id>.L <x>.W <y>.W <unit id>.B <visible>.B <has msg>.B <msg>.80B (ZC_SKILL_ENTRY2) static void clif_getareachar_skillunit(struct map_session_data *sd, struct skill_unit *unit) { - int fd = sd->fd; + int fd = sd->fd; - if (unit->group->state.guildaura) - return; + if( unit->group->state.guildaura ) + return; #if PACKETVER >= 3 - if (unit->group->unit_id==UNT_GRAFFITI) { // Graffiti [Valaris] - WFIFOHEAD(fd,packet_len(0x1c9)); - WFIFOW(fd, 0)=0x1c9; - WFIFOL(fd, 2)=unit->bl.id; - WFIFOL(fd, 6)=unit->group->src_id; - WFIFOW(fd,10)=unit->bl.x; - WFIFOW(fd,12)=unit->bl.y; - WFIFOB(fd,14)=unit->group->unit_id; - WFIFOB(fd,15)=1; - WFIFOB(fd,16)=1; - safestrncpy((char *)WFIFOP(fd,17),unit->group->valstr,MESSAGE_SIZE); - WFIFOSET(fd,packet_len(0x1c9)); - return; - } + if(unit->group->unit_id==UNT_GRAFFITI) { // Graffiti [Valaris] + WFIFOHEAD(fd,packet_len(0x1c9)); + WFIFOW(fd, 0)=0x1c9; + WFIFOL(fd, 2)=unit->bl.id; + WFIFOL(fd, 6)=unit->group->src_id; + WFIFOW(fd,10)=unit->bl.x; + WFIFOW(fd,12)=unit->bl.y; + WFIFOB(fd,14)=unit->group->unit_id; + WFIFOB(fd,15)=1; + WFIFOB(fd,16)=1; + safestrncpy((char*)WFIFOP(fd,17),unit->group->valstr,MESSAGE_SIZE); + WFIFOSET(fd,packet_len(0x1c9)); + return; + } #endif - WFIFOHEAD(fd,packet_len(0x11f)); - WFIFOW(fd, 0)=0x11f; - WFIFOL(fd, 2)=unit->bl.id; - WFIFOL(fd, 6)=unit->group->src_id; - WFIFOW(fd,10)=unit->bl.x; - WFIFOW(fd,12)=unit->bl.y; - if (battle_config.traps_setting&1 && skill_get_inf2(unit->group->skill_id)&INF2_TRAP) - WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps. + WFIFOHEAD(fd,packet_len(0x11f)); + WFIFOW(fd, 0)=0x11f; + WFIFOL(fd, 2)=unit->bl.id; + WFIFOL(fd, 6)=unit->group->src_id; + WFIFOW(fd,10)=unit->bl.x; + WFIFOW(fd,12)=unit->bl.y; + if (battle_config.traps_setting&1 && skill_get_inf2(unit->group->skill_id)&INF2_TRAP) + WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps. else if (skill_get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT)) - WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps. - else - WFIFOB(fd,14)=unit->group->unit_id; - WFIFOB(fd,15)=1; // ignored by client (always gets set to 1) - WFIFOSET(fd,packet_len(0x11f)); + WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps. + else + WFIFOB(fd,14)=unit->group->unit_id; + WFIFOB(fd,15)=1; // ignored by client (always gets set to 1) + WFIFOSET(fd,packet_len(0x11f)); - if (unit->group->skill_id == WZ_ICEWALL) - clif_changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,5,SELF); + if(unit->group->skill_id == WZ_ICEWALL) + clif_changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,5,SELF); } @@ -4383,15 +4439,15 @@ static void clif_getareachar_skillunit(struct map_session_data *sd, struct skill *------------------------------------------*/ static void clif_clearchar_skillunit(struct skill_unit *unit, int fd) { - nullpo_retv(unit); + nullpo_retv(unit); - WFIFOHEAD(fd,packet_len(0x120)); - WFIFOW(fd, 0)=0x120; - WFIFOL(fd, 2)=unit->bl.id; - WFIFOSET(fd,packet_len(0x120)); + WFIFOHEAD(fd,packet_len(0x120)); + WFIFOW(fd, 0)=0x120; + WFIFOL(fd, 2)=unit->bl.id; + WFIFOSET(fd,packet_len(0x120)); - if (unit->group && unit->group->skill_id == WZ_ICEWALL) - clif_changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,SELF); + if(unit->group && unit->group->skill_id == WZ_ICEWALL) + clif_changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,SELF); } @@ -4399,59 +4455,59 @@ static void clif_clearchar_skillunit(struct skill_unit *unit, int fd) /// 0120 <id>.L void clif_skill_delunit(struct skill_unit *unit) { - unsigned char buf[16]; + unsigned char buf[16]; - nullpo_retv(unit); + nullpo_retv(unit); - WBUFW(buf, 0)=0x120; - WBUFL(buf, 2)=unit->bl.id; - clif_send(buf,packet_len(0x120),&unit->bl,AREA); + WBUFW(buf, 0)=0x120; + WBUFL(buf, 2)=unit->bl.id; + clif_send(buf,packet_len(0x120),&unit->bl,AREA); } /// Sent when an object gets ankle-snared (ZC_SKILL_UPDATE). /// 01ac <id>.L /// Only affects units with class [139,153] client-side. -void clif_skillunit_update(struct block_list *bl) +void clif_skillunit_update(struct block_list* bl) { - unsigned char buf[6]; - nullpo_retv(bl); + unsigned char buf[6]; + nullpo_retv(bl); - WBUFW(buf,0) = 0x1ac; - WBUFL(buf,2) = bl->id; + WBUFW(buf,0) = 0x1ac; + WBUFL(buf,2) = bl->id; - clif_send(buf,packet_len(0x1ac),bl,AREA); + clif_send(buf,packet_len(0x1ac),bl,AREA); } /*========================================== * *------------------------------------------*/ -static int clif_getareachar(struct block_list *bl,va_list ap) +static int clif_getareachar(struct block_list* bl,va_list ap) { - struct map_session_data *sd; + struct map_session_data *sd; - nullpo_ret(bl); + nullpo_ret(bl); - sd=va_arg(ap,struct map_session_data *); + sd=va_arg(ap,struct map_session_data*); - if (sd == NULL || !sd->fd) - return 0; + if (sd == NULL || !sd->fd) + return 0; - switch (bl->type) { - case BL_ITEM: - clif_getareachar_item(sd,(struct flooritem_data *) bl); - break; - case BL_SKILL: - clif_getareachar_skillunit(sd,(TBL_SKILL *)bl); - break; - default: - if (&sd->bl == bl) - break; - clif_getareachar_unit(sd,bl); - break; - } - return 0; + switch(bl->type){ + case BL_ITEM: + clif_getareachar_item(sd,(struct flooritem_data*) bl); + break; + case BL_SKILL: + clif_getareachar_skillunit(sd,(TBL_SKILL*)bl); + break; + default: + if(&sd->bl == bl) + break; + clif_getareachar_unit(sd,bl); + break; + } + return 0; } /*========================================== @@ -4459,54 +4515,54 @@ static int clif_getareachar(struct block_list *bl,va_list ap) *------------------------------------------*/ int clif_outsight(struct block_list *bl,va_list ap) { - struct block_list *tbl; - struct view_data *vd; - TBL_PC *sd, *tsd; - tbl=va_arg(ap,struct block_list *); - if (bl == tbl) return 0; - sd = BL_CAST(BL_PC, bl); - tsd = BL_CAST(BL_PC, tbl); - - if (tsd && tsd->fd) { - //tsd has lost sight of the bl object. - switch (bl->type) { - case BL_PC: - if (sd->vd.class_ != INVISIBLE_CLASS) - clif_clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); - if (sd->chatID) { - struct chat_data *cd; - cd=(struct chat_data *)map_id2bl(sd->chatID); - if (cd->usersd[0]==sd) - clif_dispchat(cd,tsd->fd); - } - if (sd->state.vending) - clif_closevendingboard(bl,tsd->fd); - if (sd->state.buyingstore) - clif_buyingstore_disappear_entry_single(tsd, sd); - break; - case BL_ITEM: - clif_clearflooritem((struct flooritem_data *)bl,tsd->fd); - break; - case BL_SKILL: - clif_clearchar_skillunit((struct skill_unit *)bl,tsd->fd); - break; - case BL_NPC: - if (!(((TBL_NPC *)bl)->sc.option&OPTION_INVISIBLE)) - clif_clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); - break; - default: - if ((vd=status_get_viewdata(bl)) && vd->class_ != INVISIBLE_CLASS) - clif_clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); - break; - } - } - if (sd && sd->fd) { - //sd is watching tbl go out of view. - if (((vd=status_get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS) && - !(tbl->type == BL_NPC && (((TBL_NPC *)tbl)->sc.option&OPTION_INVISIBLE))) - clif_clearunit_single(tbl->id,CLR_OUTSIGHT,sd->fd); - } - return 0; + struct block_list *tbl; + struct view_data *vd; + TBL_PC *sd, *tsd; + tbl=va_arg(ap,struct block_list*); + if(bl == tbl) return 0; + sd = BL_CAST(BL_PC, bl); + tsd = BL_CAST(BL_PC, tbl); + + if (tsd && tsd->fd) + { //tsd has lost sight of the bl object. + switch(bl->type){ + case BL_PC: + if (sd->vd.class_ != INVISIBLE_CLASS) + clif_clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); + if(sd->chatID){ + struct chat_data *cd; + cd=(struct chat_data*)map_id2bl(sd->chatID); + if(cd->usersd[0]==sd) + clif_dispchat(cd,tsd->fd); + } + if( sd->state.vending ) + clif_closevendingboard(bl,tsd->fd); + if( sd->state.buyingstore ) + clif_buyingstore_disappear_entry_single(tsd, sd); + break; + case BL_ITEM: + clif_clearflooritem((struct flooritem_data*)bl,tsd->fd); + break; + case BL_SKILL: + clif_clearchar_skillunit((struct skill_unit *)bl,tsd->fd); + break; + case BL_NPC: + if( !(((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE) ) + clif_clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); + break; + default: + if ((vd=status_get_viewdata(bl)) && vd->class_ != INVISIBLE_CLASS) + clif_clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); + break; + } + } + if (sd && sd->fd) + { //sd is watching tbl go out of view. + if (((vd=status_get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS) && + !(tbl->type == BL_NPC && (((TBL_NPC*)tbl)->sc.option&OPTION_INVISIBLE))) + clif_clearunit_single(tbl->id,CLR_OUTSIGHT,sd->fd); + } + return 0; } /*========================================== @@ -4514,34 +4570,34 @@ int clif_outsight(struct block_list *bl,va_list ap) *------------------------------------------*/ int clif_insight(struct block_list *bl,va_list ap) { - struct block_list *tbl; - TBL_PC *sd, *tsd; - tbl=va_arg(ap,struct block_list *); - - if (bl == tbl) return 0; - - sd = BL_CAST(BL_PC, bl); - tsd = BL_CAST(BL_PC, tbl); - - if (tsd && tsd->fd) { - //Tell tsd that bl entered into his view - switch (bl->type) { - case BL_ITEM: - clif_getareachar_item(tsd,(struct flooritem_data *)bl); - break; - case BL_SKILL: - clif_getareachar_skillunit(tsd,(TBL_SKILL *)bl); - break; - default: - clif_getareachar_unit(tsd,bl); - break; - } - } - if (sd && sd->fd) { - //Tell sd that tbl walked into his view - clif_getareachar_unit(sd,tbl); - } - return 0; + struct block_list *tbl; + TBL_PC *sd, *tsd; + tbl=va_arg(ap,struct block_list*); + + if (bl == tbl) return 0; + + sd = BL_CAST(BL_PC, bl); + tsd = BL_CAST(BL_PC, tbl); + + if (tsd && tsd->fd) + { //Tell tsd that bl entered into his view + switch(bl->type){ + case BL_ITEM: + clif_getareachar_item(tsd,(struct flooritem_data*)bl); + break; + case BL_SKILL: + clif_getareachar_skillunit(tsd,(TBL_SKILL*)bl); + break; + default: + clif_getareachar_unit(tsd,bl); + break; + } + } + if (sd && sd->fd) + { //Tell sd that tbl walked into his view + clif_getareachar_unit(sd,tbl); + } + return 0; } @@ -4549,45 +4605,49 @@ int clif_insight(struct block_list *bl,va_list ap) /// 010f <packet len>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.B }* void clif_skillinfoblock(struct map_session_data *sd) { - int fd; - int i,len,id; - - nullpo_retv(sd); - - fd=sd->fd; - if (!fd) return; - - WFIFOHEAD(fd, MAX_SKILL * 37 + 4); - WFIFOW(fd,0) = 0x10f; - for (i = 0, len = 4; i < MAX_SKILL; i++) { - if ((id = sd->status.skill[i].id) != 0) { - // workaround for bugreport:5348 - if (len + 37 > 8192) - break; - - WFIFOW(fd,len) = id; - WFIFOL(fd,len+2) = skill_get_inf(id); - WFIFOW(fd,len+6) = sd->status.skill[i].lv; - WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv); - WFIFOW(fd,len+10)= skill_get_range2(&sd->bl, id,sd->status.skill[i].lv); - safestrncpy((char *)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); - if (sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) - WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class_))? 1:0; - else - WFIFOB(fd,len+36) = 0; - len += 37; - } - } - WFIFOW(fd,2)=len; - WFIFOSET(fd,len); - - // workaround for bugreport:5348; send the remaining skills one by one to bypass packet size limit - for (; i < MAX_SKILL; i++) { - if ((id = sd->status.skill[i].id) != 0) { - clif_addskill(sd, id); - clif_skillinfo(sd, id, 0); - } - } + int fd; + int i,len,id; + + nullpo_retv(sd); + + fd=sd->fd; + if (!fd) return; + + WFIFOHEAD(fd, MAX_SKILL * 37 + 4); + WFIFOW(fd,0) = 0x10f; + for ( i = 0, len = 4; i < MAX_SKILL; i++) + { + if( (id = sd->status.skill[i].id) != 0 ) + { + // workaround for bugreport:5348 + if (len + 37 > 8192) + break; + + WFIFOW(fd,len) = id; + WFIFOL(fd,len+2) = skill_get_inf(id); + WFIFOW(fd,len+6) = sd->status.skill[i].lv; + WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv); + WFIFOW(fd,len+10)= skill_get_range2(&sd->bl, id,sd->status.skill[i].lv); + safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); + if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) + WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class_))? 1:0; + else + WFIFOB(fd,len+36) = 0; + len += 37; + } + } + WFIFOW(fd,2)=len; + WFIFOSET(fd,len); + + // workaround for bugreport:5348; send the remaining skills one by one to bypass packet size limit + for ( ; i < MAX_SKILL; i++) + { + if( (id = sd->status.skill[i].id) != 0 ) + { + clif_addskill(sd, id); + clif_skillinfo(sd, id, 0); + } + } } /** * Server tells client 'sd' to add skill of id 'id' to it's skill tree (e.g. with Ice Falcion item) @@ -4597,29 +4657,29 @@ void clif_skillinfoblock(struct map_session_data *sd) /// 0111 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.B void clif_addskill(struct map_session_data *sd, int id) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; - if (!fd) return; - - if (sd->status.skill[id].id <= 0) - return; - - WFIFOHEAD(fd, packet_len(0x111)); - WFIFOW(fd,0) = 0x111; - WFIFOW(fd,2) = id; - WFIFOL(fd,4) = skill_get_inf(id); - WFIFOW(fd,8) = sd->status.skill[id].lv; - WFIFOW(fd,10) = skill_get_sp(id,sd->status.skill[id].lv); - WFIFOW(fd,12)= skill_get_range2(&sd->bl, id,sd->status.skill[id].lv); - safestrncpy((char *)WFIFOP(fd,14), skill_get_name(id), NAME_LENGTH); - if (sd->status.skill[id].flag == SKILL_FLAG_PERMANENT) - WFIFOB(fd,38) = (sd->status.skill[id].lv < skill_tree_get_max(id, sd->status.class_))? 1:0; - else - WFIFOB(fd,38) = 0; - WFIFOSET(fd,packet_len(0x111)); + fd = sd->fd; + if (!fd) return; + + if( sd->status.skill[id].id <= 0 ) + return; + + WFIFOHEAD(fd, packet_len(0x111)); + WFIFOW(fd,0) = 0x111; + WFIFOW(fd,2) = id; + WFIFOL(fd,4) = skill_get_inf(id); + WFIFOW(fd,8) = sd->status.skill[id].lv; + WFIFOW(fd,10) = skill_get_sp(id,sd->status.skill[id].lv); + WFIFOW(fd,12)= skill_get_range2(&sd->bl, id,sd->status.skill[id].lv); + safestrncpy((char*)WFIFOP(fd,14), skill_get_name(id), NAME_LENGTH); + if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) + WFIFOB(fd,38) = (sd->status.skill[id].lv < skill_tree_get_max(id, sd->status.class_))? 1:0; + else + WFIFOB(fd,38) = 0; + WFIFOSET(fd,packet_len(0x111)); } @@ -4628,18 +4688,18 @@ void clif_addskill(struct map_session_data *sd, int id) void clif_deleteskill(struct map_session_data *sd, int id) { #if PACKETVER >= 20081217 - int fd; + int fd; - nullpo_retv(sd); - fd = sd->fd; - if (!fd) return; + nullpo_retv(sd); + fd = sd->fd; + if( !fd ) return; - WFIFOHEAD(fd,packet_len(0x441)); - WFIFOW(fd,0) = 0x441; - WFIFOW(fd,2) = id; - WFIFOSET(fd,packet_len(0x441)); + WFIFOHEAD(fd,packet_len(0x441)); + WFIFOW(fd,0) = 0x441; + WFIFOW(fd,2) = id; + WFIFOSET(fd,packet_len(0x441)); #else - clif_skillinfoblock(sd); + clif_skillinfoblock(sd); #endif } @@ -4648,19 +4708,19 @@ void clif_deleteskill(struct map_session_data *sd, int id) /// 010e <skill id>.W <level>.W <sp cost>.W <attack range>.W <upgradable>.B void clif_skillup(struct map_session_data *sd,int skill_num) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x10e)); - WFIFOW(fd,0) = 0x10e; - WFIFOW(fd,2) = skill_num; - WFIFOW(fd,4) = sd->status.skill[skill_num].lv; - WFIFOW(fd,6) = skill_get_sp(skill_num,sd->status.skill[skill_num].lv); - WFIFOW(fd,8) = skill_get_range2(&sd->bl,skill_num,sd->status.skill[skill_num].lv); - 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(0x10e)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x10e)); + WFIFOW(fd,0) = 0x10e; + WFIFOW(fd,2) = skill_num; + WFIFOW(fd,4) = sd->status.skill[skill_num].lv; + WFIFOW(fd,6) = skill_get_sp(skill_num,sd->status.skill[skill_num].lv); + WFIFOW(fd,8) = skill_get_range2(&sd->bl,skill_num,sd->status.skill[skill_num].lv); + 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(0x10e)); } @@ -4668,20 +4728,20 @@ void clif_skillup(struct map_session_data *sd,int skill_num) /// 07e1 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <upgradable>.B void clif_skillinfo(struct map_session_data *sd,int skill, int inf) { - const int fd = sd->fd; - - WFIFOHEAD(fd,packet_len(0x7e1)); - WFIFOW(fd,0) = 0x7e1; - WFIFOW(fd,2) = skill; - WFIFOL(fd,4) = inf?inf:skill_get_inf(skill); - WFIFOW(fd,8) = sd->status.skill[skill].lv; - WFIFOW(fd,10) = skill_get_sp(skill,sd->status.skill[skill].lv); - WFIFOW(fd,12) = skill_get_range2(&sd->bl,skill,sd->status.skill[skill].lv); - if (sd->status.skill[skill].flag == SKILL_FLAG_PERMANENT) - WFIFOB(fd,14) = (sd->status.skill[skill].lv < skill_tree_get_max(skill, sd->status.class_))? 1:0; - else - WFIFOB(fd,14) = 0; - WFIFOSET(fd,packet_len(0x7e1)); + const int fd = sd->fd; + + WFIFOHEAD(fd,packet_len(0x7e1)); + WFIFOW(fd,0) = 0x7e1; + WFIFOW(fd,2) = skill; + WFIFOL(fd,4) = inf?inf:skill_get_inf(skill); + WFIFOW(fd,8) = sd->status.skill[skill].lv; + WFIFOW(fd,10) = skill_get_sp(skill,sd->status.skill[skill].lv); + WFIFOW(fd,12) = skill_get_range2(&sd->bl,skill,sd->status.skill[skill].lv); + if( sd->status.skill[skill].flag == SKILL_FLAG_PERMANENT ) + WFIFOB(fd,14) = (sd->status.skill[skill].lv < skill_tree_get_max(skill, sd->status.class_))? 1:0; + else + WFIFOB(fd,14) = 0; + WFIFOSET(fd,packet_len(0x7e1)); } @@ -4700,47 +4760,47 @@ void clif_skillinfo(struct map_session_data *sd,int skill, int inf) /// is disposable: /// 0 = yellow chat text "[src name] will use skill [skill name]." /// 1 = no text -void clif_skillcasting(struct block_list *bl, int src_id, int dst_id, int dst_x, int dst_y, int skill_num, int property, int casttime) +void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, int skill_num, int property, int casttime) { #if PACKETVER < 20091124 - const int cmd = 0x13e; + const int cmd = 0x13e; #else - const int cmd = 0x7fb; + const int cmd = 0x7fb; #endif - unsigned char buf[32]; - - WBUFW(buf,0) = cmd; - WBUFL(buf,2) = src_id; - WBUFL(buf,6) = dst_id; - WBUFW(buf,10) = dst_x; - WBUFW(buf,12) = dst_y; - WBUFW(buf,14) = skill_num; - WBUFL(buf,16) = property<0?0:property; //Avoid sending negatives as element [Skotlex] - WBUFL(buf,20) = casttime; + unsigned char buf[32]; + + WBUFW(buf,0) = cmd; + WBUFL(buf,2) = src_id; + WBUFL(buf,6) = dst_id; + WBUFW(buf,10) = dst_x; + WBUFW(buf,12) = dst_y; + WBUFW(buf,14) = skill_num; + WBUFL(buf,16) = property<0?0:property; //Avoid sending negatives as element [Skotlex] + WBUFL(buf,20) = casttime; #if PACKETVER >= 20091124 - WBUFB(buf,24) = 0; // isDisposable + WBUFB(buf,24) = 0; // isDisposable #endif - if (disguised(bl)) { - clif_send(buf,packet_len(cmd), bl, AREA_WOS); - WBUFL(buf,2) = -src_id; - clif_send(buf,packet_len(cmd), bl, SELF); - } else - clif_send(buf,packet_len(cmd), bl, AREA); + if (disguised(bl)) { + clif_send(buf,packet_len(cmd), bl, AREA_WOS); + WBUFL(buf,2) = -src_id; + clif_send(buf,packet_len(cmd), bl, SELF); + } else + clif_send(buf,packet_len(cmd), bl, AREA); } /// Notifies clients in area, that an object canceled casting (ZC_DISPEL). /// 01b9 <id>.L -void clif_skillcastcancel(struct block_list *bl) +void clif_skillcastcancel(struct block_list* bl) { - unsigned char buf[16]; + unsigned char buf[16]; - nullpo_retv(bl); + nullpo_retv(bl); - WBUFW(buf,0) = 0x1b9; - WBUFL(buf,2) = bl->id; - clif_send(buf,packet_len(0x1b9), bl, AREA); + WBUFW(buf,0) = 0x1b9; + WBUFL(buf,2) = bl->id; + clif_send(buf,packet_len(0x1b9), bl, AREA); } @@ -4769,35 +4829,35 @@ void clif_skillcastcancel(struct block_list *bl) /// suggesting this is an ACK packet for the UseSkill packets and should be sent on success too [FlavioJS] void clif_skill_fail(struct map_session_data *sd,int skill_id,enum useskill_fail_cause cause,int btype) { - int fd; + int fd; - if (!sd) { //Since this is the most common nullpo.... - ShowDebug("clif_skill_fail: Error, received NULL sd for skill %d\n", skill_id); - return; - } + if (!sd) { //Since this is the most common nullpo.... + ShowDebug("clif_skill_fail: Error, received NULL sd for skill %d\n", skill_id); + return; + } - fd=sd->fd; - if (!fd) return; + fd=sd->fd; + if (!fd) return; - if (battle_config.display_skill_fail&1) - return; //Disable all skill failed messages + if(battle_config.display_skill_fail&1) + return; //Disable all skill failed messages - if (cause==USESKILL_FAIL_SKILLINTERVAL && !sd->state.showdelay) - return; //Disable delay failed messages + if(cause==USESKILL_FAIL_SKILLINTERVAL && !sd->state.showdelay) + return; //Disable delay failed messages - if (skill_id == RG_SNATCHER && battle_config.display_skill_fail&4) - return; + if(skill_id == RG_SNATCHER && battle_config.display_skill_fail&4) + return; - if (skill_id == TF_POISON && battle_config.display_skill_fail&8) - return; + if(skill_id == TF_POISON && battle_config.display_skill_fail&8) + return; - WFIFOHEAD(fd,packet_len(0x110)); - WFIFOW(fd,0) = 0x110; - WFIFOW(fd,2) = skill_id; - WFIFOL(fd,4) = btype; - WFIFOB(fd,8) = 0;// success - WFIFOB(fd,9) = cause; - WFIFOSET(fd,packet_len(0x110)); + WFIFOHEAD(fd,packet_len(0x110)); + WFIFOW(fd,0) = 0x110; + WFIFOW(fd,2) = skill_id; + WFIFOL(fd,4) = btype; + WFIFOB(fd,8) = 0;// success + WFIFOB(fd,9) = cause; + WFIFOSET(fd,packet_len(0x110)); } @@ -4806,16 +4866,16 @@ void clif_skill_fail(struct map_session_data *sd,int skill_id,enum useskill_fail void clif_skill_cooldown(struct map_session_data *sd, int skillid, unsigned int tick) { #if PACKETVER>=20081112 - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x43d)); - WFIFOW(fd,0) = 0x43d; - WFIFOW(fd,2) = skillid; - WFIFOL(fd,4) = tick; - WFIFOSET(fd,packet_len(0x43d)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x43d)); + WFIFOW(fd,0) = 0x43d; + WFIFOW(fd,2) = skillid; + WFIFOL(fd,4) = tick; + WFIFOSET(fd,packet_len(0x43d)); #endif } @@ -4825,85 +4885,85 @@ void clif_skill_cooldown(struct map_session_data *sd, int skillid, unsigned int /// 01de <skill id>.W <src id>.L <dst id>.L <tick>.L <src delay>.L <dst delay>.L <damage>.L <level>.W <div>.W <type>.B (ZC_NOTIFY_SKILL2) int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,int skill_id,int skill_lv,int type) { - unsigned char buf[64]; - struct status_change *sc; + unsigned char buf[64]; + struct status_change *sc; - nullpo_ret(src); - nullpo_ret(dst); + nullpo_ret(src); + nullpo_ret(dst); - type = clif_calc_delay(type,div,damage,ddelay); - sc = status_get_sc(dst); - if (sc && sc->count) { - if (sc->data[SC_HALLUCINATION] && damage) - damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; - } + type = clif_calc_delay(type,div,damage,ddelay); + sc = status_get_sc(dst); + if(sc && sc->count) { + if(sc->data[SC_HALLUCINATION] && damage) + damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; + } #if PACKETVER < 3 - WBUFW(buf,0)=0x114; - WBUFW(buf,2)=skill_id; - WBUFL(buf,4)=src->id; - WBUFL(buf,8)=dst->id; - WBUFL(buf,12)=tick; - WBUFL(buf,16)=sdelay; - WBUFL(buf,20)=ddelay; - if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) { - WBUFW(buf,24)=damage?div:0; - } else { - WBUFW(buf,24)=damage; - } - WBUFW(buf,26)=skill_lv; - WBUFW(buf,28)=div; - WBUFB(buf,30)=type; - if (disguised(dst)) { - clif_send(buf,packet_len(0x114),dst,AREA_WOS); - WBUFL(buf,8)=-dst->id; - clif_send(buf,packet_len(0x114),dst,SELF); - } else - clif_send(buf,packet_len(0x114),dst,AREA); - - if (disguised(src)) { - WBUFL(buf,4)=-src->id; - if (disguised(dst)) - WBUFL(buf,8)=dst->id; - if (damage > 0) - WBUFW(buf,24)=-1; - clif_send(buf,packet_len(0x114),src,SELF); - } + WBUFW(buf,0)=0x114; + WBUFW(buf,2)=skill_id; + WBUFL(buf,4)=src->id; + WBUFL(buf,8)=dst->id; + WBUFL(buf,12)=tick; + WBUFL(buf,16)=sdelay; + WBUFL(buf,20)=ddelay; + if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) { + WBUFW(buf,24)=damage?div:0; + } else { + WBUFW(buf,24)=damage; + } + WBUFW(buf,26)=skill_lv; + WBUFW(buf,28)=div; + WBUFB(buf,30)=type; + if (disguised(dst)) { + clif_send(buf,packet_len(0x114),dst,AREA_WOS); + WBUFL(buf,8)=-dst->id; + clif_send(buf,packet_len(0x114),dst,SELF); + } else + clif_send(buf,packet_len(0x114),dst,AREA); + + if(disguised(src)) { + WBUFL(buf,4)=-src->id; + if (disguised(dst)) + WBUFL(buf,8)=dst->id; + if(damage > 0) + WBUFW(buf,24)=-1; + clif_send(buf,packet_len(0x114),src,SELF); + } #else - WBUFW(buf,0)=0x1de; - WBUFW(buf,2)=skill_id; - WBUFL(buf,4)=src->id; - WBUFL(buf,8)=dst->id; - WBUFL(buf,12)=tick; - WBUFL(buf,16)=sdelay; - WBUFL(buf,20)=ddelay; - if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) { - WBUFL(buf,24)=damage?div:0; - } else { - WBUFL(buf,24)=damage; - } - WBUFW(buf,28)=skill_lv; - WBUFW(buf,30)=div; - WBUFB(buf,32)=type; - if (disguised(dst)) { - clif_send(buf,packet_len(0x1de),dst,AREA_WOS); - WBUFL(buf,8)=-dst->id; - clif_send(buf,packet_len(0x1de),dst,SELF); - } else - clif_send(buf,packet_len(0x1de),dst,AREA); - - if (disguised(src)) { - WBUFL(buf,4)=-src->id; - if (disguised(dst)) - WBUFL(buf,8)=dst->id; - if (damage > 0) - WBUFL(buf,24)=-1; - clif_send(buf,packet_len(0x1de),src,SELF); - } + WBUFW(buf,0)=0x1de; + WBUFW(buf,2)=skill_id; + WBUFL(buf,4)=src->id; + WBUFL(buf,8)=dst->id; + WBUFL(buf,12)=tick; + WBUFL(buf,16)=sdelay; + WBUFL(buf,20)=ddelay; + if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) { + WBUFL(buf,24)=damage?div:0; + } else { + WBUFL(buf,24)=damage; + } + WBUFW(buf,28)=skill_lv; + WBUFW(buf,30)=div; + WBUFB(buf,32)=type; + if (disguised(dst)) { + clif_send(buf,packet_len(0x1de),dst,AREA_WOS); + WBUFL(buf,8)=-dst->id; + clif_send(buf,packet_len(0x1de),dst,SELF); + } else + clif_send(buf,packet_len(0x1de),dst,AREA); + + if(disguised(src)) { + WBUFL(buf,4)=-src->id; + if (disguised(dst)) + WBUFL(buf,8)=dst->id; + if(damage > 0) + WBUFL(buf,24)=-1; + clif_send(buf,packet_len(0x1de),src,SELF); + } #endif - //Because the damage delay must be synced with the client, here is where the can-walk tick must be updated. [Skotlex] - return clif_calc_walkdelay(dst,ddelay,type,damage,div); + //Because the damage delay must be synced with the client, here is where the can-walk tick must be updated. [Skotlex] + return clif_calc_walkdelay(dst,ddelay,type,damage,div); } @@ -4912,56 +4972,56 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int /* int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,int skill_id,int skill_lv,int type) { - unsigned char buf[64]; - struct status_change *sc; - - nullpo_ret(src); - nullpo_ret(dst); - - type = (type>0)?type:skill_get_hit(skill_id); - type = clif_calc_delay(type,div,damage,ddelay); - sc = status_get_sc(dst); - - if(sc && sc->count) { - if(sc->data[SC_HALLUCINATION] && damage) - damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; - } - - WBUFW(buf,0)=0x115; - WBUFW(buf,2)=skill_id; - WBUFL(buf,4)=src->id; - WBUFL(buf,8)=dst->id; - WBUFL(buf,12)=tick; - WBUFL(buf,16)=sdelay; - WBUFL(buf,20)=ddelay; - WBUFW(buf,24)=dst->x; - WBUFW(buf,26)=dst->y; - if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) { - WBUFW(buf,28)=damage?div:0; - } else { - WBUFW(buf,28)=damage; - } - WBUFW(buf,30)=skill_lv; - WBUFW(buf,32)=div; - WBUFB(buf,34)=type; - clif_send(buf,packet_len(0x115),src,AREA); - if(disguised(src)) { - WBUFL(buf,4)=-src->id; - if(damage > 0) - WBUFW(buf,28)=-1; - clif_send(buf,packet_len(0x115),src,SELF); - } - if (disguised(dst)) { - WBUFL(buf,8)=-dst->id; - if (disguised(src)) - WBUFL(buf,4)=src->id; - else if(damage > 0) - WBUFW(buf,28)=-1; - clif_send(buf,packet_len(0x115),dst,SELF); - } - - //Because the damage delay must be synced with the client, here is where the can-walk tick must be updated. [Skotlex] - return clif_calc_walkdelay(dst,ddelay,type,damage,div); + unsigned char buf[64]; + struct status_change *sc; + + nullpo_ret(src); + nullpo_ret(dst); + + type = (type>0)?type:skill_get_hit(skill_id); + type = clif_calc_delay(type,div,damage,ddelay); + sc = status_get_sc(dst); + + if(sc && sc->count) { + if(sc->data[SC_HALLUCINATION] && damage) + damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; + } + + WBUFW(buf,0)=0x115; + WBUFW(buf,2)=skill_id; + WBUFL(buf,4)=src->id; + WBUFL(buf,8)=dst->id; + WBUFL(buf,12)=tick; + WBUFL(buf,16)=sdelay; + WBUFL(buf,20)=ddelay; + WBUFW(buf,24)=dst->x; + WBUFW(buf,26)=dst->y; + if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) { + WBUFW(buf,28)=damage?div:0; + } else { + WBUFW(buf,28)=damage; + } + WBUFW(buf,30)=skill_lv; + WBUFW(buf,32)=div; + WBUFB(buf,34)=type; + clif_send(buf,packet_len(0x115),src,AREA); + if(disguised(src)) { + WBUFL(buf,4)=-src->id; + if(damage > 0) + WBUFW(buf,28)=-1; + clif_send(buf,packet_len(0x115),src,SELF); + } + if (disguised(dst)) { + WBUFL(buf,8)=-dst->id; + if (disguised(src)) + WBUFL(buf,4)=src->id; + else if(damage > 0) + WBUFW(buf,28)=-1; + clif_send(buf,packet_len(0x115),dst,SELF); + } + + //Because the damage delay must be synced with the client, here is where the can-walk tick must be updated. [Skotlex] + return clif_calc_walkdelay(dst,ddelay,type,damage,div); } */ @@ -4970,32 +5030,32 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned in /// 011a <skill id>.W <skill lv>.W <dst id>.L <src id>.L <result>.B int clif_skill_nodamage(struct block_list *src,struct block_list *dst,int skill_id,int heal,int fail) { - unsigned char buf[32]; - - nullpo_ret(dst); - - WBUFW(buf,0)=0x11a; - WBUFW(buf,2)=skill_id; - WBUFW(buf,4)=min(heal, INT16_MAX); - WBUFL(buf,6)=dst->id; - WBUFL(buf,10)=src?src->id:0; - WBUFB(buf,14)=fail; - - if (disguised(dst)) { - clif_send(buf,packet_len(0x11a),dst,AREA_WOS); - WBUFL(buf,6)=-dst->id; - clif_send(buf,packet_len(0x11a),dst,SELF); - } else - clif_send(buf,packet_len(0x11a),dst,AREA); - - if (src && disguised(src)) { - WBUFL(buf,10)=-src->id; - if (disguised(dst)) - WBUFL(buf,6)=dst->id; - clif_send(buf,packet_len(0x11a),src,SELF); - } + unsigned char buf[32]; + + nullpo_ret(dst); - return fail; + WBUFW(buf,0)=0x11a; + WBUFW(buf,2)=skill_id; + WBUFW(buf,4)=min(heal, INT16_MAX); + WBUFL(buf,6)=dst->id; + WBUFL(buf,10)=src?src->id:0; + WBUFB(buf,14)=fail; + + if (disguised(dst)) { + clif_send(buf,packet_len(0x11a),dst,AREA_WOS); + WBUFL(buf,6)=-dst->id; + clif_send(buf,packet_len(0x11a),dst,SELF); + } else + clif_send(buf,packet_len(0x11a),dst,AREA); + + if(src && disguised(src)) { + WBUFL(buf,10)=-src->id; + if (disguised(dst)) + WBUFL(buf,6)=dst->id; + clif_send(buf,packet_len(0x11a),src,SELF); + } + + return fail; } @@ -5003,23 +5063,23 @@ int clif_skill_nodamage(struct block_list *src,struct block_list *dst,int skill_ /// 0117 <skill id>.W <src id>.L <level>.W <x>.W <y>.W <tick>.L void clif_skill_poseffect(struct block_list *src,int skill_id,int val,int x,int y,int tick) { - unsigned char buf[32]; + unsigned char buf[32]; - nullpo_retv(src); + nullpo_retv(src); - WBUFW(buf,0)=0x117; - WBUFW(buf,2)=skill_id; - WBUFL(buf,4)=src->id; - WBUFW(buf,8)=val; - WBUFW(buf,10)=x; - WBUFW(buf,12)=y; - WBUFL(buf,14)=tick; - if (disguised(src)) { - clif_send(buf,packet_len(0x117),src,AREA_WOS); - WBUFL(buf,4)=-src->id; - clif_send(buf,packet_len(0x117),src,SELF); - } else - clif_send(buf,packet_len(0x117),src,AREA); + WBUFW(buf,0)=0x117; + WBUFW(buf,2)=skill_id; + WBUFL(buf,4)=src->id; + WBUFW(buf,8)=val; + WBUFW(buf,10)=x; + WBUFW(buf,12)=y; + WBUFL(buf,14)=tick; + if(disguised(src)) { + clif_send(buf,packet_len(0x117),src,AREA_WOS); + WBUFL(buf,4)=-src->id; + clif_send(buf,packet_len(0x117),src,SELF); + } else + clif_send(buf,packet_len(0x117),src,AREA); } @@ -5029,69 +5089,69 @@ void clif_skill_poseffect(struct block_list *src,int skill_id,int val,int x,int //FIXME: this is just an AREA version of clif_getareachar_skillunit() void clif_skill_setunit(struct skill_unit *unit) { - unsigned char buf[128]; + unsigned char buf[128]; - nullpo_retv(unit); + nullpo_retv(unit); - if (unit->group->state.guildaura) - return; + if( unit->group->state.guildaura ) + return; #if PACKETVER >= 3 - if (unit->group->unit_id==UNT_GRAFFITI) { // Graffiti [Valaris] - WBUFW(buf, 0)=0x1c9; - WBUFL(buf, 2)=unit->bl.id; - WBUFL(buf, 6)=unit->group->src_id; - WBUFW(buf,10)=unit->bl.x; - WBUFW(buf,12)=unit->bl.y; - WBUFB(buf,14)=unit->group->unit_id; - WBUFB(buf,15)=1; - WBUFB(buf,16)=1; - safestrncpy((char *)WBUFP(buf,17),unit->group->valstr,MESSAGE_SIZE); - clif_send(buf,packet_len(0x1c9),&unit->bl,AREA); - return; - } + if(unit->group->unit_id==UNT_GRAFFITI) { // Graffiti [Valaris] + WBUFW(buf, 0)=0x1c9; + WBUFL(buf, 2)=unit->bl.id; + WBUFL(buf, 6)=unit->group->src_id; + WBUFW(buf,10)=unit->bl.x; + WBUFW(buf,12)=unit->bl.y; + WBUFB(buf,14)=unit->group->unit_id; + WBUFB(buf,15)=1; + WBUFB(buf,16)=1; + safestrncpy((char*)WBUFP(buf,17),unit->group->valstr,MESSAGE_SIZE); + clif_send(buf,packet_len(0x1c9),&unit->bl,AREA); + return; + } #endif - WBUFW(buf, 0)=0x11f; - WBUFL(buf, 2)=unit->bl.id; - WBUFL(buf, 6)=unit->group->src_id; - WBUFW(buf,10)=unit->bl.x; - WBUFW(buf,12)=unit->bl.y; - if (unit->group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE) - WBUFB(buf,14)=unit->val2&UF_SONG?UNT_DISSONANCE:UNT_UGLYDANCE; + WBUFW(buf, 0)=0x11f; + WBUFL(buf, 2)=unit->bl.id; + WBUFL(buf, 6)=unit->group->src_id; + WBUFW(buf,10)=unit->bl.x; + WBUFW(buf,12)=unit->bl.y; + if (unit->group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE) + WBUFB(buf,14)=unit->val2&UF_SONG?UNT_DISSONANCE:UNT_UGLYDANCE; else if (skill_get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT)) WBUFB(buf, 14) = UNT_DUMMYSKILL; // Only display the unit at center. - else - WBUFB(buf,14)=unit->group->unit_id; - WBUFB(buf,15)=1; // ignored by client (always gets set to 1) - clif_send(buf,packet_len(0x11f),&unit->bl,AREA); + else + WBUFB(buf,14)=unit->group->unit_id; + WBUFB(buf,15)=1; // ignored by client (always gets set to 1) + clif_send(buf,packet_len(0x11f),&unit->bl,AREA); } /// Presents a list of available warp destinations (ZC_WARPLIST). /// 011c <skill id>.W { <map name>.16B }*4 -void clif_skill_warppoint(struct map_session_data *sd, short skill_num, short skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4) +void clif_skill_warppoint(struct map_session_data* sd, short skill_num, short skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4) { - int fd; - nullpo_retv(sd); - fd = sd->fd; - - WFIFOHEAD(fd,packet_len(0x11c)); - WFIFOW(fd,0) = 0x11c; - WFIFOW(fd,2) = skill_num; - memset(WFIFOP(fd,4), 0x00, 4*MAP_NAME_LENGTH_EXT); - if (map1 == (unsigned short)-1) strcpy((char *)WFIFOP(fd,4), "Random"); - else // normal map name - if (map1 > 0) mapindex_getmapname_ext(mapindex_id2name(map1), (char *)WFIFOP(fd,4)); - if (map2 > 0) mapindex_getmapname_ext(mapindex_id2name(map2), (char *)WFIFOP(fd,20)); - if (map3 > 0) mapindex_getmapname_ext(mapindex_id2name(map3), (char *)WFIFOP(fd,36)); - if (map4 > 0) mapindex_getmapname_ext(mapindex_id2name(map4), (char *)WFIFOP(fd,52)); - WFIFOSET(fd,packet_len(0x11c)); - - sd->menuskill_id = skill_num; - if (skill_num == AL_WARP) - sd->menuskill_val = (sd->ud.skillx<<16)|sd->ud.skilly; //Store warp position here. - else - sd->menuskill_val = skill_lv; + int fd; + nullpo_retv(sd); + fd = sd->fd; + + WFIFOHEAD(fd,packet_len(0x11c)); + WFIFOW(fd,0) = 0x11c; + WFIFOW(fd,2) = skill_num; + memset(WFIFOP(fd,4), 0x00, 4*MAP_NAME_LENGTH_EXT); + if (map1 == (unsigned short)-1) strcpy((char*)WFIFOP(fd,4), "Random"); + else // normal map name + if (map1 > 0) mapindex_getmapname_ext(mapindex_id2name(map1), (char*)WFIFOP(fd,4)); + if (map2 > 0) mapindex_getmapname_ext(mapindex_id2name(map2), (char*)WFIFOP(fd,20)); + if (map3 > 0) mapindex_getmapname_ext(mapindex_id2name(map3), (char*)WFIFOP(fd,36)); + if (map4 > 0) mapindex_getmapname_ext(mapindex_id2name(map4), (char*)WFIFOP(fd,52)); + WFIFOSET(fd,packet_len(0x11c)); + + sd->menuskill_id = skill_num; + if (skill_num == AL_WARP) + sd->menuskill_val = (sd->ud.skillx<<16)|sd->ud.skilly; //Store warp position here. + else + sd->menuskill_val = skill_lv; } @@ -5104,17 +5164,17 @@ void clif_skill_warppoint(struct map_session_data *sd, short skill_num, short sk /// /// @param sd Who receives the message /// @param type What message -void clif_skill_memomessage(struct map_session_data *sd, int type) +void clif_skill_memomessage(struct map_session_data* sd, int type) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x11e)); - WFIFOW(fd,0)=0x11e; - WFIFOB(fd,2)=type; - WFIFOSET(fd,packet_len(0x11e)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x11e)); + WFIFOW(fd,0)=0x11e; + WFIFOB(fd,2)=type; + WFIFOSET(fd,packet_len(0x11e)); } @@ -5128,15 +5188,15 @@ void clif_skill_memomessage(struct map_session_data *sd, int type) /// @param type What message void clif_skill_teleportmessage(struct map_session_data *sd, int type) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x189)); - WFIFOW(fd,0)=0x189; - WFIFOW(fd,2)=type; - WFIFOSET(fd,packet_len(0x189)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x189)); + WFIFOW(fd,0)=0x189; + WFIFOW(fd,2)=type; + WFIFOSET(fd,packet_len(0x189)); } @@ -5145,35 +5205,35 @@ void clif_skill_teleportmessage(struct map_session_data *sd, int type) /// <water%>.B <earth%>.B <fire%>.B <wind%>.B <poison%>.B <holy%>.B <shadow%>.B <ghost%>.B <undead%>.B void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) { - struct status_data *status; - unsigned char buf[64]; - int i;//, fix; + struct status_data *status; + unsigned char buf[64]; + int i;//, fix; - nullpo_retv(sd); - nullpo_retv(dst); + nullpo_retv(sd); + nullpo_retv(dst); - if (dst->type != BL_MOB) - return; + if( dst->type != BL_MOB ) + return; - status = status_get_status_data(dst); + status = status_get_status_data(dst); - WBUFW(buf, 0)=0x18c; - WBUFW(buf, 2)=status_get_class(dst); - WBUFW(buf, 4)=status_get_lv(dst); - WBUFW(buf, 6)=status->size; - WBUFL(buf, 8)=status->hp; - WBUFW(buf,12)= (battle_config.estimation_type&1?status->def:0) - +(battle_config.estimation_type&2?status->def2:0); - WBUFW(buf,14)=status->race; - WBUFW(buf,16)= (battle_config.estimation_type&1?status->mdef:0) - +(battle_config.estimation_type&2?status->mdef2:0); - WBUFW(buf,18)= status->def_ele; - for (i=0; i<9; i++) - WBUFB(buf,20+i)= (unsigned char)battle_attr_ratio(i+1,status->def_ele, status->ele_lv); - // The following caps negative attributes to 0 since the client displays them as 255-fix. [Skotlex] - // WBUFB(buf,20+i)= (unsigned char)((fix=battle_attr_ratio(i+1,status->def_ele, status->ele_lv))<0?0:fix); + WBUFW(buf, 0)=0x18c; + WBUFW(buf, 2)=status_get_class(dst); + WBUFW(buf, 4)=status_get_lv(dst); + WBUFW(buf, 6)=status->size; + WBUFL(buf, 8)=status->hp; + WBUFW(buf,12)= (battle_config.estimation_type&1?status->def:0) + +(battle_config.estimation_type&2?status->def2:0); + WBUFW(buf,14)=status->race; + WBUFW(buf,16)= (battle_config.estimation_type&1?status->mdef:0) + +(battle_config.estimation_type&2?status->mdef2:0); + WBUFW(buf,18)= status->def_ele; + for(i=0;i<9;i++) + WBUFB(buf,20+i)= (unsigned char)battle_attr_ratio(i+1,status->def_ele, status->ele_lv); +// The following caps negative attributes to 0 since the client displays them as 255-fix. [Skotlex] +// WBUFB(buf,20+i)= (unsigned char)((fix=battle_attr_ratio(i+1,status->def_ele, status->ele_lv))<0?0:fix); - clif_send(buf,packet_len(0x18c),&sd->bl,sd->status.party_id>0?PARTY_SAMEMAP:SELF); + clif_send(buf,packet_len(0x18c),&sd->bl,sd->status.party_id>0?PARTY_SAMEMAP:SELF); } @@ -5183,39 +5243,39 @@ void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) /// unused by the client void clif_skill_produce_mix_list(struct map_session_data *sd, int skillid , int trigger) { - int i,c,view,fd; - nullpo_retv(sd); - - if (sd->menuskill_id == skillid) - return; //Avoid resending the menu twice or more times... - if (skillid == GC_CREATENEWPOISON) - skillid = GC_RESEARCHNEWPOISON; - - fd=sd->fd; - WFIFOHEAD(fd, MAX_SKILL_PRODUCE_DB * 8 + 8); - WFIFOW(fd, 0)=0x18d; - - for (i=0,c=0; i<MAX_SKILL_PRODUCE_DB; i++) { - if (skill_can_produce_mix(sd,skill_produce_db[i].nameid, trigger, 1) && - ((skillid > 0 && skill_produce_db[i].req_skill == skillid) || skillid < 0) - ) { - if ((view = itemdb_viewid(skill_produce_db[i].nameid)) > 0) - WFIFOW(fd,c*8+ 4)= view; - else - WFIFOW(fd,c*8+ 4)= skill_produce_db[i].nameid; - WFIFOW(fd,c*8+ 6)= 0; - WFIFOW(fd,c*8+ 8)= 0; - WFIFOW(fd,c*8+10)= 0; - c++; - } - } - WFIFOW(fd, 2)=c*8+8; - WFIFOSET(fd,WFIFOW(fd,2)); - if (c > 0) { - sd->menuskill_id = skillid; - sd->menuskill_val = trigger; - return; - } + int i,c,view,fd; + nullpo_retv(sd); + + if(sd->menuskill_id == skillid) + return; //Avoid resending the menu twice or more times... + if( skillid == GC_CREATENEWPOISON ) + skillid = GC_RESEARCHNEWPOISON; + + fd=sd->fd; + WFIFOHEAD(fd, MAX_SKILL_PRODUCE_DB * 8 + 8); + WFIFOW(fd, 0)=0x18d; + + for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){ + if( skill_can_produce_mix(sd,skill_produce_db[i].nameid, trigger, 1) && + ( ( skillid > 0 && skill_produce_db[i].req_skill == skillid ) || skillid < 0 ) + ){ + if((view = itemdb_viewid(skill_produce_db[i].nameid)) > 0) + WFIFOW(fd,c*8+ 4)= view; + else + WFIFOW(fd,c*8+ 4)= skill_produce_db[i].nameid; + WFIFOW(fd,c*8+ 6)= 0; + WFIFOW(fd,c*8+ 8)= 0; + WFIFOW(fd,c*8+10)= 0; + c++; + } + } + WFIFOW(fd, 2)=c*8+8; + WFIFOSET(fd,WFIFOW(fd,2)); + if(c > 0) { + sd->menuskill_id = skillid; + sd->menuskill_val = trigger; + return; + } } @@ -5230,55 +5290,55 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skillid , int /// 6 = GN_S_PHARMACY void clif_cooking_list(struct map_session_data *sd, int trigger, int skill_id, int qty, int list_type) { - int fd; - int i, c; - int view; - - nullpo_retv(sd); - fd = sd->fd; - - WFIFOHEAD(fd, 6 + 2 * MAX_SKILL_PRODUCE_DB); - WFIFOW(fd,0) = 0x25a; - WFIFOW(fd,4) = list_type; // list type - - c = 0; - for (i = 0; i < MAX_SKILL_PRODUCE_DB; i++) { - if (!skill_can_produce_mix(sd,skill_produce_db[i].nameid,trigger, qty)) - continue; - - if ((view = itemdb_viewid(skill_produce_db[i].nameid)) > 0) - WFIFOW(fd, 6 + 2 * c) = view; - else - WFIFOW(fd, 6 + 2 * c) = skill_produce_db[i].nameid; - - c++; - } - - if (skill_id == AM_PHARMACY) { // Only send it while Cooking else check for c. - WFIFOW(fd,2) = 6 + 2 * c; - WFIFOSET(fd,WFIFOW(fd,2)); - } - - if (c > 0) { - sd->menuskill_id = skill_id; - sd->menuskill_val = trigger; - if (skill_id != AM_PHARMACY) { - sd->menuskill_val2 = qty; // amount. - WFIFOW(fd,2) = 6 + 2 * c; - WFIFOSET(fd,WFIFOW(fd,2)); - } - } else { - clif_menuskill_clear(sd); - if (skill_id != AM_PHARMACY) { // AM_PHARMACY is used to Cooking. - // It fails. + int fd; + int i, c; + int view; + + nullpo_retv(sd); + fd = sd->fd; + + WFIFOHEAD(fd, 6 + 2 * MAX_SKILL_PRODUCE_DB); + WFIFOW(fd,0) = 0x25a; + WFIFOW(fd,4) = list_type; // list type + + c = 0; + for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) { + if( !skill_can_produce_mix(sd,skill_produce_db[i].nameid,trigger, qty) ) + continue; + + if( (view = itemdb_viewid(skill_produce_db[i].nameid)) > 0 ) + WFIFOW(fd, 6 + 2 * c) = view; + else + WFIFOW(fd, 6 + 2 * c) = skill_produce_db[i].nameid; + + c++; + } + + if( skill_id == AM_PHARMACY ) { // Only send it while Cooking else check for c. + WFIFOW(fd,2) = 6 + 2 * c; + WFIFOSET(fd,WFIFOW(fd,2)); + } + + if( c > 0 ) { + sd->menuskill_id = skill_id; + sd->menuskill_val = trigger; + if( skill_id != AM_PHARMACY ) { + sd->menuskill_val2 = qty; // amount. + WFIFOW(fd,2) = 6 + 2 * c; + WFIFOSET(fd,WFIFOW(fd,2)); + } + } else { + clif_menuskill_clear(sd); + if( skill_id != AM_PHARMACY ) { // AM_PHARMACY is used to Cooking. + // It fails. #if PACKETVER >= 20090922 - clif_msg_skill(sd,skill_id,0x625); + clif_msg_skill(sd,skill_id,0x625); #else - WFIFOW(fd,2) = 6 + 2 * c; - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOW(fd,2) = 6 + 2 * c; + WFIFOSET(fd,WFIFOW(fd,2)); #endif - } - } + } + } } @@ -5287,162 +5347,161 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, int skill_id, i /// 043f <index>.W <id>.L <state>.B <remain msec>.L { <val>.L }*3 (ZC_MSG_STATE_CHANGE2) [used exclusively for starting statuses on pcs] void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3) { - unsigned char buf[32]; - struct map_session_data *sd; + unsigned char buf[32]; + struct map_session_data *sd; - if (type == SI_BLANK) //It shows nothing on the client... - return; + if (type == SI_BLANK) //It shows nothing on the client... + return; - nullpo_retv(bl); + nullpo_retv(bl); - sd = BL_CAST(BL_PC, bl); + sd = BL_CAST(BL_PC, bl); - if (!(status_type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client - return; + if (!(status_type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client + return; #if PACKETVER >= 20090121 - if (flag && battle_config.display_status_timers && sd) - WBUFW(buf,0)=0x43f; - else + if(flag && battle_config.display_status_timers && sd) + WBUFW(buf,0)=0x43f; + else #endif - WBUFW(buf,0)=0x196; - WBUFW(buf,2)=type; - WBUFL(buf,4)=bl->id; - WBUFB(buf,8)=flag; + WBUFW(buf,0)=0x196; + WBUFW(buf,2)=type; + WBUFL(buf,4)=bl->id; + WBUFB(buf,8)=flag; #if PACKETVER >= 20090121 - if (flag && battle_config.display_status_timers && sd) { - if (tick <= 0) - tick = 9999; // this is indeed what official servers do - - WBUFL(buf,9) = tick; - WBUFL(buf,13) = val1; - WBUFL(buf,17) = val2; - WBUFL(buf,21) = val3; - } + if(flag && battle_config.display_status_timers && sd) + { + if (tick <= 0) + tick = 9999; // this is indeed what official servers do + + WBUFL(buf,9) = tick; + WBUFL(buf,13) = val1; + WBUFL(buf,17) = val2; + WBUFL(buf,21) = val3; + } #endif - clif_send(buf,packet_len(WBUFW(buf,0)),bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA); + clif_send(buf,packet_len(WBUFW(buf,0)),bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA); } /// Send message (modified by [Yor]) (ZC_NOTIFY_PLAYERCHAT). /// 008e <packet len>.W <message>.?B -void clif_displaymessage(const int fd, const char *mes) -{ - nullpo_retv(mes); - - //Scrapped, as these are shared by disconnected players =X [Skotlex] - if (fd == 0) - ; - else { - char *message, *line; - - message = aStrdup(mes); - line = strtok(message, "\n"); - while (line != NULL) { - // Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client) - int len = strnlen(line, 255); - - if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line. - WFIFOHEAD(fd, 5 + len); - WFIFOW(fd,0) = 0x8e; - WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate - safestrncpy((char *)WFIFOP(fd,4), line, len + 1); - WFIFOSET(fd, 5 + len); - } - line = strtok(NULL, "\n"); - } - aFree(message); - } +void clif_displaymessage(const int fd, const char* mes) +{ + nullpo_retv(mes); + + //Scrapped, as these are shared by disconnected players =X [Skotlex] + if (fd == 0) + ; + else { + char *message, *line; + + message = aStrdup(mes); + line = strtok(message, "\n"); + while(line != NULL) { + // Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client) + int len = strnlen(line, 255); + + if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line. + WFIFOHEAD(fd, 5 + len); + WFIFOW(fd,0) = 0x8e; + WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate + safestrncpy(WFIFOP(fd,4), line, len + 1); + WFIFOSET(fd, 5 + len); + } + line = strtok(NULL, "\n"); + } + aFree(message); + } } /// Send broadcast message in yellow or blue without font formatting (ZC_BROADCAST). /// 009a <packet len>.W <message>.?B -void clif_broadcast(struct block_list *bl, const char *mes, int len, int type, enum send_target target) +void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, enum send_target target) { - int lp = type ? 4 : 0; - unsigned char *buf = (unsigned char *)aMalloc((4 + lp + len)*sizeof(unsigned char)); + int lp = type ? 4 : 0; + unsigned char *buf = (unsigned char*)aMalloc((4 + lp + len)*sizeof(unsigned char)); - WBUFW(buf,0) = 0x9a; - WBUFW(buf,2) = 4 + lp + len; - if (type == 0x10) // bc_blue - WBUFL(buf,4) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. - else if (type == 0x20) // bc_woe - WBUFL(buf,4) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. - memcpy(WBUFP(buf, 4 + lp), mes, len); - clif_send(buf, WBUFW(buf,2), bl, target); + WBUFW(buf,0) = 0x9a; + WBUFW(buf,2) = 4 + lp + len; + if (type == 0x10) // bc_blue + WBUFL(buf,4) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. + else if (type == 0x20) // bc_woe + WBUFL(buf,4) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. + memcpy(WBUFP(buf, 4 + lp), mes, len); + clif_send(buf, WBUFW(buf,2), bl, target); - if (buf) - aFree(buf); + if (buf) + aFree(buf); } /*========================================== * Displays a message on a 'bl' to all it's nearby clients * Used by npc_globalmessage *------------------------------------------*/ -void clif_GlobalMessage(struct block_list *bl, const char *message) -{ - char buf[100]; - int len; - nullpo_retv(bl); +void clif_GlobalMessage(struct block_list* bl, const char* message) { + char buf[100]; + int len; + nullpo_retv(bl); - if (!message) - return; + if(!message) + return; - len = strlen(message)+1; + len = strlen(message)+1; - if (len > sizeof(buf)-8) { - ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len); - len = sizeof(buf)-8; - } + if( len > sizeof(buf)-8 ) { + ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len); + len = sizeof(buf)-8; + } - WBUFW(buf,0)=0x8d; - WBUFW(buf,2)=len+8; - WBUFL(buf,4)=bl->id; - safestrncpy((char *) WBUFP(buf,8),message,len); - clif_send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT); + WBUFW(buf,0)=0x8d; + WBUFW(buf,2)=len+8; + WBUFL(buf,4)=bl->id; + safestrncpy((char *) WBUFP(buf,8),message,len); + clif_send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT); } /*========================================== * Send main chat message [LuzZza] *------------------------------------------*/ -void clif_MainChatMessage(const char *message) -{ - uint8 buf[200]; - int len; +void clif_MainChatMessage(const char* message) { + uint8 buf[200]; + int len; - if (!message) - return; + if(!message) + return; - len = strlen(message)+1; - if (len+8 > sizeof(buf)) { - ShowDebug("clif_MainChatMessage: Received message too long (len %d): %s\n", len, message); - len = sizeof(buf)-8; - } - WBUFW(buf,0)=0x8d; - WBUFW(buf,2)=len+8; - WBUFL(buf,4)=0; - safestrncpy((char *) WBUFP(buf,8),message,len); - clif_send(buf,WBUFW(buf,2),NULL,CHAT_MAINCHAT); + len = strlen(message)+1; + if (len+8 > sizeof(buf)) { + ShowDebug("clif_MainChatMessage: Received message too long (len %d): %s\n", len, message); + len = sizeof(buf)-8; + } + WBUFW(buf,0)=0x8d; + WBUFW(buf,2)=len+8; + WBUFL(buf,4)=0; + safestrncpy((char *) WBUFP(buf,8),message,len); + clif_send(buf,WBUFW(buf,2),NULL,CHAT_MAINCHAT); } /// Send broadcast message with font formatting (ZC_BROADCAST2). /// 01c3 <packet len>.W <fontColor>.L <fontType>.W <fontSize>.W <fontAlign>.W <fontY>.W <message>.?B -void clif_broadcast2(struct block_list *bl, const char *mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target) +void clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target) { - unsigned char *buf = (unsigned char *)aMalloc((16 + len)*sizeof(unsigned char)); + unsigned char *buf = (unsigned char*)aMalloc((16 + len)*sizeof(unsigned char)); - WBUFW(buf,0) = 0x1c3; - WBUFW(buf,2) = len + 16; - WBUFL(buf,4) = fontColor; - WBUFW(buf,8) = fontType; - WBUFW(buf,10) = fontSize; - WBUFW(buf,12) = fontAlign; - WBUFW(buf,14) = fontY; - memcpy(WBUFP(buf,16), mes, len); - clif_send(buf, WBUFW(buf,2), bl, target); + WBUFW(buf,0) = 0x1c3; + WBUFW(buf,2) = len + 16; + WBUFL(buf,4) = fontColor; + WBUFW(buf,8) = fontType; + WBUFW(buf,10) = fontSize; + WBUFW(buf,12) = fontAlign; + WBUFW(buf,14) = fontY; + memcpy(WBUFP(buf,16), mes, len); + clif_send(buf, WBUFW(buf,2), bl, target); - if (buf) - aFree(buf); + if (buf) + aFree(buf); } @@ -5454,11 +5513,11 @@ void clif_broadcast2(struct block_list *bl, const char *mes, int len, unsigned l /// ? = ignored void clif_heal(int fd,int type,int val) { - WFIFOHEAD(fd,packet_len(0x13d)); - WFIFOW(fd,0)=0x13d; - WFIFOW(fd,2)=type; - WFIFOW(fd,4)=cap_value(val,0,INT16_MAX); - WFIFOSET(fd,packet_len(0x13d)); + WFIFOHEAD(fd,packet_len(0x13d)); + WFIFOW(fd,0)=0x13d; + WFIFOW(fd,2)=type; + WFIFOW(fd,4)=cap_value(val,0,INT16_MAX); + WFIFOSET(fd,packet_len(0x13d)); } @@ -5468,49 +5527,49 @@ void clif_heal(int fd,int type,int val) /// ignored void clif_resurrection(struct block_list *bl,int type) { - unsigned char buf[16]; + unsigned char buf[16]; - nullpo_retv(bl); + nullpo_retv(bl); - WBUFW(buf,0)=0x148; - WBUFL(buf,2)=bl->id; - WBUFW(buf,6)=0; + WBUFW(buf,0)=0x148; + WBUFL(buf,2)=bl->id; + WBUFW(buf,6)=0; - clif_send(buf,packet_len(0x148),bl,type==1 ? AREA : AREA_WOS); - if (disguised(bl)) - clif_spawn(bl); + clif_send(buf,packet_len(0x148),bl,type==1 ? AREA : AREA_WOS); + if (disguised(bl)) + clif_spawn(bl); } /// Sets the map property (ZC_NOTIFY_MAPPROPERTY). /// 0199 <type>.W -void clif_map_property(struct map_session_data *sd, enum map_property property) +void clif_map_property(struct map_session_data* sd, enum map_property property) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x199)); - WFIFOW(fd,0)=0x199; - WFIFOW(fd,2)=property; - WFIFOSET(fd,packet_len(0x199)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x199)); + WFIFOW(fd,0)=0x199; + WFIFOW(fd,2)=property; + WFIFOSET(fd,packet_len(0x199)); } /// Set the map type (ZC_NOTIFY_MAPPROPERTY2). /// 01d6 <type>.W -void clif_map_type(struct map_session_data *sd, enum map_type type) +void clif_map_type(struct map_session_data* sd, enum map_type type) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x1D6)); - WFIFOW(fd,0)=0x1D6; - WFIFOW(fd,2)=type; - WFIFOSET(fd,packet_len(0x1D6)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x1D6)); + WFIFOW(fd,0)=0x1D6; + WFIFOW(fd,2)=type; + WFIFOSET(fd,packet_len(0x1D6)); } @@ -5518,30 +5577,30 @@ void clif_map_type(struct map_session_data *sd, enum map_type type) /// 019a <id>.L <ranking>.L <total>.L void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type) { - if (type == 2) { - int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x19a)); - WFIFOW(fd,0) = 0x19a; - WFIFOL(fd,2) = sd->bl.id; - WFIFOL(fd,6) = pvprank; - WFIFOL(fd,10) = pvpnum; - WFIFOSET(fd,packet_len(0x19a)); - } else { - unsigned char buf[32]; - WBUFW(buf,0) = 0x19a; - WBUFL(buf,2) = sd->bl.id; - if (sd->sc.option&(OPTION_HIDE|OPTION_CLOAK)) - WBUFL(buf,6) = UINT32_MAX; //On client displays as -- - else - WBUFL(buf,6) = pvprank; - WBUFL(buf,10) = pvpnum; - if (sd->sc.option&OPTION_INVISIBLE || sd->disguise) //Causes crashes when a 'mob' with pvp info dies. - clif_send(buf,packet_len(0x19a),&sd->bl,SELF); - else if (!type) - clif_send(buf,packet_len(0x19a),&sd->bl,AREA); - else - clif_send(buf,packet_len(0x19a),&sd->bl,ALL_SAMEMAP); - } + if(type == 2) { + int fd = sd->fd; + WFIFOHEAD(fd,packet_len(0x19a)); + WFIFOW(fd,0) = 0x19a; + WFIFOL(fd,2) = sd->bl.id; + WFIFOL(fd,6) = pvprank; + WFIFOL(fd,10) = pvpnum; + WFIFOSET(fd,packet_len(0x19a)); + } else { + unsigned char buf[32]; + WBUFW(buf,0) = 0x19a; + WBUFL(buf,2) = sd->bl.id; + if(sd->sc.option&(OPTION_HIDE|OPTION_CLOAK)) + WBUFL(buf,6) = UINT32_MAX; //On client displays as -- + else + WBUFL(buf,6) = pvprank; + WBUFL(buf,10) = pvpnum; + if(sd->sc.option&OPTION_INVISIBLE || sd->disguise) //Causes crashes when a 'mob' with pvp info dies. + clif_send(buf,packet_len(0x19a),&sd->bl,SELF); + else if(!type) + clif_send(buf,packet_len(0x19a),&sd->bl,AREA); + else + clif_send(buf,packet_len(0x19a),&sd->bl,ALL_SAMEMAP); + } } @@ -5550,15 +5609,15 @@ void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type) *------------------------------------------*/ void clif_map_property_mapall(int map, enum map_property property) { - struct block_list bl; - unsigned char buf[16]; + struct block_list bl; + unsigned char buf[16]; - bl.id = 0; - bl.type = BL_NUL; - bl.m = map; - WBUFW(buf,0)=0x199; - WBUFW(buf,2)=property; - clif_send(buf,packet_len(0x199),&bl,ALL_SAMEMAP); + bl.id = 0; + bl.type = BL_NUL; + bl.m = map; + WBUFW(buf,0)=0x199; + WBUFW(buf,2)=property; + clif_send(buf,packet_len(0x199),&bl,ALL_SAMEMAP); } @@ -5570,12 +5629,12 @@ void clif_map_property_mapall(int map, enum map_property property) /// 2 = downgrade void clif_refine(int fd, int fail, int index, int val) { - WFIFOHEAD(fd,packet_len(0x188)); - WFIFOW(fd,0)=0x188; - WFIFOW(fd,2)=fail; - WFIFOW(fd,4)=index+2; - WFIFOW(fd,6)=val; - WFIFOSET(fd,packet_len(0x188)); + WFIFOHEAD(fd,packet_len(0x188)); + WFIFOW(fd,0)=0x188; + WFIFOW(fd,2)=fail; + WFIFOW(fd,4)=index+2; + WFIFOW(fd,6)=val; + WFIFOSET(fd,packet_len(0x188)); } @@ -5588,35 +5647,35 @@ void clif_refine(int fd, int fail, int index, int val) /// 3 = "you lack the item %s to upgrade the weapon" MsgStringTable[914] in rgb(255,200,200) void clif_upgrademessage(int fd, int result, int item_id) { - WFIFOHEAD(fd,packet_len(0x223)); - WFIFOW(fd,0)=0x223; - WFIFOL(fd,2)=result; - WFIFOW(fd,6)=item_id; - WFIFOSET(fd,packet_len(0x223)); + WFIFOHEAD(fd,packet_len(0x223)); + WFIFOW(fd,0)=0x223; + WFIFOL(fd,2)=result; + WFIFOW(fd,6)=item_id; + WFIFOSET(fd,packet_len(0x223)); } /// Whisper is transmitted to the destination player (ZC_WHISPER). /// 0097 <packet len>.W <nick>.24B <message>.?B /// 0097 <packet len>.W <nick>.24B <isAdmin>.L <message>.?B (PACKETVER >= 20091104) -void clif_wis_message(int fd, const char *nick, const char *mes, int mes_len) +void clif_wis_message(int fd, const char* nick, const char* mes, int mes_len) { #if PACKETVER < 20091104 - WFIFOHEAD(fd, mes_len + NAME_LENGTH + 4); - WFIFOW(fd,0) = 0x97; - WFIFOW(fd,2) = mes_len + NAME_LENGTH + 4; - safestrncpy((char *)WFIFOP(fd,4), nick, NAME_LENGTH); - safestrncpy((char *)WFIFOP(fd,28), mes, mes_len); - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOHEAD(fd, mes_len + NAME_LENGTH + 4); + WFIFOW(fd,0) = 0x97; + WFIFOW(fd,2) = mes_len + NAME_LENGTH + 4; + safestrncpy((char*)WFIFOP(fd,4), nick, NAME_LENGTH); + safestrncpy((char*)WFIFOP(fd,28), mes, mes_len); + WFIFOSET(fd,WFIFOW(fd,2)); #else - WFIFOHEAD(fd, mes_len + NAME_LENGTH + 8); - WFIFOW(fd,0) = 0x97; - WFIFOW(fd,2) = mes_len + NAME_LENGTH + 8; - safestrncpy((char *)WFIFOP(fd,4), nick, NAME_LENGTH); - WFIFOL(fd,28) = 0; // isAdmin; if nonzero, also displays text above char - // TODO: WFIFOL(fd,28) = pc_get_group_level(ssd); - safestrncpy((char *)WFIFOP(fd,32), mes, mes_len); - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOHEAD(fd, mes_len + NAME_LENGTH + 8); + WFIFOW(fd,0) = 0x97; + WFIFOW(fd,2) = mes_len + NAME_LENGTH + 8; + safestrncpy((char*)WFIFOP(fd,4), nick, NAME_LENGTH); + WFIFOL(fd,28) = 0; // isAdmin; if nonzero, also displays text above char + // TODO: WFIFOL(fd,28) = pc_get_group_level(ssd); + safestrncpy((char*)WFIFOP(fd,32), mes, mes_len); + WFIFOSET(fd,WFIFOW(fd,2)); #endif } @@ -5630,22 +5689,22 @@ void clif_wis_message(int fd, const char *nick, const char *mes, int mes_len) /// 3 = everyone ignored by target void clif_wis_end(int fd, int flag) { - WFIFOHEAD(fd,packet_len(0x98)); - WFIFOW(fd,0) = 0x98; - WFIFOW(fd,2) = flag; - WFIFOSET(fd,packet_len(0x98)); + WFIFOHEAD(fd,packet_len(0x98)); + WFIFOW(fd,0) = 0x98; + WFIFOW(fd,2) = flag; + WFIFOSET(fd,packet_len(0x98)); } /// Returns character name requested by char_id (ZC_ACK_REQNAME_BYGID). /// 0194 <char id>.L <name>.24B -void clif_solved_charname(int fd, int charid, const char *name) +void clif_solved_charname(int fd, int charid, const char* name) { - WFIFOHEAD(fd,packet_len(0x194)); - WFIFOW(fd,0)=0x194; - WFIFOL(fd,2)=charid; - safestrncpy((char *)WFIFOP(fd,6), name, NAME_LENGTH); - WFIFOSET(fd,packet_len(0x194)); + WFIFOHEAD(fd,packet_len(0x194)); + WFIFOW(fd,0)=0x194; + WFIFOL(fd,2)=charid; + safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH); + WFIFOSET(fd,packet_len(0x194)); } @@ -5653,48 +5712,48 @@ void clif_solved_charname(int fd, int charid, const char *name) /// 017b <packet len>.W { <name id>.W }* void clif_use_card(struct map_session_data *sd,int idx) { - int i,c,ep; - int fd=sd->fd; + int i,c,ep; + int fd=sd->fd; - nullpo_retv(sd); - if (idx < 0 || idx >= MAX_INVENTORY) //Crash-fix from bad packets. - return; + nullpo_retv(sd); + if (idx < 0 || idx >= MAX_INVENTORY) //Crash-fix from bad packets. + return; - if (!sd->inventory_data[idx] || sd->inventory_data[idx]->type != IT_CARD) - return; //Avoid parsing invalid item indexes (no card/no item) + if (!sd->inventory_data[idx] || sd->inventory_data[idx]->type != IT_CARD) + return; //Avoid parsing invalid item indexes (no card/no item) - ep=sd->inventory_data[idx]->equip; - WFIFOHEAD(fd,MAX_INVENTORY * 2 + 4); - WFIFOW(fd,0)=0x17b; + ep=sd->inventory_data[idx]->equip; + WFIFOHEAD(fd,MAX_INVENTORY * 2 + 4); + WFIFOW(fd,0)=0x17b; - for (i=c=0; i<MAX_INVENTORY; i++) { - int j; + for(i=c=0;i<MAX_INVENTORY;i++){ + int j; - if (sd->inventory_data[i] == NULL) - continue; - if (sd->inventory_data[i]->type!=IT_WEAPON && sd->inventory_data[i]->type!=IT_ARMOR) - continue; - if (itemdb_isspecial(sd->status.inventory[i].card[0])) //Can't slot it - continue; + if(sd->inventory_data[i] == NULL) + continue; + if(sd->inventory_data[i]->type!=IT_WEAPON && sd->inventory_data[i]->type!=IT_ARMOR) + continue; + if(itemdb_isspecial(sd->status.inventory[i].card[0])) //Can't slot it + continue; - if (sd->status.inventory[i].identify==0) //Not identified - continue; + if(sd->status.inventory[i].identify==0 ) //Not identified + continue; - if ((sd->inventory_data[i]->equip&ep)==0) //Not equippable on this part. - continue; + if((sd->inventory_data[i]->equip&ep)==0) //Not equippable on this part. + continue; - if (sd->inventory_data[i]->type==IT_WEAPON && ep==EQP_SHIELD) //Shield card won't go on left weapon. - continue; + if(sd->inventory_data[i]->type==IT_WEAPON && ep==EQP_SHIELD) //Shield card won't go on left weapon. + continue; - ARR_FIND(0, sd->inventory_data[i]->slot, j, sd->status.inventory[i].card[j] == 0); - if (j == sd->inventory_data[i]->slot) // No room - continue; + ARR_FIND( 0, sd->inventory_data[i]->slot, j, sd->status.inventory[i].card[j] == 0 ); + if( j == sd->inventory_data[i]->slot ) // No room + continue; - WFIFOW(fd,4+c*2)=i+2; - c++; - } - WFIFOW(fd,2)=4+c*2; - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOW(fd,4+c*2)=i+2; + c++; + } + WFIFOW(fd,2)=4+c*2; + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -5705,17 +5764,17 @@ void clif_use_card(struct map_session_data *sd,int idx) /// 1 = failure void clif_insert_card(struct map_session_data *sd,int idx_equip,int idx_card,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x17d)); - WFIFOW(fd,0)=0x17d; - WFIFOW(fd,2)=idx_equip+2; - WFIFOW(fd,4)=idx_card+2; - WFIFOB(fd,6)=flag; - WFIFOSET(fd,packet_len(0x17d)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x17d)); + WFIFOW(fd,0)=0x17d; + WFIFOW(fd,2)=idx_equip+2; + WFIFOW(fd,4)=idx_card+2; + WFIFOB(fd,6)=flag; + WFIFOSET(fd,packet_len(0x17d)); } @@ -5723,27 +5782,27 @@ void clif_insert_card(struct map_session_data *sd,int idx_equip,int idx_card,int /// 0177 <packet len>.W { <name id>.W }* void clif_item_identify_list(struct map_session_data *sd) { - int i,c; - int fd; + int i,c; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; + fd=sd->fd; - WFIFOHEAD(fd,MAX_INVENTORY * 2 + 4); - WFIFOW(fd,0)=0x177; - for (i=c=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid > 0 && !sd->status.inventory[i].identify) { - WFIFOW(fd,c*2+4)=i+2; - c++; - } - } - if (c > 0) { - WFIFOW(fd,2)=c*2+4; - WFIFOSET(fd,WFIFOW(fd,2)); - sd->menuskill_id = MC_IDENTIFY; - sd->menuskill_val = c; - } + WFIFOHEAD(fd,MAX_INVENTORY * 2 + 4); + WFIFOW(fd,0)=0x177; + for(i=c=0;i<MAX_INVENTORY;i++){ + if(sd->status.inventory[i].nameid > 0 && !sd->status.inventory[i].identify){ + WFIFOW(fd,c*2+4)=i+2; + c++; + } + } + if(c > 0) { + WFIFOW(fd,2)=c*2+4; + WFIFOSET(fd,WFIFOW(fd,2)); + sd->menuskill_id = MC_IDENTIFY; + sd->menuskill_val = c; + } } @@ -5751,16 +5810,16 @@ void clif_item_identify_list(struct map_session_data *sd) /// 0179 <index>.W <result>.B void clif_item_identified(struct map_session_data *sd,int idx,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x179)); - WFIFOW(fd, 0)=0x179; - WFIFOW(fd, 2)=idx+2; - WFIFOB(fd, 4)=flag; - WFIFOSET(fd,packet_len(0x179)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x179)); + WFIFOW(fd, 0)=0x179; + WFIFOW(fd, 2)=idx+2; + WFIFOB(fd, 4)=flag; + WFIFOSET(fd,packet_len(0x179)); } @@ -5768,34 +5827,34 @@ void clif_item_identified(struct map_session_data *sd,int idx,int flag) /// 01fc <packet len>.W { <index>.W <name id>.W <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* void clif_item_repair_list(struct map_session_data *sd,struct map_session_data *dstsd, int lv) { - int i,c; - int fd; - int nameid; - - nullpo_retv(sd); - nullpo_retv(dstsd); - - fd=sd->fd; - - WFIFOHEAD(fd, MAX_INVENTORY * 13 + 4); - WFIFOW(fd,0)=0x1fc; - for (i=c=0; i<MAX_INVENTORY; i++) { - if ((nameid=dstsd->status.inventory[i].nameid) > 0 && dstsd->status.inventory[i].attribute!=0) { // && skill_can_repair(sd,nameid)){ - WFIFOW(fd,c*13+4) = i; - WFIFOW(fd,c*13+6) = nameid; - WFIFOB(fd,c*13+8) = dstsd->status.inventory[i].refine; - clif_addcards(WFIFOP(fd,c*13+9), &dstsd->status.inventory[i]); - c++; - } - } - if (c > 0) { - WFIFOW(fd,2)=c*13+4; - WFIFOSET(fd,WFIFOW(fd,2)); - sd->menuskill_id = BS_REPAIRWEAPON; - sd->menuskill_val = dstsd->bl.id; - sd->menuskill_val2 = lv; - } else - clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); + int i,c; + int fd; + int nameid; + + nullpo_retv(sd); + nullpo_retv(dstsd); + + fd=sd->fd; + + WFIFOHEAD(fd, MAX_INVENTORY * 13 + 4); + WFIFOW(fd,0)=0x1fc; + for(i=c=0;i<MAX_INVENTORY;i++){ + if((nameid=dstsd->status.inventory[i].nameid) > 0 && dstsd->status.inventory[i].attribute!=0){// && skill_can_repair(sd,nameid)){ + WFIFOW(fd,c*13+4) = i; + WFIFOW(fd,c*13+6) = nameid; + WFIFOB(fd,c*13+8) = dstsd->status.inventory[i].refine; + clif_addcards(WFIFOP(fd,c*13+9), &dstsd->status.inventory[i]); + c++; + } + } + if(c > 0) { + WFIFOW(fd,2)=c*13+4; + WFIFOSET(fd,WFIFOW(fd,2)); + sd->menuskill_id = BS_REPAIRWEAPON; + sd->menuskill_val = dstsd->bl.id; + sd->menuskill_val2 = lv; + }else + clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); } @@ -5808,32 +5867,32 @@ void clif_item_repair_list(struct map_session_data *sd,struct map_session_data * /// 1 = Item repair failure. void clif_item_repaireffect(struct map_session_data *sd,int idx,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; + fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x1fe)); - WFIFOW(fd, 0)=0x1fe; - WFIFOW(fd, 2)=idx+2; - WFIFOB(fd, 4)=flag; - WFIFOSET(fd,packet_len(0x1fe)); + WFIFOHEAD(fd,packet_len(0x1fe)); + WFIFOW(fd, 0)=0x1fe; + WFIFOW(fd, 2)=idx+2; + WFIFOB(fd, 4)=flag; + WFIFOSET(fd,packet_len(0x1fe)); } /// Displays a message, that an equipment got damaged (ZC_EQUIPITEM_DAMAGED). /// 02bb <equip location>.W <account id>.L -void clif_item_damaged(struct map_session_data *sd, unsigned short position) +void clif_item_damaged(struct map_session_data* sd, unsigned short position) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x2bb)); - WFIFOW(fd,0) = 0x2bb; - WFIFOW(fd,2) = position; - WFIFOL(fd,4) = sd->bl.id; // TODO: the packet seems to be sent to other people as well, probably party and/or guild. - WFIFOSET(fd,packet_len(0x2bb)); + WFIFOHEAD(fd,packet_len(0x2bb)); + WFIFOW(fd,0) = 0x2bb; + WFIFOW(fd,2) = position; + WFIFOL(fd,4) = sd->bl.id; // TODO: the packet seems to be sent to other people as well, probably party and/or guild. + WFIFOSET(fd,packet_len(0x2bb)); } @@ -5841,42 +5900,42 @@ void clif_item_damaged(struct map_session_data *sd, unsigned short position) /// 0221 <packet len>.W { <index>.W <name id>.W <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* void clif_item_refine_list(struct map_session_data *sd) { - int i,c; - int fd; - int skilllv; - int wlv; - int refine_item[5]; - - nullpo_retv(sd); - - skilllv = pc_checkskill(sd,WS_WEAPONREFINE); - - fd=sd->fd; - - refine_item[0] = -1; - refine_item[1] = pc_search_inventory(sd,1010); - refine_item[2] = pc_search_inventory(sd,1011); - refine_item[3] = refine_item[4] = pc_search_inventory(sd,984); - - WFIFOHEAD(fd, MAX_INVENTORY * 13 + 4); - WFIFOW(fd,0)=0x221; - for (i=c=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].refine < skilllv && - sd->status.inventory[i].identify && (wlv=itemdb_wlv(sd->status.inventory[i].nameid)) >=1 && - refine_item[wlv]!=-1 && !(sd->status.inventory[i].equip&EQP_ARMS)) { - WFIFOW(fd,c*13+ 4)=i+2; - WFIFOW(fd,c*13+ 6)=sd->status.inventory[i].nameid; - WFIFOB(fd,c*13+ 8)=sd->status.inventory[i].refine; - clif_addcards(WFIFOP(fd,c*13+9), &sd->status.inventory[i]); - c++; - } - } - WFIFOW(fd,2)=c*13+4; - WFIFOSET(fd,WFIFOW(fd,2)); - if (c > 0) { - sd->menuskill_id = WS_WEAPONREFINE; - sd->menuskill_val = skilllv; - } + int i,c; + int fd; + int skilllv; + int wlv; + int refine_item[5]; + + nullpo_retv(sd); + + skilllv = pc_checkskill(sd,WS_WEAPONREFINE); + + fd=sd->fd; + + refine_item[0] = -1; + refine_item[1] = pc_search_inventory(sd,1010); + refine_item[2] = pc_search_inventory(sd,1011); + refine_item[3] = refine_item[4] = pc_search_inventory(sd,984); + + WFIFOHEAD(fd, MAX_INVENTORY * 13 + 4); + WFIFOW(fd,0)=0x221; + for(i=c=0;i<MAX_INVENTORY;i++){ + if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].refine < skilllv && + sd->status.inventory[i].identify && (wlv=itemdb_wlv(sd->status.inventory[i].nameid)) >=1 && + refine_item[wlv]!=-1 && !(sd->status.inventory[i].equip&EQP_ARMS)){ + WFIFOW(fd,c*13+ 4)=i+2; + WFIFOW(fd,c*13+ 6)=sd->status.inventory[i].nameid; + WFIFOB(fd,c*13+ 8)=sd->status.inventory[i].refine; + clif_addcards(WFIFOP(fd,c*13+9), &sd->status.inventory[i]); + c++; + } + } + WFIFOW(fd,2)=c*13+4; + WFIFOSET(fd,WFIFOW(fd,2)); + if (c > 0) { + sd->menuskill_id = WS_WEAPONREFINE; + sd->menuskill_val = skilllv; + } } @@ -5884,22 +5943,22 @@ void clif_item_refine_list(struct map_session_data *sd) /// 0147 <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradable>.B void clif_item_skill(struct map_session_data *sd,int skillid,int skilllv) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x147)); - WFIFOW(fd, 0)=0x147; - WFIFOW(fd, 2)=skillid; - WFIFOW(fd, 4)=skill_get_inf(skillid); - WFIFOW(fd, 6)=0; - WFIFOW(fd, 8)=skilllv; - WFIFOW(fd,10)=skill_get_sp(skillid,skilllv); - WFIFOW(fd,12)=skill_get_range2(&sd->bl, skillid,skilllv); - safestrncpy((char *)WFIFOP(fd,14),skill_get_name(skillid),NAME_LENGTH); - WFIFOB(fd,38)=0; - WFIFOSET(fd,packet_len(0x147)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x147)); + WFIFOW(fd, 0)=0x147; + WFIFOW(fd, 2)=skillid; + WFIFOW(fd, 4)=skill_get_inf(skillid); + WFIFOW(fd, 6)=0; + WFIFOW(fd, 8)=skilllv; + WFIFOW(fd,10)=skill_get_sp(skillid,skilllv); + WFIFOW(fd,12)=skill_get_range2(&sd->bl, skillid,skilllv); + safestrncpy((char*)WFIFOP(fd,14),skill_get_name(skillid),NAME_LENGTH); + WFIFOB(fd,38)=0; + WFIFOSET(fd,packet_len(0x147)); } @@ -5908,46 +5967,46 @@ void clif_item_skill(struct map_session_data *sd,int skillid,int skilllv) /// 01c5 <index>.W <amount>.L <name id>.W <type>.B <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W (ZC_ADD_ITEM_TO_CART2) void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail) { - int view,fd; - unsigned char *buf; + int view,fd; + unsigned char *buf; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - if (n<0 || n>=MAX_CART || sd->status.cart[n].nameid<=0) - return; + fd=sd->fd; + if(n<0 || n>=MAX_CART || sd->status.cart[n].nameid<=0) + return; #if PACKETVER < 5 - WFIFOHEAD(fd,packet_len(0x124)); - buf=WFIFOP(fd,0); - WBUFW(buf,0)=0x124; - WBUFW(buf,2)=n+2; - WBUFL(buf,4)=amount; - if ((view = itemdb_viewid(sd->status.cart[n].nameid)) > 0) - WBUFW(buf,8)=view; - else - WBUFW(buf,8)=sd->status.cart[n].nameid; - WBUFB(buf,10)=sd->status.cart[n].identify; - WBUFB(buf,11)=sd->status.cart[n].attribute; - WBUFB(buf,12)=sd->status.cart[n].refine; - clif_addcards(WBUFP(buf,13), &sd->status.cart[n]); - WFIFOSET(fd,packet_len(0x124)); + WFIFOHEAD(fd,packet_len(0x124)); + buf=WFIFOP(fd,0); + WBUFW(buf,0)=0x124; + WBUFW(buf,2)=n+2; + WBUFL(buf,4)=amount; + if((view = itemdb_viewid(sd->status.cart[n].nameid)) > 0) + WBUFW(buf,8)=view; + else + WBUFW(buf,8)=sd->status.cart[n].nameid; + WBUFB(buf,10)=sd->status.cart[n].identify; + WBUFB(buf,11)=sd->status.cart[n].attribute; + WBUFB(buf,12)=sd->status.cart[n].refine; + clif_addcards(WBUFP(buf,13), &sd->status.cart[n]); + WFIFOSET(fd,packet_len(0x124)); #else - WFIFOHEAD(fd,packet_len(0x1c5)); - buf=WFIFOP(fd,0); - WBUFW(buf,0)=0x1c5; - WBUFW(buf,2)=n+2; - WBUFL(buf,4)=amount; - if ((view = itemdb_viewid(sd->status.cart[n].nameid)) > 0) - WBUFW(buf,8)=view; - else - WBUFW(buf,8)=sd->status.cart[n].nameid; - WBUFB(buf,10)=itemdb_type(sd->status.cart[n].nameid); - WBUFB(buf,11)=sd->status.cart[n].identify; - WBUFB(buf,12)=sd->status.cart[n].attribute; - WBUFB(buf,13)=sd->status.cart[n].refine; - clif_addcards(WBUFP(buf,14), &sd->status.cart[n]); - WFIFOSET(fd,packet_len(0x1c5)); + WFIFOHEAD(fd,packet_len(0x1c5)); + buf=WFIFOP(fd,0); + WBUFW(buf,0)=0x1c5; + WBUFW(buf,2)=n+2; + WBUFL(buf,4)=amount; + if((view = itemdb_viewid(sd->status.cart[n].nameid)) > 0) + WBUFW(buf,8)=view; + else + WBUFW(buf,8)=sd->status.cart[n].nameid; + WBUFB(buf,10)=itemdb_type(sd->status.cart[n].nameid); + WBUFB(buf,11)=sd->status.cart[n].identify; + WBUFB(buf,12)=sd->status.cart[n].attribute; + WBUFB(buf,13)=sd->status.cart[n].refine; + clif_addcards(WBUFP(buf,14), &sd->status.cart[n]); + WFIFOSET(fd,packet_len(0x1c5)); #endif } @@ -5956,17 +6015,17 @@ void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail) /// 0125 <index>.W <amount>.L void clif_cart_delitem(struct map_session_data *sd,int n,int amount) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; + fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x125)); - WFIFOW(fd,0)=0x125; - WFIFOW(fd,2)=n+2; - WFIFOL(fd,4)=amount; - WFIFOSET(fd,packet_len(0x125)); + WFIFOHEAD(fd,packet_len(0x125)); + WFIFOW(fd,0)=0x125; + WFIFOW(fd,2)=n+2; + WFIFOL(fd,4)=amount; + WFIFOSET(fd,packet_len(0x125)); } @@ -5974,107 +6033,108 @@ void clif_cart_delitem(struct map_session_data *sd,int n,int amount) /// 012d <num>.W /// num: /// number of allowed item slots -void clif_openvendingreq(struct map_session_data *sd, int num) +void clif_openvendingreq(struct map_session_data* sd, int num) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x12d)); - WFIFOW(fd,0) = 0x12d; - WFIFOW(fd,2) = num; - WFIFOSET(fd,packet_len(0x12d)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0x12d)); + WFIFOW(fd,0) = 0x12d; + WFIFOW(fd,2) = num; + WFIFOSET(fd,packet_len(0x12d)); } /// Displays a vending board to target/area (ZC_STORE_ENTRY). /// 0131 <owner id>.L <message>.80B -void clif_showvendingboard(struct block_list *bl, const char *message, int fd) +void clif_showvendingboard(struct block_list* bl, const char* message, int fd) { - unsigned char buf[128]; + unsigned char buf[128]; - nullpo_retv(bl); + nullpo_retv(bl); - WBUFW(buf,0) = 0x131; - WBUFL(buf,2) = bl->id; - safestrncpy((char *)WBUFP(buf,6), message, 80); + WBUFW(buf,0) = 0x131; + WBUFL(buf,2) = bl->id; + safestrncpy((char*)WBUFP(buf,6), message, 80); - if (fd) { - WFIFOHEAD(fd,packet_len(0x131)); - memcpy(WFIFOP(fd,0),buf,packet_len(0x131)); - WFIFOSET(fd,packet_len(0x131)); - } else { - clif_send(buf,packet_len(0x131),bl,AREA_WOS); - } + if( fd ) { + WFIFOHEAD(fd,packet_len(0x131)); + memcpy(WFIFOP(fd,0),buf,packet_len(0x131)); + WFIFOSET(fd,packet_len(0x131)); + } else { + clif_send(buf,packet_len(0x131),bl,AREA_WOS); + } } /// Removes a vending board from screen (ZC_DISAPPEAR_ENTRY). /// 0132 <owner id>.L -void clif_closevendingboard(struct block_list *bl, int fd) +void clif_closevendingboard(struct block_list* bl, int fd) { - unsigned char buf[16]; + unsigned char buf[16]; - nullpo_retv(bl); + nullpo_retv(bl); - WBUFW(buf,0) = 0x132; - WBUFL(buf,2) = bl->id; - if (fd) { - WFIFOHEAD(fd,packet_len(0x132)); - memcpy(WFIFOP(fd,0),buf,packet_len(0x132)); - WFIFOSET(fd,packet_len(0x132)); - } else { - clif_send(buf,packet_len(0x132),bl,AREA_WOS); - } + WBUFW(buf,0) = 0x132; + WBUFL(buf,2) = bl->id; + if( fd ) { + WFIFOHEAD(fd,packet_len(0x132)); + memcpy(WFIFOP(fd,0),buf,packet_len(0x132)); + WFIFOSET(fd,packet_len(0x132)); + } else { + clif_send(buf,packet_len(0x132),bl,AREA_WOS); + } } /// Sends a list of items in a shop. /// R 0133 <packet len>.W <owner id>.L { <price>.L <amount>.W <index>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* (ZC_PC_PURCHASE_ITEMLIST_FROMMC) /// R 0800 <packet len>.W <owner id>.L <unique id>.L { <price>.L <amount>.W <index>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* (ZC_PC_PURCHASE_ITEMLIST_FROMMC2) -void clif_vendinglist(struct map_session_data *sd, int id, struct s_vending *vending) +void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* vending) { - int i,fd; - int count; - struct map_session_data *vsd; + int i,fd; + int count; + struct map_session_data* vsd; #if PACKETVER < 20100105 - const int cmd = 0x133; - const int offset = 8; + const int cmd = 0x133; + const int offset = 8; #else - const int cmd = 0x800; - const int offset = 12; + const int cmd = 0x800; + const int offset = 12; #endif - nullpo_retv(sd); - nullpo_retv(vending); - nullpo_retv(vsd=map_id2sd(id)); + nullpo_retv(sd); + nullpo_retv(vending); + nullpo_retv(vsd=map_id2sd(id)); - fd = sd->fd; - count = vsd->vend_num; + fd = sd->fd; + count = vsd->vend_num; - WFIFOHEAD(fd, offset+count*22); - WFIFOW(fd,0) = cmd; - WFIFOW(fd,2) = offset+count*22; - WFIFOL(fd,4) = id; + WFIFOHEAD(fd, offset+count*22); + WFIFOW(fd,0) = cmd; + WFIFOW(fd,2) = offset+count*22; + WFIFOL(fd,4) = id; #if PACKETVER >= 20100105 - WFIFOL(fd,8) = vsd->vender_id; + WFIFOL(fd,8) = vsd->vender_id; #endif - for (i = 0; i < count; i++) { - int index = vending[i].index; - struct item_data *data = itemdb_search(vsd->status.cart[index].nameid); - WFIFOL(fd,offset+ 0+i*22) = vending[i].value; - WFIFOW(fd,offset+ 4+i*22) = vending[i].amount; - WFIFOW(fd,offset+ 6+i*22) = vending[i].index + 2; - WFIFOB(fd,offset+ 8+i*22) = itemtype(data->type); - WFIFOW(fd,offset+ 9+i*22) = (data->view_id > 0) ? data->view_id : vsd->status.cart[index].nameid; - WFIFOB(fd,offset+11+i*22) = vsd->status.cart[index].identify; - WFIFOB(fd,offset+12+i*22) = vsd->status.cart[index].attribute; - WFIFOB(fd,offset+13+i*22) = vsd->status.cart[index].refine; - clif_addcards(WFIFOP(fd,offset+14+i*22), &vsd->status.cart[index]); - } - WFIFOSET(fd,WFIFOW(fd,2)); + for( i = 0; i < count; i++ ) + { + int index = vending[i].index; + struct item_data* data = itemdb_search(vsd->status.cart[index].nameid); + WFIFOL(fd,offset+ 0+i*22) = vending[i].value; + WFIFOW(fd,offset+ 4+i*22) = vending[i].amount; + WFIFOW(fd,offset+ 6+i*22) = vending[i].index + 2; + WFIFOB(fd,offset+ 8+i*22) = itemtype(data->type); + WFIFOW(fd,offset+ 9+i*22) = ( data->view_id > 0 ) ? data->view_id : vsd->status.cart[index].nameid; + WFIFOB(fd,offset+11+i*22) = vsd->status.cart[index].identify; + WFIFOB(fd,offset+12+i*22) = vsd->status.cart[index].attribute; + WFIFOB(fd,offset+13+i*22) = vsd->status.cart[index].refine; + clif_addcards(WFIFOP(fd,offset+14+i*22), &vsd->status.cart[index]); + } + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -6088,69 +6148,70 @@ void clif_vendinglist(struct map_session_data *sd, int id, struct s_vending *ven /// 5 = "cannot use an npc shop while in a trade" /// 6 = Because the store information was incorrect the item was not purchased. /// 7 = No sales information. -void clif_buyvending(struct map_session_data *sd, int index, int amount, int fail) +void clif_buyvending(struct map_session_data* sd, int index, int amount, int fail) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x135)); - WFIFOW(fd,0) = 0x135; - WFIFOW(fd,2) = index+2; - WFIFOW(fd,4) = amount; - WFIFOB(fd,6) = fail; - WFIFOSET(fd,packet_len(0x135)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0x135)); + WFIFOW(fd,0) = 0x135; + WFIFOW(fd,2) = index+2; + WFIFOW(fd,4) = amount; + WFIFOB(fd,6) = fail; + WFIFOSET(fd,packet_len(0x135)); } /// Shop creation success (ZC_PC_PURCHASE_MYITEMLIST). /// 0136 <packet len>.W <owner id>.L { <price>.L <index>.W <amount>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* -void clif_openvending(struct map_session_data *sd, int id, struct s_vending *vending) -{ - int i,fd; - int count; - - nullpo_retv(sd); - - fd = sd->fd; - count = sd->vend_num; - - WFIFOHEAD(fd, 8+count*22); - WFIFOW(fd,0) = 0x136; - WFIFOW(fd,2) = 8+count*22; - WFIFOL(fd,4) = id; - for (i = 0; i < count; i++) { - int index = vending[i].index; - struct item_data *data = itemdb_search(sd->status.cart[index].nameid); - WFIFOL(fd, 8+i*22) = vending[i].value; - WFIFOW(fd,12+i*22) = vending[i].index + 2; - WFIFOW(fd,14+i*22) = vending[i].amount; - WFIFOB(fd,16+i*22) = itemtype(data->type); - WFIFOW(fd,17+i*22) = (data->view_id > 0) ? data->view_id : sd->status.cart[index].nameid; - WFIFOB(fd,19+i*22) = sd->status.cart[index].identify; - WFIFOB(fd,20+i*22) = sd->status.cart[index].attribute; - WFIFOB(fd,21+i*22) = sd->status.cart[index].refine; - clif_addcards(WFIFOP(fd,22+i*22), &sd->status.cart[index]); - } - WFIFOSET(fd,WFIFOW(fd,2)); +void clif_openvending(struct map_session_data* sd, int id, struct s_vending* vending) +{ + int i,fd; + int count; + + nullpo_retv(sd); + + fd = sd->fd; + count = sd->vend_num; + + WFIFOHEAD(fd, 8+count*22); + WFIFOW(fd,0) = 0x136; + WFIFOW(fd,2) = 8+count*22; + WFIFOL(fd,4) = id; + for( i = 0; i < count; i++ ) + { + int index = vending[i].index; + struct item_data* data = itemdb_search(sd->status.cart[index].nameid); + WFIFOL(fd, 8+i*22) = vending[i].value; + WFIFOW(fd,12+i*22) = vending[i].index + 2; + WFIFOW(fd,14+i*22) = vending[i].amount; + WFIFOB(fd,16+i*22) = itemtype(data->type); + WFIFOW(fd,17+i*22) = ( data->view_id > 0 ) ? data->view_id : sd->status.cart[index].nameid; + WFIFOB(fd,19+i*22) = sd->status.cart[index].identify; + WFIFOB(fd,20+i*22) = sd->status.cart[index].attribute; + WFIFOB(fd,21+i*22) = sd->status.cart[index].refine; + clif_addcards(WFIFOP(fd,22+i*22), &sd->status.cart[index]); + } + WFIFOSET(fd,WFIFOW(fd,2)); } /// Inform merchant that someone has bought an item (ZC_DELETEITEM_FROM_MCSTORE). /// 0137 <index>.W <amount>.W -void clif_vendingreport(struct map_session_data *sd, int index, int amount) +void clif_vendingreport(struct map_session_data* sd, int index, int amount) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x137)); - WFIFOW(fd,0) = 0x137; - WFIFOW(fd,2) = index+2; - WFIFOW(fd,4) = amount; - WFIFOSET(fd,packet_len(0x137)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0x137)); + WFIFOW(fd,0) = 0x137; + WFIFOW(fd,2) = index+2; + WFIFOW(fd,4) = amount; + WFIFOSET(fd,packet_len(0x137)); } @@ -6164,15 +6225,15 @@ void clif_vendingreport(struct map_session_data *sd, int index, int amount) /// ? = nothing void clif_party_created(struct map_session_data *sd,int result) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xfa)); - WFIFOW(fd,0)=0xfa; - WFIFOB(fd,2)=result; - WFIFOSET(fd,packet_len(0xfa)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xfa)); + WFIFOW(fd,0)=0xfa; + WFIFOB(fd,2)=result; + WFIFOSET(fd,packet_len(0xfa)); } @@ -6187,29 +6248,29 @@ void clif_party_created(struct map_session_data *sd,int result) /// 1 = disconnected void clif_party_member_info(struct party_data *p, struct map_session_data *sd) { - unsigned char buf[81]; - int i; + unsigned char buf[81]; + int i; - if (!sd) { //Pick any party member (this call is used when changing item share rules) - ARR_FIND(0, MAX_PARTY, i, p->data[i].sd != 0); - } else { - ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd); - } - if (i >= MAX_PARTY) return; //Should never happen... - sd = p->data[i].sd; + if (!sd) { //Pick any party member (this call is used when changing item share rules) + ARR_FIND( 0, MAX_PARTY, i, p->data[i].sd != 0 ); + } else { + ARR_FIND( 0, MAX_PARTY, i, p->data[i].sd == sd ); + } + if (i >= MAX_PARTY) return; //Should never happen... + sd = p->data[i].sd; - WBUFW(buf, 0) = 0x1e9; - WBUFL(buf, 2) = sd->status.account_id; - WBUFL(buf, 6) = (p->party.member[i].leader)?0:1; - WBUFW(buf,10) = sd->bl.x; - WBUFW(buf,12) = sd->bl.y; - WBUFB(buf,14) = (p->party.member[i].online)?0:1; - memcpy(WBUFP(buf,15), p->party.name, NAME_LENGTH); - memcpy(WBUFP(buf,39), sd->status.name, NAME_LENGTH); - mapindex_getmapname_ext(map[sd->bl.m].name, (char *)WBUFP(buf,63)); - WBUFB(buf,79) = (p->party.item&1)?1:0; - WBUFB(buf,80) = (p->party.item&2)?1:0; - clif_send(buf,packet_len(0x1e9),&sd->bl,PARTY); + WBUFW(buf, 0) = 0x1e9; + WBUFL(buf, 2) = sd->status.account_id; + WBUFL(buf, 6) = (p->party.member[i].leader)?0:1; + WBUFW(buf,10) = sd->bl.x; + WBUFW(buf,12) = sd->bl.y; + WBUFB(buf,14) = (p->party.member[i].online)?0:1; + memcpy(WBUFP(buf,15), p->party.name, NAME_LENGTH); + memcpy(WBUFP(buf,39), sd->status.name, NAME_LENGTH); + mapindex_getmapname_ext(map[sd->bl.m].name, (char*)WBUFP(buf,63)); + WBUFB(buf,79) = (p->party.item&1)?1:0; + WBUFB(buf,80) = (p->party.item&2)?1:0; + clif_send(buf,packet_len(0x1e9),&sd->bl,PARTY); } @@ -6221,36 +6282,37 @@ void clif_party_member_info(struct party_data *p, struct map_session_data *sd) /// state: /// 0 = connected /// 1 = disconnected -void clif_party_info(struct party_data *p, struct map_session_data *sd) +void clif_party_info(struct party_data* p, struct map_session_data *sd) { - unsigned char buf[2+2+NAME_LENGTH+(4+NAME_LENGTH+MAP_NAME_LENGTH_EXT+1+1)*MAX_PARTY]; - struct map_session_data *party_sd = NULL; - int i, c; + unsigned char buf[2+2+NAME_LENGTH+(4+NAME_LENGTH+MAP_NAME_LENGTH_EXT+1+1)*MAX_PARTY]; + struct map_session_data* party_sd = NULL; + int i, c; - nullpo_retv(p); + nullpo_retv(p); - WBUFW(buf,0) = 0xfb; - memcpy(WBUFP(buf,4), p->party.name, NAME_LENGTH); - for (i = 0, c = 0; i < MAX_PARTY; i++) { - struct party_member *m = &p->party.member[i]; - if (!m->account_id) continue; + WBUFW(buf,0) = 0xfb; + memcpy(WBUFP(buf,4), p->party.name, NAME_LENGTH); + for(i = 0, c = 0; i < MAX_PARTY; i++) + { + struct party_member* m = &p->party.member[i]; + if(!m->account_id) continue; - if (party_sd == NULL) party_sd = p->data[i].sd; + if(party_sd == NULL) party_sd = p->data[i].sd; - WBUFL(buf,28+c*46) = m->account_id; - memcpy(WBUFP(buf,28+c*46+4), m->name, NAME_LENGTH); - mapindex_getmapname_ext(mapindex_id2name(m->map), (char *)WBUFP(buf,28+c*46+28)); - WBUFB(buf,28+c*46+44) = (m->leader) ? 0 : 1; - WBUFB(buf,28+c*46+45) = (m->online) ? 0 : 1; - c++; - } - WBUFW(buf,2) = 28+c*46; + WBUFL(buf,28+c*46) = m->account_id; + memcpy(WBUFP(buf,28+c*46+4), m->name, NAME_LENGTH); + mapindex_getmapname_ext(mapindex_id2name(m->map), (char*)WBUFP(buf,28+c*46+28)); + WBUFB(buf,28+c*46+44) = (m->leader) ? 0 : 1; + WBUFB(buf,28+c*46+45) = (m->online) ? 0 : 1; + c++; + } + WBUFW(buf,2) = 28+c*46; - if (sd) { // send only to self - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); - } else if (party_sd) { // send to whole party - clif_send(buf, WBUFW(buf,2), &party_sd->bl, PARTY); - } + if(sd) { // send only to self + clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + } else if (party_sd) { // send to whole party + clif_send(buf, WBUFW(buf,2), &party_sd->bl, PARTY); + } } @@ -6259,16 +6321,16 @@ void clif_party_info(struct party_data *p, struct map_session_data *sd) /// flag: /// 0 = allow party invites /// 1 = auto-deny party invites -void clif_partyinvitationstate(struct map_session_data *sd) +void clif_partyinvitationstate(struct map_session_data* sd) { - int fd; - nullpo_retv(sd); - fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; - WFIFOHEAD(fd, packet_len(0x2c9)); - WFIFOW(fd, 0) = 0x2c9; - WFIFOB(fd, 2) = 0; // not implemented - WFIFOSET(fd, packet_len(0x2c9)); + WFIFOHEAD(fd, packet_len(0x2c9)); + WFIFOW(fd, 0) = 0x2c9; + WFIFOB(fd, 2) = 0; // not implemented + WFIFOSET(fd, packet_len(0x2c9)); } @@ -6278,26 +6340,26 @@ void clif_partyinvitationstate(struct map_session_data *sd) void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd) { #if PACKETVER < 20070821 - const int cmd = 0xfe; + const int cmd = 0xfe; #else - const int cmd = 0x2c6; + const int cmd = 0x2c6; #endif - int fd; - struct party_data *p; + int fd; + struct party_data *p; - nullpo_retv(sd); - nullpo_retv(tsd); + nullpo_retv(sd); + nullpo_retv(tsd); - fd=tsd->fd; + fd=tsd->fd; - if ((p=party_search(sd->status.party_id))==NULL) - return; + if( (p=party_search(sd->status.party_id))==NULL ) + return; - WFIFOHEAD(fd,packet_len(cmd)); - WFIFOW(fd,0)=cmd; - WFIFOL(fd,2)=sd->status.party_id; - memcpy(WFIFOP(fd,6),p->party.name,NAME_LENGTH); - WFIFOSET(fd,packet_len(cmd)); + WFIFOHEAD(fd,packet_len(cmd)); + WFIFOW(fd,0)=cmd; + WFIFOL(fd,2)=sd->status.party_id; + memcpy(WFIFOP(fd,6),p->party.name,NAME_LENGTH); + WFIFOSET(fd,packet_len(cmd)); } @@ -6313,31 +6375,31 @@ void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd) /// result=7 : char is not online or doesn't exist -> MsgStringTable[71] (since 20070904) /// result=8 : (%s) TODO instance related? -> MsgStringTable[1388] (since 20080527) /// return=9 : TODO map prohibits party joining? -> MsgStringTable[1871] (since 20110205) -void clif_party_inviteack(struct map_session_data *sd, const char *nick, int result) +void clif_party_inviteack(struct map_session_data* sd, const char* nick, int result) { - int fd; - nullpo_retv(sd); - fd=sd->fd; + int fd; + nullpo_retv(sd); + fd=sd->fd; #if PACKETVER < 20070904 - if (result == 7) { - clif_displaymessage(fd, msg_txt(3)); - return; - } + if( result == 7 ) { + clif_displaymessage(fd, msg_txt(3)); + return; + } #endif #if PACKETVER < 20070821 - WFIFOHEAD(fd,packet_len(0xfd)); - WFIFOW(fd,0) = 0xfd; - safestrncpy((char *)WFIFOP(fd,2),nick,NAME_LENGTH); - WFIFOB(fd,26) = result; - WFIFOSET(fd,packet_len(0xfd)); + WFIFOHEAD(fd,packet_len(0xfd)); + WFIFOW(fd,0) = 0xfd; + safestrncpy((char*)WFIFOP(fd,2),nick,NAME_LENGTH); + WFIFOB(fd,26) = result; + WFIFOSET(fd,packet_len(0xfd)); #else - WFIFOHEAD(fd,packet_len(0x2c5)); - WFIFOW(fd,0) = 0x2c5; - safestrncpy((char *)WFIFOP(fd,2),nick,NAME_LENGTH); - WFIFOL(fd,26) = result; - WFIFOSET(fd,packet_len(0x2c5)); + WFIFOHEAD(fd,packet_len(0x2c5)); + WFIFOW(fd,0) = 0x2c5; + safestrncpy((char*)WFIFOP(fd,2),nick,NAME_LENGTH); + WFIFOL(fd,26) = result; + WFIFOSET(fd,packet_len(0x2c5)); #endif } @@ -6355,32 +6417,32 @@ void clif_party_inviteack(struct map_session_data *sd, const char *nick, int res /// 1 = send to sd void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag) { - unsigned char buf[16]; + unsigned char buf[16]; #if PACKETVER < 20090603 - const int cmd = 0x101; + const int cmd = 0x101; #else - const int cmd = 0x7d8; + const int cmd = 0x7d8; #endif - nullpo_retv(p); - - if (!sd && flag==0) { - int i; - for (i=0; i<MAX_PARTY && !p->data[i].sd; i++); - if (i < MAX_PARTY) - sd = p->data[i].sd; - } - if (!sd) return; - WBUFW(buf,0)=cmd; - WBUFL(buf,2)=((flag&0x01)?2:p->party.exp); + nullpo_retv(p); + + if(!sd && flag==0){ + int i; + for(i=0;i<MAX_PARTY && !p->data[i].sd;i++); + if (i < MAX_PARTY) + sd = p->data[i].sd; + } + if(!sd) return; + WBUFW(buf,0)=cmd; + WBUFL(buf,2)=((flag&0x01)?2:p->party.exp); #if PACKETVER >= 20090603 - WBUFB(buf,6)=(p->party.item&1)?1:0; - WBUFB(buf,7)=(p->party.item&2)?1:0; + WBUFB(buf,6)=(p->party.item&1)?1:0; + WBUFB(buf,7)=(p->party.item&2)?1:0; #endif - if (flag==0) - clif_send(buf,packet_len(cmd),&sd->bl,PARTY); - else - clif_send(buf,packet_len(cmd),&sd->bl,SELF); + if(flag==0) + clif_send(buf,packet_len(cmd),&sd->bl,PARTY); + else + clif_send(buf,packet_len(cmd),&sd->bl,SELF); } @@ -6390,57 +6452,59 @@ void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag /// 1 = expel /// 2 = cannot leave party on this map /// 3 = cannot expel from party on this map -void clif_party_withdraw(struct party_data *p, struct map_session_data *sd, int account_id, const char *name, int flag) +void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int account_id, const char* name, int flag) { - unsigned char buf[64]; - int i; + unsigned char buf[64]; + int i; - nullpo_retv(p); + nullpo_retv(p); - if (!sd && (flag&0xf0)==0) { - for (i=0; i<MAX_PARTY && !p->data[i].sd; i++); - if (i < MAX_PARTY) - sd = p->data[i].sd; - } + if(!sd && (flag&0xf0)==0) + { + for(i=0;i<MAX_PARTY && !p->data[i].sd;i++); + if (i < MAX_PARTY) + sd = p->data[i].sd; + } - if (!sd) return; + if(!sd) return; - WBUFW(buf,0)=0x105; - WBUFL(buf,2)=account_id; - memcpy(WBUFP(buf,6),name,NAME_LENGTH); - WBUFB(buf,30)=flag&0x0f; - if ((flag&0xf0)==0) - clif_send(buf,packet_len(0x105),&sd->bl,PARTY); - else - clif_send(buf,packet_len(0x105),&sd->bl,SELF); + WBUFW(buf,0)=0x105; + WBUFL(buf,2)=account_id; + memcpy(WBUFP(buf,6),name,NAME_LENGTH); + WBUFB(buf,30)=flag&0x0f; + if((flag&0xf0)==0) + clif_send(buf,packet_len(0x105),&sd->bl,PARTY); + else + clif_send(buf,packet_len(0x105),&sd->bl,SELF); } /// Party chat message (ZC_NOTIFY_CHAT_PARTY). /// 0109 <packet len>.W <account id>.L <message>.?B -void clif_party_message(struct party_data *p, int account_id, const char *mes, int len) +void clif_party_message(struct party_data* p, int account_id, const char* mes, int len) { - struct map_session_data *sd; - int i; + struct map_session_data *sd; + int i; - nullpo_retv(p); + nullpo_retv(p); - for (i=0; i < MAX_PARTY && !p->data[i].sd; i++); - if (i < MAX_PARTY) { - unsigned char buf[1024]; + for(i=0; i < MAX_PARTY && !p->data[i].sd;i++); + if(i < MAX_PARTY){ + unsigned char buf[1024]; - if (len > sizeof(buf)-8) { - ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%d, party_id=%d).\n", mes, len, sizeof(buf)-8, p->party.party_id); - len = sizeof(buf)-8; - } + if( len > sizeof(buf)-8 ) + { + ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%d, party_id=%d).\n", mes, len, sizeof(buf)-8, p->party.party_id); + len = sizeof(buf)-8; + } - sd = p->data[i].sd; - WBUFW(buf,0)=0x109; - WBUFW(buf,2)=len+8; - WBUFL(buf,4)=account_id; - safestrncpy((char *)WBUFP(buf,8), mes, len); - clif_send(buf,len+8,&sd->bl,PARTY); - } + sd = p->data[i].sd; + WBUFW(buf,0)=0x109; + WBUFW(buf,2)=len+8; + WBUFL(buf,4)=account_id; + safestrncpy(WBUFP(buf,8), mes, len); + clif_send(buf,len+8,&sd->bl,PARTY); + } } @@ -6448,15 +6512,15 @@ void clif_party_message(struct party_data *p, int account_id, const char *mes, i /// 0107 <account id>.L <x>.W <y>.W void clif_party_xy(struct map_session_data *sd) { - unsigned char buf[16]; + unsigned char buf[16]; - nullpo_retv(sd); + nullpo_retv(sd); - WBUFW(buf,0)=0x107; - WBUFL(buf,2)=sd->status.account_id; - WBUFW(buf,6)=sd->bl.x; - WBUFW(buf,8)=sd->bl.y; - clif_send(buf,packet_len(0x107),&sd->bl,PARTY_SAMEMAP_WOS); + WBUFW(buf,0)=0x107; + WBUFL(buf,2)=sd->status.account_id; + WBUFW(buf,6)=sd->bl.x; + WBUFW(buf,8)=sd->bl.y; + clif_send(buf,packet_len(0x107),&sd->bl,PARTY_SAMEMAP_WOS); } @@ -6465,12 +6529,12 @@ void clif_party_xy(struct map_session_data *sd) *------------------------------------------*/ void clif_party_xy_single(int fd, struct map_session_data *sd) { - WFIFOHEAD(fd,packet_len(0x107)); - WFIFOW(fd,0)=0x107; - WFIFOL(fd,2)=sd->status.account_id; - WFIFOW(fd,6)=sd->bl.x; - WFIFOW(fd,8)=sd->bl.y; - WFIFOSET(fd,packet_len(0x107)); + WFIFOHEAD(fd,packet_len(0x107)); + WFIFOW(fd,0)=0x107; + WFIFOL(fd,2)=sd->status.account_id; + WFIFOW(fd,6)=sd->bl.x; + WFIFOW(fd,8)=sd->bl.y; + WFIFOSET(fd,packet_len(0x107)); } @@ -6479,30 +6543,30 @@ void clif_party_xy_single(int fd, struct map_session_data *sd) /// 080e <account id>.L <hp>.L <max hp>.L (ZC_NOTIFY_HP_TO_GROUPM_R2) void clif_party_hp(struct map_session_data *sd) { - unsigned char buf[16]; + unsigned char buf[16]; #if PACKETVER < 20100126 - const int cmd = 0x106; + const int cmd = 0x106; #else - const int cmd = 0x80e; + const int cmd = 0x80e; #endif - nullpo_retv(sd); + nullpo_retv(sd); - WBUFW(buf,0)=cmd; - WBUFL(buf,2)=sd->status.account_id; + WBUFW(buf,0)=cmd; + WBUFL(buf,2)=sd->status.account_id; #if PACKETVER < 20100126 - if (sd->battle_status.max_hp > INT16_MAX) { //To correctly display the %hp bar. [Skotlex] - WBUFW(buf,6) = sd->battle_status.hp/(sd->battle_status.max_hp/100); - WBUFW(buf,8) = 100; - } else { - WBUFW(buf,6) = sd->battle_status.hp; - WBUFW(buf,8) = sd->battle_status.max_hp; - } + if (sd->battle_status.max_hp > INT16_MAX) { //To correctly display the %hp bar. [Skotlex] + WBUFW(buf,6) = sd->battle_status.hp/(sd->battle_status.max_hp/100); + WBUFW(buf,8) = 100; + } else { + WBUFW(buf,6) = sd->battle_status.hp; + WBUFW(buf,8) = sd->battle_status.max_hp; + } #else - WBUFL(buf,6) = sd->battle_status.hp; - WBUFL(buf,10) = sd->battle_status.max_hp; + WBUFL(buf,6) = sd->battle_status.hp; + WBUFL(buf,10) = sd->battle_status.max_hp; #endif - clif_send(buf,packet_len(cmd),&sd->bl,PARTY_AREA_WOS); + clif_send(buf,packet_len(cmd),&sd->bl,PARTY_AREA_WOS); } @@ -6512,48 +6576,48 @@ void clif_party_hp(struct map_session_data *sd) void clif_hpmeter_single(int fd, int id, unsigned int hp, unsigned int maxhp) { #if PACKETVER < 20100126 - const int cmd = 0x106; + const int cmd = 0x106; #else - const int cmd = 0x80e; + const int cmd = 0x80e; #endif - WFIFOHEAD(fd,packet_len(cmd)); - WFIFOW(fd,0) = cmd; - WFIFOL(fd,2) = id; + WFIFOHEAD(fd,packet_len(cmd)); + WFIFOW(fd,0) = cmd; + WFIFOL(fd,2) = id; #if PACKETVER < 20100126 - if (maxhp > INT16_MAX) { - // To correctly display the %hp bar. [Skotlex] - WFIFOW(fd,6) = hp/(maxhp/100); - WFIFOW(fd,8) = 100; - } else { - WFIFOW(fd,6) = hp; - WFIFOW(fd,8) = maxhp; - } + if( maxhp > INT16_MAX ) + {// To correctly display the %hp bar. [Skotlex] + WFIFOW(fd,6) = hp/(maxhp/100); + WFIFOW(fd,8) = 100; + } else { + WFIFOW(fd,6) = hp; + WFIFOW(fd,8) = maxhp; + } #else - WFIFOL(fd,6) = hp; - WFIFOL(fd,10) = maxhp; + WFIFOL(fd,6) = hp; + WFIFOL(fd,10) = maxhp; #endif - WFIFOSET(fd, packet_len(cmd)); + WFIFOSET(fd, packet_len(cmd)); } /// Notifies the client, that it's attack target is too far (ZC_ATTACK_FAILURE_FOR_DISTANCE). /// 0139 <target id>.L <target x>.W <target y>.W <x>.W <y>.W <atk range>.W void clif_movetoattack(struct map_session_data *sd,struct block_list *bl) { - int fd; + int fd; - nullpo_retv(sd); - nullpo_retv(bl); + nullpo_retv(sd); + nullpo_retv(bl); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x139)); - WFIFOW(fd, 0)=0x139; - WFIFOL(fd, 2)=bl->id; - WFIFOW(fd, 6)=bl->x; - WFIFOW(fd, 8)=bl->y; - WFIFOW(fd,10)=sd->bl.x; - WFIFOW(fd,12)=sd->bl.y; - WFIFOW(fd,14)=sd->battle_status.rhw.range; - WFIFOSET(fd,packet_len(0x139)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x139)); + WFIFOW(fd, 0)=0x139; + WFIFOL(fd, 2)=bl->id; + WFIFOW(fd, 6)=bl->x; + WFIFOW(fd, 8)=bl->y; + WFIFOW(fd,10)=sd->bl.x; + WFIFOW(fd,12)=sd->bl.y; + WFIFOW(fd,14)=sd->battle_status.rhw.range; + WFIFOSET(fd,packet_len(0x139)); } @@ -6564,22 +6628,22 @@ void clif_movetoattack(struct map_session_data *sd,struct block_list *bl) /// 1 = failure /// 2 = success (alchemist) /// 3 = failure (alchemist) -void clif_produceeffect(struct map_session_data *sd,int flag,int nameid) +void clif_produceeffect(struct map_session_data* sd,int flag,int nameid) { - int view,fd; + int view,fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; - clif_solved_charname(fd, sd->status.char_id, sd->status.name); - WFIFOHEAD(fd,packet_len(0x18f)); - WFIFOW(fd, 0)=0x18f; - WFIFOW(fd, 2)=flag; - if ((view = itemdb_viewid(nameid)) > 0) - WFIFOW(fd, 4)=view; - else - WFIFOW(fd, 4)=nameid; - WFIFOSET(fd,packet_len(0x18f)); + fd = sd->fd; + clif_solved_charname(fd, sd->status.char_id, sd->status.name); + WFIFOHEAD(fd,packet_len(0x18f)); + WFIFOW(fd, 0)=0x18f; + WFIFOW(fd, 2)=flag; + if((view = itemdb_viewid(nameid)) > 0) + WFIFOW(fd, 4)=view; + else + WFIFOW(fd, 4)=nameid; + WFIFOSET(fd,packet_len(0x18f)); } @@ -6587,14 +6651,14 @@ void clif_produceeffect(struct map_session_data *sd,int flag,int nameid) /// 019e void clif_catch_process(struct map_session_data *sd) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x19e)); - WFIFOW(fd,0)=0x19e; - WFIFOSET(fd,packet_len(0x19e)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x19e)); + WFIFOW(fd,0)=0x19e; + WFIFOSET(fd,packet_len(0x19e)); } @@ -6604,15 +6668,15 @@ void clif_catch_process(struct map_session_data *sd) /// 1 = success void clif_pet_roulette(struct map_session_data *sd,int data) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x1a0)); - WFIFOW(fd,0)=0x1a0; - WFIFOB(fd,2)=data; - WFIFOSET(fd,packet_len(0x1a0)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x1a0)); + WFIFOW(fd,0)=0x1a0; + WFIFOB(fd,2)=data; + WFIFOSET(fd,packet_len(0x1a0)); } @@ -6620,31 +6684,31 @@ void clif_pet_roulette(struct map_session_data *sd,int data) /// 01a6 <packet len>.W { <index>.W }* void clif_sendegg(struct map_session_data *sd) { - int i,n=0,fd; + int i,n=0,fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - if (battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m)) { - //Disable pet hatching in GvG grounds during Guild Wars [Skotlex] - clif_displaymessage(fd, msg_txt(666)); - return; - } - WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4); - WFIFOW(fd,0)=0x1a6; - for (i=0,n=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid<=0 || sd->inventory_data[i] == NULL || - sd->inventory_data[i]->type!=IT_PETEGG || - sd->status.inventory[i].amount<=0) - continue; - WFIFOW(fd,n*2+4)=i+2; - n++; - } - WFIFOW(fd,2)=4+n*2; - WFIFOSET(fd,WFIFOW(fd,2)); + fd=sd->fd; + if (battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m)) + { //Disable pet hatching in GvG grounds during Guild Wars [Skotlex] + clif_displaymessage(fd, msg_txt(666)); + return; + } + WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4); + WFIFOW(fd,0)=0x1a6; + for(i=0,n=0;i<MAX_INVENTORY;i++){ + if(sd->status.inventory[i].nameid<=0 || sd->inventory_data[i] == NULL || + sd->inventory_data[i]->type!=IT_PETEGG || + sd->status.inventory[i].amount<=0) + continue; + WFIFOW(fd,n*2+4)=i+2; + n++; + } + WFIFOW(fd,2)=4+n*2; + WFIFOSET(fd,WFIFOW(fd,2)); - sd->menuskill_id = SA_TAMINGMONSTER; - sd->menuskill_val = -1; + sd->menuskill_id = SA_TAMINGMONSTER; + sd->menuskill_val = -1; } @@ -6659,19 +6723,19 @@ void clif_sendegg(struct map_session_data *sd) /// 5 = hairstyle /// /// If sd is null, the update is sent to nearby objects, otherwise it is sent only to that player. -void clif_send_petdata(struct map_session_data *sd, struct pet_data *pd, int type, int param) +void clif_send_petdata(struct map_session_data* sd, struct pet_data* pd, int type, int param) { - uint8 buf[16]; - nullpo_retv(pd); + uint8 buf[16]; + nullpo_retv(pd); - WBUFW(buf,0) = 0x1a4; - WBUFB(buf,2) = type; - WBUFL(buf,3) = pd->bl.id; - WBUFL(buf,7) = param; - if (sd) - clif_send(buf, packet_len(0x1a4), &sd->bl, SELF); - else - clif_send(buf, packet_len(0x1a4), &pd->bl, AREA); + WBUFW(buf,0) = 0x1a4; + WBUFB(buf,2) = type; + WBUFL(buf,3) = pd->bl.id; + WBUFL(buf,7) = param; + if (sd) + clif_send(buf, packet_len(0x1a4), &sd->bl, SELF); + else + clif_send(buf, packet_len(0x1a4), &pd->bl, AREA); } @@ -6679,26 +6743,26 @@ void clif_send_petdata(struct map_session_data *sd, struct pet_data *pd, int typ /// 01a2 <name>.24B <renamed>.B <level>.W <hunger>.W <intimacy>.W <accessory id>.W <class>.W void clif_send_petstatus(struct map_session_data *sd) { - int fd; - struct s_pet *pet; - - nullpo_retv(sd); - nullpo_retv(sd->pd); - - fd=sd->fd; - pet = &sd->pd->pet; - WFIFOHEAD(fd,packet_len(0x1a2)); - WFIFOW(fd,0)=0x1a2; - memcpy(WFIFOP(fd,2),pet->name,NAME_LENGTH); - WFIFOB(fd,26)=battle_config.pet_rename?0:pet->rename_flag; - WFIFOW(fd,27)=pet->level; - WFIFOW(fd,29)=pet->hungry; - WFIFOW(fd,31)=pet->intimate; - WFIFOW(fd,33)=pet->equip; + int fd; + struct s_pet *pet; + + nullpo_retv(sd); + nullpo_retv(sd->pd); + + fd=sd->fd; + pet = &sd->pd->pet; + WFIFOHEAD(fd,packet_len(0x1a2)); + WFIFOW(fd,0)=0x1a2; + memcpy(WFIFOP(fd,2),pet->name,NAME_LENGTH); + WFIFOB(fd,26)=battle_config.pet_rename?0:pet->rename_flag; + WFIFOW(fd,27)=pet->level; + WFIFOW(fd,29)=pet->hungry; + WFIFOW(fd,31)=pet->intimate; + WFIFOW(fd,33)=pet->equip; #if PACKETVER >= 20081126 - WFIFOW(fd,35)=pet->class_; + WFIFOW(fd,35)=pet->class_; #endif - WFIFOSET(fd,packet_len(0x1a2)); + WFIFOSET(fd,packet_len(0x1a2)); } @@ -6708,26 +6772,26 @@ void clif_send_petstatus(struct map_session_data *sd) /// @see CZ_PET_ACT. void clif_pet_emotion(struct pet_data *pd,int param) { - unsigned char buf[16]; + unsigned char buf[16]; - nullpo_retv(pd); + nullpo_retv(pd); - memset(buf,0,packet_len(0x1aa)); + memset(buf,0,packet_len(0x1aa)); - WBUFW(buf,0)=0x1aa; - WBUFL(buf,2)=pd->bl.id; - if (param >= 100 && pd->petDB->talk_convert_class) { - if (pd->petDB->talk_convert_class < 0) - return; - else if (pd->petDB->talk_convert_class > 0) { - // replace mob_id component of talk/act data - param -= (pd->pet.class_ - 100)*100; - param += (pd->petDB->talk_convert_class - 100)*100; - } - } - WBUFL(buf,6)=param; + WBUFW(buf,0)=0x1aa; + WBUFL(buf,2)=pd->bl.id; + if(param >= 100 && pd->petDB->talk_convert_class) { + if(pd->petDB->talk_convert_class < 0) + return; + else if(pd->petDB->talk_convert_class > 0) { + // replace mob_id component of talk/act data + param -= (pd->pet.class_ - 100)*100; + param += (pd->petDB->talk_convert_class - 100)*100; + } + } + WBUFL(buf,6)=param; - clif_send(buf,packet_len(0x1aa),&pd->bl,AREA); + clif_send(buf,packet_len(0x1aa),&pd->bl,AREA); } @@ -6738,16 +6802,16 @@ void clif_pet_emotion(struct pet_data *pd,int param) /// 1 = success void clif_pet_food(struct map_session_data *sd,int foodid,int fail) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x1a3)); - WFIFOW(fd,0)=0x1a3; - WFIFOB(fd,2)=fail; - WFIFOW(fd,3)=foodid; - WFIFOSET(fd,packet_len(0x1a3)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x1a3)); + WFIFOW(fd,0)=0x1a3; + WFIFOB(fd,2)=fail; + WFIFOW(fd,3)=foodid; + WFIFOSET(fd,packet_len(0x1a3)); } @@ -6755,46 +6819,46 @@ void clif_pet_food(struct map_session_data *sd,int foodid,int fail) /// 01cd { <skill id>.L }*7 void clif_autospell(struct map_session_data *sd,int skilllv) { - int fd; - - nullpo_retv(sd); - - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x1cd)); - WFIFOW(fd, 0)=0x1cd; - - if (skilllv>0 && pc_checkskill(sd,MG_NAPALMBEAT)>0) - WFIFOL(fd,2)= MG_NAPALMBEAT; - else - WFIFOL(fd,2)= 0x00000000; - if (skilllv>1 && pc_checkskill(sd,MG_COLDBOLT)>0) - WFIFOL(fd,6)= MG_COLDBOLT; - else - WFIFOL(fd,6)= 0x00000000; - if (skilllv>1 && pc_checkskill(sd,MG_FIREBOLT)>0) - WFIFOL(fd,10)= MG_FIREBOLT; - else - WFIFOL(fd,10)= 0x00000000; - if (skilllv>1 && pc_checkskill(sd,MG_LIGHTNINGBOLT)>0) - WFIFOL(fd,14)= MG_LIGHTNINGBOLT; - else - WFIFOL(fd,14)= 0x00000000; - if (skilllv>4 && pc_checkskill(sd,MG_SOULSTRIKE)>0) - WFIFOL(fd,18)= MG_SOULSTRIKE; - else - WFIFOL(fd,18)= 0x00000000; - if (skilllv>7 && pc_checkskill(sd,MG_FIREBALL)>0) - WFIFOL(fd,22)= MG_FIREBALL; - else - WFIFOL(fd,22)= 0x00000000; - if (skilllv>9 && pc_checkskill(sd,MG_FROSTDIVER)>0) - WFIFOL(fd,26)= MG_FROSTDIVER; - else - WFIFOL(fd,26)= 0x00000000; - - WFIFOSET(fd,packet_len(0x1cd)); - sd->menuskill_id = SA_AUTOSPELL; - sd->menuskill_val = skilllv; + int fd; + + nullpo_retv(sd); + + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x1cd)); + WFIFOW(fd, 0)=0x1cd; + + if(skilllv>0 && pc_checkskill(sd,MG_NAPALMBEAT)>0) + WFIFOL(fd,2)= MG_NAPALMBEAT; + else + WFIFOL(fd,2)= 0x00000000; + if(skilllv>1 && pc_checkskill(sd,MG_COLDBOLT)>0) + WFIFOL(fd,6)= MG_COLDBOLT; + else + WFIFOL(fd,6)= 0x00000000; + if(skilllv>1 && pc_checkskill(sd,MG_FIREBOLT)>0) + WFIFOL(fd,10)= MG_FIREBOLT; + else + WFIFOL(fd,10)= 0x00000000; + if(skilllv>1 && pc_checkskill(sd,MG_LIGHTNINGBOLT)>0) + WFIFOL(fd,14)= MG_LIGHTNINGBOLT; + else + WFIFOL(fd,14)= 0x00000000; + if(skilllv>4 && pc_checkskill(sd,MG_SOULSTRIKE)>0) + WFIFOL(fd,18)= MG_SOULSTRIKE; + else + WFIFOL(fd,18)= 0x00000000; + if(skilllv>7 && pc_checkskill(sd,MG_FIREBALL)>0) + WFIFOL(fd,22)= MG_FIREBALL; + else + WFIFOL(fd,22)= 0x00000000; + if(skilllv>9 && pc_checkskill(sd,MG_FROSTDIVER)>0) + WFIFOL(fd,26)= MG_FROSTDIVER; + else + WFIFOL(fd,26)= 0x00000000; + + WFIFOSET(fd,packet_len(0x1cd)); + sd->menuskill_id = SA_AUTOSPELL; + sd->menuskill_val = skilllv; } @@ -6802,34 +6866,37 @@ void clif_autospell(struct map_session_data *sd,int skilllv) /// 01cf <devoter id>.L { <devotee id>.L }*5 <max distance>.W void clif_devotion(struct block_list *src, struct map_session_data *tsd) { - unsigned char buf[56]; - int i; + unsigned char buf[56]; + int i; - nullpo_retv(src); - memset(buf,0,packet_len(0x1cf)); + nullpo_retv(src); + memset(buf,0,packet_len(0x1cf)); - WBUFW(buf,0) = 0x1cf; - WBUFL(buf,2) = src->id; - if (src->type == BL_MER) { - struct mercenary_data *md = BL_CAST(BL_MER,src); - if (md && md->master && md->devotion_flag) - WBUFL(buf,6) = md->master->bl.id; + WBUFW(buf,0) = 0x1cf; + WBUFL(buf,2) = src->id; + if( src->type == BL_MER ) + { + struct mercenary_data *md = BL_CAST(BL_MER,src); + if( md && md->master && md->devotion_flag ) + WBUFL(buf,6) = md->master->bl.id; - WBUFW(buf,26) = skill_get_range2(src, ML_DEVOTION, mercenary_checkskill(md, ML_DEVOTION)); - } else { - struct map_session_data *sd = BL_CAST(BL_PC,src); - if (sd == NULL) - return; + WBUFW(buf,26) = skill_get_range2(src, ML_DEVOTION, mercenary_checkskill(md, ML_DEVOTION)); + } + else + { + struct map_session_data *sd = BL_CAST(BL_PC,src); + if( sd == NULL ) + return; - for (i = 0; i < 5; i++) - WBUFL(buf,6+4*i) = sd->devotion[i]; - WBUFW(buf,26) = skill_get_range2(src, CR_DEVOTION, pc_checkskill(sd, CR_DEVOTION)); - } + for( i = 0; i < 5; i++ ) + WBUFL(buf,6+4*i) = sd->devotion[i]; + WBUFW(buf,26) = skill_get_range2(src, CR_DEVOTION, pc_checkskill(sd, CR_DEVOTION)); + } - if (tsd) - clif_send(buf, packet_len(0x1cf), &tsd->bl, SELF); - else - clif_send(buf, packet_len(0x1cf), src, AREA); + if( tsd ) + clif_send(buf, packet_len(0x1cf), &tsd->bl, SELF); + else + clif_send(buf, packet_len(0x1cf), src, AREA); } /*========================================== @@ -6838,8 +6905,7 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd) * 01d0 <id>.L <amount>.W (ZC_SPIRITS) * 01e1 <id>.L <amount>.W (ZC_SPIRITS2) *------------------------------------------*/ -void clif_spiritball(struct block_list *bl) -{ +void clif_spiritball(struct block_list *bl) { unsigned char buf[16]; TBL_PC *sd = BL_CAST(BL_PC,bl); TBL_HOM *hd = BL_CAST(BL_HOM,bl); @@ -6848,14 +6914,10 @@ void clif_spiritball(struct block_list *bl) WBUFW(buf, 0) = 0x1d0; WBUFL(buf, 2) = bl->id; - WBUFW(buf, 6) = 0; //init to 0 - switch (bl->type) { - case BL_PC: - WBUFW(buf, 6) = sd->spiritball; - break; - case BL_HOM: - WBUFW(buf, 6) = hd->spiritball; - break; + WBUFW(buf, 6) = 0; //init to 0 + switch(bl->type){ + case BL_PC: WBUFW(buf, 6) = sd->spiritball; break; + case BL_HOM: WBUFW(buf, 6) = hd->spiritball; break; } clif_send(buf, packet_len(0x1d0), bl, AREA); } @@ -6865,14 +6927,14 @@ void clif_spiritball(struct block_list *bl) /// 01d2 <account id>.L <delay>.L void clif_combo_delay(struct block_list *bl,int wait) { - unsigned char buf[32]; + unsigned char buf[32]; - nullpo_retv(bl); + nullpo_retv(bl); - WBUFW(buf,0)=0x1d2; - WBUFL(buf,2)=bl->id; - WBUFL(buf,6)=wait; - clif_send(buf,packet_len(0x1d2),bl,AREA); + WBUFW(buf,0)=0x1d2; + WBUFL(buf,2)=bl->id; + WBUFL(buf,6)=wait; + clif_send(buf,packet_len(0x1d2),bl,AREA); } @@ -6883,16 +6945,16 @@ void clif_combo_delay(struct block_list *bl,int wait) /// 1 = active void clif_bladestop(struct block_list *src, int dst_id, int active) { - unsigned char buf[32]; + unsigned char buf[32]; - nullpo_retv(src); + nullpo_retv(src); - WBUFW(buf,0)=0x1d1; - WBUFL(buf,2)=src->id; - WBUFL(buf,6)=dst_id; - WBUFL(buf,10)=active; + WBUFW(buf,0)=0x1d1; + WBUFL(buf,2)=src->id; + WBUFL(buf,6)=dst_id; + WBUFL(buf,10)=active; - clif_send(buf,packet_len(0x1d1),src,AREA); + clif_send(buf,packet_len(0x1d1),src,AREA); } @@ -6900,13 +6962,13 @@ void clif_bladestop(struct block_list *src, int dst_id, int active) /// 010c <account id>.L void clif_mvp_effect(struct map_session_data *sd) { - unsigned char buf[16]; + unsigned char buf[16]; - nullpo_retv(sd); + nullpo_retv(sd); - WBUFW(buf,0)=0x10c; - WBUFL(buf,2)=sd->bl.id; - clif_send(buf,packet_len(0x10c),&sd->bl,AREA); + WBUFW(buf,0)=0x10c; + WBUFL(buf,2)=sd->bl.id; + clif_send(buf,packet_len(0x10c),&sd->bl,AREA); } @@ -6914,18 +6976,18 @@ void clif_mvp_effect(struct map_session_data *sd) /// 010a <name id>.W void clif_mvp_item(struct map_session_data *sd,int nameid) { - int view,fd; + int view,fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x10a)); - WFIFOW(fd,0)=0x10a; - if ((view = itemdb_viewid(nameid)) > 0) - WFIFOW(fd,2)=view; - else - WFIFOW(fd,2)=nameid; - WFIFOSET(fd,packet_len(0x10a)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x10a)); + WFIFOW(fd,0)=0x10a; + if((view = itemdb_viewid(nameid)) > 0) + WFIFOW(fd,2)=view; + else + WFIFOW(fd,2)=nameid; + WFIFOSET(fd,packet_len(0x10a)); } @@ -6933,15 +6995,15 @@ void clif_mvp_item(struct map_session_data *sd,int nameid) /// 010b <exp>.L void clif_mvp_exp(struct map_session_data *sd, unsigned int exp) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x10b)); - WFIFOW(fd,0)=0x10b; - WFIFOL(fd,2)=cap_value(exp,0,INT32_MAX); - WFIFOSET(fd,packet_len(0x10b)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x10b)); + WFIFOW(fd,0)=0x10b; + WFIFOL(fd,2)=cap_value(exp,0,INT32_MAX); + WFIFOSET(fd,packet_len(0x10b)); } @@ -6950,13 +7012,13 @@ void clif_mvp_exp(struct map_session_data *sd, unsigned int exp) /// /// "You are the MVP, but cannot obtain the reward because /// you are overweight." -void clif_mvp_noitem(struct map_session_data *sd) +void clif_mvp_noitem(struct map_session_data* sd) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x10d)); - WFIFOW(fd,0) = 0x10d; - WFIFOSET(fd,packet_len(0x10d)); + WFIFOHEAD(fd,packet_len(0x10d)); + WFIFOW(fd,0) = 0x10d; + WFIFOSET(fd,packet_len(0x10d)); } @@ -6969,15 +7031,15 @@ void clif_mvp_noitem(struct map_session_data *sd) /// 3 = "You need the neccessary item to create a Guild." void clif_guild_created(struct map_session_data *sd,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x167)); - WFIFOW(fd,0)=0x167; - WFIFOB(fd,2)=flag; - WFIFOSET(fd,packet_len(0x167)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x167)); + WFIFOW(fd,0)=0x167; + WFIFOB(fd,2)=flag; + WFIFOSET(fd,packet_len(0x167)); } @@ -6988,21 +7050,21 @@ void clif_guild_created(struct map_session_data *sd,int flag) /// &0x10 = allow expel void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g) { - int ps,fd; - nullpo_retv(sd); - nullpo_retv(g); + int ps,fd; + nullpo_retv(sd); + nullpo_retv(g); - fd=sd->fd; - ps=guild_getposition(g,sd); - WFIFOHEAD(fd,packet_len(0x16c)); - WFIFOW(fd,0)=0x16c; - WFIFOL(fd,2)=g->guild_id; - WFIFOL(fd,6)=g->emblem_id; - WFIFOL(fd,10)=g->position[ps].mode; - WFIFOB(fd,14)=(bool)(sd->state.gmaster_flag==g); - WFIFOL(fd,15)=0; // InterSID (unknown purpose) - memcpy(WFIFOP(fd,19),g->name,NAME_LENGTH); - WFIFOSET(fd,packet_len(0x16c)); + fd=sd->fd; + ps=guild_getposition(g,sd); + WFIFOHEAD(fd,packet_len(0x16c)); + WFIFOW(fd,0)=0x16c; + WFIFOL(fd,2)=g->guild_id; + WFIFOL(fd,6)=g->emblem_id; + WFIFOL(fd,10)=g->position[ps].mode; + WFIFOB(fd,14)=(bool)(sd->state.gmaster_flag==g); + WFIFOL(fd,15)=0; // InterSID (unknown purpose) + memcpy(WFIFOP(fd,19),g->name,NAME_LENGTH); + WFIFOSET(fd,packet_len(0x16c)); } @@ -7014,27 +7076,30 @@ void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g) /// 1 = online void clif_guild_memberlogin_notice(struct guild *g,int idx,int flag) { - unsigned char buf[64]; - struct map_session_data *sd; - - nullpo_retv(g); - - WBUFW(buf, 0)=0x1f2; - WBUFL(buf, 2)=g->member[idx].account_id; - WBUFL(buf, 6)=g->member[idx].char_id; - WBUFL(buf,10)=flag; - - if ((sd = g->member[idx].sd) != NULL) { - WBUFW(buf,14) = sd->status.sex; - WBUFW(buf,16) = sd->status.hair; - WBUFW(buf,18) = sd->status.hair_color; - clif_send(buf,packet_len(0x1f2),&sd->bl,GUILD_WOS); - } else if ((sd = guild_getavailablesd(g)) != NULL) { - WBUFW(buf,14) = 0; - WBUFW(buf,16) = 0; - WBUFW(buf,18) = 0; - clif_send(buf,packet_len(0x1f2),&sd->bl,GUILD); - } + unsigned char buf[64]; + struct map_session_data* sd; + + nullpo_retv(g); + + WBUFW(buf, 0)=0x1f2; + WBUFL(buf, 2)=g->member[idx].account_id; + WBUFL(buf, 6)=g->member[idx].char_id; + WBUFL(buf,10)=flag; + + if( ( sd = g->member[idx].sd ) != NULL ) + { + WBUFW(buf,14) = sd->status.sex; + WBUFW(buf,16) = sd->status.hair; + WBUFW(buf,18) = sd->status.hair_color; + clif_send(buf,packet_len(0x1f2),&sd->bl,GUILD_WOS); + } + else if( ( sd = guild_getavailablesd(g) ) != NULL ) + { + WBUFW(buf,14) = 0; + WBUFW(buf,16) = 0; + WBUFW(buf,18) = 0; + clif_send(buf,packet_len(0x1f2),&sd->bl,GUILD); + } } // Function `clif_guild_memberlogin_notice` sends info about @@ -7048,31 +7113,31 @@ void clif_guild_memberlogin_notice(struct guild *g,int idx,int flag) // to economize traffic. [LuzZza] void clif_guild_send_onlineinfo(struct map_session_data *sd) { - struct guild *g; - unsigned char buf[14*128]; - int i, count=0, p_len; + struct guild *g; + unsigned char buf[14*128]; + int i, count=0, p_len; - nullpo_retv(sd); + nullpo_retv(sd); - p_len = packet_len(0x16d); + p_len = packet_len(0x16d); - if (!(g = guild_search(sd->status.guild_id))) - return; + if(!(g = guild_search(sd->status.guild_id))) + return; - for (i=0; i<g->max_member; i++) { + for(i=0; i<g->max_member; i++) { - if (g->member[i].account_id > 0 && - g->member[i].account_id != sd->status.account_id) { + if(g->member[i].account_id > 0 && + g->member[i].account_id != sd->status.account_id) { - WBUFW(buf,count*p_len) = 0x16d; - WBUFL(buf,count*p_len+2) = g->member[i].account_id; - WBUFL(buf,count*p_len+6) = g->member[i].char_id; - WBUFL(buf,count*p_len+10) = g->member[i].online; - count++; - } - } + WBUFW(buf,count*p_len) = 0x16d; + WBUFL(buf,count*p_len+2) = g->member[i].account_id; + WBUFL(buf,count*p_len+6) = g->member[i].char_id; + WBUFL(buf,count*p_len+10) = g->member[i].online; + count++; + } + } - clif_send(buf, p_len*count, &sd->bl, SELF); + clif_send(buf, p_len*count, &sd->bl, SELF); } @@ -7088,52 +7153,51 @@ void clif_guild_send_onlineinfo(struct map_session_data *sd) /// &0x80 = Notice void clif_guild_masterormember(struct map_session_data *sd) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x14e)); - WFIFOW(fd,0) = 0x14e; - WFIFOL(fd,2) = (sd->state.gmaster_flag) ? 0xd7 : 0x57; - WFIFOSET(fd,packet_len(0x14e)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x14e)); + WFIFOW(fd,0) = 0x14e; + WFIFOL(fd,2) = (sd->state.gmaster_flag) ? 0xd7 : 0x57; + WFIFOSET(fd,packet_len(0x14e)); } /// Guild basic information (Territories [Valaris]) /// 0150 <guild id>.L <level>.L <member num>.L <member max>.L <exp>.L <max exp>.L <points>.L <honor>.L <virtue>.L <emblem id>.L <name>.24B <master name>.24B <manage land>.16B (ZC_GUILD_INFO) /// 01b6 <guild id>.L <level>.L <member num>.L <member max>.L <exp>.L <max exp>.L <points>.L <honor>.L <virtue>.L <emblem id>.L <name>.24B <master name>.24B <manage land>.16B <zeny>.L (ZC_GUILD_INFO2) -void clif_guild_basicinfo(struct map_session_data *sd) -{ - int fd; - struct guild *g; +void clif_guild_basicinfo(struct map_session_data *sd) { + int fd; + struct guild *g; - nullpo_retv(sd); - fd = sd->fd; + nullpo_retv(sd); + fd = sd->fd; - if ((g = guild_search(sd->status.guild_id)) == NULL) - return; + if( (g = guild_search(sd->status.guild_id)) == NULL ) + return; - WFIFOHEAD(fd,packet_len(0x1b6)); - WFIFOW(fd, 0)=0x1b6;//0x150; - WFIFOL(fd, 2)=g->guild_id; - WFIFOL(fd, 6)=g->guild_lv; - WFIFOL(fd,10)=g->connect_member; - WFIFOL(fd,14)=g->max_member; - WFIFOL(fd,18)=g->average_lv; - WFIFOL(fd,22)=(uint32)cap_value(g->exp,0,INT32_MAX); - WFIFOL(fd,26)=g->next_exp; - WFIFOL(fd,30)=0; // Tax Points - WFIFOL(fd,34)=0; // Honor: (left) Vulgar [-100,100] Famed (right) - WFIFOL(fd,38)=0; // Virtue: (down) Wicked [-100,100] Righteous (up) - WFIFOL(fd,42)=g->emblem_id; - memcpy(WFIFOP(fd,46),g->name, NAME_LENGTH); - memcpy(WFIFOP(fd,70),g->master, NAME_LENGTH); + WFIFOHEAD(fd,packet_len(0x1b6)); + WFIFOW(fd, 0)=0x1b6;//0x150; + WFIFOL(fd, 2)=g->guild_id; + WFIFOL(fd, 6)=g->guild_lv; + WFIFOL(fd,10)=g->connect_member; + WFIFOL(fd,14)=g->max_member; + WFIFOL(fd,18)=g->average_lv; + WFIFOL(fd,22)=(uint32)cap_value(g->exp,0,INT32_MAX); + WFIFOL(fd,26)=g->next_exp; + WFIFOL(fd,30)=0; // Tax Points + WFIFOL(fd,34)=0; // Honor: (left) Vulgar [-100,100] Famed (right) + WFIFOL(fd,38)=0; // Virtue: (down) Wicked [-100,100] Righteous (up) + WFIFOL(fd,42)=g->emblem_id; + memcpy(WFIFOP(fd,46),g->name, NAME_LENGTH); + memcpy(WFIFOP(fd,70),g->master, NAME_LENGTH); - safestrncpy((char *)WFIFOP(fd,94),msg_txt(300+guild_checkcastles(g)),16); // "'N' castles" - WFIFOL(fd,110) = 0; // zeny + safestrncpy((char*)WFIFOP(fd,94),msg_txt(300+guild_checkcastles(g)),16); // "'N' castles" + WFIFOL(fd,110) = 0; // zeny - WFIFOSET(fd,packet_len(0x1b6)); + WFIFOSET(fd,packet_len(0x1b6)); } @@ -7141,27 +7205,27 @@ void clif_guild_basicinfo(struct map_session_data *sd) /// 014c <packet len>.W { <relation>.L <guild id>.L <guild name>.24B }* void clif_guild_allianceinfo(struct map_session_data *sd) { - int fd,i,c; - struct guild *g; + int fd,i,c; + struct guild *g; - nullpo_retv(sd); - if ((g = guild_search(sd->status.guild_id)) == NULL) - return; - - fd = sd->fd; - WFIFOHEAD(fd, MAX_GUILDALLIANCE * 32 + 4); - WFIFOW(fd, 0)=0x14c; - for (i=c=0; i<MAX_GUILDALLIANCE; i++) { - struct guild_alliance *a=&g->alliance[i]; - if (a->guild_id>0) { - WFIFOL(fd,c*32+4)=a->opposition; - WFIFOL(fd,c*32+8)=a->guild_id; - memcpy(WFIFOP(fd,c*32+12),a->name,NAME_LENGTH); - c++; - } - } - WFIFOW(fd, 2)=c*32+4; - WFIFOSET(fd,WFIFOW(fd,2)); + nullpo_retv(sd); + if( (g = guild_search(sd->status.guild_id)) == NULL ) + return; + + fd = sd->fd; + WFIFOHEAD(fd, MAX_GUILDALLIANCE * 32 + 4); + WFIFOW(fd, 0)=0x14c; + for(i=c=0;i<MAX_GUILDALLIANCE;i++){ + struct guild_alliance *a=&g->alliance[i]; + if(a->guild_id>0){ + WFIFOL(fd,c*32+4)=a->opposition; + WFIFOL(fd,c*32+8)=a->guild_id; + memcpy(WFIFOP(fd,c*32+12),a->name,NAME_LENGTH); + c++; + } + } + WFIFOW(fd, 2)=c*32+4; + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -7174,38 +7238,38 @@ void clif_guild_allianceinfo(struct map_session_data *sd) /// probably member's self-introduction (unused, no client UI/packets for editing it) void clif_guild_memberlist(struct map_session_data *sd) { - int fd; - int i,c; - struct guild *g; - nullpo_retv(sd); - - if ((fd = sd->fd) == 0) - return; - if ((g = guild_search(sd->status.guild_id)) == NULL) - return; - - WFIFOHEAD(fd, g->max_member * 104 + 4); - WFIFOW(fd, 0)=0x154; - for (i=0,c=0; i<g->max_member; i++) { - struct guild_member *m=&g->member[i]; - if (m->account_id==0) - continue; - WFIFOL(fd,c*104+ 4)=m->account_id; - WFIFOL(fd,c*104+ 8)=m->char_id; - 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+20)=m->lv; - WFIFOL(fd,c*104+22)=(int)cap_value(m->exp,0,INT32_MAX); - WFIFOL(fd,c*104+26)=m->online; - WFIFOL(fd,c*104+30)=m->position; - memset(WFIFOP(fd,c*104+34),0,50); //[Ind] - This is displayed in the 'note' column but being you can't edit it it's sent empty. - memcpy(WFIFOP(fd,c*104+84),m->name,NAME_LENGTH); - c++; - } - WFIFOW(fd, 2)=c*104+4; - WFIFOSET(fd,WFIFOW(fd,2)); + int fd; + int i,c; + struct guild *g; + nullpo_retv(sd); + + if( (fd = sd->fd) == 0 ) + return; + if( (g = guild_search(sd->status.guild_id)) == NULL ) + return; + + WFIFOHEAD(fd, g->max_member * 104 + 4); + WFIFOW(fd, 0)=0x154; + for(i=0,c=0;i<g->max_member;i++){ + struct guild_member *m=&g->member[i]; + if(m->account_id==0) + continue; + WFIFOL(fd,c*104+ 4)=m->account_id; + WFIFOL(fd,c*104+ 8)=m->char_id; + 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+20)=m->lv; + WFIFOL(fd,c*104+22)=(int)cap_value(m->exp,0,INT32_MAX); + WFIFOL(fd,c*104+26)=m->online; + WFIFOL(fd,c*104+30)=m->position; + memset(WFIFOP(fd,c*104+34),0,50); //[Ind] - This is displayed in the 'note' column but being you can't edit it it's sent empty. + memcpy(WFIFOP(fd,c*104+84),m->name,NAME_LENGTH); + c++; + } + WFIFOW(fd, 2)=c*104+4; + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -7213,22 +7277,22 @@ void clif_guild_memberlist(struct map_session_data *sd) /// 0166 <packet len>.W { <position id>.L <position name>.24B }* void clif_guild_positionnamelist(struct map_session_data *sd) { - int i,fd; - struct guild *g; + int i,fd; + struct guild *g; - nullpo_retv(sd); - if ((g = guild_search(sd->status.guild_id)) == NULL) - return; - - fd = sd->fd; - WFIFOHEAD(fd, MAX_GUILDPOSITION * 28 + 4); - WFIFOW(fd, 0)=0x166; - for (i=0; i<MAX_GUILDPOSITION; i++) { - WFIFOL(fd,i*28+4)=i; - memcpy(WFIFOP(fd,i*28+8),g->position[i].name,NAME_LENGTH); - } - WFIFOW(fd,2)=i*28+4; - WFIFOSET(fd,WFIFOW(fd,2)); + nullpo_retv(sd); + if( (g = guild_search(sd->status.guild_id)) == NULL ) + return; + + fd = sd->fd; + WFIFOHEAD(fd, MAX_GUILDPOSITION * 28 + 4); + WFIFOW(fd, 0)=0x166; + for(i=0;i<MAX_GUILDPOSITION;i++){ + WFIFOL(fd,i*28+4)=i; + memcpy(WFIFOP(fd,i*28+8),g->position[i].name,NAME_LENGTH); + } + WFIFOW(fd,2)=i*28+4; + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -7241,25 +7305,25 @@ void clif_guild_positionnamelist(struct map_session_data *sd) /// TODO void clif_guild_positioninfolist(struct map_session_data *sd) { - int i,fd; - struct guild *g; + int i,fd; + struct guild *g; - nullpo_retv(sd); - if ((g = guild_search(sd->status.guild_id)) == NULL) - return; - - fd = sd->fd; - WFIFOHEAD(fd, MAX_GUILDPOSITION * 16 + 4); - WFIFOW(fd, 0)=0x160; - for (i=0; i<MAX_GUILDPOSITION; i++) { - struct guild_position *p=&g->position[i]; - WFIFOL(fd,i*16+ 4)=i; - WFIFOL(fd,i*16+ 8)=p->mode; - WFIFOL(fd,i*16+12)=i; - WFIFOL(fd,i*16+16)=p->exp_mode; - } - WFIFOW(fd, 2)=i*16+4; - WFIFOSET(fd,WFIFOW(fd,2)); + nullpo_retv(sd); + if( (g = guild_search(sd->status.guild_id)) == NULL ) + return; + + fd = sd->fd; + WFIFOHEAD(fd, MAX_GUILDPOSITION * 16 + 4); + WFIFOW(fd, 0)=0x160; + for(i=0;i<MAX_GUILDPOSITION;i++){ + struct guild_position *p=&g->position[i]; + WFIFOL(fd,i*16+ 4)=i; + WFIFOL(fd,i*16+ 8)=p->mode; + WFIFOL(fd,i*16+12)=i; + WFIFOL(fd,i*16+16)=p->exp_mode; + } + WFIFOW(fd, 2)=i*16+4; + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -7272,25 +7336,25 @@ void clif_guild_positioninfolist(struct map_session_data *sd) /// TODO void clif_guild_positionchanged(struct guild *g,int idx) { - // FIXME: This packet is intended to update the clients after a - // commit of position info changes, not sending one packet per - // position. - struct map_session_data *sd; - unsigned char buf[128]; + // FIXME: This packet is intended to update the clients after a + // commit of position info changes, not sending one packet per + // position. + struct map_session_data *sd; + unsigned char buf[128]; - nullpo_retv(g); + nullpo_retv(g); - WBUFW(buf, 0)=0x174; - WBUFW(buf, 2)=44; // packet len - // GUILD_REG_POSITION_INFO{ - WBUFL(buf, 4)=idx; - WBUFL(buf, 8)=g->position[idx].mode; - WBUFL(buf,12)=idx; - WBUFL(buf,16)=g->position[idx].exp_mode; - memcpy(WBUFP(buf,20),g->position[idx].name,NAME_LENGTH); - // }* - if ((sd=guild_getavailablesd(g))!=NULL) - clif_send(buf,WBUFW(buf,2),&sd->bl,GUILD); + WBUFW(buf, 0)=0x174; + WBUFW(buf, 2)=44; // packet len + // GUILD_REG_POSITION_INFO{ + WBUFL(buf, 4)=idx; + WBUFL(buf, 8)=g->position[idx].mode; + WBUFL(buf,12)=idx; + WBUFL(buf,16)=g->position[idx].exp_mode; + memcpy(WBUFP(buf,20),g->position[idx].name,NAME_LENGTH); + // }* + if( (sd=guild_getavailablesd(g))!=NULL ) + clif_send(buf,WBUFW(buf,2),&sd->bl,GUILD); } @@ -7298,23 +7362,23 @@ void clif_guild_positionchanged(struct guild *g,int idx) /// 0156 <packet len>.W { <account id>.L <char id>.L <position id>.L }* void clif_guild_memberpositionchanged(struct guild *g,int idx) { - // FIXME: This packet is intended to update the clients after a - // commit of member position assignment changes, not sending one - // packet per position. - struct map_session_data *sd; - unsigned char buf[64]; + // FIXME: This packet is intended to update the clients after a + // commit of member position assignment changes, not sending one + // packet per position. + struct map_session_data *sd; + unsigned char buf[64]; - nullpo_retv(g); + nullpo_retv(g); - WBUFW(buf, 0)=0x156; - WBUFW(buf, 2)=16; // packet len - // MEMBER_POSITION_INFO{ - WBUFL(buf, 4)=g->member[idx].account_id; - WBUFL(buf, 8)=g->member[idx].char_id; - WBUFL(buf,12)=g->member[idx].position; - // }* - if ((sd=guild_getavailablesd(g))!=NULL) - clif_send(buf,WBUFW(buf,2),&sd->bl,GUILD); + WBUFW(buf, 0)=0x156; + WBUFW(buf, 2)=16; // packet len + // MEMBER_POSITION_INFO{ + WBUFL(buf, 4)=g->member[idx].account_id; + WBUFL(buf, 8)=g->member[idx].char_id; + WBUFL(buf,12)=g->member[idx].position; + // }* + if( (sd=guild_getavailablesd(g))!=NULL ) + clif_send(buf,WBUFW(buf,2),&sd->bl,GUILD); } @@ -7322,99 +7386,101 @@ void clif_guild_memberpositionchanged(struct guild *g,int idx) /// 0152 <packet len>.W <guild id>.L <emblem id>.L <emblem data>.?B void clif_guild_emblem(struct map_session_data *sd,struct guild *g) { - int fd; - nullpo_retv(sd); - nullpo_retv(g); + int fd; + nullpo_retv(sd); + nullpo_retv(g); - fd = sd->fd; - if (g->emblem_len <= 0) - return; + fd = sd->fd; + if( g->emblem_len <= 0 ) + return; - WFIFOHEAD(fd,g->emblem_len+12); - WFIFOW(fd,0)=0x152; - WFIFOW(fd,2)=g->emblem_len+12; - WFIFOL(fd,4)=g->guild_id; - WFIFOL(fd,8)=g->emblem_id; - memcpy(WFIFOP(fd,12),g->emblem_data,g->emblem_len); - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOHEAD(fd,g->emblem_len+12); + WFIFOW(fd,0)=0x152; + WFIFOW(fd,2)=g->emblem_len+12; + WFIFOL(fd,4)=g->guild_id; + WFIFOL(fd,8)=g->emblem_id; + memcpy(WFIFOP(fd,12),g->emblem_data,g->emblem_len); + WFIFOSET(fd,WFIFOW(fd,2)); } /// Sends update of the guild id/emblem id to everyone in the area (ZC_CHANGE_GUILD). /// 01b4 <id>.L <guild id>.L <emblem id>.W -void clif_guild_emblem_area(struct block_list *bl) +void clif_guild_emblem_area(struct block_list* bl) { - uint8 buf[12]; + uint8 buf[12]; - nullpo_retv(bl); + nullpo_retv(bl); - // TODO this packet doesn't force the update of ui components that have the emblem visible - // (emblem in the flag npcs and emblem over the head in agit maps) [FlavioJS] - WBUFW(buf,0) = 0x1b4; - WBUFL(buf,2) = bl->id; - WBUFL(buf,6) = status_get_guild_id(bl); - WBUFW(buf,10) = status_get_emblem_id(bl); - clif_send(buf, 12, bl, AREA_WOS); + // TODO this packet doesn't force the update of ui components that have the emblem visible + // (emblem in the flag npcs and emblem over the head in agit maps) [FlavioJS] + WBUFW(buf,0) = 0x1b4; + WBUFL(buf,2) = bl->id; + WBUFL(buf,6) = status_get_guild_id(bl); + WBUFW(buf,10) = status_get_emblem_id(bl); + clif_send(buf, 12, bl, AREA_WOS); } /// Sends guild skills (ZC_GUILD_SKILLINFO). /// 0162 <packet len>.W <skill points>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <atk range>.W <skill name>.24B <upgradable>.B }* -void clif_guild_skillinfo(struct map_session_data *sd) -{ - int fd; - struct guild *g; - int i,c; - - nullpo_retv(sd); - if ((g = guild_search(sd->status.guild_id)) == NULL) - return; - - fd = sd->fd; - WFIFOHEAD(fd, 6 + MAX_GUILDSKILL*37); - WFIFOW(fd,0) = 0x0162; - WFIFOW(fd,4) = g->skill_point; - for (i = 0, c = 0; i < MAX_GUILDSKILL; i++) { - if (g->skill[i].id > 0 && guild_check_skill_require(g, g->skill[i].id)) { - int id = g->skill[i].id; - int p = 6 + c*37; - WFIFOW(fd,p+0) = id; - WFIFOL(fd,p+2) = skill_get_inf(id); - WFIFOW(fd,p+6) = g->skill[i].lv; - WFIFOW(fd,p+8) = skill_get_sp(id, g->skill[i].lv); - WFIFOW(fd,p+10) = skill_get_range(id, g->skill[i].lv); - safestrncpy((char *)WFIFOP(fd,p+12), skill_get_name(id), NAME_LENGTH); - WFIFOB(fd,p+36)= (g->skill[i].lv < guild_skill_get_max(id) && sd == g->member[0].sd) ? 1 : 0; - c++; - } - } - WFIFOW(fd,2) = 6 + c*37; - WFIFOSET(fd,WFIFOW(fd,2)); +void clif_guild_skillinfo(struct map_session_data* sd) +{ + int fd; + struct guild* g; + int i,c; + + nullpo_retv(sd); + if( (g = guild_search(sd->status.guild_id)) == NULL ) + return; + + fd = sd->fd; + WFIFOHEAD(fd, 6 + MAX_GUILDSKILL*37); + WFIFOW(fd,0) = 0x0162; + WFIFOW(fd,4) = g->skill_point; + for(i = 0, c = 0; i < MAX_GUILDSKILL; i++) + { + if(g->skill[i].id > 0 && guild_check_skill_require(g, g->skill[i].id)) + { + int id = g->skill[i].id; + int p = 6 + c*37; + WFIFOW(fd,p+0) = id; + WFIFOL(fd,p+2) = skill_get_inf(id); + WFIFOW(fd,p+6) = g->skill[i].lv; + WFIFOW(fd,p+8) = skill_get_sp(id, g->skill[i].lv); + WFIFOW(fd,p+10) = skill_get_range(id, g->skill[i].lv); + safestrncpy((char*)WFIFOP(fd,p+12), skill_get_name(id), NAME_LENGTH); + WFIFOB(fd,p+36)= (g->skill[i].lv < guild_skill_get_max(id) && sd == g->member[0].sd) ? 1 : 0; + c++; + } + } + WFIFOW(fd,2) = 6 + c*37; + WFIFOSET(fd,WFIFOW(fd,2)); } /// Sends guild notice to client (ZC_GUILD_NOTICE). /// 016f <subject>.60B <notice>.120B -void clif_guild_notice(struct map_session_data *sd, struct guild *g) +void clif_guild_notice(struct map_session_data* sd, struct guild* g) { - int fd; + int fd; - nullpo_retv(sd); - nullpo_retv(g); + nullpo_retv(sd); + nullpo_retv(g); - fd = sd->fd; + fd = sd->fd; - if (!session_isActive(fd)) - return; + if ( !session_isActive(fd) ) + return; - if (g->mes1[0] == '\0' && g->mes2[0] == '\0') - return; + if(g->mes1[0] == '\0' && g->mes2[0] == '\0') + return; - WFIFOHEAD(fd,packet_len(0x16f)); - WFIFOW(fd,0) = 0x16f; - memcpy(WFIFOP(fd,2), g->mes1, MAX_GUILDMES1); - memcpy(WFIFOP(fd,62), g->mes2, MAX_GUILDMES2); - WFIFOSET(fd,packet_len(0x16f)); + WFIFOHEAD(fd,packet_len(0x16f)); + WFIFOW(fd,0) = 0x16f; + memcpy(WFIFOP(fd,2), g->mes1, MAX_GUILDMES1); + memcpy(WFIFOP(fd,62), g->mes2, MAX_GUILDMES2); + WFIFOSET(fd,packet_len(0x16f)); } @@ -7422,17 +7488,17 @@ void clif_guild_notice(struct map_session_data *sd, struct guild *g) /// 016a <guild id>.L <guild name>.24B void clif_guild_invite(struct map_session_data *sd,struct guild *g) { - int fd; + int fd; - nullpo_retv(sd); - nullpo_retv(g); + nullpo_retv(sd); + nullpo_retv(g); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x16a)); - WFIFOW(fd,0)=0x16a; - WFIFOL(fd,2)=g->guild_id; - memcpy(WFIFOP(fd,6),g->name,NAME_LENGTH); - WFIFOSET(fd,packet_len(0x16a)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x16a)); + WFIFOW(fd,0)=0x16a; + WFIFOL(fd,2)=g->guild_id; + memcpy(WFIFOP(fd,6),g->name,NAME_LENGTH); + WFIFOSET(fd,packet_len(0x16a)); } @@ -7445,15 +7511,15 @@ void clif_guild_invite(struct map_session_data *sd,struct guild *g) /// 3 = Guild full. void clif_guild_inviteack(struct map_session_data *sd,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x169)); - WFIFOW(fd,0)=0x169; - WFIFOB(fd,2)=flag; - WFIFOSET(fd,packet_len(0x169)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x169)); + WFIFOW(fd,0)=0x169; + WFIFOB(fd,2)=flag; + WFIFOSET(fd,packet_len(0x169)); } @@ -7461,104 +7527,108 @@ void clif_guild_inviteack(struct map_session_data *sd,int flag) /// 015a <char name>.24B <reason>.40B void clif_guild_leave(struct map_session_data *sd,const char *name,const char *mes) { - unsigned char buf[128]; + unsigned char buf[128]; - nullpo_retv(sd); + nullpo_retv(sd); - WBUFW(buf, 0)=0x15a; - memcpy(WBUFP(buf, 2),name,NAME_LENGTH); - memcpy(WBUFP(buf,26),mes,40); - clif_send(buf,packet_len(0x15a),&sd->bl,GUILD_NOBG); + WBUFW(buf, 0)=0x15a; + memcpy(WBUFP(buf, 2),name,NAME_LENGTH); + memcpy(WBUFP(buf,26),mes,40); + clif_send(buf,packet_len(0x15a),&sd->bl,GUILD_NOBG); } /// Notifies clients of a guild of an expelled member. /// 015c <char name>.24B <reason>.40B <account name>.24B (ZC_ACK_BAN_GUILD) /// 0839 <char name>.24B <reason>.40B (ZC_ACK_BAN_GUILD_SSO) -void clif_guild_expulsion(struct map_session_data *sd, const char *name, const char *mes, int account_id) +void clif_guild_expulsion(struct map_session_data* sd, const char* name, const char* mes, int account_id) { - unsigned char buf[128]; + unsigned char buf[128]; #if PACKETVER < 20100803 - const unsigned short cmd = 0x15c; + const unsigned short cmd = 0x15c; #else - const unsigned short cmd = 0x839; + const unsigned short cmd = 0x839; #endif - nullpo_retv(sd); + nullpo_retv(sd); - WBUFW(buf,0) = cmd; - safestrncpy((char *)WBUFP(buf,2), name, NAME_LENGTH); - safestrncpy((char *)WBUFP(buf,26), mes, 40); + WBUFW(buf,0) = cmd; + safestrncpy((char*)WBUFP(buf,2), name, NAME_LENGTH); + safestrncpy((char*)WBUFP(buf,26), mes, 40); #if PACKETVER < 20100803 - memset(WBUFP(buf,66), 0, NAME_LENGTH); // account name (not used for security reasons) + memset(WBUFP(buf,66), 0, NAME_LENGTH); // account name (not used for security reasons) #endif - clif_send(buf, packet_len(cmd), &sd->bl, GUILD_NOBG); + clif_send(buf, packet_len(cmd), &sd->bl, GUILD_NOBG); } /// Guild expulsion list (ZC_BAN_LIST). /// 0163 <packet len>.W { <char name>.24B <account name>.24B <reason>.40B }* /// 0163 <packet len>.W { <char name>.24B <reason>.40B }* (PACKETVER >= 20100803) -void clif_guild_expulsionlist(struct map_session_data *sd) +void clif_guild_expulsionlist(struct map_session_data* sd) { #if PACKETVER < 20100803 - const int offset = NAME_LENGTH*2+40; + const int offset = NAME_LENGTH*2+40; #else - const int offset = NAME_LENGTH+40; + const int offset = NAME_LENGTH+40; #endif - int fd, i, c = 0; - struct guild *g; + int fd, i, c = 0; + struct guild* g; - nullpo_retv(sd); + nullpo_retv(sd); - if ((g = guild_search(sd->status.guild_id)) == NULL) - return; + if( (g = guild_search(sd->status.guild_id)) == NULL ) + return; - fd = sd->fd; + fd = sd->fd; - WFIFOHEAD(fd,4 + MAX_GUILDEXPULSION * offset); - WFIFOW(fd,0) = 0x163; + WFIFOHEAD(fd,4 + MAX_GUILDEXPULSION * offset); + WFIFOW(fd,0) = 0x163; - for (i = 0; i < MAX_GUILDEXPULSION; i++) { - struct guild_expulsion *e = &g->expulsion[i]; + for( i = 0; i < MAX_GUILDEXPULSION; i++ ) + { + struct guild_expulsion* e = &g->expulsion[i]; - if (e->account_id > 0) { - memcpy(WFIFOP(fd,4 + c*offset), e->name, NAME_LENGTH); + if( e->account_id > 0 ) + { + memcpy(WFIFOP(fd,4 + c*offset), e->name, NAME_LENGTH); #if PACKETVER < 20100803 - memset(WFIFOP(fd,4 + c*offset+24), 0, NAME_LENGTH); // account name (not used for security reasons) - memcpy(WFIFOP(fd,4 + c*offset+48), e->mes, 40); + memset(WFIFOP(fd,4 + c*offset+24), 0, NAME_LENGTH); // account name (not used for security reasons) + memcpy(WFIFOP(fd,4 + c*offset+48), e->mes, 40); #else - memcpy(WFIFOP(fd,4 + c*offset+24), e->mes, 40); + memcpy(WFIFOP(fd,4 + c*offset+24), e->mes, 40); #endif - c++; - } - } - WFIFOW(fd,2) = 4 + c*offset; - WFIFOSET(fd,WFIFOW(fd,2)); + c++; + } + } + WFIFOW(fd,2) = 4 + c*offset; + WFIFOSET(fd,WFIFOW(fd,2)); } /// Guild chat message (ZC_GUILD_CHAT). /// 017f <packet len>.W <message>.?B void clif_guild_message(struct guild *g,int account_id,const char *mes,int len) -{ - // TODO: account_id is not used, candidate for deletion? [Ai4rei] - struct map_session_data *sd; - uint8 buf[256]; +{// TODO: account_id is not used, candidate for deletion? [Ai4rei] + struct map_session_data *sd; + uint8 buf[256]; - if (len == 0) { - return; - } else if (len > sizeof(buf)-5) { - ShowWarning("clif_guild_message: Truncated message '%s' (len=%d, max=%d, guild_id=%d).\n", mes, len, sizeof(buf)-5, g->guild_id); - len = sizeof(buf)-5; - } + if( len == 0 ) + { + return; + } + else if( len > sizeof(buf)-5 ) + { + ShowWarning("clif_guild_message: Truncated message '%s' (len=%d, max=%d, guild_id=%d).\n", mes, len, sizeof(buf)-5, g->guild_id); + len = sizeof(buf)-5; + } - WBUFW(buf, 0) = 0x17f; - WBUFW(buf, 2) = len + 5; - safestrncpy((char *)WBUFP(buf,4), mes, len+1); + WBUFW(buf, 0) = 0x17f; + WBUFW(buf, 2) = len + 5; + safestrncpy((char*)WBUFP(buf,4), mes, len+1); - if ((sd = guild_getavailablesd(g)) != NULL) - clif_send(buf, WBUFW(buf,2), &sd->bl, GUILD_NOBG); + if ((sd = guild_getavailablesd(g)) != NULL) + clif_send(buf, WBUFW(buf,2), &sd->bl, GUILD_NOBG); } @@ -7566,22 +7636,21 @@ void clif_guild_message(struct guild *g,int account_id,const char *mes,int len) * Server tells client 'sd' that his guild skill 'skill_num' gone to level 'lv' *------------------------------------------*/ int clif_guild_skillup(struct map_session_data *sd,int skill_num,int lv) -{ - // TODO: Merge with clif_skillup (same packet). - int fd; +{// TODO: Merge with clif_skillup (same packet). + int fd; - nullpo_ret(sd); + nullpo_ret(sd); - fd=sd->fd; - WFIFOHEAD(fd,11); - WFIFOW(fd,0) = 0x10e; - WFIFOW(fd,2) = skill_num; - WFIFOW(fd,4) = lv; - WFIFOW(fd,6) = skill_get_sp(skill_num,lv); - WFIFOW(fd,8) = skill_get_range(skill_num,lv); - WFIFOB(fd,10) = 1; - WFIFOSET(fd,11); - return 0; + fd=sd->fd; + WFIFOHEAD(fd,11); + WFIFOW(fd,0) = 0x10e; + WFIFOW(fd,2) = skill_num; + WFIFOW(fd,4) = lv; + WFIFOW(fd,6) = skill_get_sp(skill_num,lv); + WFIFOW(fd,8) = skill_get_range(skill_num,lv); + WFIFOB(fd,10) = 1; + WFIFOSET(fd,11); + return 0; } @@ -7589,16 +7658,16 @@ int clif_guild_skillup(struct map_session_data *sd,int skill_num,int lv) /// 0171 <inviter account id>.L <guild name>.24B void clif_guild_reqalliance(struct map_session_data *sd,int account_id,const char *name) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x171)); - WFIFOW(fd,0)=0x171; - WFIFOL(fd,2)=account_id; - memcpy(WFIFOP(fd,6),name,NAME_LENGTH); - WFIFOSET(fd,packet_len(0x171)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x171)); + WFIFOW(fd,0)=0x171; + WFIFOL(fd,2)=account_id; + memcpy(WFIFOP(fd,6),name,NAME_LENGTH); + WFIFOSET(fd,packet_len(0x171)); } @@ -7613,15 +7682,15 @@ void clif_guild_reqalliance(struct map_session_data *sd,int account_id,const cha /// 5 = Alliances are disabled. void clif_guild_allianceack(struct map_session_data *sd,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x173)); - WFIFOW(fd,0)=0x173; - WFIFOL(fd,2)=flag; - WFIFOSET(fd,packet_len(0x173)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x173)); + WFIFOW(fd,0)=0x173; + WFIFOL(fd,2)=flag; + WFIFOSET(fd,packet_len(0x173)); } @@ -7632,18 +7701,18 @@ void clif_guild_allianceack(struct map_session_data *sd,int flag) /// 1 = Enemy void clif_guild_delalliance(struct map_session_data *sd,int guild_id,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; - if (fd <= 0) - return; - WFIFOHEAD(fd,packet_len(0x184)); - WFIFOW(fd,0)=0x184; - WFIFOL(fd,2)=guild_id; - WFIFOL(fd,6)=flag; - WFIFOSET(fd,packet_len(0x184)); + fd = sd->fd; + if (fd <= 0) + return; + WFIFOHEAD(fd,packet_len(0x184)); + WFIFOW(fd,0)=0x184; + WFIFOL(fd,2)=guild_id; + WFIFOL(fd,6)=flag; + WFIFOSET(fd,packet_len(0x184)); } @@ -7656,15 +7725,15 @@ void clif_guild_delalliance(struct map_session_data *sd,int guild_id,int flag) /// 3 = Antagonists are disabled. void clif_guild_oppositionack(struct map_session_data *sd,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x181)); - WFIFOW(fd,0)=0x181; - WFIFOB(fd,2)=flag; - WFIFOSET(fd,packet_len(0x181)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x181)); + WFIFOW(fd,0)=0x181; + WFIFOB(fd,2)=flag; + WFIFOSET(fd,packet_len(0x181)); } @@ -7673,12 +7742,12 @@ void clif_guild_oppositionack(struct map_session_data *sd,int flag) /* void clif_guild_allianceadded(struct guild *g,int idx) { - unsigned char buf[64]; - WBUFW(buf,0)=0x185; - WBUFL(buf,2)=g->alliance[idx].opposition; - WBUFL(buf,6)=g->alliance[idx].guild_id; - memcpy(WBUFP(buf,10),g->alliance[idx].name,NAME_LENGTH); - clif_send(buf,packet_len(0x185),guild_getavailablesd(g),GUILD); + unsigned char buf[64]; + WBUFW(buf,0)=0x185; + WBUFL(buf,2)=g->alliance[idx].opposition; + WBUFL(buf,6)=g->alliance[idx].guild_id; + memcpy(WBUFP(buf,10),g->alliance[idx].name,NAME_LENGTH); + clif_send(buf,packet_len(0x185),guild_getavailablesd(g),GUILD); } */ @@ -7690,15 +7759,15 @@ void clif_guild_allianceadded(struct guild *g,int idx) /// 2 = there are still members in the guild void clif_guild_broken(struct map_session_data *sd,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x15e)); - WFIFOW(fd,0)=0x15e; - WFIFOL(fd,2)=flag; - WFIFOSET(fd,packet_len(0x15e)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x15e)); + WFIFOW(fd,0)=0x15e; + WFIFOL(fd,2)=flag; + WFIFOSET(fd,packet_len(0x15e)); } @@ -7708,28 +7777,28 @@ void clif_guild_broken(struct map_session_data *sd,int flag) /// enum emotion_type void clif_emotion(struct block_list *bl,int type) { - unsigned char buf[8]; + unsigned char buf[8]; - nullpo_retv(bl); + nullpo_retv(bl); - WBUFW(buf,0)=0xc0; - WBUFL(buf,2)=bl->id; - WBUFB(buf,6)=type; - clif_send(buf,packet_len(0xc0),bl,AREA); + WBUFW(buf,0)=0xc0; + WBUFL(buf,2)=bl->id; + WBUFB(buf,6)=type; + clif_send(buf,packet_len(0xc0),bl,AREA); } /// Displays the contents of a talkiebox trap (ZC_TALKBOX_CHATCONTENTS). /// 0191 <id>.L <contents>.80B -void clif_talkiebox(struct block_list *bl, const char *talkie) +void clif_talkiebox(struct block_list* bl, const char* talkie) { - unsigned char buf[MESSAGE_SIZE+6]; - nullpo_retv(bl); + unsigned char buf[MESSAGE_SIZE+6]; + nullpo_retv(bl); - WBUFW(buf,0) = 0x191; - WBUFL(buf,2) = bl->id; - safestrncpy((char *)WBUFP(buf,6),talkie,MESSAGE_SIZE); - clif_send(buf,packet_len(0x191),bl,AREA); + WBUFW(buf,0) = 0x191; + WBUFL(buf,2) = bl->id; + safestrncpy((char*)WBUFP(buf,6),talkie,MESSAGE_SIZE); + clif_send(buf,packet_len(0x191),bl,AREA); } @@ -7737,13 +7806,13 @@ void clif_talkiebox(struct block_list *bl, const char *talkie) /// 01ea <id>.L void clif_wedding_effect(struct block_list *bl) { - unsigned char buf[6]; + unsigned char buf[6]; - nullpo_retv(bl); + nullpo_retv(bl); - WBUFW(buf,0) = 0x1ea; - WBUFL(buf,2) = bl->id; - clif_send(buf, packet_len(0x1ea), bl, AREA); + WBUFW(buf,0) = 0x1ea; + WBUFL(buf,2) = bl->id; + clif_send(buf, packet_len(0x1ea), bl, AREA); } @@ -7751,25 +7820,30 @@ void clif_wedding_effect(struct block_list *bl) /// 01e6 <partner name>.24B void clif_callpartner(struct map_session_data *sd) { - unsigned char buf[26]; - const char *p; + unsigned char buf[26]; + const char *p; - nullpo_retv(sd); + nullpo_retv(sd); - WBUFW(buf,0) = 0x1e6; + WBUFW(buf,0) = 0x1e6; - if (sd->status.partner_id) { - if ((p = map_charid2nick(sd->status.partner_id)) != NULL) { - memcpy(WBUFP(buf,2), p, NAME_LENGTH); - } else { - WBUFB(buf,2) = 0; - } - } else { - // Send zero-length name if no partner, to initialize the client buffer. - WBUFB(buf,2) = 0; - } + if( sd->status.partner_id ) + { + if( ( p = map_charid2nick(sd->status.partner_id) ) != NULL ) + { + memcpy(WBUFP(buf,2), p, NAME_LENGTH); + } + else + { + WBUFB(buf,2) = 0; + } + } + else + {// Send zero-length name if no partner, to initialize the client buffer. + WBUFB(buf,2) = 0; + } - clif_send(buf, packet_len(0x1e6), &sd->bl, AREA); + clif_send(buf, packet_len(0x1e6), &sd->bl, AREA); } @@ -7779,29 +7853,29 @@ void clif_callpartner(struct map_session_data *sd) /* void clif_marriage_process(struct map_session_data *sd) { - int fd; - nullpo_retv(sd); + int fd; + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x1e4)); - WFIFOW(fd,0)=0x1e4; - WFIFOSET(fd,packet_len(0x1e4)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x1e4)); + WFIFOW(fd,0)=0x1e4; + WFIFOSET(fd,packet_len(0x1e4)); } */ /// Notice of divorce (ZC_DIVORCE). /// 0205 <partner name>.24B -void clif_divorced(struct map_session_data *sd, const char *name) +void clif_divorced(struct map_session_data* sd, const char* name) { - int fd; - nullpo_retv(sd); + int fd; + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x205)); - WFIFOW(fd,0)=0x205; - memcpy(WFIFOP(fd,2), name, NAME_LENGTH); - WFIFOSET(fd, packet_len(0x205)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x205)); + WFIFOW(fd,0)=0x205; + memcpy(WFIFOP(fd,2), name, NAME_LENGTH); + WFIFOSET(fd, packet_len(0x205)); } @@ -7811,14 +7885,14 @@ void clif_divorced(struct map_session_data *sd, const char *name) /* void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_session_data* ssd) { - nullpo_retv(sd); + nullpo_retv(sd); - WFIFOHEAD(fd,packet_len(0x1e2)); - WFIFOW(fd,0) = 0x1e2; - WFIFOL(fd,2) = ssd->status.account_id; - WFIFOL(fd,6) = ssd->status.char_id; - safestrncpy((char*)WFIFOP(fd,10), ssd->status.name, NAME_LENGTH); - WFIFOSET(fd, packet_len(0x1e2)); + WFIFOHEAD(fd,packet_len(0x1e2)); + WFIFOW(fd,0) = 0x1e2; + WFIFOL(fd,2) = ssd->status.account_id; + WFIFOL(fd,6) = ssd->status.char_id; + safestrncpy((char*)WFIFOP(fd,10), ssd->status.name, NAME_LENGTH); + WFIFOSET(fd, packet_len(0x1e2)); } */ @@ -7828,27 +7902,30 @@ void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_sess *------------------------------------------*/ void clif_disp_onlyself(struct map_session_data *sd, const char *mes, int len) { - clif_disp_message(&sd->bl, mes, len, SELF); + clif_disp_message(&sd->bl, mes, len, SELF); } /*========================================== * Displays a message using the guild-chat colors to the specified targets. [Skotlex] *------------------------------------------*/ -void clif_disp_message(struct block_list *src, const char *mes, int len, enum send_target target) +void clif_disp_message(struct block_list* src, const char* mes, int len, enum send_target target) { - unsigned char buf[256]; + unsigned char buf[256]; - if (len == 0) { - return; - } else if (len > sizeof(buf)-5) { - ShowWarning("clif_disp_message: Truncated message '%s' (len=%d, max=%d, aid=%d).\n", mes, len, sizeof(buf)-5, src->id); - len = sizeof(buf)-5; - } + if( len == 0 ) + { + return; + } + else if( len > sizeof(buf)-5 ) + { + ShowWarning("clif_disp_message: Truncated message '%s' (len=%d, max=%d, aid=%d).\n", mes, len, sizeof(buf)-5, src->id); + len = sizeof(buf)-5; + } - WBUFW(buf, 0) = 0x17f; - WBUFW(buf, 2) = len + 5; - safestrncpy((char *)WBUFP(buf,4), mes, len+1); - clif_send(buf, WBUFW(buf,2), src, target); + WBUFW(buf, 0) = 0x17f; + WBUFW(buf, 2) = len + 5; + safestrncpy((char*)WBUFP(buf,4), mes, len+1); + clif_send(buf, WBUFW(buf,2), src, target); } @@ -7860,29 +7937,29 @@ void clif_disp_message(struct block_list *src, const char *mes, int len, enum se /// 1 = success void clif_GM_kickack(struct map_session_data *sd, int id) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xcd)); - WFIFOW(fd,0) = 0xcd; - WFIFOB(fd,2) = id; // FIXME: this is not account id - WFIFOSET(fd, packet_len(0xcd)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0xcd)); + WFIFOW(fd,0) = 0xcd; + WFIFOB(fd,2) = id; // FIXME: this is not account id + WFIFOSET(fd, packet_len(0xcd)); } void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd) { - int fd = tsd->fd; + int fd = tsd->fd; - if (fd > 0) - clif_authfail_fd(fd, 15); - else - map_quit(tsd); + if( fd > 0 ) + clif_authfail_fd(fd, 15); + else + map_quit(tsd); - if (sd) - clif_GM_kickack(sd,tsd->status.account_id); + if( sd ) + clif_GM_kickack(sd,tsd->status.account_id); } @@ -7895,16 +7972,16 @@ void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd) /// 3 = "Chat Block has been applied by GM due to your ill-mannerous action." /// 4 = "Automated Chat Block has been applied due to Anti-Spam System." /// 5 = "You got a good point from %s." -void clif_manner_message(struct map_session_data *sd, uint32 type) +void clif_manner_message(struct map_session_data* sd, uint32 type) { - int fd; - nullpo_retv(sd); + int fd; + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x14a)); - WFIFOW(fd,0) = 0x14a; - WFIFOL(fd,2) = type; - WFIFOSET(fd, packet_len(0x14a)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0x14a)); + WFIFOW(fd,0) = 0x14a; + WFIFOL(fd,2) = type; + WFIFOSET(fd, packet_len(0x14a)); } @@ -7913,18 +7990,18 @@ void clif_manner_message(struct map_session_data *sd, uint32 type) /// type: /// 0 = positive (unmute) /// 1 = negative (mute) -void clif_GM_silence(struct map_session_data *sd, struct map_session_data *tsd, uint8 type) +void clif_GM_silence(struct map_session_data* sd, struct map_session_data* tsd, uint8 type) { - int fd; - nullpo_retv(sd); - nullpo_retv(tsd); + int fd; + nullpo_retv(sd); + nullpo_retv(tsd); - fd = tsd->fd; - WFIFOHEAD(fd,packet_len(0x14b)); - WFIFOW(fd,0) = 0x14b; - WFIFOB(fd,2) = type; - safestrncpy((char *)WFIFOP(fd,3), sd->status.name, NAME_LENGTH); - WFIFOSET(fd, packet_len(0x14b)); + fd = tsd->fd; + WFIFOHEAD(fd,packet_len(0x14b)); + WFIFOW(fd,0) = 0x14b; + WFIFOB(fd,2) = type; + safestrncpy((char*)WFIFOP(fd,3), sd->status.name, NAME_LENGTH); + WFIFOSET(fd, packet_len(0x14b)); } @@ -7939,16 +8016,16 @@ void clif_GM_silence(struct map_session_data *sd, struct map_session_data *tsd, /// 2 = too many blocks void clif_wisexin(struct map_session_data *sd,int type,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xd1)); - WFIFOW(fd,0)=0xd1; - WFIFOB(fd,2)=type; - WFIFOB(fd,3)=flag; - WFIFOSET(fd,packet_len(0xd1)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xd1)); + WFIFOW(fd,0)=0xd1; + WFIFOB(fd,2)=type; + WFIFOB(fd,3)=flag; + WFIFOSET(fd,packet_len(0xd1)); } /// Notifies the client about the result of a request to allow/deny whispers from anyone (ZC_SETTING_WHISPER_STATE). @@ -7961,32 +8038,32 @@ void clif_wisexin(struct map_session_data *sd,int type,int flag) /// 1 = failure void clif_wisall(struct map_session_data *sd,int type,int flag) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd=sd->fd; - WFIFOHEAD(fd,packet_len(0xd2)); - WFIFOW(fd,0)=0xd2; - WFIFOB(fd,2)=type; - WFIFOB(fd,3)=flag; - WFIFOSET(fd,packet_len(0xd2)); + fd=sd->fd; + WFIFOHEAD(fd,packet_len(0xd2)); + WFIFOW(fd,0)=0xd2; + WFIFOB(fd,2)=type; + WFIFOB(fd,3)=flag; + WFIFOSET(fd,packet_len(0xd2)); } /// Play a BGM! [Rikter/Yommy] (ZC_PLAY_NPC_BGM). /// 07fe <bgm>.24B -void clif_playBGM(struct map_session_data *sd, const char *name) +void clif_playBGM(struct map_session_data* sd, const char* name) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x7fe)); - WFIFOW(fd,0) = 0x7fe; - safestrncpy((char *)WFIFOP(fd,2), name, NAME_LENGTH); - WFIFOSET(fd,packet_len(0x7fe)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0x7fe)); + WFIFOW(fd,0) = 0x7fe; + safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + WFIFOSET(fd,packet_len(0x7fe)); } @@ -8003,35 +8080,35 @@ void clif_playBGM(struct map_session_data *sd, const char *name) /// npc id: /// The accustic direction of the sound is determined by the /// relative position of the NPC to the player (3D sound). -void clif_soundeffect(struct map_session_data *sd, struct block_list *bl, const char *name, int type) +void clif_soundeffect(struct map_session_data* sd, struct block_list* bl, const char* name, int type) { - int fd; + int fd; - nullpo_retv(sd); - nullpo_retv(bl); + nullpo_retv(sd); + nullpo_retv(bl); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x1d3)); - WFIFOW(fd,0) = 0x1d3; - safestrncpy((char *)WFIFOP(fd,2), name, NAME_LENGTH); - WFIFOB(fd,26) = type; - WFIFOL(fd,27) = 0; - WFIFOL(fd,31) = bl->id; - WFIFOSET(fd,packet_len(0x1d3)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0x1d3)); + WFIFOW(fd,0) = 0x1d3; + safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + WFIFOB(fd,26) = type; + WFIFOL(fd,27) = 0; + WFIFOL(fd,31) = bl->id; + WFIFOSET(fd,packet_len(0x1d3)); } -void clif_soundeffectall(struct block_list *bl, const char *name, int type, enum send_target coverage) +void clif_soundeffectall(struct block_list* bl, const char* name, int type, enum send_target coverage) { - unsigned char buf[40]; + unsigned char buf[40]; - nullpo_retv(bl); + nullpo_retv(bl); - WBUFW(buf,0) = 0x1d3; - safestrncpy((char *)WBUFP(buf,2), name, NAME_LENGTH); - WBUFB(buf,26) = type; - WBUFL(buf,27) = 0; - WBUFL(buf,31) = bl->id; - clif_send(buf, packet_len(0x1d3), bl, coverage); + WBUFW(buf,0) = 0x1d3; + safestrncpy((char*)WBUFP(buf,2), name, NAME_LENGTH); + WBUFB(buf,26) = type; + WBUFL(buf,27) = 0; + WBUFL(buf,31) = bl->id; + clif_send(buf, packet_len(0x1d3), bl, coverage); } @@ -8039,33 +8116,33 @@ void clif_soundeffectall(struct block_list *bl, const char *name, int type, enum /// 01f3 <id>.L <effect id>.L /// effect id: /// @see doc/effect_list.txt -void clif_specialeffect(struct block_list *bl, int type, enum send_target target) +void clif_specialeffect(struct block_list* bl, int type, enum send_target target) { - unsigned char buf[24]; + unsigned char buf[24]; - nullpo_retv(bl); + nullpo_retv(bl); - memset(buf, 0, packet_len(0x1f3)); + memset(buf, 0, packet_len(0x1f3)); - WBUFW(buf,0) = 0x1f3; - WBUFL(buf,2) = bl->id; - WBUFL(buf,6) = type; + WBUFW(buf,0) = 0x1f3; + WBUFL(buf,2) = bl->id; + WBUFL(buf,6) = type; - clif_send(buf, packet_len(0x1f3), bl, target); + clif_send(buf, packet_len(0x1f3), bl, target); - if (disguised(bl)) { - WBUFL(buf,2) = -bl->id; - clif_send(buf, packet_len(0x1f3), bl, SELF); - } + if (disguised(bl)) { + WBUFL(buf,2) = -bl->id; + clif_send(buf, packet_len(0x1f3), bl, SELF); + } } -void clif_specialeffect_single(struct block_list *bl, int type, int fd) +void clif_specialeffect_single(struct block_list* bl, int type, int fd) { - WFIFOHEAD(fd,10); - WFIFOW(fd,0) = 0x1f3; - WFIFOL(fd,2) = bl->id; - WFIFOL(fd,6) = type; - WFIFOSET(fd,10); + WFIFOHEAD(fd,10); + WFIFOW(fd,0) = 0x1f3; + WFIFOL(fd,2) = bl->id; + WFIFOL(fd,6) = type; + WFIFOSET(fd,10); } @@ -8075,317 +8152,332 @@ void clif_specialeffect_single(struct block_list *bl, int type, int fd) /// @see doc/effect_list.txt /// num data: /// effect-dependent value -void clif_specialeffect_value(struct block_list *bl, int effect_id, int num, send_target target) +void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, send_target target) { - uint8 buf[14]; + uint8 buf[14]; - WBUFW(buf,0) = 0x284; - WBUFL(buf,2) = bl->id; - WBUFL(buf,6) = effect_id; - WBUFL(buf,10) = num; + WBUFW(buf,0) = 0x284; + WBUFL(buf,2) = bl->id; + WBUFL(buf,6) = effect_id; + WBUFL(buf,10) = num; - clif_send(buf, packet_len(0x284), bl, target); + clif_send(buf, packet_len(0x284), bl, target); - if (disguised(bl)) { - WBUFL(buf,2) = -bl->id; - clif_send(buf, packet_len(0x284), bl, SELF); - } + if( disguised(bl) ) + { + WBUFL(buf,2) = -bl->id; + clif_send(buf, packet_len(0x284), bl, SELF); + } } // Modification of clif_messagecolor to send colored messages to players to chat log only (doesn't display overhead) /// 02c1 <packet len>.W <id>.L <color>.L <message>.?B -int clif_colormes(struct map_session_data *sd, enum clif_colors color, const char *msg) -{ - unsigned short msg_len = strlen(msg) + 1; +int clif_colormes(struct map_session_data * sd, enum clif_colors color, const char* msg) { + unsigned short msg_len = strlen(msg) + 1; - WFIFOHEAD(sd->fd,msg_len + 12); - WFIFOW(sd->fd,0) = 0x2C1; - WFIFOW(sd->fd,2) = msg_len + 12; - WFIFOL(sd->fd,4) = 0; - WFIFOL(sd->fd,8) = color_table[color]; - safestrncpy((char *)WFIFOP(sd->fd,12), msg, msg_len); - clif_send(WFIFOP(sd->fd,0), WFIFOW(sd->fd,2), &sd->bl, SELF); + WFIFOHEAD(sd->fd,msg_len + 12); + WFIFOW(sd->fd,0) = 0x2C1; + WFIFOW(sd->fd,2) = msg_len + 12; + WFIFOL(sd->fd,4) = 0; + WFIFOL(sd->fd,8) = color_table[color]; + safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); + clif_send(WFIFOP(sd->fd,0), WFIFOW(sd->fd,2), &sd->bl, SELF); - return 0; + return 0; } /// Monster/NPC color chat [SnakeDrak] (ZC_NPC_CHAT). /// 02c1 <packet len>.W <id>.L <color>.L <message>.?B -void clif_messagecolor(struct block_list *bl, unsigned long color, const char *msg) -{ - unsigned short msg_len = strlen(msg) + 1; - uint8 buf[256]; - color = (color & 0x0000FF) << 16 | (color & 0x00FF00) | (color & 0xFF0000) >> 16; // RGB to BGR +void clif_messagecolor(struct block_list* bl, unsigned long color, const char* msg) { + unsigned short msg_len = strlen(msg) + 1; + uint8 buf[256]; + color = (color & 0x0000FF) << 16 | (color & 0x00FF00) | (color & 0xFF0000) >> 16; // RGB to BGR - nullpo_retv(bl); + nullpo_retv(bl); - if (msg_len > sizeof(buf)-12) { - ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%u).\n", msg, msg_len); - msg_len = sizeof(buf)-12; - } + if( msg_len > sizeof(buf)-12 ) + { + ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%u).\n", msg, msg_len); + msg_len = sizeof(buf)-12; + } - WBUFW(buf,0) = 0x2C1; - WBUFW(buf,2) = msg_len + 12; - WBUFL(buf,4) = bl->id; - WBUFL(buf,8) = color; - memcpy(WBUFP(buf,12), msg, msg_len); + WBUFW(buf,0) = 0x2C1; + WBUFW(buf,2) = msg_len + 12; + WBUFL(buf,4) = bl->id; + WBUFL(buf,8) = color; + memcpy(WBUFP(buf,12), msg, msg_len); - clif_send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); + clif_send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); } /// Public chat message [Valaris] (ZC_NOTIFY_CHAT). /// 008d <packet len>.W <id>.L <message>.?B -void clif_message(struct block_list *bl, const char *msg) -{ - unsigned short msg_len = strlen(msg) + 1; - uint8 buf[256]; - nullpo_retv(bl); +void clif_message(struct block_list* bl, const char* msg) { + unsigned short msg_len = strlen(msg) + 1; + uint8 buf[256]; + nullpo_retv(bl); - if (msg_len > sizeof(buf)-8) { - ShowWarning("clif_message: Truncating too long message '%s' (len=%u).\n", msg, msg_len); - msg_len = sizeof(buf)-8; - } + if( msg_len > sizeof(buf)-8 ) { + ShowWarning("clif_message: Truncating too long message '%s' (len=%u).\n", msg, msg_len); + msg_len = sizeof(buf)-8; + } - WBUFW(buf,0) = 0x8d; - WBUFW(buf,2) = msg_len + 8; - WBUFL(buf,4) = bl->id; - safestrncpy((char *)WBUFP(buf,8), msg, msg_len); + WBUFW(buf,0) = 0x8d; + WBUFW(buf,2) = msg_len + 8; + WBUFL(buf,4) = bl->id; + safestrncpy((char*)WBUFP(buf,8), msg, msg_len); - clif_send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); + clif_send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); } // refresh the client's screen, getting rid of any effects void clif_refresh(struct map_session_data *sd) { - int i; - nullpo_retv(sd); - - clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y); - clif_inventorylist(sd); - if (pc_iscarton(sd)) { - clif_cartlist(sd); - clif_updatestatus(sd,SP_CARTINFO); - } - clif_updatestatus(sd,SP_WEIGHT); - clif_updatestatus(sd,SP_MAXWEIGHT); - clif_updatestatus(sd,SP_STR); - clif_updatestatus(sd,SP_AGI); - clif_updatestatus(sd,SP_VIT); - clif_updatestatus(sd,SP_INT); - clif_updatestatus(sd,SP_DEX); - clif_updatestatus(sd,SP_LUK); - if (sd->spiritball) - clif_spiritball_single(sd->fd, sd); - for (i = 1; i < 5; i++) { - if (sd->talisman[i] > 0) - clif_talisman_single(sd->fd, sd, i); - } - if (sd->vd.cloth_color) - clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); - if (merc_is_hom_active(sd->hd)) - clif_send_homdata(sd,SP_ACK,0); - if (sd->md) { - clif_mercenary_info(sd); - clif_mercenary_skillblock(sd); - } - if (sd->ed) - clif_elemental_info(sd); - map_foreachinrange(clif_getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd); - clif_weather_check(sd); - if (sd->chatID) - chat_leavechat(sd,0); - if (sd->state.vending) - clif_openvending(sd, sd->bl.id, sd->vending); - if (pc_issit(sd)) - clif_sitting(&sd->bl); // FIXME: just send to self, not area - if (pc_isdead(sd)) // When you refresh, resend the death packet. - clif_clearunit_single(sd->bl.id,CLR_DEAD,sd->fd); - else - clif_changed_dir(&sd->bl, SELF); - - // unlike vending, resuming buyingstore crashes the client. - buyingstore_close(sd); - - mail_clear(sd); + int i; + nullpo_retv(sd); + + clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y); + clif_inventorylist(sd); + if(pc_iscarton(sd)) { + clif_cartlist(sd); + clif_updatestatus(sd,SP_CARTINFO); + } + clif_updatestatus(sd,SP_WEIGHT); + clif_updatestatus(sd,SP_MAXWEIGHT); + clif_updatestatus(sd,SP_STR); + clif_updatestatus(sd,SP_AGI); + clif_updatestatus(sd,SP_VIT); + clif_updatestatus(sd,SP_INT); + clif_updatestatus(sd,SP_DEX); + clif_updatestatus(sd,SP_LUK); + if (sd->spiritball) + clif_spiritball_single(sd->fd, sd); + for(i = 1; i < 5; i++){ + if( sd->talisman[i] > 0 ) + clif_talisman_single(sd->fd, sd, i); + } + if (sd->vd.cloth_color) + clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); + if(merc_is_hom_active(sd->hd)) + clif_send_homdata(sd,SP_ACK,0); + if( sd->md ) { + clif_mercenary_info(sd); + clif_mercenary_skillblock(sd); + } + if( sd->ed ) + clif_elemental_info(sd); + map_foreachinrange(clif_getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd); + clif_weather_check(sd); + if( sd->chatID ) + chat_leavechat(sd,0); + if( sd->state.vending ) + clif_openvending(sd, sd->bl.id, sd->vending); + if( pc_issit(sd) ) + clif_sitting(&sd->bl); // FIXME: just send to self, not area + if( pc_isdead(sd) ) // When you refresh, resend the death packet. + clif_clearunit_single(sd->bl.id,CLR_DEAD,sd->fd); + else + clif_changed_dir(&sd->bl, SELF); + + // unlike vending, resuming buyingstore crashes the client. + buyingstore_close(sd); + + mail_clear(sd); } /// Updates the object's (bl) name on client. /// 0095 <id>.L <char name>.24B (ZC_ACK_REQNAME) /// 0195 <id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B (ZC_ACK_REQNAMEALL) -void clif_charnameack(int fd, struct block_list *bl) -{ - unsigned char buf[103]; - int cmd = 0x95, i, ps = -1; - - nullpo_retv(bl); - - WBUFW(buf,0) = cmd; - WBUFL(buf,2) = bl->id; - - switch (bl->type) { - case BL_PC: { - struct map_session_data *ssd = (struct map_session_data *)bl; - struct party_data *p = NULL; - struct guild *g = NULL; - - //Requesting your own "shadow" name. [Skotlex] - if (ssd->fd == fd && ssd->disguise) - WBUFL(buf,2) = -bl->id; - - if (ssd->fakename[0]) { - WBUFW(buf, 0) = cmd = 0x195; - memcpy(WBUFP(buf,6), ssd->fakename, NAME_LENGTH); - WBUFB(buf,30) = WBUFB(buf,54) = WBUFB(buf,78) = 0; - break; - } - memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH); - - if (ssd->status.party_id) { - p = party_search(ssd->status.party_id); - } - if (ssd->status.guild_id) { - if ((g = guild_search(ssd->status.guild_id)) != NULL) { - ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id); - if (i < g->max_member) ps = g->member[i].position; - } - } - - if (!battle_config.display_party_name && g == NULL) { - // do not display party unless the player is also in a guild - p = NULL; - } - - if (p == NULL && g == NULL) - break; - - WBUFW(buf, 0) = cmd = 0x195; - if (p) - memcpy(WBUFP(buf,30), p->party.name, NAME_LENGTH); - else - WBUFB(buf,30) = 0; - - if (g && ps >= 0 && ps < MAX_GUILDPOSITION) { - memcpy(WBUFP(buf,54), g->name,NAME_LENGTH); - memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH); - } else { //Assume no guild. - WBUFB(buf,54) = 0; - WBUFB(buf,78) = 0; - } - } - break; - //[blackhole89] - case BL_HOM: - memcpy(WBUFP(buf,6), ((TBL_HOM *)bl)->homunculus.name, NAME_LENGTH); - break; - case BL_MER: - memcpy(WBUFP(buf,6), ((TBL_MER *)bl)->db->name, NAME_LENGTH); - break; - case BL_PET: - memcpy(WBUFP(buf,6), ((TBL_PET *)bl)->pet.name, NAME_LENGTH); - break; - case BL_NPC: - memcpy(WBUFP(buf,6), ((TBL_NPC *)bl)->name, NAME_LENGTH); - break; - case BL_MOB: { - struct mob_data *md = (struct mob_data *)bl; - nullpo_retv(md); - - memcpy(WBUFP(buf,6), md->name, NAME_LENGTH); - if (md->guardian_data && md->guardian_data->guild_id) { - WBUFW(buf, 0) = cmd = 0x195; - WBUFB(buf,30) = 0; - memcpy(WBUFP(buf,54), md->guardian_data->guild_name, NAME_LENGTH); - memcpy(WBUFP(buf,78), md->guardian_data->castle->castle_name, NAME_LENGTH); - } else if (battle_config.show_mob_info) { - char mobhp[50], *str_p = mobhp; - WBUFW(buf, 0) = cmd = 0x195; - if (battle_config.show_mob_info&4) - str_p += sprintf(str_p, "Lv. %d | ", md->level); - if (battle_config.show_mob_info&1) - str_p += sprintf(str_p, "HP: %u/%u | ", md->status.hp, md->status.max_hp); - if (battle_config.show_mob_info&2) - str_p += sprintf(str_p, "HP: %d%% | ", get_percentage(md->status.hp, md->status.max_hp)); - //Even thought mobhp ain't a name, we send it as one so the client - //can parse it. [Skotlex] - if (str_p != mobhp) { - *(str_p-3) = '\0'; //Remove trailing space + pipe. - memcpy(WBUFP(buf,30), mobhp, NAME_LENGTH); - WBUFB(buf,54) = 0; - WBUFB(buf,78) = 0; - } - } - } - break; - case BL_CHAT: //FIXME: Clients DO request this... what should be done about it? The chat's title may not fit... [Skotlex] - // memcpy(WBUFP(buf,6), (struct chat*)->title, NAME_LENGTH); - // break; - return; - case BL_ELEM: - memcpy(WBUFP(buf,6), ((TBL_ELEM *)bl)->db->name, NAME_LENGTH); - break; - default: - ShowError("clif_charnameack: bad type %d(%d)\n", bl->type, bl->id); - return; - } - - // if no receipient specified just update nearby clients - if (fd == 0) - clif_send(buf, packet_len(cmd), bl, AREA); - else { - WFIFOHEAD(fd, packet_len(cmd)); - memcpy(WFIFOP(fd, 0), buf, packet_len(cmd)); - WFIFOSET(fd, packet_len(cmd)); - } +void clif_charnameack (int fd, struct block_list *bl) +{ + unsigned char buf[103]; + int cmd = 0x95, i, ps = -1; + + nullpo_retv(bl); + + WBUFW(buf,0) = cmd; + WBUFL(buf,2) = bl->id; + + switch( bl->type ) + { + case BL_PC: + { + struct map_session_data *ssd = (struct map_session_data *)bl; + struct party_data *p = NULL; + struct guild *g = NULL; + + //Requesting your own "shadow" name. [Skotlex] + if (ssd->fd == fd && ssd->disguise) + WBUFL(buf,2) = -bl->id; + + if( ssd->fakename[0] ) + { + WBUFW(buf, 0) = cmd = 0x195; + memcpy(WBUFP(buf,6), ssd->fakename, NAME_LENGTH); + WBUFB(buf,30) = WBUFB(buf,54) = WBUFB(buf,78) = 0; + break; + } + memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH); + + if( ssd->status.party_id ) + { + p = party_search(ssd->status.party_id); + } + if( ssd->status.guild_id ) + { + if( ( g = guild_search(ssd->status.guild_id) ) != NULL ) + { + ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id); + if( i < g->max_member ) ps = g->member[i].position; + } + } + + if( !battle_config.display_party_name && g == NULL ) + {// do not display party unless the player is also in a guild + p = NULL; + } + + if (p == NULL && g == NULL) + break; + + WBUFW(buf, 0) = cmd = 0x195; + if (p) + memcpy(WBUFP(buf,30), p->party.name, NAME_LENGTH); + else + WBUFB(buf,30) = 0; + + if (g && ps >= 0 && ps < MAX_GUILDPOSITION) + { + memcpy(WBUFP(buf,54), g->name,NAME_LENGTH); + memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH); + } else { //Assume no guild. + WBUFB(buf,54) = 0; + WBUFB(buf,78) = 0; + } + } + break; + //[blackhole89] + case BL_HOM: + memcpy(WBUFP(buf,6), ((TBL_HOM*)bl)->homunculus.name, NAME_LENGTH); + break; + case BL_MER: + memcpy(WBUFP(buf,6), ((TBL_MER*)bl)->db->name, NAME_LENGTH); + break; + case BL_PET: + memcpy(WBUFP(buf,6), ((TBL_PET*)bl)->pet.name, NAME_LENGTH); + break; + case BL_NPC: + memcpy(WBUFP(buf,6), ((TBL_NPC*)bl)->name, NAME_LENGTH); + break; + case BL_MOB: + { + struct mob_data *md = (struct mob_data *)bl; + nullpo_retv(md); + + memcpy(WBUFP(buf,6), md->name, NAME_LENGTH); + if( md->guardian_data && md->guardian_data->guild_id ) + { + WBUFW(buf, 0) = cmd = 0x195; + WBUFB(buf,30) = 0; + memcpy(WBUFP(buf,54), md->guardian_data->guild_name, NAME_LENGTH); + memcpy(WBUFP(buf,78), md->guardian_data->castle->castle_name, NAME_LENGTH); + } + else if( battle_config.show_mob_info ) + { + char mobhp[50], *str_p = mobhp; + WBUFW(buf, 0) = cmd = 0x195; + if( battle_config.show_mob_info&4 ) + str_p += sprintf(str_p, "Lv. %d | ", md->level); + if( battle_config.show_mob_info&1 ) + str_p += sprintf(str_p, "HP: %u/%u | ", md->status.hp, md->status.max_hp); + if( battle_config.show_mob_info&2 ) + str_p += sprintf(str_p, "HP: %d%% | ", get_percentage(md->status.hp, md->status.max_hp)); + //Even thought mobhp ain't a name, we send it as one so the client + //can parse it. [Skotlex] + if( str_p != mobhp ) + { + *(str_p-3) = '\0'; //Remove trailing space + pipe. + memcpy(WBUFP(buf,30), mobhp, NAME_LENGTH); + WBUFB(buf,54) = 0; + WBUFB(buf,78) = 0; + } + } + } + break; + case BL_CHAT: //FIXME: Clients DO request this... what should be done about it? The chat's title may not fit... [Skotlex] +// memcpy(WBUFP(buf,6), (struct chat*)->title, NAME_LENGTH); +// break; + return; + case BL_ELEM: + memcpy(WBUFP(buf,6), ((TBL_ELEM*)bl)->db->name, NAME_LENGTH); + break; + default: + ShowError("clif_charnameack: bad type %d(%d)\n", bl->type, bl->id); + return; + } + + // if no receipient specified just update nearby clients + if (fd == 0) + clif_send(buf, packet_len(cmd), bl, AREA); + else { + WFIFOHEAD(fd, packet_len(cmd)); + memcpy(WFIFOP(fd, 0), buf, packet_len(cmd)); + WFIFOSET(fd, packet_len(cmd)); + } } //Used to update when a char leaves a party/guild. [Skotlex] //Needed because when you send a 0x95 packet, the client will not remove the cached party/guild info that is not sent. -void clif_charnameupdate(struct map_session_data *ssd) +void clif_charnameupdate (struct map_session_data *ssd) { - unsigned char buf[103]; - int cmd = 0x195, ps = -1, i; - struct party_data *p = NULL; - struct guild *g = NULL; + unsigned char buf[103]; + int cmd = 0x195, ps = -1, i; + struct party_data *p = NULL; + struct guild *g = NULL; - nullpo_retv(ssd); + nullpo_retv(ssd); - if (ssd->fakename[0]) - return; //No need to update as the party/guild was not displayed anyway. + if( ssd->fakename[0] ) + return; //No need to update as the party/guild was not displayed anyway. - WBUFW(buf,0) = cmd; - WBUFL(buf,2) = ssd->bl.id; + WBUFW(buf,0) = cmd; + WBUFL(buf,2) = ssd->bl.id; - memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH); + memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH); - if (!battle_config.display_party_name) { - if (ssd->status.party_id > 0 && ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL) - p = party_search(ssd->status.party_id); - } else { - if (ssd->status.party_id > 0) - p = party_search(ssd->status.party_id); - } + if (!battle_config.display_party_name) { + if (ssd->status.party_id > 0 && ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL) + p = party_search(ssd->status.party_id); + }else{ + if (ssd->status.party_id > 0) + p = party_search(ssd->status.party_id); + } - if (ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL) { - ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id); - if (i < g->max_member) ps = g->member[i].position; - } + if( ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL ) + { + ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id); + if( i < g->max_member ) ps = g->member[i].position; + } - if (p) - memcpy(WBUFP(buf,30), p->party.name, NAME_LENGTH); - else - WBUFB(buf,30) = 0; - - if (g && ps >= 0 && ps < MAX_GUILDPOSITION) { - memcpy(WBUFP(buf,54), g->name,NAME_LENGTH); - memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH); - } else { - WBUFB(buf,54) = 0; - WBUFB(buf,78) = 0; - } + if( p ) + memcpy(WBUFP(buf,30), p->party.name, NAME_LENGTH); + else + WBUFB(buf,30) = 0; + + if( g && ps >= 0 && ps < MAX_GUILDPOSITION ) + { + memcpy(WBUFP(buf,54), g->name,NAME_LENGTH); + memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH); + } + else + { + WBUFB(buf,54) = 0; + WBUFB(buf,78) = 0; + } - // Update nearby clients - clif_send(buf, packet_len(cmd), &ssd->bl, AREA); + // Update nearby clients + clif_send(buf, packet_len(cmd), &ssd->bl, AREA); } @@ -8397,46 +8489,47 @@ void clif_charnameupdate(struct map_session_data *ssd) /// stays that way. void clif_slide(struct block_list *bl, int x, int y) { - unsigned char buf[10]; - nullpo_retv(bl); + unsigned char buf[10]; + nullpo_retv(bl); - WBUFW(buf, 0) = 0x01ff; - WBUFL(buf, 2) = bl->id; - WBUFW(buf, 6) = x; - WBUFW(buf, 8) = y; - clif_send(buf, packet_len(0x1ff), bl, AREA); + WBUFW(buf, 0) = 0x01ff; + WBUFL(buf, 2) = bl->id; + WBUFW(buf, 6) = x; + WBUFW(buf, 8) = y; + clif_send(buf, packet_len(0x1ff), bl, AREA); - if (disguised(bl)) { - WBUFL(buf,2) = -bl->id; - clif_send(buf, packet_len(0x1ff), bl, SELF); - } + if( disguised(bl) ) + { + WBUFL(buf,2) = -bl->id; + clif_send(buf, packet_len(0x1ff), bl, SELF); + } } /*------------------------------------------ * @me command by lordalfa, rewritten implementation by Skotlex *------------------------------------------*/ -void clif_disp_overhead(struct map_session_data *sd, const char *mes) +void clif_disp_overhead(struct map_session_data *sd, const char* mes) { - unsigned char buf[256]; //This should be more than sufficient, the theorical max is CHAT_SIZE + 8 (pads and extra inserted crap) - int len_mes = strlen(mes)+1; //Account for \0 + unsigned char buf[256]; //This should be more than sufficient, the theorical max is CHAT_SIZE + 8 (pads and extra inserted crap) + int len_mes = strlen(mes)+1; //Account for \0 - if (len_mes > sizeof(buf)-8) { - ShowError("clif_disp_overhead: Message too long (length %d)\n", len_mes); - len_mes = sizeof(buf)-8; //Trunk it to avoid problems. - } - // send message to others - WBUFW(buf,0) = 0x8d; - WBUFW(buf,2) = len_mes + 8; // len of message + 8 (command+len+id) - WBUFL(buf,4) = sd->bl.id; - safestrncpy((char *)WBUFP(buf,8), mes, len_mes); - clif_send(buf, WBUFW(buf,2), &sd->bl, AREA_CHAT_WOC); + if (len_mes > sizeof(buf)-8) { + ShowError("clif_disp_overhead: Message too long (length %d)\n", len_mes); + len_mes = sizeof(buf)-8; //Trunk it to avoid problems. + } + // send message to others + WBUFW(buf,0) = 0x8d; + WBUFW(buf,2) = len_mes + 8; // len of message + 8 (command+len+id) + WBUFL(buf,4) = sd->bl.id; + safestrncpy((char*)WBUFP(buf,8), mes, len_mes); + clif_send(buf, WBUFW(buf,2), &sd->bl, AREA_CHAT_WOC); - // send back message to the speaker - WBUFW(buf,0) = 0x8e; - WBUFW(buf, 2) = len_mes + 4; - safestrncpy((char *)WBUFP(buf,4), mes, len_mes); - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + // send back message to the speaker + WBUFW(buf,0) = 0x8e; + WBUFW(buf, 2) = len_mes + 4; + safestrncpy((char*)WBUFP(buf,4), mes, len_mes); + clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); } /*========================== @@ -8445,13 +8538,13 @@ void clif_disp_overhead(struct map_session_data *sd, const char *mes) *--------------------------*/ void clif_party_xy_remove(struct map_session_data *sd) { - unsigned char buf[16]; - nullpo_retv(sd); - WBUFW(buf,0)=0x107; - WBUFL(buf,2)=sd->status.account_id; - WBUFW(buf,6)=-1; - WBUFW(buf,8)=-1; - clif_send(buf,packet_len(0x107),&sd->bl,PARTY_SAMEMAP_WOS); + unsigned char buf[16]; + nullpo_retv(sd); + WBUFW(buf,0)=0x107; + WBUFL(buf,2)=sd->status.account_id; + WBUFW(buf,6)=-1; + WBUFW(buf,8)=-1; + clif_send(buf,packet_len(0x107),&sd->bl,PARTY_SAMEMAP_WOS); } @@ -8472,11 +8565,11 @@ void clif_party_xy_remove(struct map_session_data *sd) /// ? = nothing void clif_gospel_info(struct map_session_data *sd, int type) { - int fd=sd->fd; - WFIFOHEAD(fd,packet_len(0x215)); - WFIFOW(fd,0)=0x215; - WFIFOL(fd,2)=type; - WFIFOSET(fd, packet_len(0x215)); + int fd=sd->fd; + WFIFOHEAD(fd,packet_len(0x215)); + WFIFOW(fd,0)=0x215; + WFIFOL(fd,2)=type; + WFIFOSET(fd, packet_len(0x215)); } @@ -8509,29 +8602,29 @@ void clif_gospel_info(struct map_session_data *sd, int type) /// 22 = [Collector Rank] Target Item : <monster_id used as item id> /// 30 = [Sun, Moon and Stars Angel] Designed places and monsters have been reset. /// 40 = Target HP : <monster_id used as HP> -void clif_starskill(struct map_session_data *sd, const char *mapname, int monster_id, unsigned char star, unsigned char result) +void clif_starskill(struct map_session_data* sd, const char* mapname, int monster_id, unsigned char star, unsigned char result) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x20e)); - WFIFOW(fd,0) = 0x20e; - safestrncpy((char *)WFIFOP(fd,2), mapname, NAME_LENGTH); - WFIFOL(fd,26) = monster_id; - WFIFOB(fd,30) = star; - WFIFOB(fd,31) = result; - WFIFOSET(fd,packet_len(0x20e)); + WFIFOHEAD(fd,packet_len(0x20e)); + WFIFOW(fd,0) = 0x20e; + safestrncpy((char*)WFIFOP(fd,2), mapname, NAME_LENGTH); + WFIFOL(fd,26) = monster_id; + WFIFOB(fd,30) = star; + WFIFOB(fd,31) = result; + WFIFOSET(fd,packet_len(0x20e)); } /*========================================== * Info about Star Glaldiator save map [Komurka] * type: 1: Information, 0: Map registered *------------------------------------------*/ -void clif_feel_info(struct map_session_data *sd, unsigned char feel_level, unsigned char type) +void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsigned char type) { - char mapname[MAP_NAME_LENGTH_EXT]; + char mapname[MAP_NAME_LENGTH_EXT]; - mapindex_getmapname_ext(mapindex_id2name(sd->feel_map[feel_level].index), mapname); - clif_starskill(sd, mapname, 0, feel_level, type ? 1 : 0); + mapindex_getmapname_ext(mapindex_id2name(sd->feel_map[feel_level].index), mapname); + clif_starskill(sd, mapname, 0, feel_level, type ? 1 : 0); } /*========================================== @@ -8540,13 +8633,18 @@ void clif_feel_info(struct map_session_data *sd, unsigned char feel_level, unsig *------------------------------------------*/ void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int class_, unsigned char type) { - if (pcdb_checkid(class_)) { - clif_starskill(sd, job_name(class_), class_, hate_level, type ? 10 : 11); - } else if (mobdb_checkid(class_)) { - clif_starskill(sd, mob_db(class_)->jname, class_, hate_level, type ? 10 : 11); - } else { - ShowWarning("clif_hate_info: Received invalid class %d for this packet (char_id=%d, hate_level=%u, type=%u).\n", class_, sd->status.char_id, (unsigned int)hate_level, (unsigned int)type); - } + if( pcdb_checkid(class_) ) + { + clif_starskill(sd, job_name(class_), class_, hate_level, type ? 10 : 11); + } + else if( mobdb_checkid(class_) ) + { + clif_starskill(sd, mob_db(class_)->jname, class_, hate_level, type ? 10 : 11); + } + else + { + ShowWarning("clif_hate_info: Received invalid class %d for this packet (char_id=%d, hate_level=%u, type=%u).\n", class_, sd->status.char_id, (unsigned int)hate_level, (unsigned int)type); + } } /*========================================== @@ -8554,7 +8652,7 @@ void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int cl *------------------------------------------*/ void clif_mission_info(struct map_session_data *sd, int mob_id, unsigned char progress) { - clif_starskill(sd, mob_db(mob_id)->jname, mob_id, progress, 20); + clif_starskill(sd, mob_db(mob_id)->jname, mob_id, progress, 20); } /*========================================== @@ -8562,7 +8660,7 @@ void clif_mission_info(struct map_session_data *sd, int mob_id, unsigned char pr *------------------------------------------*/ void clif_feel_hate_reset(struct map_session_data *sd) { - clif_starskill(sd, "", 0, 0, 30); + clif_starskill(sd, "", 0, 0, 30); } @@ -8573,17 +8671,17 @@ void clif_feel_hate_reset(struct map_session_data *sd) /// value: /// 0 = disabled /// 1 = enabled -void clif_equiptickack(struct map_session_data *sd, int flag) +void clif_equiptickack(struct map_session_data* sd, int flag) { - int fd; - nullpo_retv(sd); - fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; - WFIFOHEAD(fd, packet_len(0x2d9)); - WFIFOW(fd, 0) = 0x2d9; - WFIFOL(fd, 2) = 0; - WFIFOL(fd, 6) = flag; - WFIFOSET(fd, packet_len(0x2d9)); + WFIFOHEAD(fd, packet_len(0x2d9)); + WFIFOW(fd, 0) = 0x2d9; + WFIFOL(fd, 2) = 0; + WFIFOL(fd, 6) = flag; + WFIFOSET(fd, packet_len(0x2d9)); } @@ -8592,16 +8690,16 @@ void clif_equiptickack(struct map_session_data *sd, int flag) /// open equip window: /// 0 = disabled /// 1 = enabled -void clif_equipcheckbox(struct map_session_data *sd) +void clif_equipcheckbox(struct map_session_data* sd) { - int fd; - nullpo_retv(sd); - fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; - WFIFOHEAD(fd, packet_len(0x2da)); - WFIFOW(fd, 0) = 0x2da; - WFIFOB(fd, 2) = (sd->status.show_equip ? 1 : 0); - WFIFOSET(fd, packet_len(0x2da)); + WFIFOHEAD(fd, packet_len(0x2da)); + WFIFOW(fd, 0) = 0x2da; + WFIFOB(fd, 2) = (sd->status.show_equip ? 1 : 0); + WFIFOSET(fd, packet_len(0x2da)); } @@ -8610,97 +8708,98 @@ void clif_equipcheckbox(struct map_session_data *sd) /// 02d7 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE, PACKETVER >= 20100629) /// 0859 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE2, PACKETVER >= 20101124) /// 0859 <packet len>.W <name>.24B <class>.W <hairstyle>.W <bottom-viewid>.W <mid-viewid>.W <up-viewid>.W <robe>.W <haircolor>.W <cloth-dye>.W <gender>.B {equip item}.28B* (ZC_EQUIPWIN_MICROSCOPE2, PACKETVER >= 20110111) -void clif_viewequip_ack(struct map_session_data *sd, struct map_session_data *tsd) +void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* tsd) { - uint8 *buf; - int i, n, fd, offset = 0; + uint8* buf; + int i, n, fd, offset = 0; #if PACKETVER < 20100629 - const int s = 26; + const int s = 26; #else - const int s = 28; + const int s = 28; #endif - nullpo_retv(sd); - nullpo_retv(tsd); - fd = sd->fd; + nullpo_retv(sd); + nullpo_retv(tsd); + fd = sd->fd; - WFIFOHEAD(fd, MAX_INVENTORY * s + 43); - buf = WFIFOP(fd,0); + WFIFOHEAD(fd, MAX_INVENTORY * s + 43); + buf = WFIFOP(fd,0); #if PACKETVER < 20101124 - WBUFW(buf, 0) = 0x2d7; + WBUFW(buf, 0) = 0x2d7; #else - WBUFW(buf, 0) = 0x859; + WBUFW(buf, 0) = 0x859; #endif - safestrncpy((char *)WBUFP(buf, 4), tsd->status.name, NAME_LENGTH); - WBUFW(buf,28) = tsd->status.class_; - WBUFW(buf,30) = tsd->vd.hair_style; - WBUFW(buf,32) = tsd->vd.head_bottom; - WBUFW(buf,34) = tsd->vd.head_mid; - WBUFW(buf,36) = tsd->vd.head_top; + safestrncpy((char*)WBUFP(buf, 4), tsd->status.name, NAME_LENGTH); + WBUFW(buf,28) = tsd->status.class_; + WBUFW(buf,30) = tsd->vd.hair_style; + WBUFW(buf,32) = tsd->vd.head_bottom; + WBUFW(buf,34) = tsd->vd.head_mid; + WBUFW(buf,36) = tsd->vd.head_top; #if PACKETVER >= 20110111 - WBUFW(buf,38) = tsd->vd.robe; - offset+= 2; - buf = WBUFP(buf,2); + WBUFW(buf,38) = tsd->vd.robe; + offset+= 2; + buf = WBUFP(buf,2); #endif - WBUFW(buf,38) = tsd->vd.hair_color; - WBUFW(buf,40) = tsd->vd.cloth_color; - WBUFB(buf,42) = tsd->vd.sex; - - for (i=0,n=0; i < MAX_INVENTORY; i++) { - if (tsd->status.inventory[i].nameid <= 0 || tsd->inventory_data[i] == NULL) // Item doesn't exist - continue; - if (!itemdb_isequip2(tsd->inventory_data[i])) // Is not equippable - continue; - - // Inventory position - WBUFW(buf, n*s+43) = i + 2; - // Add refine, identify flag, element, etc. - clif_item_sub(WBUFP(buf,0), n*s+45, &tsd->status.inventory[i], tsd->inventory_data[i], pc_equippoint(tsd, i)); - // Add cards - clif_addcards(WBUFP(buf, n*s+55), &tsd->status.inventory[i]); - // Expiration date stuff, if all of those are set to 0 then the client doesn't show anything related (6 bytes) - WBUFL(buf, n*s+63) = tsd->status.inventory[i].expire_time; - WBUFW(buf, n*s+67) = 0; + WBUFW(buf,38) = tsd->vd.hair_color; + WBUFW(buf,40) = tsd->vd.cloth_color; + WBUFB(buf,42) = tsd->vd.sex; + + for(i=0,n=0; i < MAX_INVENTORY; i++) + { + if (tsd->status.inventory[i].nameid <= 0 || tsd->inventory_data[i] == NULL) // Item doesn't exist + continue; + if (!itemdb_isequip2(tsd->inventory_data[i])) // Is not equippable + continue; + + // Inventory position + WBUFW(buf, n*s+43) = i + 2; + // Add refine, identify flag, element, etc. + clif_item_sub(WBUFP(buf,0), n*s+45, &tsd->status.inventory[i], tsd->inventory_data[i], pc_equippoint(tsd, i)); + // Add cards + clif_addcards(WBUFP(buf, n*s+55), &tsd->status.inventory[i]); + // Expiration date stuff, if all of those are set to 0 then the client doesn't show anything related (6 bytes) + WBUFL(buf, n*s+63) = tsd->status.inventory[i].expire_time; + WBUFW(buf, n*s+67) = 0; #if PACKETVER >= 20100629 - if (tsd->inventory_data[i]->equip&EQP_VISIBLE) - WBUFW(buf, n*s+69) = tsd->inventory_data[i]->look; - else - WBUFW(buf, n*s+69) = 0; + if (tsd->inventory_data[i]->equip&EQP_VISIBLE) + WBUFW(buf, n*s+69) = tsd->inventory_data[i]->look; + else + WBUFW(buf, n*s+69) = 0; #endif - n++; - } + n++; + } - WFIFOW(fd, 2) = 43+offset+n*s; // Set length - WFIFOSET(fd, WFIFOW(fd, 2)); + WFIFOW(fd, 2) = 43+offset+n*s; // Set length + WFIFOSET(fd, WFIFOW(fd, 2)); } /// Display msgstringtable.txt string (ZC_MSG). /// 0291 <message>.W -void clif_msg(struct map_session_data *sd, unsigned short id) +void clif_msg(struct map_session_data* sd, unsigned short id) { - int fd; - nullpo_retv(sd); - fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; - WFIFOHEAD(fd, packet_len(0x291)); - WFIFOW(fd, 0) = 0x291; - WFIFOW(fd, 2) = id; // zero-based msgstringtable.txt index - WFIFOSET(fd, packet_len(0x291)); + WFIFOHEAD(fd, packet_len(0x291)); + WFIFOW(fd, 0) = 0x291; + WFIFOW(fd, 2) = id; // zero-based msgstringtable.txt index + WFIFOSET(fd, packet_len(0x291)); } /// Display msgstringtable.txt string and fill in a valid for %d format (ZC_MSG_VALUE). /// 0x7e2 <message>.W <value>.L -void clif_msg_value(struct map_session_data *sd, unsigned short id, int value) +void clif_msg_value(struct map_session_data* sd, unsigned short id, int value) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd, packet_len(0x7e2)); - WFIFOW(fd,0) = 0x7e2; - WFIFOW(fd,2) = id; - WFIFOL(fd,4) = value; - WFIFOSET(fd, packet_len(0x7e2)); + WFIFOHEAD(fd, packet_len(0x7e2)); + WFIFOW(fd,0) = 0x7e2; + WFIFOW(fd,2) = id; + WFIFOL(fd,4) = value; + WFIFOSET(fd, packet_len(0x7e2)); } @@ -8709,22 +8808,22 @@ void clif_msg_value(struct map_session_data *sd, unsigned short id, int value) /// /// NOTE: Message has following format and is printed in color 0xCDCDFF (purple): /// "[SkillName] Message" -void clif_msg_skill(struct map_session_data *sd, unsigned short skill_id, int msg_id) +void clif_msg_skill(struct map_session_data* sd, unsigned short skill_id, int msg_id) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd, packet_len(0x7e6)); - WFIFOW(fd,0) = 0x7e6; - WFIFOW(fd,2) = skill_id; - WFIFOL(fd,4) = msg_id; - WFIFOSET(fd, packet_len(0x7e6)); + WFIFOHEAD(fd, packet_len(0x7e6)); + WFIFOW(fd,0) = 0x7e6; + WFIFOW(fd,2) = skill_id; + WFIFOL(fd,4) = msg_id; + WFIFOSET(fd, packet_len(0x7e6)); } /// View player equip request denied -void clif_viewequip_fail(struct map_session_data *sd) +void clif_viewequip_fail(struct map_session_data* sd) { - clif_msg(sd, 0x54d); + clif_msg(sd, 0x54d); } @@ -8732,92 +8831,95 @@ void clif_viewequip_fail(struct map_session_data *sd) /// Returns true if the packet was parsed successfully. /// Formats: 0 - <packet id>.w <packet len>.w (<name> : <message>).?B 00 /// 1 - <packet id>.w <packet len>.w <name>.24B <message>.?B 00 -static bool clif_process_message(struct map_session_data *sd, int format, char **name_, int *namelen_, char **message_, int *messagelen_) -{ - char *text, *name, *message; - unsigned int packetlen, textlen, namelen, messagelen; - int fd = sd->fd; - - *name_ = NULL; - *namelen_ = 0; - *message_ = NULL; - *messagelen_ = 0; - - packetlen = RFIFOW(fd,2); - // basic structure checks - if (packetlen < 4 + 1) { - // 4-byte header and at least an empty string is expected - ShowWarning("clif_process_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name); - return false; - } - - text = (char *)RFIFOP(fd,4); - textlen = packetlen - 4; - - // process <name> part of the packet - if (format == 0) { - // name and message are separated by ' : ' - // validate name - name = text; - namelen = strnlen(sd->status.name, NAME_LENGTH-1); // name length (w/o zero byte) - - if (strncmp(name, sd->status.name, namelen) || // the text must start with the speaker's name - name[namelen] != ' ' || name[namelen+1] != ':' || name[namelen+2] != ' ') { // followed by ' : ' - //Hacked message, or infamous "client desynch" issue where they pick one char while loading another. - ShowWarning("clif_process_message: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name); - set_eof(fd); // Just kick them out to correct it. - return false; - } - - message = name + namelen + 3; - messagelen = textlen - namelen - 3; // this should be the message length (w/ zero byte included) - } else { - // name has fixed width - if (textlen < NAME_LENGTH + 1) { - ShowWarning("clif_process_message: Received malformed packet from player '%s' (packet length is incorrect)!\n", sd->status.name); - return false; - } - - // validate name - name = text; - namelen = strnlen(name, NAME_LENGTH-1); // name length (w/o zero byte) - - if (name[namelen] != '\0') { - // only restriction is that the name must be zero-terminated - ShowWarning("clif_process_message: Player '%s' sent an unterminated name!\n", sd->status.name); - return false; - } - - message = name + NAME_LENGTH; - messagelen = textlen - NAME_LENGTH; // this should be the message length (w/ zero byte included) - } - - if (messagelen != strnlen(message, messagelen)+1) { - // the declared length must match real length - ShowWarning("clif_process_message: Received malformed packet from player '%s' (length is incorrect)!\n", sd->status.name); - return false; - } - // verify <message> part of the packet - if (message[messagelen-1] != '\0') { - // message must be zero-terminated - ShowWarning("clif_process_message: Player '%s' sent an unterminated message string!\n", sd->status.name); - return false; - } - if (messagelen > CHAT_SIZE_MAX-1) { - // messages mustn't be too long - // Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer. - // Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity. - // Neither the official client nor server place any restriction on the length of the data in the packet, - // but we'll only allow reasonably long strings here. This also makes sure that they fit into the `chatlog` table. - ShowWarning("clif_process_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX-1, message); - return false; - } - - *name_ = name; - *namelen_ = namelen; - *message_ = message; - *messagelen_ = messagelen; - return true; +static bool clif_process_message(struct map_session_data* sd, int format, char** name_, int* namelen_, char** message_, int* messagelen_) +{ + char *text, *name, *message; + unsigned int packetlen, textlen, namelen, messagelen; + int fd = sd->fd; + + *name_ = NULL; + *namelen_ = 0; + *message_ = NULL; + *messagelen_ = 0; + + packetlen = RFIFOW(fd,2); + // basic structure checks + if( packetlen < 4 + 1 ) + { // 4-byte header and at least an empty string is expected + ShowWarning("clif_process_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name); + return false; + } + + text = (char*)RFIFOP(fd,4); + textlen = packetlen - 4; + + // process <name> part of the packet + if( format == 0 ) + {// name and message are separated by ' : ' + // validate name + name = text; + namelen = strnlen(sd->status.name, NAME_LENGTH-1); // name length (w/o zero byte) + + if( strncmp(name, sd->status.name, namelen) || // the text must start with the speaker's name + name[namelen] != ' ' || name[namelen+1] != ':' || name[namelen+2] != ' ' ) // followed by ' : ' + { + //Hacked message, or infamous "client desynch" issue where they pick one char while loading another. + ShowWarning("clif_process_message: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name); + set_eof(fd); // Just kick them out to correct it. + return false; + } + + message = name + namelen + 3; + messagelen = textlen - namelen - 3; // this should be the message length (w/ zero byte included) + } + else + {// name has fixed width + if( textlen < NAME_LENGTH + 1 ) + { + ShowWarning("clif_process_message: Received malformed packet from player '%s' (packet length is incorrect)!\n", sd->status.name); + return false; + } + + // validate name + name = text; + namelen = strnlen(name, NAME_LENGTH-1); // name length (w/o zero byte) + + if( name[namelen] != '\0' ) + { // only restriction is that the name must be zero-terminated + ShowWarning("clif_process_message: Player '%s' sent an unterminated name!\n", sd->status.name); + return false; + } + + message = name + NAME_LENGTH; + messagelen = textlen - NAME_LENGTH; // this should be the message length (w/ zero byte included) + } + + if( messagelen != strnlen(message, messagelen)+1 ) + { // the declared length must match real length + ShowWarning("clif_process_message: Received malformed packet from player '%s' (length is incorrect)!\n", sd->status.name); + return false; + } + // verify <message> part of the packet + if( message[messagelen-1] != '\0' ) + { // message must be zero-terminated + ShowWarning("clif_process_message: Player '%s' sent an unterminated message string!\n", sd->status.name); + return false; + } + if( messagelen > CHAT_SIZE_MAX-1 ) + { // messages mustn't be too long + // Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer. + // Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity. + // Neither the official client nor server place any restriction on the length of the data in the packet, + // but we'll only allow reasonably long strings here. This also makes sure that they fit into the `chatlog` table. + ShowWarning("clif_process_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX-1, message); + return false; + } + + *name_ = name; + *namelen_ = namelen; + *message_ = message; + *messagelen_ = messagelen; + return true; } // --------------------- @@ -8835,62 +8937,62 @@ static bool clif_process_message(struct map_session_data *sd, int format, char * // Only the first 'invalid' error that appears is used. static int clif_guess_PacketVer(int fd, int get_previous, int *error) { - static int err = 1; - static int packet_ver = -1; - int cmd, packet_len, value; //Value is used to temporarily store account/char_id/sex + static int err = 1; + static int packet_ver = -1; + int cmd, packet_len, value; //Value is used to temporarily store account/char_id/sex - if (get_previous) { - //For quick reruns, since the normal code flow is to fetch this once to identify the packet version, then again in the wanttoconnect function. [Skotlex] - if (error) - *error = err; - return packet_ver; - } + if (get_previous) + {//For quick reruns, since the normal code flow is to fetch this once to identify the packet version, then again in the wanttoconnect function. [Skotlex] + if( error ) + *error = err; + return packet_ver; + } - //By default, start searching on the default one. - err = 1; - packet_ver = clif_config.packet_db_ver; - cmd = RFIFOW(fd,0); - packet_len = RFIFOREST(fd); + //By default, start searching on the default one. + err = 1; + packet_ver = clif_config.packet_db_ver; + cmd = RFIFOW(fd,0); + packet_len = RFIFOREST(fd); #define SET_ERROR(n) \ - if( err == 1 )\ - err = n;\ - //define SET_ERROR - - // FIXME: If the packet is not received at once, this will FAIL. - // Figure out, when it happens, that only part of the packet is - // received, or fix the function to be able to deal with that - // case. + if( err == 1 )\ + err = n;\ +//define SET_ERROR + + // FIXME: If the packet is not received at once, this will FAIL. + // Figure out, when it happens, that only part of the packet is + // received, or fix the function to be able to deal with that + // case. #define CHECK_PACKET_VER() \ - if( cmd != clif_config.connect_cmd[packet_ver] || packet_len != packet_db[packet_ver][cmd].len )\ - ;/* not wanttoconnection or wrong length */\ - else if( (value=(int)RFIFOL(fd, packet_db[packet_ver][cmd].pos[0])) < START_ACCOUNT_NUM || value > END_ACCOUNT_NUM )\ - { SET_ERROR(2); }/* invalid account_id */\ - else if( (value=(int)RFIFOL(fd, packet_db[packet_ver][cmd].pos[1])) <= 0 )\ - { SET_ERROR(3); }/* invalid char_id */\ - /* RFIFOL(fd, packet_db[packet_ver][cmd].pos[2]) - don't care about login_id1 */\ - /* RFIFOL(fd, packet_db[packet_ver][cmd].pos[3]) - don't care about client_tick */\ - else if( (value=(int)RFIFOB(fd, packet_db[packet_ver][cmd].pos[4])) != 0 && value != 1 )\ - { SET_ERROR(6); }/* invalid sex */\ - else\ - {\ - err = 0;\ - if( error )\ - *error = 0;\ - return packet_ver;\ - }\ - //define CHECK_PACKET_VER - - CHECK_PACKET_VER();//Default packet version found. - - for (packet_ver = MAX_PACKET_VER; packet_ver > 0; packet_ver--) { - //Start guessing the version, giving priority to the newer ones. [Skotlex] - CHECK_PACKET_VER(); - } - if (error) - *error = err; - packet_ver = -1; - return -1; + if( cmd != clif_config.connect_cmd[packet_ver] || packet_len != packet_db[packet_ver][cmd].len )\ + ;/* not wanttoconnection or wrong length */\ + else if( (value=(int)RFIFOL(fd, packet_db[packet_ver][cmd].pos[0])) < START_ACCOUNT_NUM || value > END_ACCOUNT_NUM )\ + { SET_ERROR(2); }/* invalid account_id */\ + else if( (value=(int)RFIFOL(fd, packet_db[packet_ver][cmd].pos[1])) <= 0 )\ + { SET_ERROR(3); }/* invalid char_id */\ + /* RFIFOL(fd, packet_db[packet_ver][cmd].pos[2]) - don't care about login_id1 */\ + /* RFIFOL(fd, packet_db[packet_ver][cmd].pos[3]) - don't care about client_tick */\ + else if( (value=(int)RFIFOB(fd, packet_db[packet_ver][cmd].pos[4])) != 0 && value != 1 )\ + { SET_ERROR(6); }/* invalid sex */\ + else\ + {\ + err = 0;\ + if( error )\ + *error = 0;\ + return packet_ver;\ + }\ +//define CHECK_PACKET_VER + + CHECK_PACKET_VER();//Default packet version found. + + for (packet_ver = MAX_PACKET_VER; packet_ver > 0; packet_ver--) + { //Start guessing the version, giving priority to the newer ones. [Skotlex] + CHECK_PACKET_VER(); + } + if( error ) + *error = err; + packet_ver = -1; + return -1; #undef SET_ERROR #undef CHECK_PACKET_VER } @@ -8905,86 +9007,87 @@ static int clif_guess_PacketVer(int fd, int get_previous, int *error) /// 0072 <account id>.L <char id>.L <auth code>.L <client time>.L <gender>.B (CZ_ENTER) /// 0436 <account id>.L <char id>.L <auth code>.L <client time>.L <gender>.B (CZ_ENTER2) /// There are various variants of this packet, some of them have padding between fields. -void clif_parse_WantToConnection(int fd, TBL_PC *sd) -{ - struct block_list *bl; - struct auth_node *node; - int cmd, account_id, char_id, login_id1, sex; - unsigned int client_tick; //The client tick is a tick, therefore it needs be unsigned. [Skotlex] - 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]) - - if (sd) { - ShowError("clif_parse_WantToConnection : invalid request (character already logged in)\n"); - return; - } - - // Only valid packet version get here - packet_ver = clif_guess_PacketVer(fd, 1, NULL); - - cmd = RFIFOW(fd,0); - account_id = RFIFOL(fd, packet_db[packet_ver][cmd].pos[0]); - char_id = RFIFOL(fd, packet_db[packet_ver][cmd].pos[1]); - login_id1 = RFIFOL(fd, packet_db[packet_ver][cmd].pos[2]); - client_tick = RFIFOL(fd, packet_db[packet_ver][cmd].pos[3]); - sex = RFIFOB(fd, packet_db[packet_ver][cmd].pos[4]); - - if (packet_ver < 5 || // reject really old client versions - (packet_ver <= 9 && (battle_config.packet_ver_flag & 1) == 0) || // older than 6sept04 - (packet_ver > 9 && (battle_config.packet_ver_flag & 1<<(packet_ver-9)) == 0)) { // version not allowed - // packet version rejected - ShowInfo("Rejected connection attempt, forbidden packet version (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"', Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%s"CL_RESET"').\n", account_id, char_id, packet_ver, ip2str(session[fd]->client_addr, NULL)); - WFIFOHEAD(fd,packet_len(0x6a)); - WFIFOW(fd,0) = 0x6a; - WFIFOB(fd,2) = 5; // Your Game's EXE file is not the latest version - WFIFOSET(fd,packet_len(0x6a)); - set_eof(fd); - return; - } - - if (runflag != MAPSERVER_ST_RUNNING) { - // not allowed - clif_authfail_fd(fd,1);// server closed - return; - } - - //Check for double login. - bl = map_id2bl(account_id); - if (bl && bl->type != BL_PC) { - ShowError("clif_parse_WantToConnection: a non-player object already has id %d, please increase the starting account number\n", account_id); - WFIFOHEAD(fd,packet_len(0x6a)); - WFIFOW(fd,0) = 0x6a; - WFIFOB(fd,2) = 3; // Rejected by server - WFIFOSET(fd,packet_len(0x6a)); - set_eof(fd); - return; - } - - if (bl || - ((node=chrif_search(account_id)) && //An already existing node is valid only if it is for this login. - !(node->account_id == account_id && node->char_id == char_id && node->state == ST_LOGIN))) { - clif_authfail_fd(fd, 8); //Still recognizes last connection - return; - } - - CREATE(sd, TBL_PC, 1); - sd->fd = fd; - sd->packet_ver = packet_ver; - session[fd]->session_data = sd; - - pc_setnewpc(sd, account_id, char_id, login_id1, client_tick, sex, fd); +void clif_parse_WantToConnection(int fd, TBL_PC* sd) +{ + struct block_list* bl; + struct auth_node* node; + int cmd, account_id, char_id, login_id1, sex; + unsigned int client_tick; //The client tick is a tick, therefore it needs be unsigned. [Skotlex] + 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]) + + if (sd) { + ShowError("clif_parse_WantToConnection : invalid request (character already logged in)\n"); + return; + } + + // Only valid packet version get here + packet_ver = clif_guess_PacketVer(fd, 1, NULL); + + cmd = RFIFOW(fd,0); + account_id = RFIFOL(fd, packet_db[packet_ver][cmd].pos[0]); + char_id = RFIFOL(fd, packet_db[packet_ver][cmd].pos[1]); + login_id1 = RFIFOL(fd, packet_db[packet_ver][cmd].pos[2]); + client_tick = RFIFOL(fd, packet_db[packet_ver][cmd].pos[3]); + sex = RFIFOB(fd, packet_db[packet_ver][cmd].pos[4]); + + if( packet_ver < 5 || // reject really old client versions + (packet_ver <= 9 && (battle_config.packet_ver_flag & 1) == 0) || // older than 6sept04 + (packet_ver > 9 && (battle_config.packet_ver_flag & 1<<(packet_ver-9)) == 0)) // version not allowed + {// packet version rejected + ShowInfo("Rejected connection attempt, forbidden packet version (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"', Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%s"CL_RESET"').\n", account_id, char_id, packet_ver, ip2str(session[fd]->client_addr, NULL)); + WFIFOHEAD(fd,packet_len(0x6a)); + WFIFOW(fd,0) = 0x6a; + WFIFOB(fd,2) = 5; // Your Game's EXE file is not the latest version + WFIFOSET(fd,packet_len(0x6a)); + set_eof(fd); + return; + } + + if( runflag != MAPSERVER_ST_RUNNING ) + {// not allowed + clif_authfail_fd(fd,1);// server closed + return; + } + + //Check for double login. + bl = map_id2bl(account_id); + if(bl && bl->type != BL_PC) { + ShowError("clif_parse_WantToConnection: a non-player object already has id %d, please increase the starting account number\n", account_id); + WFIFOHEAD(fd,packet_len(0x6a)); + WFIFOW(fd,0) = 0x6a; + WFIFOB(fd,2) = 3; // Rejected by server + WFIFOSET(fd,packet_len(0x6a)); + set_eof(fd); + return; + } + + if (bl || + ((node=chrif_search(account_id)) && //An already existing node is valid only if it is for this login. + !(node->account_id == account_id && node->char_id == char_id && node->state == ST_LOGIN))) + { + clif_authfail_fd(fd, 8); //Still recognizes last connection + return; + } + + CREATE(sd, TBL_PC, 1); + sd->fd = fd; + sd->packet_ver = packet_ver; + session[fd]->session_data = sd; + + pc_setnewpc(sd, account_id, char_id, login_id1, client_tick, sex, fd); #if PACKETVER < 20070521 - WFIFOHEAD(fd,4); - WFIFOL(fd,0) = sd->bl.id; - WFIFOSET(fd,4); + WFIFOHEAD(fd,4); + WFIFOL(fd,0) = sd->bl.id; + WFIFOSET(fd,4); #else - WFIFOHEAD(fd,packet_len(0x283)); - WFIFOW(fd,0) = 0x283; - WFIFOL(fd,2) = sd->bl.id; - WFIFOSET(fd,packet_len(0x283)); + WFIFOHEAD(fd,packet_len(0x283)); + WFIFOW(fd,0) = 0x283; + WFIFOL(fd,2) = sd->bl.id; + WFIFOSET(fd,packet_len(0x283)); #endif - chrif_authreq(sd); + chrif_authreq(sd); } @@ -8992,325 +9095,332 @@ void clif_parse_WantToConnection(int fd, TBL_PC *sd) /// 007d void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) { - if (sd->bl.prev != NULL) - return; + if(sd->bl.prev != NULL) + return; - if (!sd->state.active) { - //Character loading is not complete yet! - //Let pc_reg_received reinvoke this when ready. - sd->state.connect_new = 0; - return; - } + if (!sd->state.active) + { //Character loading is not complete yet! + //Let pc_reg_received reinvoke this when ready. + sd->state.connect_new = 0; + return; + } - if (sd->state.rewarp) { - //Rewarp player. - sd->state.rewarp = 0; - clif_changemap(sd, sd->mapindex, sd->bl.x, sd->bl.y); - return; - } + if (sd->state.rewarp) + { //Rewarp player. + sd->state.rewarp = 0; + clif_changemap(sd, sd->mapindex, sd->bl.x, sd->bl.y); + return; + } - sd->state.warping = 0; + sd->state.warping = 0; - // look + // look #if PACKETVER < 4 - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); - clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); + 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); + clif_changelook(&sd->bl,LOOK_WEAPON,0); #endif - if (sd->vd.cloth_color) - clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); - - // item - clif_inventorylist(sd); // inventory list first, otherwise deleted items in pc_checkitem show up as 'unknown item' - pc_checkitem(sd); - - // cart - if (pc_iscarton(sd)) { - clif_cartlist(sd); - clif_updatestatus(sd,SP_CARTINFO); - } - - // weight - clif_updatestatus(sd,SP_WEIGHT); - clif_updatestatus(sd,SP_MAXWEIGHT); - - // guild - // (needs to go before clif_spawn() to show guild emblems correctly) - if (sd->status.guild_id) - guild_send_memberinfoshort(sd,1); - - if (battle_config.pc_invincible_time > 0) { - if (map_flag_gvg(sd->bl.m)) - pc_setinvincibletimer(sd,battle_config.pc_invincible_time<<1); - else - pc_setinvincibletimer(sd,battle_config.pc_invincible_time); - } - - if (map[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs) - map_spawnmobs(sd->bl.m); - if (!(sd->sc.option&OPTION_INVISIBLE)) { - // increment the number of pvp players on the map - map[sd->bl.m].users_pvp++; - } - if (map[sd->bl.m].instance_id) { - instance[map[sd->bl.m].instance_id].users++; - instance_check_idle(map[sd->bl.m].instance_id); - } - sd->state.debug_remove_map = 0; // temporary state to track double remove_map's [FlavioJS] - - // reset the callshop flag if the player changes map - sd->state.callshop = 0; - - map_addblock(&sd->bl); - clif_spawn(&sd->bl); - - // Party - // (needs to go after clif_spawn() to show hp bars correctly) - if (sd->status.party_id) { - party_send_movemap(sd); - clif_party_hp(sd); // Show hp after displacement [LuzZza] - } - - if (sd->bg_id) clif_bg_hp(sd); // BattleGround System - - if (map[sd->bl.m].flag.pvp && !(sd->sc.option&OPTION_INVISIBLE)) { - if (!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris] - if (!map[sd->bl.m].flag.pvp_nocalcrank) - sd->pvp_timer = add_timer(gettick()+200, pc_calc_pvprank_timer, sd->bl.id, 0); - sd->pvp_rank = 0; - sd->pvp_lastusers = 0; - sd->pvp_point = 5; - sd->pvp_won = 0; - sd->pvp_lost = 0; - } - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - } else - // set flag, if it's a duel [LuzZza] - if (sd->duel_group) - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - - if (map[sd->bl.m].flag.gvg_dungeon) - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); //TODO: Figure out the real packet to send here. - - if (map_flag_gvg(sd->bl.m)) - clif_map_property(sd, MAPPROPERTY_AGITZONE); - - // info about nearby objects - // must use foreachinarea (CIRCULAR_AREA interferes with foreachinrange) - 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, BL_ALL, sd); - - // pet - if (sd->pd) { - if (battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m)) { - //Return the pet to egg. [Skotlex] - clif_displaymessage(sd->fd, msg_txt(666)); - pet_menu(sd, 3); //Option 3 is return to egg. - } else { - map_addblock(&sd->pd->bl); - clif_spawn(&sd->pd->bl); - clif_send_petdata(sd,sd->pd,0,0); - clif_send_petstatus(sd); - // skill_unit_move(&sd->pd->bl,gettick(),1); - } - } - - //homunculus [blackhole89] - if (merc_is_hom_active(sd->hd)) { - map_addblock(&sd->hd->bl); - clif_spawn(&sd->hd->bl); - clif_send_homdata(sd,SP_ACK,0); - clif_hominfo(sd,sd->hd,1); - clif_hominfo(sd,sd->hd,0); //for some reason, at least older clients want this sent twice - clif_homskillinfoblock(sd); - if (battle_config.hom_setting&0x8) - status_calc_bl(&sd->hd->bl, SCB_SPEED); //Homunc mimic their master's speed on each map change - if (!(battle_config.hom_setting&0x2)) - skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately - } - - if (sd->md) { - map_addblock(&sd->md->bl); - clif_spawn(&sd->md->bl); - clif_mercenary_info(sd); - clif_mercenary_skillblock(sd); - status_calc_bl(&sd->md->bl, SCB_SPEED); //Mercenary mimic their master's speed on each map change - } - - if (sd->ed) { - map_addblock(&sd->ed->bl); - clif_spawn(&sd->ed->bl); - clif_elemental_info(sd); - clif_elemental_updatestatus(sd,SP_HP); - clif_hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.matk_max); - clif_elemental_updatestatus(sd,SP_SP); - status_calc_bl(&sd->ed->bl, SCB_SPEED); //Elemental mimic their master's speed on each map change - } - - if (sd->state.connect_new) { - int lv; - sd->state.connect_new = 0; - clif_skillinfoblock(sd); - clif_hotkeys_send(sd); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_NEXTBASEEXP); - clif_updatestatus(sd,SP_JOBEXP); - clif_updatestatus(sd,SP_NEXTJOBEXP); - clif_updatestatus(sd,SP_SKILLPOINT); - clif_initialstatus(sd); - - if (sd->sc.option&OPTION_FALCON) - clif_status_load(&sd->bl, SI_FALCON, 1); - - if (sd->sc.option&OPTION_RIDING) - clif_status_load(&sd->bl, SI_RIDING, 1); - else if (sd->sc.option&OPTION_WUGRIDER) - clif_status_load(&sd->bl, SI_WUGRIDER, 1); - - if (sd->status.manner < 0) - sc_start(&sd->bl,SC_NOCHAT,100,0,0); - - //Auron reported that This skill only triggers when you logon on the map o.O [Skotlex] - if ((lv = pc_checkskill(sd,SG_KNOWLEDGE)) > 0) { - if (sd->bl.m == sd->feel_map[0].m - || sd->bl.m == sd->feel_map[1].m - || sd->bl.m == sd->feel_map[2].m) - sc_start(&sd->bl, SC_KNOWLEDGE, 100, lv, skill_get_time(SG_KNOWLEDGE, lv)); - } - - if (sd->pd && sd->pd->pet.intimate > 900) - clif_pet_emotion(sd->pd,(sd->pd->pet.class_ - 100)*100 + 50 + pet_hungry_val(sd->pd)); - - if (merc_is_hom_active(sd->hd)) - merc_hom_init_timers(sd->hd); - - if (night_flag && map[sd->bl.m].flag.nightenabled) { - sd->state.night = 1; - clif_status_load(&sd->bl, SI_NIGHT, 1); - } - - // Notify everyone that this char logged in [Skotlex]. - map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1); - - //Login Event - npc_script_event(sd, NPCE_LOGIN); - } else { - //For some reason the client "loses" these on warp/map-change. - clif_updatestatus(sd,SP_STR); - clif_updatestatus(sd,SP_AGI); - clif_updatestatus(sd,SP_VIT); - clif_updatestatus(sd,SP_INT); - clif_updatestatus(sd,SP_DEX); - clif_updatestatus(sd,SP_LUK); - - // abort currently running script - sd->state.using_fake_npc = 0; - sd->state.menu_or_input = 0; - sd->npc_menu = 0; - - if (sd->npc_id) - npc_event_dequeue(sd); - } - - if (sd->state.changemap) { - // restore information that gets lost on map-change + if(sd->vd.cloth_color) + clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); + + // item + clif_inventorylist(sd); // inventory list first, otherwise deleted items in pc_checkitem show up as 'unknown item' + pc_checkitem(sd); + + // cart + if(pc_iscarton(sd)) { + clif_cartlist(sd); + clif_updatestatus(sd,SP_CARTINFO); + } + + // weight + clif_updatestatus(sd,SP_WEIGHT); + clif_updatestatus(sd,SP_MAXWEIGHT); + + // guild + // (needs to go before clif_spawn() to show guild emblems correctly) + if(sd->status.guild_id) + guild_send_memberinfoshort(sd,1); + + if(battle_config.pc_invincible_time > 0) { + if(map_flag_gvg(sd->bl.m)) + pc_setinvincibletimer(sd,battle_config.pc_invincible_time<<1); + else + pc_setinvincibletimer(sd,battle_config.pc_invincible_time); + } + + if( map[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs ) + map_spawnmobs(sd->bl.m); + if( !(sd->sc.option&OPTION_INVISIBLE) ) + {// increment the number of pvp players on the map + map[sd->bl.m].users_pvp++; + } + if( map[sd->bl.m].instance_id ) + { + instance[map[sd->bl.m].instance_id].users++; + instance_check_idle(map[sd->bl.m].instance_id); + } + sd->state.debug_remove_map = 0; // temporary state to track double remove_map's [FlavioJS] + + // reset the callshop flag if the player changes map + sd->state.callshop = 0; + + map_addblock(&sd->bl); + clif_spawn(&sd->bl); + + // Party + // (needs to go after clif_spawn() to show hp bars correctly) + if(sd->status.party_id) { + party_send_movemap(sd); + clif_party_hp(sd); // Show hp after displacement [LuzZza] + } + + if( sd->bg_id ) clif_bg_hp(sd); // BattleGround System + + if(map[sd->bl.m].flag.pvp && !(sd->sc.option&OPTION_INVISIBLE)) { + if(!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris] + if (!map[sd->bl.m].flag.pvp_nocalcrank) + sd->pvp_timer = add_timer(gettick()+200, pc_calc_pvprank_timer, sd->bl.id, 0); + sd->pvp_rank = 0; + sd->pvp_lastusers = 0; + sd->pvp_point = 5; + sd->pvp_won = 0; + sd->pvp_lost = 0; + } + clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); + } else + // set flag, if it's a duel [LuzZza] + if(sd->duel_group) + clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); + + if (map[sd->bl.m].flag.gvg_dungeon) + clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); //TODO: Figure out the real packet to send here. + + if( map_flag_gvg(sd->bl.m) ) + clif_map_property(sd, MAPPROPERTY_AGITZONE); + + // info about nearby objects + // must use foreachinarea (CIRCULAR_AREA interferes with foreachinrange) + 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, BL_ALL, sd); + + // pet + if( sd->pd ) + { + if( battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m) ) + { //Return the pet to egg. [Skotlex] + clif_displaymessage(sd->fd, msg_txt(666)); + pet_menu(sd, 3); //Option 3 is return to egg. + } + else + { + map_addblock(&sd->pd->bl); + clif_spawn(&sd->pd->bl); + clif_send_petdata(sd,sd->pd,0,0); + clif_send_petstatus(sd); +// skill_unit_move(&sd->pd->bl,gettick(),1); + } + } + + //homunculus [blackhole89] + if( merc_is_hom_active(sd->hd) ) + { + map_addblock(&sd->hd->bl); + clif_spawn(&sd->hd->bl); + clif_send_homdata(sd,SP_ACK,0); + clif_hominfo(sd,sd->hd,1); + clif_hominfo(sd,sd->hd,0); //for some reason, at least older clients want this sent twice + clif_homskillinfoblock(sd); + if( battle_config.hom_setting&0x8 ) + status_calc_bl(&sd->hd->bl, SCB_SPEED); //Homunc mimic their master's speed on each map change + if( !(battle_config.hom_setting&0x2) ) + skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately + } + + if( sd->md ) { + map_addblock(&sd->md->bl); + clif_spawn(&sd->md->bl); + clif_mercenary_info(sd); + clif_mercenary_skillblock(sd); + } + + if( sd->ed ) { + map_addblock(&sd->ed->bl); + clif_spawn(&sd->ed->bl); + clif_elemental_info(sd); + clif_elemental_updatestatus(sd,SP_HP); + clif_hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.matk_max); + clif_elemental_updatestatus(sd,SP_SP); + } + + if(sd->state.connect_new) { + int lv; + sd->state.connect_new = 0; + clif_skillinfoblock(sd); + clif_hotkeys_send(sd); + clif_updatestatus(sd,SP_BASEEXP); + clif_updatestatus(sd,SP_NEXTBASEEXP); + clif_updatestatus(sd,SP_JOBEXP); + clif_updatestatus(sd,SP_NEXTJOBEXP); + clif_updatestatus(sd,SP_SKILLPOINT); + clif_initialstatus(sd); + + if (sd->sc.option&OPTION_FALCON) + clif_status_load(&sd->bl, SI_FALCON, 1); + + if (sd->sc.option&OPTION_RIDING) + clif_status_load(&sd->bl, SI_RIDING, 1); + else if (sd->sc.option&OPTION_WUGRIDER) + clif_status_load(&sd->bl, SI_WUGRIDER, 1); + + if(sd->status.manner < 0) + sc_start(&sd->bl,SC_NOCHAT,100,0,0); + + //Auron reported that This skill only triggers when you logon on the map o.O [Skotlex] + if ((lv = pc_checkskill(sd,SG_KNOWLEDGE)) > 0) { + if(sd->bl.m == sd->feel_map[0].m + || sd->bl.m == sd->feel_map[1].m + || sd->bl.m == sd->feel_map[2].m) + sc_start(&sd->bl, SC_KNOWLEDGE, 100, lv, skill_get_time(SG_KNOWLEDGE, lv)); + } + + if(sd->pd && sd->pd->pet.intimate > 900) + clif_pet_emotion(sd->pd,(sd->pd->pet.class_ - 100)*100 + 50 + pet_hungry_val(sd->pd)); + + if(merc_is_hom_active(sd->hd)) + merc_hom_init_timers(sd->hd); + + if (night_flag && map[sd->bl.m].flag.nightenabled) { + sd->state.night = 1; + clif_status_load(&sd->bl, SI_NIGHT, 1); + } + + // Notify everyone that this char logged in [Skotlex]. + map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1); + + //Login Event + npc_script_event(sd, NPCE_LOGIN); + } else { + //For some reason the client "loses" these on warp/map-change. + clif_updatestatus(sd,SP_STR); + clif_updatestatus(sd,SP_AGI); + clif_updatestatus(sd,SP_VIT); + clif_updatestatus(sd,SP_INT); + clif_updatestatus(sd,SP_DEX); + clif_updatestatus(sd,SP_LUK); + + // abort currently running script + sd->state.using_fake_npc = 0; + sd->state.menu_or_input = 0; + sd->npc_menu = 0; + + if(sd->npc_id) + npc_event_dequeue(sd); + } + + if( sd->state.changemap ) + {// restore information that gets lost on map-change #if PACKETVER >= 20070918 - clif_partyinvitationstate(sd); - clif_equipcheckbox(sd); + clif_partyinvitationstate(sd); + clif_equipcheckbox(sd); #endif - if ((battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100) && - (map_flag_gvg(sd->state.pmap) || map_flag_gvg(sd->bl.m) || map[sd->state.pmap].flag.battleground || map[sd->bl.m].flag.battleground)) - status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty - - if (night_flag && map[sd->bl.m].flag.nightenabled) { - //Display night. - if (!sd->state.night) { - sd->state.night = 1; - clif_status_load(&sd->bl, SI_NIGHT, 1); - } - } else if (sd->state.night) { - //Clear night display. - sd->state.night = 0; - clif_status_load(&sd->bl, SI_NIGHT, 0); - } - - if (map[sd->bl.m].flag.battleground) { - clif_map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode - if (map[sd->bl.m].flag.battleground == 2) - clif_bg_updatescore_single(sd); - } - - if (map[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m)) { - char output[128]; - sprintf(output, "[ Kill Steal Protection Disable. KS is allowed in this map ]"); - clif_broadcast(&sd->bl, output, strlen(output) + 1, 0x10, SELF); - } - - map_iwall_get(sd); // Updates Walls Info on this Map to Client - sd->state.changemap = false; - } - - mail_clear(sd); - - /* Guild Aura Init */ - if (sd->state.gmaster_flag) { - guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->state.gmaster_flag,GD_LEADERSHIP)); - guild_guildaura_refresh(sd,GD_GLORYWOUNDS,guild_checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS)); - guild_guildaura_refresh(sd,GD_SOULCOLD,guild_checkskill(sd->state.gmaster_flag,GD_SOULCOLD)); - guild_guildaura_refresh(sd,GD_HAWKEYES,guild_checkskill(sd->state.gmaster_flag,GD_HAWKEYES)); - } - - if (sd->state.vending) { /* show we have a vending */ - clif_openvending(sd,sd->bl.id,sd->vending); - clif_showvendingboard(&sd->bl,sd->message,0); - } - - if (map[sd->bl.m].flag.loadevent) // Lance - npc_script_event(sd, NPCE_LOADMAP); - - if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) - clif_status_load(&sd->bl, SI_DEVIL, 1); //blindness [Komurka] - - if (sd->sc.opt2) //Client loses these on warp. - clif_changeoption(&sd->bl); - - clif_weather_check(sd); - - // For automatic triggering of NPCs after map loading (so you don't need to walk 1 step first) - 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; - - /* it broke at some point (e.g. during a crash), so we make it visibly dead again. */ - if (!sd->status.hp && !pc_isdead(sd) && status_isdead(&sd->bl)) - pc_setdead(sd); - - // If player is dead, and is spawned (such as @refresh) send death packet. [Valaris] - if (pc_isdead(sd)) - clif_clearunit_area(&sd->bl, CLR_DEAD); - else { - skill_usave_trigger(sd); - clif_changed_dir(&sd->bl, SELF); - } - - // Trigger skill effects if you appear standing on them - if (!battle_config.pc_invincible_time) - skill_unit_move(&sd->bl,gettick(),1); + if( (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100) && + (map_flag_gvg(sd->state.pmap) || map_flag_gvg(sd->bl.m) || map[sd->state.pmap].flag.battleground || map[sd->bl.m].flag.battleground) ) + status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty + + if( night_flag && map[sd->bl.m].flag.nightenabled ) + { //Display night. + if( !sd->state.night ) + { + sd->state.night = 1; + clif_status_load(&sd->bl, SI_NIGHT, 1); + } + } + else if( sd->state.night ) + { //Clear night display. + sd->state.night = 0; + clif_status_load(&sd->bl, SI_NIGHT, 0); + } + + if( map[sd->bl.m].flag.battleground ) + { + clif_map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode + if( map[sd->bl.m].flag.battleground == 2 ) + clif_bg_updatescore_single(sd); + } + + if( map[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) ) + { + char output[128]; + sprintf(output, "[ Kill Steal Protection Disable. KS is allowed in this map ]"); + clif_broadcast(&sd->bl, output, strlen(output) + 1, 0x10, SELF); + } + + map_iwall_get(sd); // Updates Walls Info on this Map to Client + sd->state.changemap = false; + } + + mail_clear(sd); + + /* Guild Aura Init */ + if( sd->state.gmaster_flag ) { + guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->state.gmaster_flag,GD_LEADERSHIP)); + guild_guildaura_refresh(sd,GD_GLORYWOUNDS,guild_checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS)); + guild_guildaura_refresh(sd,GD_SOULCOLD,guild_checkskill(sd->state.gmaster_flag,GD_SOULCOLD)); + guild_guildaura_refresh(sd,GD_HAWKEYES,guild_checkskill(sd->state.gmaster_flag,GD_HAWKEYES)); + } + + if( sd->state.vending ) { /* show we have a vending */ + clif_openvending(sd,sd->bl.id,sd->vending); + clif_showvendingboard(&sd->bl,sd->message,0); + } + + if(map[sd->bl.m].flag.loadevent) // Lance + npc_script_event(sd, NPCE_LOADMAP); + + if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) + clif_status_load(&sd->bl, SI_DEVIL, 1); //blindness [Komurka] + + if (sd->sc.opt2) //Client loses these on warp. + clif_changeoption(&sd->bl); + + clif_weather_check(sd); + + // For automatic triggering of NPCs after map loading (so you don't need to walk 1 step first) + 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; + + /* it broke at some point (e.g. during a crash), so we make it visibly dead again. */ + if( !sd->status.hp && !pc_isdead(sd) && status_isdead(&sd->bl) ) + pc_setdead(sd); + + // If player is dead, and is spawned (such as @refresh) send death packet. [Valaris] + if(pc_isdead(sd)) + clif_clearunit_area(&sd->bl, CLR_DEAD); + else { + skill_usave_trigger(sd); + clif_changed_dir(&sd->bl, SELF); + } + +// Trigger skill effects if you appear standing on them + if(!battle_config.pc_invincible_time) + skill_unit_move(&sd->bl,gettick(),1); } /// Server's tick (ZC_NOTIFY_TIME). /// 007f <time>.L -void clif_notify_time(struct map_session_data *sd, unsigned long time) +void clif_notify_time(struct map_session_data* sd, unsigned long time) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x7f)); - WFIFOW(fd,0) = 0x7f; - WFIFOL(fd,2) = time; - WFIFOSET(fd,packet_len(0x7f)); + WFIFOHEAD(fd,packet_len(0x7f)); + WFIFOW(fd,0) = 0x7f; + WFIFOL(fd,2) = time; + WFIFOSET(fd,packet_len(0x7f)); } @@ -9320,9 +9430,9 @@ void clif_notify_time(struct map_session_data *sd, unsigned long time) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_TickSend(int fd, struct map_session_data *sd) { - sd->client_tick = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + sd->client_tick = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - clif_notify_time(sd, gettick()); + clif_notify_time(sd, gettick()); } @@ -9330,85 +9440,83 @@ void clif_parse_TickSend(int fd, struct map_session_data *sd) /// 02b9 { <is skill>.B <id>.L <count>.W }*27 (ZC_SHORTCUT_KEY_LIST) /// 07d9 { <is skill>.B <id>.L <count>.W }*36 (ZC_SHORTCUT_KEY_LIST_V2, PACKETVER >= 20090603) /// 07d9 { <is skill>.B <id>.L <count>.W }*38 (ZC_SHORTCUT_KEY_LIST_V2, PACKETVER >= 20090617) -void clif_hotkeys_send(struct map_session_data *sd) -{ +void clif_hotkeys_send(struct map_session_data *sd) { #ifdef HOTKEY_SAVING - const int fd = sd->fd; - int i; + const int fd = sd->fd; + int i; #if PACKETVER < 20090603 - const int cmd = 0x2b9; + const int cmd = 0x2b9; #else - const int cmd = 0x7d9; + const int cmd = 0x7d9; #endif - if (!fd) return; - WFIFOHEAD(fd, 2+MAX_HOTKEYS*7); - WFIFOW(fd, 0) = cmd; - for (i = 0; i < MAX_HOTKEYS; i++) { - WFIFOB(fd, 2 + 0 + i * 7) = sd->status.hotkeys[i].type; // type: 0: item, 1: skill - WFIFOL(fd, 2 + 1 + i * 7) = sd->status.hotkeys[i].id; // item or skill ID - WFIFOW(fd, 2 + 5 + i * 7) = sd->status.hotkeys[i].lv; // skill level - } - WFIFOSET(fd, packet_len(cmd)); + if (!fd) return; + WFIFOHEAD(fd, 2+MAX_HOTKEYS*7); + WFIFOW(fd, 0) = cmd; + for(i = 0; i < MAX_HOTKEYS; i++) { + WFIFOB(fd, 2 + 0 + i * 7) = sd->status.hotkeys[i].type; // type: 0: item, 1: skill + WFIFOL(fd, 2 + 1 + i * 7) = sd->status.hotkeys[i].id; // item or skill ID + WFIFOW(fd, 2 + 5 + i * 7) = sd->status.hotkeys[i].lv; // skill level + } + WFIFOSET(fd, packet_len(cmd)); #endif } /// Request to update a position on the hotkey bar (CZ_SHORTCUT_KEY_CHANGE). /// 02ba <index>.W <is skill>.B <id>.L <count>.W -void clif_parse_Hotkey(int fd, struct map_session_data *sd) -{ +void clif_parse_Hotkey(int fd, struct map_session_data *sd) { #ifdef HOTKEY_SAVING - unsigned short idx; - int cmd; + unsigned short idx; + int cmd; - cmd = RFIFOW(fd, 0); - idx = RFIFOW(fd, packet_db[sd->packet_ver][cmd].pos[0]); - if (idx >= MAX_HOTKEYS) return; + cmd = RFIFOW(fd, 0); + idx = RFIFOW(fd, packet_db[sd->packet_ver][cmd].pos[0]); + if (idx >= MAX_HOTKEYS) return; - sd->status.hotkeys[idx].type = RFIFOB(fd, packet_db[sd->packet_ver][cmd].pos[1]); - sd->status.hotkeys[idx].id = RFIFOL(fd, packet_db[sd->packet_ver][cmd].pos[2]); - sd->status.hotkeys[idx].lv = RFIFOW(fd, packet_db[sd->packet_ver][cmd].pos[3]); + sd->status.hotkeys[idx].type = RFIFOB(fd, packet_db[sd->packet_ver][cmd].pos[1]); + sd->status.hotkeys[idx].id = RFIFOL(fd, packet_db[sd->packet_ver][cmd].pos[2]); + sd->status.hotkeys[idx].lv = RFIFOW(fd, packet_db[sd->packet_ver][cmd].pos[3]); #endif } /// Displays cast-like progress bar (ZC_PROGRESS). /// 02f0 <color>.L <time>.L -void clif_progressbar(struct map_session_data *sd, unsigned long color, unsigned int second) +void clif_progressbar(struct map_session_data * sd, unsigned long color, unsigned int second) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x2f0)); - WFIFOW(fd,0) = 0x2f0; - WFIFOL(fd,2) = color; - WFIFOL(fd,6) = second; - WFIFOSET(fd,packet_len(0x2f0)); + WFIFOHEAD(fd,packet_len(0x2f0)); + WFIFOW(fd,0) = 0x2f0; + WFIFOL(fd,2) = color; + WFIFOL(fd,6) = second; + WFIFOSET(fd,packet_len(0x2f0)); } /// Removes an ongoing progress bar (ZC_PROGRESS_CANCEL). /// 02f2 -void clif_progressbar_abort(struct map_session_data *sd) +void clif_progressbar_abort(struct map_session_data * sd) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x2f2)); - WFIFOW(fd,0) = 0x2f2; - WFIFOSET(fd,packet_len(0x2f2)); + WFIFOHEAD(fd,packet_len(0x2f2)); + WFIFOW(fd,0) = 0x2f2; + WFIFOSET(fd,packet_len(0x2f2)); } /// Notification from the client, that the progress bar has reached 100% (CZ_PROGRESS). /// 02f1 -void clif_parse_progressbar(int fd, struct map_session_data *sd) +void clif_parse_progressbar(int fd, struct map_session_data * sd) { - int npc_id = sd->progressbar.npc_id; + int npc_id = sd->progressbar.npc_id; - if (gettick() < sd->progressbar.timeout && sd->st) - sd->st->state = END; + if( gettick() < sd->progressbar.timeout && sd->st ) + sd->st->state = END; - sd->progressbar.npc_id = sd->progressbar.timeout = 0; - npc_scriptcont(sd, npc_id); + sd->progressbar.npc_id = sd->progressbar.timeout = 0; + npc_scriptcont(sd, npc_id); } @@ -9418,31 +9526,31 @@ void clif_parse_progressbar(int fd, struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_WalkToXY(int fd, struct map_session_data *sd) { - short x, y; + short x, y; - if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl, CLR_DEAD); - return; - } + if (pc_isdead(sd)) { + clif_clearunit_area(&sd->bl, CLR_DEAD); + return; + } - if (sd->sc.opt1 && (sd->sc.opt1 == OPT1_STONEWAIT || sd->sc.opt1 == OPT1_BURNING)) - ; //You CAN walk on this OPT1 value. - else if (sd->progressbar.npc_id) - clif_progressbar_abort(sd); - else if (pc_cant_act(sd)) - return; + if (sd->sc.opt1 && ( sd->sc.opt1 == OPT1_STONEWAIT || sd->sc.opt1 == OPT1_BURNING )) + ; //You CAN walk on this OPT1 value. + else if( sd->progressbar.npc_id ) + clif_progressbar_abort(sd); + else if (pc_cant_act(sd)) + return; - if (sd->sc.data[SC_RUN] || sd->sc.data[SC_WUGDASH]) - return; + if(sd->sc.data[SC_RUN] || sd->sc.data[SC_WUGDASH]) + return; - pc_delinvincibletimer(sd); + pc_delinvincibletimer(sd); - RFIFOPOS(fd, packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0], &x, &y, NULL); + RFIFOPOS(fd, packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0], &x, &y, NULL); - //Set last idle time... [Skotlex] - sd->idletime = last_tick; + //Set last idle time... [Skotlex] + sd->idletime = last_tick; - unit_walktoxy(&sd->bl, x, y, 4); + unit_walktoxy(&sd->bl, x, y, 4); } @@ -9452,14 +9560,14 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) /// 0 = disconnect (quit) /// 1 = cannot disconnect (wait 10 seconds) /// ? = ignored -void clif_disconnect_ack(struct map_session_data *sd, short result) +void clif_disconnect_ack(struct map_session_data* sd, short result) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x18b)); - WFIFOW(fd,0) = 0x18b; - WFIFOW(fd,2) = result; - WFIFOSET(fd,packet_len(0x18b)); + WFIFOHEAD(fd,packet_len(0x18b)); + WFIFOW(fd,0) = 0x18b; + WFIFOW(fd,2) = result; + WFIFOSET(fd,packet_len(0x18b)); } @@ -9469,14 +9577,15 @@ void clif_disconnect_ack(struct map_session_data *sd, short result) /// 0 = quit void clif_parse_QuitGame(int fd, struct map_session_data *sd) { - /* Rovert's prevent logout option fixed [Valaris] */ - if (!sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && - (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout)) { - set_eof(fd); - clif_disconnect_ack(sd, 0); - } else { - clif_disconnect_ack(sd, 1); - } + /* Rovert's prevent logout option fixed [Valaris] */ + if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && + (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) ) + { + set_eof(fd); + clif_disconnect_ack(sd, 0); + } else { + clif_disconnect_ack(sd, 1); + } } @@ -9486,106 +9595,106 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) { - int id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - struct block_list *bl; - //struct status_change *sc; - - if (id < 0 && -id == sd->bl.id) // for disguises [Valaris] - id = sd->bl.id; - - bl = map_id2bl(id); - if (bl == NULL) - return; // Lagged clients could request names of already gone mobs/players. [Skotlex] - - if (sd->bl.m != bl->m || !check_distance_bl(&sd->bl, bl, AREA_SIZE)) - return; // Block namerequests past view range - - // 'see people in GM hide' cheat detection - /* disabled due to false positives (network lag + request name of char that's about to hide = race condition) - sc = status_get_sc(bl); - if (sc && sc->option&OPTION_INVISIBLE && !disguised(bl) && - bl->type != BL_NPC && //Skip hidden NPCs which can be seen using Maya Purple - pc_get_group_level(sd) < battle_config.hack_info_GM_level - ) { - char gm_msg[256]; - sprintf(gm_msg, "Hack on NameRequest: character '%s' (account: %d) requested the name of an invisible target (id: %d).\n", sd->status.name, sd->status.account_id, id); - ShowWarning(gm_msg); - // information is sent to all online GMs - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, gm_msg); - return; - } - */ + int id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + struct block_list* bl; + //struct status_change *sc; - clif_charnameack(fd, bl); -} + if( id < 0 && -id == sd->bl.id ) // for disguises [Valaris] + id = sd->bl.id; + bl = map_id2bl(id); + if( bl == NULL ) + return; // Lagged clients could request names of already gone mobs/players. [Skotlex] -/// Validates and processes global messages -/// 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT) -/// There are various variants of this packet. -void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) -{ - const char *text = (char *)RFIFOP(fd,4); - int textlen = RFIFOW(fd,2) - 4; - - char *name, *message, *fakename = NULL; - int namelen, messagelen; + if( sd->bl.m != bl->m || !check_distance_bl(&sd->bl, bl, AREA_SIZE) ) + return; // Block namerequests past view range - bool is_fake; + // 'see people in GM hide' cheat detection + /* disabled due to false positives (network lag + request name of char that's about to hide = race condition) + sc = status_get_sc(bl); + if (sc && sc->option&OPTION_INVISIBLE && !disguised(bl) && + bl->type != BL_NPC && //Skip hidden NPCs which can be seen using Maya Purple + pc_get_group_level(sd) < battle_config.hack_info_GM_level + ) { + char gm_msg[256]; + sprintf(gm_msg, "Hack on NameRequest: character '%s' (account: %d) requested the name of an invisible target (id: %d).\n", sd->status.name, sd->status.account_id, id); + ShowWarning(gm_msg); + // information is sent to all online GMs + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, gm_msg); + return; + } + */ - // validate packet and retrieve name and message - if (!clif_process_message(sd, 0, &name, &namelen, &message, &messagelen)) - return; - - if (is_atcommand(fd, sd, message, 1)) - return; + clif_charnameack(fd, bl); +} - if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) - return; - if (battle_config.min_chat_delay) { - //[Skotlex] - if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) - return; - sd->cantalk_tick = gettick() + battle_config.min_chat_delay; - } - /** - * Fake Name Design by FatalEror (bug report #9) - **/ - if ((is_fake = (sd->fakename[0]))) { - fakename = (char *) aMalloc(strlen(sd->fakename)+messagelen+3); - strcpy(fakename, sd->fakename); - strcat(fakename, " : "); - strcat(fakename, message); - textlen = strlen(fakename) + 1; - } - // send message to others (using the send buffer for temp. storage) - WFIFOHEAD(fd, 8 + textlen); - WFIFOW(fd,0) = 0x8d; - WFIFOW(fd,2) = 8 + textlen; - WFIFOL(fd,4) = sd->bl.id; - safestrncpy((char *)WFIFOP(fd,8), is_fake ? fakename : text, textlen); - //FIXME: chat has range of 9 only - clif_send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, sd->chatID ? CHAT_WOS : AREA_CHAT_WOC); - - // send back message to the speaker - if (is_fake) { - WFIFOW(fd,0) = 0x8e; - WFIFOW(fd,2) = textlen + 4; - safestrncpy((char *)WFIFOP(fd,4), fakename, textlen); - aFree(fakename); - } else { - memcpy(WFIFOP(fd,0), RFIFOP(fd,0), RFIFOW(fd,2)); - WFIFOW(fd,0) = 0x8e; - } - WFIFOSET(fd, WFIFOW(fd,2)); +/// Validates and processes global messages +/// 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT) +/// There are various variants of this packet. +void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) +{ + const char* text = (char*)RFIFOP(fd,4); + int textlen = RFIFOW(fd,2) - 4; + + char *name, *message, *fakename = NULL; + int namelen, messagelen; + + bool is_fake; + + // validate packet and retrieve name and message + if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) ) + return; + + if( is_atcommand(fd, sd, message, 1) ) + return; + + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + return; + + if( battle_config.min_chat_delay ) + { //[Skotlex] + if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) + return; + sd->cantalk_tick = gettick() + battle_config.min_chat_delay; + } + /** + * Fake Name Design by FatalEror (bug report #9) + **/ + if( ( is_fake = ( sd->fakename[0] ) ) ) { + fakename = (char*) aMalloc(strlen(sd->fakename)+messagelen+3); + strcpy(fakename, sd->fakename); + strcat(fakename, " : "); + strcat(fakename, message); + textlen = strlen(fakename) + 1; + } + // send message to others (using the send buffer for temp. storage) + WFIFOHEAD(fd, 8 + textlen); + WFIFOW(fd,0) = 0x8d; + WFIFOW(fd,2) = 8 + textlen; + WFIFOL(fd,4) = sd->bl.id; + safestrncpy((char*)WFIFOP(fd,8), is_fake ? fakename : text, textlen); + //FIXME: chat has range of 9 only + clif_send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, sd->chatID ? CHAT_WOS : AREA_CHAT_WOC); + + // send back message to the speaker + if( is_fake ) { + WFIFOW(fd,0) = 0x8e; + WFIFOW(fd,2) = textlen + 4; + safestrncpy((char*)WFIFOP(fd,4), fakename, textlen); + aFree(fakename); + } else { + memcpy(WFIFOP(fd,0), RFIFOP(fd,0), RFIFOW(fd,2)); + WFIFOW(fd,0) = 0x8e; + } + WFIFOSET(fd, WFIFOW(fd,2)); #ifdef PCRE_SUPPORT - // trigger listening npcs - map_foreachinrange(npc_chat_sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl); + // trigger listening npcs + map_foreachinrange(npc_chat_sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl); #endif - // Chat logging type 'O' / Global Chat - log_chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message); + // Chat logging type 'O' / Global Chat + log_chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message); } @@ -9594,13 +9703,13 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) /// 0140 <map name>.16B <x>.W <y>.W void clif_parse_MapMove(int fd, struct map_session_data *sd) { - char command[MAP_NAME_LENGTH_EXT+25]; - char *map_name; + char command[MAP_NAME_LENGTH_EXT+25]; + char* map_name; - map_name = (char *)RFIFOP(fd,2); - map_name[MAP_NAME_LENGTH_EXT-1]='\0'; - sprintf(command, "%cmapmove %s %d %d", atcommand_symbol, map_name, RFIFOW(fd,18), RFIFOW(fd,20)); - is_atcommand(fd, sd, command, 1); + map_name = (char*)RFIFOP(fd,2); + map_name[MAP_NAME_LENGTH_EXT-1]='\0'; + sprintf(command, "%cmapmove %s %d %d", atcommand_symbol, map_name, RFIFOW(fd,18), RFIFOW(fd,20)); + is_atcommand(fd, sd, command, 1); } @@ -9621,20 +9730,20 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd) /// 7 = northeast void clif_changed_dir(struct block_list *bl, enum send_target target) { - unsigned char buf[64]; + unsigned char buf[64]; - WBUFW(buf,0) = 0x9c; - WBUFL(buf,2) = bl->id; - WBUFW(buf,6) = bl->type==BL_PC?((TBL_PC *)bl)->head_dir:0; - WBUFB(buf,8) = unit_getdir(bl); + WBUFW(buf,0) = 0x9c; + WBUFL(buf,2) = bl->id; + WBUFW(buf,6) = bl->type==BL_PC?((TBL_PC*)bl)->head_dir:0; + WBUFB(buf,8) = unit_getdir(bl); - clif_send(buf, packet_len(0x9c), bl, target); + clif_send(buf, packet_len(0x9c), bl, target); - if (disguised(bl)) { - WBUFL(buf,2) = -bl->id; - WBUFW(buf,6) = 0; - clif_send(buf, packet_len(0x9c), bl, SELF); - } + if (disguised(bl)) { + WBUFL(buf,2) = -bl->id; + WBUFW(buf,6) = 0; + clif_send(buf, packet_len(0x9c), bl, SELF); + } } @@ -9644,13 +9753,13 @@ void clif_changed_dir(struct block_list *bl, enum send_target target) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_ChangeDir(int fd, struct map_session_data *sd) { - unsigned char headdir, dir; + unsigned char headdir, dir; - headdir = RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - dir = RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); - pc_setdir(sd, dir, headdir); + headdir = RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + dir = RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); + pc_setdir(sd, dir, headdir); - clif_changed_dir(&sd->bl, AREA_WOS); + clif_changed_dir(&sd->bl, AREA_WOS); } @@ -9660,42 +9769,42 @@ void clif_parse_ChangeDir(int fd, struct map_session_data *sd) /// @see enum emotion_type void clif_parse_Emotion(int fd, struct map_session_data *sd) { - int emoticon = RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + int emoticon = RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 2) { - if (emoticon == E_MUTE) {// prevent use of the mute emote [Valaris] - clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); - return; - } - // fix flood of emotion icon (ro-proxy): flood only the hacker player - if (sd->emotionlasttime + 1 >= time(NULL)) { // not more than 1 per second - sd->emotionlasttime = time(NULL); - clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); - return; - } - sd->emotionlasttime = time(NULL); + if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 2) { + if (emoticon == E_MUTE) {// prevent use of the mute emote [Valaris] + clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); + return; + } + // fix flood of emotion icon (ro-proxy): flood only the hacker player + if (sd->emotionlasttime + 1 >= time(NULL)) { // not more than 1 per second + sd->emotionlasttime = time(NULL); + clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); + return; + } + sd->emotionlasttime = time(NULL); - if (battle_config.client_reshuffle_dice && emoticon>=E_DICE1 && emoticon<=E_DICE6) { - // re-roll dice - emoticon = rnd()%6+E_DICE1; - } + if(battle_config.client_reshuffle_dice && emoticon>=E_DICE1 && emoticon<=E_DICE6) + {// re-roll dice + emoticon = rnd()%6+E_DICE1; + } - clif_emotion(&sd->bl, emoticon); - } else - clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); + clif_emotion(&sd->bl, emoticon); + } else + clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); } /// Amount of currently online players, reply to /w /who (ZC_USER_COUNT). /// 00c2 <count>.L -void clif_user_count(struct map_session_data *sd, int count) +void clif_user_count(struct map_session_data* sd, int count) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xc2)); - WFIFOW(fd,0) = 0xc2; - WFIFOL(fd,2) = count; - WFIFOSET(fd,packet_len(0xc2)); + WFIFOHEAD(fd,packet_len(0xc2)); + WFIFOW(fd,0) = 0xc2; + WFIFOL(fd,2) = count; + WFIFOSET(fd,packet_len(0xc2)); } @@ -9704,92 +9813,93 @@ void clif_user_count(struct map_session_data *sd, int count) /// 00c1 void clif_parse_HowManyConnections(int fd, struct map_session_data *sd) { - clif_user_count(sd, map_getusers()); + clif_user_count(sd, map_getusers()); } void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, unsigned int tick) { - if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl, CLR_DEAD); - return; - } - - if (sd->sc.count && - (sd->sc.data[SC_TRICKDEAD] || - sd->sc.data[SC_AUTOCOUNTER] || - sd->sc.data[SC_BLADESTOP] || - sd->sc.data[SC__MANHOLE] || - sd->sc.data[SC_CURSEDCIRCLE_ATKER] || - sd->sc.data[SC_CURSEDCIRCLE_TARGET])) - return; - - pc_stop_walking(sd, 1); - pc_stop_attack(sd); - - if (target_id<0 && -target_id == sd->bl.id) // for disguises [Valaris] - target_id = sd->bl.id; - - switch (action_type) { - case 0x00: // once attack - case 0x07: // continuous attack - - if (pc_cant_act(sd) || sd->sc.option&OPTION_HIDE) - return; - - if (sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER)) - return; - - if (sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM]) - return; - - if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) { - if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { - clif_skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0); - return; - } - } - - pc_delinvincibletimer(sd); - sd->idletime = last_tick; - unit_attack(&sd->bl, target_id, action_type != 0); - break; - case 0x02: // sitdown - if (battle_config.basic_skill_check && pc_checkskill(sd, NV_BASIC) < 3) { - clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 2); - break; - } - - if (pc_issit(sd)) { - //Bugged client? Just refresh them. - clif_sitting(&sd->bl); - return; - } - - if (sd->ud.skilltimer != INVALID_TIMER || (sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING)) - break; - - if (sd->sc.count && ( - sd->sc.data[SC_DANCING] || - (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) - )) //No sitting during these states either. - break; - - pc_setsit(sd); - skill_sit(sd,1); - clif_sitting(&sd->bl); - break; - case 0x03: // standup - if (!pc_issit(sd)) { - //Bugged client? Just refresh them. - clif_standing(&sd->bl); - return; - } - pc_setstand(sd); - skill_sit(sd,0); - clif_standing(&sd->bl); - break; - } + if (pc_isdead(sd)) { + clif_clearunit_area(&sd->bl, CLR_DEAD); + return; + } + + if (sd->sc.count && + (sd->sc.data[SC_TRICKDEAD] || + sd->sc.data[SC_AUTOCOUNTER] || + sd->sc.data[SC_BLADESTOP] || + sd->sc.data[SC__MANHOLE] || + sd->sc.data[SC_CURSEDCIRCLE_ATKER] || + sd->sc.data[SC_CURSEDCIRCLE_TARGET] )) + return; + + pc_stop_walking(sd, 1); + pc_stop_attack(sd); + + if(target_id<0 && -target_id == sd->bl.id) // for disguises [Valaris] + target_id = sd->bl.id; + + switch(action_type) + { + case 0x00: // once attack + case 0x07: // continuous attack + + if( pc_cant_act(sd) || sd->sc.option&OPTION_HIDE ) + return; + + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER) ) + return; + + if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] ) + return; + + if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) { + if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { + clif_skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0); + return; + } + } + + pc_delinvincibletimer(sd); + sd->idletime = last_tick; + unit_attack(&sd->bl, target_id, action_type != 0); + break; + case 0x02: // sitdown + if (battle_config.basic_skill_check && pc_checkskill(sd, NV_BASIC) < 3) { + clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 2); + break; + } + + if(pc_issit(sd)) { + //Bugged client? Just refresh them. + clif_sitting(&sd->bl); + return; + } + + if (sd->ud.skilltimer != INVALID_TIMER || (sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING )) + break; + + if (sd->sc.count && ( + sd->sc.data[SC_DANCING] || + (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) + )) //No sitting during these states either. + break; + + pc_setsit(sd); + skill_sit(sd,1); + clif_sitting(&sd->bl); + break; + case 0x03: // standup + if (!pc_issit(sd)) { + //Bugged client? Just refresh them. + clif_standing(&sd->bl); + return; + } + pc_setstand(sd); + skill_sit(sd,0); + clif_standing(&sd->bl); + break; + } } @@ -9806,11 +9916,11 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, /// There are various variants of this packet, some of them have padding between fields. void clif_parse_ActionRequest(int fd, struct map_session_data *sd) { - clif_parse_ActionRequest_sub(sd, - RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]), - RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), - gettick() - ); + clif_parse_ActionRequest_sub(sd, + RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]), + RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), + gettick() + ); } @@ -9821,162 +9931,162 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) /// 1 = char-select (disconnect) void clif_parse_Restart(int fd, struct map_session_data *sd) { - switch (RFIFOB(fd,2)) { - case 0x00: - pc_respawn(sd,CLR_RESPAWN); - break; - case 0x01: - /* Rovert's Prevent logout option - Fixed [Valaris] */ - if (!sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && - (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout)) { - //Send to char-server for character selection. - chrif_charselectreq(sd, session[fd]->client_addr); - } else { - clif_disconnect_ack(sd, 1); - } - break; - } + switch(RFIFOB(fd,2)) { + case 0x00: + pc_respawn(sd,CLR_RESPAWN); + break; + case 0x01: + /* Rovert's Prevent logout option - Fixed [Valaris] */ + if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && + (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) ) + { //Send to char-server for character selection. + chrif_charselectreq(sd, session[fd]->client_addr); + } else { + clif_disconnect_ack(sd, 1); + } + break; + } } /// Validates and processes whispered messages (CZ_WHISPER). /// 0096 <packet len>.W <nick>.24B <message>.?B -void clif_parse_WisMessage(int fd, struct map_session_data *sd) -{ - struct map_session_data *dstsd; - int i; - - char *target, *message; - int namelen, messagelen; - - // validate packet and retrieve name and message - if (!clif_process_message(sd, 1, &target, &namelen, &message, &messagelen)) - return; - - if (is_atcommand(fd, sd, message, 1)) - return; - - if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) - return; - - if (battle_config.min_chat_delay) { //[Skotlex] - if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) { - return; - } - sd->cantalk_tick = gettick() + battle_config.min_chat_delay; - } - - // Chat logging type 'W' / Whisper - log_chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message); - - //-------------------------------------------------------// - // Lordalfa - Paperboy - To whisper NPC commands // - //-------------------------------------------------------// - if (target[0] && (strncasecmp(target,"NPC:",4) == 0) && (strlen(target) > 4)) { - char *str = target+4; //Skip the NPC: string part. - struct npc_data *npc; - if ((npc = npc_name2id(str))) { - char split_data[NUM_WHISPER_VAR][CHAT_SIZE_MAX]; - char *split; - char output[256]; - - str = message; - // skip codepage indicator, if detected - if (str[0] == '|' && strlen(str) >= 4) - str += 3; - for (i = 0; i < NUM_WHISPER_VAR; ++i) { // Splits the message using '#' as separators - split = strchr(str,'#'); - if (split == NULL) { // use the remaining string - safestrncpy(split_data[i], str, ARRAYLENGTH(split_data[i])); - for (++i; i < NUM_WHISPER_VAR; ++i) - split_data[i][0] = '\0'; - break; - } - *split = '\0'; - safestrncpy(split_data[i], str, ARRAYLENGTH(split_data[i])); - str = split+1; - } - - for (i = 0; i < NUM_WHISPER_VAR; ++i) { - sprintf(output, "@whispervar%d$", i); - set_var(sd,output,(char *) split_data[i]); - } - - sprintf(output, "%s::OnWhisperGlobal", npc->exname); - npc_event(sd,output,0); // Calls the NPC label - - return; - } - } else if (strcmpi(target, main_chat_nick) == 0) { // Main chat [LuzZza] - if (!sd->state.mainchat) - clif_displaymessage(fd, msg_txt(388)); // You should enable main chat with "@main on" command. - else { - // send the main message using inter-server system - intif_main_message(sd, message); - } - - return; - } - - // searching destination character - dstsd = map_nick2sd(target); - - if (dstsd == NULL || strcmp(dstsd->status.name, target) != 0) { - // player is not on this map-server - // 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). - intif_wis_message(sd, target, message, messagelen); - return; - } - - // if player ignores everyone - if (dstsd->state.ignoreAll) { - if (dstsd->sc.option & OPTION_INVISIBLE && pc_get_group_level(sd) < pc_get_group_level(dstsd)) - clif_wis_end(fd, 1); // 1: target character is not loged in - else - clif_wis_end(fd, 3); // 3: everyone ignored by target - return; - } - - // if player is autotrading - if (dstsd->state.autotrade == 1) { - char output[256]; - sprintf(output, "%s is in autotrade mode and cannot receive whispered messages.", dstsd->status.name); - clif_wis_message(fd, wisp_server_name, output, strlen(output) + 1); - return; - } - - // if player ignores the source character - ARR_FIND(0, MAX_IGNORE_LIST, i, dstsd->ignore[i].name[0] == '\0' || strcmp(dstsd->ignore[i].name, sd->status.name) == 0); - if (i < MAX_IGNORE_LIST && dstsd->ignore[i].name[0] != '\0') { // source char present in ignore list - clif_wis_end(fd, 2); // 2: ignored by target - return; - } - - // notify sender of success - clif_wis_end(fd, 0); // 0: success to send wisper - - // Normal message - clif_wis_message(dstsd->fd, sd->status.name, message, messagelen); +void clif_parse_WisMessage(int fd, struct map_session_data* sd) +{ + struct map_session_data* dstsd; + int i; + + char *target, *message; + int namelen, messagelen; + + // validate packet and retrieve name and message + if( !clif_process_message(sd, 1, &target, &namelen, &message, &messagelen) ) + return; + + if ( is_atcommand(fd, sd, message, 1) ) + return; + + if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) + return; + + if (battle_config.min_chat_delay) { //[Skotlex] + if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) { + return; + } + sd->cantalk_tick = gettick() + battle_config.min_chat_delay; + } + + // Chat logging type 'W' / Whisper + log_chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message); + + //-------------------------------------------------------// + // Lordalfa - Paperboy - To whisper NPC commands // + //-------------------------------------------------------// + if (target[0] && (strncasecmp(target,"NPC:",4) == 0) && (strlen(target) > 4)) + { + char* str = target+4; //Skip the NPC: string part. + struct npc_data* npc; + if ((npc = npc_name2id(str))) { + char split_data[NUM_WHISPER_VAR][CHAT_SIZE_MAX]; + char *split; + char output[256]; + + str = message; + // skip codepage indicator, if detected + if( str[0] == '|' && strlen(str) >= 4 ) + str += 3; + for( i = 0; i < NUM_WHISPER_VAR; ++i ) {// Splits the message using '#' as separators + split = strchr(str,'#'); + if( split == NULL ) { // use the remaining string + safestrncpy(split_data[i], str, ARRAYLENGTH(split_data[i])); + for( ++i; i < NUM_WHISPER_VAR; ++i ) + split_data[i][0] = '\0'; + break; + } + *split = '\0'; + safestrncpy(split_data[i], str, ARRAYLENGTH(split_data[i])); + str = split+1; + } + + for( i = 0; i < NUM_WHISPER_VAR; ++i ) { + sprintf(output, "@whispervar%d$", i); + set_var(sd,output,(char *) split_data[i]); + } + + sprintf(output, "%s::OnWhisperGlobal", npc->exname); + npc_event(sd,output,0); // Calls the NPC label + + return; + } + } else if(strcmpi(target, main_chat_nick) == 0) { // Main chat [LuzZza] + if(!sd->state.mainchat) + clif_displaymessage(fd, msg_txt(388)); // You should enable main chat with "@main on" command. + else { + // send the main message using inter-server system + intif_main_message( sd, message ); + } + + return; + } + + // searching destination character + dstsd = map_nick2sd(target); + + if (dstsd == NULL || strcmp(dstsd->status.name, target) != 0) { + // player is not on this map-server + // 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). + intif_wis_message(sd, target, message, messagelen); + return; + } + + // if player ignores everyone + if (dstsd->state.ignoreAll) { + if (dstsd->sc.option & OPTION_INVISIBLE && pc_get_group_level(sd) < pc_get_group_level(dstsd)) + clif_wis_end(fd, 1); // 1: target character is not loged in + else + clif_wis_end(fd, 3); // 3: everyone ignored by target + return; + } + + // if player is autotrading + if( dstsd->state.autotrade == 1 ) { + char output[256]; + sprintf(output, "%s is in autotrade mode and cannot receive whispered messages.", dstsd->status.name); + clif_wis_message(fd, wisp_server_name, output, strlen(output) + 1); + return; + } + + // if player ignores the source character + ARR_FIND(0, MAX_IGNORE_LIST, i, dstsd->ignore[i].name[0] == '\0' || strcmp(dstsd->ignore[i].name, sd->status.name) == 0); + if(i < MAX_IGNORE_LIST && dstsd->ignore[i].name[0] != '\0') { // source char present in ignore list + clif_wis_end(fd, 2); // 2: ignored by target + return; + } + + // notify sender of success + clif_wis_end(fd, 0); // 0: success to send wisper + + // Normal message + clif_wis_message(dstsd->fd, sd->status.name, message, messagelen); } /// /b /nb (CZ_BROADCAST). /// Request to broadcast a message on whole server. /// 0099 <packet len>.W <text>.?B 00 -void clif_parse_Broadcast(int fd, struct map_session_data *sd) -{ - char command[CHAT_SIZE_MAX+11]; - char *msg = (char *)RFIFOP(fd,4); - unsigned int len = RFIFOW(fd,2)-4; +void clif_parse_Broadcast(int fd, struct map_session_data* sd) { + char command[CHAT_SIZE_MAX+11]; + char* msg = (char*)RFIFOP(fd,4); + unsigned int len = RFIFOW(fd,2)-4; - // as the length varies depending on the command used, just block unreasonably long strings - mes_len_check(msg, len, CHAT_SIZE_MAX); + // as the length varies depending on the command used, just block unreasonably long strings + mes_len_check(msg, len, CHAT_SIZE_MAX); - sprintf(command, "%ckami %s", atcommand_symbol, msg); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%ckami %s", atcommand_symbol, msg); + is_atcommand(fd, sd, command, 1); } @@ -9986,35 +10096,35 @@ void clif_parse_Broadcast(int fd, struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_TakeItem(int fd, struct map_session_data *sd) { - struct flooritem_data *fitem; - int map_object_id; + struct flooritem_data *fitem; + int map_object_id; - map_object_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + map_object_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - fitem = (struct flooritem_data *)map_id2bl(map_object_id); + fitem = (struct flooritem_data*)map_id2bl(map_object_id); - do { - if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl, CLR_DEAD); - break; - } + do { + if (pc_isdead(sd)) { + clif_clearunit_area(&sd->bl, CLR_DEAD); + break; + } - if (fitem == NULL || fitem->bl.type != BL_ITEM || fitem->bl.m != sd->bl.m) - break; + if (fitem == NULL || fitem->bl.type != BL_ITEM || fitem->bl.m != sd->bl.m) + break; - if (sd->sc.cant.pickup) - break; + if( sd->sc.cant.pickup ) + break; - if (pc_cant_act(sd)) - break; + if (pc_cant_act(sd)) + break; - if (!pc_takeitem(sd, fitem)) - break; + if (!pc_takeitem(sd, fitem)) + break; - return; - } while (0); - // Client REQUIRES a fail packet or you can no longer pick items. - clif_additem(sd,0,0,6); + return; + } while (0); + // Client REQUIRES a fail packet or you can no longer pick items. + clif_additem(sd,0,0,6); } @@ -10024,31 +10134,31 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_DropItem(int fd, struct map_session_data *sd) { - int item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; - int item_amount = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); + int item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; + int item_amount = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); - for (;;) { - if (pc_isdead(sd)) - break; + for(;;) { + if (pc_isdead(sd)) + break; - if (pc_cant_act(sd)) - break; + if (pc_cant_act(sd)) + break; - if (sd->sc.count && ( - sd->sc.data[SC_AUTOCOUNTER] || - sd->sc.data[SC_BLADESTOP] || - (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) - )) - break; + if (sd->sc.count && ( + sd->sc.data[SC_AUTOCOUNTER] || + sd->sc.data[SC_BLADESTOP] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) + )) + break; - if (!pc_dropitem(sd, item_index, item_amount)) - break; + if (!pc_dropitem(sd, item_index, item_amount)) + break; - return; - } + return; + } - //Because the client does not like being ignored. - clif_dropitem(sd, item_index,0); + //Because the client does not like being ignored. + clif_dropitem(sd, item_index,0); } @@ -10058,28 +10168,29 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_UseItem(int fd, struct map_session_data *sd) { - int n; + int n; - if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl, CLR_DEAD); - return; - } + if (pc_isdead(sd)) { + clif_clearunit_area(&sd->bl, CLR_DEAD); + return; + } - //This flag enables you to use items while in an NPC. [Skotlex] - if (sd->npc_id) { - if (sd->npc_id != sd->npc_item_flag) - return; - } else if (pc_istrading(sd)) - return; + //This flag enables you to use items while in an NPC. [Skotlex] + if (sd->npc_id) { + if (sd->npc_id != sd->npc_item_flag) + return; + } + else if (pc_istrading(sd)) + return; - //Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex] - sd->idletime = last_tick; - n = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; + //Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex] + sd->idletime = last_tick; + n = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; - if (n <0 || n >= MAX_INVENTORY) - return; - if (!pc_useitem(sd,n)) - clif_useitemack(sd,n,0,false); //Send an empty ack packet or the client gets stuck. + if(n <0 || n >= MAX_INVENTORY) + return; + if (!pc_useitem(sd,n)) + clif_useitemack(sd,n,0,false); //Send an empty ack packet or the client gets stuck. } @@ -10087,42 +10198,42 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) /// 00a9 <index>.W <position>.W void clif_parse_EquipItem(int fd,struct map_session_data *sd) { - int index; + int index; - if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl,CLR_DEAD); - return; - } - index = RFIFOW(fd,2)-2; - if (index < 0 || index >= MAX_INVENTORY) - return; //Out of bounds check. + if(pc_isdead(sd)) { + clif_clearunit_area(&sd->bl,CLR_DEAD); + return; + } + index = RFIFOW(fd,2)-2; + if (index < 0 || index >= MAX_INVENTORY) + return; //Out of bounds check. - if (sd->npc_id) { - if (sd->npc_id != sd->npc_item_flag) - return; - } else if (sd->state.storage_flag || sd->sc.opt1) - ; //You can equip/unequip stuff while storage is open/under status changes - else if (pc_cant_act(sd)) - return; - - if (!sd->status.inventory[index].identify) { - clif_equipitemack(sd,index,0,0); // fail - return; - } + if(sd->npc_id) { + if (sd->npc_id != sd->npc_item_flag) + return; + } else if (sd->state.storage_flag || sd->sc.opt1) + ; //You can equip/unequip stuff while storage is open/under status changes + else if (pc_cant_act(sd)) + return; - if (!sd->inventory_data[index]) - return; + if(!sd->status.inventory[index].identify) { + clif_equipitemack(sd,index,0,0); // fail + return; + } - if (sd->inventory_data[index]->type == IT_PETARMOR) { - pet_equipitem(sd,index); - return; - } + if(!sd->inventory_data[index]) + return; - //Client doesn't send the position for ammo. - if (sd->inventory_data[index]->type == IT_AMMO) - pc_equipitem(sd,index,EQP_AMMO); - else - pc_equipitem(sd,index,RFIFOW(fd,4)); + if(sd->inventory_data[index]->type == IT_PETARMOR){ + pet_equipitem(sd,index); + return; + } + + //Client doesn't send the position for ammo. + if(sd->inventory_data[index]->type == IT_AMMO) + pc_equipitem(sd,index,EQP_AMMO); + else + pc_equipitem(sd,index,RFIFOW(fd,4)); } @@ -10130,21 +10241,21 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) /// 00ab <index>.W void clif_parse_UnequipItem(int fd,struct map_session_data *sd) { - int index; + int index; - if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl,CLR_DEAD); - return; - } + if(pc_isdead(sd)) { + clif_clearunit_area(&sd->bl,CLR_DEAD); + return; + } - if (sd->state.storage_flag || sd->sc.opt1) - ; //You can equip/unequip stuff while storage is open/under status changes - else if (pc_cant_act(sd)) - return; + if (sd->state.storage_flag || sd->sc.opt1) + ; //You can equip/unequip stuff while storage is open/under status changes + else if (pc_cant_act(sd)) + return; - index = RFIFOW(fd,2)-2; + index = RFIFOW(fd,2)-2; - pc_unequipitem(sd,index,1); + pc_unequipitem(sd,index,1); } @@ -10154,28 +10265,28 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd) /// 1 = click void clif_parse_NpcClicked(int fd,struct map_session_data *sd) { - struct block_list *bl; + struct block_list *bl; - if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl,CLR_DEAD); - return; - } + if(pc_isdead(sd)) { + clif_clearunit_area(&sd->bl,CLR_DEAD); + return; + } - if (pc_cant_act(sd)) - return; - - bl = map_id2bl(RFIFOL(fd,2)); - if (!bl) return; - switch (bl->type) { - case BL_MOB: - case BL_PC: - clif_parse_ActionRequest_sub(sd, 0x07, bl->id, gettick()); - break; - case BL_NPC: - if (bl->m != -1) // the user can't click floating npcs directly (hack attempt) - npc_click(sd,(TBL_NPC *)bl); - break; - } + if (pc_cant_act(sd)) + return; + + bl = map_id2bl(RFIFOL(fd,2)); + if (!bl) return; + switch (bl->type) { + case BL_MOB: + case BL_PC: + clif_parse_ActionRequest_sub(sd, 0x07, bl->id, gettick()); + break; + case BL_NPC: + if( bl->m != -1 )// the user can't click floating npcs directly (hack attempt) + npc_click(sd,(TBL_NPC*)bl); + break; + } } @@ -10186,9 +10297,9 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) /// 1 = sell void clif_parse_NpcBuySellSelected(int fd,struct map_session_data *sd) { - if (sd->state.trading) - return; - npc_buysellsel(sd,RFIFOL(fd,2),RFIFOB(fd,6)); + if (sd->state.trading) + return; + npc_buysellsel(sd,RFIFOL(fd,2),RFIFOB(fd,6)); } @@ -10199,33 +10310,33 @@ void clif_parse_NpcBuySellSelected(int fd,struct map_session_data *sd) /// 1 = "You do not have enough zeny." /// 2 = "You are over your Weight Limit." /// 3 = "Out of the maximum capacity, you have too many items." -void clif_npc_buy_result(struct map_session_data *sd, unsigned char result) +void clif_npc_buy_result(struct map_session_data* sd, unsigned char result) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xca)); - WFIFOW(fd,0) = 0xca; - WFIFOB(fd,2) = result; - WFIFOSET(fd,packet_len(0xca)); + WFIFOHEAD(fd,packet_len(0xca)); + WFIFOW(fd,0) = 0xca; + WFIFOB(fd,2) = result; + WFIFOSET(fd,packet_len(0xca)); } /// Request to buy chosen items from npc shop (CZ_PC_PURCHASE_ITEMLIST). /// 00c8 <packet len>.W { <amount>.W <name id>.W }* -void clif_parse_NpcBuyListSend(int fd, struct map_session_data *sd) +void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd) { - int n = (RFIFOW(fd,2)-4) /4; - unsigned short *item_list = (unsigned short *)RFIFOP(fd,4); - int result; + int n = (RFIFOW(fd,2)-4) /4; + unsigned short* item_list = (unsigned short*)RFIFOP(fd,4); + int result; - if (sd->state.trading || !sd->npc_shopid) - result = 1; - else - result = npc_buylist(sd,n,item_list); + if( sd->state.trading || !sd->npc_shopid ) + result = 1; + else + result = npc_buylist(sd,n,item_list); - sd->npc_shopid = 0; //Clear shop data. + sd->npc_shopid = 0; //Clear shop data. - clif_npc_buy_result(sd, result); + clif_npc_buy_result(sd, result); } @@ -10234,14 +10345,14 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data *sd) /// result: /// 0 = "The deal has successfully completed." /// 1 = "The deal has failed." -void clif_npc_sell_result(struct map_session_data *sd, unsigned char result) +void clif_npc_sell_result(struct map_session_data* sd, unsigned char result) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0xcb)); - WFIFOW(fd,0) = 0xcb; - WFIFOB(fd,2) = result; - WFIFOSET(fd,packet_len(0xcb)); + WFIFOHEAD(fd,packet_len(0xcb)); + WFIFOW(fd,0) = 0xcb; + WFIFOB(fd,2) = result; + WFIFOSET(fd,packet_len(0xcb)); } @@ -10249,20 +10360,20 @@ void clif_npc_sell_result(struct map_session_data *sd, unsigned char result) /// 00c9 <packet len>.W { <index>.W <amount>.W }* void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) { - int fail=0,n; - unsigned short *item_list; + int fail=0,n; + unsigned short *item_list; - n = (RFIFOW(fd,2)-4) /4; - item_list = (unsigned short *)RFIFOP(fd,4); + n = (RFIFOW(fd,2)-4) /4; + item_list = (unsigned short*)RFIFOP(fd,4); - if (sd->state.trading || !sd->npc_shopid) - fail = 1; - else - fail = npc_selllist(sd,n,item_list); + if (sd->state.trading || !sd->npc_shopid) + fail = 1; + else + fail = npc_selllist(sd,n,item_list); - sd->npc_shopid = 0; //Clear shop data. + sd->npc_shopid = 0; //Clear shop data. - clif_npc_sell_result(sd, fail); + clif_npc_sell_result(sd, fail); } @@ -10271,41 +10382,41 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) /// type: /// 0 = private /// 1 = public -void clif_parse_CreateChatRoom(int fd, struct map_session_data *sd) -{ - int len = RFIFOW(fd,2)-15; - int limit = RFIFOW(fd,4); - bool pub = (RFIFOB(fd,6) != 0); - const char *password = (char *)RFIFOP(fd,7); //not zero-terminated - const char *title = (char *)RFIFOP(fd,15); // not zero-terminated - char s_password[CHATROOM_PASS_SIZE]; - char s_title[CHATROOM_TITLE_SIZE]; - - if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) - return; - if (battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 4) { - clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,3); - return; - } +void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) +{ + int len = RFIFOW(fd,2)-15; + int limit = RFIFOW(fd,4); + bool pub = (RFIFOB(fd,6) != 0); + const char* password = (char*)RFIFOP(fd,7); //not zero-terminated + const char* title = (char*)RFIFOP(fd,15); // not zero-terminated + char s_password[CHATROOM_PASS_SIZE]; + char s_title[CHATROOM_TITLE_SIZE]; + + if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) + return; + if(battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 4) { + clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,3); + return; + } - if (len <= 0) - return; // invalid input + if( len <= 0 ) + return; // invalid input - safestrncpy(s_password, password, CHATROOM_PASS_SIZE); - safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); //NOTE: assumes that safestrncpy will not access the len+1'th byte + safestrncpy(s_password, password, CHATROOM_PASS_SIZE); + safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); //NOTE: assumes that safestrncpy will not access the len+1'th byte - chat_createpcchat(sd, s_title, s_password, limit, pub); + chat_createpcchat(sd, s_title, s_password, limit, pub); } /// Chatroom join request (CZ_REQ_ENTER_ROOM). /// 00d9 <chat ID>.L <passwd>.8B -void clif_parse_ChatAddMember(int fd, struct map_session_data *sd) +void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) { - int chatid = RFIFOL(fd,2); - const char *password = (char *)RFIFOP(fd,6); // not zero-terminated + int chatid = RFIFOL(fd,2); + const char* password = (char*)RFIFOP(fd,6); // not zero-terminated - chat_joinchat(sd,chatid,password); + chat_joinchat(sd,chatid,password); } @@ -10314,23 +10425,23 @@ void clif_parse_ChatAddMember(int fd, struct map_session_data *sd) /// type: /// 0 = private /// 1 = public -void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data *sd) +void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd) { - int len = RFIFOW(fd,2)-15; - int limit = RFIFOW(fd,4); - bool pub = (RFIFOB(fd,6) != 0); - const char *password = (char *)RFIFOP(fd,7); // not zero-terminated - const char *title = (char *)RFIFOP(fd,15); // not zero-terminated - char s_password[CHATROOM_PASS_SIZE]; - char s_title[CHATROOM_TITLE_SIZE]; + int len = RFIFOW(fd,2)-15; + int limit = RFIFOW(fd,4); + bool pub = (RFIFOB(fd,6) != 0); + const char* password = (char*)RFIFOP(fd,7); // not zero-terminated + const char* title = (char*)RFIFOP(fd,15); // not zero-terminated + char s_password[CHATROOM_PASS_SIZE]; + char s_title[CHATROOM_TITLE_SIZE]; - if (len <= 0) - return; // invalid input + if( len <= 0 ) + return; // invalid input - safestrncpy(s_password, password, CHATROOM_PASS_SIZE); - safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); //NOTE: assumes that safestrncpy will not access the len+1'th byte + safestrncpy(s_password, password, CHATROOM_PASS_SIZE); + safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); //NOTE: assumes that safestrncpy will not access the len+1'th byte - chat_changechatstatus(sd, s_title, s_password, limit, pub); + chat_changechatstatus(sd, s_title, s_password, limit, pub); } @@ -10339,9 +10450,9 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data *sd) /// role: /// 0 = owner /// 1 = normal -void clif_parse_ChangeChatOwner(int fd, struct map_session_data *sd) +void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) { - chat_changechatowner(sd,(char *)RFIFOP(fd,6)); + chat_changechatowner(sd,(char*)RFIFOP(fd,6)); } @@ -10349,15 +10460,15 @@ void clif_parse_ChangeChatOwner(int fd, struct map_session_data *sd) /// 00e2 <name>.24B void clif_parse_KickFromChat(int fd,struct map_session_data *sd) { - chat_kickchat(sd,(char *)RFIFOP(fd,2)); + chat_kickchat(sd,(char*)RFIFOP(fd,2)); } /// Request to leave the current chatroom (CZ_EXIT_ROOM). /// 00e3 -void clif_parse_ChatLeave(int fd, struct map_session_data *sd) +void clif_parse_ChatLeave(int fd, struct map_session_data* sd) { - chat_leavechat(sd,0); + chat_leavechat(sd,0); } @@ -10366,14 +10477,14 @@ void clif_parse_ChatLeave(int fd, struct map_session_data *sd) //0: static void clif_noask_sub(struct map_session_data *src, struct map_session_data *target, int type) { - const char *msg; - char output[256]; - // Your request has been rejected by autoreject option. - msg = msg_txt(392); - clif_disp_onlyself(src, msg, strlen(msg)); - //Notice that a request was rejected. - snprintf(output, 256, msg_txt(393+type), src->status.name, 256); - clif_disp_onlyself(target, output, strlen(output)); + const char* msg; + char output[256]; + // Your request has been rejected by autoreject option. + msg = msg_txt(392); + clif_disp_onlyself(src, msg, strlen(msg)); + //Notice that a request was rejected. + snprintf(output, 256, msg_txt(393+type), src->status.name, 256); + clif_disp_onlyself(target, output, strlen(output)); } @@ -10381,25 +10492,26 @@ static void clif_noask_sub(struct map_session_data *src, struct map_session_data /// 00e4 <account id>.L void clif_parse_TradeRequest(int fd,struct map_session_data *sd) { - struct map_session_data *t_sd; + struct map_session_data *t_sd; - t_sd = map_id2sd(RFIFOL(fd,2)); + t_sd = map_id2sd(RFIFOL(fd,2)); - if (!sd->chatID && pc_cant_act(sd)) - return; //You can trade while in a chatroom. + if(!sd->chatID && pc_cant_act(sd)) + return; //You can trade while in a chatroom. - // @noask [LuzZza] - if (t_sd && t_sd->state.noask) { - clif_noask_sub(sd, t_sd, 0); - return; - } + // @noask [LuzZza] + if(t_sd && t_sd->state.noask) { + clif_noask_sub(sd, t_sd, 0); + return; + } - if (battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 1) { - clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,0); - return; - } + if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 1) + { + clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,0); + return; + } - trade_traderequest(sd,t_sd); + trade_traderequest(sd,t_sd); } @@ -10410,7 +10522,7 @@ void clif_parse_TradeRequest(int fd,struct map_session_data *sd) /// 4 = rejected void clif_parse_TradeAck(int fd,struct map_session_data *sd) { - trade_tradeack(sd,RFIFOB(fd,2)); + trade_tradeack(sd,RFIFOB(fd,2)); } @@ -10418,13 +10530,13 @@ void clif_parse_TradeAck(int fd,struct map_session_data *sd) /// 00e8 <index>.W <amount>.L void clif_parse_TradeAddItem(int fd,struct map_session_data *sd) { - short index = RFIFOW(fd,2); - int amount = RFIFOL(fd,4); + short index = RFIFOW(fd,2); + int amount = RFIFOL(fd,4); - if (index == 0) - trade_tradeaddzeny(sd, amount); - else - trade_tradeadditem(sd, index, (short)amount); + if( index == 0 ) + trade_tradeaddzeny(sd, amount); + else + trade_tradeadditem(sd, index, (short)amount); } @@ -10432,7 +10544,7 @@ void clif_parse_TradeAddItem(int fd,struct map_session_data *sd) /// 00eb void clif_parse_TradeOk(int fd,struct map_session_data *sd) { - trade_tradeok(sd); + trade_tradeok(sd); } @@ -10440,7 +10552,7 @@ void clif_parse_TradeOk(int fd,struct map_session_data *sd) /// 00ed void clif_parse_TradeCancel(int fd,struct map_session_data *sd) { - trade_tradecancel(sd); + trade_tradecancel(sd); } @@ -10448,7 +10560,7 @@ void clif_parse_TradeCancel(int fd,struct map_session_data *sd) /// 00ef void clif_parse_TradeCommit(int fd,struct map_session_data *sd) { - trade_tradecommit(sd); + trade_tradecommit(sd); } @@ -10456,7 +10568,7 @@ void clif_parse_TradeCommit(int fd,struct map_session_data *sd) /// 0118 void clif_parse_StopAttack(int fd,struct map_session_data *sd) { - pc_stop_attack(sd); + pc_stop_attack(sd); } @@ -10464,11 +10576,11 @@ void clif_parse_StopAttack(int fd,struct map_session_data *sd) /// 0126 <index>.W <amount>.L void clif_parse_PutItemToCart(int fd,struct map_session_data *sd) { - if (pc_istrading(sd)) - return; - if (!pc_iscarton(sd)) - return; - pc_putitemtocart(sd,RFIFOW(fd,2)-2,RFIFOL(fd,4)); + if (pc_istrading(sd)) + return; + if (!pc_iscarton(sd)) + return; + pc_putitemtocart(sd,RFIFOW(fd,2)-2,RFIFOL(fd,4)); } @@ -10476,9 +10588,9 @@ void clif_parse_PutItemToCart(int fd,struct map_session_data *sd) /// 0127 <index>.W <amount>.L void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd) { - if (!pc_iscarton(sd)) - return; - pc_getitemfromcart(sd,RFIFOW(fd,2)-2,RFIFOL(fd,4)); + if (!pc_iscarton(sd)) + return; + pc_getitemfromcart(sd,RFIFOW(fd,2)-2,RFIFOL(fd,4)); } @@ -10486,15 +10598,15 @@ void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd) /// 012a void clif_parse_RemoveOption(int fd,struct map_session_data *sd) { - /** - * Attempts to remove these options when this function is called (will remove all available) - **/ + /** + * Attempts to remove these options when this function is called (will remove all available) + **/ #ifdef NEW_CARTS - pc_setoption(sd,sd->sc.option&~(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR)); - if (sd->sc.data[SC_PUSH_CART]) - pc_setcart(sd,0); + pc_setoption(sd,sd->sc.option&~(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR)); + if( sd->sc.data[SC_PUSH_CART] ) + pc_setcart(sd,0); #else - pc_setoption(sd,sd->sc.option&~(OPTION_CART|OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR)); + pc_setoption(sd,sd->sc.option&~(OPTION_CART|OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR)); #endif } @@ -10502,32 +10614,31 @@ void clif_parse_RemoveOption(int fd,struct map_session_data *sd) /// Request to change cart's visual look (CZ_REQ_CHANGECART). /// 01af <num>.W void clif_parse_ChangeCart(int fd,struct map_session_data *sd) -{ - // TODO: State tracking? - int type; +{// TODO: State tracking? + int type; - if (sd && pc_checkskill(sd, MC_CHANGECART) < 1) - return; + if( sd && pc_checkskill(sd, MC_CHANGECART) < 1 ) + return; - type = (int)RFIFOW(fd,2); + type = (int)RFIFOW(fd,2); #ifdef NEW_CARTS - if ((type == 9 && sd->status.base_level > 131) || - (type == 8 && sd->status.base_level > 121) || - (type == 7 && sd->status.base_level > 111) || - (type == 6 && sd->status.base_level > 101) || - (type == 5 && sd->status.base_level > 90) || - (type == 4 && sd->status.base_level > 80) || - (type == 3 && sd->status.base_level > 65) || - (type == 2 && sd->status.base_level > 40) || - (type == 1)) + if( (type == 9 && sd->status.base_level > 131) || + (type == 8 && sd->status.base_level > 121) || + (type == 7 && sd->status.base_level > 111) || + (type == 6 && sd->status.base_level > 101) || + (type == 5 && sd->status.base_level > 90) || + (type == 4 && sd->status.base_level > 80) || + (type == 3 && sd->status.base_level > 65) || + (type == 2 && sd->status.base_level > 40) || + (type == 1)) #else - if ((type == 5 && sd->status.base_level > 90) || - (type == 4 && sd->status.base_level > 80) || - (type == 3 && sd->status.base_level > 65) || - (type == 2 && sd->status.base_level > 40) || - (type == 1)) + if( (type == 5 && sd->status.base_level > 90) || + (type == 4 && sd->status.base_level > 80) || + (type == 3 && sd->status.base_level > 65) || + (type == 2 && sd->status.base_level > 40) || + (type == 1)) #endif - pc_setcart(sd,type); + pc_setcart(sd,type); } @@ -10540,7 +10651,7 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd) /// the like void clif_parse_StatusUp(int fd,struct map_session_data *sd) { - pc_statusup(sd,RFIFOW(fd,2)); + pc_statusup(sd,RFIFOW(fd,2)); } @@ -10548,95 +10659,100 @@ void clif_parse_StatusUp(int fd,struct map_session_data *sd) /// 0112 <skill id>.W void clif_parse_SkillUp(int fd,struct map_session_data *sd) { - pc_skillup(sd,RFIFOW(fd,2)); + pc_skillup(sd,RFIFOW(fd,2)); } static void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_data *sd, unsigned int tick, short skillnum, short skilllv, int target_id) { - int lv; + int lv; - if (!hd) - return; - if (skillnotok_hom(skillnum, hd)) - return; - if (hd->bl.id != target_id && skill_get_inf(skillnum)&INF_SELF_SKILL) - target_id = hd->bl.id; - if (hd->ud.skilltimer != INVALID_TIMER) { - if (skillnum != SA_CASTCANCEL && skillnum != SO_SPELLFIST) return; - } else if (DIFF_TICK(tick, hd->ud.canact_tick) < 0) - return; + if( !hd ) + return; + if( skillnotok_hom(skillnum, hd) ) + return; + if( hd->bl.id != target_id && skill_get_inf(skillnum)&INF_SELF_SKILL ) + target_id = hd->bl.id; + if( hd->ud.skilltimer != INVALID_TIMER ) + { + if( skillnum != SA_CASTCANCEL && skillnum != SO_SPELLFIST ) return; + } + else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) + return; - lv = merc_hom_checkskill(hd, skillnum); - if (skilllv > lv) - skilllv = lv; - if (skilllv) - unit_skilluse_id(&hd->bl, target_id, skillnum, skilllv); + lv = merc_hom_checkskill(hd, skillnum); + if( skilllv > lv ) + skilllv = lv; + if( skilllv ) + unit_skilluse_id(&hd->bl, target_id, skillnum, skilllv); } static void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_data *sd, unsigned int tick, short skillnum, short skilllv, short x, short y, int skillmoreinfo) { - int lv; - if (!hd) - return; - if (skillnotok_hom(skillnum, hd)) - return; - if (hd->ud.skilltimer != INVALID_TIMER) { - if (skillnum != SA_CASTCANCEL && skillnum != SO_SPELLFIST) return; - } else if (DIFF_TICK(tick, hd->ud.canact_tick) < 0) - return; - - if (hd->sc.data[SC_BASILICA]) - return; - lv = merc_hom_checkskill(hd, skillnum); - if (skilllv > lv) - skilllv = lv; - if (skilllv) - unit_skilluse_pos(&hd->bl, x, y, skillnum, skilllv); + int lv; + if( !hd ) + return; + if( skillnotok_hom(skillnum, hd) ) + return; + if( hd->ud.skilltimer != INVALID_TIMER ) { + if( skillnum != SA_CASTCANCEL && skillnum != SO_SPELLFIST ) return; + } else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) + return; + + if( hd->sc.data[SC_BASILICA] ) + return; + lv = merc_hom_checkskill(hd, skillnum); + if( skilllv > lv ) + skilllv = lv; + if( skilllv ) + unit_skilluse_pos(&hd->bl, x, y, skillnum, skilllv); } static void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, short skillnum, short skilllv, int target_id) { - int lv; + int lv; - if (!md) - return; - if (skillnotok_mercenary(skillnum, md)) - return; - if (md->bl.id != target_id && skill_get_inf(skillnum)&INF_SELF_SKILL) - target_id = md->bl.id; - if (md->ud.skilltimer != INVALID_TIMER) { - if (skillnum != SA_CASTCANCEL && skillnum != SO_SPELLFIST) return; - } else if (DIFF_TICK(tick, md->ud.canact_tick) < 0) - return; + if( !md ) + return; + if( skillnotok_mercenary(skillnum, md) ) + return; + if( md->bl.id != target_id && skill_get_inf(skillnum)&INF_SELF_SKILL ) + target_id = md->bl.id; + if( md->ud.skilltimer != INVALID_TIMER ) + { + if( skillnum != SA_CASTCANCEL && skillnum != SO_SPELLFIST ) return; + } + else if( DIFF_TICK(tick, md->ud.canact_tick) < 0 ) + return; - lv = mercenary_checkskill(md, skillnum); - if (skilllv > lv) - skilllv = lv; - if (skilllv) - unit_skilluse_id(&md->bl, target_id, skillnum, skilllv); + lv = mercenary_checkskill(md, skillnum); + if( skilllv > lv ) + skilllv = lv; + if( skilllv ) + unit_skilluse_id(&md->bl, target_id, skillnum, skilllv); } static void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, short skillnum, short skilllv, short x, short y, int skillmoreinfo) { - int lv; - if (!md) - return; - if (skillnotok_mercenary(skillnum, md)) - return; - if (md->ud.skilltimer != INVALID_TIMER) - return; - if (DIFF_TICK(tick, md->ud.canact_tick) < 0) { - clif_skill_fail(md->master, skillnum, USESKILL_FAIL_SKILLINTERVAL, 0); - return; - } - - if (md->sc.data[SC_BASILICA]) - return; - lv = mercenary_checkskill(md, skillnum); - if (skilllv > lv) - skilllv = lv; - if (skilllv) - unit_skilluse_pos(&md->bl, x, y, skillnum, skilllv); + int lv; + if( !md ) + return; + if( skillnotok_mercenary(skillnum, md) ) + return; + if( md->ud.skilltimer != INVALID_TIMER ) + return; + if( DIFF_TICK(tick, md->ud.canact_tick) < 0 ) + { + clif_skill_fail(md->master, skillnum, USESKILL_FAIL_SKILLINTERVAL, 0); + return; + } + + if( md->sc.data[SC_BASILICA] ) + return; + lv = mercenary_checkskill(md, skillnum); + if( skilllv > lv ) + skilllv = lv; + if( skilllv ) + unit_skilluse_pos(&md->bl, x, y, skillnum, skilllv); } @@ -10646,95 +10762,101 @@ static void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct /// There are various variants of this packet, some of them have padding between fields. void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) { - short skillnum, skilllv; - int tmp, target_id; - unsigned int tick = gettick(); - - skilllv = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - skillnum = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); - target_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[2]); - - if (skilllv < 1) skilllv = 1; //No clue, I have seen the client do this with guild skills :/ [Skotlex] - - tmp = skill_get_inf(skillnum); - if (tmp&INF_GROUND_SKILL || !tmp) - return; //Using a ground/passive skill on a target? WRONG. - - if (skillnum >= HM_SKILLBASE && skillnum < HM_SKILLBASE + MAX_HOMUNSKILL) { - clif_parse_UseSkillToId_homun(sd->hd, sd, tick, skillnum, skilllv, target_id); - return; - } - - if (skillnum >= MC_SKILLBASE && skillnum < MC_SKILLBASE + MAX_MERCSKILL) { - clif_parse_UseSkillToId_mercenary(sd->md, sd, tick, skillnum, skilllv, target_id); - return; - } - - // Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] - sd->idletime = last_tick; - - if( pc_cant_act(sd) && skillnum != RK_REFRESH && !(skillnum == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN)) ) - return; - if (pc_issit(sd)) - return; - - if (skillnotok(skillnum, sd)) - return; - - if (sd->bl.id != target_id && tmp&INF_SELF_SKILL) - target_id = sd->bl.id; // never trust the client - - if (target_id < 0 && -target_id == sd->bl.id) // for disguises [Valaris] - target_id = sd->bl.id; - - if (sd->ud.skilltimer != INVALID_TIMER) { - if (skillnum != SA_CASTCANCEL && skillnum != SO_SPELLFIST) - return; - } else if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { - if (sd->skillitem != skillnum) { - clif_skill_fail(sd, skillnum, USESKILL_FAIL_SKILLINTERVAL, 0); - return; - } - } - - if (sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER)) - return; - - if (sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id)) - return; // On basilica only caster can use Basilica again to stop it. - - if (sd->menuskill_id) { - if (sd->menuskill_id == SA_TAMINGMONSTER) { - clif_menuskill_clear(sd); //Cancel pet capture. - } else if (sd->menuskill_id != SA_AUTOSPELL) - return; //Can't use skills while a menu is open. - } - if (sd->skillitem == skillnum) { - if (skilllv != sd->skillitemlv) - skilllv = sd->skillitemlv; - if (!(tmp&INF_SELF_SKILL)) - pc_delinvincibletimer(sd); // Target skills thru items cancel invincibility. [Inkfish] - unit_skilluse_id(&sd->bl, target_id, skillnum, skilllv); - return; - } - - sd->skillitem = sd->skillitemlv = 0; - - if (skillnum >= GD_SKILLBASE) { - if (sd->state.gmaster_flag) - skilllv = guild_checkskill(sd->state.gmaster_flag, skillnum); - else - skilllv = 0; - } else { - tmp = pc_checkskill(sd, skillnum); - if (skilllv > tmp) - skilllv = tmp; - } - - pc_delinvincibletimer(sd); - - if (skilllv) - unit_skilluse_id(&sd->bl, target_id, skillnum, skilllv); + short skillnum, skilllv; + int tmp, target_id; + unsigned int tick = gettick(); + + skilllv = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + skillnum = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); + target_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[2]); + + if( skilllv < 1 ) skilllv = 1; //No clue, I have seen the client do this with guild skills :/ [Skotlex] + + tmp = skill_get_inf(skillnum); + if (tmp&INF_GROUND_SKILL || !tmp) + return; //Using a ground/passive skill on a target? WRONG. + + if( skillnum >= HM_SKILLBASE && skillnum < HM_SKILLBASE + MAX_HOMUNSKILL ) + { + clif_parse_UseSkillToId_homun(sd->hd, sd, tick, skillnum, skilllv, target_id); + return; + } + + if( skillnum >= MC_SKILLBASE && skillnum < MC_SKILLBASE + MAX_MERCSKILL ) + { + clif_parse_UseSkillToId_mercenary(sd->md, sd, tick, skillnum, skilllv, target_id); + return; + } + + // Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] + sd->idletime = last_tick; + + if( pc_cant_act(sd) && !(skillnum == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN)) ) + return; + if( pc_issit(sd) ) + return; + + if( skillnotok(skillnum, sd) ) + return; + + if( sd->bl.id != target_id && tmp&INF_SELF_SKILL ) + target_id = sd->bl.id; // never trust the client + + if( target_id < 0 && -target_id == sd->bl.id ) // for disguises [Valaris] + target_id = sd->bl.id; + + if( sd->ud.skilltimer != INVALID_TIMER ) + { + if( skillnum != SA_CASTCANCEL && skillnum != SO_SPELLFIST ) + return; + } + else if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) + { + if( sd->skillitem != skillnum ) + { + clif_skill_fail(sd, skillnum, USESKILL_FAIL_SKILLINTERVAL, 0); + return; + } + } + + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER) ) + return; + + if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) ) + return; // On basilica only caster can use Basilica again to stop it. + + if( sd->menuskill_id ) { + if( sd->menuskill_id == SA_TAMINGMONSTER ) { + clif_menuskill_clear(sd); //Cancel pet capture. + } else if( sd->menuskill_id != SA_AUTOSPELL ) + return; //Can't use skills while a menu is open. + } + if( sd->skillitem == skillnum ) { + if( skilllv != sd->skillitemlv ) + skilllv = sd->skillitemlv; + if( !(tmp&INF_SELF_SKILL) ) + pc_delinvincibletimer(sd); // Target skills thru items cancel invincibility. [Inkfish] + unit_skilluse_id(&sd->bl, target_id, skillnum, skilllv); + return; + } + + sd->skillitem = sd->skillitemlv = 0; + + if( skillnum >= GD_SKILLBASE ) { + if( sd->state.gmaster_flag ) + skilllv = guild_checkskill(sd->state.gmaster_flag, skillnum); + else + skilllv = 0; + } else { + tmp = pc_checkskill(sd, skillnum); + if( skilllv > tmp ) + skilllv = tmp; + } + + pc_delinvincibletimer(sd); + + if( skilllv ) + unit_skilluse_id(&sd->bl, target_id, skillnum, skilllv); } /*========================================== @@ -10742,73 +10864,76 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) *------------------------------------------*/ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, short skilllv, short skillnum, short x, short y, int skillmoreinfo) { - unsigned int tick = gettick(); - - if (!(skill_get_inf(skillnum)&INF_GROUND_SKILL)) - return; //Using a target skill on the ground? WRONG. - - if (skillnum >= HM_SKILLBASE && skillnum < HM_SKILLBASE + MAX_HOMUNSKILL) { - clif_parse_UseSkillToPos_homun(sd->hd, sd, tick, skillnum, skilllv, x, y, skillmoreinfo); - return; - } - - if (skillnum >= MC_SKILLBASE && skillnum < MC_SKILLBASE + MAX_MERCSKILL) { - clif_parse_UseSkillToPos_mercenary(sd->md, sd, tick, skillnum, skilllv, x, y, skillmoreinfo); - return; - } - - //Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] - sd->idletime = last_tick; - - if (skillnotok(skillnum, sd)) - return; - if (skillmoreinfo != -1) { - if (pc_issit(sd)) { - clif_skill_fail(sd, skillnum, USESKILL_FAIL_LEVEL, 0); - return; - } - //You can't use Graffiti/TalkieBox AND have a vending open, so this is safe. - safestrncpy(sd->message, (char *)RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE); - } - - if (sd->ud.skilltimer != INVALID_TIMER) - return; - - if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { - if (sd->skillitem != skillnum) { - clif_skill_fail(sd, skillnum, USESKILL_FAIL_SKILLINTERVAL, 0); - return; - } - } - - if (sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER)) - return; - - if (sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id)) - return; // On basilica only caster can use Basilica again to stop it. - - if (sd->menuskill_id) { - if (sd->menuskill_id == SA_TAMINGMONSTER) { - clif_menuskill_clear(sd); //Cancel pet capture. - } else if (sd->menuskill_id != SA_AUTOSPELL) - return; //Can't use skills while a menu is open. - } - - pc_delinvincibletimer(sd); - - if (sd->skillitem == skillnum) { - if (skilllv != sd->skillitemlv) - skilllv = sd->skillitemlv; - unit_skilluse_pos(&sd->bl, x, y, skillnum, skilllv); - } else { - int lv; - sd->skillitem = sd->skillitemlv = 0; - if ((lv = pc_checkskill(sd, skillnum)) > 0) { - if (skilllv > lv) - skilllv = lv; - unit_skilluse_pos(&sd->bl, x, y, skillnum,skilllv); - } - } + unsigned int tick = gettick(); + + if( !(skill_get_inf(skillnum)&INF_GROUND_SKILL) ) + return; //Using a target skill on the ground? WRONG. + + if( skillnum >= HM_SKILLBASE && skillnum < HM_SKILLBASE + MAX_HOMUNSKILL ) { + clif_parse_UseSkillToPos_homun(sd->hd, sd, tick, skillnum, skilllv, x, y, skillmoreinfo); + return; + } + + if( skillnum >= MC_SKILLBASE && skillnum < MC_SKILLBASE + MAX_MERCSKILL ) + { + clif_parse_UseSkillToPos_mercenary(sd->md, sd, tick, skillnum, skilllv, x, y, skillmoreinfo); + return; + } + + //Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] + sd->idletime = last_tick; + + if( skillnotok(skillnum, sd) ) + return; + if( skillmoreinfo != -1 ) + { + if( pc_issit(sd) ) + { + clif_skill_fail(sd, skillnum, USESKILL_FAIL_LEVEL, 0); + return; + } + //You can't use Graffiti/TalkieBox AND have a vending open, so this is safe. + safestrncpy(sd->message, (char*)RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE); + } + + if( sd->ud.skilltimer != INVALID_TIMER ) + return; + + if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) { + if( sd->skillitem != skillnum ) { + clif_skill_fail(sd, skillnum, USESKILL_FAIL_SKILLINTERVAL, 0); + return; + } + } + + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER) ) + return; + + if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) ) + return; // On basilica only caster can use Basilica again to stop it. + + if( sd->menuskill_id ) { + if( sd->menuskill_id == SA_TAMINGMONSTER ) { + clif_menuskill_clear(sd); //Cancel pet capture. + } else if( sd->menuskill_id != SA_AUTOSPELL ) + return; //Can't use skills while a menu is open. + } + + pc_delinvincibletimer(sd); + + if( sd->skillitem == skillnum ) { + if( skilllv != sd->skillitemlv ) + skilllv = sd->skillitemlv; + unit_skilluse_pos(&sd->bl, x, y, skillnum, skilllv); + } else { + int lv; + sd->skillitem = sd->skillitemlv = 0; + if( (lv = pc_checkskill(sd, skillnum)) > 0 ) { + if( skilllv > lv ) + skilllv = lv; + unit_skilluse_pos(&sd->bl, x, y, skillnum,skilllv); + } + } } @@ -10818,18 +10943,18 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, sho /// There are various variants of this packet, some of them have padding between fields. void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) { - if (pc_cant_act(sd)) - return; - if (pc_issit(sd)) - return; + if (pc_cant_act(sd)) + return; + if (pc_issit(sd)) + return; - clif_parse_UseSkillToPosSub(fd, sd, - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), //skill lv - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]), //skill num - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[2]), //pos x - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[3]), //pos y - -1 //Skill more info. - ); + clif_parse_UseSkillToPosSub(fd, sd, + RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), //skill lv + RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]), //skill num + RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[2]), //pos x + RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[3]), //pos y + -1 //Skill more info. + ); } @@ -10839,39 +10964,39 @@ void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd) { - if (pc_cant_act(sd)) - return; - if (pc_issit(sd)) - return; + if (pc_cant_act(sd)) + return; + if (pc_issit(sd)) + return; - clif_parse_UseSkillToPosSub(fd, sd, - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), //Skill lv - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]), //Skill num - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[2]), //pos x - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[3]), //pos y - packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[4] //skill more info - ); + clif_parse_UseSkillToPosSub(fd, sd, + RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), //Skill lv + RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]), //Skill num + RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[2]), //pos x + RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[3]), //pos y + packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[4] //skill more info + ); } /// Answer to map selection dialog (CZ_SELECT_WARPPOINT). /// 011b <skill id>.W <map name>.16B -void clif_parse_UseSkillMap(int fd, struct map_session_data *sd) +void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) { - short skill_num = RFIFOW(fd,2); - char map_name[MAP_NAME_LENGTH]; - mapindex_getmapname((char *)RFIFOP(fd,4), map_name); + short skill_num = RFIFOW(fd,2); + char map_name[MAP_NAME_LENGTH]; + mapindex_getmapname((char*)RFIFOP(fd,4), map_name); - if (skill_num != sd->menuskill_id) - return; + if(skill_num != sd->menuskill_id) + return; - if (pc_cant_act(sd)) { - clif_menuskill_clear(sd); - return; - } + if( pc_cant_act(sd) ) { + clif_menuskill_clear(sd); + return; + } - pc_delinvincibletimer(sd); - skill_castend_map(sd,skill_num,map_name); + pc_delinvincibletimer(sd); + skill_castend_map(sd,skill_num,map_name); } @@ -10879,8 +11004,8 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data *sd) /// 011d void clif_parse_RequestMemo(int fd,struct map_session_data *sd) { - if (!pc_isdead(sd)) - pc_memo(sd,-1); + if (!pc_isdead(sd)) + pc_memo(sd,-1); } @@ -10888,24 +11013,24 @@ void clif_parse_RequestMemo(int fd,struct map_session_data *sd) /// 018e <name id>.W { <material id>.W }*3 void clif_parse_ProduceMix(int fd,struct map_session_data *sd) { - switch (sd->menuskill_id) { - case -1: - case AM_PHARMACY: - case RK_RUNEMASTERY: - case GC_RESEARCHNEWPOISON: - break; - default: - return; - } - if (pc_istrading(sd)) { - //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); - clif_menuskill_clear(sd); - return; - } - if (skill_can_produce_mix(sd,RFIFOW(fd,2),sd->menuskill_val, 1)) - skill_produce_mix(sd,0,RFIFOW(fd,2),RFIFOW(fd,4),RFIFOW(fd,6),RFIFOW(fd,8), 1); - clif_menuskill_clear(sd); + switch( sd->menuskill_id ) { + case -1: + case AM_PHARMACY: + case RK_RUNEMASTERY: + case GC_RESEARCHNEWPOISON: + break; + default: + return; + } + if (pc_istrading(sd)) { + //Make it fail to avoid shop exploits where you sell something different than you see. + clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); + clif_menuskill_clear(sd); + return; + } + if( skill_can_produce_mix(sd,RFIFOW(fd,2),sd->menuskill_val, 1) ) + skill_produce_mix(sd,0,RFIFOW(fd,2),RFIFOW(fd,4),RFIFOW(fd,6),RFIFOW(fd,8), 1); + clif_menuskill_clear(sd); } @@ -10918,23 +11043,22 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd) /// 4 = GN_MIX_COOKING /// 5 = GN_MAKEBOMB /// 6 = GN_S_PHARMACY -void clif_parse_Cooking(int fd,struct map_session_data *sd) -{ - int type = RFIFOW(fd,2); - int nameid = RFIFOW(fd,4); - int amount = sd->menuskill_val2?sd->menuskill_val2:1; - if (type == 6 && sd->menuskill_id != GN_MIX_COOKING && sd->menuskill_id != GN_S_PHARMACY) - return; - - if (pc_istrading(sd)) { - //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); - clif_menuskill_clear(sd); - return; - } - if (skill_can_produce_mix(sd,nameid,sd->menuskill_val, amount)) - skill_produce_mix(sd,sd->menuskill_id,nameid,0,0,0,amount); - clif_menuskill_clear(sd); +void clif_parse_Cooking(int fd,struct map_session_data *sd) { + int type = RFIFOW(fd,2); + int nameid = RFIFOW(fd,4); + int amount = sd->menuskill_val2?sd->menuskill_val2:1; + if( type == 6 && sd->menuskill_id != GN_MIX_COOKING && sd->menuskill_id != GN_S_PHARMACY ) + return; + + if (pc_istrading(sd)) { + //Make it fail to avoid shop exploits where you sell something different than you see. + clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); + clif_menuskill_clear(sd); + return; + } + if( skill_can_produce_mix(sd,nameid,sd->menuskill_val, amount) ) + skill_produce_mix(sd,sd->menuskill_id,nameid,0,0,0,amount); + clif_menuskill_clear(sd); } @@ -10942,16 +11066,16 @@ void clif_parse_Cooking(int fd,struct map_session_data *sd) /// 01fd <index>.W <name id>.W <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W void clif_parse_RepairItem(int fd, struct map_session_data *sd) { - if (sd->menuskill_id != BS_REPAIRWEAPON) - return; - if (pc_istrading(sd)) { - //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); - clif_menuskill_clear(sd); - return; - } - skill_repairweapon(sd,RFIFOW(fd,2)); - clif_menuskill_clear(sd); + if (sd->menuskill_id != BS_REPAIRWEAPON) + return; + if (pc_istrading(sd)) { + //Make it fail to avoid shop exploits where you sell something different than you see. + clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); + clif_menuskill_clear(sd); + return; + } + skill_repairweapon(sd,RFIFOW(fd,2)); + clif_menuskill_clear(sd); } @@ -10959,19 +11083,19 @@ void clif_parse_RepairItem(int fd, struct map_session_data *sd) /// 0222 <index>.L void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) { - int idx; + int idx; - if (sd->menuskill_id != WS_WEAPONREFINE) //Packet exploit? - return; - if (pc_istrading(sd)) { - //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); - clif_menuskill_clear(sd); - return; - } - idx = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - skill_weaponrefine(sd, idx-2); - clif_menuskill_clear(sd); + if (sd->menuskill_id != WS_WEAPONREFINE) //Packet exploit? + return; + if (pc_istrading(sd)) { + //Make it fail to avoid shop exploits where you sell something different than you see. + clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); + clif_menuskill_clear(sd); + return; + } + idx = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + skill_weaponrefine(sd, idx-2); + clif_menuskill_clear(sd); } @@ -10984,18 +11108,19 @@ void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) /// overflows to choice%256. void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) { - int npc_id = RFIFOL(fd,2); - uint8 select = RFIFOB(fd,6); + int npc_id = RFIFOL(fd,2); + uint8 select = RFIFOB(fd,6); - if ((select > sd->npc_menu && select != 0xff) || select == 0) { - TBL_NPC *nd = map_id2nd(npc_id); - ShowWarning("Invalid menu selection on npc %d:'%s' - got %d, valid range is [%d..%d] (player AID:%d, CID:%d, name:'%s')!\n", npc_id, (nd)?nd->name:"invalid npc id", select, 1, sd->npc_menu, sd->bl.id, sd->status.char_id, sd->status.name); - clif_GM_kick(NULL,sd); - return; - } + if( (select > sd->npc_menu && select != 0xff) || select == 0 ) + { + TBL_NPC* nd = map_id2nd(npc_id); + ShowWarning("Invalid menu selection on npc %d:'%s' - got %d, valid range is [%d..%d] (player AID:%d, CID:%d, name:'%s')!\n", npc_id, (nd)?nd->name:"invalid npc id", select, 1, sd->npc_menu, sd->bl.id, sd->status.char_id, sd->status.name); + clif_GM_kick(NULL,sd); + return; + } - sd->npc_menu = select; - npc_scriptcont(sd,npc_id); + sd->npc_menu = select; + npc_scriptcont(sd,npc_id); } @@ -11003,7 +11128,7 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) /// 00b9 <npc id>.L void clif_parse_NpcNextClicked(int fd,struct map_session_data *sd) { - npc_scriptcont(sd,RFIFOL(fd,2)); + npc_scriptcont(sd,RFIFOL(fd,2)); } @@ -11011,27 +11136,27 @@ void clif_parse_NpcNextClicked(int fd,struct map_session_data *sd) /// 0143 <npc id>.L <value>.L void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) { - int npcid = RFIFOL(fd,2); - int amount = (int)RFIFOL(fd,6); + int npcid = RFIFOL(fd,2); + int amount = (int)RFIFOL(fd,6); - sd->npc_amount = amount; - npc_scriptcont(sd, npcid); + sd->npc_amount = amount; + npc_scriptcont(sd, npcid); } /// NPC text input dialog value (CZ_INPUT_EDITDLGSTR). /// 01d5 <packet len>.W <npc id>.L <string>.?B -void clif_parse_NpcStringInput(int fd, struct map_session_data *sd) +void clif_parse_NpcStringInput(int fd, struct map_session_data* sd) { - int message_len = RFIFOW(fd,2)-8; - int npcid = RFIFOL(fd,4); - const char *message = (char *)RFIFOP(fd,8); + int message_len = RFIFOW(fd,2)-8; + int npcid = RFIFOL(fd,4); + const char* message = (char*)RFIFOP(fd,8); - if (message_len <= 0) - return; // invalid input + if( message_len <= 0 ) + return; // invalid input - safestrncpy(sd->npc_str, message, min(message_len,CHATBOX_SIZE)); - npc_scriptcont(sd, npcid); + safestrncpy(sd->npc_str, message, min(message_len,CHATBOX_SIZE)); + npc_scriptcont(sd, npcid); } @@ -11039,9 +11164,9 @@ void clif_parse_NpcStringInput(int fd, struct map_session_data *sd) /// 0146 <npc id>.L void clif_parse_NpcCloseClicked(int fd,struct map_session_data *sd) { - if (!sd->npc_id) //Avoid parsing anything when the script was done with. [Skotlex] - return; - npc_scriptcont(sd,RFIFOL(fd,2)); + if (!sd->npc_id) //Avoid parsing anything when the script was done with. [Skotlex] + return; + npc_scriptcont(sd,RFIFOL(fd,2)); } @@ -11051,16 +11176,16 @@ void clif_parse_NpcCloseClicked(int fd,struct map_session_data *sd) /// -1 = cancel void clif_parse_ItemIdentify(int fd,struct map_session_data *sd) { - short idx = RFIFOW(fd,2); + short idx = RFIFOW(fd,2); - if (sd->menuskill_id != MC_IDENTIFY) - return; - if (idx == -1) { // cancel pressed - clif_menuskill_clear(sd); - return; - } - skill_identify(sd,idx-2); - clif_menuskill_clear(sd); + if (sd->menuskill_id != MC_IDENTIFY) + return; + if( idx == -1 ) {// cancel pressed + clif_menuskill_clear(sd); + return; + } + skill_identify(sd,idx-2); + clif_menuskill_clear(sd); } @@ -11068,31 +11193,31 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd) /// 01ae <name id>.W void clif_parse_SelectArrow(int fd,struct map_session_data *sd) { - if (pc_istrading(sd)) { - //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); - clif_menuskill_clear(sd); - return; - } - switch (sd->menuskill_id) { - case AC_MAKINGARROW: - skill_arrow_create(sd,RFIFOW(fd,2)); - break; - case SA_CREATECON: - skill_produce_mix(sd,SA_CREATECON,RFIFOW(fd,2),0,0,0, 1); - break; - case WL_READING_SB: - skill_spellbook(sd,RFIFOW(fd,2)); - break; - case GC_POISONINGWEAPON: - skill_poisoningweapon(sd,RFIFOW(fd,2)); - break; - case NC_MAGICDECOY: - skill_magicdecoy(sd,RFIFOW(fd,2)); - break; - } - - clif_menuskill_clear(sd); + if (pc_istrading(sd)) { + //Make it fail to avoid shop exploits where you sell something different than you see. + clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); + clif_menuskill_clear(sd); + return; + } + switch( sd->menuskill_id ) { + case AC_MAKINGARROW: + skill_arrow_create(sd,RFIFOW(fd,2)); + break; + case SA_CREATECON: + skill_produce_mix(sd,SA_CREATECON,RFIFOW(fd,2),0,0,0, 1); + break; + case WL_READING_SB: + skill_spellbook(sd,RFIFOW(fd,2)); + break; + case GC_POISONINGWEAPON: + skill_poisoningweapon(sd,RFIFOW(fd,2)); + break; + case NC_MAGICDECOY: + skill_magicdecoy(sd,RFIFOW(fd,2)); + break; + } + + clif_menuskill_clear(sd); } @@ -11100,10 +11225,10 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd) /// 01ce <skill id>.L void clif_parse_AutoSpell(int fd,struct map_session_data *sd) { - if (sd->menuskill_id != SA_AUTOSPELL) - return; - skill_autospell(sd,RFIFOL(fd,2)); - clif_menuskill_clear(sd); + if (sd->menuskill_id != SA_AUTOSPELL) + return; + skill_autospell(sd,RFIFOL(fd,2)); + clif_menuskill_clear(sd); } @@ -11111,9 +11236,9 @@ void clif_parse_AutoSpell(int fd,struct map_session_data *sd) /// 017a <card index>.W void clif_parse_UseCard(int fd,struct map_session_data *sd) { - if (sd->state.trading != 0) - return; - clif_use_card(sd,RFIFOW(fd,2)-2); + if (sd->state.trading != 0) + return; + clif_use_card(sd,RFIFOW(fd,2)-2); } @@ -11121,9 +11246,9 @@ void clif_parse_UseCard(int fd,struct map_session_data *sd) /// 017c <card index>.W <equip index>.W void clif_parse_InsertCard(int fd,struct map_session_data *sd) { - if (sd->state.trading != 0) - return; - pc_insert_card(sd,RFIFOW(fd,2)-2,RFIFOW(fd,4)-2); + if (sd->state.trading != 0) + return; + pc_insert_card(sd,RFIFOW(fd,2)-2,RFIFOW(fd,4)-2); } @@ -11133,10 +11258,10 @@ void clif_parse_InsertCard(int fd,struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_SolveCharName(int fd, struct map_session_data *sd) { - int charid; + int charid; - charid = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - map_reqnickdb(sd, charid); + charid = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + map_reqnickdb(sd, charid); } @@ -11146,33 +11271,32 @@ void clif_parse_SolveCharName(int fd, struct map_session_data *sd) /// type: /// 0 = state /// 1 = skill -void clif_parse_ResetChar(int fd, struct map_session_data *sd) -{ - char cmd[15]; +void clif_parse_ResetChar(int fd, struct map_session_data *sd) { + char cmd[15]; - if (RFIFOW(fd,2)) - sprintf(cmd,"%cresetskill",atcommand_symbol); - else - sprintf(cmd,"%cresetstat",atcommand_symbol); + if( RFIFOW(fd,2) ) + sprintf(cmd,"%cresetskill",atcommand_symbol); + else + sprintf(cmd,"%cresetstat",atcommand_symbol); - is_atcommand(fd, sd, cmd, 1); + is_atcommand(fd, sd, cmd, 1); } /// /lb /nlb (CZ_LOCALBROADCAST). /// Request to broadcast a message on current map. /// 019c <packet len>.W <text>.?B -void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd) +void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd) { - char command[CHAT_SIZE_MAX+16]; - char *msg = (char *)RFIFOP(fd,4); - unsigned int len = RFIFOW(fd,2)-4; + char command[CHAT_SIZE_MAX+16]; + char* msg = (char*)RFIFOP(fd,4); + unsigned int len = RFIFOW(fd,2)-4; - // as the length varies depending on the command used, just block unreasonably long strings - mes_len_check(msg, len, CHAT_SIZE_MAX); + // as the length varies depending on the command used, just block unreasonably long strings + mes_len_check(msg, len, CHAT_SIZE_MAX); - sprintf(command, "%clkami %s", atcommand_symbol, msg); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%clkami %s", atcommand_symbol, msg); + is_atcommand(fd, sd, command, 1); } @@ -11182,20 +11306,21 @@ void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) { - int item_index, item_amount; + int item_index, item_amount; - if (pc_istrading(sd)) - return; + if (pc_istrading(sd)) + return; - item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; - item_amount = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); - if (item_index < 0 || item_index >= MAX_INVENTORY || item_amount < 1) - return; + item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; + item_amount = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); + if (item_index < 0 || item_index >= MAX_INVENTORY || item_amount < 1) + return; - if (sd->state.storage_flag == 1) - storage_storageadd(sd, item_index, item_amount); - else if (sd->state.storage_flag == 2) - storage_guild_storageadd(sd, item_index, item_amount); + if (sd->state.storage_flag == 1) + storage_storageadd(sd, item_index, item_amount); + else + if (sd->state.storage_flag == 2) + storage_guild_storageadd(sd, item_index, item_amount); } @@ -11205,15 +11330,16 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) { - int item_index, item_amount; + int item_index, item_amount; - item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-1; - item_amount = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); + item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-1; + item_amount = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); - if (sd->state.storage_flag == 1) - storage_storageget(sd, item_index, item_amount); - else if (sd->state.storage_flag == 2) - storage_guild_storageget(sd, item_index, item_amount); + if (sd->state.storage_flag == 1) + storage_storageget(sd, item_index, item_amount); + else + if(sd->state.storage_flag == 2) + storage_guild_storageget(sd, item_index, item_amount); } @@ -11221,15 +11347,16 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) /// 0129 <index>.W <amount>.L void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) { - if (sd->state.vending) - return; - if (!pc_iscarton(sd)) - return; + if( sd->state.vending ) + return; + if (!pc_iscarton(sd)) + return; - if (sd->state.storage_flag == 1) - storage_storageaddfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); - else if (sd->state.storage_flag == 2) - storage_guild_storageaddfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); + if (sd->state.storage_flag == 1) + storage_storageaddfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); + else + if (sd->state.storage_flag == 2) + storage_guild_storageaddfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4)); } @@ -11237,15 +11364,16 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd) /// 0128 <index>.W <amount>.L void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) { - if (sd->state.vending) - return; - if (!pc_iscarton(sd)) - return; + if( sd->state.vending ) + return; + if (!pc_iscarton(sd)) + return; - if (sd->state.storage_flag == 1) - storage_storagegettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4)); - else if (sd->state.storage_flag == 2) - storage_guild_storagegettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4)); + if (sd->state.storage_flag == 1) + storage_storagegettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4)); + else + if (sd->state.storage_flag == 2) + storage_guild_storagegettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4)); } @@ -11253,10 +11381,11 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd) /// 00f7 void clif_parse_CloseKafra(int fd, struct map_session_data *sd) { - if (sd->state.storage_flag == 1) - storage_storageclose(sd); - else if (sd->state.storage_flag == 2) - storage_guild_storageclose(sd); + if( sd->state.storage_flag == 1 ) + storage_storageclose(sd); + else + if( sd->state.storage_flag == 2 ) + storage_guild_storageclose(sd); } @@ -11268,14 +11397,14 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd) /// 8 = too many wrong passwords /// ? = ignored /// NOTE: This packet is only available on certain non-kRO clients. -void clif_storagepassword(struct map_session_data *sd, short info) +void clif_storagepassword(struct map_session_data* sd, short info) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x23a)); - WFIFOW(fd,0) = 0x23a; - WFIFOW(fd,2) = info; - WFIFOSET(fd,packet_len(0x23a)); + WFIFOHEAD(fd,packet_len(0x23a)); + WFIFOW(fd,0) = 0x23a; + WFIFOW(fd,2) = info; + WFIFOSET(fd,packet_len(0x23a)); } @@ -11287,7 +11416,7 @@ void clif_storagepassword(struct map_session_data *sd, short info) /// NOTE: This packet is only available on certain non-kRO clients. void clif_parse_StoragePassword(int fd, struct map_session_data *sd) { - //TODO + //TODO } @@ -11301,15 +11430,15 @@ void clif_parse_StoragePassword(int fd, struct map_session_data *sd) /// 8 = too many wrong passwords /// ? = ignored /// NOTE: This packet is only available on certain non-kRO clients. -void clif_storagepassword_result(struct map_session_data *sd, short result, short error_count) +void clif_storagepassword_result(struct map_session_data* sd, short result, short error_count) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x23c)); - WFIFOW(fd,0) = 0x23c; - WFIFOW(fd,2) = result; - WFIFOW(fd,4) = error_count; - WFIFOSET(fd,packet_len(0x23c)); + WFIFOHEAD(fd,packet_len(0x23c)); + WFIFOW(fd,0) = 0x23c; + WFIFOW(fd,2) = result; + WFIFOW(fd,4) = error_count; + WFIFOSET(fd,packet_len(0x23c)); } @@ -11318,40 +11447,42 @@ void clif_storagepassword_result(struct map_session_data *sd, short result, shor /// 01e8 <party name>.24B <item pickup rule>.B <item share rule>.B (CZ_MAKE_GROUP2) void clif_parse_CreateParty(int fd, struct map_session_data *sd) { - char *name = (char *)RFIFOP(fd,2); - name[NAME_LENGTH-1] = '\0'; + char* name = (char*)RFIFOP(fd,2); + name[NAME_LENGTH-1] = '\0'; - if (map[sd->bl.m].flag.partylock) { - // Party locked. - clif_displaymessage(fd, msg_txt(227)); - return; - } - if (battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 7) { - clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,4); - return; - } + if( map[sd->bl.m].flag.partylock ) + {// Party locked. + clif_displaymessage(fd, msg_txt(227)); + return; + } + if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 7 ) + { + clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,4); + return; + } - party_create(sd,name,0,0); + party_create(sd,name,0,0); } void clif_parse_CreateParty2(int fd, struct map_session_data *sd) { - char *name = (char *)RFIFOP(fd,2); - int item1 = RFIFOB(fd,26); - int item2 = RFIFOB(fd,27); - name[NAME_LENGTH-1] = '\0'; + char* name = (char*)RFIFOP(fd,2); + int item1 = RFIFOB(fd,26); + int item2 = RFIFOB(fd,27); + name[NAME_LENGTH-1] = '\0'; - if (map[sd->bl.m].flag.partylock) { - // Party locked. - clif_displaymessage(fd, msg_txt(227)); - return; - } - if (battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 7) { - clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,4); - return; - } + if( map[sd->bl.m].flag.partylock ) + {// Party locked. + clif_displaymessage(fd, msg_txt(227)); + return; + } + if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 7 ) + { + clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,4); + return; + } - party_create(sd,name,item1,item2); + party_create(sd,name,item1,item2); } @@ -11360,46 +11491,46 @@ void clif_parse_CreateParty2(int fd, struct map_session_data *sd) /// 02c4 <char name>.24B (CZ_PARTY_JOIN_REQ) void clif_parse_PartyInvite(int fd, struct map_session_data *sd) { - struct map_session_data *t_sd; + struct map_session_data *t_sd; - if (map[sd->bl.m].flag.partylock) { - // Party locked. - clif_displaymessage(fd, msg_txt(227)); - return; - } + if(map[sd->bl.m].flag.partylock) + {// Party locked. + clif_displaymessage(fd, msg_txt(227)); + return; + } - t_sd = map_id2sd(RFIFOL(fd,2)); + t_sd = map_id2sd(RFIFOL(fd,2)); - if (t_sd && t_sd->state.noask) { - // @noask [LuzZza] - clif_noask_sub(sd, t_sd, 1); - return; - } + if(t_sd && t_sd->state.noask) + {// @noask [LuzZza] + clif_noask_sub(sd, t_sd, 1); + return; + } - party_invite(sd, t_sd); + party_invite(sd, t_sd); } void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) { - struct map_session_data *t_sd; - char *name = (char *)RFIFOP(fd,2); - name[NAME_LENGTH-1] = '\0'; + struct map_session_data *t_sd; + char *name = (char*)RFIFOP(fd,2); + name[NAME_LENGTH-1] = '\0'; - if (map[sd->bl.m].flag.partylock) { - // Party locked. - clif_displaymessage(fd, msg_txt(227)); - return; - } + if(map[sd->bl.m].flag.partylock) + {// Party locked. + clif_displaymessage(fd, msg_txt(227)); + return; + } - t_sd = map_nick2sd(name); + t_sd = map_nick2sd(name); - if (t_sd && t_sd->state.noask) { - // @noask [LuzZza] - clif_noask_sub(sd, t_sd, 1); - return; - } + if(t_sd && t_sd->state.noask) + {// @noask [LuzZza] + clif_noask_sub(sd, t_sd, 1); + return; + } - party_invite(sd, t_sd); + party_invite(sd, t_sd); } @@ -11411,12 +11542,12 @@ void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) /// 1 = accept void clif_parse_ReplyPartyInvite(int fd,struct map_session_data *sd) { - party_reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6)); + party_reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd) { - party_reply_invite(sd,RFIFOL(fd,2),RFIFOB(fd,6)); + party_reply_invite(sd,RFIFOL(fd,2),RFIFOB(fd,6)); } @@ -11424,12 +11555,12 @@ void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd) /// 0100 void clif_parse_LeaveParty(int fd, struct map_session_data *sd) { - if (map[sd->bl.m].flag.partylock) { - //Guild locked. - clif_displaymessage(fd, msg_txt(227)); - return; - } - party_leave(sd); + if(map[sd->bl.m].flag.partylock) + { //Guild locked. + clif_displaymessage(fd, msg_txt(227)); + return; + } + party_leave(sd); } @@ -11437,12 +11568,12 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd) /// 0103 <account id>.L <char name>.24B void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) { - if (map[sd->bl.m].flag.partylock) { - //Guild locked. - clif_displaymessage(fd, msg_txt(227)); - return; - } - party_removemember(sd,RFIFOL(fd,2),(char *)RFIFOP(fd,6)); + if(map[sd->bl.m].flag.partylock) + { //Guild locked. + clif_displaymessage(fd, msg_txt(227)); + return; + } + party_removemember(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6)); } @@ -11451,68 +11582,68 @@ void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) /// 07d7 <exp share rule>.L <item pickup rule>.B <item share rule>.B (CZ_GROUPINFO_CHANGE_V2) void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) { - struct party_data *p; - int i; + struct party_data *p; + int i; - if (!sd->status.party_id) - return; + if( !sd->status.party_id ) + return; - p = party_search(sd->status.party_id); - if (p == NULL) - return; + p = party_search(sd->status.party_id); + if( p == NULL ) + return; - ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd); - if (i == MAX_PARTY) - return; //Shouldn't happen + ARR_FIND( 0, MAX_PARTY, i, p->data[i].sd == sd ); + if( i == MAX_PARTY ) + return; //Shouldn't happen - if (!p->party.member[i].leader) - return; + if( !p->party.member[i].leader ) + return; #if PACKETVER < 20090603 - //Client can't change the item-field - party_changeoption(sd, RFIFOL(fd,2), p->party.item); + //Client can't change the item-field + party_changeoption(sd, RFIFOL(fd,2), p->party.item); #else - party_changeoption(sd, RFIFOL(fd,2), ((RFIFOB(fd,6)?1:0)|(RFIFOB(fd,7)?2:0))); + party_changeoption(sd, RFIFOL(fd,2), ((RFIFOB(fd,6)?1:0)|(RFIFOB(fd,7)?2:0))); #endif } /// Validates and processes party messages (CZ_REQUEST_CHAT_PARTY). /// 0108 <packet len>.W <text>.?B (<name> : <message>) 00 -void clif_parse_PartyMessage(int fd, struct map_session_data *sd) +void clif_parse_PartyMessage(int fd, struct map_session_data* sd) { - const char *text = (char *)RFIFOP(fd,4); - int textlen = RFIFOW(fd,2) - 4; + const char* text = (char*)RFIFOP(fd,4); + int textlen = RFIFOW(fd,2) - 4; - char *name, *message; - int namelen, messagelen; + char *name, *message; + int namelen, messagelen; - // validate packet and retrieve name and message - if (!clif_process_message(sd, 0, &name, &namelen, &message, &messagelen)) - return; + // validate packet and retrieve name and message + if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) ) + return; - if (is_atcommand(fd, sd, message, 1)) - return; + if( is_atcommand(fd, sd, message, 1) ) + return; - if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) - return; + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + return; - if (battle_config.min_chat_delay) { - //[Skotlex] - if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) - return; - sd->cantalk_tick = gettick() + battle_config.min_chat_delay; - } + if( battle_config.min_chat_delay ) + { //[Skotlex] + if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) + return; + sd->cantalk_tick = gettick() + battle_config.min_chat_delay; + } - party_send_message(sd, text, textlen); + party_send_message(sd, text, textlen); } /// Changes Party Leader (CZ_CHANGE_GROUP_MASTER). /// 07da <account id>.L -void clif_parse_PartyChangeLeader(int fd, struct map_session_data *sd) +void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) { - party_changeleader(sd, map_id2sd(RFIFOL(fd,2))); + party_changeleader(sd, map_id2sd(RFIFOL(fd,2))); } @@ -11521,17 +11652,17 @@ void clif_parse_PartyChangeLeader(int fd, struct map_session_data *sd) /// Request to register a party booking advertisment (CZ_PARTY_BOOKING_REQ_REGISTER). /// 0802 <level>.W <map id>.W { <job>.W }*6 -void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data *sd) +void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data* sd) { - short level = RFIFOW(fd,2); - short mapid = RFIFOW(fd,4); - short job[PARTY_BOOKING_JOBS]; - int i; + short level = RFIFOW(fd,2); + short mapid = RFIFOW(fd,4); + short job[PARTY_BOOKING_JOBS]; + int i; - for (i=0; i<PARTY_BOOKING_JOBS; i++) - job[i] = RFIFOB(fd,6+i*2); + for(i=0; i<PARTY_BOOKING_JOBS; i++) + job[i] = RFIFOB(fd,6+i*2); - party_booking_register(sd, level, mapid, job); + party_booking_register(sd, level, mapid, job); } @@ -11543,26 +11674,26 @@ void clif_parse_PartyBookingRegisterReq(int fd, struct map_session_data *sd) /// 2 = already registered void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x803)); - WFIFOW(fd,0) = 0x803; - WFIFOW(fd,2) = flag; - WFIFOSET(fd,packet_len(0x803)); + WFIFOHEAD(fd,packet_len(0x803)); + WFIFOW(fd,0) = 0x803; + WFIFOW(fd,2) = flag; + WFIFOSET(fd,packet_len(0x803)); } /// Request to search for party booking advertisments (CZ_PARTY_BOOKING_REQ_SEARCH). /// 0804 <level>.W <map id>.W <job>.W <last index>.L <result count>.W -void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data *sd) +void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data* sd) { - short level = RFIFOW(fd,2); - short mapid = RFIFOW(fd,4); - short job = RFIFOW(fd,6); - unsigned long lastindex = RFIFOL(fd,8); - short resultcount = RFIFOW(fd,12); + short level = RFIFOW(fd,2); + short mapid = RFIFOW(fd,4); + short job = RFIFOW(fd,6); + unsigned long lastindex = RFIFOL(fd,8); + short resultcount = RFIFOW(fd,12); - party_booking_search(sd, level, mapid, job, lastindex, resultcount); + party_booking_search(sd, level, mapid, job, lastindex, resultcount); } @@ -11571,35 +11702,36 @@ void clif_parse_PartyBookingSearchReq(int fd, struct map_session_data *sd) /// more results: /// 0 = no /// 1 = yes -void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info **results, int count, bool more_result) -{ - int i, j; - int size = sizeof(struct party_booking_ad_info); // structure size (48) - struct party_booking_ad_info *pb_ad; - WFIFOHEAD(fd,size*count + 5); - WFIFOW(fd,0) = 0x805; - WFIFOW(fd,2) = size*count + 5; - WFIFOB(fd,4) = more_result; - for (i=0; i<count; i++) { - pb_ad = results[i]; - WFIFOL(fd,i*size+5) = pb_ad->index; - memcpy(WFIFOP(fd,i*size+9),pb_ad->charname,NAME_LENGTH); - WFIFOL(fd,i*size+33) = pb_ad->starttime; // FIXME: This is expire time - WFIFOW(fd,i*size+37) = pb_ad->p_detail.level; - WFIFOW(fd,i*size+39) = pb_ad->p_detail.mapid; - for (j=0; j<PARTY_BOOKING_JOBS; j++) - WFIFOW(fd,i*size+41+j*2) = pb_ad->p_detail.job[j]; - } - WFIFOSET(fd,WFIFOW(fd,2)); +void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results, int count, bool more_result) +{ + int i, j; + int size = sizeof(struct party_booking_ad_info); // structure size (48) + struct party_booking_ad_info *pb_ad; + WFIFOHEAD(fd,size*count + 5); + WFIFOW(fd,0) = 0x805; + WFIFOW(fd,2) = size*count + 5; + WFIFOB(fd,4) = more_result; + for(i=0; i<count; i++) + { + pb_ad = results[i]; + WFIFOL(fd,i*size+5) = pb_ad->index; + memcpy(WFIFOP(fd,i*size+9),pb_ad->charname,NAME_LENGTH); + WFIFOL(fd,i*size+33) = pb_ad->starttime; // FIXME: This is expire time + WFIFOW(fd,i*size+37) = pb_ad->p_detail.level; + WFIFOW(fd,i*size+39) = pb_ad->p_detail.mapid; + for(j=0; j<PARTY_BOOKING_JOBS; j++) + WFIFOW(fd,i*size+41+j*2) = pb_ad->p_detail.job[j]; + } + WFIFOSET(fd,WFIFOW(fd,2)); } /// Request to delete own party booking advertisment (CZ_PARTY_BOOKING_REQ_DELETE). /// 0806 -void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data *sd) +void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd) { - if (party_booking_delete(sd)) - clif_PartyBookingDeleteAck(sd, 0); + if(party_booking_delete(sd)) + clif_PartyBookingDeleteAck(sd, 0); } @@ -11610,131 +11742,131 @@ void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data *sd) /// 1 = success (auto-removed expired ad) /// 2 = failure /// 3 = nothing registered -void clif_PartyBookingDeleteAck(struct map_session_data *sd, int flag) +void clif_PartyBookingDeleteAck(struct map_session_data* sd, int flag) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x807)); - WFIFOW(fd,0) = 0x807; - WFIFOW(fd,2) = flag; - WFIFOSET(fd,packet_len(0x807)); + WFIFOHEAD(fd,packet_len(0x807)); + WFIFOW(fd,0) = 0x807; + WFIFOW(fd,2) = flag; + WFIFOSET(fd,packet_len(0x807)); } /// Request to update party booking advertisment (CZ_PARTY_BOOKING_REQ_UPDATE). /// 0808 { <job>.W }*6 -void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data *sd) +void clif_parse_PartyBookingUpdateReq(int fd, struct map_session_data* sd) { - short job[PARTY_BOOKING_JOBS]; - int i; + short job[PARTY_BOOKING_JOBS]; + int i; - for (i=0; i<PARTY_BOOKING_JOBS; i++) - job[i] = RFIFOW(fd,2+i*2); + for(i=0; i<PARTY_BOOKING_JOBS; i++) + job[i] = RFIFOW(fd,2+i*2); - party_booking_update(sd, job); + party_booking_update(sd, job); } /// Notification about new party booking advertisment (ZC_PARTY_BOOKING_NOTIFY_INSERT). /// 0809 <index>.L <char name>.24B <expire time>.L <level>.W <map id>.W { <job>.W }*6 -void clif_PartyBookingInsertNotify(struct map_session_data *sd, struct party_booking_ad_info *pb_ad) +void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad) { - int i; - uint8 buf[38+PARTY_BOOKING_JOBS*2]; + int i; + uint8 buf[38+PARTY_BOOKING_JOBS*2]; - if (pb_ad == NULL) return; + if(pb_ad == NULL) return; - WBUFW(buf,0) = 0x809; - WBUFL(buf,2) = pb_ad->index; - memcpy(WBUFP(buf,6),pb_ad->charname,NAME_LENGTH); - WBUFL(buf,30) = pb_ad->starttime; // FIXME: This is expire time - WBUFW(buf,34) = pb_ad->p_detail.level; - WBUFW(buf,36) = pb_ad->p_detail.mapid; - for (i=0; i<PARTY_BOOKING_JOBS; i++) - WBUFW(buf,38+i*2) = pb_ad->p_detail.job[i]; + WBUFW(buf,0) = 0x809; + WBUFL(buf,2) = pb_ad->index; + memcpy(WBUFP(buf,6),pb_ad->charname,NAME_LENGTH); + WBUFL(buf,30) = pb_ad->starttime; // FIXME: This is expire time + WBUFW(buf,34) = pb_ad->p_detail.level; + WBUFW(buf,36) = pb_ad->p_detail.mapid; + for(i=0; i<PARTY_BOOKING_JOBS; i++) + WBUFW(buf,38+i*2) = pb_ad->p_detail.job[i]; - clif_send(buf, packet_len(0x809), &sd->bl, ALL_CLIENT); + clif_send(buf, packet_len(0x809), &sd->bl, ALL_CLIENT); } /// Notification about updated party booking advertisment (ZC_PARTY_BOOKING_NOTIFY_UPDATE). /// 080a <index>.L { <job>.W }*6 -void clif_PartyBookingUpdateNotify(struct map_session_data *sd, struct party_booking_ad_info *pb_ad) +void clif_PartyBookingUpdateNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad) { - int i; - uint8 buf[6+PARTY_BOOKING_JOBS*2]; + int i; + uint8 buf[6+PARTY_BOOKING_JOBS*2]; - if (pb_ad == NULL) return; + if(pb_ad == NULL) return; - WBUFW(buf,0) = 0x80a; - WBUFL(buf,2) = pb_ad->index; - for (i=0; i<PARTY_BOOKING_JOBS; i++) - WBUFW(buf,6+i*2) = pb_ad->p_detail.job[i]; - clif_send(buf,packet_len(0x80a),&sd->bl,ALL_CLIENT); // Now UPDATE all client. + WBUFW(buf,0) = 0x80a; + WBUFL(buf,2) = pb_ad->index; + for(i=0; i<PARTY_BOOKING_JOBS; i++) + WBUFW(buf,6+i*2) = pb_ad->p_detail.job[i]; + clif_send(buf,packet_len(0x80a),&sd->bl,ALL_CLIENT); // Now UPDATE all client. } /// Notification about deleted party booking advertisment (ZC_PARTY_BOOKING_NOTIFY_DELETE). /// 080b <index>.L -void clif_PartyBookingDeleteNotify(struct map_session_data *sd, int index) +void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index) { - uint8 buf[6]; + uint8 buf[6]; - WBUFW(buf,0) = 0x80b; - WBUFL(buf,2) = index; + WBUFW(buf,0) = 0x80b; + WBUFL(buf,2) = index; - clif_send(buf, packet_len(0x80b), &sd->bl, ALL_CLIENT); // Now UPDATE all client. + clif_send(buf, packet_len(0x80b), &sd->bl, ALL_CLIENT); // Now UPDATE all client. } /// Request to close own vending (CZ_REQ_CLOSESTORE). /// 012e -void clif_parse_CloseVending(int fd, struct map_session_data *sd) +void clif_parse_CloseVending(int fd, struct map_session_data* sd) { - vending_closevending(sd); + vending_closevending(sd); } /// Request to open a vending shop (CZ_REQ_BUY_FROMMC). /// 0130 <account id>.L -void clif_parse_VendingListReq(int fd, struct map_session_data *sd) +void clif_parse_VendingListReq(int fd, struct map_session_data* sd) { - if (sd->npc_id) { - // using an NPC - return; - } - vending_vendinglistreq(sd,RFIFOL(fd,2)); + if( sd->npc_id ) + {// using an NPC + return; + } + vending_vendinglistreq(sd,RFIFOL(fd,2)); } /// Shop item(s) purchase request (CZ_PC_PURCHASE_ITEMLIST_FROMMC). /// 0134 <packet len>.W <account id>.L { <amount>.W <index>.W }* -void clif_parse_PurchaseReq(int fd, struct map_session_data *sd) +void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) { - int len = (int)RFIFOW(fd,2) - 8; - int id = (int)RFIFOL(fd,4); - const uint8 *data = (uint8 *)RFIFOP(fd,8); + int len = (int)RFIFOW(fd,2) - 8; + int id = (int)RFIFOL(fd,4); + const uint8* data = (uint8*)RFIFOP(fd,8); - vending_purchasereq(sd, id, sd->vended_id, data, len/4); + vending_purchasereq(sd, id, sd->vended_id, data, len/4); - // whether it fails or not, the buy window is closed - sd->vended_id = 0; + // whether it fails or not, the buy window is closed + sd->vended_id = 0; } /// Shop item(s) purchase request (CZ_PC_PURCHASE_ITEMLIST_FROMMC2). /// 0801 <packet len>.W <account id>.L <unique id>.L { <amount>.W <index>.W }* -void clif_parse_PurchaseReq2(int fd, struct map_session_data *sd) +void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) { - int len = (int)RFIFOW(fd,2) - 12; - int aid = (int)RFIFOL(fd,4); - int uid = (int)RFIFOL(fd,8); - const uint8 *data = (uint8 *)RFIFOP(fd,12); + int len = (int)RFIFOW(fd,2) - 12; + int aid = (int)RFIFOL(fd,4); + int uid = (int)RFIFOL(fd,8); + const uint8* data = (uint8*)RFIFOP(fd,12); - vending_purchasereq(sd, aid, uid, data, len/4); + vending_purchasereq(sd, aid, uid, data, len/4); - // whether it fails or not, the buy window is closed - sd->vended_id = 0; + // whether it fails or not, the buy window is closed + sd->vended_id = 0; } @@ -11744,36 +11876,36 @@ void clif_parse_PurchaseReq2(int fd, struct map_session_data *sd) /// result: /// 0 = canceled /// 1 = open -void clif_parse_OpenVending(int fd, struct map_session_data *sd) -{ - short len = (short)RFIFOW(fd,2) - 85; - const char *message = (char *)RFIFOP(fd,4); - bool flag = (bool)RFIFOB(fd,84); - const uint8 *data = (uint8 *)RFIFOP(fd,85); - - if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) - return; - if (map[sd->bl.m].flag.novending) { - clif_displaymessage(sd->fd, msg_txt(276)); // "You can't open a shop on this map" - return; - } - if (map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOVENDING)) { - clif_displaymessage(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." - return; - } +void clif_parse_OpenVending(int fd, struct map_session_data* sd) +{ + short len = (short)RFIFOW(fd,2) - 85; + const char* message = (char*)RFIFOP(fd,4); + bool flag = (bool)RFIFOB(fd,84); + const uint8* data = (uint8*)RFIFOP(fd,85); - if (vending_checknearnpc(&sd->bl)) { - char output[150]; - sprintf(output, msg_txt(662), battle_config.min_npc_vending_distance); - clif_displaymessage(sd->fd, output); - clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); - return; - } + if( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM ) + return; + if( map[sd->bl.m].flag.novending ) { + clif_displaymessage (sd->fd, msg_txt(276)); // "You can't open a shop on this map" + return; + } + if( map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOVENDING) ) { + clif_displaymessage (sd->fd, msg_txt(204)); // "You can't open a shop on this cell." + return; + } - if (message[0] == '\0') // invalid input - return; + if( vending_checknearnpc(&sd->bl) ) { + char output[150]; + sprintf(output, msg_txt(662), battle_config.min_npc_vending_distance); + clif_displaymessage(sd->fd, output); + clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); + return; + } - vending_openvending(sd, message, flag, data, len/8); + if( message[0] == '\0' ) // invalid input + return; + + vending_openvending(sd, message, flag, data, len/8); } @@ -11781,16 +11913,16 @@ void clif_parse_OpenVending(int fd, struct map_session_data *sd) /// 0165 <char id>.L <guild name>.24B void clif_parse_CreateGuild(int fd,struct map_session_data *sd) { - char *name = (char *)RFIFOP(fd,6); - name[NAME_LENGTH-1] = '\0'; + char* name = (char*)RFIFOP(fd,6); + name[NAME_LENGTH-1] = '\0'; - if (map[sd->bl.m].flag.guildlock) { - //Guild locked. - clif_displaymessage(fd, msg_txt(228)); - return; - } + if(map[sd->bl.m].flag.guildlock) + { //Guild locked. + clif_displaymessage(fd, msg_txt(228)); + return; + } - guild_create(sd, name); + guild_create(sd, name); } @@ -11798,7 +11930,7 @@ void clif_parse_CreateGuild(int fd,struct map_session_data *sd) /// 014d void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd) { - clif_guild_masterormember(sd); + clif_guild_masterormember(sd); } @@ -11814,32 +11946,33 @@ void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd) /// 6 = notice void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) { - if (!sd->status.guild_id && !sd->bg_id) - return; - - switch (RFIFOL(fd,2)) { - case 0: // Basic Information Guild, hostile alliance information - clif_guild_basicinfo(sd); - clif_guild_allianceinfo(sd); - break; - case 1: // Members list, list job title - clif_guild_positionnamelist(sd); - clif_guild_memberlist(sd); - break; - case 2: // List job title, title information list - clif_guild_positionnamelist(sd); - clif_guild_positioninfolist(sd); - break; - case 3: // Skill list - clif_guild_skillinfo(sd); - break; - case 4: // Expulsion list - clif_guild_expulsionlist(sd); - break; - default: - ShowError("clif: guild request info: unknown type %d\n", RFIFOL(fd,2)); - break; - } + if( !sd->status.guild_id && !sd->bg_id ) + return; + + switch( RFIFOL(fd,2) ) + { + case 0: // Basic Information Guild, hostile alliance information + clif_guild_basicinfo(sd); + clif_guild_allianceinfo(sd); + break; + case 1: // Members list, list job title + clif_guild_positionnamelist(sd); + clif_guild_memberlist(sd); + break; + case 2: // List job title, title information list + clif_guild_positionnamelist(sd); + clif_guild_positioninfolist(sd); + break; + case 3: // Skill list + clif_guild_skillinfo(sd); + break; + case 4: // Expulsion list + clif_guild_expulsionlist(sd); + break; + default: + ShowError("clif: guild request info: unknown type %d\n", RFIFOL(fd,2)); + break; + } } @@ -11847,14 +11980,14 @@ void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) /// 0161 <packet len>.W { <position id>.L <mode>.L <ranking>.L <pay rate>.L <name>.24B }* void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) { - int i; + int i; - if (!sd->state.gmaster_flag) - return; + if(!sd->state.gmaster_flag) + return; - for (i = 4; i < RFIFOW(fd,2); i += 40) { - guild_change_position(sd->status.guild_id, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), (char *)RFIFOP(fd,i+16)); - } + for(i = 4; i < RFIFOW(fd,2); i += 40 ){ + guild_change_position(sd->status.guild_id, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), (char*)RFIFOP(fd,i+16)); + } } @@ -11862,15 +11995,15 @@ void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) /// 0155 <packet len>.W { <account id>.L <char id>.L <position id>.L }* void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd) { - int i; + int i; - if (!sd->state.gmaster_flag) - return; + if(!sd->state.gmaster_flag) + return; - for (i=4; i<RFIFOW(fd,2); i+=12) { - guild_change_memberposition(sd->status.guild_id, - RFIFOL(fd,i),RFIFOL(fd,i+4),RFIFOL(fd,i+8)); - } + for(i=4;i<RFIFOW(fd,2);i+=12){ + guild_change_memberposition(sd->status.guild_id, + RFIFOL(fd,i),RFIFOL(fd,i+4),RFIFOL(fd,i+8)); + } } @@ -11878,28 +12011,28 @@ void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd) /// 0151 <guild id>.L void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd) { - struct guild *g; - int guild_id = RFIFOL(fd,2); + struct guild* g; + int guild_id = RFIFOL(fd,2); - if ((g = guild_search(guild_id)) != NULL) - clif_guild_emblem(sd,g); + if( (g = guild_search(guild_id)) != NULL ) + clif_guild_emblem(sd,g); } /// Validates data of a guild emblem (compressed bitmap) -static bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) +static bool clif_validate_emblem(const uint8* emblem, unsigned long emblem_len) { - bool success; - uint8 buf[1800]; // no well-formed emblem bitmap is larger than 1782 (24 bit) / 1654 (8 bit) bytes - unsigned long buf_len = sizeof(buf); + bool success; + uint8 buf[1800]; // no well-formed emblem bitmap is larger than 1782 (24 bit) / 1654 (8 bit) bytes + unsigned long buf_len = sizeof(buf); - success = (decode_zip(buf, &buf_len, emblem, emblem_len) == 0 && buf_len >= 18) // sizeof(BITMAPFILEHEADER) + sizeof(biSize) of the following info header struct - && RBUFW(buf,0) == 0x4d42 // BITMAPFILEHEADER.bfType (signature) - && RBUFL(buf,2) == buf_len // BITMAPFILEHEADER.bfSize (file size) - && RBUFL(buf,10) < buf_len // BITMAPFILEHEADER.bfOffBits (offset to bitmap bits) - ; + success = ( decode_zip(buf, &buf_len, emblem, emblem_len) == 0 && buf_len >= 18 ) // sizeof(BITMAPFILEHEADER) + sizeof(biSize) of the following info header struct + && RBUFW(buf,0) == 0x4d42 // BITMAPFILEHEADER.bfType (signature) + && RBUFL(buf,2) == buf_len // BITMAPFILEHEADER.bfSize (file size) + && RBUFL(buf,10) < buf_len // BITMAPFILEHEADER.bfOffBits (offset to bitmap bits) + ; - return success; + return success; } @@ -11907,38 +12040,39 @@ static bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) /// 0153 <packet len>.W <emblem data>.?B void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd) { - unsigned long emblem_len = RFIFOW(fd,2)-4; - const uint8 *emblem = RFIFOP(fd,4); + unsigned long emblem_len = RFIFOW(fd,2)-4; + const uint8* emblem = RFIFOP(fd,4); - if (!emblem_len || !sd->state.gmaster_flag) - return; + if( !emblem_len || !sd->state.gmaster_flag ) + return; - if (!clif_validate_emblem(emblem, emblem_len)) { - ShowWarning("clif_parse_GuildChangeEmblem: Rejected malformed guild emblem (size=%lu, accound_id=%d, char_id=%d, guild_id=%d).\n", emblem_len, sd->status.account_id, sd->status.char_id, sd->status.guild_id); - return; - } + if( !clif_validate_emblem(emblem, emblem_len) ) + { + ShowWarning("clif_parse_GuildChangeEmblem: Rejected malformed guild emblem (size=%lu, accound_id=%d, char_id=%d, guild_id=%d).\n", emblem_len, sd->status.account_id, sd->status.char_id, sd->status.guild_id); + return; + } - guild_change_emblem(sd, emblem_len, (const char *)emblem); + guild_change_emblem(sd, emblem_len, (const char*)emblem); } /// Guild notice update request (CZ_GUILD_NOTICE). /// 016e <guild id>.L <msg1>.60B <msg2>.120B -void clif_parse_GuildChangeNotice(int fd, struct map_session_data *sd) +void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd) { - int guild_id = RFIFOL(fd,2); - char *msg1 = (char *)RFIFOP(fd,6); - char *msg2 = (char *)RFIFOP(fd,66); + int guild_id = RFIFOL(fd,2); + char* msg1 = (char*)RFIFOP(fd,6); + char* msg2 = (char*)RFIFOP(fd,66); - if (!sd->state.gmaster_flag) - return; + if(!sd->state.gmaster_flag) + return; - // compensate for some client defects when using multilanguage mode - if (msg1[0] == '|' && msg1[3] == '|') msg1+= 3; // skip duplicate marker - if (msg2[0] == '|' && msg2[3] == '|') msg2+= 3; // skip duplicate marker - if (msg2[0] == '|') msg2[strnlen(msg2, MAX_GUILDMES2)-1] = '\0'; // delete extra space at the end of string + // compensate for some client defects when using multilanguage mode + if (msg1[0] == '|' && msg1[3] == '|') msg1+= 3; // skip duplicate marker + if (msg2[0] == '|' && msg2[3] == '|') msg2+= 3; // skip duplicate marker + if (msg2[0] == '|') msg2[strnlen(msg2, MAX_GUILDMES2)-1] = '\0'; // delete extra space at the end of string - guild_change_notice(sd, guild_id, msg1, msg2); + guild_change_notice(sd, guild_id, msg1, msg2); } @@ -11946,23 +12080,23 @@ void clif_parse_GuildChangeNotice(int fd, struct map_session_data *sd) /// 0168 <account id>.L <inviter account id>.L <inviter char id>.L void clif_parse_GuildInvite(int fd,struct map_session_data *sd) { - struct map_session_data *t_sd; + struct map_session_data *t_sd; - if (map[sd->bl.m].flag.guildlock) { - //Guild locked. - clif_displaymessage(fd, msg_txt(228)); - return; - } + if(map[sd->bl.m].flag.guildlock) + { //Guild locked. + clif_displaymessage(fd, msg_txt(228)); + return; + } - t_sd = map_id2sd(RFIFOL(fd,2)); + t_sd = map_id2sd(RFIFOL(fd,2)); - // @noask [LuzZza] - if (t_sd && t_sd->state.noask) { - clif_noask_sub(sd, t_sd, 2); - return; - } + // @noask [LuzZza] + if(t_sd && t_sd->state.noask) { + clif_noask_sub(sd, t_sd, 2); + return; + } - guild_invite(sd,t_sd); + guild_invite(sd,t_sd); } @@ -11973,7 +12107,7 @@ void clif_parse_GuildInvite(int fd,struct map_session_data *sd) /// 1 = accept void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) { - guild_reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6)); + guild_reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } @@ -11981,17 +12115,18 @@ void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) /// 0159 <guild id>.L <account id>.L <char id>.L <reason>.40B void clif_parse_GuildLeave(int fd,struct map_session_data *sd) { - if (map[sd->bl.m].flag.guildlock) { - //Guild locked. - clif_displaymessage(fd, msg_txt(228)); - return; - } - if (sd->bg_id) { - clif_displaymessage(fd, msg_txt(670)); //"You can't leave battleground guilds." - return; - } + if(map[sd->bl.m].flag.guildlock) + { //Guild locked. + clif_displaymessage(fd, msg_txt(228)); + return; + } + if( sd->bg_id ) + { + clif_displaymessage(fd, msg_txt(670)); //"You can't leave battleground guilds." + return; + } - guild_leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char *)RFIFOP(fd,14)); + guild_leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); } @@ -11999,46 +12134,46 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd) /// 015b <guild id>.L <account id>.L <char id>.L <reason>.40B void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) { - if (map[sd->bl.m].flag.guildlock || sd->bg_id) { - // Guild locked. - clif_displaymessage(fd, msg_txt(228)); - return; - } - guild_expulsion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char *)RFIFOP(fd,14)); + if( map[sd->bl.m].flag.guildlock || sd->bg_id ) + { // Guild locked. + clif_displaymessage(fd, msg_txt(228)); + return; + } + guild_expulsion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); } /// Validates and processes guild messages (CZ_GUILD_CHAT). /// 017e <packet len>.W <text>.?B (<name> : <message>) 00 -void clif_parse_GuildMessage(int fd, struct map_session_data *sd) +void clif_parse_GuildMessage(int fd, struct map_session_data* sd) { - const char *text = (char *)RFIFOP(fd,4); - int textlen = RFIFOW(fd,2) - 4; + const char* text = (char*)RFIFOP(fd,4); + int textlen = RFIFOW(fd,2) - 4; - char *name, *message; - int namelen, messagelen; + char *name, *message; + int namelen, messagelen; - // validate packet and retrieve name and message - if (!clif_process_message(sd, 0, &name, &namelen, &message, &messagelen)) - return; + // validate packet and retrieve name and message + if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) ) + return; - if (is_atcommand(fd, sd, message, 1)) - return; + if( is_atcommand(fd, sd, message, 1) ) + return; - if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) - return; + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + return; - if (battle_config.min_chat_delay) { - //[Skotlex] - if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) - return; - sd->cantalk_tick = gettick() + battle_config.min_chat_delay; - } + if( battle_config.min_chat_delay ) + { //[Skotlex] + if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) + return; + sd->cantalk_tick = gettick() + battle_config.min_chat_delay; + } - if (sd->bg_id) - bg_send_message(sd, text, textlen); - else - guild_send_message(sd, text, textlen); + if( sd->bg_id ) + bg_send_message(sd, text, textlen); + else + guild_send_message(sd, text, textlen); } @@ -12046,26 +12181,26 @@ void clif_parse_GuildMessage(int fd, struct map_session_data *sd) /// 0170 <account id>.L <inviter account id>.L <inviter char id>.L void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) { - struct map_session_data *t_sd; + struct map_session_data *t_sd; - if (!sd->state.gmaster_flag) - return; + if(!sd->state.gmaster_flag) + return; - if (map[sd->bl.m].flag.guildlock) { - //Guild locked. - clif_displaymessage(fd, msg_txt(228)); - return; - } + if(map[sd->bl.m].flag.guildlock) + { //Guild locked. + clif_displaymessage(fd, msg_txt(228)); + return; + } - t_sd = map_id2sd(RFIFOL(fd,2)); + t_sd = map_id2sd(RFIFOL(fd,2)); - // @noask [LuzZza] - if (t_sd && t_sd->state.noask) { - clif_noask_sub(sd, t_sd, 3); - return; - } + // @noask [LuzZza] + if(t_sd && t_sd->state.noask) { + clif_noask_sub(sd, t_sd, 3); + return; + } - guild_reqalliance(sd,t_sd); + guild_reqalliance(sd,t_sd); } @@ -12076,7 +12211,7 @@ void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) /// 1 = accept void clif_parse_GuildReplyAlliance(int fd, struct map_session_data *sd) { - guild_reply_reqalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); + guild_reply_reqalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } @@ -12087,15 +12222,15 @@ void clif_parse_GuildReplyAlliance(int fd, struct map_session_data *sd) /// 1 = Enemy void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd) { - if (!sd->state.gmaster_flag) - return; + if(!sd->state.gmaster_flag) + return; - if (map[sd->bl.m].flag.guildlock) { - //Guild locked. - clif_displaymessage(fd, msg_txt(228)); - return; - } - guild_delalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); + if(map[sd->bl.m].flag.guildlock) + { //Guild locked. + clif_displaymessage(fd, msg_txt(228)); + return; + } + guild_delalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } @@ -12103,26 +12238,26 @@ void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd) /// 0180 <account id>.L void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) { - struct map_session_data *t_sd; + struct map_session_data *t_sd; - if (!sd->state.gmaster_flag) - return; + if(!sd->state.gmaster_flag) + return; - if (map[sd->bl.m].flag.guildlock) { - //Guild locked. - clif_displaymessage(fd, msg_txt(228)); - return; - } + if(map[sd->bl.m].flag.guildlock) + { //Guild locked. + clif_displaymessage(fd, msg_txt(228)); + return; + } - t_sd = map_id2sd(RFIFOL(fd,2)); + t_sd = map_id2sd(RFIFOL(fd,2)); - // @noask [LuzZza] - if (t_sd && t_sd->state.noask) { - clif_noask_sub(sd, t_sd, 4); - return; - } + // @noask [LuzZza] + if(t_sd && t_sd->state.noask) { + clif_noask_sub(sd, t_sd, 4); + return; + } - guild_opposition(sd,t_sd); + guild_opposition(sd,t_sd); } @@ -12133,12 +12268,12 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) /// field name and size is same as the one in CH_DELETE_CHAR. void clif_parse_GuildBreak(int fd, struct map_session_data *sd) { - if (map[sd->bl.m].flag.guildlock) { - //Guild locked. - clif_displaymessage(fd, msg_txt(228)); - return; - } - guild_break(sd,(char *)RFIFOP(fd,2)); + if( map[sd->bl.m].flag.guildlock ) + { //Guild locked. + clif_displaymessage(fd, msg_txt(228)); + return; + } + guild_break(sd,(char*)RFIFOP(fd,2)); } @@ -12155,7 +12290,7 @@ void clif_parse_GuildBreak(int fd, struct map_session_data *sd) /// 4 = unequip accessory void clif_parse_PetMenu(int fd, struct map_session_data *sd) { - pet_menu(sd,RFIFOB(fd,2)); + pet_menu(sd,RFIFOB(fd,2)); } @@ -12163,7 +12298,7 @@ void clif_parse_PetMenu(int fd, struct map_session_data *sd) /// 019f <id>.L void clif_parse_CatchPet(int fd, struct map_session_data *sd) { - pet_catch_process2(sd,RFIFOL(fd,2)); + pet_catch_process2(sd,RFIFOL(fd,2)); } @@ -12171,13 +12306,14 @@ void clif_parse_CatchPet(int fd, struct map_session_data *sd) /// 01a7 <index>.W void clif_parse_SelectEgg(int fd, struct map_session_data *sd) { - if (sd->menuskill_id != SA_TAMINGMONSTER || sd->menuskill_val != -1) { - //Forged packet, disconnect them [Kevin] - clif_authfail_fd(fd, 0); - return; - } - pet_select_egg(sd,RFIFOW(fd,2)-2); - clif_menuskill_clear(sd); + if (sd->menuskill_id != SA_TAMINGMONSTER || sd->menuskill_val != -1) + { + //Forged packet, disconnect them [Kevin] + clif_authfail_fd(fd, 0); + return; + } + pet_select_egg(sd,RFIFOW(fd,2)-2); + clif_menuskill_clear(sd); } @@ -12207,8 +12343,8 @@ void clif_parse_SelectEgg(int fd, struct map_session_data *sd) /// 4 = full (so_full) void clif_parse_SendEmotion(int fd, struct map_session_data *sd) { - if (sd->pd) - clif_pet_emotion(sd->pd,RFIFOL(fd,2)); + if(sd->pd) + clif_pet_emotion(sd->pd,RFIFOL(fd,2)); } @@ -12216,7 +12352,7 @@ void clif_parse_SendEmotion(int fd, struct map_session_data *sd) /// 01a5 <name>.24B void clif_parse_ChangePetName(int fd, struct map_session_data *sd) { - pet_change_name(sd,(char *)RFIFOP(fd,2)); + pet_change_name(sd,(char*)RFIFOP(fd,2)); } @@ -12226,60 +12362,62 @@ void clif_parse_ChangePetName(int fd, struct map_session_data *sd) /// NOTE: Also sent when using GM right click menu "(name) force to quit" void clif_parse_GMKick(int fd, struct map_session_data *sd) { - struct block_list *target; - int tid; - - tid = RFIFOL(fd,2); - target = map_id2bl(tid); - if (!target) { - clif_GM_kickack(sd, 0); - return; - } - - switch (target->type) { - case BL_PC: { - char command[NAME_LENGTH+6]; - sprintf(command, "%ckick %s", atcommand_symbol, status_get_name(target)); - is_atcommand(fd, sd, command, 1); - } - break; - - /** - * This one does not invoke any atcommand, so we need to check for permissions. - */ - case BL_MOB: { - char command[100]; - if (!pc_can_use_command(sd, "killmonster", COMMAND_ATCOMMAND)) { - clif_GM_kickack(sd, 0); - return; - } - sprintf(command, "/kick %s (%d)", status_get_name(target), status_get_class(target)); - log_atcommand(sd, command); - status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target' - } - break; - - case BL_NPC: { - char command[NAME_LENGTH+11]; - sprintf(command, "%cunloadnpc %s", atcommand_symbol, status_get_name(target)); - is_atcommand(fd, sd, command, 1); - } - break; - - default: - clif_GM_kickack(sd, 0); - } + struct block_list *target; + int tid; + + tid = RFIFOL(fd,2); + target = map_id2bl(tid); + if (!target) { + clif_GM_kickack(sd, 0); + return; + } + + switch (target->type) { + case BL_PC: + { + char command[NAME_LENGTH+6]; + sprintf(command, "%ckick %s", atcommand_symbol, status_get_name(target)); + is_atcommand(fd, sd, command, 1); + } + break; + + /** + * This one does not invoke any atcommand, so we need to check for permissions. + */ + case BL_MOB: + { + char command[100]; + if( !pc_can_use_command(sd, "killmonster", COMMAND_ATCOMMAND)) { + clif_GM_kickack(sd, 0); + return; + } + sprintf(command, "/kick %s (%d)", status_get_name(target), status_get_class(target)); + log_atcommand(sd, command); + status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target' + } + break; + + case BL_NPC: + { + char command[NAME_LENGTH+11]; + sprintf(command, "%cunloadnpc %s", atcommand_symbol, status_get_name(target)); + is_atcommand(fd, sd, command, 1); + } + break; + + default: + clif_GM_kickack(sd, 0); + } } /// /killall (CZ_DISCONNECT_ALL_CHARACTER). /// Request to disconnect all characters. /// 00ce -void clif_parse_GMKickAll(int fd, struct map_session_data *sd) -{ - char cmd[15]; - sprintf(cmd,"%ckickall",atcommand_symbol); - is_atcommand(fd, sd, cmd, 1); +void clif_parse_GMKickAll(int fd, struct map_session_data* sd) { + char cmd[15]; + sprintf(cmd,"%ckickall",atcommand_symbol); + is_atcommand(fd, sd, cmd, 1); } @@ -12291,33 +12429,33 @@ void clif_parse_GMKickAll(int fd, struct map_session_data *sd) /// Request to warp to a character with given name. /// 01bb <char name>.24B void clif_parse_GMShift(int fd, struct map_session_data *sd) -{ - // FIXME: remove is supposed to receive account name for clients prior 20100803RE - char *player_name; - char command[NAME_LENGTH+8]; +{// FIXME: remove is supposed to receive account name for clients prior 20100803RE + char *player_name; + char command[NAME_LENGTH+8]; - player_name = (char *)RFIFOP(fd,2); - player_name[NAME_LENGTH-1] = '\0'; + player_name = (char*)RFIFOP(fd,2); + player_name[NAME_LENGTH-1] = '\0'; - sprintf(command, "%cjumpto %s", atcommand_symbol, player_name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cjumpto %s", atcommand_symbol, player_name); + is_atcommand(fd, sd, command, 1); } /// /remove (CZ_REMOVE_AID_SSO). /// Request to warp to a character with given account ID. /// 0843 <account id>.L -void clif_parse_GMRemove2(int fd, struct map_session_data *sd) +void clif_parse_GMRemove2(int fd, struct map_session_data* sd) { - int account_id; - struct map_session_data *pl_sd; + int account_id; + struct map_session_data* pl_sd; - account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - if ((pl_sd = map_id2sd(account_id)) != NULL) { - char command[NAME_LENGTH+8]; - sprintf(command, "%cjumpto %s", atcommand_symbol, pl_sd->status.name); - is_atcommand(fd, sd, command, 1); - } + account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + if( (pl_sd = map_id2sd(account_id)) != NULL ) + { + char command[NAME_LENGTH+8]; + sprintf(command, "%cjumpto %s", atcommand_symbol, pl_sd->status.name); + is_atcommand(fd, sd, command, 1); + } } @@ -12329,33 +12467,33 @@ void clif_parse_GMRemove2(int fd, struct map_session_data *sd) /// Request to summon a player with given name to own position. /// 01bd <char name>.24B void clif_parse_GMRecall(int fd, struct map_session_data *sd) -{ - // FIXME: recall is supposed to receive account name for clients prior 20100803RE - char *player_name; - char command [NAME_LENGTH+8]; +{// FIXME: recall is supposed to receive account name for clients prior 20100803RE + char *player_name; + char command [NAME_LENGTH+8]; - player_name = (char *)RFIFOP(fd,2); - player_name[NAME_LENGTH-1] = '\0'; + player_name = (char*)RFIFOP(fd,2); + player_name[NAME_LENGTH-1] = '\0'; - sprintf(command, "%crecall %s", atcommand_symbol, player_name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%crecall %s", atcommand_symbol, player_name); + is_atcommand(fd, sd, command, 1); } /// /recall (CZ_RECALL_SSO). /// Request to summon a player with given account ID to own position. /// 0842 <account id>.L -void clif_parse_GMRecall2(int fd, struct map_session_data *sd) +void clif_parse_GMRecall2(int fd, struct map_session_data* sd) { - int account_id; - struct map_session_data *pl_sd; + int account_id; + struct map_session_data* pl_sd; - account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - if ((pl_sd = map_id2sd(account_id)) != NULL) { - char command[NAME_LENGTH+8]; - sprintf(command, "%crecall %s", atcommand_symbol, pl_sd->status.name); - is_atcommand(fd, sd, command, 1); - } + account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + if( (pl_sd = map_id2sd(account_id)) != NULL ) + { + char command[NAME_LENGTH+8]; + sprintf(command, "%crecall %s", atcommand_symbol, pl_sd->status.name); + is_atcommand(fd, sd, command, 1); + } } @@ -12364,27 +12502,27 @@ void clif_parse_GMRecall2(int fd, struct map_session_data *sd) /// 013f <item/mob name>.24B void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) { - char *monster_item_name; - char command[NAME_LENGTH+10]; + char *monster_item_name; + char command[NAME_LENGTH+10]; - monster_item_name = (char *)RFIFOP(fd,2); - monster_item_name[NAME_LENGTH-1] = '\0'; + monster_item_name = (char*)RFIFOP(fd,2); + monster_item_name[NAME_LENGTH-1] = '\0'; - // FIXME: Should look for item first, then for monster. - // FIXME: /monster takes mob_db Sprite_Name as argument - if (mobdb_searchname(monster_item_name)) { - snprintf(command, sizeof(command)-1, "%cmonster %s", atcommand_symbol, monster_item_name); - is_atcommand(fd, sd, command, 1); - return; - } - // FIXME: Stackables have a quantity of 20. - // FIXME: Equips are supposed to be unidentified. + // FIXME: Should look for item first, then for monster. + // FIXME: /monster takes mob_db Sprite_Name as argument + if( mobdb_searchname(monster_item_name) ) { + snprintf(command, sizeof(command)-1, "%cmonster %s", atcommand_symbol, monster_item_name); + is_atcommand(fd, sd, command, 1); + return; + } + // FIXME: Stackables have a quantity of 20. + // FIXME: Equips are supposed to be unidentified. - if (itemdb_searchname(monster_item_name)) { - snprintf(command, sizeof(command)-1, "%citem %s", atcommand_symbol, monster_item_name); - is_atcommand(fd, sd, command, 1); - return; - } + if( itemdb_searchname(monster_item_name) ) { + snprintf(command, sizeof(command)-1, "%citem %s", atcommand_symbol, monster_item_name); + is_atcommand(fd, sd, command, 1); + return; + } } @@ -12392,13 +12530,12 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) /// 019d <effect state>.L /// effect state: /// TODO: Any OPTION_* ? -void clif_parse_GMHide(int fd, struct map_session_data *sd) -{ - char cmd[6]; +void clif_parse_GMHide(int fd, struct map_session_data *sd) { + char cmd[6]; - sprintf(cmd,"%chide",atcommand_symbol); + sprintf(cmd,"%chide",atcommand_symbol); - is_atcommand(fd, sd, cmd, 1); + is_atcommand(fd, sd, cmd, 1); } @@ -12410,56 +12547,56 @@ void clif_parse_GMHide(int fd, struct map_session_data *sd) /// 2 = self mute (+10 minutes) void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) { - int id, type, value; - struct map_session_data *dstsd; - char command[NAME_LENGTH+15]; + int id, type, value; + struct map_session_data *dstsd; + char command[NAME_LENGTH+15]; - id = RFIFOL(fd,2); - type = RFIFOB(fd,6); - value = RFIFOW(fd,7); + id = RFIFOL(fd,2); + type = RFIFOB(fd,6); + value = RFIFOW(fd,7); - if (type == 0) - value = -value; + if( type == 0 ) + value = -value; - //If type is 2 and the ids don't match, this is a crafted hacked packet! - //Disabled because clients keep self-muting when you give players public @ commands... [Skotlex] - if (type == 2 /* && (pc_get_group_level(sd) > 0 || sd->bl.id != id)*/) - return; + //If type is 2 and the ids don't match, this is a crafted hacked packet! + //Disabled because clients keep self-muting when you give players public @ commands... [Skotlex] + if (type == 2 /* && (pc_get_group_level(sd) > 0 || sd->bl.id != id)*/) + return; - dstsd = map_id2sd(id); - if (dstsd == NULL) - return; + dstsd = map_id2sd(id); + if( dstsd == NULL ) + return; - sprintf(command, "%cmute %d %s", atcommand_symbol, value, dstsd->status.name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cmute %d %s", atcommand_symbol, value, dstsd->status.name); + is_atcommand(fd, sd, command, 1); } /// /rc (CZ_REQ_GIVE_MANNER_BYNAME). /// GM adjustment of a player's manner value by -60. /// 0212 <char name>.24B -void clif_parse_GMRc(int fd, struct map_session_data *sd) +void clif_parse_GMRc(int fd, struct map_session_data* sd) { - char command[NAME_LENGTH+15]; - char *name = (char *)RFIFOP(fd,2); + char command[NAME_LENGTH+15]; + char *name = (char*)RFIFOP(fd,2); - name[NAME_LENGTH-1] = '\0'; - sprintf(command, "%cmute %d %s", atcommand_symbol, 60, name); - is_atcommand(fd, sd, command, 1); + name[NAME_LENGTH-1] = '\0'; + sprintf(command, "%cmute %d %s", atcommand_symbol, 60, name); + is_atcommand(fd, sd, command, 1); } /// Result of request to resolve account name (ZC_ACK_ACCOUNTNAME). /// 01e0 <account id>.L <account name>.24B -void clif_account_name(struct map_session_data *sd, int account_id, const char *accname) +void clif_account_name(struct map_session_data* sd, int account_id, const char* accname) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x1e0)); - WFIFOW(fd,0) = 0x1e0; - WFIFOL(fd,2) = account_id; - safestrncpy((char *)WFIFOP(fd,6), accname, NAME_LENGTH); - WFIFOSET(fd,packet_len(0x1e0)); + WFIFOHEAD(fd,packet_len(0x1e0)); + WFIFOW(fd,0) = 0x1e0; + WFIFOL(fd,2) = account_id; + safestrncpy((char*)WFIFOP(fd,6), accname, NAME_LENGTH); + WFIFOSET(fd,packet_len(0x1e0)); } @@ -12467,10 +12604,10 @@ void clif_account_name(struct map_session_data *sd, int account_id, const char * /// 01df <account id>.L void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd) { - int account_id = RFIFOL(fd,2); + int account_id = RFIFOL(fd,2); - //TODO: find out if this works for any player or only for authorized GMs - clif_account_name(sd, account_id, ""); // insert account name here >_< + //TODO: find out if this works for any player or only for authorized GMs + clif_account_name(sd, account_id, ""); // insert account name here >_< } @@ -12482,18 +12619,18 @@ void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd) /// 1 = walkable void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) { - int x,y,type; + int x,y,type; - if (pc_has_permission(sd, PC_PERM_USE_CHANGEMAPTYPE)) - return; + if( pc_has_permission(sd, PC_PERM_USE_CHANGEMAPTYPE) ) + return; - x = RFIFOW(fd,2); - y = RFIFOW(fd,4); - type = RFIFOW(fd,6); + x = RFIFOW(fd,2); + y = RFIFOW(fd,4); + type = RFIFOW(fd,6); - map_setgatcell(sd->bl.m,x,y,type); - clif_changemapcell(0,sd->bl.m,x,y,type,ALL_SAMEMAP); - //FIXME: once players leave the map, the client 'forgets' this information. + map_setgatcell(sd->bl.m,x,y,type); + clif_changemapcell(0,sd->bl.m,x,y,type,ALL_SAMEMAP); + //FIXME: once players leave the map, the client 'forgets' this information. } @@ -12503,55 +12640,56 @@ void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) /// type: /// 0 = (/ex nick) deny speech from nick /// 1 = (/in nick) allow speech from nick -void clif_parse_PMIgnore(int fd, struct map_session_data *sd) -{ - char *nick; - uint8 type; - int i; - - nick = (char *)RFIFOP(fd,2); // speed up - nick[NAME_LENGTH-1] = '\0'; // to be sure that the player name has at most 23 characters - type = RFIFOB(fd,26); - - if (type == 0) { - // Add name to ignore list (block) - if (strcmp(wisp_server_name, nick) == 0) { - clif_wisexin(sd, type, 1); // fail - return; - } - - // try to find a free spot, while checking for duplicates at the same time - ARR_FIND(0, MAX_IGNORE_LIST, i, sd->ignore[i].name[0] == '\0' || strcmp(sd->ignore[i].name, nick) == 0); - if (i == MAX_IGNORE_LIST) { - // no space for new entry - clif_wisexin(sd, type, 2); // too many blocks - return; - } - if (sd->ignore[i].name[0] != '\0') { - // name already exists - clif_wisexin(sd, type, 0); // Aegis reports success. - return; - } - - //Insert in position i - safestrncpy(sd->ignore[i].name, nick, NAME_LENGTH); - } else { - // Remove name from ignore list (unblock) - - // find entry - ARR_FIND(0, MAX_IGNORE_LIST, i, sd->ignore[i].name[0] == '\0' || strcmp(sd->ignore[i].name, nick) == 0); - if (i == MAX_IGNORE_LIST || sd->ignore[i].name[i] == '\0') { - //Not found - clif_wisexin(sd, type, 1); // fail - return; - } - // move everything one place down to overwrite removed entry - memmove(sd->ignore[i].name, sd->ignore[i+1].name, (MAX_IGNORE_LIST-i-1)*sizeof(sd->ignore[0].name)); - // wipe last entry - memset(sd->ignore[MAX_IGNORE_LIST-1].name, 0, sizeof(sd->ignore[0].name)); - } - - clif_wisexin(sd, type, 0); // success +void clif_parse_PMIgnore(int fd, struct map_session_data* sd) +{ + char* nick; + uint8 type; + int i; + + nick = (char*)RFIFOP(fd,2); // speed up + nick[NAME_LENGTH-1] = '\0'; // to be sure that the player name has at most 23 characters + type = RFIFOB(fd,26); + + if( type == 0 ) + { // Add name to ignore list (block) + if (strcmp(wisp_server_name, nick) == 0) { + clif_wisexin(sd, type, 1); // fail + return; + } + + // try to find a free spot, while checking for duplicates at the same time + ARR_FIND( 0, MAX_IGNORE_LIST, i, sd->ignore[i].name[0] == '\0' || strcmp(sd->ignore[i].name, nick) == 0 ); + if( i == MAX_IGNORE_LIST ) + {// no space for new entry + clif_wisexin(sd, type, 2); // too many blocks + return; + } + if( sd->ignore[i].name[0] != '\0' ) + {// name already exists + clif_wisexin(sd, type, 0); // Aegis reports success. + return; + } + + //Insert in position i + safestrncpy(sd->ignore[i].name, nick, NAME_LENGTH); + } + else + { // Remove name from ignore list (unblock) + + // find entry + ARR_FIND( 0, MAX_IGNORE_LIST, i, sd->ignore[i].name[0] == '\0' || strcmp(sd->ignore[i].name, nick) == 0 ); + if( i == MAX_IGNORE_LIST || sd->ignore[i].name[i] == '\0' ) + { //Not found + clif_wisexin(sd, type, 1); // fail + return; + } + // move everything one place down to overwrite removed entry + memmove(sd->ignore[i].name, sd->ignore[i+1].name, (MAX_IGNORE_LIST-i-1)*sizeof(sd->ignore[0].name)); + // wipe last entry + memset(sd->ignore[MAX_IGNORE_LIST-1].name, 0, sizeof(sd->ignore[0].name)); + } + + clif_wisexin(sd, type, 0); // success } @@ -12563,51 +12701,53 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd) /// 1 = (/inall) allow all speech void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) { - int type = RFIFOB(fd,2), flag; - - if (type == 0) { - // Deny all - if (sd->state.ignoreAll) { - flag = 1; // fail - } else { - sd->state.ignoreAll = 1; - flag = 0; // success - } - } else { - //Unblock everyone - if (sd->state.ignoreAll) { - sd->state.ignoreAll = 0; - flag = 0; // success - } else { - if (sd->ignore[0].name[0] != '\0') { - //Wipe the ignore list. - memset(sd->ignore, 0, sizeof(sd->ignore)); - flag = 0; // success - } else { - flag = 1; // fail - } - } - } - - clif_wisall(sd, type, flag); + int type = RFIFOB(fd,2), flag; + + if( type == 0 ) + {// Deny all + if( sd->state.ignoreAll ) { + flag = 1; // fail + } else { + sd->state.ignoreAll = 1; + flag = 0; // success + } + } + else + {//Unblock everyone + if( sd->state.ignoreAll ) { + sd->state.ignoreAll = 0; + flag = 0; // success + } else { + if (sd->ignore[0].name[0] != '\0') + { //Wipe the ignore list. + memset(sd->ignore, 0, sizeof(sd->ignore)); + flag = 0; // success + } else { + flag = 1; // fail + } + } + } + + clif_wisall(sd, type, flag); } /// Whisper ignore list (ZC_WHISPER_LIST). /// 00d4 <packet len>.W { <char name>.24B }* -void clif_PMIgnoreList(struct map_session_data *sd) +void clif_PMIgnoreList(struct map_session_data* sd) { - int i, fd = sd->fd; + int i, fd = sd->fd; - WFIFOHEAD(fd,4+ARRAYLENGTH(sd->ignore)*NAME_LENGTH); - WFIFOW(fd,0) = 0xd4; + WFIFOHEAD(fd,4+ARRAYLENGTH(sd->ignore)*NAME_LENGTH); + WFIFOW(fd,0) = 0xd4; - for (i = 0; i < ARRAYLENGTH(sd->ignore) && sd->ignore[i].name[0]; i++) { - memcpy(WFIFOP(fd,4+i*NAME_LENGTH), sd->ignore[i].name, NAME_LENGTH); - } + for( i = 0; i < ARRAYLENGTH(sd->ignore) && sd->ignore[i].name[0]; i++ ) + { + memcpy(WFIFOP(fd,4+i*NAME_LENGTH), sd->ignore[i].name, NAME_LENGTH); + } - WFIFOW(fd,2) = 4+i*NAME_LENGTH; - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOW(fd,2) = 4+i*NAME_LENGTH; + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -12615,7 +12755,7 @@ void clif_PMIgnoreList(struct map_session_data *sd) /// 00d3 void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd) { - clif_PMIgnoreList(sd); + clif_PMIgnoreList(sd); } @@ -12623,18 +12763,19 @@ void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd) /// 01e7 void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) { - if (sd->state.doridori) return; - - switch (sd->class_&MAPID_UPPERMASK) { - case MAPID_SOUL_LINKER: - case MAPID_STAR_GLADIATOR: - case MAPID_TAEKWON: - if (!sd->state.rest) - break; - case MAPID_SUPER_NOVICE: - sd->state.doridori=1; - break; - } + if (sd->state.doridori) return; + + switch (sd->class_&MAPID_UPPERMASK) + { + case MAPID_SOUL_LINKER: + case MAPID_STAR_GLADIATOR: + case MAPID_TAEKWON: + if (!sd->state.rest) + break; + case MAPID_SUPER_NOVICE: + sd->state.doridori=1; + break; + } } @@ -12648,19 +12789,21 @@ void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) /// "Help me out~ Please~ T_T" void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) { - if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) { - unsigned int next = pc_nextbaseexp(sd); - if (next == 0) next = pc_thisbaseexp(sd); - if (next) { - int percent = (int)(((float)sd->status.base_exp/(float)next)*1000.); - - if (percent && (percent%100) == 0) { - // 10.0%, 20.0%, ..., 90.0% - sc_start(&sd->bl, status_skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill_get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] - clif_skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions - } - } - } + if( ( sd->class_&MAPID_UPPERMASK ) == MAPID_SUPER_NOVICE ) + { + unsigned int next = pc_nextbaseexp(sd); + if( next == 0 ) next = pc_thisbaseexp(sd); + if( next ) + { + int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. ); + + if( percent && ( percent%100 ) == 0 ) + {// 10.0%, 20.0%, ..., 90.0% + sc_start(&sd->bl, status_skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill_get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] + clif_skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions + } + } + } } @@ -12674,33 +12817,33 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) /// 1 = offline void clif_friendslist_toggle(struct map_session_data *sd,int account_id, int char_id, int online) { - int i, fd = sd->fd; + int i, fd = sd->fd; - //Seek friend. - for (i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id && - (sd->status.friends[i].char_id != char_id || sd->status.friends[i].account_id != account_id); i++); + //Seek friend. + for (i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id && + (sd->status.friends[i].char_id != char_id || sd->status.friends[i].account_id != account_id); i++); - if (i == MAX_FRIENDS || sd->status.friends[i].char_id == 0) - return; //Not found + if(i == MAX_FRIENDS || sd->status.friends[i].char_id == 0) + return; //Not found - WFIFOHEAD(fd,packet_len(0x206)); - WFIFOW(fd, 0) = 0x206; - WFIFOL(fd, 2) = sd->status.friends[i].account_id; - WFIFOL(fd, 6) = sd->status.friends[i].char_id; - WFIFOB(fd,10) = !online; //Yeah, a 1 here means "logged off", go figure... - WFIFOSET(fd, packet_len(0x206)); + WFIFOHEAD(fd,packet_len(0x206)); + WFIFOW(fd, 0) = 0x206; + WFIFOL(fd, 2) = sd->status.friends[i].account_id; + WFIFOL(fd, 6) = sd->status.friends[i].char_id; + WFIFOB(fd,10) = !online; //Yeah, a 1 here means "logged off", go figure... + WFIFOSET(fd, packet_len(0x206)); } //Subfunction called from clif_foreachclient to toggle friends on/off [Skotlex] int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap) { - int account_id, char_id, online; - account_id = va_arg(ap, int); - char_id = va_arg(ap, int); - online = va_arg(ap, int); - clif_friendslist_toggle(sd, account_id, char_id, online); - return 0; + int account_id, char_id, online; + account_id = va_arg(ap, int); + char_id = va_arg(ap, int); + online = va_arg(ap, int); + clif_friendslist_toggle(sd, account_id, char_id, online); + return 0; } @@ -12708,27 +12851,28 @@ int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap) /// 0201 <packet len>.W { <account id>.L <char id>.L <name>.24B }* void clif_friendslist_send(struct map_session_data *sd) { - int i = 0, n, fd = sd->fd; + int i = 0, n, fd = sd->fd; - // Send friends list - WFIFOHEAD(fd, MAX_FRIENDS * 32 + 4); - WFIFOW(fd, 0) = 0x201; - for (i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id; i++) { - WFIFOL(fd, 4 + 32 * i + 0) = sd->status.friends[i].account_id; - WFIFOL(fd, 4 + 32 * i + 4) = sd->status.friends[i].char_id; - memcpy(WFIFOP(fd, 4 + 32 * i + 8), &sd->status.friends[i].name, NAME_LENGTH); - } + // Send friends list + WFIFOHEAD(fd, MAX_FRIENDS * 32 + 4); + WFIFOW(fd, 0) = 0x201; + for(i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id; i++) + { + WFIFOL(fd, 4 + 32 * i + 0) = sd->status.friends[i].account_id; + WFIFOL(fd, 4 + 32 * i + 4) = sd->status.friends[i].char_id; + memcpy(WFIFOP(fd, 4 + 32 * i + 8), &sd->status.friends[i].name, NAME_LENGTH); + } - if (i) { - WFIFOW(fd,2) = 4 + 32 * i; - WFIFOSET(fd, WFIFOW(fd,2)); - } + if (i) { + WFIFOW(fd,2) = 4 + 32 * i; + WFIFOSET(fd, WFIFOW(fd,2)); + } - for (n = 0; n < i; n++) { - //Sending the online players - if (map_charid2sd(sd->status.friends[n].char_id)) - clif_friendslist_toggle(sd, sd->status.friends[n].account_id, sd->status.friends[n].char_id, 1); - } + for (n = 0; n < i; n++) + { //Sending the online players + if (map_charid2sd(sd->status.friends[n].char_id)) + clif_friendslist_toggle(sd, sd->status.friends[n].account_id, sd->status.friends[n].char_id, 1); + } } @@ -12741,34 +12885,35 @@ void clif_friendslist_send(struct map_session_data *sd) /// 3 = MsgStringTable[820]="(%s)'s Friend List is full." void clif_friendslist_reqack(struct map_session_data *sd, struct map_session_data *f_sd, int type) { - int fd; - nullpo_retv(sd); + int fd; + nullpo_retv(sd); - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x209)); - WFIFOW(fd,0) = 0x209; - WFIFOW(fd,2) = type; - if (f_sd) { - WFIFOL(fd,4) = f_sd->status.account_id; - WFIFOL(fd,8) = f_sd->status.char_id; - memcpy(WFIFOP(fd, 12), f_sd->status.name,NAME_LENGTH); - } - WFIFOSET(fd, packet_len(0x209)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0x209)); + WFIFOW(fd,0) = 0x209; + WFIFOW(fd,2) = type; + if (f_sd) + { + WFIFOL(fd,4) = f_sd->status.account_id; + WFIFOL(fd,8) = f_sd->status.char_id; + memcpy(WFIFOP(fd, 12), f_sd->status.name,NAME_LENGTH); + } + WFIFOSET(fd, packet_len(0x209)); } /// Asks a player for permission to be added as friend (ZC_REQ_ADD_FRIENDS). /// 0207 <req account id>.L <req char id>.L <req char name>.24B -void clif_friendlist_req(struct map_session_data *sd, int account_id, int char_id, const char *name) +void clif_friendlist_req(struct map_session_data* sd, int account_id, int char_id, const char* name) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x207)); - WFIFOW(fd,0) = 0x207; - WFIFOL(fd,2) = account_id; - WFIFOL(fd,6) = char_id; - memcpy(WFIFOP(fd,10), name, NAME_LENGTH); - WFIFOSET(fd,packet_len(0x207)); + WFIFOHEAD(fd,packet_len(0x207)); + WFIFOW(fd,0) = 0x207; + WFIFOL(fd,2) = account_id; + WFIFOL(fd,6) = char_id; + memcpy(WFIFOP(fd,10), name, NAME_LENGTH); + WFIFOSET(fd,packet_len(0x207)); } @@ -12776,48 +12921,48 @@ void clif_friendlist_req(struct map_session_data *sd, int account_id, int char_i /// 0202 <name>.24B void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) { - struct map_session_data *f_sd; - int i; + struct map_session_data *f_sd; + int i; - f_sd = map_nick2sd((char *)RFIFOP(fd,2)); + f_sd = map_nick2sd((char*)RFIFOP(fd,2)); - // ensure that the request player's friend list is not full - ARR_FIND(0, MAX_FRIENDS, i, sd->status.friends[i].char_id == 0); + // ensure that the request player's friend list is not full + ARR_FIND(0, MAX_FRIENDS, i, sd->status.friends[i].char_id == 0); - if (i == MAX_FRIENDS) { - clif_friendslist_reqack(sd, f_sd, 2); - return; - } + if( i == MAX_FRIENDS ) { + clif_friendslist_reqack(sd, f_sd, 2); + return; + } - // Friend doesn't exist (no player with this name) - if (f_sd == NULL) { - clif_displaymessage(fd, msg_txt(3)); - return; - } + // Friend doesn't exist (no player with this name) + if (f_sd == NULL) { + clif_displaymessage(fd, msg_txt(3)); + return; + } - if (sd->bl.id == f_sd->bl.id) { - // adding oneself as friend - return; - } + if( sd->bl.id == f_sd->bl.id ) + {// adding oneself as friend + return; + } - // @noask [LuzZza] - if (f_sd->state.noask) { - clif_noask_sub(sd, f_sd, 5); - return; - } + // @noask [LuzZza] + if(f_sd->state.noask) { + clif_noask_sub(sd, f_sd, 5); + return; + } - // Friend already exists - for (i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id != 0; i++) { - if (sd->status.friends[i].char_id == f_sd->status.char_id) { - clif_displaymessage(fd, msg_txt(671)); //"Friend already exists." - return; - } - } + // Friend already exists + for (i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id != 0; i++) { + if (sd->status.friends[i].char_id == f_sd->status.char_id) { + clif_displaymessage(fd, msg_txt(671)); //"Friend already exists." + return; + } + } - f_sd->friend_req = sd->status.char_id; - sd->friend_req = f_sd->status.char_id; + f_sd->friend_req = sd->status.char_id; + sd->friend_req = f_sd->status.char_id; - clif_friendlist_req(f_sd, sd->status.account_id, sd->status.char_id, sd->status.name); + clif_friendlist_req(f_sd, sd->status.account_id, sd->status.char_id, sd->status.name); } @@ -12829,64 +12974,64 @@ void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) /// 1 = accepted void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) { - struct map_session_data *f_sd; - int account_id; - char reply; + struct map_session_data *f_sd; + int account_id; + char reply; - account_id = RFIFOL(fd,2); - //char_id = RFIFOL(fd,6); + account_id = RFIFOL(fd,2); + //char_id = RFIFOL(fd,6); #if PACKETVER < 6 - reply = RFIFOB(fd,10); + reply = RFIFOB(fd,10); #else - reply = RFIFOL(fd,10); + reply = RFIFOL(fd,10); #endif - if (sd->bl.id == account_id) { - // adding oneself as friend - return; - } - - f_sd = map_id2sd(account_id); //The account id is the same as the bl.id of players. - if (f_sd == NULL) - return; - - if (reply == 0 || !(sd->friend_req == f_sd->status.char_id && f_sd->friend_req == sd->status.char_id)) - clif_friendslist_reqack(f_sd, sd, 1); - else { - int i; - // Find an empty slot - for (i = 0; i < MAX_FRIENDS; i++) - if (f_sd->status.friends[i].char_id == 0) - break; - if (i == MAX_FRIENDS) { - clif_friendslist_reqack(f_sd, sd, 2); - return; - } - - f_sd->status.friends[i].account_id = sd->status.account_id; - f_sd->status.friends[i].char_id = sd->status.char_id; - memcpy(f_sd->status.friends[i].name, sd->status.name, NAME_LENGTH); - clif_friendslist_reqack(f_sd, sd, 0); - - if (battle_config.friend_auto_add) { - // Also add f_sd to sd's friendlist. - for (i = 0; i < MAX_FRIENDS; i++) { - if (sd->status.friends[i].char_id == f_sd->status.char_id) - return; //No need to add anything. - if (sd->status.friends[i].char_id == 0) - break; - } - if (i == MAX_FRIENDS) { - clif_friendslist_reqack(sd, f_sd, 2); - return; - } - - sd->status.friends[i].account_id = f_sd->status.account_id; - sd->status.friends[i].char_id = f_sd->status.char_id; - memcpy(sd->status.friends[i].name, f_sd->status.name, NAME_LENGTH); - clif_friendslist_reqack(sd, f_sd, 0); - } - } + if( sd->bl.id == account_id ) + {// adding oneself as friend + return; + } + + f_sd = map_id2sd(account_id); //The account id is the same as the bl.id of players. + if (f_sd == NULL) + return; + + if (reply == 0 || !( sd->friend_req == f_sd->status.char_id && f_sd->friend_req == sd->status.char_id ) ) + clif_friendslist_reqack(f_sd, sd, 1); + else { + int i; + // Find an empty slot + for (i = 0; i < MAX_FRIENDS; i++) + if (f_sd->status.friends[i].char_id == 0) + break; + if (i == MAX_FRIENDS) { + clif_friendslist_reqack(f_sd, sd, 2); + return; + } + + f_sd->status.friends[i].account_id = sd->status.account_id; + f_sd->status.friends[i].char_id = sd->status.char_id; + memcpy(f_sd->status.friends[i].name, sd->status.name, NAME_LENGTH); + clif_friendslist_reqack(f_sd, sd, 0); + + if (battle_config.friend_auto_add) { + // Also add f_sd to sd's friendlist. + for (i = 0; i < MAX_FRIENDS; i++) { + if (sd->status.friends[i].char_id == f_sd->status.char_id) + return; //No need to add anything. + if (sd->status.friends[i].char_id == 0) + break; + } + if (i == MAX_FRIENDS) { + clif_friendslist_reqack(sd, f_sd, 2); + return; + } + + sd->status.friends[i].account_id = f_sd->status.account_id; + sd->status.friends[i].char_id = f_sd->status.char_id; + memcpy(sd->status.friends[i].name, f_sd->status.name, NAME_LENGTH); + clif_friendslist_reqack(sd, f_sd, 0); + } + } } @@ -12894,80 +13039,80 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) /// 0203 <account id>.L <char id>.L void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd) { - struct map_session_data *f_sd = NULL; - int account_id, char_id; - int i, j; - - account_id = RFIFOL(fd,2); - char_id = RFIFOL(fd,6); - - // Search friend - for (i = 0; i < MAX_FRIENDS && - (sd->status.friends[i].char_id != char_id || sd->status.friends[i].account_id != account_id); i++); - - if (i == MAX_FRIENDS) { - clif_displaymessage(fd, msg_txt(672)); //"Name not found in list." - return; - } - - //remove from friend's list first - if ((f_sd = map_id2sd(account_id)) && f_sd->status.char_id == char_id) { - for (i = 0; i < MAX_FRIENDS && - (f_sd->status.friends[i].char_id != sd->status.char_id || f_sd->status.friends[i].account_id != sd->status.account_id); i++); - - if (i != MAX_FRIENDS) { - // move all chars up - for (j = i + 1; j < MAX_FRIENDS; j++) - memcpy(&f_sd->status.friends[j-1], &f_sd->status.friends[j], sizeof(f_sd->status.friends[0])); - - memset(&f_sd->status.friends[MAX_FRIENDS-1], 0, sizeof(f_sd->status.friends[MAX_FRIENDS-1])); - //should the guy be notified of some message? we should add it here if so - WFIFOHEAD(f_sd->fd,packet_len(0x20a)); - WFIFOW(f_sd->fd,0) = 0x20a; - WFIFOL(f_sd->fd,2) = sd->status.account_id; - WFIFOL(f_sd->fd,6) = sd->status.char_id; - WFIFOSET(f_sd->fd, packet_len(0x20a)); - } - - } else { //friend not online -- ask char server to delete from his friendlist - if (chrif_removefriend(char_id,sd->status.char_id)) { // char-server offline, abort - clif_displaymessage(fd, msg_txt(673)); //"This action can't be performed at the moment. Please try again later." - return; - } - } - - // We can now delete from original requester - for (i = 0; i < MAX_FRIENDS && - (sd->status.friends[i].char_id != char_id || sd->status.friends[i].account_id != account_id); i++); - // move all chars up - for (j = i + 1; j < MAX_FRIENDS; j++) - memcpy(&sd->status.friends[j-1], &sd->status.friends[j], sizeof(sd->status.friends[0])); - - memset(&sd->status.friends[MAX_FRIENDS-1], 0, sizeof(sd->status.friends[MAX_FRIENDS-1])); - clif_displaymessage(fd, msg_txt(674)); //"Friend removed" - - WFIFOHEAD(fd,packet_len(0x20a)); - WFIFOW(fd,0) = 0x20a; - WFIFOL(fd,2) = account_id; - WFIFOL(fd,6) = char_id; - WFIFOSET(fd, packet_len(0x20a)); + struct map_session_data *f_sd = NULL; + int account_id, char_id; + int i, j; + + account_id = RFIFOL(fd,2); + char_id = RFIFOL(fd,6); + + // Search friend + for (i = 0; i < MAX_FRIENDS && + (sd->status.friends[i].char_id != char_id || sd->status.friends[i].account_id != account_id); i++); + + if (i == MAX_FRIENDS) { + clif_displaymessage(fd, msg_txt(672)); //"Name not found in list." + return; + } + + //remove from friend's list first + if( (f_sd = map_id2sd(account_id)) && f_sd->status.char_id == char_id) { + for (i = 0; i < MAX_FRIENDS && + (f_sd->status.friends[i].char_id != sd->status.char_id || f_sd->status.friends[i].account_id != sd->status.account_id); i++); + + if (i != MAX_FRIENDS) { + // move all chars up + for(j = i + 1; j < MAX_FRIENDS; j++) + memcpy(&f_sd->status.friends[j-1], &f_sd->status.friends[j], sizeof(f_sd->status.friends[0])); + + memset(&f_sd->status.friends[MAX_FRIENDS-1], 0, sizeof(f_sd->status.friends[MAX_FRIENDS-1])); + //should the guy be notified of some message? we should add it here if so + WFIFOHEAD(f_sd->fd,packet_len(0x20a)); + WFIFOW(f_sd->fd,0) = 0x20a; + WFIFOL(f_sd->fd,2) = sd->status.account_id; + WFIFOL(f_sd->fd,6) = sd->status.char_id; + WFIFOSET(f_sd->fd, packet_len(0x20a)); + } + + } else { //friend not online -- ask char server to delete from his friendlist + if(chrif_removefriend(char_id,sd->status.char_id)) { // char-server offline, abort + clif_displaymessage(fd, msg_txt(673)); //"This action can't be performed at the moment. Please try again later." + return; + } + } + + // We can now delete from original requester + for (i = 0; i < MAX_FRIENDS && + (sd->status.friends[i].char_id != char_id || sd->status.friends[i].account_id != account_id); i++); + // move all chars up + for(j = i + 1; j < MAX_FRIENDS; j++) + memcpy(&sd->status.friends[j-1], &sd->status.friends[j], sizeof(sd->status.friends[0])); + + memset(&sd->status.friends[MAX_FRIENDS-1], 0, sizeof(sd->status.friends[MAX_FRIENDS-1])); + clif_displaymessage(fd, msg_txt(674)); //"Friend removed" + + WFIFOHEAD(fd,packet_len(0x20a)); + WFIFOW(fd,0) = 0x20a; + WFIFOL(fd,2) = account_id; + WFIFOL(fd,6) = char_id; + WFIFOSET(fd, packet_len(0x20a)); } /// /pvpinfo list (ZC_ACK_PVPPOINT). /// 0210 <char id>.L <account id>.L <win point>.L <lose point>.L <point>.L -void clif_PVPInfo(struct map_session_data *sd) +void clif_PVPInfo(struct map_session_data* sd) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x210)); - WFIFOW(fd,0) = 0x210; - WFIFOL(fd,2) = sd->status.char_id; - WFIFOL(fd,6) = sd->status.account_id; - WFIFOL(fd,10) = sd->pvp_won; // times won - WFIFOL(fd,14) = sd->pvp_lost; // times lost - WFIFOL(fd,18) = sd->pvp_point; - WFIFOSET(fd, packet_len(0x210)); + WFIFOHEAD(fd,packet_len(0x210)); + WFIFOW(fd,0) = 0x210; + WFIFOL(fd,2) = sd->status.char_id; + WFIFOL(fd,6) = sd->status.account_id; + WFIFOL(fd,10) = sd->pvp_won; // times won + WFIFOL(fd,14) = sd->pvp_lost; // times lost + WFIFOL(fd,18) = sd->pvp_point; + WFIFOSET(fd, packet_len(0x210)); } @@ -12975,38 +13120,39 @@ void clif_PVPInfo(struct map_session_data *sd) /// 020f <char id>.L <account id>.L void clif_parse_PVPInfo(int fd,struct map_session_data *sd) { - // TODO: Is there a way to use this on an another player (char/acc id)? - clif_PVPInfo(sd); + // TODO: Is there a way to use this on an another player (char/acc id)? + clif_PVPInfo(sd); } /// /blacksmith list (ZC_BLACKSMITH_RANK). /// 0219 { <name>.24B }*10 { <point>.L }*10 -void clif_blacksmith(struct map_session_data *sd) -{ - int i, fd = sd->fd; - const char *name; - - WFIFOHEAD(fd,packet_len(0x219)); - WFIFOW(fd,0) = 0x219; - //Packet size limits this list to 10 elements. [Skotlex] - for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) { - if (smith_fame_list[i].id > 0) { - if (strcmp(smith_fame_list[i].name, "-") == 0 && - (name = map_charid2nick(smith_fame_list[i].id)) != NULL) { - strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), name, NAME_LENGTH); - } else - strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), smith_fame_list[i].name, NAME_LENGTH); - } else - strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), "None", 5); - WFIFOL(fd, 242 + i * 4) = smith_fame_list[i].fame; - } - for (; i < 10; i++) { //In case the MAX is less than 10. - strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), "Unavailable", 12); - WFIFOL(fd, 242 + i * 4) = 0; - } - - WFIFOSET(fd, packet_len(0x219)); +void clif_blacksmith(struct map_session_data* sd) +{ + int i, fd = sd->fd; + const char* name; + + WFIFOHEAD(fd,packet_len(0x219)); + WFIFOW(fd,0) = 0x219; + //Packet size limits this list to 10 elements. [Skotlex] + for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) { + if (smith_fame_list[i].id > 0) { + if (strcmp(smith_fame_list[i].name, "-") == 0 && + (name = map_charid2nick(smith_fame_list[i].id)) != NULL) + { + strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), name, NAME_LENGTH); + } else + strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), smith_fame_list[i].name, NAME_LENGTH); + } else + strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), "None", 5); + WFIFOL(fd, 242 + i * 4) = smith_fame_list[i].fame; + } + for(;i < 10; i++) { //In case the MAX is less than 10. + strncpy((char *)(WFIFOP(fd, 2 + 24 * i)), "Unavailable", 12); + WFIFOL(fd, 242 + i * 4) = 0; + } + + WFIFOSET(fd, packet_len(0x219)); } @@ -13014,7 +13160,7 @@ void clif_blacksmith(struct map_session_data *sd) /// 0217 void clif_parse_Blacksmith(int fd,struct map_session_data *sd) { - clif_blacksmith(sd); + clif_blacksmith(sd); } @@ -13022,43 +13168,44 @@ void clif_parse_Blacksmith(int fd,struct map_session_data *sd) /// 021b <points>.L <total points>.L void clif_fame_blacksmith(struct map_session_data *sd, int points) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x21b)); - WFIFOW(fd,0) = 0x21b; - WFIFOL(fd,2) = points; - WFIFOL(fd,6) = sd->status.fame; - WFIFOSET(fd, packet_len(0x21b)); + WFIFOHEAD(fd,packet_len(0x21b)); + WFIFOW(fd,0) = 0x21b; + WFIFOL(fd,2) = points; + WFIFOL(fd,6) = sd->status.fame; + WFIFOSET(fd, packet_len(0x21b)); } /// /alchemist list (ZC_ALCHEMIST_RANK). /// 021a { <name>.24B }*10 { <point>.L }*10 -void clif_alchemist(struct map_session_data *sd) -{ - int i, fd = sd->fd; - const char *name; - - WFIFOHEAD(fd,packet_len(0x21a)); - WFIFOW(fd,0) = 0x21a; - //Packet size limits this list to 10 elements. [Skotlex] - for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) { - if (chemist_fame_list[i].id > 0) { - if (strcmp(chemist_fame_list[i].name, "-") == 0 && - (name = map_charid2nick(chemist_fame_list[i].id)) != NULL) { - memcpy(WFIFOP(fd, 2 + 24 * i), name, NAME_LENGTH); - } else - memcpy(WFIFOP(fd, 2 + 24 * i), chemist_fame_list[i].name, NAME_LENGTH); - } else - memcpy(WFIFOP(fd, 2 + 24 * i), "None", NAME_LENGTH); - WFIFOL(fd, 242 + i * 4) = chemist_fame_list[i].fame; - } - for (; i < 10; i++) { //In case the MAX is less than 10. - memcpy(WFIFOP(fd, 2 + 24 * i), "Unavailable", NAME_LENGTH); - WFIFOL(fd, 242 + i * 4) = 0; - } - - WFIFOSET(fd, packet_len(0x21a)); +void clif_alchemist(struct map_session_data* sd) +{ + int i, fd = sd->fd; + const char* name; + + WFIFOHEAD(fd,packet_len(0x21a)); + WFIFOW(fd,0) = 0x21a; + //Packet size limits this list to 10 elements. [Skotlex] + for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) { + if (chemist_fame_list[i].id > 0) { + if (strcmp(chemist_fame_list[i].name, "-") == 0 && + (name = map_charid2nick(chemist_fame_list[i].id)) != NULL) + { + memcpy(WFIFOP(fd, 2 + 24 * i), name, NAME_LENGTH); + } else + memcpy(WFIFOP(fd, 2 + 24 * i), chemist_fame_list[i].name, NAME_LENGTH); + } else + memcpy(WFIFOP(fd, 2 + 24 * i), "None", NAME_LENGTH); + WFIFOL(fd, 242 + i * 4) = chemist_fame_list[i].fame; + } + for(;i < 10; i++) { //In case the MAX is less than 10. + memcpy(WFIFOP(fd, 2 + 24 * i), "Unavailable", NAME_LENGTH); + WFIFOL(fd, 242 + i * 4) = 0; + } + + WFIFOSET(fd, packet_len(0x21a)); } @@ -13066,7 +13213,7 @@ void clif_alchemist(struct map_session_data *sd) /// 0218 void clif_parse_Alchemist(int fd,struct map_session_data *sd) { - clif_alchemist(sd); + clif_alchemist(sd); } @@ -13074,42 +13221,43 @@ void clif_parse_Alchemist(int fd,struct map_session_data *sd) /// 021c <points>.L <total points>.L void clif_fame_alchemist(struct map_session_data *sd, int points) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x21c)); - WFIFOW(fd,0) = 0x21c; - WFIFOL(fd,2) = points; - WFIFOL(fd,6) = sd->status.fame; - WFIFOSET(fd, packet_len(0x21c)); + WFIFOHEAD(fd,packet_len(0x21c)); + WFIFOW(fd,0) = 0x21c; + WFIFOL(fd,2) = points; + WFIFOL(fd,6) = sd->status.fame; + WFIFOSET(fd, packet_len(0x21c)); } /// /taekwon list (ZC_TAEKWON_RANK). /// 0226 { <name>.24B }*10 { <point>.L }*10 -void clif_taekwon(struct map_session_data *sd) -{ - int i, fd = sd->fd; - const char *name; - - WFIFOHEAD(fd,packet_len(0x226)); - WFIFOW(fd,0) = 0x226; - //Packet size limits this list to 10 elements. [Skotlex] - for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) { - if (taekwon_fame_list[i].id > 0) { - if (strcmp(taekwon_fame_list[i].name, "-") == 0 && - (name = map_charid2nick(taekwon_fame_list[i].id)) != NULL) { - memcpy(WFIFOP(fd, 2 + 24 * i), name, NAME_LENGTH); - } else - memcpy(WFIFOP(fd, 2 + 24 * i), taekwon_fame_list[i].name, NAME_LENGTH); - } else - memcpy(WFIFOP(fd, 2 + 24 * i), "None", NAME_LENGTH); - WFIFOL(fd, 242 + i * 4) = taekwon_fame_list[i].fame; - } - for (; i < 10; i++) { //In case the MAX is less than 10. - memcpy(WFIFOP(fd, 2 + 24 * i), "Unavailable", NAME_LENGTH); - WFIFOL(fd, 242 + i * 4) = 0; - } - WFIFOSET(fd, packet_len(0x226)); +void clif_taekwon(struct map_session_data* sd) +{ + int i, fd = sd->fd; + const char* name; + + WFIFOHEAD(fd,packet_len(0x226)); + WFIFOW(fd,0) = 0x226; + //Packet size limits this list to 10 elements. [Skotlex] + for (i = 0; i < 10 && i < MAX_FAME_LIST; i++) { + if (taekwon_fame_list[i].id > 0) { + if (strcmp(taekwon_fame_list[i].name, "-") == 0 && + (name = map_charid2nick(taekwon_fame_list[i].id)) != NULL) + { + memcpy(WFIFOP(fd, 2 + 24 * i), name, NAME_LENGTH); + } else + memcpy(WFIFOP(fd, 2 + 24 * i), taekwon_fame_list[i].name, NAME_LENGTH); + } else + memcpy(WFIFOP(fd, 2 + 24 * i), "None", NAME_LENGTH); + WFIFOL(fd, 242 + i * 4) = taekwon_fame_list[i].fame; + } + for(;i < 10; i++) { //In case the MAX is less than 10. + memcpy(WFIFOP(fd, 2 + 24 * i), "Unavailable", NAME_LENGTH); + WFIFOL(fd, 242 + i * 4) = 0; + } + WFIFOSET(fd, packet_len(0x226)); } @@ -13117,7 +13265,7 @@ void clif_taekwon(struct map_session_data *sd) /// 0225 void clif_parse_Taekwon(int fd,struct map_session_data *sd) { - clif_taekwon(sd); + clif_taekwon(sd); } @@ -13125,29 +13273,29 @@ void clif_parse_Taekwon(int fd,struct map_session_data *sd) /// 0224 <points>.L <total points>.L void clif_fame_taekwon(struct map_session_data *sd, int points) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x224)); - WFIFOW(fd,0) = 0x224; - WFIFOL(fd,2) = points; - WFIFOL(fd,6) = sd->status.fame; - WFIFOSET(fd, packet_len(0x224)); + WFIFOHEAD(fd,packet_len(0x224)); + WFIFOW(fd,0) = 0x224; + WFIFOL(fd,2) = points; + WFIFOL(fd,6) = sd->status.fame; + WFIFOSET(fd, packet_len(0x224)); } /// /pk list (ZC_KILLER_RANK). /// 0238 { <name>.24B }*10 { <point>.L }*10 -void clif_ranking_pk(struct map_session_data *sd) +void clif_ranking_pk(struct map_session_data* sd) { - int i, fd = sd->fd; + int i, fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x238)); - WFIFOW(fd,0) = 0x238; - for (i=0; i<10; i++) { - memcpy(WFIFOP(fd,i*24+2), "Unknown", NAME_LENGTH); - WFIFOL(fd,i*4+242) = 0; - } - WFIFOSET(fd, packet_len(0x238)); + WFIFOHEAD(fd,packet_len(0x238)); + WFIFOW(fd,0) = 0x238; + for(i=0;i<10;i++){ + memcpy(WFIFOP(fd,i*24+2), "Unknown", NAME_LENGTH); + WFIFOL(fd,i*4+242) = 0; + } + WFIFOSET(fd, packet_len(0x238)); } @@ -13155,7 +13303,7 @@ void clif_ranking_pk(struct map_session_data *sd) /// 0237 void clif_parse_RankingPk(int fd,struct map_session_data *sd) { - clif_ranking_pk(sd); + clif_ranking_pk(sd); } @@ -13167,21 +13315,21 @@ void clif_parse_RankingPk(int fd,struct map_session_data *sd) /// 2 = star void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd) { - int i; - if (sd->menuskill_id != SG_FEEL) - return; - i = sd->menuskill_val-1; - if (i<0 || i >= MAX_PC_FEELHATE) return; //Bug? + int i; + if (sd->menuskill_id != SG_FEEL) + return; + i = sd->menuskill_val-1; + if (i<0 || i >= MAX_PC_FEELHATE) return; //Bug? - sd->feel_map[i].index = map_id2index(sd->bl.m); - sd->feel_map[i].m = sd->bl.m; - pc_setglobalreg(sd,sg_info[i].feel_var,sd->feel_map[i].index); + sd->feel_map[i].index = map_id2index(sd->bl.m); + sd->feel_map[i].m = sd->bl.m; + pc_setglobalreg(sd,sg_info[i].feel_var,sd->feel_map[i].index); - //Are these really needed? Shouldn't they show up automatically from the feel save packet? - // clif_misceffect2(&sd->bl, 0x1b0); - // clif_misceffect2(&sd->bl, 0x21f); - clif_feel_info(sd, i, 0); - clif_menuskill_clear(sd); +//Are these really needed? Shouldn't they show up automatically from the feel save packet? +// clif_misceffect2(&sd->bl, 0x1b0); +// clif_misceffect2(&sd->bl, 0x21f); + clif_feel_info(sd, i, 0); + clif_menuskill_clear(sd); } @@ -13193,12 +13341,12 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd) /// 2 = star void clif_feel_req(int fd, struct map_session_data *sd, int skilllv) { - WFIFOHEAD(fd,packet_len(0x253)); - WFIFOW(fd,0)=0x253; - WFIFOB(fd,2)=TOB(skilllv-1); - WFIFOSET(fd, packet_len(0x253)); - sd->menuskill_id = SG_FEEL; - sd->menuskill_val = skilllv; + WFIFOHEAD(fd,packet_len(0x253)); + WFIFOW(fd,0)=0x253; + WFIFOB(fd,2)=TOB(skilllv-1); + WFIFOSET(fd, packet_len(0x253)); + sd->menuskill_id = SG_FEEL; + sd->menuskill_val = skilllv; } @@ -13206,7 +13354,7 @@ void clif_feel_req(int fd, struct map_session_data *sd, int skilllv) /// 0231 <name>.24B void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) { - merc_hom_change_name(sd,(char *)RFIFOP(fd,2)); + merc_hom_change_name(sd,(char*)RFIFOP(fd,2)); } @@ -13214,20 +13362,20 @@ void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) /// 0234 <id>.L void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) { - int id = RFIFOL(fd,2); // Mercenary or Homunculus - struct block_list *bl = NULL; - struct unit_data *ud = NULL; + int id = RFIFOL(fd,2); // Mercenary or Homunculus + struct block_list *bl = NULL; + struct unit_data *ud = NULL; - if (sd->md && sd->md->bl.id == id) - bl = &sd->md->bl; - else if (merc_is_hom_active(sd->hd) && sd->hd->bl.id == id) - bl = &sd->hd->bl; // Moving Homunculus - else - return; + if( sd->md && sd->md->bl.id == id ) + bl = &sd->md->bl; + else if( merc_is_hom_active(sd->hd) && sd->hd->bl.id == id ) + bl = &sd->hd->bl; // Moving Homunculus + else + return; - unit_calc_pos(bl, sd->bl.x, sd->bl.y, sd->ud.dir); - ud = unit_bl2ud(bl); - unit_walktoxy(bl, ud->to_x, ud->to_y, 4); + unit_calc_pos(bl, sd->bl.x, sd->bl.y, sd->ud.dir); + ud = unit_bl2ud(bl); + unit_walktoxy(bl, ud->to_x, ud->to_y, 4); } @@ -13235,20 +13383,20 @@ void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) /// 0232 <id>.L <position data>.3B void clif_parse_HomMoveTo(int fd, struct map_session_data *sd) { - int id = RFIFOL(fd,2); // Mercenary or Homunculus - struct block_list *bl = NULL; - short x, y; + int id = RFIFOL(fd,2); // Mercenary or Homunculus + struct block_list *bl = NULL; + short x, y; - RFIFOPOS(fd, packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1], &x, &y, NULL); + RFIFOPOS(fd, packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1], &x, &y, NULL); - if (sd->md && sd->md->bl.id == id) - bl = &sd->md->bl; // Moving Mercenary - else if (merc_is_hom_active(sd->hd) && sd->hd->bl.id == id) - bl = &sd->hd->bl; // Moving Homunculus - else - return; + if( sd->md && sd->md->bl.id == id ) + bl = &sd->md->bl; // Moving Mercenary + else if( merc_is_hom_active(sd->hd) && sd->hd->bl.id == id ) + bl = &sd->hd->bl; // Moving Homunculus + else + return; - unit_walktoxy(bl, x, y, 4); + unit_walktoxy(bl, x, y, 4); } @@ -13258,19 +13406,19 @@ void clif_parse_HomMoveTo(int fd, struct map_session_data *sd) /// always 0 void clif_parse_HomAttack(int fd,struct map_session_data *sd) { - struct block_list *bl = NULL; - int id = RFIFOL(fd,2), - target_id = RFIFOL(fd,6), - action_type = RFIFOB(fd,10); + struct block_list *bl = NULL; + int id = RFIFOL(fd,2), + target_id = RFIFOL(fd,6), + action_type = RFIFOB(fd,10); - if (merc_is_hom_active(sd->hd) && sd->hd->bl.id == id) - bl = &sd->hd->bl; - else if (sd->md && sd->md->bl.id == id) - bl = &sd->md->bl; - else return; + if( merc_is_hom_active(sd->hd) && sd->hd->bl.id == id ) + bl = &sd->hd->bl; + else if( sd->md && sd->md->bl.id == id ) + bl = &sd->md->bl; + else return; - unit_stop_attack(bl); - unit_attack(bl, target_id, action_type != 0); + unit_stop_attack(bl); + unit_attack(bl, target_id, action_type != 0); } @@ -13283,16 +13431,15 @@ void clif_parse_HomAttack(int fd,struct map_session_data *sd) /// 1 = feed /// 2 = delete void clif_parse_HomMenu(int fd, struct map_session_data *sd) -{ - //[orn] - int cmd; +{ //[orn] + int cmd; - cmd = RFIFOW(fd,0); + cmd = RFIFOW(fd,0); - if (!merc_is_hom_active(sd->hd)) - return; + if(!merc_is_hom_active(sd->hd)) + return; - merc_menu(sd,RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[1])); + merc_menu(sd,RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[1])); } @@ -13300,19 +13447,19 @@ void clif_parse_HomMenu(int fd, struct map_session_data *sd) /// 0292 void clif_parse_AutoRevive(int fd, struct map_session_data *sd) { - int item_position = pc_search_inventory(sd, ITEMID_TOKEN_OF_SIEGFRIED); + int item_position = pc_search_inventory(sd, ITEMID_TOKEN_OF_SIEGFRIED); - if (item_position < 0) - return; + if (item_position < 0) + return; - if (sd->sc.data[SC_HELLPOWER]) //Cannot res while under the effect of SC_HELLPOWER. - return; + if (sd->sc.data[SC_HELLPOWER]) //Cannot res while under the effect of SC_HELLPOWER. + return; - if (!status_revive(&sd->bl, 100, 100)) - return; + if (!status_revive(&sd->bl, 100, 100)) + return; - clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); - pc_delitem(sd, item_position, 1, 0, 1, LOG_TYPE_CONSUME); + clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); + pc_delitem(sd, item_position, 1, 0, 1, LOG_TYPE_CONSUME); } @@ -13323,37 +13470,37 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) /// <itemdefPower>.W <plusdefPower>.W <mdefPower>.W <plusmdefPower>.W /// <hitSuccessValue>.W <avoidSuccessValue>.W <plusAvoidSuccessValue>.W /// <criticalSuccessValue>.W <ASPD>.W <plusASPD>.W -void clif_check(int fd, struct map_session_data *pl_sd) -{ - WFIFOHEAD(fd,packet_len(0x214)); - WFIFOW(fd, 0) = 0x214; - WFIFOB(fd, 2) = min(pl_sd->status.str, UINT8_MAX); - WFIFOB(fd, 3) = pc_need_status_point(pl_sd, SP_STR, 1); - WFIFOB(fd, 4) = min(pl_sd->status.agi, UINT8_MAX); - WFIFOB(fd, 5) = pc_need_status_point(pl_sd, SP_AGI, 1); - WFIFOB(fd, 6) = min(pl_sd->status.vit, UINT8_MAX); - WFIFOB(fd, 7) = pc_need_status_point(pl_sd, SP_VIT, 1); - WFIFOB(fd, 8) = min(pl_sd->status.int_, UINT8_MAX); - WFIFOB(fd, 9) = pc_need_status_point(pl_sd, SP_INT, 1); - WFIFOB(fd,10) = min(pl_sd->status.dex, UINT8_MAX); - WFIFOB(fd,11) = pc_need_status_point(pl_sd, SP_DEX, 1); - WFIFOB(fd,12) = min(pl_sd->status.luk, UINT8_MAX); - WFIFOB(fd,13) = pc_need_status_point(pl_sd, SP_LUK, 1); - WFIFOW(fd,14) = pl_sd->battle_status.batk+pl_sd->battle_status.rhw.atk+pl_sd->battle_status.lhw.atk; - WFIFOW(fd,16) = pl_sd->battle_status.rhw.atk2+pl_sd->battle_status.lhw.atk2; - WFIFOW(fd,18) = pl_sd->battle_status.matk_max; - WFIFOW(fd,20) = pl_sd->battle_status.matk_min; - WFIFOW(fd,22) = pl_sd->battle_status.def; - WFIFOW(fd,24) = pl_sd->battle_status.def2; - WFIFOW(fd,26) = pl_sd->battle_status.mdef; - WFIFOW(fd,28) = pl_sd->battle_status.mdef2; - WFIFOW(fd,30) = pl_sd->battle_status.hit; - WFIFOW(fd,32) = pl_sd->battle_status.flee; - WFIFOW(fd,34) = pl_sd->battle_status.flee2/10; - WFIFOW(fd,36) = pl_sd->battle_status.cri/10; - WFIFOW(fd,38) = (2000-pl_sd->battle_status.amotion)/10; // aspd - WFIFOW(fd,40) = 0; // FIXME: What is 'plusASPD' supposed to be? Maybe adelay? - WFIFOSET(fd,packet_len(0x214)); +void clif_check(int fd, struct map_session_data* pl_sd) +{ + WFIFOHEAD(fd,packet_len(0x214)); + WFIFOW(fd, 0) = 0x214; + WFIFOB(fd, 2) = min(pl_sd->status.str, UINT8_MAX); + WFIFOB(fd, 3) = pc_need_status_point(pl_sd, SP_STR, 1); + WFIFOB(fd, 4) = min(pl_sd->status.agi, UINT8_MAX); + WFIFOB(fd, 5) = pc_need_status_point(pl_sd, SP_AGI, 1); + WFIFOB(fd, 6) = min(pl_sd->status.vit, UINT8_MAX); + WFIFOB(fd, 7) = pc_need_status_point(pl_sd, SP_VIT, 1); + WFIFOB(fd, 8) = min(pl_sd->status.int_, UINT8_MAX); + WFIFOB(fd, 9) = pc_need_status_point(pl_sd, SP_INT, 1); + WFIFOB(fd,10) = min(pl_sd->status.dex, UINT8_MAX); + WFIFOB(fd,11) = pc_need_status_point(pl_sd, SP_DEX, 1); + WFIFOB(fd,12) = min(pl_sd->status.luk, UINT8_MAX); + WFIFOB(fd,13) = pc_need_status_point(pl_sd, SP_LUK, 1); + WFIFOW(fd,14) = pl_sd->battle_status.batk+pl_sd->battle_status.rhw.atk+pl_sd->battle_status.lhw.atk; + WFIFOW(fd,16) = pl_sd->battle_status.rhw.atk2+pl_sd->battle_status.lhw.atk2; + WFIFOW(fd,18) = pl_sd->battle_status.matk_max; + WFIFOW(fd,20) = pl_sd->battle_status.matk_min; + WFIFOW(fd,22) = pl_sd->battle_status.def; + WFIFOW(fd,24) = pl_sd->battle_status.def2; + WFIFOW(fd,26) = pl_sd->battle_status.mdef; + WFIFOW(fd,28) = pl_sd->battle_status.mdef2; + WFIFOW(fd,30) = pl_sd->battle_status.hit; + WFIFOW(fd,32) = pl_sd->battle_status.flee; + WFIFOW(fd,34) = pl_sd->battle_status.flee2/10; + WFIFOW(fd,36) = pl_sd->battle_status.cri/10; + WFIFOW(fd,38) = (2000-pl_sd->battle_status.amotion)/10; // aspd + WFIFOW(fd,40) = 0; // FIXME: What is 'plusASPD' supposed to be? Maybe adelay? + WFIFOSET(fd,packet_len(0x214)); } @@ -13362,19 +13509,20 @@ void clif_check(int fd, struct map_session_data *pl_sd) /// 0213 <char name>.24B void clif_parse_Check(int fd, struct map_session_data *sd) { - char charname[NAME_LENGTH]; - struct map_session_data *pl_sd; + char charname[NAME_LENGTH]; + struct map_session_data* pl_sd; - if (!pc_has_permission(sd, PC_PERM_USE_CHECK)) - return; + if(!pc_has_permission(sd, PC_PERM_USE_CHECK)) + return; - safestrncpy(charname, (const char *)RFIFOP(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), sizeof(charname)); + safestrncpy(charname, (const char*)RFIFOP(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), sizeof(charname)); - if ((pl_sd = map_nick2sd(charname)) == NULL || pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { - return; - } + if( ( pl_sd = map_nick2sd(charname) ) == NULL || pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) + { + return; + } - clif_check(fd, pl_sd); + clif_check(fd, pl_sd); } @@ -13390,11 +13538,11 @@ void clif_parse_Check(int fd, struct map_session_data *sd) /// 1 = failure void clif_Mail_setattachment(int fd, int index, uint8 flag) { - WFIFOHEAD(fd,packet_len(0x255)); - WFIFOW(fd,0) = 0x255; - WFIFOW(fd,2) = index; - WFIFOB(fd,4) = flag; - WFIFOSET(fd,packet_len(0x255)); + WFIFOHEAD(fd,packet_len(0x255)); + WFIFOW(fd,0) = 0x255; + WFIFOW(fd,2) = index; + WFIFOB(fd,4) = flag; + WFIFOSET(fd,packet_len(0x255)); } @@ -13406,10 +13554,10 @@ void clif_Mail_setattachment(int fd, int index, uint8 flag) /// 2 = too many items void clif_Mail_getattachment(int fd, uint8 flag) { - WFIFOHEAD(fd,packet_len(0x245)); - WFIFOW(fd,0) = 0x245; - WFIFOB(fd,2) = flag; - WFIFOSET(fd,packet_len(0x245)); + WFIFOHEAD(fd,packet_len(0x245)); + WFIFOW(fd,0) = 0x245; + WFIFOB(fd,2) = flag; + WFIFOSET(fd,packet_len(0x245)); } @@ -13420,10 +13568,10 @@ void clif_Mail_getattachment(int fd, uint8 flag) /// 1 = recipinent does not exist void clif_Mail_send(int fd, bool fail) { - WFIFOHEAD(fd,packet_len(0x249)); - WFIFOW(fd,0) = 0x249; - WFIFOB(fd,2) = fail; - WFIFOSET(fd,packet_len(0x249)); + WFIFOHEAD(fd,packet_len(0x249)); + WFIFOW(fd,0) = 0x249; + WFIFOB(fd,2) = fail; + WFIFOSET(fd,packet_len(0x249)); } @@ -13434,11 +13582,11 @@ void clif_Mail_send(int fd, bool fail) /// 1 = failure void clif_Mail_delete(int fd, int mail_id, short fail) { - WFIFOHEAD(fd, packet_len(0x257)); - WFIFOW(fd,0) = 0x257; - WFIFOL(fd,2) = mail_id; - WFIFOW(fd,6) = fail; - WFIFOSET(fd, packet_len(0x257)); + WFIFOHEAD(fd, packet_len(0x257)); + WFIFOW(fd,0) = 0x257; + WFIFOL(fd,2) = mail_id; + WFIFOW(fd,6) = fail; + WFIFOSET(fd, packet_len(0x257)); } @@ -13449,11 +13597,11 @@ void clif_Mail_delete(int fd, int mail_id, short fail) /// 1 = failure void clif_Mail_return(int fd, int mail_id, short fail) { - WFIFOHEAD(fd,packet_len(0x274)); - WFIFOW(fd,0) = 0x274; - WFIFOL(fd,2) = mail_id; - WFIFOW(fd,6) = fail; - WFIFOSET(fd,packet_len(0x274)); + WFIFOHEAD(fd,packet_len(0x274)); + WFIFOW(fd,0) = 0x274; + WFIFOL(fd,2) = mail_id; + WFIFOW(fd,6) = fail; + WFIFOSET(fd,packet_len(0x274)); } @@ -13461,12 +13609,12 @@ void clif_Mail_return(int fd, int mail_id, short fail) /// 024a <mail id>.L <title>.40B <sender>.24B void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title) { - WFIFOHEAD(fd,packet_len(0x24a)); - WFIFOW(fd,0) = 0x24a; - WFIFOL(fd,2) = mail_id; - safestrncpy((char *)WFIFOP(fd,6), title, MAIL_TITLE_LENGTH); - safestrncpy((char *)WFIFOP(fd,46), sender, NAME_LENGTH); - WFIFOSET(fd,packet_len(0x24a)); + WFIFOHEAD(fd,packet_len(0x24a)); + WFIFOW(fd,0) = 0x24a; + WFIFOL(fd,2) = mail_id; + safestrncpy((char*)WFIFOP(fd,6), title, MAIL_TITLE_LENGTH); + safestrncpy((char*)WFIFOP(fd,46), sender, NAME_LENGTH); + WFIFOSET(fd,packet_len(0x24a)); } @@ -13477,10 +13625,10 @@ void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title) /// 1 = close void clif_Mail_window(int fd, int flag) { - WFIFOHEAD(fd,packet_len(0x260)); - WFIFOW(fd,0) = 0x260; - WFIFOL(fd,2) = flag; - WFIFOSET(fd,packet_len(0x260)); + WFIFOHEAD(fd,packet_len(0x260)); + WFIFOW(fd,0) = 0x260; + WFIFOL(fd,2) = flag; + WFIFOSET(fd,packet_len(0x260)); } @@ -13491,37 +13639,38 @@ void clif_Mail_window(int fd, int flag) /// 1 = read void clif_Mail_refreshinbox(struct map_session_data *sd) { - int fd = sd->fd; - struct mail_data *md = &sd->mail.inbox; - struct mail_message *msg; - int len, i, j; - - len = 8 + (73 * md->amount); - - WFIFOHEAD(fd,len); - WFIFOW(fd,0) = 0x240; - WFIFOW(fd,2) = len; - WFIFOL(fd,4) = md->amount; - for (i = j = 0; i < MAIL_MAX_INBOX && j < md->amount; i++) { - msg = &md->msg[i]; - if (msg->id < 1) - continue; - - WFIFOL(fd,8+73*j) = msg->id; - memcpy(WFIFOP(fd,12+73*j), msg->title, MAIL_TITLE_LENGTH); - WFIFOB(fd,52+73*j) = (msg->status != MAIL_UNREAD); - memcpy(WFIFOP(fd,53+73*j), msg->send_name, NAME_LENGTH); - WFIFOL(fd,77+73*j) = (uint32)msg->timestamp; - j++; - } - WFIFOSET(fd,len); - - if (md->full) { - // TODO: is this official? - char output[100]; - sprintf(output, "Inbox is full (Max %d). Delete some mails.", MAIL_MAX_INBOX); - clif_disp_onlyself(sd, output, strlen(output)); - } + int fd = sd->fd; + struct mail_data *md = &sd->mail.inbox; + struct mail_message *msg; + int len, i, j; + + len = 8 + (73 * md->amount); + + WFIFOHEAD(fd,len); + WFIFOW(fd,0) = 0x240; + WFIFOW(fd,2) = len; + WFIFOL(fd,4) = md->amount; + for( i = j = 0; i < MAIL_MAX_INBOX && j < md->amount; i++ ) + { + msg = &md->msg[i]; + if (msg->id < 1) + continue; + + WFIFOL(fd,8+73*j) = msg->id; + memcpy(WFIFOP(fd,12+73*j), msg->title, MAIL_TITLE_LENGTH); + WFIFOB(fd,52+73*j) = (msg->status != MAIL_UNREAD); + memcpy(WFIFOP(fd,53+73*j), msg->send_name, NAME_LENGTH); + WFIFOL(fd,77+73*j) = (uint32)msg->timestamp; + j++; + } + WFIFOSET(fd,len); + + if( md->full ) + {// TODO: is this official? + char output[100]; + sprintf(output, "Inbox is full (Max %d). Delete some mails.", MAIL_MAX_INBOX); + clif_disp_onlyself(sd, output, strlen(output)); + } } @@ -13529,15 +13678,15 @@ void clif_Mail_refreshinbox(struct map_session_data *sd) /// 023f void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) { - struct mail_data *md = &sd->mail.inbox; + struct mail_data* md = &sd->mail.inbox; - if (md->amount < MAIL_MAX_INBOX && (md->full || sd->mail.changed)) - intif_Mail_requestinbox(sd->status.char_id, 1); - else - clif_Mail_refreshinbox(sd); + if( md->amount < MAIL_MAX_INBOX && (md->full || sd->mail.changed) ) + intif_Mail_requestinbox(sd->status.char_id, 1); + else + clif_Mail_refreshinbox(sd); - mail_removeitem(sd, 0); - mail_removezeny(sd, 0); + mail_removeitem(sd, 0); + mail_removezeny(sd, 0); } @@ -13547,59 +13696,64 @@ void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) /// <card1>.W <card2>.W <card3>.W <card4>.W <message>.?B void clif_Mail_read(struct map_session_data *sd, int mail_id) { - int i, fd = sd->fd; - - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if (i == MAIL_MAX_INBOX) { - clif_Mail_return(sd->fd, mail_id, 1); // Mail doesn't exist - ShowWarning("clif_parse_Mail_read: char '%s' trying to read a message not the inbox.\n", sd->status.name); - return; - } else { - struct mail_message *msg = &sd->mail.inbox.msg[i]; - struct item *item = &msg->item; - struct item_data *data; - int msg_len = strlen(msg->body), len; - - if (msg_len == 0) { - strcpy(msg->body, "(no message)"); - msg_len = strlen(msg->body); - } - - len = 101 + msg_len; - - WFIFOHEAD(fd,len); - WFIFOW(fd,0) = 0x242; - WFIFOW(fd,2) = len; - WFIFOL(fd,4) = msg->id; - safestrncpy((char *)WFIFOP(fd,8), msg->title, MAIL_TITLE_LENGTH + 1); - safestrncpy((char *)WFIFOP(fd,48), msg->send_name, NAME_LENGTH + 1); - WFIFOL(fd,72) = 0; - WFIFOL(fd,76) = msg->zeny; - - if (item->nameid && (data = itemdb_exists(item->nameid)) != NULL) { - WFIFOL(fd,80) = item->amount; - WFIFOW(fd,84) = (data->view_id)?data->view_id:item->nameid; - WFIFOW(fd,86) = data->type; - WFIFOB(fd,88) = item->identify; - WFIFOB(fd,89) = item->attribute; - WFIFOB(fd,90) = item->refine; - WFIFOW(fd,91) = item->card[0]; - WFIFOW(fd,93) = item->card[1]; - WFIFOW(fd,95) = item->card[2]; - WFIFOW(fd,97) = item->card[3]; - } else // no item, set all to zero - memset(WFIFOP(fd,80), 0x00, 19); - - WFIFOB(fd,99) = (unsigned char)msg_len; - safestrncpy((char *)WFIFOP(fd,100), msg->body, msg_len + 1); - WFIFOSET(fd,len); - - if (msg->status == MAIL_UNREAD) { - msg->status = MAIL_READ; - intif_Mail_read(mail_id); - clif_parse_Mail_refreshinbox(fd, sd); - } - } + int i, fd = sd->fd; + + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i == MAIL_MAX_INBOX ) + { + clif_Mail_return(sd->fd, mail_id, 1); // Mail doesn't exist + ShowWarning("clif_parse_Mail_read: char '%s' trying to read a message not the inbox.\n", sd->status.name); + return; + } + else + { + struct mail_message *msg = &sd->mail.inbox.msg[i]; + struct item *item = &msg->item; + struct item_data *data; + int msg_len = strlen(msg->body), len; + + if( msg_len == 0 ) { + strcpy(msg->body, "(no message)"); + msg_len = strlen(msg->body); + } + + len = 101 + msg_len; + + WFIFOHEAD(fd,len); + WFIFOW(fd,0) = 0x242; + WFIFOW(fd,2) = len; + WFIFOL(fd,4) = msg->id; + safestrncpy((char*)WFIFOP(fd,8), msg->title, MAIL_TITLE_LENGTH + 1); + safestrncpy((char*)WFIFOP(fd,48), msg->send_name, NAME_LENGTH + 1); + WFIFOL(fd,72) = 0; + WFIFOL(fd,76) = msg->zeny; + + if( item->nameid && (data = itemdb_exists(item->nameid)) != NULL ) + { + WFIFOL(fd,80) = item->amount; + WFIFOW(fd,84) = (data->view_id)?data->view_id:item->nameid; + WFIFOW(fd,86) = data->type; + WFIFOB(fd,88) = item->identify; + WFIFOB(fd,89) = item->attribute; + WFIFOB(fd,90) = item->refine; + WFIFOW(fd,91) = item->card[0]; + WFIFOW(fd,93) = item->card[1]; + WFIFOW(fd,95) = item->card[2]; + WFIFOW(fd,97) = item->card[3]; + } + else // no item, set all to zero + memset(WFIFOP(fd,80), 0x00, 19); + + WFIFOB(fd,99) = (unsigned char)msg_len; + safestrncpy((char*)WFIFOP(fd,100), msg->body, msg_len + 1); + WFIFOSET(fd,len); + + if (msg->status == MAIL_UNREAD) { + msg->status = MAIL_READ; + intif_Mail_read(mail_id); + clif_parse_Mail_refreshinbox(fd, sd); + } + } } @@ -13607,14 +13761,14 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) /// 0241 <mail id>.L void clif_parse_Mail_read(int fd, struct map_session_data *sd) { - int mail_id = RFIFOL(fd,2); + int mail_id = RFIFOL(fd,2); - if (mail_id <= 0) - return; - if (mail_invalid_operation(sd)) - return; + if( mail_id <= 0 ) + return; + if( mail_invalid_operation(sd) ) + return; - clif_Mail_read(sd, RFIFOL(fd,2)); + clif_Mail_read(sd, RFIFOL(fd,2)); } @@ -13622,61 +13776,66 @@ void clif_parse_Mail_read(int fd, struct map_session_data *sd) /// 0244 <mail id>.L void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) { - int mail_id = RFIFOL(fd,2); - int i; - bool fail = false; - - if (!chrif_isconnected()) - return; - if (mail_id <= 0) - return; - if (mail_invalid_operation(sd)) - return; - - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if (i == MAIL_MAX_INBOX) - return; - - if (sd->mail.inbox.msg[i].zeny < 1 && (sd->mail.inbox.msg[i].item.nameid < 1 || sd->mail.inbox.msg[i].item.amount < 1)) - return; - - if (sd->mail.inbox.msg[i].zeny + sd->status.zeny > MAX_ZENY) { - clif_Mail_getattachment(fd, 1); - return; - } - - if (sd->mail.inbox.msg[i].item.nameid > 0) { - struct item_data *data; - unsigned int weight; - - if ((data = itemdb_exists(sd->mail.inbox.msg[i].item.nameid)) == NULL) - return; - - switch (pc_checkadditem(sd, data->nameid, sd->mail.inbox.msg[i].item.amount)) { - case ADDITEM_NEW: - fail = (pc_inventoryblank(sd) == 0); - break; - case ADDITEM_OVERAMOUNT: - fail = true; - } - - if (fail) { - clif_Mail_getattachment(fd, 1); - return; - } - - weight = data->weight * sd->mail.inbox.msg[i].item.amount; - if (sd->weight + weight > sd->max_weight) { - clif_Mail_getattachment(fd, 2); - return; - } - } - - sd->mail.inbox.msg[i].zeny = 0; - memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item)); - clif_Mail_read(sd, mail_id); - - intif_Mail_getattach(sd->status.char_id, mail_id); + int mail_id = RFIFOL(fd,2); + int i; + bool fail = false; + + if( !chrif_isconnected() ) + return; + if( mail_id <= 0 ) + return; + if( mail_invalid_operation(sd) ) + return; + + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i == MAIL_MAX_INBOX ) + return; + + if( sd->mail.inbox.msg[i].zeny < 1 && (sd->mail.inbox.msg[i].item.nameid < 1 || sd->mail.inbox.msg[i].item.amount < 1) ) + return; + + if( sd->mail.inbox.msg[i].zeny + sd->status.zeny > MAX_ZENY ) + { + clif_Mail_getattachment(fd, 1); + return; + } + + if( sd->mail.inbox.msg[i].item.nameid > 0 ) + { + struct item_data *data; + unsigned int weight; + + if ((data = itemdb_exists(sd->mail.inbox.msg[i].item.nameid)) == NULL) + return; + + switch( pc_checkadditem(sd, data->nameid, sd->mail.inbox.msg[i].item.amount) ) + { + case ADDITEM_NEW: + fail = ( pc_inventoryblank(sd) == 0 ); + break; + case ADDITEM_OVERAMOUNT: + fail = true; + } + + if( fail ) + { + clif_Mail_getattachment(fd, 1); + return; + } + + weight = data->weight * sd->mail.inbox.msg[i].item.amount; + if( sd->weight + weight > sd->max_weight ) + { + clif_Mail_getattachment(fd, 2); + return; + } + } + + sd->mail.inbox.msg[i].zeny = 0; + memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item)); + clif_Mail_read(sd, mail_id); + + intif_Mail_getattach(sd->status.char_id, mail_id); } @@ -13684,28 +13843,29 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) /// 0243 <mail id>.L void clif_parse_Mail_delete(int fd, struct map_session_data *sd) { - int mail_id = RFIFOL(fd,2); - int i; + int mail_id = RFIFOL(fd,2); + int i; - if (!chrif_isconnected()) - return; - if (mail_id <= 0) - return; - if (mail_invalid_operation(sd)) - return; + if( !chrif_isconnected() ) + return; + if( mail_id <= 0 ) + return; + if( mail_invalid_operation(sd) ) + return; - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if (i < MAIL_MAX_INBOX) { - struct mail_message *msg = &sd->mail.inbox.msg[i]; + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if (i < MAIL_MAX_INBOX) + { + struct mail_message *msg = &sd->mail.inbox.msg[i]; - if ((msg->item.nameid > 0 && msg->item.amount > 0) || msg->zeny > 0) { - // can't delete mail without removing attachment first - clif_Mail_delete(sd->fd, mail_id, 1); - return; - } + if( (msg->item.nameid > 0 && msg->item.amount > 0) || msg->zeny > 0 ) + {// can't delete mail without removing attachment first + clif_Mail_delete(sd->fd, mail_id, 1); + return; + } - intif_Mail_delete(sd->status.char_id, mail_id); - } + intif_Mail_delete(sd->status.char_id, mail_id); + } } @@ -13713,19 +13873,19 @@ void clif_parse_Mail_delete(int fd, struct map_session_data *sd) /// 0273 <mail id>.L <receive name>.24B void clif_parse_Mail_return(int fd, struct map_session_data *sd) { - int mail_id = RFIFOL(fd,2); - int i; + int mail_id = RFIFOL(fd,2); + int i; - if (mail_id <= 0) - return; - if (mail_invalid_operation(sd)) - return; + if( mail_id <= 0 ) + return; + if( mail_invalid_operation(sd) ) + return; - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if (i < MAIL_MAX_INBOX && sd->mail.inbox.msg[i].send_id != 0) - intif_Mail_return(sd->status.char_id, mail_id); - else - clif_Mail_return(sd->fd, mail_id, 1); + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i < MAIL_MAX_INBOX && sd->mail.inbox.msg[i].send_id != 0 ) + intif_Mail_return(sd->status.char_id, mail_id); + else + clif_Mail_return(sd->fd, mail_id, 1); } @@ -13733,17 +13893,17 @@ void clif_parse_Mail_return(int fd, struct map_session_data *sd) /// 0247 <index>.W <amount>.L void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) { - int idx = RFIFOW(fd,2); - int amount = RFIFOL(fd,4); - unsigned char flag; + int idx = RFIFOW(fd,2); + int amount = RFIFOL(fd,4); + unsigned char flag; - if (!chrif_isconnected()) - return; - if (idx < 0 || amount < 0) - return; + if( !chrif_isconnected() ) + return; + if (idx < 0 || amount < 0) + return; - flag = mail_setitem(sd, idx, amount); - clif_Mail_setattachment(fd,idx,flag); + flag = mail_setitem(sd, idx, amount); + clif_Mail_setattachment(fd,idx,flag); } @@ -13755,12 +13915,12 @@ void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) /// 2 = remove zeny void clif_parse_Mail_winopen(int fd, struct map_session_data *sd) { - int flag = RFIFOW(fd,2); + int flag = RFIFOW(fd,2); - if (flag == 0 || flag == 1) - mail_removeitem(sd, 0); - if (flag == 0 || flag == 2) - mail_removezeny(sd, 0); + if (flag == 0 || flag == 1) + mail_removeitem(sd, 0); + if (flag == 0 || flag == 2) + mail_removezeny(sd, 0); } @@ -13768,59 +13928,56 @@ void clif_parse_Mail_winopen(int fd, struct map_session_data *sd) /// 0248 <packet len>.W <recipient>.24B <title>.40B <body len>.B <body>.?B void clif_parse_Mail_send(int fd, struct map_session_data *sd) { - struct mail_message msg; - int body_len; + struct mail_message msg; + int body_len; - if (!chrif_isconnected()) - return; - if (sd->state.trading) - return; + if( !chrif_isconnected() ) + return; + if( sd->state.trading ) + return; - if (RFIFOW(fd,2) < 69) { - ShowWarning("Invalid Msg Len from account %d.\n", sd->status.account_id); - return; - } + if( RFIFOW(fd,2) < 69 ) { + ShowWarning("Invalid Msg Len from account %d.\n", sd->status.account_id); + return; + } - if (DIFF_TICK(sd->cansendmail_tick, gettick()) > 0) { - clif_displaymessage(sd->fd,msg_txt(675)); //"Cannot send mails too fast!!." - clif_Mail_send(fd, true); // fail - return; - } + if( DIFF_TICK(sd->cansendmail_tick, gettick()) > 0 ) + { + clif_displaymessage(sd->fd,msg_txt(675)); //"Cannot send mails too fast!!." + clif_Mail_send(fd, true); // fail + return; + } - body_len = RFIFOB(fd,68); + body_len = RFIFOB(fd,68); - if (body_len > MAIL_BODY_LENGTH) - body_len = MAIL_BODY_LENGTH; + if (body_len > MAIL_BODY_LENGTH) + body_len = MAIL_BODY_LENGTH; - if (!mail_setattachment(sd, &msg)) { - // Invalid Append condition - clif_Mail_send(sd->fd, true); // fail - mail_removeitem(sd,0); - mail_removezeny(sd,0); - return; - } + if( !mail_setattachment(sd, &msg) ) + { // Invalid Append condition + clif_Mail_send(sd->fd, true); // fail + mail_removeitem(sd,0); + mail_removezeny(sd,0); + return; + } - msg.id = 0; // id will be assigned by charserver - msg.send_id = sd->status.char_id; - msg.dest_id = 0; // will attempt to resolve name - safestrncpy(msg.send_name, sd->status.name, NAME_LENGTH); - safestrncpy(msg.dest_name, (char *)RFIFOP(fd,4), NAME_LENGTH); - safestrncpy(msg.title, (char *)RFIFOP(fd,28), MAIL_TITLE_LENGTH); + msg.id = 0; // id will be assigned by charserver + msg.send_id = sd->status.char_id; + msg.dest_id = 0; // will attempt to resolve name + safestrncpy(msg.send_name, sd->status.name, NAME_LENGTH); + safestrncpy(msg.dest_name, (char*)RFIFOP(fd,4), NAME_LENGTH); + safestrncpy(msg.title, (char*)RFIFOP(fd,28), MAIL_TITLE_LENGTH); - if (msg.title[0] == '\0') { - return; // Message has no length and somehow client verification was skipped. - } - - if (body_len) - safestrncpy(msg.body, (char *)RFIFOP(fd,69), body_len + 1); - else - memset(msg.body, 0x00, MAIL_BODY_LENGTH); + if (body_len) + safestrncpy(msg.body, (char*)RFIFOP(fd,69), body_len + 1); + else + memset(msg.body, 0x00, MAIL_BODY_LENGTH); - msg.timestamp = time(NULL); - if (!intif_Mail_send(sd->status.account_id, &msg)) - mail_deliveryfail(sd, &msg); + msg.timestamp = time(NULL); + if( !intif_Mail_send(sd->status.account_id, &msg) ) + mail_deliveryfail(sd, &msg); - sd->cansendmail_tick = gettick() + 1000; // 1 Second flood Protection + sd->cansendmail_tick = gettick() + 1000; // 1 Second flood Protection } @@ -13835,15 +13992,15 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd) /// 1 = close void clif_Auction_openwindow(struct map_session_data *sd) { - int fd = sd->fd; + int fd = sd->fd; - if (sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading) - return; + if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading ) + return; - WFIFOHEAD(fd,packet_len(0x25f)); - WFIFOW(fd,0) = 0x25f; - WFIFOL(fd,2) = 0; - WFIFOSET(fd,packet_len(0x25f)); + WFIFOHEAD(fd,packet_len(0x25f)); + WFIFOW(fd,0) = 0x25f; + WFIFOL(fd,2) = 0; + WFIFOSET(fd,packet_len(0x25f)); } @@ -13851,44 +14008,45 @@ void clif_Auction_openwindow(struct map_session_data *sd) /// 0252 <packet len>.W <pages>.L <count>.L { <auction id>.L <seller name>.24B <name id>.W <type>.L <amount>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <now price>.L <max price>.L <buyer name>.24B <delete time>.L }* void clif_Auction_results(struct map_session_data *sd, short count, short pages, uint8 *buf) { - int i, fd = sd->fd, len = sizeof(struct auction_data); - struct auction_data auction; - struct item_data *item; - int k; - - WFIFOHEAD(fd,12 + (count * 83)); - WFIFOW(fd,0) = 0x252; - WFIFOW(fd,2) = 12 + (count * 83); - WFIFOL(fd,4) = pages; - WFIFOL(fd,8) = count; - - for (i = 0; i < count; i++) { - memcpy(&auction, RBUFP(buf,i * len), len); - k = 12 + (i * 83); - - WFIFOL(fd,k) = auction.auction_id; - safestrncpy((char *)WFIFOP(fd,4+k), auction.seller_name, NAME_LENGTH); - - if ((item = itemdb_exists(auction.item.nameid)) != NULL && item->view_id > 0) - WFIFOW(fd,28+k) = item->view_id; - else - WFIFOW(fd,28+k) = auction.item.nameid; - - WFIFOL(fd,30+k) = auction.type; - WFIFOW(fd,34+k) = auction.item.amount; // Always 1 - WFIFOB(fd,36+k) = auction.item.identify; - WFIFOB(fd,37+k) = auction.item.attribute; - WFIFOB(fd,38+k) = auction.item.refine; - WFIFOW(fd,39+k) = auction.item.card[0]; - WFIFOW(fd,41+k) = auction.item.card[1]; - WFIFOW(fd,43+k) = auction.item.card[2]; - WFIFOW(fd,45+k) = auction.item.card[3]; - WFIFOL(fd,47+k) = auction.price; - WFIFOL(fd,51+k) = auction.buynow; - safestrncpy((char *)WFIFOP(fd,55+k), auction.buyer_name, NAME_LENGTH); - WFIFOL(fd,79+k) = (uint32)auction.timestamp; - } - WFIFOSET(fd,WFIFOW(fd,2)); + int i, fd = sd->fd, len = sizeof(struct auction_data); + struct auction_data auction; + struct item_data *item; + int k; + + WFIFOHEAD(fd,12 + (count * 83)); + WFIFOW(fd,0) = 0x252; + WFIFOW(fd,2) = 12 + (count * 83); + WFIFOL(fd,4) = pages; + WFIFOL(fd,8) = count; + + for( i = 0; i < count; i++ ) + { + memcpy(&auction, RBUFP(buf,i * len), len); + k = 12 + (i * 83); + + WFIFOL(fd,k) = auction.auction_id; + safestrncpy((char*)WFIFOP(fd,4+k), auction.seller_name, NAME_LENGTH); + + if( (item = itemdb_exists(auction.item.nameid)) != NULL && item->view_id > 0 ) + WFIFOW(fd,28+k) = item->view_id; + else + WFIFOW(fd,28+k) = auction.item.nameid; + + WFIFOL(fd,30+k) = auction.type; + WFIFOW(fd,34+k) = auction.item.amount; // Always 1 + WFIFOB(fd,36+k) = auction.item.identify; + WFIFOB(fd,37+k) = auction.item.attribute; + WFIFOB(fd,38+k) = auction.item.refine; + WFIFOW(fd,39+k) = auction.item.card[0]; + WFIFOW(fd,41+k) = auction.item.card[1]; + WFIFOW(fd,43+k) = auction.item.card[2]; + WFIFOW(fd,45+k) = auction.item.card[3]; + WFIFOL(fd,47+k) = auction.price; + WFIFOL(fd,51+k) = auction.buynow; + safestrncpy((char*)WFIFOP(fd,55+k), auction.buyer_name, NAME_LENGTH); + WFIFOL(fd,79+k) = (uint32)auction.timestamp; + } + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -13899,11 +14057,11 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages, /// 1 = failure static void clif_Auction_setitem(int fd, int index, bool fail) { - WFIFOHEAD(fd,packet_len(0x256)); - WFIFOW(fd,0) = 0x256; - WFIFOW(fd,2) = index; - WFIFOB(fd,4) = fail; - WFIFOSET(fd,packet_len(0x256)); + WFIFOHEAD(fd,packet_len(0x256)); + WFIFOW(fd,0) = 0x256; + WFIFOW(fd,2) = index; + WFIFOB(fd,4) = fail; + WFIFOSET(fd,packet_len(0x256)); } @@ -13915,10 +14073,10 @@ static void clif_Auction_setitem(int fd, int index, bool fail) /// ? = junk, uninitialized value (ex. when switching between list filters) void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd) { - if (sd->auction.amount > 0) - clif_additem(sd, sd->auction.index, sd->auction.amount, 0); + if( sd->auction.amount > 0 ) + clif_additem(sd, sd->auction.index, sd->auction.amount, 0); - sd->auction.amount = 0; + sd->auction.amount = 0; } @@ -13926,40 +14084,41 @@ void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd) /// 024c <index>.W <count>.L void clif_parse_Auction_setitem(int fd, struct map_session_data *sd) { - int idx = RFIFOW(fd,2) - 2; - int amount = RFIFOL(fd,4); // Always 1 - struct item_data *item; + int idx = RFIFOW(fd,2) - 2; + int amount = RFIFOL(fd,4); // Always 1 + struct item_data *item; - if (sd->auction.amount > 0) - sd->auction.amount = 0; + if( sd->auction.amount > 0 ) + sd->auction.amount = 0; - if (idx < 0 || idx >= MAX_INVENTORY) { - ShowWarning("Character %s trying to set invalid item index in auctions.\n", sd->status.name); - return; - } + if( idx < 0 || idx >= MAX_INVENTORY ) + { + ShowWarning("Character %s trying to set invalid item index in auctions.\n", sd->status.name); + return; + } - if (amount != 1 || amount > sd->status.inventory[idx].amount) { - // By client, amount is always set to 1. Maybe this is a future implementation. - ShowWarning("Character %s trying to set invalid amount in auctions.\n", sd->status.name); - return; - } + if( amount != 1 || amount > sd->status.inventory[idx].amount ) + { // By client, amount is always set to 1. Maybe this is a future implementation. + ShowWarning("Character %s trying to set invalid amount in auctions.\n", sd->status.name); + return; + } - if ((item = itemdb_exists(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC)) { - // Consumable or pets are not allowed - clif_Auction_setitem(sd->fd, idx, true); - return; - } + if( (item = itemdb_exists(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC) ) + { // Consumable or pets are not allowed + clif_Auction_setitem(sd->fd, idx, true); + return; + } - if (!pc_can_give_items(sd) || sd->status.inventory[idx].expire_time || - !sd->status.inventory[idx].identify || - !itemdb_canauction(&sd->status.inventory[idx],pc_get_group_level(sd))) { // Quest Item or something else - clif_Auction_setitem(sd->fd, idx, true); - return; - } + if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time || + !sd->status.inventory[idx].identify || + !itemdb_canauction(&sd->status.inventory[idx],pc_get_group_level(sd)) ) { // Quest Item or something else + clif_Auction_setitem(sd->fd, idx, true); + return; + } - sd->auction.index = idx; - sd->auction.amount = amount; - clif_Auction_setitem(fd, idx + 2, false); + sd->auction.index = idx; + sd->auction.amount = amount; + clif_Auction_setitem(fd, idx + 2, false); } /// Result from an auction action (ZC_AUCTION_RESULT). @@ -13977,10 +14136,10 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd) /// 9 = You cannot place more than 5 bids at a time void clif_Auction_message(int fd, unsigned char flag) { - WFIFOHEAD(fd,packet_len(0x250)); - WFIFOW(fd,0) = 0x250; - WFIFOB(fd,2) = flag; - WFIFOSET(fd,packet_len(0x250)); + WFIFOHEAD(fd,packet_len(0x250)); + WFIFOW(fd,0) = 0x250; + WFIFOB(fd,2) = flag; + WFIFOSET(fd,packet_len(0x250)); } @@ -13992,10 +14151,10 @@ void clif_Auction_message(int fd, unsigned char flag) /// 2 = Auction ID is incorrect void clif_Auction_close(int fd, unsigned char flag) { - WFIFOHEAD(fd,packet_len(0x25e)); - WFIFOW(fd,0) = 0x25d; // BUG: The client identifies this packet as 0x25d (CZ_AUCTION_REQ_MY_SELL_STOP) - WFIFOW(fd,2) = flag; - WFIFOSET(fd,packet_len(0x25e)); + WFIFOHEAD(fd,packet_len(0x25e)); + WFIFOW(fd,0) = 0x25d; // BUG: The client identifies this packet as 0x25d (CZ_AUCTION_REQ_MY_SELL_STOP) + WFIFOW(fd,2) = flag; + WFIFOSET(fd,packet_len(0x25e)); } @@ -14003,75 +14162,81 @@ void clif_Auction_close(int fd, unsigned char flag) /// 024d <now money>.L <max money>.L <delete hour>.W void clif_parse_Auction_register(int fd, struct map_session_data *sd) { - struct auction_data auction; - struct item_data *item; - - auction.price = RFIFOL(fd,2); - auction.buynow = RFIFOL(fd,6); - auction.hours = RFIFOW(fd,10); - - // Invalid Situations... - if (sd->auction.amount < 1) { - ShowWarning("Character %s trying to register auction without item.\n", sd->status.name); - return; - } - - if (auction.price >= auction.buynow) { - ShowWarning("Character %s trying to alter auction prices.\n", sd->status.name); - return; - } - - if (auction.hours < 1 || auction.hours > 48) { - ShowWarning("Character %s trying to enter an invalid time for auction.\n", sd->status.name); - return; - } - - // Auction checks... - if (sd->status.zeny < (auction.hours * battle_config.auction_feeperhour)) { - clif_Auction_message(fd, 5); // You do not have enough zeny to pay the Auction Fee. - return; - } - - if (auction.buynow > battle_config.auction_maximumprice) { - // Zeny Limits - auction.buynow = battle_config.auction_maximumprice; - if (auction.price >= auction.buynow) - auction.price = auction.buynow - 1; - } - - auction.auction_id = 0; - auction.seller_id = sd->status.char_id; - safestrncpy(auction.seller_name, sd->status.name, sizeof(auction.seller_name)); - auction.buyer_id = 0; - memset(auction.buyer_name, '\0', sizeof(auction.buyer_name)); - - if (sd->status.inventory[sd->auction.index].nameid == 0 || sd->status.inventory[sd->auction.index].amount < sd->auction.amount) { - clif_Auction_message(fd, 2); // The auction has been canceled - return; - } - - if ((item = itemdb_exists(sd->status.inventory[sd->auction.index].nameid)) == NULL) { - // Just in case - clif_Auction_message(fd, 2); // The auction has been canceled - return; - } - - safestrncpy(auction.item_name, item->jname, sizeof(auction.item_name)); - auction.type = item->type; - memcpy(&auction.item, &sd->status.inventory[sd->auction.index], sizeof(struct item)); - auction.item.amount = 1; - auction.timestamp = 0; - - if (!intif_Auction_register(&auction)) - clif_Auction_message(fd, 4); // No Char Server? lets say something to the client - else { - int zeny = auction.hours*battle_config.auction_feeperhour; - - pc_delitem(sd, sd->auction.index, sd->auction.amount, 1, 6, LOG_TYPE_AUCTION); - sd->auction.amount = 0; - - pc_payzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); - } + struct auction_data auction; + struct item_data *item; + + auction.price = RFIFOL(fd,2); + auction.buynow = RFIFOL(fd,6); + auction.hours = RFIFOW(fd,10); + + // Invalid Situations... + if( sd->auction.amount < 1 ) + { + ShowWarning("Character %s trying to register auction without item.\n", sd->status.name); + return; + } + + if( auction.price >= auction.buynow ) + { + ShowWarning("Character %s trying to alter auction prices.\n", sd->status.name); + return; + } + + if( auction.hours < 1 || auction.hours > 48 ) + { + ShowWarning("Character %s trying to enter an invalid time for auction.\n", sd->status.name); + return; + } + + // Auction checks... + if( sd->status.zeny < (auction.hours * battle_config.auction_feeperhour) ) + { + clif_Auction_message(fd, 5); // You do not have enough zeny to pay the Auction Fee. + return; + } + + if( auction.buynow > battle_config.auction_maximumprice ) + { // Zeny Limits + auction.buynow = battle_config.auction_maximumprice; + if( auction.price >= auction.buynow ) + auction.price = auction.buynow - 1; + } + + auction.auction_id = 0; + auction.seller_id = sd->status.char_id; + safestrncpy(auction.seller_name, sd->status.name, sizeof(auction.seller_name)); + auction.buyer_id = 0; + memset(auction.buyer_name, '\0', sizeof(auction.buyer_name)); + + if( sd->status.inventory[sd->auction.index].nameid == 0 || sd->status.inventory[sd->auction.index].amount < sd->auction.amount ) + { + clif_Auction_message(fd, 2); // The auction has been canceled + return; + } + + if( (item = itemdb_exists(sd->status.inventory[sd->auction.index].nameid)) == NULL ) + { // Just in case + clif_Auction_message(fd, 2); // The auction has been canceled + return; + } + + safestrncpy(auction.item_name, item->jname, sizeof(auction.item_name)); + auction.type = item->type; + memcpy(&auction.item, &sd->status.inventory[sd->auction.index], sizeof(struct item)); + auction.item.amount = 1; + auction.timestamp = 0; + + if( !intif_Auction_register(&auction) ) + clif_Auction_message(fd, 4); // No Char Server? lets say something to the client + else + { + int zeny = auction.hours*battle_config.auction_feeperhour; + + pc_delitem(sd, sd->auction.index, sd->auction.amount, 1, 6, LOG_TYPE_AUCTION); + sd->auction.amount = 0; + + pc_payzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); + } } @@ -14079,9 +14244,9 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) /// 024e <auction id>.L void clif_parse_Auction_cancel(int fd, struct map_session_data *sd) { - unsigned int auction_id = RFIFOL(fd,2); + unsigned int auction_id = RFIFOL(fd,2); - intif_Auction_cancel(sd->status.char_id, auction_id); + intif_Auction_cancel(sd->status.char_id, auction_id); } @@ -14089,9 +14254,9 @@ void clif_parse_Auction_cancel(int fd, struct map_session_data *sd) /// 025d <auction id>.L void clif_parse_Auction_close(int fd, struct map_session_data *sd) { - unsigned int auction_id = RFIFOL(fd,2); + unsigned int auction_id = RFIFOL(fd,2); - intif_Auction_close(sd->status.char_id, auction_id); + intif_Auction_close(sd->status.char_id, auction_id); } @@ -14099,24 +14264,24 @@ void clif_parse_Auction_close(int fd, struct map_session_data *sd) /// 024f <auction id>.L <money>.L void clif_parse_Auction_bid(int fd, struct map_session_data *sd) { - unsigned int auction_id = RFIFOL(fd,2); - int bid = RFIFOL(fd,6); + unsigned int auction_id = RFIFOL(fd,2); + int bid = RFIFOL(fd,6); - if (!pc_can_give_items(sd)) { //They aren't supposed to give zeny [Inkfish] - clif_displaymessage(sd->fd, msg_txt(246)); - return; - } + if( !pc_can_give_items(sd) ) { //They aren't supposed to give zeny [Inkfish] + clif_displaymessage(sd->fd, msg_txt(246)); + return; + } - if (bid <= 0) - clif_Auction_message(fd, 0); // You have failed to bid into the auction - else if (bid > sd->status.zeny) - clif_Auction_message(fd, 8); // You do not have enough zeny - else if (CheckForCharServer()) // char server is down (bugreport:1138) - clif_Auction_message(fd, 0); // You have failed to bid into the auction - else { - pc_payzeny(sd, bid, LOG_TYPE_AUCTION, NULL); - intif_Auction_bid(sd->status.char_id, sd->status.name, auction_id, bid); - } + if( bid <= 0 ) + clif_Auction_message(fd, 0); // You have failed to bid into the auction + else if( bid > sd->status.zeny ) + clif_Auction_message(fd, 8); // You do not have enough zeny + else if ( CheckForCharServer() ) // char server is down (bugreport:1138) + clif_Auction_message(fd, 0); // You have failed to bid into the auction + else { + pc_payzeny(sd, bid, LOG_TYPE_AUCTION, NULL); + intif_Auction_bid(sd->status.char_id, sd->status.name, auction_id, bid); + } } @@ -14129,16 +14294,16 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd) /// 3 = misc /// 4 = name search /// 5 = auction id search -void clif_parse_Auction_search(int fd, struct map_session_data *sd) +void clif_parse_Auction_search(int fd, struct map_session_data* sd) { - char search_text[NAME_LENGTH]; - short type = RFIFOW(fd,2), page = RFIFOW(fd,32); - int price = RFIFOL(fd,4); // FIXME: bug #5071 + char search_text[NAME_LENGTH]; + short type = RFIFOW(fd,2), page = RFIFOW(fd,32); + int price = RFIFOL(fd,4); // FIXME: bug #5071 - clif_parse_Auction_cancelreg(fd, sd); + clif_parse_Auction_cancelreg(fd, sd); - safestrncpy(search_text, (char *)RFIFOP(fd,8), sizeof(search_text)); - intif_Auction_requestlist(sd->status.char_id, type, price, search_text, page); + safestrncpy(search_text, (char*)RFIFOP(fd,8), sizeof(search_text)); + intif_Auction_requestlist(sd->status.char_id, type, price, search_text, page); } @@ -14147,12 +14312,12 @@ void clif_parse_Auction_search(int fd, struct map_session_data *sd) /// type: /// 0 = sell (own auctions) /// 1 = buy (own bids) -void clif_parse_Auction_buysell(int fd, struct map_session_data *sd) +void clif_parse_Auction_buysell(int fd, struct map_session_data* sd) { - short type = RFIFOW(fd,2) + 6; - clif_parse_Auction_cancelreg(fd, sd); + short type = RFIFOW(fd,2) + 6; + clif_parse_Auction_cancelreg(fd, sd); - intif_Auction_requestlist(sd->status.char_id, type, 0, "", 1); + intif_Auction_requestlist(sd->status.char_id, type, 0, "", 1); } @@ -14164,34 +14329,35 @@ void clif_parse_Auction_buysell(int fd, struct map_session_data *sd) /// 0287 <packet len>.W <cash point>.L <kafra point>.L { <sell price>.L <discount price>.L <item type>.B <name id>.W }* (PACKETVER >= 20070711) void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) { - int fd,i; + int fd,i; #if PACKETVER < 20070711 - const int offset = 8; + const int offset = 8; #else - const int offset = 12; + const int offset = 12; #endif - nullpo_retv(sd); - nullpo_retv(nd); - - fd = sd->fd; - sd->npc_shopid = nd->bl.id; - WFIFOHEAD(fd,offset+nd->u.shop.count*11); - WFIFOW(fd,0) = 0x287; - WFIFOW(fd,2) = offset+nd->u.shop.count*11; - WFIFOL(fd,4) = sd->cashPoints; // Cash Points + nullpo_retv(sd); + nullpo_retv(nd); + + fd = sd->fd; + sd->npc_shopid = nd->bl.id; + WFIFOHEAD(fd,offset+nd->u.shop.count*11); + WFIFOW(fd,0) = 0x287; + WFIFOW(fd,2) = offset+nd->u.shop.count*11; + WFIFOL(fd,4) = sd->cashPoints; // Cash Points #if PACKETVER >= 20070711 - WFIFOL(fd,8) = sd->kafraPoints; // Kafra Points + WFIFOL(fd,8) = sd->kafraPoints; // Kafra Points #endif - for (i = 0; i < nd->u.shop.count; i++) { - struct item_data *id = itemdb_search(nd->u.shop.shop_item[i].nameid); - WFIFOL(fd,offset+0+i*11) = nd->u.shop.shop_item[i].value; - WFIFOL(fd,offset+4+i*11) = nd->u.shop.shop_item[i].value; // Discount Price - WFIFOB(fd,offset+8+i*11) = itemtype(id->type); - WFIFOW(fd,offset+9+i*11) = (id->view_id > 0) ? id->view_id : id->nameid; - } - WFIFOSET(fd,WFIFOW(fd,2)); + for( i = 0; i < nd->u.shop.count; i++ ) + { + struct item_data* id = itemdb_search(nd->u.shop.shop_item[i].nameid); + WFIFOL(fd,offset+0+i*11) = nd->u.shop.shop_item[i].value; + WFIFOL(fd,offset+4+i*11) = nd->u.shop.shop_item[i].value; // Discount Price + WFIFOB(fd,offset+8+i*11) = itemtype(id->type); + WFIFOW(fd,offset+9+i*11) = ( id->view_id > 0 ) ? id->view_id : id->nameid; + } + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -14208,20 +14374,20 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) /// 6 = You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY) /// 7 = You can purchase up to 10 items. /// 8 = Some items could not be purchased. -void clif_cashshop_ack(struct map_session_data *sd, int error) +void clif_cashshop_ack(struct map_session_data* sd, int error) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd, packet_len(0x289)); - WFIFOW(fd,0) = 0x289; - WFIFOL(fd,2) = sd->cashPoints; + WFIFOHEAD(fd, packet_len(0x289)); + WFIFOW(fd,0) = 0x289; + WFIFOL(fd,2) = sd->cashPoints; #if PACKETVER < 20070711 - WFIFOW(fd,6) = TOW(error); + WFIFOW(fd,6) = TOW(error); #else - WFIFOL(fd,6) = sd->kafraPoints; - WFIFOW(fd,10) = TOW(error); + WFIFOL(fd,6) = sd->kafraPoints; + WFIFOW(fd,10) = TOW(error); #endif - WFIFOSET(fd, packet_len(0x289)); + WFIFOSET(fd, packet_len(0x289)); } @@ -14234,9 +14400,10 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) int fail = 0; nullpo_retv(sd); - if (sd->state.trading || !sd->npc_shopid) + if( sd->state.trading || !sd->npc_shopid ) fail = 1; - else { + else + { #if PACKETVER < 20101116 short nameid = RFIFOW(fd,2); short amount = RFIFOW(fd,4); @@ -14247,9 +14414,10 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) int len = RFIFOW(fd,2); int points = RFIFOL(fd,4); int count = RFIFOW(fd,8); - unsigned short *item_list = (unsigned short *)RFIFOP(fd,10); + unsigned short* item_list = (unsigned short*)RFIFOP(fd,10); - if (len < 10 || len != 10 + count * 4) { + if( len < 10 || len != 10 + count * 4) + { ShowWarning("Player %u sent incorrect cash shop buy packet (len %u:%u)!\n", sd->status.char_id, len, 10 + count * 4); return; } @@ -14272,12 +14440,12 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) /// 2 = "You cannot adopt a married person." void clif_Adopt_reply(struct map_session_data *sd, int type) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,6); - WFIFOW(fd,0) = 0x216; - WFIFOL(fd,2) = type; - WFIFOSET(fd,6); + WFIFOHEAD(fd,6); + WFIFOW(fd,0) = 0x216; + WFIFOL(fd,2) = type; + WFIFOSET(fd,6); } @@ -14285,14 +14453,14 @@ void clif_Adopt_reply(struct map_session_data *sd, int type) /// 01f6 <account id>.L <char id>.L <name>.B void clif_Adopt_request(struct map_session_data *sd, struct map_session_data *src, int p_id) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,34); - WFIFOW(fd,0) = 0x1f6; - WFIFOL(fd,2) = src->status.account_id; - WFIFOL(fd,6) = p_id; - memcpy(WFIFOP(fd,10), src->status.name, NAME_LENGTH); - WFIFOSET(fd,34); + WFIFOHEAD(fd,34); + WFIFOW(fd,0) = 0x1f6; + WFIFOL(fd,2) = src->status.account_id; + WFIFOL(fd,6) = p_id; + memcpy(WFIFOP(fd,10), src->status.name, NAME_LENGTH); + WFIFOSET(fd,34); } @@ -14300,12 +14468,13 @@ void clif_Adopt_request(struct map_session_data *sd, struct map_session_data *sr /// 01f9 <account id>.L void clif_parse_Adopt_request(int fd, struct map_session_data *sd) { - struct map_session_data *tsd = map_id2sd(RFIFOL(fd,2)), *p_sd = map_charid2sd(sd->status.partner_id); + struct map_session_data *tsd = map_id2sd(RFIFOL(fd,2)), *p_sd = map_charid2sd(sd->status.partner_id); - if (pc_can_Adopt(sd, p_sd, tsd)) { - tsd->adopt_invite = sd->status.account_id; - clif_Adopt_request(tsd, sd, p_sd->status.account_id); - } + if( pc_can_Adopt(sd, p_sd, tsd) ) + { + tsd->adopt_invite = sd->status.account_id; + clif_Adopt_request(tsd, sd, p_sd->status.account_id); + } } @@ -14316,25 +14485,25 @@ void clif_parse_Adopt_request(int fd, struct map_session_data *sd) /// 1 = accepted void clif_parse_Adopt_reply(int fd, struct map_session_data *sd) { - int p1_id = RFIFOL(fd,2); - int p2_id = RFIFOL(fd,6); - int result = RFIFOL(fd,10); - struct map_session_data *p1_sd = map_id2sd(p1_id); - struct map_session_data *p2_sd = map_id2sd(p2_id); + int p1_id = RFIFOL(fd,2); + int p2_id = RFIFOL(fd,6); + int result = RFIFOL(fd,10); + struct map_session_data* p1_sd = map_id2sd(p1_id); + struct map_session_data* p2_sd = map_id2sd(p2_id); - int pid = sd->adopt_invite; - sd->adopt_invite = 0; + int pid = sd->adopt_invite; + sd->adopt_invite = 0; - if (p1_sd == NULL || p2_sd == NULL) - return; // Both players need to be online + if( p1_sd == NULL || p2_sd == NULL ) + return; // Both players need to be online - if (pid != p1_sd->status.account_id) - return; // Incorrect values + if( pid != p1_sd->status.account_id ) + return; // Incorrect values - if (result == 0) - return; // Rejected + if( result == 0 ) + return; // Rejected - pc_adoption(p1_sd, p2_sd, sd); + pc_adoption(p1_sd, p2_sd, sd); } @@ -14347,55 +14516,59 @@ void clif_parse_Adopt_reply(int fd, struct map_session_data *sd) /// 3 = Boss is dead (BOSS_INFO_DEAD). void clif_bossmapinfo(int fd, struct mob_data *md, short flag) { - WFIFOHEAD(fd,70); - memset(WFIFOP(fd,0),0,70); - WFIFOW(fd,0) = 0x293; - - if (md != NULL) { - if (md->bl.prev != NULL) { - // Boss on This Map - if (flag) { - WFIFOB(fd,2) = 1; - WFIFOL(fd,3) = md->bl.x; - WFIFOL(fd,7) = md->bl.y; - } else - WFIFOB(fd,2) = 2; // First Time - } else if (md->spawn_timer != INVALID_TIMER) { - // Boss is Dead - const struct TimerData *timer_data = get_timer(md->spawn_timer); - unsigned int seconds; - int hours, minutes; - - seconds = DIFF_TICK(timer_data->tick, gettick()) / 1000 + 60; - hours = seconds / (60 * 60); - seconds = seconds - (60 * 60 * hours); - minutes = seconds / 60; - - WFIFOB(fd,2) = 3; - WFIFOW(fd,11) = hours; // Hours - WFIFOW(fd,13) = minutes; // Minutes - } - safestrncpy((char *)WFIFOP(fd,19), md->db->jname, NAME_LENGTH); - } - - WFIFOSET(fd,70); + WFIFOHEAD(fd,70); + memset(WFIFOP(fd,0),0,70); + WFIFOW(fd,0) = 0x293; + + if( md != NULL ) + { + if( md->bl.prev != NULL ) + { // Boss on This Map + if( flag ) + { + WFIFOB(fd,2) = 1; + WFIFOL(fd,3) = md->bl.x; + WFIFOL(fd,7) = md->bl.y; + } + else + WFIFOB(fd,2) = 2; // First Time + } + else if (md->spawn_timer != INVALID_TIMER) + { // Boss is Dead + const struct TimerData * timer_data = get_timer(md->spawn_timer); + unsigned int seconds; + int hours, minutes; + + seconds = DIFF_TICK(timer_data->tick, gettick()) / 1000 + 60; + hours = seconds / (60 * 60); + seconds = seconds - (60 * 60 * hours); + minutes = seconds / 60; + + WFIFOB(fd,2) = 3; + WFIFOW(fd,11) = hours; // Hours + WFIFOW(fd,13) = minutes; // Minutes + } + safestrncpy((char*)WFIFOP(fd,19), md->db->jname, NAME_LENGTH); + } + + WFIFOSET(fd,70); } /// Requesting equip of a player (CZ_EQUIPWIN_MICROSCOPE). /// 02d6 <account id>.L -void clif_parse_ViewPlayerEquip(int fd, struct map_session_data *sd) +void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) { - int charid = RFIFOL(fd, 2); - struct map_session_data *tsd = map_id2sd(charid); + int charid = RFIFOL(fd, 2); + struct map_session_data* tsd = map_id2sd(charid); - if (!tsd) - return; + if (!tsd) + return; - if (tsd->status.show_equip || pc_has_permission(sd, PC_PERM_VIEW_EQUIPMENT)) - clif_viewequip_ack(sd, tsd); - else - clif_viewequip_fail(sd); + if( tsd->status.show_equip || pc_has_permission(sd, PC_PERM_VIEW_EQUIPMENT) ) + clif_viewequip_ack(sd, tsd); + else + clif_viewequip_fail(sd); } @@ -14406,11 +14579,11 @@ void clif_parse_ViewPlayerEquip(int fd, struct map_session_data *sd) /// value: /// 0 = disabled /// 1 = enabled -void clif_parse_EquipTick(int fd, struct map_session_data *sd) +void clif_parse_EquipTick(int fd, struct map_session_data* sd) { - bool flag = (bool)RFIFOL(fd,6); - sd->status.show_equip = flag; - clif_equiptickack(sd, flag); + bool flag = (bool)RFIFOL(fd,6); + sd->status.show_equip = flag; + clif_equiptickack(sd, flag); } @@ -14419,141 +14592,146 @@ void clif_parse_EquipTick(int fd, struct map_session_data *sd) /// Sends list of all quest states (ZC_ALL_QUEST_LIST). /// 02b1 <packet len>.W <num>.L { <quest id>.L <active>.B }*num -void clif_quest_send_list(struct map_session_data *sd) +void clif_quest_send_list(struct map_session_data * sd) { - int fd = sd->fd; - int i; - int len = sd->avail_quests*5+8; + int fd = sd->fd; + int i; + int len = sd->avail_quests*5+8; - WFIFOHEAD(fd,len); - WFIFOW(fd, 0) = 0x2b1; - WFIFOW(fd, 2) = len; - WFIFOL(fd, 4) = sd->avail_quests; + WFIFOHEAD(fd,len); + WFIFOW(fd, 0) = 0x2b1; + WFIFOW(fd, 2) = len; + WFIFOL(fd, 4) = sd->avail_quests; - for (i = 0; i < sd->avail_quests; i++) { - WFIFOL(fd, i*5+8) = sd->quest_log[i].quest_id; - WFIFOB(fd, i*5+12) = sd->quest_log[i].state; - } + for( i = 0; i < sd->avail_quests; i++ ) + { + WFIFOL(fd, i*5+8) = sd->quest_log[i].quest_id; + WFIFOB(fd, i*5+12) = sd->quest_log[i].state; + } - WFIFOSET(fd, len); + WFIFOSET(fd, len); } /// Sends list of all quest missions (ZC_ALL_QUEST_MISSION). /// 02b2 <packet len>.W <num>.L { <quest id>.L <start time>.L <expire time>.L <mobs>.W { <mob id>.L <mob count>.W <mob name>.24B }*3 }*num -void clif_quest_send_mission(struct map_session_data *sd) -{ - int fd = sd->fd; - int i, j; - int len = sd->avail_quests*104+8; - struct mob_db *mob; - - WFIFOHEAD(fd, len); - WFIFOW(fd, 0) = 0x2b2; - WFIFOW(fd, 2) = len; - WFIFOL(fd, 4) = sd->avail_quests; - - for (i = 0; i < sd->avail_quests; i++) { - WFIFOL(fd, i*104+8) = sd->quest_log[i].quest_id; - WFIFOL(fd, i*104+12) = sd->quest_log[i].time - quest_db[sd->quest_index[i]].time; - WFIFOL(fd, i*104+16) = sd->quest_log[i].time; - WFIFOW(fd, i*104+20) = quest_db[sd->quest_index[i]].num_objectives; - - for (j = 0 ; j < quest_db[sd->quest_index[i]].num_objectives; j++) { - WFIFOL(fd, i*104+22+j*30) = quest_db[sd->quest_index[i]].mob[j]; - WFIFOW(fd, i*104+26+j*30) = sd->quest_log[i].count[j]; - mob = mob_db(quest_db[sd->quest_index[i]].mob[j]); - memcpy(WFIFOP(fd, i*104+28+j*30), mob?mob->jname:"NULL", NAME_LENGTH); - } - } +void clif_quest_send_mission(struct map_session_data * sd) +{ + int fd = sd->fd; + int i, j; + int len = sd->avail_quests*104+8; + struct mob_db *mob; - WFIFOSET(fd, len); + WFIFOHEAD(fd, len); + WFIFOW(fd, 0) = 0x2b2; + WFIFOW(fd, 2) = len; + WFIFOL(fd, 4) = sd->avail_quests; + + for( i = 0; i < sd->avail_quests; i++ ) + { + WFIFOL(fd, i*104+8) = sd->quest_log[i].quest_id; + WFIFOL(fd, i*104+12) = sd->quest_log[i].time - quest_db[sd->quest_index[i]].time; + WFIFOL(fd, i*104+16) = sd->quest_log[i].time; + WFIFOW(fd, i*104+20) = quest_db[sd->quest_index[i]].num_objectives; + + for( j = 0 ; j < quest_db[sd->quest_index[i]].num_objectives; j++ ) + { + WFIFOL(fd, i*104+22+j*30) = quest_db[sd->quest_index[i]].mob[j]; + WFIFOW(fd, i*104+26+j*30) = sd->quest_log[i].count[j]; + mob = mob_db(quest_db[sd->quest_index[i]].mob[j]); + memcpy(WFIFOP(fd, i*104+28+j*30), mob?mob->jname:"NULL", NAME_LENGTH); + } + } + + WFIFOSET(fd, len); } /// Notification about a new quest (ZC_ADD_QUEST). /// 02b3 <quest id>.L <active>.B <start time>.L <expire time>.L <mobs>.W { <mob id>.L <mob count>.W <mob name>.24B }*3 -void clif_quest_add(struct map_session_data *sd, struct quest *qd, int index) -{ - int fd = sd->fd; - int i; - struct mob_db *mob; - - WFIFOHEAD(fd, packet_len(0x2b3)); - WFIFOW(fd, 0) = 0x2b3; - WFIFOL(fd, 2) = qd->quest_id; - WFIFOB(fd, 6) = qd->state; - WFIFOB(fd, 7) = qd->time - quest_db[index].time; - WFIFOL(fd, 11) = qd->time; - WFIFOW(fd, 15) = quest_db[index].num_objectives; - - for (i = 0; i < quest_db[index].num_objectives; i++) { - WFIFOL(fd, i*30+17) = quest_db[index].mob[i]; - WFIFOW(fd, i*30+21) = qd->count[i]; - mob = mob_db(quest_db[index].mob[i]); - memcpy(WFIFOP(fd, i*30+23), mob?mob->jname:"NULL", NAME_LENGTH); - } +void clif_quest_add(struct map_session_data * sd, struct quest * qd, int index) +{ + int fd = sd->fd; + int i; + struct mob_db *mob; + + WFIFOHEAD(fd, packet_len(0x2b3)); + WFIFOW(fd, 0) = 0x2b3; + WFIFOL(fd, 2) = qd->quest_id; + WFIFOB(fd, 6) = qd->state; + WFIFOB(fd, 7) = qd->time - quest_db[index].time; + WFIFOL(fd, 11) = qd->time; + WFIFOW(fd, 15) = quest_db[index].num_objectives; - WFIFOSET(fd, packet_len(0x2b3)); + for( i = 0; i < quest_db[index].num_objectives; i++ ) + { + WFIFOL(fd, i*30+17) = quest_db[index].mob[i]; + WFIFOW(fd, i*30+21) = qd->count[i]; + mob = mob_db(quest_db[index].mob[i]); + memcpy(WFIFOP(fd, i*30+23), mob?mob->jname:"NULL", NAME_LENGTH); + } + + WFIFOSET(fd, packet_len(0x2b3)); } /// Notification about a quest being removed (ZC_DEL_QUEST). /// 02b4 <quest id>.L -void clif_quest_delete(struct map_session_data *sd, int quest_id) +void clif_quest_delete(struct map_session_data * sd, int quest_id) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd, packet_len(0x2b4)); - WFIFOW(fd, 0) = 0x2b4; - WFIFOL(fd, 2) = quest_id; - WFIFOSET(fd, packet_len(0x2b4)); + WFIFOHEAD(fd, packet_len(0x2b4)); + WFIFOW(fd, 0) = 0x2b4; + WFIFOL(fd, 2) = quest_id; + WFIFOSET(fd, packet_len(0x2b4)); } /// Notification of an update to the hunting mission counter (ZC_UPDATE_MISSION_HUNT). /// 02b5 <packet len>.W <mobs>.W { <quest id>.L <mob id>.L <total count>.W <current count>.W }*3 -void clif_quest_update_objective(struct map_session_data *sd, struct quest *qd, int index) -{ - int fd = sd->fd; - int i; - int len = quest_db[index].num_objectives*12+6; - - WFIFOHEAD(fd, len); - WFIFOW(fd, 0) = 0x2b5; - WFIFOW(fd, 2) = len; - WFIFOW(fd, 4) = quest_db[index].num_objectives; - - for (i = 0; i < quest_db[index].num_objectives; i++) { - WFIFOL(fd, i*12+6) = qd->quest_id; - WFIFOL(fd, i*12+10) = quest_db[index].mob[i]; - WFIFOW(fd, i*12+14) = quest_db[index].count[i]; - WFIFOW(fd, i*12+16) = qd->count[i]; - } +void clif_quest_update_objective(struct map_session_data * sd, struct quest * qd, int index) +{ + int fd = sd->fd; + int i; + int len = quest_db[index].num_objectives*12+6; + + WFIFOHEAD(fd, len); + WFIFOW(fd, 0) = 0x2b5; + WFIFOW(fd, 2) = len; + WFIFOW(fd, 4) = quest_db[index].num_objectives; + + for( i = 0; i < quest_db[index].num_objectives; i++ ) + { + WFIFOL(fd, i*12+6) = qd->quest_id; + WFIFOL(fd, i*12+10) = quest_db[index].mob[i]; + WFIFOW(fd, i*12+14) = quest_db[index].count[i]; + WFIFOW(fd, i*12+16) = qd->count[i]; + } - WFIFOSET(fd, len); + WFIFOSET(fd, len); } /// Request to change the state of a quest (CZ_ACTIVE_QUEST). /// 02b6 <quest id>.L <active>.B -void clif_parse_questStateAck(int fd, struct map_session_data *sd) +void clif_parse_questStateAck(int fd, struct map_session_data * sd) { - quest_update_status(sd, RFIFOL(fd,2), RFIFOB(fd,6)?Q_ACTIVE:Q_INACTIVE); + quest_update_status(sd, RFIFOL(fd,2), RFIFOB(fd,6)?Q_ACTIVE:Q_INACTIVE); } /// Notification about the change of a quest state (ZC_ACTIVE_QUEST). /// 02b7 <quest id>.L <active>.B -void clif_quest_update_status(struct map_session_data *sd, int quest_id, bool active) +void clif_quest_update_status(struct map_session_data * sd, int quest_id, bool active) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd, packet_len(0x2b7)); - WFIFOW(fd, 0) = 0x2b7; - WFIFOL(fd, 2) = quest_id; - WFIFOB(fd, 6) = active; - WFIFOSET(fd, packet_len(0x2b7)); + WFIFOHEAD(fd, packet_len(0x2b7)); + WFIFOW(fd, 0) = 0x2b7; + WFIFOL(fd, 2) = quest_id; + WFIFOB(fd, 6) = active; + WFIFOSET(fd, packet_len(0x2b7)); } @@ -14571,16 +14749,16 @@ void clif_quest_update_status(struct map_session_data *sd, int quest_id, bool ac void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, short state, short color) { #if PACKETVER >= 20090218 - int fd = sd->fd; - - WFIFOHEAD(fd, packet_len(0x446)); - WFIFOW(fd, 0) = 0x446; - WFIFOL(fd, 2) = bl->id; - WFIFOW(fd, 6) = bl->x; - WFIFOW(fd, 8) = bl->y; - WFIFOW(fd, 10) = state; - WFIFOW(fd, 12) = color; - WFIFOSET(fd, packet_len(0x446)); + int fd = sd->fd; + + WFIFOHEAD(fd, packet_len(0x446)); + WFIFOW(fd, 0) = 0x446; + WFIFOL(fd, 2) = bl->id; + WFIFOW(fd, 6) = bl->x; + WFIFOW(fd, 8) = bl->y; + WFIFOW(fd, 10) = state; + WFIFOW(fd, 12) = color; + WFIFOSET(fd, packet_len(0x446)); #endif } @@ -14592,64 +14770,66 @@ void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, s /// 02a2 <var id>.W <value>.L void clif_mercenary_updatestatus(struct map_session_data *sd, int type) { - struct mercenary_data *md; - struct status_data *status; - int fd; - if (sd == NULL || (md = sd->md) == NULL) - return; - - fd = sd->fd; - status = &md->battle_status; - WFIFOHEAD(fd,packet_len(0x2a2)); - WFIFOW(fd,0) = 0x2a2; - WFIFOW(fd,2) = type; - switch (type) { - case SP_ATK1: { - int atk = rnd()%(status->rhw.atk2 - status->rhw.atk + 1) + status->rhw.atk; - WFIFOL(fd,4) = cap_value(atk, 0, INT16_MAX); - } - break; - case SP_MATK1: - WFIFOL(fd,4) = cap_value(status->matk_max, 0, INT16_MAX); - break; - case SP_HIT: - WFIFOL(fd,4) = status->hit; - break; - case SP_CRITICAL: - WFIFOL(fd,4) = status->cri/10; - break; - case SP_DEF1: - WFIFOL(fd,4) = status->def; - break; - case SP_MDEF1: - WFIFOL(fd,4) = status->mdef; - break; - case SP_MERCFLEE: - WFIFOL(fd,4) = status->flee; - break; - case SP_ASPD: - WFIFOL(fd,4) = status->amotion; - break; - case SP_HP: - WFIFOL(fd,4) = status->hp; - break; - case SP_MAXHP: - WFIFOL(fd,4) = status->max_hp; - break; - case SP_SP: - WFIFOL(fd,4) = status->sp; - break; - case SP_MAXSP: - WFIFOL(fd,4) = status->max_sp; - break; - case SP_MERCKILLS: - WFIFOL(fd,4) = md->mercenary.kill_count; - break; - case SP_MERCFAITH: - WFIFOL(fd,4) = mercenary_get_faith(md); - break; - } - WFIFOSET(fd,packet_len(0x2a2)); + struct mercenary_data *md; + struct status_data *status; + int fd; + if( sd == NULL || (md = sd->md) == NULL ) + return; + + fd = sd->fd; + status = &md->battle_status; + WFIFOHEAD(fd,packet_len(0x2a2)); + WFIFOW(fd,0) = 0x2a2; + WFIFOW(fd,2) = type; + switch( type ) + { + case SP_ATK1: + { + int atk = rnd()%(status->rhw.atk2 - status->rhw.atk + 1) + status->rhw.atk; + WFIFOL(fd,4) = cap_value(atk, 0, INT16_MAX); + } + break; + case SP_MATK1: + WFIFOL(fd,4) = cap_value(status->matk_max, 0, INT16_MAX); + break; + case SP_HIT: + WFIFOL(fd,4) = status->hit; + break; + case SP_CRITICAL: + WFIFOL(fd,4) = status->cri/10; + break; + case SP_DEF1: + WFIFOL(fd,4) = status->def; + break; + case SP_MDEF1: + WFIFOL(fd,4) = status->mdef; + break; + case SP_MERCFLEE: + WFIFOL(fd,4) = status->flee; + break; + case SP_ASPD: + WFIFOL(fd,4) = status->amotion; + break; + case SP_HP: + WFIFOL(fd,4) = status->hp; + break; + case SP_MAXHP: + WFIFOL(fd,4) = status->max_hp; + break; + case SP_SP: + WFIFOL(fd,4) = status->sp; + break; + case SP_MAXSP: + WFIFOL(fd,4) = status->max_sp; + break; + case SP_MERCKILLS: + WFIFOL(fd,4) = md->mercenary.kill_count; + break; + case SP_MERCFAITH: + WFIFOL(fd,4) = mercenary_get_faith(md); + break; + } + WFIFOSET(fd,packet_len(0x2a2)); } @@ -14659,43 +14839,43 @@ void clif_mercenary_updatestatus(struct map_session_data *sd, int type) /// <calls>.L <kills>.L <atk range>.W void clif_mercenary_info(struct map_session_data *sd) { - int fd; - struct mercenary_data *md; - struct status_data *status; - int atk; - - if (sd == NULL || (md = sd->md) == NULL) - return; - - fd = sd->fd; - status = &md->battle_status; - - WFIFOHEAD(fd,packet_len(0x29b)); - WFIFOW(fd,0) = 0x29b; - WFIFOL(fd,2) = md->bl.id; - - // Mercenary shows ATK as a random value between ATK ~ ATK2 - atk = rnd()%(status->rhw.atk2 - status->rhw.atk + 1) + status->rhw.atk; - WFIFOW(fd,6) = cap_value(atk, 0, INT16_MAX); - WFIFOW(fd,8) = cap_value(status->matk_max, 0, INT16_MAX); - WFIFOW(fd,10) = status->hit; - WFIFOW(fd,12) = status->cri/10; - WFIFOW(fd,14) = status->def; - WFIFOW(fd,16) = status->mdef; - WFIFOW(fd,18) = status->flee; - WFIFOW(fd,20) = status->amotion; - safestrncpy((char *)WFIFOP(fd,22), md->db->name, NAME_LENGTH); - WFIFOW(fd,46) = md->db->lv; - WFIFOL(fd,48) = status->hp; - WFIFOL(fd,52) = status->max_hp; - WFIFOL(fd,56) = status->sp; - WFIFOL(fd,60) = status->max_sp; - WFIFOL(fd,64) = (int)time(NULL) + (mercenary_get_lifetime(md) / 1000); - WFIFOW(fd,68) = mercenary_get_faith(md); - WFIFOL(fd,70) = mercenary_get_calls(md); - WFIFOL(fd,74) = md->mercenary.kill_count; - WFIFOW(fd,78) = md->battle_status.rhw.range; - WFIFOSET(fd,packet_len(0x29b)); + int fd; + struct mercenary_data *md; + struct status_data *status; + int atk; + + if( sd == NULL || (md = sd->md) == NULL ) + return; + + fd = sd->fd; + status = &md->battle_status; + + WFIFOHEAD(fd,packet_len(0x29b)); + WFIFOW(fd,0) = 0x29b; + WFIFOL(fd,2) = md->bl.id; + + // Mercenary shows ATK as a random value between ATK ~ ATK2 + atk = rnd()%(status->rhw.atk2 - status->rhw.atk + 1) + status->rhw.atk; + WFIFOW(fd,6) = cap_value(atk, 0, INT16_MAX); + WFIFOW(fd,8) = cap_value(status->matk_max, 0, INT16_MAX); + WFIFOW(fd,10) = status->hit; + WFIFOW(fd,12) = status->cri/10; + WFIFOW(fd,14) = status->def; + WFIFOW(fd,16) = status->mdef; + WFIFOW(fd,18) = status->flee; + WFIFOW(fd,20) = status->amotion; + safestrncpy((char*)WFIFOP(fd,22), md->db->name, NAME_LENGTH); + WFIFOW(fd,46) = md->db->lv; + WFIFOL(fd,48) = status->hp; + WFIFOL(fd,52) = status->max_hp; + WFIFOL(fd,56) = status->sp; + WFIFOL(fd,60) = status->max_sp; + WFIFOL(fd,64) = (int)time(NULL) + (mercenary_get_lifetime(md) / 1000); + WFIFOW(fd,68) = mercenary_get_faith(md); + WFIFOL(fd,70) = mercenary_get_calls(md); + WFIFOL(fd,74) = md->mercenary.kill_count; + WFIFOW(fd,78) = md->battle_status.rhw.range; + WFIFOSET(fd,packet_len(0x29b)); } @@ -14703,31 +14883,32 @@ void clif_mercenary_info(struct map_session_data *sd) /// 029d <packet len>.W { <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.B }* void clif_mercenary_skillblock(struct map_session_data *sd) { - struct mercenary_data *md; - int fd, i, len = 4, id, j; - - if (sd == NULL || (md = sd->md) == NULL) - return; - - fd = sd->fd; - WFIFOHEAD(fd,4+37*MAX_MERCSKILL); - WFIFOW(fd,0) = 0x29d; - for (i = 0; i < MAX_MERCSKILL; i++) { - if ((id = md->db->skill[i].id) == 0) - continue; - j = id - MC_SKILLBASE; - WFIFOW(fd,len) = id; - WFIFOL(fd,len+2) = skill_get_inf(id); - WFIFOW(fd,len+6) = md->db->skill[j].lv; - WFIFOW(fd,len+8) = skill_get_sp(id, md->db->skill[j].lv); - WFIFOW(fd,len+10) = skill_get_range2(&md->bl, id, md->db->skill[j].lv); - safestrncpy((char *)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); - WFIFOB(fd,len+36) = 0; // Skillable for Mercenary? - len += 37; - } + struct mercenary_data *md; + int fd, i, len = 4, id, j; - WFIFOW(fd,2) = len; - WFIFOSET(fd,len); + if( sd == NULL || (md = sd->md) == NULL ) + return; + + fd = sd->fd; + WFIFOHEAD(fd,4+37*MAX_MERCSKILL); + WFIFOW(fd,0) = 0x29d; + for( i = 0; i < MAX_MERCSKILL; i++ ) + { + if( (id = md->db->skill[i].id) == 0 ) + continue; + j = id - MC_SKILLBASE; + WFIFOW(fd,len) = id; + WFIFOL(fd,len+2) = skill_get_inf(id); + WFIFOW(fd,len+6) = md->db->skill[j].lv; + WFIFOW(fd,len+8) = skill_get_sp(id, md->db->skill[j].lv); + WFIFOW(fd,len+10) = skill_get_range2(&md->bl, id, md->db->skill[j].lv); + safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); + WFIFOB(fd,len+36) = 0; // Skillable for Mercenary? + len += 37; + } + + WFIFOW(fd,2) = len; + WFIFOSET(fd,len); } @@ -14735,13 +14916,13 @@ void clif_mercenary_skillblock(struct map_session_data *sd) /// 029f <command>.B /// 1 = mercenary information /// 2 = delete -void clif_parse_mercenary_action(int fd, struct map_session_data *sd) +void clif_parse_mercenary_action(int fd, struct map_session_data* sd) { - int option = RFIFOB(fd,2); - if (sd->md == NULL) - return; + int option = RFIFOB(fd,2); + if( sd->md == NULL ) + return; - if (option == 2) merc_delete(sd->md, 2); + if( option == 2 ) merc_delete(sd->md, 2); } @@ -14751,35 +14932,33 @@ void clif_parse_mercenary_action(int fd, struct map_session_data *sd) /// 1 = Your mercenary soldier has been killed. /// 2 = Your mercenary soldier has been fired. /// 3 = Your mercenary soldier has ran away. -void clif_mercenary_message(struct map_session_data *sd, int message) +void clif_mercenary_message(struct map_session_data* sd, int message) { - clif_msg(sd, 1266 + message); + clif_msg(sd, 1266 + message); } /// Notification about the remaining time of a rental item (ZC_CASH_TIME_COUNTER). /// 0298 <name id>.W <seconds>.L void clif_rental_time(int fd, int nameid, int seconds) -{ - // '<ItemName>' item will disappear in <seconds/60> minutes. - WFIFOHEAD(fd,packet_len(0x298)); - WFIFOW(fd,0) = 0x298; - WFIFOW(fd,2) = nameid; - WFIFOL(fd,4) = seconds; - WFIFOSET(fd,packet_len(0x298)); +{ // '<ItemName>' item will disappear in <seconds/60> minutes. + WFIFOHEAD(fd,packet_len(0x298)); + WFIFOW(fd,0) = 0x298; + WFIFOW(fd,2) = nameid; + WFIFOL(fd,4) = seconds; + WFIFOSET(fd,packet_len(0x298)); } /// Deletes a rental item from client's inventory (ZC_CASH_ITEM_DELETE). /// 0299 <index>.W <name id>.W void clif_rental_expired(int fd, int index, int nameid) -{ - // '<ItemName>' item has been deleted from the Inventory - WFIFOHEAD(fd,packet_len(0x299)); - WFIFOW(fd,0) = 0x299; - WFIFOW(fd,2) = index+2; - WFIFOW(fd,4) = nameid; - WFIFOSET(fd,packet_len(0x299)); +{ // '<ItemName>' item has been deleted from the Inventory + WFIFOHEAD(fd,packet_len(0x299)); + WFIFOW(fd,0) = 0x299; + WFIFOW(fd,2) = index+2; + WFIFOW(fd,4) = nameid; + WFIFOSET(fd,packet_len(0x299)); } @@ -14787,11 +14966,11 @@ void clif_rental_expired(int fd, int index, int nameid) /// 0294 <book id>.L <page>.L void clif_readbook(int fd, int book_id, int page) { - WFIFOHEAD(fd,packet_len(0x294)); - WFIFOW(fd,0) = 0x294; - WFIFOL(fd,2) = book_id; - WFIFOL(fd,6) = page; - WFIFOSET(fd,packet_len(0x294)); + WFIFOHEAD(fd,packet_len(0x294)); + WFIFOW(fd,0) = 0x294; + WFIFOL(fd,2) = book_id; + WFIFOL(fd,6) = page; + WFIFOSET(fd,packet_len(0x294)); } @@ -14802,24 +14981,26 @@ void clif_readbook(int fd, int book_id, int page) /// 02e0 <account id>.L <name>.24B <hp>.W <max hp>.W void clif_bg_hp(struct map_session_data *sd) { - unsigned char buf[34]; - const int cmd = 0x2e0; - nullpo_retv(sd); + unsigned char buf[34]; + const int cmd = 0x2e0; + nullpo_retv(sd); - WBUFW(buf,0) = cmd; - WBUFL(buf,2) = sd->status.account_id; - memcpy(WBUFP(buf,6), sd->status.name, NAME_LENGTH); - - if (sd->battle_status.max_hp > INT16_MAX) { - // To correctly display the %hp bar. [Skotlex] - WBUFW(buf,30) = sd->battle_status.hp/(sd->battle_status.max_hp/100); - WBUFW(buf,32) = 100; - } else { - WBUFW(buf,30) = sd->battle_status.hp; - WBUFW(buf,32) = sd->battle_status.max_hp; - } + WBUFW(buf,0) = cmd; + WBUFL(buf,2) = sd->status.account_id; + memcpy(WBUFP(buf,6), sd->status.name, NAME_LENGTH); - clif_send(buf, packet_len(cmd), &sd->bl, BG_AREA_WOS); + if( sd->battle_status.max_hp > INT16_MAX ) + { // To correctly display the %hp bar. [Skotlex] + WBUFW(buf,30) = sd->battle_status.hp/(sd->battle_status.max_hp/100); + WBUFW(buf,32) = 100; + } + else + { + WBUFW(buf,30) = sd->battle_status.hp; + WBUFW(buf,32) = sd->battle_status.max_hp; + } + + clif_send(buf, packet_len(cmd), &sd->bl, BG_AREA_WOS); } @@ -14827,32 +15008,32 @@ void clif_bg_hp(struct map_session_data *sd) /// 02df <account id>.L <name>.24B <class>.W <x>.W <y>.W void clif_bg_xy(struct map_session_data *sd) { - unsigned char buf[36]; - nullpo_retv(sd); + unsigned char buf[36]; + nullpo_retv(sd); - WBUFW(buf,0)=0x2df; - WBUFL(buf,2)=sd->status.account_id; - memcpy(WBUFP(buf,6), sd->status.name, NAME_LENGTH); - WBUFW(buf,30)=sd->status.class_; - WBUFW(buf,32)=sd->bl.x; - WBUFW(buf,34)=sd->bl.y; + WBUFW(buf,0)=0x2df; + WBUFL(buf,2)=sd->status.account_id; + memcpy(WBUFP(buf,6), sd->status.name, NAME_LENGTH); + WBUFW(buf,30)=sd->status.class_; + WBUFW(buf,32)=sd->bl.x; + WBUFW(buf,34)=sd->bl.y; - clif_send(buf, packet_len(0x2df), &sd->bl, BG_SAMEMAP_WOS); + clif_send(buf, packet_len(0x2df), &sd->bl, BG_SAMEMAP_WOS); } void clif_bg_xy_remove(struct map_session_data *sd) { - unsigned char buf[36]; - nullpo_retv(sd); + unsigned char buf[36]; + nullpo_retv(sd); - WBUFW(buf,0)=0x2df; - WBUFL(buf,2)=sd->status.account_id; - memset(WBUFP(buf,6), 0, NAME_LENGTH); - WBUFW(buf,30)=0; - WBUFW(buf,32)=-1; - WBUFW(buf,34)=-1; + WBUFW(buf,0)=0x2df; + WBUFL(buf,2)=sd->status.account_id; + memset(WBUFP(buf,6), 0, NAME_LENGTH); + WBUFW(buf,30)=0; + WBUFW(buf,32)=-1; + WBUFW(buf,34)=-1; - clif_send(buf, packet_len(0x2df), &sd->bl, BG_SAMEMAP_WOS); + clif_send(buf, packet_len(0x2df), &sd->bl, BG_SAMEMAP_WOS); } @@ -14860,51 +15041,52 @@ void clif_bg_xy_remove(struct map_session_data *sd) /// 02dc <packet len>.W <account id>.L <name>.24B <message>.?B void clif_bg_message(struct battleground_data *bg, int src_id, const char *name, const char *mes, int len) { - struct map_session_data *sd; - unsigned char *buf; - if ((sd = bg_getavailablesd(bg)) == NULL) - return; + struct map_session_data *sd; + unsigned char *buf; + if( (sd = bg_getavailablesd(bg)) == NULL ) + return; - buf = (unsigned char *)aMalloc((len + NAME_LENGTH + 8)*sizeof(unsigned char)); + buf = (unsigned char*)aMalloc((len + NAME_LENGTH + 8)*sizeof(unsigned char)); - WBUFW(buf,0) = 0x2dc; - WBUFW(buf,2) = len + NAME_LENGTH + 8; - WBUFL(buf,4) = src_id; - memcpy(WBUFP(buf,8), name, NAME_LENGTH); - memcpy(WBUFP(buf,32), mes, len); - clif_send(buf,WBUFW(buf,2), &sd->bl, BG); + WBUFW(buf,0) = 0x2dc; + WBUFW(buf,2) = len + NAME_LENGTH + 8; + WBUFL(buf,4) = src_id; + memcpy(WBUFP(buf,8), name, NAME_LENGTH); + memcpy(WBUFP(buf,32), mes, len); + clif_send(buf,WBUFW(buf,2), &sd->bl, BG); - if (buf) - aFree(buf); + if( buf ) + aFree(buf); } /// Validates and processes battlechat messages [pakpil] (CZ_BATTLEFIELD_CHAT). /// 0x2db <packet len>.W <text>.?B (<name> : <message>) 00 -void clif_parse_BattleChat(int fd, struct map_session_data *sd) +void clif_parse_BattleChat(int fd, struct map_session_data* sd) { - const char *text = (char *)RFIFOP(fd,4); - int textlen = RFIFOW(fd,2) - 4; + const char* text = (char*)RFIFOP(fd,4); + int textlen = RFIFOW(fd,2) - 4; - char *name, *message; - int namelen, messagelen; + char *name, *message; + int namelen, messagelen; - if (!clif_process_message(sd, 0, &name, &namelen, &message, &messagelen)) - return; + if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) ) + return; - if (is_atcommand(fd, sd, message, 1)) - return; + if( is_atcommand(fd, sd, message, 1) ) + return; - if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) - return; + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + return; - if (battle_config.min_chat_delay) { - if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) - return; - sd->cantalk_tick = gettick() + battle_config.min_chat_delay; - } + if( battle_config.min_chat_delay ) + { + if( DIFF_TICK(sd->cantalk_tick, gettick()) > 0 ) + return; + sd->cantalk_tick = gettick() + battle_config.min_chat_delay; + } - bg_send_message(sd, text, textlen); + bg_send_message(sd, text, textlen); } @@ -14912,30 +15094,30 @@ void clif_parse_BattleChat(int fd, struct map_session_data *sd) /// 02de <camp A points>.W <camp B points>.W void clif_bg_updatescore(int m) { - struct block_list bl; - unsigned char buf[6]; + struct block_list bl; + unsigned char buf[6]; - bl.id = 0; - bl.type = BL_NUL; - bl.m = m; + bl.id = 0; + bl.type = BL_NUL; + bl.m = m; - WBUFW(buf,0) = 0x2de; - WBUFW(buf,2) = map[m].bgscore_lion; - WBUFW(buf,4) = map[m].bgscore_eagle; - clif_send(buf,packet_len(0x2de),&bl,ALL_SAMEMAP); + WBUFW(buf,0) = 0x2de; + WBUFW(buf,2) = map[m].bgscore_lion; + WBUFW(buf,4) = map[m].bgscore_eagle; + clif_send(buf,packet_len(0x2de),&bl,ALL_SAMEMAP); } void clif_bg_updatescore_single(struct map_session_data *sd) { - int fd; - nullpo_retv(sd); - fd = sd->fd; + int fd; + nullpo_retv(sd); + fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x2de)); - WFIFOW(fd,0) = 0x2de; - WFIFOW(fd,2) = map[sd->bl.m].bgscore_lion; - WFIFOW(fd,4) = map[sd->bl.m].bgscore_eagle; - WFIFOSET(fd,packet_len(0x2de)); + WFIFOHEAD(fd,packet_len(0x2de)); + WFIFOW(fd,0) = 0x2de; + WFIFOW(fd,2) = map[sd->bl.m].bgscore_lion; + WFIFOW(fd,4) = map[sd->bl.m].bgscore_eagle; + WFIFOSET(fd,packet_len(0x2de)); } @@ -14943,25 +15125,25 @@ void clif_bg_updatescore_single(struct map_session_data *sd) /// 02dd <account id>.L <name>.24B <camp>.W void clif_sendbgemblem_area(struct map_session_data *sd) { - unsigned char buf[33]; - nullpo_retv(sd); + unsigned char buf[33]; + nullpo_retv(sd); - WBUFW(buf, 0) = 0x2dd; - WBUFL(buf,2) = sd->bl.id; - safestrncpy((char *)WBUFP(buf,6), sd->status.name, NAME_LENGTH); // name don't show in screen. - WBUFW(buf,30) = sd->bg_id; - clif_send(buf,packet_len(0x2dd), &sd->bl, AREA); + WBUFW(buf, 0) = 0x2dd; + WBUFL(buf,2) = sd->bl.id; + safestrncpy((char*)WBUFP(buf,6), sd->status.name, NAME_LENGTH); // name don't show in screen. + WBUFW(buf,30) = sd->bg_id; + clif_send(buf,packet_len(0x2dd), &sd->bl, AREA); } void clif_sendbgemblem_single(int fd, struct map_session_data *sd) { - nullpo_retv(sd); - WFIFOHEAD(fd,32); - WFIFOW(fd,0) = 0x2dd; - WFIFOL(fd,2) = sd->bl.id; - safestrncpy((char *)WFIFOP(fd,6), sd->status.name, NAME_LENGTH); - WFIFOW(fd,30) = sd->bg_id; - WFIFOSET(fd,packet_len(0x2dd)); + nullpo_retv(sd); + WFIFOHEAD(fd,32); + WFIFOW(fd,0) = 0x2dd; + WFIFOL(fd,2) = sd->bl.id; + safestrncpy((char*)WFIFOP(fd,6), sd->status.name, NAME_LENGTH); + WFIFOW(fd,30) = sd->bg_id; + WFIFOSET(fd,packet_len(0x2dd)); } @@ -14970,12 +15152,12 @@ void clif_sendbgemblem_single(int fd, struct map_session_data *sd) void clif_font(struct map_session_data *sd) { #if PACKETVER >= 20080102 - unsigned char buf[8]; - nullpo_retv(sd); - WBUFW(buf,0) = 0x2ef; - WBUFL(buf,2) = sd->bl.id; - WBUFW(buf,6) = sd->user_font; - clif_send(buf, packet_len(0x2ef), &sd->bl, AREA); + unsigned char buf[8]; + nullpo_retv(sd); + WBUFW(buf,0) = 0x2ef; + WBUFL(buf,2) = sd->bl.id; + WBUFW(buf,6) = sd->user_font; + clif_send(buf, packet_len(0x2ef), &sd->bl, AREA); #endif } @@ -14985,112 +15167,121 @@ void clif_font(struct map_session_data *sd) *------------------------------------------*/ int clif_instance(int instance_id, int type, int flag) { - struct map_session_data *sd; - struct party_data *p; - unsigned char buf[255]; - - if ((p = party_search(instance[instance_id].party_id)) == NULL || (sd = party_getavailablesd(p)) == NULL) - return 0; - - switch (type) { - case 1: - // S 0x2cb <Instance name>.61B <Standby Position>.W - // Required to start the instancing information window on Client - // This window re-appear each "refresh" of client automatically until type 4 is send to client. - WBUFW(buf,0) = 0x02CB; - memcpy(WBUFP(buf,2),instance[instance_id].name,INSTANCE_NAME_LENGTH); - WBUFW(buf,63) = flag; - clif_send(buf,packet_len(0x02CB),&sd->bl,PARTY); - break; - case 2: - // S 0x2cc <Standby Position>.W - // To announce Instancing queue creation if no maps available - WBUFW(buf,0) = 0x02CC; - WBUFW(buf,2) = flag; - clif_send(buf,packet_len(0x02CC),&sd->bl,PARTY); - break; - case 3: - case 4: - // S 0x2cd <Instance Name>.61B <Instance Remaining Time>.L <Instance Noplayers close time>.L - WBUFW(buf,0) = 0x02CD; - memcpy(WBUFP(buf,2),instance[instance_id].name,61); - if (type == 3) { - WBUFL(buf,63) = (uint32)instance[instance_id].progress_timeout; - WBUFL(buf,67) = 0; - } else { - WBUFL(buf,63) = 0; - WBUFL(buf,67) = (uint32)instance[instance_id].idle_timeout; - } - clif_send(buf,packet_len(0x02CD),&sd->bl,PARTY); - break; - case 5: - // S 0x2ce <Message ID>.L - // 0 = Notification (EnterLimitDate update?) - // 1 = The Memorial Dungeon expired; it has been destroyed - // 2 = The Memorial Dungeon's entry time limit expired; it has been destroyed - // 3 = The Memorial Dungeon has been removed. - // 4 = Create failure (removes the instance window) - WBUFW(buf,0) = 0x02CE; - WBUFL(buf,2) = flag; - //WBUFL(buf,6) = EnterLimitDate; - clif_send(buf,packet_len(0x02CE),&sd->bl,PARTY); - break; - } - return 0; + struct map_session_data *sd; + struct party_data *p; + unsigned char buf[255]; + + if( (p = party_search(instance[instance_id].party_id)) == NULL || (sd = party_getavailablesd(p)) == NULL ) + return 0; + + switch( type ) + { + case 1: + // S 0x2cb <Instance name>.61B <Standby Position>.W + // Required to start the instancing information window on Client + // This window re-appear each "refresh" of client automatically until type 4 is send to client. + WBUFW(buf,0) = 0x02CB; + memcpy(WBUFP(buf,2),instance[instance_id].name,INSTANCE_NAME_LENGTH); + WBUFW(buf,63) = flag; + clif_send(buf,packet_len(0x02CB),&sd->bl,PARTY); + break; + case 2: + // S 0x2cc <Standby Position>.W + // To announce Instancing queue creation if no maps available + WBUFW(buf,0) = 0x02CC; + WBUFW(buf,2) = flag; + clif_send(buf,packet_len(0x02CC),&sd->bl,PARTY); + break; + case 3: + case 4: + // S 0x2cd <Instance Name>.61B <Instance Remaining Time>.L <Instance Noplayers close time>.L + WBUFW(buf,0) = 0x02CD; + memcpy(WBUFP(buf,2),instance[instance_id].name,61); + if( type == 3 ) + { + WBUFL(buf,63) = (uint32)instance[instance_id].progress_timeout; + WBUFL(buf,67) = 0; + } + else + { + WBUFL(buf,63) = 0; + WBUFL(buf,67) = (uint32)instance[instance_id].idle_timeout; + } + clif_send(buf,packet_len(0x02CD),&sd->bl,PARTY); + break; + case 5: + // S 0x2ce <Message ID>.L + // 0 = Notification (EnterLimitDate update?) + // 1 = The Memorial Dungeon expired; it has been destroyed + // 2 = The Memorial Dungeon's entry time limit expired; it has been destroyed + // 3 = The Memorial Dungeon has been removed. + // 4 = Create failure (removes the instance window) + WBUFW(buf,0) = 0x02CE; + WBUFL(buf,2) = flag; + //WBUFL(buf,6) = EnterLimitDate; + clif_send(buf,packet_len(0x02CE),&sd->bl,PARTY); + break; + } + return 0; } void clif_instance_join(int fd, int instance_id) { - if (instance[instance_id].idle_timer != INVALID_TIMER) { - WFIFOHEAD(fd,packet_len(0x02CD)); - WFIFOW(fd,0) = 0x02CD; - memcpy(WFIFOP(fd,2),instance[instance_id].name,61); - WFIFOL(fd,63) = 0; - WFIFOL(fd,67) = (uint32)instance[instance_id].idle_timeout; - WFIFOSET(fd,packet_len(0x02CD)); - } else if (instance[instance_id].progress_timer != INVALID_TIMER) { - WFIFOHEAD(fd,packet_len(0x02CD)); - WFIFOW(fd,0) = 0x02CD; - memcpy(WFIFOP(fd,2),instance[instance_id].name,61); - WFIFOL(fd,63) = (uint32)instance[instance_id].progress_timeout;; - WFIFOL(fd,67) = 0; - WFIFOSET(fd,packet_len(0x02CD)); - } else { - WFIFOHEAD(fd,packet_len(0x02CB)); - WFIFOW(fd,0) = 0x02CB; - memcpy(WFIFOP(fd,2),instance[instance_id].name,61); - WFIFOW(fd,63) = 0; - WFIFOSET(fd,packet_len(0x02CB)); - } + if( instance[instance_id].idle_timer != INVALID_TIMER ) + { + WFIFOHEAD(fd,packet_len(0x02CD)); + WFIFOW(fd,0) = 0x02CD; + memcpy(WFIFOP(fd,2),instance[instance_id].name,61); + WFIFOL(fd,63) = 0; + WFIFOL(fd,67) = (uint32)instance[instance_id].idle_timeout; + WFIFOSET(fd,packet_len(0x02CD)); + } + else if( instance[instance_id].progress_timer != INVALID_TIMER ) + { + WFIFOHEAD(fd,packet_len(0x02CD)); + WFIFOW(fd,0) = 0x02CD; + memcpy(WFIFOP(fd,2),instance[instance_id].name,61); + WFIFOL(fd,63) = (uint32)instance[instance_id].progress_timeout;; + WFIFOL(fd,67) = 0; + WFIFOSET(fd,packet_len(0x02CD)); + } + else + { + WFIFOHEAD(fd,packet_len(0x02CB)); + WFIFOW(fd,0) = 0x02CB; + memcpy(WFIFOP(fd,2),instance[instance_id].name,61); + WFIFOW(fd,63) = 0; + WFIFOSET(fd,packet_len(0x02CB)); + } } void clif_instance_leave(int fd) { - WFIFOHEAD(fd,packet_len(0x02CE)); - WFIFOW(fd,0) = 0x02ce; - WFIFOL(fd,2) = 4; - WFIFOSET(fd,packet_len(0x02CE)); + WFIFOHEAD(fd,packet_len(0x02CE)); + WFIFOW(fd,0) = 0x02ce; + WFIFOL(fd,2) = 4; + WFIFOSET(fd,packet_len(0x02CE)); } /// Notifies clients about item picked up by a party member (ZC_ITEM_PICKUP_PARTY). /// 02b8 <account id>.L <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B -void clif_party_show_picker(struct map_session_data *sd, struct item *item_data) +void clif_party_show_picker(struct map_session_data * sd, struct item * item_data) { #if PACKETVER >= 20071002 - unsigned char buf[22]; - struct item_data *id = itemdb_search(item_data->nameid); - - WBUFW(buf,0) = 0x2b8; - WBUFL(buf,2) = sd->status.account_id; - WBUFW(buf,6) = item_data->nameid; - WBUFB(buf,8) = item_data->identify; - WBUFB(buf,9) = item_data->attribute; - WBUFB(buf,10) = item_data->refine; - clif_addcards(WBUFP(buf,11), item_data); - WBUFW(buf,19) = id->equip; // equip location - WBUFB(buf,21) = itemtype(id->type); // item type - clif_send(buf, packet_len(0x2b8), &sd->bl, PARTY_SAMEMAP_WOS); + unsigned char buf[22]; + struct item_data* id = itemdb_search(item_data->nameid); + + WBUFW(buf,0) = 0x2b8; + WBUFL(buf,2) = sd->status.account_id; + WBUFW(buf,6) = item_data->nameid; + WBUFB(buf,8) = item_data->identify; + WBUFB(buf,9) = item_data->attribute; + WBUFB(buf,10) = item_data->refine; + clif_addcards(WBUFP(buf,11), item_data); + WBUFW(buf,19) = id->equip; // equip location + WBUFB(buf,21) = itemtype(id->type); // item type + clif_send(buf, packet_len(0x2b8), &sd->bl, PARTY_SAMEMAP_WOS); #endif } @@ -15104,19 +15295,19 @@ void clif_party_show_picker(struct map_session_data *sd, struct item *item_data) /// 1 = quest exp gain/loss void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool quest) { - int fd; + int fd; - nullpo_retv(sd); + nullpo_retv(sd); - fd = sd->fd; + fd = sd->fd; - WFIFOHEAD(fd, packet_len(0x7f6)); - WFIFOW(fd,0) = 0x7f6; - WFIFOL(fd,2) = sd->bl.id; - WFIFOL(fd,6) = exp; - WFIFOW(fd,10) = type; - WFIFOW(fd,12) = quest?1:0;// Normal exp is shown in yellow, quest exp is shown in purple. - WFIFOSET(fd,packet_len(0x7f6)); + WFIFOHEAD(fd, packet_len(0x7f6)); + WFIFOW(fd,0) = 0x7f6; + WFIFOL(fd,2) = sd->bl.id; + WFIFOL(fd,6) = exp; + WFIFOW(fd,10) = type; + WFIFOW(fd,12) = quest?1:0;// Normal exp is shown in yellow, quest exp is shown in purple. + WFIFOSET(fd,packet_len(0x7f6)); } @@ -15128,13 +15319,13 @@ void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, b /// 3 = Decremental counter (1 tick/second), 'value' specifies start value (stops when reaching 0, displays at most 2 digits). /// value: /// Except for type 3 it is interpreted as seconds for displaying as DD:HH:MM:SS, HH:MM:SS, MM:SS or SS (leftmost '00' is not displayed). -void clif_showdigit(struct map_session_data *sd, unsigned char type, int value) +void clif_showdigit(struct map_session_data* sd, unsigned char type, int value) { - WFIFOHEAD(sd->fd, packet_len(0x1b1)); - WFIFOW(sd->fd,0) = 0x1b1; - WFIFOB(sd->fd,2) = type; - WFIFOL(sd->fd,3) = value; - WFIFOSET(sd->fd, packet_len(0x1b1)); + WFIFOHEAD(sd->fd, packet_len(0x1b1)); + WFIFOW(sd->fd,0) = 0x1b1; + WFIFOB(sd->fd,2) = type; + WFIFOL(sd->fd,3) = value; + WFIFOSET(sd->fd, packet_len(0x1b1)); } @@ -15150,102 +15341,99 @@ void clif_showdigit(struct map_session_data *sd, unsigned char type, int value) /// constructed, this state tracking was rendered useless, /// as the only skill unit, that is sent with 0x1c9 is /// Graffiti. -void clif_parse_LessEffect(int fd, struct map_session_data *sd) +void clif_parse_LessEffect(int fd, struct map_session_data* sd) { - int isLess = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + int isLess = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - sd->state.lesseffect = (isLess != 0); + sd->state.lesseffect = ( isLess != 0 ); } /// S 07e4 <length>.w <option>.l <val>.l {<index>.w <amount>.w).4b* -void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd) -{ - int n = (RFIFOW(fd,2)-12) / 4; - int type = RFIFOL(fd,4); - int flag = RFIFOL(fd,8); // Button clicked: 0 = Cancel, 1 = OK - unsigned short *item_list = (unsigned short *)RFIFOP(fd,12); - - if (sd->state.trading || sd->npc_shopid) - return; - - if (flag == 0 || n == 0) { - clif_menuskill_clear(sd); - return; // Canceled by player. - } - - if (sd->menuskill_id != SO_EL_ANALYSIS && sd->menuskill_id != GN_CHANGEMATERIAL) { - clif_menuskill_clear(sd); - return; // Prevent hacking. - } - - switch (type) { - case 0: // Change Material - skill_changematerial(sd,n,item_list); - break; - case 1: // Level 1: Pure to Rough - case 2: // Level 2: Rough to Pure - skill_elementalanalysis(sd,n,type,item_list); - break; - } - clif_menuskill_clear(sd); - - return; +void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) { + int n = (RFIFOW(fd,2)-12) / 4; + int type = RFIFOL(fd,4); + int flag = RFIFOL(fd,8); // Button clicked: 0 = Cancel, 1 = OK + unsigned short* item_list = (unsigned short*)RFIFOP(fd,12); + + if( sd->state.trading || sd->npc_shopid ) + return; + + if( flag == 0 || n == 0) { + clif_menuskill_clear(sd); + return; // Canceled by player. + } + + if( sd->menuskill_id != SO_EL_ANALYSIS && sd->menuskill_id != GN_CHANGEMATERIAL ) { + clif_menuskill_clear(sd); + return; // Prevent hacking. + } + + switch( type ) { + case 0: // Change Material + skill_changematerial(sd,n,item_list); + break; + case 1: // Level 1: Pure to Rough + case 2: // Level 2: Rough to Pure + skill_elementalanalysis(sd,n,type,item_list); + break; + } + clif_menuskill_clear(sd); + + return; } /*========================================== * Elemental System *==========================================*/ -void clif_elemental_updatestatus(struct map_session_data *sd, int type) -{ - struct elemental_data *ed; - struct status_data *status; - int fd; - - if (sd == NULL || (ed = sd->ed) == NULL) - return; - - fd = sd->fd; - status = &ed->battle_status; - WFIFOHEAD(fd,8); - WFIFOW(fd,0) = 0x81e; - WFIFOW(fd,2) = type; - switch (type) { - case SP_HP: - WFIFOL(fd,4) = status->hp; - break; - case SP_MAXHP: - WFIFOL(fd,4) = status->max_hp; - break; - case SP_SP: - WFIFOL(fd,4) = status->sp; - break; - case SP_MAXSP: - WFIFOL(fd,4) = status->max_sp; - break; - } - WFIFOSET(fd,8); -} - -void clif_elemental_info(struct map_session_data *sd) -{ - int fd; - struct elemental_data *ed; - struct status_data *status; - - if (sd == NULL || (ed = sd->ed) == NULL) - return; - - fd = sd->fd; - status = &ed->battle_status; - - WFIFOHEAD(fd,22); - WFIFOW(fd, 0) = 0x81d; - WFIFOL(fd, 2) = ed->bl.id; - WFIFOL(fd, 6) = status->hp; - WFIFOL(fd,10) = status->max_hp; - WFIFOL(fd,14) = status->sp; - WFIFOL(fd,18) = status->max_sp; - WFIFOSET(fd,22); +void clif_elemental_updatestatus(struct map_session_data *sd, int type) { + struct elemental_data *ed; + struct status_data *status; + int fd; + + if( sd == NULL || (ed = sd->ed) == NULL ) + return; + + fd = sd->fd; + status = &ed->battle_status; + WFIFOHEAD(fd,8); + WFIFOW(fd,0) = 0x81e; + WFIFOW(fd,2) = type; + switch( type ) { + case SP_HP: + WFIFOL(fd,4) = status->hp; + break; + case SP_MAXHP: + WFIFOL(fd,4) = status->max_hp; + break; + case SP_SP: + WFIFOL(fd,4) = status->sp; + break; + case SP_MAXSP: + WFIFOL(fd,4) = status->max_sp; + break; + } + WFIFOSET(fd,8); +} + +void clif_elemental_info(struct map_session_data *sd) { + int fd; + struct elemental_data *ed; + struct status_data *status; + + if( sd == NULL || (ed = sd->ed) == NULL ) + return; + + fd = sd->fd; + status = &ed->battle_status; + + WFIFOHEAD(fd,22); + WFIFOW(fd, 0) = 0x81d; + WFIFOL(fd, 2) = ed->bl.id; + WFIFOL(fd, 6) = status->hp; + WFIFOL(fd,10) = status->max_hp; + WFIFOL(fd,14) = status->sp; + WFIFOL(fd,18) = status->max_sp; + WFIFOSET(fd,22); } @@ -15254,14 +15442,14 @@ void clif_elemental_info(struct map_session_data *sd) /// Opens preparation window for buying store (ZC_OPEN_BUYING_STORE). /// 0810 <slots>.B -void clif_buyingstore_open(struct map_session_data *sd) +void clif_buyingstore_open(struct map_session_data* sd) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x810)); - WFIFOW(fd,0) = 0x810; - WFIFOB(fd,2) = sd->buyingstore.slots; - WFIFOSET(fd,packet_len(0x810)); + WFIFOHEAD(fd,packet_len(0x810)); + WFIFOW(fd,0) = 0x810; + WFIFOB(fd,2) = sd->buyingstore.slots; + WFIFOSET(fd,packet_len(0x810)); } @@ -15270,40 +15458,41 @@ void clif_buyingstore_open(struct map_session_data *sd) /// result: /// 0 = cancel /// 1 = open -static void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data *sd) -{ - const unsigned int blocksize = 8; - uint8 *itemlist; - char storename[MESSAGE_SIZE]; - unsigned char result; - int zenylimit; - unsigned int count, packet_len; - struct s_packet_db *info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; - - packet_len = RFIFOW(fd,info->pos[0]); - - // TODO: Make this check global for all variable length packets. - if (packet_len < 89) { - // minimum packet length - ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 89, packet_len, sd->bl.id); - return; - } +static void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) +{ + const unsigned int blocksize = 8; + uint8* itemlist; + char storename[MESSAGE_SIZE]; + unsigned char result; + int zenylimit; + unsigned int count, packet_len; + struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; - zenylimit = RFIFOL(fd,info->pos[1]); - result = RFIFOL(fd,info->pos[2]); - safestrncpy(storename, (const char *)RFIFOP(fd,info->pos[3]), sizeof(storename)); - itemlist = RFIFOP(fd,info->pos[4]); + packet_len = RFIFOW(fd,info->pos[0]); - // so that buyingstore_create knows, how many elements it has access to - packet_len-= info->pos[4]; + // TODO: Make this check global for all variable length packets. + if( packet_len < 89 ) + {// minimum packet length + ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 89, packet_len, sd->bl.id); + return; + } - if (packet_len%blocksize) { - ShowError("clif_parse_ReqOpenBuyingStore: Unexpected item list size %u (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize); - return; - } - count = packet_len/blocksize; + zenylimit = RFIFOL(fd,info->pos[1]); + result = RFIFOL(fd,info->pos[2]); + safestrncpy(storename, (const char*)RFIFOP(fd,info->pos[3]), sizeof(storename)); + itemlist = RFIFOP(fd,info->pos[4]); + + // so that buyingstore_create knows, how many elements it has access to + packet_len-= info->pos[4]; + + if( packet_len%blocksize ) + { + ShowError("clif_parse_ReqOpenBuyingStore: Unexpected item list size %u (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize); + return; + } + count = packet_len/blocksize; - buyingstore_create(sd, zenylimit, result, storename, itemlist, count); + buyingstore_create(sd, zenylimit, result, storename, itemlist, count); } @@ -15314,165 +15503,168 @@ static void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data *sd) /// 2 = "Total amount of then possessed items exceeds the weight limit by <weight/10-maxweight*90%>. Please re-enter." (0x6ce, MSI_BUYINGSTORE_OVERWEIGHT) /// 8 = "No sale (purchase) information available." (0x705) /// ? = nothing -void clif_buyingstore_open_failed(struct map_session_data *sd, unsigned short result, unsigned int weight) +void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x812)); - WFIFOW(fd,0) = 0x812; - WFIFOW(fd,2) = result; - WFIFOL(fd,4) = weight; - WFIFOSET(fd,packet_len(0x812)); + WFIFOHEAD(fd,packet_len(0x812)); + WFIFOW(fd,0) = 0x812; + WFIFOW(fd,2) = result; + WFIFOL(fd,4) = weight; + WFIFOSET(fd,packet_len(0x812)); } /// Notification, that the requested buying store was created (ZC_MYITEMLIST_BUYING_STORE). /// 0813 <packet len>.W <account id>.L <limit zeny>.L { <price>.L <count>.W <type>.B <name id>.W }* -void clif_buyingstore_myitemlist(struct map_session_data *sd) -{ - int fd = sd->fd; - unsigned int i; - - WFIFOHEAD(fd,12+sd->buyingstore.slots*9); - WFIFOW(fd,0) = 0x813; - WFIFOW(fd,2) = 12+sd->buyingstore.slots*9; - WFIFOL(fd,4) = sd->bl.id; - WFIFOL(fd,8) = sd->buyingstore.zenylimit; - - for (i = 0; i < sd->buyingstore.slots; i++) { - WFIFOL(fd,12+i*9) = sd->buyingstore.items[i].price; - WFIFOW(fd,16+i*9) = sd->buyingstore.items[i].amount; - WFIFOB(fd,18+i*9) = itemtype(itemdb_type(sd->buyingstore.items[i].nameid)); - WFIFOW(fd,19+i*9) = sd->buyingstore.items[i].nameid; - } +void clif_buyingstore_myitemlist(struct map_session_data* sd) +{ + int fd = sd->fd; + unsigned int i; + + WFIFOHEAD(fd,12+sd->buyingstore.slots*9); + WFIFOW(fd,0) = 0x813; + WFIFOW(fd,2) = 12+sd->buyingstore.slots*9; + WFIFOL(fd,4) = sd->bl.id; + WFIFOL(fd,8) = sd->buyingstore.zenylimit; + + for( i = 0; i < sd->buyingstore.slots; i++ ) + { + WFIFOL(fd,12+i*9) = sd->buyingstore.items[i].price; + WFIFOW(fd,16+i*9) = sd->buyingstore.items[i].amount; + WFIFOB(fd,18+i*9) = itemtype(itemdb_type(sd->buyingstore.items[i].nameid)); + WFIFOW(fd,19+i*9) = sd->buyingstore.items[i].nameid; + } - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOSET(fd,WFIFOW(fd,2)); } /// Notifies clients in area of a buying store (ZC_BUYING_STORE_ENTRY). /// 0814 <account id>.L <store name>.80B -void clif_buyingstore_entry(struct map_session_data *sd) +void clif_buyingstore_entry(struct map_session_data* sd) { - uint8 buf[86]; + uint8 buf[86]; - WBUFW(buf,0) = 0x814; - WBUFL(buf,2) = sd->bl.id; - memcpy(WBUFP(buf,6), sd->message, MESSAGE_SIZE); + WBUFW(buf,0) = 0x814; + WBUFL(buf,2) = sd->bl.id; + memcpy(WBUFP(buf,6), sd->message, MESSAGE_SIZE); - clif_send(buf, packet_len(0x814), &sd->bl, AREA_WOS); + clif_send(buf, packet_len(0x814), &sd->bl, AREA_WOS); } -void clif_buyingstore_entry_single(struct map_session_data *sd, struct map_session_data *pl_sd) +void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x814)); - WFIFOW(fd,0) = 0x814; - WFIFOL(fd,2) = pl_sd->bl.id; - memcpy(WFIFOP(fd,6), pl_sd->message, MESSAGE_SIZE); - WFIFOSET(fd,packet_len(0x814)); + WFIFOHEAD(fd,packet_len(0x814)); + WFIFOW(fd,0) = 0x814; + WFIFOL(fd,2) = pl_sd->bl.id; + memcpy(WFIFOP(fd,6), pl_sd->message, MESSAGE_SIZE); + WFIFOSET(fd,packet_len(0x814)); } /// Request to close own buying store (CZ_REQ_CLOSE_BUYING_STORE). /// 0815 -static void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data *sd) +static void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd) { - buyingstore_close(sd); + buyingstore_close(sd); } /// Notifies clients in area that a buying store was closed (ZC_DISAPPEAR_BUYING_STORE_ENTRY). /// 0816 <account id>.L -void clif_buyingstore_disappear_entry(struct map_session_data *sd) +void clif_buyingstore_disappear_entry(struct map_session_data* sd) { - uint8 buf[6]; + uint8 buf[6]; - WBUFW(buf,0) = 0x816; - WBUFL(buf,2) = sd->bl.id; + WBUFW(buf,0) = 0x816; + WBUFL(buf,2) = sd->bl.id; - clif_send(buf, packet_len(0x816), &sd->bl, AREA_WOS); + clif_send(buf, packet_len(0x816), &sd->bl, AREA_WOS); } -void clif_buyingstore_disappear_entry_single(struct map_session_data *sd, struct map_session_data *pl_sd) +void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x816)); - WFIFOW(fd,0) = 0x816; - WFIFOL(fd,2) = pl_sd->bl.id; - WFIFOSET(fd,packet_len(0x816)); + WFIFOHEAD(fd,packet_len(0x816)); + WFIFOW(fd,0) = 0x816; + WFIFOL(fd,2) = pl_sd->bl.id; + WFIFOSET(fd,packet_len(0x816)); } /// Request to open someone else's buying store (CZ_REQ_CLICK_TO_BUYING_STORE). /// 0817 <account id>.L -static void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data *sd) +static void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd) { - int account_id; + int account_id; - account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - buyingstore_open(sd, account_id); + buyingstore_open(sd, account_id); } /// Sends buying store item list (ZC_ACK_ITEMLIST_BUYING_STORE). /// 0818 <packet len>.W <account id>.L <store id>.L <limit zeny>.L { <price>.L <amount>.W <type>.B <name id>.W }* -void clif_buyingstore_itemlist(struct map_session_data *sd, struct map_session_data *pl_sd) -{ - int fd = sd->fd; - unsigned int i; - - WFIFOHEAD(fd,16+pl_sd->buyingstore.slots*9); - WFIFOW(fd,0) = 0x818; - WFIFOW(fd,2) = 16+pl_sd->buyingstore.slots*9; - WFIFOL(fd,4) = pl_sd->bl.id; - WFIFOL(fd,8) = pl_sd->buyer_id; - WFIFOL(fd,12) = pl_sd->buyingstore.zenylimit; - - for (i = 0; i < pl_sd->buyingstore.slots; i++) { - WFIFOL(fd,16+i*9) = pl_sd->buyingstore.items[i].price; - WFIFOW(fd,20+i*9) = pl_sd->buyingstore.items[i].amount; // TODO: Figure out, if no longer needed items (amount == 0) are listed on official. - WFIFOB(fd,22+i*9) = itemtype(itemdb_type(pl_sd->buyingstore.items[i].nameid)); - WFIFOW(fd,23+i*9) = pl_sd->buyingstore.items[i].nameid; - } +void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_data* pl_sd) +{ + int fd = sd->fd; + unsigned int i; + + WFIFOHEAD(fd,16+pl_sd->buyingstore.slots*9); + WFIFOW(fd,0) = 0x818; + WFIFOW(fd,2) = 16+pl_sd->buyingstore.slots*9; + WFIFOL(fd,4) = pl_sd->bl.id; + WFIFOL(fd,8) = pl_sd->buyer_id; + WFIFOL(fd,12) = pl_sd->buyingstore.zenylimit; + + for( i = 0; i < pl_sd->buyingstore.slots; i++ ) + { + WFIFOL(fd,16+i*9) = pl_sd->buyingstore.items[i].price; + WFIFOW(fd,20+i*9) = pl_sd->buyingstore.items[i].amount; // TODO: Figure out, if no longer needed items (amount == 0) are listed on official. + WFIFOB(fd,22+i*9) = itemtype(itemdb_type(pl_sd->buyingstore.items[i].nameid)); + WFIFOW(fd,23+i*9) = pl_sd->buyingstore.items[i].nameid; + } - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOSET(fd,WFIFOW(fd,2)); } /// Request to sell items to a buying store (CZ_REQ_TRADE_BUYING_STORE). /// 0819 <packet len>.W <account id>.L <store id>.L { <index>.W <name id>.W <amount>.W }* -static void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data *sd) +static void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { - const unsigned int blocksize = 6; - uint8 *itemlist; - int account_id; - unsigned int count, packet_len, buyer_id; - struct s_packet_db *info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; + const unsigned int blocksize = 6; + uint8* itemlist; + int account_id; + unsigned int count, packet_len, buyer_id; + struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; - packet_len = RFIFOW(fd,info->pos[0]); + packet_len = RFIFOW(fd,info->pos[0]); - if (packet_len < 12) { - // minimum packet length - ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 12, packet_len, sd->bl.id); - return; - } + if( packet_len < 12 ) + {// minimum packet length + ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 12, packet_len, sd->bl.id); + return; + } - account_id = RFIFOL(fd,info->pos[1]); - buyer_id = RFIFOL(fd,info->pos[2]); - itemlist = RFIFOP(fd,info->pos[3]); + account_id = RFIFOL(fd,info->pos[1]); + buyer_id = RFIFOL(fd,info->pos[2]); + itemlist = RFIFOP(fd,info->pos[3]); - // so that buyingstore_trade knows, how many elements it has access to - packet_len-= info->pos[3]; + // so that buyingstore_trade knows, how many elements it has access to + packet_len-= info->pos[3]; - if (packet_len%blocksize) { - ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%d, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize); - return; - } - count = packet_len/blocksize; + if( packet_len%blocksize ) + { + ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%d, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize); + return; + } + count = packet_len/blocksize; - buyingstore_trade(sd, account_id, buyer_id, itemlist, count); + buyingstore_trade(sd, account_id, buyer_id, itemlist, count); } @@ -15482,29 +15674,29 @@ static void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data *sd) /// 3 = "All items within the buy limit were purchased." (0x6cf, MSI_BUYINGSTORE_TRADE_OVERLIMITZENY) /// 4 = "All items were purchased." (0x6d0, MSI_BUYINGSTORE_TRADE_BUYCOMPLETE) /// ? = nothing -void clif_buyingstore_trade_failed_buyer(struct map_session_data *sd, short result) +void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x81a)); - WFIFOW(fd,0) = 0x81a; - WFIFOW(fd,2) = result; - WFIFOSET(fd,packet_len(0x81a)); + WFIFOHEAD(fd,packet_len(0x81a)); + WFIFOW(fd,0) = 0x81a; + WFIFOW(fd,2) = result; + WFIFOSET(fd,packet_len(0x81a)); } /// Updates the zeny limit and an item in the buying store item list (ZC_UPDATE_ITEM_FROM_BUYING_STORE). /// 081b <name id>.W <amount>.W <limit zeny>.L -void clif_buyingstore_update_item(struct map_session_data *sd, unsigned short nameid, unsigned short amount) +void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x81b)); - WFIFOW(fd,0) = 0x81b; - WFIFOW(fd,2) = nameid; - WFIFOW(fd,4) = amount; // amount of nameid received - WFIFOL(fd,6) = sd->buyingstore.zenylimit; - WFIFOSET(fd,packet_len(0x81b)); + WFIFOHEAD(fd,packet_len(0x81b)); + WFIFOW(fd,0) = 0x81b; + WFIFOW(fd,2) = nameid; + WFIFOW(fd,4) = amount; // amount of nameid received + WFIFOL(fd,6) = sd->buyingstore.zenylimit; + WFIFOSET(fd,packet_len(0x81b)); } @@ -15514,16 +15706,16 @@ void clif_buyingstore_update_item(struct map_session_data *sd, unsigned short na /// "%s (%d) were sold at %dz." (0x6d2, MSI_BUYINGSTORE_TRADE_SELLCOMPLETE) /// /// NOTE: This function has to be called _instead_ of clif_delitem/clif_dropitem. -void clif_buyingstore_delete_item(struct map_session_data *sd, short index, unsigned short amount, int price) +void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x81c)); - WFIFOW(fd,0) = 0x81c; - WFIFOW(fd,2) = index+2; - WFIFOW(fd,4) = amount; - WFIFOL(fd,6) = price; // price per item, client calculates total Zeny by itself - WFIFOSET(fd,packet_len(0x81c)); + WFIFOHEAD(fd,packet_len(0x81c)); + WFIFOW(fd,0) = 0x81c; + WFIFOW(fd,2) = index+2; + WFIFOW(fd,4) = amount; + WFIFOL(fd,6) = price; // price per item, client calculates total Zeny by itself + WFIFOSET(fd,packet_len(0x81c)); } @@ -15534,15 +15726,15 @@ void clif_buyingstore_delete_item(struct map_session_data *sd, short index, unsi /// 6 = "The trade failed, because the entered amount of item %s is higher, than the buyer is willing to buy." (0x6d3, MSI_BUYINGSTORE_TRADE_OVERCOUNT) /// 7 = "The trade failed, because the buyer is lacking required balance." (0x6d1, MSI_BUYINGSTORE_TRADE_LACKBUYERZENY) /// ? = nothing -void clif_buyingstore_trade_failed_seller(struct map_session_data *sd, short result, unsigned short nameid) +void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x824)); - WFIFOW(fd,0) = 0x824; - WFIFOW(fd,2) = result; - WFIFOW(fd,4) = nameid; - WFIFOSET(fd,packet_len(0x824)); + WFIFOHEAD(fd,packet_len(0x824)); + WFIFOW(fd,0) = 0x824; + WFIFOW(fd,2) = result; + WFIFOW(fd,4) = nameid; + WFIFOSET(fd,packet_len(0x824)); } @@ -15558,46 +15750,48 @@ void clif_buyingstore_trade_failed_seller(struct map_session_data *sd, short res /// NOTE: The client determines the item ids by specifying a name and optionally, /// amount of card slots. If the client does not know about the item it /// cannot be searched. -static void clif_parse_SearchStoreInfo(int fd, struct map_session_data *sd) +static void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) { - const unsigned int blocksize = 2; - const uint8 *itemlist; - const uint8 *cardlist; - unsigned char type; - unsigned int min_price, max_price, packet_len, count, item_count, card_count; - struct s_packet_db *info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; + const unsigned int blocksize = 2; + const uint8* itemlist; + const uint8* cardlist; + unsigned char type; + unsigned int min_price, max_price, packet_len, count, item_count, card_count; + struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; - packet_len = RFIFOW(fd,info->pos[0]); + packet_len = RFIFOW(fd,info->pos[0]); - if (packet_len < 15) { - // minimum packet length - ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 15, packet_len, sd->bl.id); - return; - } + if( packet_len < 15 ) + {// minimum packet length + ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 15, packet_len, sd->bl.id); + return; + } - type = RFIFOB(fd,info->pos[1]); - max_price = RFIFOL(fd,info->pos[2]); - min_price = RFIFOL(fd,info->pos[3]); - item_count = RFIFOB(fd,info->pos[4]); - card_count = RFIFOB(fd,info->pos[5]); - itemlist = RFIFOP(fd,info->pos[6]); - cardlist = RFIFOP(fd,info->pos[6]+blocksize*item_count); + type = RFIFOB(fd,info->pos[1]); + max_price = RFIFOL(fd,info->pos[2]); + min_price = RFIFOL(fd,info->pos[3]); + item_count = RFIFOB(fd,info->pos[4]); + card_count = RFIFOB(fd,info->pos[5]); + itemlist = RFIFOP(fd,info->pos[6]); + cardlist = RFIFOP(fd,info->pos[6]+blocksize*item_count); - // check, if there is enough data for the claimed count of items - packet_len-= info->pos[6]; + // check, if there is enough data for the claimed count of items + packet_len-= info->pos[6]; - if (packet_len%blocksize) { - ShowError("clif_parse_SearchStoreInfo: Unexpected item list size %u (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize); - return; - } - count = packet_len/blocksize; + if( packet_len%blocksize ) + { + ShowError("clif_parse_SearchStoreInfo: Unexpected item list size %u (account_id=%d, block size=%u)\n", packet_len, sd->bl.id, blocksize); + return; + } + count = packet_len/blocksize; - if (count < item_count+card_count) { - ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected count=%u, count=%u, account_id=%d).\n", item_count+card_count, count, sd->bl.id); - return; - } + if( count < item_count+card_count ) + { + ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected count=%u, count=%u, account_id=%d).\n", item_count+card_count, count, sd->bl.id); + return; + } - searchstore_query(sd, type, min_price, max_price, (const unsigned short *)itemlist, item_count, (const unsigned short *)cardlist, card_count); + searchstore_query(sd, type, min_price, max_price, (const unsigned short*)itemlist, item_count, (const unsigned short*)cardlist, card_count); } @@ -15609,45 +15803,46 @@ static void clif_parse_SearchStoreInfo(int fd, struct map_session_data *sd) /// is next page: /// 0 = no "next" label /// 1 = "next" label to retrieve more results -void clif_search_store_info_ack(struct map_session_data *sd) -{ - const unsigned int blocksize = MESSAGE_SIZE+26; - int fd = sd->fd; - unsigned int i, start, end; - - start = sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE; - end = min(sd->searchstore.count, start+SEARCHSTORE_RESULTS_PER_PAGE); - - WFIFOHEAD(fd,7+(end-start)*blocksize); - WFIFOW(fd,0) = 0x836; - WFIFOW(fd,2) = 7+(end-start)*blocksize; - WFIFOB(fd,4) = !sd->searchstore.pages; - WFIFOB(fd,5) = searchstore_querynext(sd); - WFIFOB(fd,6) = (unsigned char)min(sd->searchstore.uses, UINT8_MAX); - - for (i = start; i < end; i++) { - struct s_search_store_info_item *ssitem = &sd->searchstore.items[i]; - struct item it; - - WFIFOL(fd,i*blocksize+ 7) = ssitem->store_id; - WFIFOL(fd,i*blocksize+11) = ssitem->account_id; - memcpy(WFIFOP(fd,i*blocksize+15), ssitem->store_name, MESSAGE_SIZE); - WFIFOW(fd,i*blocksize+15+MESSAGE_SIZE) = ssitem->nameid; - WFIFOB(fd,i*blocksize+17+MESSAGE_SIZE) = itemtype(itemdb_type(ssitem->nameid)); - WFIFOL(fd,i*blocksize+18+MESSAGE_SIZE) = ssitem->price; - WFIFOW(fd,i*blocksize+22+MESSAGE_SIZE) = ssitem->amount; - WFIFOB(fd,i*blocksize+24+MESSAGE_SIZE) = ssitem->refine; - - // make-up an item for clif_addcards - memset(&it, 0, sizeof(it)); - memcpy(&it.card, &ssitem->card, sizeof(it.card)); - it.nameid = ssitem->nameid; - it.amount = ssitem->amount; - - clif_addcards(WFIFOP(fd,i*blocksize+25+MESSAGE_SIZE), &it); - } +void clif_search_store_info_ack(struct map_session_data* sd) +{ + const unsigned int blocksize = MESSAGE_SIZE+26; + int fd = sd->fd; + unsigned int i, start, end; + + start = sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE; + end = min(sd->searchstore.count, start+SEARCHSTORE_RESULTS_PER_PAGE); + + WFIFOHEAD(fd,7+(end-start)*blocksize); + WFIFOW(fd,0) = 0x836; + WFIFOW(fd,2) = 7+(end-start)*blocksize; + WFIFOB(fd,4) = !sd->searchstore.pages; + WFIFOB(fd,5) = searchstore_querynext(sd); + WFIFOB(fd,6) = (unsigned char)min(sd->searchstore.uses, UINT8_MAX); - WFIFOSET(fd,WFIFOW(fd,2)); + for( i = start; i < end; i++ ) + { + struct s_search_store_info_item* ssitem = &sd->searchstore.items[i]; + struct item it; + + WFIFOL(fd,i*blocksize+ 7) = ssitem->store_id; + WFIFOL(fd,i*blocksize+11) = ssitem->account_id; + memcpy(WFIFOP(fd,i*blocksize+15), ssitem->store_name, MESSAGE_SIZE); + WFIFOW(fd,i*blocksize+15+MESSAGE_SIZE) = ssitem->nameid; + WFIFOB(fd,i*blocksize+17+MESSAGE_SIZE) = itemtype(itemdb_type(ssitem->nameid)); + WFIFOL(fd,i*blocksize+18+MESSAGE_SIZE) = ssitem->price; + WFIFOW(fd,i*blocksize+22+MESSAGE_SIZE) = ssitem->amount; + WFIFOB(fd,i*blocksize+24+MESSAGE_SIZE) = ssitem->refine; + + // make-up an item for clif_addcards + memset(&it, 0, sizeof(it)); + memcpy(&it.card, &ssitem->card, sizeof(it.card)); + it.nameid = ssitem->nameid; + it.amount = ssitem->amount; + + clif_addcards(WFIFOP(fd,i*blocksize+25+MESSAGE_SIZE), &it); + } + + WFIFOSET(fd,WFIFOW(fd,2)); } @@ -15659,22 +15854,22 @@ void clif_search_store_info_ack(struct map_session_data *sd) /// 2 = "You cannot search anymore." (0x706) /// 3 = "You cannot search yet." (0x708) /// 4 = "No sale (purchase) information available." (0x705) -void clif_search_store_info_failed(struct map_session_data *sd, unsigned char reason) +void clif_search_store_info_failed(struct map_session_data* sd, unsigned char reason) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x837)); - WFIFOW(fd,0) = 0x837; - WFIFOB(fd,2) = reason; - WFIFOSET(fd,packet_len(0x837)); + WFIFOHEAD(fd,packet_len(0x837)); + WFIFOW(fd,0) = 0x837; + WFIFOB(fd,2) = reason; + WFIFOSET(fd,packet_len(0x837)); } /// Request to display next page of results (CZ_SEARCH_STORE_INFO_NEXT_PAGE). /// 0838 -static void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data *sd) +static void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) { - searchstore_next(sd); + searchstore_next(sd); } @@ -15683,131 +15878,133 @@ static void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data * /// type: /// 0 = Search Stores /// 1 = Search Stores (Cash), asks for confirmation, when clicking a store -void clif_open_search_store_info(struct map_session_data *sd) +void clif_open_search_store_info(struct map_session_data* sd) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x83a)); - WFIFOW(fd,0) = 0x83a; - WFIFOW(fd,2) = sd->searchstore.effect; + WFIFOHEAD(fd,packet_len(0x83a)); + WFIFOW(fd,0) = 0x83a; + WFIFOW(fd,2) = sd->searchstore.effect; #if PACKETVER > 20100701 - WFIFOB(fd,4) = (unsigned char)min(sd->searchstore.uses, UINT8_MAX); + WFIFOB(fd,4) = (unsigned char)min(sd->searchstore.uses, UINT8_MAX); #endif - WFIFOSET(fd,packet_len(0x83a)); + WFIFOSET(fd,packet_len(0x83a)); } /// Request to close the store search window (CZ_CLOSE_SEARCH_STORE_INFO). /// 083b -static void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data *sd) +static void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd) { - searchstore_close(sd); + searchstore_close(sd); } /// Request to invoke catalog effect on a store from search results (CZ_SSILIST_ITEM_CLICK). /// 083c <account id>.L <store id>.L <nameid>.W -static void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data *sd) +static void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd) { - unsigned short nameid; - int account_id, store_id; - struct s_packet_db *info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; + unsigned short nameid; + int account_id, store_id; + struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; - account_id = RFIFOL(fd,info->pos[0]); - store_id = RFIFOL(fd,info->pos[1]); - nameid = RFIFOW(fd,info->pos[2]); + account_id = RFIFOL(fd,info->pos[0]); + store_id = RFIFOL(fd,info->pos[1]); + nameid = RFIFOW(fd,info->pos[2]); - searchstore_click(sd, account_id, store_id, nameid); + searchstore_click(sd, account_id, store_id, nameid); } /// Notification of the store position on current map (ZC_SSILIST_ITEM_CLICK_ACK). /// 083d <xPos>.W <yPos>.W -void clif_search_store_info_click_ack(struct map_session_data *sd, short x, short y) +void clif_search_store_info_click_ack(struct map_session_data* sd, short x, short y) { - int fd = sd->fd; + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x83d)); - WFIFOW(fd,0) = 0x83d; - WFIFOW(fd,2) = x; - WFIFOW(fd,4) = y; - WFIFOSET(fd,packet_len(0x83d)); + WFIFOHEAD(fd,packet_len(0x83d)); + WFIFOW(fd,0) = 0x83d; + WFIFOW(fd,2) = x; + WFIFOW(fd,4) = y; + WFIFOSET(fd,packet_len(0x83d)); } /// Parse function for packet debugging. void clif_parse_debug(int fd,struct map_session_data *sd) { - int cmd, packet_len; - - // clif_parse ensures, that there is at least 2 bytes of data - cmd = RFIFOW(fd,0); - - if (sd) { - packet_len = packet_db[sd->packet_ver][cmd].len; - - if (packet_len == 0) { - // unknown - packet_len = RFIFOREST(fd); - } else if (packet_len == -1) { - // variable length - packet_len = RFIFOW(fd,2); // clif_parse ensures, that this amount of data is already received - } - ShowDebug("Packet debug of 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); - } else { - packet_len = RFIFOREST(fd); - ShowDebug("Packet debug of 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); - } - - ShowDump(RFIFOP(fd,0), packet_len); + int cmd, packet_len; + + // clif_parse ensures, that there is at least 2 bytes of data + cmd = RFIFOW(fd,0); + + if( sd ) + { + packet_len = packet_db[sd->packet_ver][cmd].len; + + if( packet_len == 0 ) + {// unknown + packet_len = RFIFOREST(fd); + } + else if( packet_len == -1 ) + {// variable length + packet_len = RFIFOW(fd,2); // clif_parse ensures, that this amount of data is already received + } + ShowDebug("Packet debug of 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); + } + else + { + packet_len = RFIFOREST(fd); + ShowDebug("Packet debug of 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); + } + + ShowDump(RFIFOP(fd,0), packet_len); } /*========================================== * Server tells client to display a window similar to Magnifier (item) one * Server populates the window with avilable elemental converter options according to player's inventory *------------------------------------------*/ -int clif_elementalconverter_list(struct map_session_data *sd) -{ - int i,c,view,fd; - - nullpo_ret(sd); - - - /// Main client packet processing function - fd=sd->fd; - WFIFOHEAD(fd, MAX_SKILL_PRODUCE_DB *2+4); - WFIFOW(fd, 0)=0x1ad; - - for (i=0,c=0; i<MAX_SKILL_PRODUCE_DB; i++) { - if (skill_can_produce_mix(sd,skill_produce_db[i].nameid,23, 1)) { - if ((view = itemdb_viewid(skill_produce_db[i].nameid)) > 0) - WFIFOW(fd,c*2+ 4)= view; - else - WFIFOW(fd,c*2+ 4)= skill_produce_db[i].nameid; - c++; - } - } - WFIFOW(fd,2) = c*2+4; - WFIFOSET(fd, WFIFOW(fd,2)); - if (c > 0) { - sd->menuskill_id = SA_CREATECON; - sd->menuskill_val = c; - } - - return 0; +int clif_elementalconverter_list(struct map_session_data *sd) { + int i,c,view,fd; + + nullpo_ret(sd); + + +/// Main client packet processing function + fd=sd->fd; + WFIFOHEAD(fd, MAX_SKILL_PRODUCE_DB *2+4); + WFIFOW(fd, 0)=0x1ad; + + for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){ + if( skill_can_produce_mix(sd,skill_produce_db[i].nameid,23, 1) ){ + if((view = itemdb_viewid(skill_produce_db[i].nameid)) > 0) + WFIFOW(fd,c*2+ 4)= view; + else + WFIFOW(fd,c*2+ 4)= skill_produce_db[i].nameid; + c++; + } + } + WFIFOW(fd,2) = c*2+4; + WFIFOSET(fd, WFIFOW(fd,2)); + if (c > 0) { + sd->menuskill_id = SA_CREATECON; + sd->menuskill_val = c; + } + + return 0; } /** * Rune Knight **/ -void clif_millenniumshield(struct map_session_data *sd, short shields) -{ +void clif_millenniumshield(struct map_session_data *sd, short shields ) { #if PACKETVER >= 20081217 - unsigned char buf[10]; + unsigned char buf[10]; - WBUFW(buf,0) = 0x440; - WBUFL(buf,2) = sd->bl.id; - WBUFW(buf,6) = shields; - WBUFW(buf,8) = 0; - clif_send(buf,packet_len(0x440),&sd->bl,AREA); + WBUFW(buf,0) = 0x440; + WBUFL(buf,2) = sd->bl.id; + WBUFW(buf,6) = shields; + WBUFW(buf,8) = 0; + clif_send(buf,packet_len(0x440),&sd->bl,AREA); #endif } /** @@ -15818,33 +16015,37 @@ void clif_millenniumshield(struct map_session_data *sd, short shields) *------------------------------------------*/ int clif_spellbook_list(struct map_session_data *sd) { - int i, c; - int fd; - - nullpo_ret(sd); - - fd = sd->fd; - WFIFOHEAD(fd, 8 * 8 + 8); - WFIFOW(fd,0) = 0x1ad; - - for (i = 0, c = 0; i < MAX_INVENTORY; i ++) { - if (itemdb_is_spellbook(sd->status.inventory[i].nameid)) { - WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid; - c ++; - } - } - - if (c > 0) { - WFIFOW(fd,2) = c * 2 + 4; - WFIFOSET(fd, WFIFOW(fd, 2)); - sd->menuskill_id = WL_READING_SB; - sd->menuskill_val = c; - } else { - status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK, 0); - } - - return 1; + int i, c; + int fd; + + nullpo_ret(sd); + + fd = sd->fd; + WFIFOHEAD(fd, 8 * 8 + 8); + WFIFOW(fd,0) = 0x1ad; + + for( i = 0, c = 0; i < MAX_INVENTORY; i ++ ) + { + if( itemdb_is_spellbook(sd->status.inventory[i].nameid) ) + { + WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid; + c ++; + } + } + + if( c > 0 ) + { + WFIFOW(fd,2) = c * 2 + 4; + WFIFOSET(fd, WFIFOW(fd, 2)); + sd->menuskill_id = WL_READING_SB; + sd->menuskill_val = c; + } + else{ + status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); + clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK, 0); + } + + return 1; } /** * Mechanic @@ -15852,36 +16053,35 @@ int clif_spellbook_list(struct map_session_data *sd) /*========================================== * Magic Decoy Material List *------------------------------------------*/ -int clif_magicdecoy_list(struct map_session_data *sd, int skill_lv, short x, short y) -{ - int i, c; - int fd; - - nullpo_ret(sd); - - fd = sd->fd; - WFIFOHEAD(fd, 8 * 8 + 8); - WFIFOW(fd,0) = 0x1ad; // This is the official packet. [pakpil] - - for (i = 0, c = 0; i < MAX_INVENTORY; i ++) { - if (itemdb_is_element(sd->status.inventory[i].nameid)) { - WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid; - c ++; - } - } - if (c > 0) { - sd->menuskill_id = NC_MAGICDECOY; - sd->menuskill_val = skill_lv; - sd->sc.comet_x = x; - sd->sc.comet_y = y; - WFIFOW(fd,2) = c * 2 + 4; - WFIFOSET(fd, WFIFOW(fd, 2)); - } else { - clif_skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0); - return 0; - } - - return 1; +int clif_magicdecoy_list(struct map_session_data *sd, int skill_lv, short x, short y) { + int i, c; + int fd; + + nullpo_ret(sd); + + fd = sd->fd; + WFIFOHEAD(fd, 8 * 8 + 8); + WFIFOW(fd,0) = 0x1ad; // This is the official packet. [pakpil] + + for( i = 0, c = 0; i < MAX_INVENTORY; i ++ ) { + if( itemdb_is_element(sd->status.inventory[i].nameid) ) { + WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid; + c ++; + } + } + if( c > 0 ) { + sd->menuskill_id = NC_MAGICDECOY; + sd->menuskill_val = skill_lv; + sd->sc.comet_x = x; + sd->sc.comet_y = y; + WFIFOW(fd,2) = c * 2 + 4; + WFIFOSET(fd, WFIFOW(fd, 2)); + } else { + clif_skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0); + return 0; + } + + return 1; } /** * Guilotine Cross @@ -15889,260 +16089,249 @@ int clif_magicdecoy_list(struct map_session_data *sd, int skill_lv, short x, sho /*========================================== * Guillotine Cross Poisons List *------------------------------------------*/ -int clif_poison_list(struct map_session_data *sd, int skill_lv) -{ - int i, c; - int fd; - - nullpo_ret(sd); - - fd = sd->fd; - WFIFOHEAD(fd, 8 * 8 + 8); - WFIFOW(fd,0) = 0x1ad; // This is the official packet. [pakpil] - - for (i = 0, c = 0; i < MAX_INVENTORY; i ++) { - if (itemdb_is_poison(sd->status.inventory[i].nameid)) { - WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid; - c ++; - } - } - if (c > 0) { - sd->menuskill_id = GC_POISONINGWEAPON; - sd->menuskill_val = skill_lv; - WFIFOW(fd,2) = c * 2 + 4; - WFIFOSET(fd, WFIFOW(fd, 2)); - } else { - clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_GUILLONTINE_POISON,0); - return 0; - } - - return 1; -} -int clif_autoshadowspell_list(struct map_session_data *sd) -{ - int fd, i, c; - nullpo_ret(sd); - fd = sd->fd; - if (!fd) return 0; - - if (sd->menuskill_id == SC_AUTOSHADOWSPELL) - return 0; - - WFIFOHEAD(fd, 2 * 6 + 4); - WFIFOW(fd,0) = 0x442; - for (i = 0, c = 0; i < MAX_SKILL; i++) - if (sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 && - sd->status.skill[i].id < GS_GLITTERING && skill_get_type(sd->status.skill[i].id) == BF_MAGIC) { - // Can't auto cast both Extended class and 3rd class skills. - WFIFOW(fd,8+c*2) = sd->status.skill[i].id; - c++; - } - - if (c > 0) { - WFIFOW(fd,2) = 8 + c * 2; - WFIFOL(fd,4) = c; - WFIFOSET(fd,WFIFOW(fd,2)); - sd->menuskill_id = SC_AUTOSHADOWSPELL; - sd->menuskill_val = c; - } else { - status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); - clif_skill_fail(sd,SC_AUTOSHADOWSPELL,USESKILL_FAIL_IMITATION_SKILL_NONE,0); - } - - return 1; +int clif_poison_list(struct map_session_data *sd, int skill_lv) { + int i, c; + int fd; + + nullpo_ret(sd); + + fd = sd->fd; + WFIFOHEAD(fd, 8 * 8 + 8); + WFIFOW(fd,0) = 0x1ad; // This is the official packet. [pakpil] + + for( i = 0, c = 0; i < MAX_INVENTORY; i ++ ) { + if( itemdb_is_poison(sd->status.inventory[i].nameid) ) { + WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid; + c ++; + } + } + if( c > 0 ) { + sd->menuskill_id = GC_POISONINGWEAPON; + sd->menuskill_val = skill_lv; + WFIFOW(fd,2) = c * 2 + 4; + WFIFOSET(fd, WFIFOW(fd, 2)); + } else { + clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_GUILLONTINE_POISON,0); + return 0; + } + + return 1; +} +int clif_autoshadowspell_list(struct map_session_data *sd) { + int fd, i, c; + nullpo_ret(sd); + fd = sd->fd; + if( !fd ) return 0; + + if( sd->menuskill_id == SC_AUTOSHADOWSPELL ) + return 0; + + WFIFOHEAD(fd, 2 * 6 + 4); + WFIFOW(fd,0) = 0x442; + for( i = 0, c = 0; i < MAX_SKILL; i++ ) + if( sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 && + sd->status.skill[i].id < GS_GLITTERING && skill_get_type(sd->status.skill[i].id) == BF_MAGIC ) + { // Can't auto cast both Extended class and 3rd class skills. + WFIFOW(fd,8+c*2) = sd->status.skill[i].id; + c++; + } + + if( c > 0 ) { + WFIFOW(fd,2) = 8 + c * 2; + WFIFOL(fd,4) = c; + WFIFOSET(fd,WFIFOW(fd,2)); + sd->menuskill_id = SC_AUTOSHADOWSPELL; + sd->menuskill_val = c; + } else { + status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); + clif_skill_fail(sd,SC_AUTOSHADOWSPELL,USESKILL_FAIL_IMITATION_SKILL_NONE,0); + } + + return 1; } /*=========================================== * Skill list for Four Elemental Analysis * and Change Material skills. *------------------------------------------*/ -int clif_skill_itemlistwindow(struct map_session_data *sd, int skill_id, int skill_lv) +int clif_skill_itemlistwindow( struct map_session_data *sd, int skill_id, int skill_lv ) { #if PACKETVER >= 20090922 - int fd; + int fd; - nullpo_ret(sd); + nullpo_ret(sd); - sd->menuskill_id = skill_id; // To prevent hacking. - sd->menuskill_val = skill_lv; + sd->menuskill_id = skill_id; // To prevent hacking. + sd->menuskill_val = skill_lv; - if (skill_id == GN_CHANGEMATERIAL) - skill_lv = 0; // Changematerial + if( skill_id == GN_CHANGEMATERIAL ) + skill_lv = 0; // Changematerial - fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x7e3)); - WFIFOW(fd,0) = 0x7e3; - WFIFOL(fd,2) = skill_lv; - WFIFOL(fd,4) = 0; - WFIFOSET(fd,packet_len(0x7e3)); + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0x7e3)); + WFIFOW(fd,0) = 0x7e3; + WFIFOL(fd,2) = skill_lv; + WFIFOL(fd,4) = 0; + WFIFOSET(fd,packet_len(0x7e3)); #endif - return 1; + return 1; } /** * Sends a new status without a tick (currently used by the new mounts) **/ -int clif_status_load_notick(struct block_list *bl,int type,int flag,int val1, int val2, int val3) -{ - unsigned char buf[32]; +int clif_status_load_notick(struct block_list *bl,int type,int flag,int val1, int val2, int val3) { + unsigned char buf[32]; - nullpo_ret(bl); + nullpo_ret(bl); - WBUFW(buf,0)=0x043f; - WBUFW(buf,2)=type; - WBUFL(buf,4)=bl->id; - WBUFB(buf,8)=flag; - WBUFL(buf,9) = 0; - WBUFL(buf,13) = val1; - WBUFL(buf,17) = val2; - WBUFL(buf,21) = val3; + WBUFW(buf,0)=0x043f; + WBUFW(buf,2)=type; + WBUFL(buf,4)=bl->id; + WBUFB(buf,8)=flag; + WBUFL(buf,9) = 0; + WBUFL(buf,13) = val1; + WBUFL(buf,17) = val2; + WBUFL(buf,21) = val3; - clif_send(buf,packet_len(0x043f),bl,AREA); - return 0; + clif_send(buf,packet_len(0x043f),bl,AREA); + return 0; } //Notifies FD of ID's type -int clif_status_load_single(int fd, int id,int type,int flag,int val1, int val2, int val3) -{ - WFIFOHEAD(fd, packet_len(0x043f)); - WFIFOW(fd,0)=0x043f; - WFIFOW(fd,2)=type; - WFIFOL(fd,4)=id; - WFIFOB(fd,8)=flag; - WFIFOL(fd,9) = 0; - WFIFOL(fd,13) = val1; - WFIFOL(fd,17) = val2; - WFIFOL(fd,21) = val3; - WFIFOSET(fd, packet_len(0x043f)); - return 0; +int clif_status_load_single(int fd, int id,int type,int flag,int val1, int val2, int val3) { + WFIFOHEAD(fd, packet_len(0x043f)); + WFIFOW(fd,0)=0x043f; + WFIFOW(fd,2)=type; + WFIFOL(fd,4)=id; + WFIFOB(fd,8)=flag; + WFIFOL(fd,9) = 0; + WFIFOL(fd,13) = val1; + WFIFOL(fd,17) = val2; + WFIFOL(fd,21) = val3; + WFIFOSET(fd, packet_len(0x043f)); + return 0; } // msgstringtable.txt // 0x291 <line>.W -void clif_msgtable(int fd, int line) -{ - WFIFOHEAD(fd, packet_len(0x291)); - WFIFOW(fd, 0) = 0x291; - WFIFOW(fd, 2) = line; - WFIFOSET(fd, packet_len(0x291)); +void clif_msgtable(int fd, int line) { + WFIFOHEAD(fd, packet_len(0x291)); + WFIFOW(fd, 0) = 0x291; + WFIFOW(fd, 2) = line; + WFIFOSET(fd, packet_len(0x291)); } // msgstringtable.txt // 0x7e2 <line>.W <value>.L -void clif_msgtable_num(int fd, int line, int num) -{ +void clif_msgtable_num(int fd, int line, int num) { #if PACKETVER >= 20090805 - WFIFOHEAD(fd, packet_len(0x7e2)); - WFIFOW(fd, 0) = 0x7e2; - WFIFOW(fd, 2) = line; - WFIFOL(fd, 4) = num; - WFIFOSET(fd, packet_len(0x7e2)); + WFIFOHEAD(fd, packet_len(0x7e2)); + WFIFOW(fd, 0) = 0x7e2; + WFIFOW(fd, 2) = line; + WFIFOL(fd, 4) = num; + WFIFOSET(fd, packet_len(0x7e2)); #endif } /*========================================== * used by SC_AUTOSHADOWSPELL * RFIFOL(fd,2) - flag (currently not used) *------------------------------------------*/ -void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) -{ +void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) { - if (sd->menuskill_id != SC_AUTOSHADOWSPELL) - return; + if( sd->menuskill_id != SC_AUTOSHADOWSPELL ) + return; - if (pc_istrading(sd)) { - clif_skill_fail(sd,sd->ud.skillid,0,0); - clif_menuskill_clear(sd); - return; - } + if( pc_istrading(sd) ) { + clif_skill_fail(sd,sd->ud.skillid,0,0); + clif_menuskill_clear(sd); + return; + } - skill_select_menu(sd,RFIFOW(fd,6)); + skill_select_menu(sd,RFIFOW(fd,6)); - clif_menuskill_clear(sd); + clif_menuskill_clear(sd); } /*========================================== * Kagerou/Oboro amulet spirit *------------------------------------------*/ void clif_talisman(struct map_session_data *sd,short type) { - unsigned char buf[10]; + unsigned char buf[10]; - nullpo_retv(sd); + nullpo_retv(sd); - WBUFW(buf,0)=0x08cf; - WBUFL(buf,2)=sd->bl.id; - WBUFW(buf,6)=type; - WBUFW(buf,8)=sd->talisman[type]; - clif_send(buf,packet_len(0x08cf),&sd->bl,AREA); + WBUFW(buf,0)=0x08cf; + WBUFL(buf,2)=sd->bl.id; + WBUFW(buf,6)=type; + WBUFW(buf,8)=sd->talisman[type]; + clif_send(buf,packet_len(0x08cf),&sd->bl,AREA); } /// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE] /// 0907 <index>.W /// /// R 0908 <index>.w <type>.b /// type: -/// 0 = move item to personal tab -/// 1 = move item to normal tab -void clif_parse_MoveItem(int fd, struct map_session_data *sd) -{ +/// 0 = move item to personal tab +/// 1 = move item to normal tab +void clif_parse_MoveItem(int fd, struct map_session_data *sd) { #if PACKETVER >= 20111122 - int index; + int index; - /* can't move while dead. */ - if (pc_isdead(sd)) { - return; - } + /* can't move while dead. */ + if(pc_isdead(sd)) { + return; + } - index = RFIFOW(fd,2)-2; + index = RFIFOW(fd,2)-2; - if (index < 0 || index >= MAX_INVENTORY) - return; + if (index < 0 || index >= MAX_INVENTORY) + return; - if (sd->status.inventory[index].favorite && RFIFOB(fd, 4) == 1) - sd->status.inventory[index].favorite = 0; - else if (RFIFOB(fd, 4) == 0) - sd->status.inventory[index].favorite = 1; - else - return;/* nothing to do. */ + if ( sd->status.inventory[index].favorite && RFIFOB(fd, 4) == 1 ) + sd->status.inventory[index].favorite = 0; + else if( RFIFOB(fd, 4) == 0 ) + sd->status.inventory[index].favorite = 1; + else + return;/* nothing to do. */ - clif_favorite_item(sd, index); + clif_favorite_item(sd, index); #endif } /// Items that are in favorite tab of inventory (ZC_ITEM_FAVORITE). /// 0900 <index>.W <favorite>.B -void clif_favorite_item(struct map_session_data *sd, unsigned short index) -{ - int fd = sd->fd; +void clif_favorite_item(struct map_session_data* sd, unsigned short index) { + int fd = sd->fd; - WFIFOHEAD(fd,packet_len(0x908)); - WFIFOW(fd,0) = 0x908; - WFIFOW(fd,2) = index+2; - WFIFOL(fd,4) = (sd->status.inventory[index].favorite == 1) ? 0 : 1; - WFIFOSET(fd,packet_len(0x908)); + WFIFOHEAD(fd,packet_len(0x908)); + WFIFOW(fd,0) = 0x908; + WFIFOW(fd,2) = index+2; + WFIFOL(fd,4) = (sd->status.inventory[index].favorite == 1) ? 0 : 1; + WFIFOSET(fd,packet_len(0x908)); } -void clif_snap(struct block_list *bl, short x, short y) -{ - unsigned char buf[10]; +void clif_snap( struct block_list *bl, short x, short y ) { + unsigned char buf[10]; - WBUFW(buf,0) = 0x8d2; - WBUFL(buf,2) = bl->id; - WBUFW(buf,6) = x; - WBUFW(buf,8) = y; + WBUFW(buf,0) = 0x8d2; + WBUFL(buf,2) = bl->id; + WBUFW(buf,6) = x; + WBUFW(buf,8) = y; - clif_send(buf,packet_len(0x8d2),bl,AREA); + clif_send(buf,packet_len(0x8d2),bl,AREA); } -void clif_monster_hp_bar(struct mob_data *md, int fd) -{ +void clif_monster_hp_bar( struct mob_data* md, int fd ) { #if PACKETVER >= 20120404 - WFIFOHEAD(fd,packet_len(0x977)); + WFIFOHEAD(fd,packet_len(0x977)); - WFIFOW(fd,0) = 0x977; - WFIFOL(fd,2) = md->bl.id; - WFIFOL(fd,6) = md->status.hp; - WFIFOL(fd,10) = md->status.max_hp; + WFIFOW(fd,0) = 0x977; + WFIFOL(fd,2) = md->bl.id; + WFIFOL(fd,6) = md->status.hp; + WFIFOL(fd,10) = md->status.max_hp; - WFIFOSET(fd,packet_len(0x977)); + WFIFOSET(fd,packet_len(0x977)); #endif } @@ -16151,153 +16340,156 @@ void clif_monster_hp_bar(struct mob_data *md, int fd) *------------------------------------------*/ static int clif_parse(int fd) { - int cmd, packet_ver, packet_len, err; - TBL_PC *sd; - int pnum; - - //TODO apply delays or disconnect based on packet throughput [FlavioJS] - // Note: "click masters" can do 80+ clicks in 10 seconds - - for (pnum = 0; pnum < 3; ++pnum) { // Limit max packets per cycle to 3 (delay packet spammers) [FlavioJS] -- This actually aids packet spammers, but stuff like /str+ gets slow without it [Ai4rei] - // begin main client packet processing loop - - sd = (TBL_PC *)session[fd]->session_data; - if (session[fd]->flag.eof) { - if (sd) { - if (sd->state.autotrade) { - //Disassociate character from the socket connection. - session[fd]->session_data = NULL; - sd->fd = 0; - ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off (using @autotrade).\n", sd->status.name); - } else if (sd->state.active) { - // Player logout display [Valaris] - ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off.\n", sd->status.name); - clif_quitsave(fd, sd); - } else { - //Unusual logout (during log on/off/map-changer procedure) - ShowInfo("Player AID:%d/CID:%d logged off.\n", sd->status.account_id, sd->status.char_id); - map_quit(sd); - } - } else { - ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", ip2str(session[fd]->client_addr, NULL)); - } - do_close(fd); - return 0; - } - - if (RFIFOREST(fd) < 2) - return 0; - - cmd = RFIFOW(fd,0); - - // identify client's packet version - if (sd) { - packet_ver = sd->packet_ver; - } else { - // check authentification packet to know packet version - packet_ver = clif_guess_PacketVer(fd, 0, &err); - if (err) { // failed to identify packet version - ShowInfo("clif_parse: Disconnecting session #%d with unknown packet version%s (p:0x%04x,l:%d).\n", fd, ( - err == 1 ? "" : - err == 2 ? ", possibly for having an invalid account_id" : - err == 3 ? ", possibly for having an invalid char_id." : - /* Uncomment when checks are added in clif_guess_PacketVer. [FlavioJS] - err == 4 ? ", possibly for having an invalid login_id1." : - err == 5 ? ", possibly for having an invalid client_tick." : - */ - err == 6 ? ", possibly for having an invalid sex." : - ". ERROR invalid error code"), cmd, RFIFOREST(fd)); - WFIFOHEAD(fd,packet_len(0x6a)); - WFIFOW(fd,0) = 0x6a; - WFIFOB(fd,2) = 3; // Rejected from Server - WFIFOSET(fd,packet_len(0x6a)); + int cmd, packet_ver, packet_len, err; + TBL_PC* sd; + int pnum; + + //TODO apply delays or disconnect based on packet throughput [FlavioJS] + // Note: "click masters" can do 80+ clicks in 10 seconds + + for( pnum = 0; pnum < 3; ++pnum )// Limit max packets per cycle to 3 (delay packet spammers) [FlavioJS] -- This actually aids packet spammers, but stuff like /str+ gets slow without it [Ai4rei] + { // begin main client packet processing loop + + sd = (TBL_PC *)session[fd]->session_data; + if (session[fd]->flag.eof) { + if (sd) { + if (sd->state.autotrade) { + //Disassociate character from the socket connection. + session[fd]->session_data = NULL; + sd->fd = 0; + ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off (using @autotrade).\n", sd->status.name); + } else + if (sd->state.active) { + // Player logout display [Valaris] + ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off.\n", sd->status.name); + clif_quitsave(fd, sd); + } else { + //Unusual logout (during log on/off/map-changer procedure) + ShowInfo("Player AID:%d/CID:%d logged off.\n", sd->status.account_id, sd->status.char_id); + map_quit(sd); + } + } else { + ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", ip2str(session[fd]->client_addr, NULL)); + } + do_close(fd); + return 0; + } + + if (RFIFOREST(fd) < 2) + return 0; + + cmd = RFIFOW(fd,0); + + // identify client's packet version + if (sd) { + packet_ver = sd->packet_ver; + } else { + // check authentification packet to know packet version + packet_ver = clif_guess_PacketVer(fd, 0, &err); + if( err ) {// failed to identify packet version + ShowInfo("clif_parse: Disconnecting session #%d with unknown packet version%s (p:0x%04x,l:%d).\n", fd, ( + err == 1 ? "" : + err == 2 ? ", possibly for having an invalid account_id" : + err == 3 ? ", possibly for having an invalid char_id." : + /* Uncomment when checks are added in clif_guess_PacketVer. [FlavioJS] + err == 4 ? ", possibly for having an invalid login_id1." : + err == 5 ? ", possibly for having an invalid client_tick." : + */ + err == 6 ? ", possibly for having an invalid sex." : + ". ERROR invalid error code"), cmd, RFIFOREST(fd)); + WFIFOHEAD(fd,packet_len(0x6a)); + WFIFOW(fd,0) = 0x6a; + WFIFOB(fd,2) = 3; // Rejected from Server + WFIFOSET(fd,packet_len(0x6a)); #ifdef DUMP_INVALID_PACKET - ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); + ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif - RFIFOSKIP(fd, RFIFOREST(fd)); - set_eof(fd); - return 0; - } - } + RFIFOSKIP(fd, RFIFOREST(fd)); + set_eof(fd); + return 0; + } + } - // filter out invalid / unsupported packets - if (cmd > MAX_PACKET_DB || packet_db[packet_ver][cmd].len == 0) { - ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", cmd, RFIFOREST(fd), fd); + // filter out invalid / unsupported packets + if (cmd > MAX_PACKET_DB || packet_db[packet_ver][cmd].len == 0) { + ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", cmd, RFIFOREST(fd), fd); #ifdef DUMP_INVALID_PACKET - ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); + ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif - set_eof(fd); - return 0; - } - - // determine real packet length - packet_len = packet_db[packet_ver][cmd].len; - if (packet_len == -1) { // variable-length packet - if (RFIFOREST(fd) < 4) - return 0; - - packet_len = RFIFOW(fd,2); - if (packet_len < 4 || packet_len > 32768) { - ShowWarning("clif_parse: Received packet 0x%04x specifies invalid packet_len (%d), disconnecting session #%d.\n", cmd, packet_len, fd); + set_eof(fd); + return 0; + } + + // determine real packet length + packet_len = packet_db[packet_ver][cmd].len; + if (packet_len == -1) { // variable-length packet + if (RFIFOREST(fd) < 4) + return 0; + + packet_len = RFIFOW(fd,2); + if (packet_len < 4 || packet_len > 32768) { + ShowWarning("clif_parse: Received packet 0x%04x specifies invalid packet_len (%d), disconnecting session #%d.\n", cmd, packet_len, fd); #ifdef DUMP_INVALID_PACKET - ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); + ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif - set_eof(fd); - return 0; - } - } - if ((int)RFIFOREST(fd) < packet_len) - return 0; // not enough data received to form the packet - - if (packet_db[packet_ver][cmd].func == clif_parse_debug) - packet_db[packet_ver][cmd].func(fd, sd); - else if (packet_db[packet_ver][cmd].func != NULL) { - if (!sd && packet_db[packet_ver][cmd].func != clif_parse_WantToConnection) - ; //Only valid packet when there is no session - else if (sd && sd->bl.prev == NULL && packet_db[packet_ver][cmd].func != clif_parse_LoadEndAck) - ; //Only valid packet when player is not on a map - else if (sd && session[sd->fd]->flag.eof) - ; //No more packets accepted - else - packet_db[packet_ver][cmd].func(fd, sd); - } + set_eof(fd); + return 0; + } + } + if ((int)RFIFOREST(fd) < packet_len) + return 0; // not enough data received to form the packet + + if( packet_db[packet_ver][cmd].func == clif_parse_debug ) + packet_db[packet_ver][cmd].func(fd, sd); + else if( packet_db[packet_ver][cmd].func != NULL ) { + if( !sd && packet_db[packet_ver][cmd].func != clif_parse_WantToConnection ) + ; //Only valid packet when there is no session + else + if( sd && sd->bl.prev == NULL && packet_db[packet_ver][cmd].func != clif_parse_LoadEndAck ) + ; //Only valid packet when player is not on a map + else + if( sd && session[sd->fd]->flag.eof ) + ; //No more packets accepted + else + packet_db[packet_ver][cmd].func(fd, sd); + } #ifdef DUMP_UNKNOWN_PACKET - else { - const char *packet_txt = "save/packet.txt"; - FILE *fp; - - if ((fp = fopen(packet_txt , "a")) != NULL) { - if (sd) { - fprintf(fp, "Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); - } else { - fprintf(fp, "Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); - } - - WriteDump(fp, RFIFOP(fd,0), packet_len); - fprintf(fp, "\n"); - fclose(fp); - } else { - ShowError("Failed to write '%s'.\n", packet_txt); - - // Dump on console instead - if (sd) { - ShowDebug("Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); - } else { - ShowDebug("Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); - } - - ShowDump(RFIFOP(fd,0), packet_len); - } - } + else { + const char* packet_txt = "save/packet.txt"; + FILE* fp; + + if( ( fp = fopen( packet_txt , "a" ) ) != NULL ) { + if( sd ) { + fprintf(fp, "Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); + } else { + fprintf(fp, "Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); + } + + WriteDump(fp, RFIFOP(fd,0), packet_len); + fprintf(fp, "\n"); + fclose(fp); + } else { + ShowError("Failed to write '%s'.\n", packet_txt); + + // Dump on console instead + if( sd ) { + ShowDebug("Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); + } else { + ShowDebug("Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); + } + + ShowDump(RFIFOP(fd,0), packet_len); + } + } #endif - RFIFOSKIP(fd, packet_len); + RFIFOSKIP(fd, packet_len); - }; // main loop end + }; // main loop end - return 0; + return 0; } /*========================================== @@ -16305,620 +16497,628 @@ static int clif_parse(int fd) *------------------------------------------*/ static int packetdb_readdb(void) { - FILE *fp; - char line[1024]; - int ln=0; - int cmd,i,j,packet_ver; - int max_cmd=-1; - int skip_ver = 0; - int warned = 0; - char *str[64],*p,*str2[64],*p2,w1[64],w2[64]; - 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, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0040 - 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, + FILE *fp; + char line[1024]; + int ln=0; + int cmd,i,j,packet_ver; + int max_cmd=-1; + int skip_ver = 0; + int warned = 0; + char *str[64],*p,*str2[64],*p2,w1[64],w2[64]; + 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, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0040 + 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, #if PACKETVER <= 20081217 - 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,110, 3, 2, + 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,110, 3, 2, #else - 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,114, 3, 2, + 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,114, 3, 2, #endif #if PACKETVER < 2 - 3, 28, 19, 11, 3, -1, 9, 5, 52, 51, 56, 58, 41, 2, 6, 6, -#elif PACKETVER < 20071106 // 78-7b Lv99 effect for later Kameshima - 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6, + 3, 28, 19, 11, 3, -1, 9, 5, 52, 51, 56, 58, 41, 2, 6, 6, +#elif PACKETVER < 20071106 // 78-7b Lv99 effect for later Kameshima + 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6, #elif PACKETVER <= 20081217 // change in 0x78 and 0x7c - 3, 28, 19, 11, 3, -1, 9, 5, 55, 53, 58, 60, 42, 2, 6, 6, + 3, 28, 19, 11, 3, -1, 9, 5, 55, 53, 58, 60, 42, 2, 6, 6, #else - 3, 28, 19, 11, 3, -1, 9, 5, 55, 53, 58, 60, 44, 2, 6, 6, + 3, 28, 19, 11, 3, -1, 9, 5, 55, 53, 58, 60, 44, 2, 6, 6, #endif - //#0x0080 - 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, + //#0x0080 + 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, #if PACKETVER <= 20100622 - 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6, + 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6, #else - 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 9, 4, 7, 0, -1, 6, // 0xaa changed to 9 (was 7) + 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 9, 4, 7, 0, -1, 6, // 0xaa changed to 9 (was 7) #endif - 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, 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, - //#0x0100 - 2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1, - 10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16, - 6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1, - 6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26, - //#0x0140 - 22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6, - 110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42, - -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182, - 14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1, - //#0x0180 - 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 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, 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, + //#0x0100 + 2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1, + 10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16, + 6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1, + 6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26, + //#0x0140 + 22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6, + 110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42, + -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182, + 14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1, + //#0x0180 + 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6, #if PACKETVER < 1 - 90, 86, 24, 6, 30,102, 8, 4, 8, 4, 14, 10, -1, 6, 2, 6, -#else // 196 comodo icon status display for later - 90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, -1, 6, 2, 6, + 90, 86, 24, 6, 30,102, 8, 4, 8, 4, 14, 10, -1, 6, 2, 6, +#else // 196 comodo icon status display for later + 90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, -1, 6, 2, 6, #endif #if PACKETVER < 20081126 - 3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4, + 3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4, #else // 0x1a2 changed (35->37) - 3, 3, 37, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4, + 3, 3, 37, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4, #endif - 11, 7, -1, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3, - //#0x01C0, Set 0x1d5=-1 - 2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 3, 9, 9, 30, 6, 28, - 8, 14, 10, 35, 6, -1, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6, - 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, - //#0x0200 - 26, -1, 26, 10, 18, 26, 11, 34, 14, 36, 10, 0, 0, -1, 32, 10, // 0x20c change to 0 (was 19) - 22, 0, 26, 26, 42, 6, 6, 2, 2,282,282, 10, 10, -1, -1, 66, + 11, 7, -1, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3, + //#0x01C0, Set 0x1d5=-1 + 2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 3, 9, 9, 30, 6, 28, + 8, 14, 10, 35, 6, -1, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6, + 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, + //#0x0200 + 26, -1, 26, 10, 18, 26, 11, 34, 14, 36, 10, 0, 0, -1, 32, 10, // 0x20c change to 0 (was 19) + 22, 0, 26, 26, 42, 6, 6, 2, 2,282,282, 10, 10, -1, -1, 66, #if PACKETVER < 20071106 - 10, -1, -1, 8, 10, 2,282, 18, 18, 15, 58, 57, 64, 5, 71, 5, + 10, -1, -1, 8, 10, 2,282, 18, 18, 15, 58, 57, 64, 5, 71, 5, #else // 0x22c changed - 10, -1, -1, 8, 10, 2,282, 18, 18, 15, 58, 57, 65, 5, 71, 5, + 10, -1, -1, 8, 10, 2,282, 18, 18, 15, 58, 57, 65, 5, 71, 5, #endif - 12, 26, 9, 11, -1, -1, 10, 2,282, 11, 4, 36, 6, -1, 4, 2, - //#0x0240 - -1, -1, -1, -1, -1, 3, 4, 8, -1, 3, 70, 4, 8, 12, 4, 10, - 3, 32, -1, 3, 3, 5, 5, 8, 2, 3, -1, 6, 4, 6, 4, 6, - 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0280 + 12, 26, 9, 11, -1, -1, 10, 2,282, 11, 4, 36, 6, -1, 4, 2, + //#0x0240 + -1, -1, -1, -1, -1, 3, 4, 8, -1, 3, 70, 4, 8, 12, 4, 10, + 3, 32, -1, 3, 3, 5, 5, 8, 2, 3, -1, 6, 4, 6, 4, 6, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0280 #if PACKETVER < 20070711 - 0, 0, 0, 6, 14, 0, 0, -1, 6, 8, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 14, 0, 0, -1, 6, 8, 18, 0, 0, 0, 0, 0, #else - 0, 0, 0, 6, 14, 0, 0, -1, 10, 12, 18, 0, 0, 0, 0, 0, // 0x288, 0x289 increase by 4 (kafra points) + 0, 0, 0, 6, 14, 0, 0, -1, 10, 12, 18, 0, 0, 0, 0, 0, // 0x288, 0x289 increase by 4 (kafra points) #endif - 0, 4, 0, 70, 10, 0, 0, 0, 8, 6, 27, 80, 0, -1, 0, 0, - 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 85, -1, -1,107, 6, -1, 7, 7, 22,191, 0, 8, 0, 0, 0, 0, - //#0x02C0 - 0, -1, 0, 0, 0, 30, 30, 0, 0, 3, 0, 65, 4, 71, 10, 0, - -1, -1, -1, 0, 29, 0, 6, -1, 10, 10, 3, 0, -1, 32, 6, 36, - 34, 33, 0, 0, 0, 0, 0, 0, -1, -1, -1, 13, 67, 59, 60, 8, - 10, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0300 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0340 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0380 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x03C0 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0400 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 25, - //#0x0440 - 10, 4, -1, 0, 0, 0, 14, 0, 0, 0, 6, 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, 0, 0, 0, 0, 0, 0, - //#0x0480 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x04C0 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0500 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, - //#0x0540 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0580 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x05C0 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0600 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, - //#0x0640 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0680 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x06C0 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0700 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, - //#0x0740 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0780 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x07C0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4, 0, 70, 10, 0, 0, 0, 8, 6, 27, 80, 0, -1, 0, 0, + 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 85, -1, -1,107, 6, -1, 7, 7, 22,191, 0, 8, 0, 0, 0, 0, + //#0x02C0 + 0, -1, 0, 0, 0, 30, 30, 0, 0, 3, 0, 65, 4, 71, 10, 0, + -1, -1, -1, 0, 29, 0, 6, -1, 10, 10, 3, 0, -1, 32, 6, 36, + 34, 33, 0, 0, 0, 0, 0, 0, -1, -1, -1, 13, 67, 59, 60, 8, + 10, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0300 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0340 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0380 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x03C0 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0400 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 25, + //#0x0440 + 10, 4, -1, 0, 0, 0, 14, 0, 0, 0, 6, 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, 0, 0, 0, 0, 0, 0, + //#0x0480 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x04C0 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0500 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, + //#0x0540 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0580 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x05C0 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0600 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, + //#0x0640 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0680 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x06C0 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0700 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, + //#0x0740 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0780 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x07C0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #if PACKETVER < 20090617 - 6, 2, -1, 4, 4, 4, 4, 8, 8,254, 6, 8, 6, 54, 30, 54, + 6, 2, -1, 4, 4, 4, 4, 8, 8,254, 6, 8, 6, 54, 30, 54, #else // 0x7d9 changed - 6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54, + 6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54, #endif - 0, 15, 8, 6, -1, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 25, 0, 0, 26, 0, - //#0x0800 + 0, 15, 8, 6, -1, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 25, 0, 0, 26, 0, + //#0x0800 #if PACKETVER < 20091229 - -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 20, + -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 20, #else // for Party booking ( PACKETVER >= 20091229 ) - -1, -1, 18, 4, 8, 6, 2, 4, 14, 50, 18, 6, 2, 3, 14, 20, + -1, -1, 18, 4, 8, 6, 2, 4, 14, 50, 18, 6, 2, 3, 14, 20, #endif - 3, -1, 8, -1, 86, 2, 6, 6, -1, -1, 4, 10, 10, 0, 0, 0, - 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -1, -1, 3, 2, 66, 5, 2, 12, 6, 0, 0, - //#0x0840 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 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, - //#0x0880 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x08C0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, - 0, 0, 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, - //#0x0900 - 0, 0, 0, 0, 0, 0, 0, 0, 5, 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, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0940 - 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, 0, - 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, - - }; - 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_WisMessage,"wis"}, - {clif_parse_Broadcast,"broadcast"}, - {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_UseSkillToPosMoreInfo,"useskilltoposinfo"}, - {clif_parse_UseSkillMap,"useskillmap"}, - {clif_parse_RequestMemo,"requestmemo"}, - {clif_parse_ProduceMix,"producemix"}, - {clif_parse_Cooking,"cooking"}, - {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_RepairItem,"repairitem"}, - {clif_parse_WeaponRefine,"weaponrefine"}, - {clif_parse_SolveCharName,"solvecharname"}, - {clif_parse_ResetChar,"resetchar"}, - {clif_parse_LocalBroadcast,"localbroadcast"}, - {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_PartyInvite2,"partyinvite2"}, - {clif_parse_ReplyPartyInvite,"replypartyinvite"}, - {clif_parse_ReplyPartyInvite2,"replypartyinvite2"}, - {clif_parse_LeaveParty,"leaveparty"}, - {clif_parse_RemovePartyMember,"removepartymember"}, - {clif_parse_PartyChangeOption,"partychangeoption"}, - {clif_parse_PartyMessage,"partymessage"}, - {clif_parse_PartyChangeLeader,"partychangeleader"}, - {clif_parse_CloseVending,"closevending"}, - {clif_parse_VendingListReq,"vendinglistreq"}, - {clif_parse_PurchaseReq,"purchasereq"}, - {clif_parse_PurchaseReq2,"purchasereq2"}, - {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_GuildExpulsion,"guildexpulsion"}, - {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_GMReqAccountName,"gmreqaccname"}, - {clif_parse_GMKickAll,"killall"}, - {clif_parse_GMRecall,"recall"}, - {clif_parse_GMRecall,"summon"}, - {clif_parse_GM_Monster_Item,"itemmonster"}, - {clif_parse_GMShift,"remove"}, - {clif_parse_GMShift,"shift"}, - {clif_parse_GMChangeMapType,"changemaptype"}, - {clif_parse_GMRc,"rc"}, - {clif_parse_GMRecall2,"recall2"}, - {clif_parse_GMRemove2,"remove2"}, - - {clif_parse_NoviceDoriDori,"sndoridori"}, - {clif_parse_NoviceExplosionSpirits,"snexplosionspirits"}, - {clif_parse_PMIgnore,"wisexin"}, - {clif_parse_PMIgnoreList,"wisexlist"}, - {clif_parse_PMIgnoreAll,"wisall"}, - {clif_parse_FriendsListAdd,"friendslistadd"}, - {clif_parse_FriendsListRemove,"friendslistremove"}, - {clif_parse_FriendsListReply,"friendslistreply"}, - {clif_parse_Blacksmith,"blacksmith"}, - {clif_parse_Alchemist,"alchemist"}, - {clif_parse_Taekwon,"taekwon"}, - {clif_parse_RankingPk,"rankingpk"}, - {clif_parse_FeelSaveOk,"feelsaveok"}, - {clif_parse_debug,"debug"}, - {clif_parse_ChangeHomunculusName,"changehomunculusname"}, - {clif_parse_HomMoveToMaster,"hommovetomaster"}, - {clif_parse_HomMoveTo,"hommoveto"}, - {clif_parse_HomAttack,"homattack"}, - {clif_parse_HomMenu,"hommenu"}, - {clif_parse_StoragePassword,"storagepassword"}, - {clif_parse_Hotkey,"hotkey"}, - {clif_parse_AutoRevive,"autorevive"}, - {clif_parse_Check,"check"}, - {clif_parse_Adopt_request,"adoptrequest"}, - {clif_parse_Adopt_reply,"adoptreply"}, - // MAIL SYSTEM - {clif_parse_Mail_refreshinbox,"mailrefresh"}, - {clif_parse_Mail_read,"mailread"}, - {clif_parse_Mail_getattach,"mailgetattach"}, - {clif_parse_Mail_delete,"maildelete"}, - {clif_parse_Mail_return,"mailreturn"}, - {clif_parse_Mail_setattach,"mailsetattach"}, - {clif_parse_Mail_winopen,"mailwinopen"}, - {clif_parse_Mail_send,"mailsend"}, - // AUCTION SYSTEM - {clif_parse_Auction_search,"auctionsearch"}, - {clif_parse_Auction_buysell,"auctionbuysell"}, - {clif_parse_Auction_setitem,"auctionsetitem"}, - {clif_parse_Auction_cancelreg,"auctioncancelreg"}, - {clif_parse_Auction_register,"auctionregister"}, - {clif_parse_Auction_cancel,"auctioncancel"}, - {clif_parse_Auction_close,"auctionclose"}, - {clif_parse_Auction_bid,"auctionbid"}, - // Quest Log System - {clif_parse_questStateAck,"queststate"}, - {clif_parse_cashshop_buy,"cashshopbuy"}, - {clif_parse_ViewPlayerEquip,"viewplayerequip"}, - {clif_parse_EquipTick,"equiptickbox"}, - {clif_parse_BattleChat,"battlechat"}, - {clif_parse_mercenary_action,"mermenu"}, - {clif_parse_progressbar,"progressbar"}, - {clif_parse_SkillSelectMenu,"skillselectmenu"}, - {clif_parse_ItemListWindowSelected,"itemlistwindowselected"}, + 3, -1, 8, -1, 86, 2, 6, 6, -1, -1, 4, 10, 10, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -1, -1, 3, 2, 66, 5, 2, 12, 6, 0, 0, + //#0x0840 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 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, + //#0x0880 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x08C0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, + 0, 0, 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, + //#0x0900 + 0, 0, 0, 0, 0, 0, 0, 0, 5, 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, 0, 0, 0, 0, 0, 0, 0, 0, + //#0x0940 + 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, 0, + 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, + + }; + 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_WisMessage,"wis"}, + {clif_parse_Broadcast,"broadcast"}, + {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_UseSkillToPosMoreInfo,"useskilltoposinfo"}, + {clif_parse_UseSkillMap,"useskillmap"}, + {clif_parse_RequestMemo,"requestmemo"}, + {clif_parse_ProduceMix,"producemix"}, + {clif_parse_Cooking,"cooking"}, + {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_RepairItem,"repairitem"}, + {clif_parse_WeaponRefine,"weaponrefine"}, + {clif_parse_SolveCharName,"solvecharname"}, + {clif_parse_ResetChar,"resetchar"}, + {clif_parse_LocalBroadcast,"localbroadcast"}, + {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_PartyInvite2,"partyinvite2"}, + {clif_parse_ReplyPartyInvite,"replypartyinvite"}, + {clif_parse_ReplyPartyInvite2,"replypartyinvite2"}, + {clif_parse_LeaveParty,"leaveparty"}, + {clif_parse_RemovePartyMember,"removepartymember"}, + {clif_parse_PartyChangeOption,"partychangeoption"}, + {clif_parse_PartyMessage,"partymessage"}, + {clif_parse_PartyChangeLeader,"partychangeleader"}, + {clif_parse_CloseVending,"closevending"}, + {clif_parse_VendingListReq,"vendinglistreq"}, + {clif_parse_PurchaseReq,"purchasereq"}, + {clif_parse_PurchaseReq2,"purchasereq2"}, + {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_GuildExpulsion,"guildexpulsion"}, + {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_GMReqAccountName,"gmreqaccname"}, + {clif_parse_GMKickAll,"killall"}, + {clif_parse_GMRecall,"recall"}, + {clif_parse_GMRecall,"summon"}, + {clif_parse_GM_Monster_Item,"itemmonster"}, + {clif_parse_GMShift,"remove"}, + {clif_parse_GMShift,"shift"}, + {clif_parse_GMChangeMapType,"changemaptype"}, + {clif_parse_GMRc,"rc"}, + {clif_parse_GMRecall2,"recall2"}, + {clif_parse_GMRemove2,"remove2"}, + + {clif_parse_NoviceDoriDori,"sndoridori"}, + {clif_parse_NoviceExplosionSpirits,"snexplosionspirits"}, + {clif_parse_PMIgnore,"wisexin"}, + {clif_parse_PMIgnoreList,"wisexlist"}, + {clif_parse_PMIgnoreAll,"wisall"}, + {clif_parse_FriendsListAdd,"friendslistadd"}, + {clif_parse_FriendsListRemove,"friendslistremove"}, + {clif_parse_FriendsListReply,"friendslistreply"}, + {clif_parse_Blacksmith,"blacksmith"}, + {clif_parse_Alchemist,"alchemist"}, + {clif_parse_Taekwon,"taekwon"}, + {clif_parse_RankingPk,"rankingpk"}, + {clif_parse_FeelSaveOk,"feelsaveok"}, + {clif_parse_debug,"debug"}, + {clif_parse_ChangeHomunculusName,"changehomunculusname"}, + {clif_parse_HomMoveToMaster,"hommovetomaster"}, + {clif_parse_HomMoveTo,"hommoveto"}, + {clif_parse_HomAttack,"homattack"}, + {clif_parse_HomMenu,"hommenu"}, + {clif_parse_StoragePassword,"storagepassword"}, + {clif_parse_Hotkey,"hotkey"}, + {clif_parse_AutoRevive,"autorevive"}, + {clif_parse_Check,"check"}, + {clif_parse_Adopt_request,"adoptrequest"}, + {clif_parse_Adopt_reply,"adoptreply"}, + // MAIL SYSTEM + {clif_parse_Mail_refreshinbox,"mailrefresh"}, + {clif_parse_Mail_read,"mailread"}, + {clif_parse_Mail_getattach,"mailgetattach"}, + {clif_parse_Mail_delete,"maildelete"}, + {clif_parse_Mail_return,"mailreturn"}, + {clif_parse_Mail_setattach,"mailsetattach"}, + {clif_parse_Mail_winopen,"mailwinopen"}, + {clif_parse_Mail_send,"mailsend"}, + // AUCTION SYSTEM + {clif_parse_Auction_search,"auctionsearch"}, + {clif_parse_Auction_buysell,"auctionbuysell"}, + {clif_parse_Auction_setitem,"auctionsetitem"}, + {clif_parse_Auction_cancelreg,"auctioncancelreg"}, + {clif_parse_Auction_register,"auctionregister"}, + {clif_parse_Auction_cancel,"auctioncancel"}, + {clif_parse_Auction_close,"auctionclose"}, + {clif_parse_Auction_bid,"auctionbid"}, + // Quest Log System + {clif_parse_questStateAck,"queststate"}, + {clif_parse_cashshop_buy,"cashshopbuy"}, + {clif_parse_ViewPlayerEquip,"viewplayerequip"}, + {clif_parse_EquipTick,"equiptickbox"}, + {clif_parse_BattleChat,"battlechat"}, + {clif_parse_mercenary_action,"mermenu"}, + {clif_parse_progressbar,"progressbar"}, + {clif_parse_SkillSelectMenu,"skillselectmenu"}, + {clif_parse_ItemListWindowSelected,"itemlistwindowselected"}, #if PACKETVER >= 20091229 - {clif_parse_PartyBookingRegisterReq,"bookingregreq"}, - {clif_parse_PartyBookingSearchReq,"bookingsearchreq"}, - {clif_parse_PartyBookingUpdateReq,"bookingupdatereq"}, - {clif_parse_PartyBookingDeleteReq,"bookingdelreq"}, + {clif_parse_PartyBookingRegisterReq,"bookingregreq"}, + {clif_parse_PartyBookingSearchReq,"bookingsearchreq"}, + {clif_parse_PartyBookingUpdateReq,"bookingupdatereq"}, + {clif_parse_PartyBookingDeleteReq,"bookingdelreq"}, #endif - {clif_parse_PVPInfo,"pvpinfo"}, - {clif_parse_LessEffect,"lesseffect"}, - // Buying Store - {clif_parse_ReqOpenBuyingStore,"reqopenbuyingstore"}, - {clif_parse_ReqCloseBuyingStore,"reqclosebuyingstore"}, - {clif_parse_ReqClickBuyingStore,"reqclickbuyingstore"}, - {clif_parse_ReqTradeBuyingStore,"reqtradebuyingstore"}, - // Store Search - {clif_parse_SearchStoreInfo,"searchstoreinfo"}, - {clif_parse_SearchStoreInfoNextPage,"searchstoreinfonextpage"}, - {clif_parse_CloseSearchStoreInfo,"closesearchstoreinfo"}, - {clif_parse_SearchStoreInfoListItemClick,"searchstoreinfolistitemclick"}, - /* */ - { clif_parse_MoveItem , "moveitem" }, - {NULL,NULL} - }; - - // initialize packet_db[SERVER] from hardcoded packet_len_table[] values - memset(packet_db,0,sizeof(packet_db)); - for (i = 0; i < ARRAYLENGTH(packet_len_table); ++i) - packet_len(i) = packet_len_table[i]; - - sprintf(line, "%s/packet_db.txt", db_path); - if ((fp=fopen(line,"r"))==NULL) { - ShowFatalError("can't read %s\n", line); - exit(EXIT_FAILURE); - } - - clif_config.packet_db_ver = MAX_PACKET_VER; - packet_ver = MAX_PACKET_VER; // read into packet_db's version by default - while (fgets(line, sizeof(line), fp)) { - ln++; - if (line[0]=='/' && line[1]=='/') - continue; - if (sscanf(line,"%256[^:]: %256[^\r\n]",w1,w2) == 2) { - if (strcmpi(w1,"packet_ver")==0) { - int prev_ver = packet_ver; - skip_ver = 0; - packet_ver = atoi(w2); - if (packet_ver > MAX_PACKET_VER) { - //Check to avoid overflowing. [Skotlex] - if ((warned&1) == 0) - ShowWarning("The packet_db table only has support up to version %d.\n", MAX_PACKET_VER); - warned &= 1; - skip_ver = 1; - } else if (packet_ver < 0) { - if ((warned&2) == 0) - ShowWarning("Negative packet versions are not supported.\n"); - warned &= 2; - skip_ver = 1; - } else if (packet_ver == SERVER) { - if ((warned&4) == 0) - ShowWarning("Packet version %d is reserved for server use only.\n", SERVER); - warned &= 4; - skip_ver = 1; - } - - if (skip_ver) { - ShowWarning("Skipping packet version %d.\n", packet_ver); - packet_ver = prev_ver; - continue; - } - // copy from previous version into new version and continue - // - indicating all following packets should be read into the newer version - memcpy(&packet_db[packet_ver], &packet_db[prev_ver], sizeof(packet_db[0])); - continue; - } else if (strcmpi(w1,"packet_db_ver")==0) { - if (strcmpi(w2,"default")==0) //This is the preferred version. - clif_config.packet_db_ver = MAX_PACKET_VER; - else // to manually set the packet DB version - clif_config.packet_db_ver = cap_value(atoi(w2), 0, MAX_PACKET_VER); - - continue; - } - } - - if (skip_ver != 0) - continue; // Skipping current packet version - - 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 (max_cmd < cmd) - max_cmd = cmd; - if (cmd <= 0 || cmd > MAX_PACKET_DB) - continue; - if (str[1]==NULL) { - ShowError("packet_db: packet len error\n"); - continue; - } - - packet_db[packet_ver][cmd].len = (short)atoi(str[1]); - - if (str[2]==NULL) { - packet_db[packet_ver][cmd].func = NULL; - ln++; - continue; - } - - // look up processing function by name - ARR_FIND(0, ARRAYLENGTH(clif_parse_func), j, clif_parse_func[j].name != NULL && strcmp(str[2],clif_parse_func[j].name)==0); - if (j < ARRAYLENGTH(clif_parse_func)) - packet_db[packet_ver][cmd].func = clif_parse_func[j].func; - - // set the identifying cmd for the packet_db version - if (strcmp(str[2],"wanttoconnection")==0) - clif_config.connect_cmd[packet_ver] = cmd; - - if (str[3]==NULL) { - ShowError("packet_db: packet error\n"); - exit(EXIT_FAILURE); - } - for (j=0,p2=str[3]; p2; j++) { - short k; - 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 - - if (j >= MAX_PACKET_POS) { - ShowError("Too many positions found for packet 0x%04x (max=%d).\n", cmd, MAX_PACKET_POS); - break; - } - - packet_db[packet_ver][cmd].pos[j] = k; - } - } - fclose(fp); - if (max_cmd > MAX_PACKET_DB) { - ShowWarning("Found packets up to 0x%X, ignored 0x%X and above.\n", max_cmd, MAX_PACKET_DB); - ShowWarning("Please increase MAX_PACKET_DB and recompile.\n"); - } - if (!clif_config.connect_cmd[clif_config.packet_db_ver]) { - //Locate the nearest version that we still support. [Skotlex] - for (j = clif_config.packet_db_ver; j >= 0 && !clif_config.connect_cmd[j]; j--); - - clif_config.packet_db_ver = j?j:MAX_PACKET_VER; - } - ShowStatus("Done reading packet database from '"CL_WHITE"%s"CL_RESET"'. Using default packet version: "CL_WHITE"%d"CL_RESET".\n", "packet_db.txt", clif_config.packet_db_ver); - return 0; + {clif_parse_PVPInfo,"pvpinfo"}, + {clif_parse_LessEffect,"lesseffect"}, + // Buying Store + {clif_parse_ReqOpenBuyingStore,"reqopenbuyingstore"}, + {clif_parse_ReqCloseBuyingStore,"reqclosebuyingstore"}, + {clif_parse_ReqClickBuyingStore,"reqclickbuyingstore"}, + {clif_parse_ReqTradeBuyingStore,"reqtradebuyingstore"}, + // Store Search + {clif_parse_SearchStoreInfo,"searchstoreinfo"}, + {clif_parse_SearchStoreInfoNextPage,"searchstoreinfonextpage"}, + {clif_parse_CloseSearchStoreInfo,"closesearchstoreinfo"}, + {clif_parse_SearchStoreInfoListItemClick,"searchstoreinfolistitemclick"}, + /* */ + { clif_parse_MoveItem , "moveitem" }, + {NULL,NULL} + }; + + // initialize packet_db[SERVER] from hardcoded packet_len_table[] values + memset(packet_db,0,sizeof(packet_db)); + for( i = 0; i < ARRAYLENGTH(packet_len_table); ++i ) + packet_len(i) = packet_len_table[i]; + + sprintf(line, "%s/packet_db.txt", db_path); + if( (fp=fopen(line,"r"))==NULL ){ + ShowFatalError("can't read %s\n", line); + exit(EXIT_FAILURE); + } + + clif_config.packet_db_ver = MAX_PACKET_VER; + packet_ver = MAX_PACKET_VER; // read into packet_db's version by default + while( fgets(line, sizeof(line), fp) ) + { + ln++; + if(line[0]=='/' && line[1]=='/') + continue; + if (sscanf(line,"%256[^:]: %256[^\r\n]",w1,w2) == 2) + { + if(strcmpi(w1,"packet_ver")==0) { + int prev_ver = packet_ver; + skip_ver = 0; + packet_ver = atoi(w2); + if ( packet_ver > MAX_PACKET_VER ) + { //Check to avoid overflowing. [Skotlex] + if( (warned&1) == 0 ) + ShowWarning("The packet_db table only has support up to version %d.\n", MAX_PACKET_VER); + warned &= 1; + skip_ver = 1; + } + else if( packet_ver < 0 ) + { + if( (warned&2) == 0 ) + ShowWarning("Negative packet versions are not supported.\n"); + warned &= 2; + skip_ver = 1; + } + else if( packet_ver == SERVER ) + { + if( (warned&4) == 0 ) + ShowWarning("Packet version %d is reserved for server use only.\n", SERVER); + warned &= 4; + skip_ver = 1; + } + + if( skip_ver ) + { + ShowWarning("Skipping packet version %d.\n", packet_ver); + packet_ver = prev_ver; + continue; + } + // copy from previous version into new version and continue + // - indicating all following packets should be read into the newer version + memcpy(&packet_db[packet_ver], &packet_db[prev_ver], sizeof(packet_db[0])); + continue; + } else if(strcmpi(w1,"packet_db_ver")==0) { + if(strcmpi(w2,"default")==0) //This is the preferred version. + clif_config.packet_db_ver = MAX_PACKET_VER; + else // to manually set the packet DB version + clif_config.packet_db_ver = cap_value(atoi(w2), 0, MAX_PACKET_VER); + + continue; + } + } + + if( skip_ver != 0 ) + continue; // Skipping current packet version + + 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(max_cmd < cmd) + max_cmd = cmd; + if(cmd <= 0 || cmd > MAX_PACKET_DB) + continue; + if(str[1]==NULL){ + ShowError("packet_db: packet len error\n"); + continue; + } + + packet_db[packet_ver][cmd].len = (short)atoi(str[1]); + + if(str[2]==NULL){ + packet_db[packet_ver][cmd].func = NULL; + ln++; + continue; + } + + // look up processing function by name + ARR_FIND( 0, ARRAYLENGTH(clif_parse_func), j, clif_parse_func[j].name != NULL && strcmp(str[2],clif_parse_func[j].name)==0 ); + if( j < ARRAYLENGTH(clif_parse_func) ) + packet_db[packet_ver][cmd].func = clif_parse_func[j].func; + + // set the identifying cmd for the packet_db version + if (strcmp(str[2],"wanttoconnection")==0) + clif_config.connect_cmd[packet_ver] = cmd; + + if(str[3]==NULL){ + ShowError("packet_db: packet error\n"); + exit(EXIT_FAILURE); + } + for(j=0,p2=str[3];p2;j++){ + short k; + 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 + + if( j >= MAX_PACKET_POS ) + { + ShowError("Too many positions found for packet 0x%04x (max=%d).\n", cmd, MAX_PACKET_POS); + break; + } + + packet_db[packet_ver][cmd].pos[j] = k; + } + } + fclose(fp); + if(max_cmd > MAX_PACKET_DB) + { + ShowWarning("Found packets up to 0x%X, ignored 0x%X and above.\n", max_cmd, MAX_PACKET_DB); + ShowWarning("Please increase MAX_PACKET_DB and recompile.\n"); + } + if (!clif_config.connect_cmd[clif_config.packet_db_ver]) + { //Locate the nearest version that we still support. [Skotlex] + for(j = clif_config.packet_db_ver; j >= 0 && !clif_config.connect_cmd[j]; j--); + + clif_config.packet_db_ver = j?j:MAX_PACKET_VER; + } + ShowStatus("Done reading packet database from '"CL_WHITE"%s"CL_RESET"'. Using default packet version: "CL_WHITE"%d"CL_RESET".\n", "packet_db.txt", clif_config.packet_db_ver); + return 0; } /*========================================== * *------------------------------------------*/ -int do_init_clif(void) -{ - const char *colors[COLOR_MAX] = { "0xFF0000" }; - int i; - /** - * Setup Color Table (saves unnecessary load of strtoul on every call) - **/ - for (i = 0; i < COLOR_MAX; i++) { - color_table[i] = strtoul(colors[i],NULL,0); - color_table[i] = (color_table[i] & 0x0000FF) << 16 | (color_table[i] & 0x00FF00) | (color_table[i] & 0xFF0000) >> 16;//RGB to BGR - } +int do_init_clif(void) { + const char* colors[COLOR_MAX] = { "0xFF0000" }; + int i; + /** + * Setup Color Table (saves unnecessary load of strtoul on every call) + **/ + for(i = 0; i < COLOR_MAX; i++) { + color_table[i] = strtoul(colors[i],NULL,0); + color_table[i] = (color_table[i] & 0x0000FF) << 16 | (color_table[i] & 0x00FF00) | (color_table[i] & 0xFF0000) >> 16;//RGB to BGR + } - clif_config.packet_db_ver = -1; // the main packet version of the DB - memset(clif_config.connect_cmd, 0, sizeof(clif_config.connect_cmd)); //The default connect command will be determined after reading the packet_db [Skotlex] + clif_config.packet_db_ver = -1; // the main packet version of the DB + memset(clif_config.connect_cmd, 0, sizeof(clif_config.connect_cmd)); //The default connect command will be determined after reading the packet_db [Skotlex] - memset(packet_db,0,sizeof(packet_db)); - //Using the packet_db file is the only way to set up packets now [Skotlex] - packetdb_readdb(); + memset(packet_db,0,sizeof(packet_db)); + //Using the packet_db file is the only way to set up packets now [Skotlex] + packetdb_readdb(); - set_defaultparse(clif_parse); - if (make_listen_bind(bind_ip,map_port) == -1) { - ShowFatalError("can't bind game port\n"); - exit(EXIT_FAILURE); - } + set_defaultparse(clif_parse); + if( make_listen_bind(bind_ip,map_port) == -1 ) { + ShowFatalError("can't bind game port\n"); + exit(EXIT_FAILURE); + } - add_timer_func_list(clif_clearunit_delayed_sub, "clif_clearunit_delayed_sub"); - add_timer_func_list(clif_delayquit, "clif_delayquit"); + add_timer_func_list(clif_clearunit_delayed_sub, "clif_clearunit_delayed_sub"); + add_timer_func_list(clif_delayquit, "clif_delayquit"); - delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR); + delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR); - return 0; + return 0; } -void do_final_clif(void) -{ - ers_destroy(delay_clearunit_ers); +void do_final_clif(void) { + ers_destroy(delay_clearunit_ers); } diff --git a/src/map/clif.h b/src/map/clif.h index cde892638..0948a12c1 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -29,17 +29,17 @@ struct quest; struct party_booking_ad_info; #include <stdarg.h> -enum { - // packet DB - MAX_PACKET_DB = 0xA00, - MAX_PACKET_VER = 30, - MAX_PACKET_POS = 20, +enum +{// packet DB + MAX_PACKET_DB = 0xA00, + MAX_PACKET_VER = 30, + MAX_PACKET_POS = 20, }; struct s_packet_db { - short len; - void (*func)(int, struct map_session_data *); - short pos[MAX_PACKET_POS]; + short len; + void (*func)(int, struct map_session_data *); + short pos[MAX_PACKET_POS]; }; // packet_db[SERVER] is reserved for server use @@ -49,271 +49,273 @@ extern struct s_packet_db packet_db[MAX_PACKET_VER+1][MAX_PACKET_DB+1]; // local define typedef enum send_target { - ALL_CLIENT, - ALL_SAMEMAP, - AREA, // area - AREA_WOS, // area, without self - AREA_WOC, // area, without chatrooms - AREA_WOSC, // area, without own chatroom - AREA_CHAT_WOC, // hearable area, without chatrooms - CHAT, // current chatroom - CHAT_WOS, // current chatroom, without self - PARTY, - PARTY_WOS, - PARTY_SAMEMAP, - PARTY_SAMEMAP_WOS, - PARTY_AREA, - PARTY_AREA_WOS, - GUILD, - GUILD_WOS, - GUILD_SAMEMAP, - GUILD_SAMEMAP_WOS, - GUILD_AREA, - GUILD_AREA_WOS, - GUILD_NOBG, - DUEL, - DUEL_WOS, - CHAT_MAINCHAT, // everyone on main chat - SELF, - BG, // BattleGround System - BG_WOS, - BG_SAMEMAP, - BG_SAMEMAP_WOS, - BG_AREA, - BG_AREA_WOS, + ALL_CLIENT, + ALL_SAMEMAP, + AREA, // area + AREA_WOS, // area, without self + AREA_WOC, // area, without chatrooms + AREA_WOSC, // area, without own chatroom + AREA_CHAT_WOC, // hearable area, without chatrooms + CHAT, // current chatroom + CHAT_WOS, // current chatroom, without self + PARTY, + PARTY_WOS, + PARTY_SAMEMAP, + PARTY_SAMEMAP_WOS, + PARTY_AREA, + PARTY_AREA_WOS, + GUILD, + GUILD_WOS, + GUILD_SAMEMAP, + GUILD_SAMEMAP_WOS, + GUILD_AREA, + GUILD_AREA_WOS, + GUILD_NOBG, + DUEL, + DUEL_WOS, + CHAT_MAINCHAT, // everyone on main chat + SELF, + BG, // BattleGround System + BG_WOS, + BG_SAMEMAP, + BG_SAMEMAP_WOS, + BG_AREA, + BG_AREA_WOS, } send_target; -typedef enum emotion_type { - E_GASP = 0, // /! - E_WHAT, // /? - E_HO, - E_LV, - E_SWT, - E_IC, - E_AN, - E_AG, - E_CASH, // /$ - E_DOTS, // /... - E_SCISSORS, // /gawi --- 10 - E_ROCK, // /bawi - E_PAPER, // /bo - E_KOREA, - E_LV2, - E_THX, - E_WAH, - E_SRY, - E_HEH, - E_SWT2, - E_HMM, // --- 20 - E_NO1, - E_NO, // /?? - E_OMG, - E_OH, - E_X, - E_HLP, - E_GO, - E_SOB, - E_GG, - E_KIS, // --- 30 - E_KIS2, - E_PIF, - E_OK, - E_MUTE, // red /... used for muted characters - E_INDONESIA, - E_BZZ, // /bzz, /stare - E_RICE, - E_AWSM, // /awsm, /cool - E_MEH, - E_SHY, // --- 40 - E_PAT, // /pat, /goodboy - E_MP, // /mp, /sptime - E_SLUR, - E_COM, // /com, /comeon - E_YAWN, // /yawn, /sleepy - E_GRAT, // /grat, /congrats - E_HP, // /hp, /hptime - E_PHILIPPINES, - E_MALAYSIA, - E_SINGAPORE, // --- 50 - E_BRAZIL, - E_FLASH, // /fsh - E_SPIN, // /spin - E_SIGH, - E_DUM, // /dum - E_LOUD, // /crwd - E_OTL, // /otl, /desp - E_DICE1, - E_DICE2, - E_DICE3, // --- 60 - E_DICE4, - E_DICE5, - E_DICE6, - E_INDIA, - E_LUV, // /love - E_RUSSIA, - E_VIRGIN, - E_MOBILE, - E_MAIL, - E_CHINESE, // --- 70 - E_ANTENNA1, - E_ANTENNA2, - E_ANTENNA3, - E_HUM, - E_ABS, - E_OOPS, - E_SPIT, - E_ENE, - E_PANIC, - E_WHISP, // --- 80 - E_YUT1, - E_YUT2, - E_YUT3, - E_YUT4, - E_YUT5, - E_YUT6, - E_YUT7, - // - E_MAX +typedef enum emotion_type +{ + E_GASP = 0, // /! + E_WHAT, // /? + E_HO, + E_LV, + E_SWT, + E_IC, + E_AN, + E_AG, + E_CASH, // /$ + E_DOTS, // /... + E_SCISSORS, // /gawi --- 10 + E_ROCK, // /bawi + E_PAPER, // /bo + E_KOREA, + E_LV2, + E_THX, + E_WAH, + E_SRY, + E_HEH, + E_SWT2, + E_HMM, // --- 20 + E_NO1, + E_NO, // /?? + E_OMG, + E_OH, + E_X, + E_HLP, + E_GO, + E_SOB, + E_GG, + E_KIS, // --- 30 + E_KIS2, + E_PIF, + E_OK, + E_MUTE, // red /... used for muted characters + E_INDONESIA, + E_BZZ, // /bzz, /stare + E_RICE, + E_AWSM, // /awsm, /cool + E_MEH, + E_SHY, // --- 40 + E_PAT, // /pat, /goodboy + E_MP, // /mp, /sptime + E_SLUR, + E_COM, // /com, /comeon + E_YAWN, // /yawn, /sleepy + E_GRAT, // /grat, /congrats + E_HP, // /hp, /hptime + E_PHILIPPINES, + E_MALAYSIA, + E_SINGAPORE, // --- 50 + E_BRAZIL, + E_FLASH, // /fsh + E_SPIN, // /spin + E_SIGH, + E_DUM, // /dum + E_LOUD, // /crwd + E_OTL, // /otl, /desp + E_DICE1, + E_DICE2, + E_DICE3, // --- 60 + E_DICE4, + E_DICE5, + E_DICE6, + E_INDIA, + E_LUV, // /love + E_RUSSIA, + E_VIRGIN, + E_MOBILE, + E_MAIL, + E_CHINESE, // --- 70 + E_ANTENNA1, + E_ANTENNA2, + E_ANTENNA3, + E_HUM, + E_ABS, + E_OOPS, + E_SPIT, + E_ENE, + E_PANIC, + E_WHISP, // --- 80 + E_YUT1, + E_YUT2, + E_YUT3, + E_YUT4, + E_YUT5, + E_YUT6, + E_YUT7, + // + E_MAX } emotion_type; -typedef enum clr_type { - CLR_OUTSIGHT = 0, - CLR_DEAD, - CLR_RESPAWN, - CLR_TELEPORT, - CLR_TRICKDEAD, +typedef enum clr_type +{ + CLR_OUTSIGHT = 0, + CLR_DEAD, + CLR_RESPAWN, + CLR_TELEPORT, + CLR_TRICKDEAD, } clr_type; -enum map_property { - // clif_map_property - MAPPROPERTY_NOTHING = 0, - MAPPROPERTY_FREEPVPZONE = 1, - MAPPROPERTY_EVENTPVPZONE = 2, - MAPPROPERTY_AGITZONE = 3, - MAPPROPERTY_PKSERVERZONE = 4, // message "You are in a PK area. Please beware of sudden attacks." in color 0x9B9BFF (light red) - MAPPROPERTY_PVPSERVERZONE = 5, - MAPPROPERTY_DENYSKILLZONE = 6, +enum map_property +{// clif_map_property + MAPPROPERTY_NOTHING = 0, + MAPPROPERTY_FREEPVPZONE = 1, + MAPPROPERTY_EVENTPVPZONE = 2, + MAPPROPERTY_AGITZONE = 3, + MAPPROPERTY_PKSERVERZONE = 4, // message "You are in a PK area. Please beware of sudden attacks." in color 0x9B9BFF (light red) + MAPPROPERTY_PVPSERVERZONE = 5, + MAPPROPERTY_DENYSKILLZONE = 6, }; -enum map_type { - // clif_map_type - MAPTYPE_VILLAGE = 0, - MAPTYPE_VILLAGE_IN = 1, - MAPTYPE_FIELD = 2, - MAPTYPE_DUNGEON = 3, - MAPTYPE_ARENA = 4, - MAPTYPE_PENALTY_FREEPKZONE = 5, - MAPTYPE_NOPENALTY_FREEPKZONE = 6, - MAPTYPE_EVENT_GUILDWAR = 7, - MAPTYPE_AGIT = 8, - MAPTYPE_DUNGEON2 = 9, - MAPTYPE_DUNGEON3 = 10, - MAPTYPE_PKSERVER = 11, - MAPTYPE_PVPSERVER = 12, - MAPTYPE_DENYSKILL = 13, - MAPTYPE_TURBOTRACK = 14, - MAPTYPE_JAIL = 15, - MAPTYPE_MONSTERTRACK = 16, - MAPTYPE_PORINGBATTLE = 17, - MAPTYPE_AGIT_SIEGEV15 = 18, - MAPTYPE_BATTLEFIELD = 19, - MAPTYPE_PVP_TOURNAMENT = 20, - //Map types 21 - 24 not used. - MAPTYPE_SIEGE_LOWLEVEL = 25, - //Map types 26 - 28 remains opens for future types. - MAPTYPE_UNUSED = 29, +enum map_type +{// clif_map_type + MAPTYPE_VILLAGE = 0, + MAPTYPE_VILLAGE_IN = 1, + MAPTYPE_FIELD = 2, + MAPTYPE_DUNGEON = 3, + MAPTYPE_ARENA = 4, + MAPTYPE_PENALTY_FREEPKZONE = 5, + MAPTYPE_NOPENALTY_FREEPKZONE = 6, + MAPTYPE_EVENT_GUILDWAR = 7, + MAPTYPE_AGIT = 8, + MAPTYPE_DUNGEON2 = 9, + MAPTYPE_DUNGEON3 = 10, + MAPTYPE_PKSERVER = 11, + MAPTYPE_PVPSERVER = 12, + MAPTYPE_DENYSKILL = 13, + MAPTYPE_TURBOTRACK = 14, + MAPTYPE_JAIL = 15, + MAPTYPE_MONSTERTRACK = 16, + MAPTYPE_PORINGBATTLE = 17, + MAPTYPE_AGIT_SIEGEV15 = 18, + MAPTYPE_BATTLEFIELD = 19, + MAPTYPE_PVP_TOURNAMENT = 20, + //Map types 21 - 24 not used. + MAPTYPE_SIEGE_LOWLEVEL = 25, + //Map types 26 - 28 remains opens for future types. + MAPTYPE_UNUSED = 29, }; -enum useskill_fail_cause { - // clif_skill_fail - USESKILL_FAIL_LEVEL = 0, - USESKILL_FAIL_SP_INSUFFICIENT = 1, - USESKILL_FAIL_HP_INSUFFICIENT = 2, - USESKILL_FAIL_STUFF_INSUFFICIENT = 3, - USESKILL_FAIL_SKILLINTERVAL = 4, - USESKILL_FAIL_MONEY = 5, - USESKILL_FAIL_THIS_WEAPON = 6, - USESKILL_FAIL_REDJAMSTONE = 7, - USESKILL_FAIL_BLUEJAMSTONE = 8, - USESKILL_FAIL_WEIGHTOVER = 9, - USESKILL_FAIL = 10, - USESKILL_FAIL_TOTARGET = 11, - USESKILL_FAIL_ANCILLA_NUMOVER = 12, - USESKILL_FAIL_HOLYWATER = 13, - USESKILL_FAIL_ANCILLA = 14, - USESKILL_FAIL_DUPLICATE_RANGEIN = 15, - USESKILL_FAIL_NEED_OTHER_SKILL = 16, - USESKILL_FAIL_NEED_HELPER = 17, - USESKILL_FAIL_INVALID_DIR = 18, - USESKILL_FAIL_SUMMON = 19, - USESKILL_FAIL_SUMMON_NONE = 20, - USESKILL_FAIL_IMITATION_SKILL_NONE = 21, - USESKILL_FAIL_DUPLICATE = 22, - USESKILL_FAIL_CONDITION = 23, - USESKILL_FAIL_PAINTBRUSH = 24, - USESKILL_FAIL_DRAGON = 25, - USESKILL_FAIL_POS = 26, - USESKILL_FAIL_HELPER_SP_INSUFFICIENT = 27, - USESKILL_FAIL_NEER_WALL = 28, - USESKILL_FAIL_NEED_EXP_1PERCENT = 29, - USESKILL_FAIL_CHORUS_SP_INSUFFICIENT = 30, - USESKILL_FAIL_GC_WEAPONBLOCKING = 31, - USESKILL_FAIL_GC_POISONINGWEAPON = 32, - USESKILL_FAIL_MADOGEAR = 33, - USESKILL_FAIL_NEED_EQUIPMENT_KUNAI = 34, - USESKILL_FAIL_TOTARGET_PLAYER = 35, - USESKILL_FAIL_SIZE = 36, - USESKILL_FAIL_CANONBALL = 37, - //XXX_USESKILL_FAIL_II_MADOGEAR_ACCELERATION = 38, - //XXX_USESKILL_FAIL_II_MADOGEAR_HOVERING_BOOSTER = 39, - USESKILL_FAIL_MADOGEAR_HOVERING = 40, - //XXX_USESKILL_FAIL_II_MADOGEAR_SELFDESTRUCTION_DEVICE = 41, - //XXX_USESKILL_FAIL_II_MADOGEAR_SHAPESHIFTER = 42, - USESKILL_FAIL_GUILLONTINE_POISON = 43, - //XXX_USESKILL_FAIL_II_MADOGEAR_COOLING_DEVICE = 44, - //XXX_USESKILL_FAIL_II_MADOGEAR_MAGNETICFIELD_GENERATOR = 45, - //XXX_USESKILL_FAIL_II_MADOGEAR_BARRIER_GENERATOR = 46, - //XXX_USESKILL_FAIL_II_MADOGEAR_OPTICALCAMOUFLAGE_GENERATOR = 47, - //XXX_USESKILL_FAIL_II_MADOGEAR_REPAIRKIT = 48, - //XXX_USESKILL_FAIL_II_MONKEY_SPANNER = 49, - USESKILL_FAIL_MADOGEAR_RIDE = 50, - USESKILL_FAIL_SPELLBOOK = 51, - USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP = 52, - USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT = 53, - USESKILL_FAIL_SPELLBOOK_READING = 54, - //XXX_USESKILL_FAIL_II_FACE_PAINTS = 55, - //XXX_USESKILL_FAIL_II_MAKEUP_BRUSH = 56, - USESKILL_FAIL_CART = 57, - //XXX_USESKILL_FAIL_II_THORNS_SEED = 58, - //XXX_USESKILL_FAIL_II_BLOOD_SUCKER_SEED = 59, - USESKILL_FAIL_NO_MORE_SPELL = 60, - //XXX_USESKILL_FAIL_II_BOMB_MUSHROOM_SPORE = 61, - //XXX_USESKILL_FAIL_II_GASOLINE_BOOMB = 62, - //XXX_USESKILL_FAIL_II_OIL_BOTTLE = 63, - //XXX_USESKILL_FAIL_II_EXPLOSION_POWDER = 64, - //XXX_USESKILL_FAIL_II_SMOKE_POWDER = 65, - //XXX_USESKILL_FAIL_II_TEAR_GAS = 66, - //XXX_USESKILL_FAIL_II_HYDROCHLORIC_ACID_BOTTLE = 67, - //XXX_USESKILL_FAIL_II_HELLS_PLANT_BOTTLE = 68, - //XXX_USESKILL_FAIL_II_MANDRAGORA_FLOWERPOT = 69, - USESKILL_FAIL_MANUAL_NOTIFY = 70, - USESKILL_FAIL_NEED_ITEM = 71, - USESKILL_FAIL_NEED_EQUIPMENT = 72, - USESKILL_FAIL_COMBOSKILL = 73, - USESKILL_FAIL_SPIRITS = 74, - USESKILL_FAIL_EXPLOSIONSPIRITS = 75, - USESKILL_FAIL_HP_TOOMANY = 76, - USESKILL_FAIL_NEED_ROYAL_GUARD_BANDING = 77, - USESKILL_FAIL_NEED_EQUIPPED_WEAPON_CLASS = 78, - USESKILL_FAIL_EL_SUMMON = 79, - USESKILL_FAIL_RELATIONGRADE = 80, - USESKILL_FAIL_STYLE_CHANGE_FIGHTER = 81, - USESKILL_FAIL_STYLE_CHANGE_GRAPPLER = 82, - USESKILL_FAIL_THERE_ARE_NPC_AROUND = 83, +enum useskill_fail_cause +{// clif_skill_fail + USESKILL_FAIL_LEVEL = 0, + USESKILL_FAIL_SP_INSUFFICIENT = 1, + USESKILL_FAIL_HP_INSUFFICIENT = 2, + USESKILL_FAIL_STUFF_INSUFFICIENT = 3, + USESKILL_FAIL_SKILLINTERVAL = 4, + USESKILL_FAIL_MONEY = 5, + USESKILL_FAIL_THIS_WEAPON = 6, + USESKILL_FAIL_REDJAMSTONE = 7, + USESKILL_FAIL_BLUEJAMSTONE = 8, + USESKILL_FAIL_WEIGHTOVER = 9, + USESKILL_FAIL = 10, + USESKILL_FAIL_TOTARGET = 11, + USESKILL_FAIL_ANCILLA_NUMOVER = 12, + USESKILL_FAIL_HOLYWATER = 13, + USESKILL_FAIL_ANCILLA = 14, + USESKILL_FAIL_DUPLICATE_RANGEIN = 15, + USESKILL_FAIL_NEED_OTHER_SKILL = 16, + USESKILL_FAIL_NEED_HELPER = 17, + USESKILL_FAIL_INVALID_DIR = 18, + USESKILL_FAIL_SUMMON = 19, + USESKILL_FAIL_SUMMON_NONE = 20, + USESKILL_FAIL_IMITATION_SKILL_NONE = 21, + USESKILL_FAIL_DUPLICATE = 22, + USESKILL_FAIL_CONDITION = 23, + USESKILL_FAIL_PAINTBRUSH = 24, + USESKILL_FAIL_DRAGON = 25, + USESKILL_FAIL_POS = 26, + USESKILL_FAIL_HELPER_SP_INSUFFICIENT = 27, + USESKILL_FAIL_NEER_WALL = 28, + USESKILL_FAIL_NEED_EXP_1PERCENT = 29, + USESKILL_FAIL_CHORUS_SP_INSUFFICIENT = 30, + USESKILL_FAIL_GC_WEAPONBLOCKING = 31, + USESKILL_FAIL_GC_POISONINGWEAPON = 32, + USESKILL_FAIL_MADOGEAR = 33, + USESKILL_FAIL_NEED_EQUIPMENT_KUNAI = 34, + USESKILL_FAIL_TOTARGET_PLAYER = 35, + USESKILL_FAIL_SIZE = 36, + USESKILL_FAIL_CANONBALL = 37, + //XXX_USESKILL_FAIL_II_MADOGEAR_ACCELERATION = 38, + //XXX_USESKILL_FAIL_II_MADOGEAR_HOVERING_BOOSTER = 39, + USESKILL_FAIL_MADOGEAR_HOVERING = 40, + //XXX_USESKILL_FAIL_II_MADOGEAR_SELFDESTRUCTION_DEVICE = 41, + //XXX_USESKILL_FAIL_II_MADOGEAR_SHAPESHIFTER = 42, + USESKILL_FAIL_GUILLONTINE_POISON = 43, + //XXX_USESKILL_FAIL_II_MADOGEAR_COOLING_DEVICE = 44, + //XXX_USESKILL_FAIL_II_MADOGEAR_MAGNETICFIELD_GENERATOR = 45, + //XXX_USESKILL_FAIL_II_MADOGEAR_BARRIER_GENERATOR = 46, + //XXX_USESKILL_FAIL_II_MADOGEAR_OPTICALCAMOUFLAGE_GENERATOR = 47, + //XXX_USESKILL_FAIL_II_MADOGEAR_REPAIRKIT = 48, + //XXX_USESKILL_FAIL_II_MONKEY_SPANNER = 49, + USESKILL_FAIL_MADOGEAR_RIDE = 50, + USESKILL_FAIL_SPELLBOOK = 51, + USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP = 52, + USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT = 53, + USESKILL_FAIL_SPELLBOOK_READING = 54, + //XXX_USESKILL_FAIL_II_FACE_PAINTS = 55, + //XXX_USESKILL_FAIL_II_MAKEUP_BRUSH = 56, + USESKILL_FAIL_CART = 57, + //XXX_USESKILL_FAIL_II_THORNS_SEED = 58, + //XXX_USESKILL_FAIL_II_BLOOD_SUCKER_SEED = 59, + USESKILL_FAIL_NO_MORE_SPELL = 60, + //XXX_USESKILL_FAIL_II_BOMB_MUSHROOM_SPORE = 61, + //XXX_USESKILL_FAIL_II_GASOLINE_BOOMB = 62, + //XXX_USESKILL_FAIL_II_OIL_BOTTLE = 63, + //XXX_USESKILL_FAIL_II_EXPLOSION_POWDER = 64, + //XXX_USESKILL_FAIL_II_SMOKE_POWDER = 65, + //XXX_USESKILL_FAIL_II_TEAR_GAS = 66, + //XXX_USESKILL_FAIL_II_HYDROCHLORIC_ACID_BOTTLE = 67, + //XXX_USESKILL_FAIL_II_HELLS_PLANT_BOTTLE = 68, + //XXX_USESKILL_FAIL_II_MANDRAGORA_FLOWERPOT = 69, + USESKILL_FAIL_MANUAL_NOTIFY = 70, + USESKILL_FAIL_NEED_ITEM = 71, + USESKILL_FAIL_NEED_EQUIPMENT = 72, + USESKILL_FAIL_COMBOSKILL = 73, + USESKILL_FAIL_SPIRITS = 74, + USESKILL_FAIL_EXPLOSIONSPIRITS = 75, + USESKILL_FAIL_HP_TOOMANY = 76, + USESKILL_FAIL_NEED_ROYAL_GUARD_BANDING = 77, + USESKILL_FAIL_NEED_EQUIPPED_WEAPON_CLASS = 78, + USESKILL_FAIL_EL_SUMMON = 79, + USESKILL_FAIL_RELATIONGRADE = 80, + USESKILL_FAIL_STYLE_CHANGE_FIGHTER = 81, + USESKILL_FAIL_STYLE_CHANGE_GRAPPLER = 82, + USESKILL_FAIL_THERE_ARE_NPC_AROUND = 83, }; -int clif_setip(const char *ip); -void clif_setbindip(const char *ip); +int clif_setip(const char* ip); +void clif_setbindip(const char* ip); void clif_setport(uint16 port); uint32 clif_getip(void); @@ -324,100 +326,100 @@ void clif_authok(struct map_session_data *sd); void clif_authrefuse(int fd, uint8 error_code); void clif_authfail_fd(int fd, int type); void clif_charselectok(int id, uint8 ok); -void clif_dropflooritem(struct flooritem_data *fitem); +void clif_dropflooritem(struct flooritem_data* fitem); void clif_clearflooritem(struct flooritem_data *fitem, int fd); void clif_clearunit_single(int id, clr_type type, int fd); -void clif_clearunit_area(struct block_list *bl, clr_type type); -void clif_clearunit_delayed(struct block_list *bl, clr_type type, unsigned int tick); -int clif_spawn(struct block_list *bl); //area -void clif_walkok(struct map_session_data *sd); // self +void clif_clearunit_area(struct block_list* bl, clr_type type); +void clif_clearunit_delayed(struct block_list* bl, clr_type type, unsigned int tick); +int clif_spawn(struct block_list *bl); //area +void clif_walkok(struct map_session_data *sd); // self void clif_move(struct unit_data *ud); //area -void clif_changemap(struct map_session_data *sd, short map, int x, int y); //self -void clif_changemapserver(struct map_session_data *sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port); //self +void clif_changemap(struct map_session_data *sd, short map, int x, int y); //self +void clif_changemapserver(struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port); //self void clif_blown(struct block_list *bl); // area void clif_slide(struct block_list *bl, int x, int y); // area -void clif_fixpos(struct block_list *bl); // area -void clif_npcbuysell(struct map_session_data *sd, int id); //self -void clif_buylist(struct map_session_data *sd, struct npc_data *nd); //self -void clif_selllist(struct map_session_data *sd); //self -void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes); //self -void clif_scriptnext(struct map_session_data *sd,int npcid); //self -void clif_scriptclose(struct map_session_data *sd, int npcid); //self -void clif_scriptmenu(struct map_session_data *sd, int npcid, const char *mes); //self -void clif_scriptinput(struct map_session_data *sd, int npcid); //self -void clif_scriptinputstr(struct map_session_data *sd, int npcid); // self -void clif_cutin(struct map_session_data *sd, const char *image, int type); //self -void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, int y, int id, int color); //self +void clif_fixpos(struct block_list *bl); // area +void clif_npcbuysell(struct map_session_data* sd, int id); //self +void clif_buylist(struct map_session_data *sd, struct npc_data *nd); //self +void clif_selllist(struct map_session_data *sd); //self +void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes); //self +void clif_scriptnext(struct map_session_data *sd,int npcid); //self +void clif_scriptclose(struct map_session_data *sd, int npcid); //self +void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes); //self +void clif_scriptinput(struct map_session_data *sd, int npcid); //self +void clif_scriptinputstr(struct map_session_data *sd, int npcid); // self +void clif_cutin(struct map_session_data* sd, const char* image, int type); //self +void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, int y, int id, int color); //self void clif_additem(struct map_session_data *sd, int n, int amount, int fail); // self -void clif_dropitem(struct map_session_data *sd,int n,int amount); //self +void clif_dropitem(struct map_session_data *sd,int n,int amount); //self void clif_delitem(struct map_session_data *sd,int n,int amount, short reason); //self -void clif_updatestatus(struct map_session_data *sd,int type); //self -void clif_changestatus(struct map_session_data *sd,int type,int val); //area -int clif_damage(struct block_list *src, struct block_list *dst, unsigned int tick, int sdelay, int ddelay, int damage, int div, int type, int damage2); // area -void clif_takeitem(struct block_list *src, struct block_list *dst); -void clif_sitting(struct block_list *bl); -void clif_standing(struct block_list *bl); -void clif_changelook(struct block_list *bl,int type,int val); // area +void clif_updatestatus(struct map_session_data *sd,int type); //self +void clif_changestatus(struct map_session_data* sd,int type,int val); //area +int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int damage, int div, int type, int damage2); // area +void clif_takeitem(struct block_list* src, struct block_list* dst); +void clif_sitting(struct block_list* bl); +void clif_standing(struct block_list* bl); +void clif_changelook(struct block_list *bl,int type,int val); // area void clif_changetraplook(struct block_list *bl,int val); // area void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_target target); //area specified in 'target' void clif_arrowequip(struct map_session_data *sd,int val); //self void clif_arrow_fail(struct map_session_data *sd,int type); //self -void clif_arrow_create_list(struct map_session_data *sd); //self -void clif_statusupack(struct map_session_data *sd,int type,int ok,int val); // self -void clif_equipitemack(struct map_session_data *sd,int n,int pos,int ok); // self -void clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok); // self -void clif_misceffect(struct block_list *bl,int type); // area -void clif_changeoption(struct block_list *bl); // area -void clif_changeoption2(struct block_list *bl); // area -void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok); // self -void clif_GlobalMessage(struct block_list *bl, const char *message); -void clif_createchat(struct map_session_data *sd, int flag); // self -void clif_dispchat(struct chat_data *cd, int fd); // area or fd -void clif_joinchatfail(struct map_session_data *sd,int flag); // self -void clif_joinchatok(struct map_session_data *sd,struct chat_data *cd); // self -void clif_addchat(struct chat_data *cd,struct map_session_data *sd); // chat -void clif_changechatowner(struct chat_data *cd, struct map_session_data *sd); // chat -void clif_clearchat(struct chat_data *cd,int fd); // area or fd -void clif_leavechat(struct chat_data *cd, struct map_session_data *sd, bool flag); // chat -void clif_changechatstatus(struct chat_data *cd); // chat -void clif_refresh(struct map_session_data *sd); // self +void clif_arrow_create_list(struct map_session_data *sd); //self +void clif_statusupack(struct map_session_data *sd,int type,int ok,int val); // self +void clif_equipitemack(struct map_session_data *sd,int n,int pos,int ok); // self +void clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok); // self +void clif_misceffect(struct block_list* bl,int type); // area +void clif_changeoption(struct block_list* bl); // area +void clif_changeoption2(struct block_list* bl); // area +void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok); // self +void clif_GlobalMessage(struct block_list* bl, const char* message); +void clif_createchat(struct map_session_data* sd, int flag); // self +void clif_dispchat(struct chat_data* cd, int fd); // area or fd +void clif_joinchatfail(struct map_session_data *sd,int flag); // self +void clif_joinchatok(struct map_session_data *sd,struct chat_data* cd); // self +void clif_addchat(struct chat_data* cd,struct map_session_data *sd); // chat +void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd); // chat +void clif_clearchat(struct chat_data *cd,int fd); // area or fd +void clif_leavechat(struct chat_data* cd, struct map_session_data* sd, bool flag); // chat +void clif_changechatstatus(struct chat_data* cd); // chat +void clif_refresh(struct map_session_data *sd); // self void clif_fame_blacksmith(struct map_session_data *sd, int points); void clif_fame_alchemist(struct map_session_data *sd, int points); void clif_fame_taekwon(struct map_session_data *sd, int points); void clif_emotion(struct block_list *bl,int type); -void clif_talkiebox(struct block_list *bl, const char *talkie); +void clif_talkiebox(struct block_list* bl, const char* talkie); void clif_wedding_effect(struct block_list *bl); -void clif_divorced(struct map_session_data *sd, const char *name); +void clif_divorced(struct map_session_data* sd, const char* name); void clif_callpartner(struct map_session_data *sd); -void clif_playBGM(struct map_session_data *sd, const char *name); -void clif_soundeffect(struct map_session_data *sd, struct block_list *bl, const char *name, int type); -void clif_soundeffectall(struct block_list *bl, const char *name, int type, enum send_target coverage); +void clif_playBGM(struct map_session_data* sd, const char* name); +void clif_soundeffect(struct map_session_data* sd, struct block_list* bl, const char* name, int type); +void clif_soundeffectall(struct block_list* bl, const char* name, int type, enum send_target coverage); void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, unsigned int tick); void clif_parse_LoadEndAck(int fd,struct map_session_data *sd); void clif_hotkeys_send(struct map_session_data *sd); // trade -void clif_traderequest(struct map_session_data *sd, const char *name); -void clif_tradestart(struct map_session_data *sd, uint8 type); -void clif_tradeadditem(struct map_session_data *sd, struct map_session_data *tsd, int index, int amount); -void clif_tradeitemok(struct map_session_data *sd, int index, int fail); -void clif_tradedeal_lock(struct map_session_data *sd, int fail); -void clif_tradecancelled(struct map_session_data *sd); -void clif_tradecompleted(struct map_session_data *sd, int fail); -void clif_tradeundo(struct map_session_data *sd); +void clif_traderequest(struct map_session_data* sd, const char* name); +void clif_tradestart(struct map_session_data* sd, uint8 type); +void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd, int index, int amount); +void clif_tradeitemok(struct map_session_data* sd, int index, int fail); +void clif_tradedeal_lock(struct map_session_data* sd, int fail); +void clif_tradecancelled(struct map_session_data* sd); +void clif_tradecompleted(struct map_session_data* sd, int fail); +void clif_tradeundo(struct map_session_data* sd); // storage -void clif_storagelist(struct map_session_data *sd, struct item *items, int items_length); -void clif_updatestorageamount(struct map_session_data *sd, int amount, int max_amount); -void clif_storageitemadded(struct map_session_data *sd, struct item *i, int index, int amount); -void clif_storageitemremoved(struct map_session_data *sd, int index, int amount); -void clif_storageclose(struct map_session_data *sd); +void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length); +void clif_updatestorageamount(struct map_session_data* sd, int amount, int max_amount); +void clif_storageitemadded(struct map_session_data* sd, struct item* i, int index, int amount); +void clif_storageitemremoved(struct map_session_data* sd, int index, int amount); +void clif_storageclose(struct map_session_data* sd); -int clif_insight(struct block_list *bl,va_list ap); // map_forallinmovearea callback -int clif_outsight(struct block_list *bl,va_list ap); // map_forallinmovearea callback +int clif_insight(struct block_list *bl,va_list ap); // map_forallinmovearea callback +int clif_outsight(struct block_list *bl,va_list ap); // map_forallinmovearea callback void clif_class_change(struct block_list *bl,int class_,int type); #define clif_mob_class_change(md, class_) clif_class_change(&md->bl, class_, 1) @@ -428,8 +430,8 @@ void clif_skillinfo(struct map_session_data *sd,int skill, int inf); void clif_addskill(struct map_session_data *sd, int id); void clif_deleteskill(struct map_session_data *sd, int id); -void clif_skillcasting(struct block_list *bl, int src_id, int dst_id, int dst_x, int dst_y, int skill_num, int property, int casttime); -void clif_skillcastcancel(struct block_list *bl); +void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, int skill_num, int property, int casttime); +void clif_skillcastcancel(struct block_list* bl); void clif_skill_fail(struct map_session_data *sd,int skill_id,enum useskill_fail_cause cause,int btype); void clif_skill_cooldown(struct map_session_data *sd, int skillid, unsigned int tick); int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,int skill_id,int skill_lv,int type); @@ -437,18 +439,18 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int int clif_skill_nodamage(struct block_list *src,struct block_list *dst,int skill_id,int heal,int fail); void clif_skill_poseffect(struct block_list *src,int skill_id,int val,int x,int y,int tick); void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst); -void clif_skill_warppoint(struct map_session_data *sd, short skill_num, short skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4); -void clif_skill_memomessage(struct map_session_data *sd, int type); +void clif_skill_warppoint(struct map_session_data* sd, short skill_num, short skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4); +void clif_skill_memomessage(struct map_session_data* sd, int type); void clif_skill_teleportmessage(struct map_session_data *sd, int type); void clif_skill_produce_mix_list(struct map_session_data *sd, int skillid, int trigger); void clif_cooking_list(struct map_session_data *sd, int trigger, int skill_id, int qty, int list_type); -void clif_produceeffect(struct map_session_data *sd,int flag,int nameid); +void clif_produceeffect(struct map_session_data* sd,int flag,int nameid); void clif_skill_setunit(struct skill_unit *unit); void clif_skill_delunit(struct skill_unit *unit); -void clif_skillunit_update(struct block_list *bl); +void clif_skillunit_update(struct block_list* bl); void clif_autospell(struct map_session_data *sd,int skilllv); void clif_devotion(struct block_list *src, struct map_session_data *tsd); @@ -460,10 +462,10 @@ void clif_changemapcell(int fd, int m, int x, int y, int type, enum send_target #define clif_status_load(bl, type, flag) clif_status_change((bl), (type), (flag), 0, 0, 0, 0) void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3); -void clif_wis_message(int fd, const char *nick, const char *mes, int mes_len); +void clif_wis_message(int fd, const char* nick, const char* mes, int mes_len); void clif_wis_end(int fd, int flag); -void clif_solved_charname(int fd, int charid, const char *name); +void clif_solved_charname(int fd, int charid, const char* name); void clif_charnameack(int fd, struct block_list *bl); void clif_charnameupdate(struct map_session_data *ssd); @@ -482,7 +484,7 @@ void clif_item_identify_list(struct map_session_data *sd); void clif_item_identified(struct map_session_data *sd,int idx,int flag); void clif_item_repair_list(struct map_session_data *sd, struct map_session_data *dstsd, int lv); void clif_item_repaireffect(struct map_session_data *sd, int idx, int flag); -void clif_item_damaged(struct map_session_data *sd, unsigned short position); +void clif_item_damaged(struct map_session_data* sd, unsigned short position); void clif_item_refine_list(struct map_session_data *sd); void clif_item_skill(struct map_session_data *sd,int skillid,int skilllv); @@ -490,29 +492,29 @@ void clif_item_skill(struct map_session_data *sd,int skillid,int skilllv); void clif_mvp_effect(struct map_session_data *sd); void clif_mvp_item(struct map_session_data *sd,int nameid); void clif_mvp_exp(struct map_session_data *sd, unsigned int exp); -void clif_mvp_noitem(struct map_session_data *sd); +void clif_mvp_noitem(struct map_session_data* sd); void clif_changed_dir(struct block_list *bl, enum send_target target); // vending -void clif_openvendingreq(struct map_session_data *sd, int num); -void clif_showvendingboard(struct block_list *bl, const char *message, int fd); -void clif_closevendingboard(struct block_list *bl, int fd); -void clif_vendinglist(struct map_session_data *sd, int id, struct s_vending *vending); -void clif_buyvending(struct map_session_data *sd, int index, int amount, int fail); -void clif_openvending(struct map_session_data *sd, int id, struct s_vending *vending); -void clif_vendingreport(struct map_session_data *sd, int index, int amount); +void clif_openvendingreq(struct map_session_data* sd, int num); +void clif_showvendingboard(struct block_list* bl, const char* message, int fd); +void clif_closevendingboard(struct block_list* bl, int fd); +void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* vending); +void clif_buyvending(struct map_session_data* sd, int index, int amount, int fail); +void clif_openvending(struct map_session_data* sd, int id, struct s_vending* vending); +void clif_vendingreport(struct map_session_data* sd, int index, int amount); void clif_movetoattack(struct map_session_data *sd,struct block_list *bl); // party void clif_party_created(struct map_session_data *sd,int result); void clif_party_member_info(struct party_data *p, struct map_session_data *sd); -void clif_party_info(struct party_data *p, struct map_session_data *sd); +void clif_party_info(struct party_data* p, struct map_session_data *sd); void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd); -void clif_party_inviteack(struct map_session_data *sd, const char *nick, int result); +void clif_party_inviteack(struct map_session_data* sd, const char* nick, int result); void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag); -void clif_party_withdraw(struct party_data *p, struct map_session_data *sd, int account_id, const char *name, int flag); -void clif_party_message(struct party_data *p, int account_id, const char *mes, int len); +void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int account_id, const char* name, int flag); +void clif_party_message(struct party_data* p, int account_id, const char* mes, int len); void clif_party_xy(struct map_session_data *sd); void clif_party_xy_single(int fd, struct map_session_data *sd); void clif_party_hp(struct map_session_data *sd); @@ -525,18 +527,18 @@ void clif_guild_masterormember(struct map_session_data *sd); void clif_guild_basicinfo(struct map_session_data *sd); void clif_guild_allianceinfo(struct map_session_data *sd); void clif_guild_memberlist(struct map_session_data *sd); -void clif_guild_skillinfo(struct map_session_data *sd); +void clif_guild_skillinfo(struct map_session_data* sd); void clif_guild_send_onlineinfo(struct map_session_data *sd); //[LuzZza] void clif_guild_memberlogin_notice(struct guild *g,int idx,int flag); void clif_guild_invite(struct map_session_data *sd,struct guild *g); void clif_guild_inviteack(struct map_session_data *sd,int flag); void clif_guild_leave(struct map_session_data *sd,const char *name,const char *mes); -void clif_guild_expulsion(struct map_session_data *sd, const char *name, const char *mes, int account_id); +void clif_guild_expulsion(struct map_session_data* sd, const char* name, const char* mes, int account_id); void clif_guild_positionchanged(struct guild *g,int idx); void clif_guild_memberpositionchanged(struct guild *g,int idx); void clif_guild_emblem(struct map_session_data *sd,struct guild *g); -void clif_guild_emblem_area(struct block_list *bl); -void clif_guild_notice(struct map_session_data *sd, struct guild *g); +void clif_guild_emblem_area(struct block_list* bl); +void clif_guild_notice(struct map_session_data* sd, struct guild* g); void clif_guild_message(struct guild *g,int account_id,const char *mes,int len); int clif_guild_skillup(struct map_session_data *sd,int skill_num,int lv); void clif_guild_reqalliance(struct map_session_data *sd,int account_id,const char *name); @@ -567,15 +569,15 @@ void clif_instance_leave(int fd); void clif_font(struct map_session_data *sd); // atcommand -void clif_displaymessage(const int fd, const char *mes); +void clif_displaymessage(const int fd, const char* mes); void clif_disp_onlyself(struct map_session_data *sd, const char *mes, int len); -void clif_disp_message(struct block_list *src, const char *mes, int len, enum send_target target); -void clif_broadcast(struct block_list *bl, const char *mes, int len, int type, enum send_target target); -void clif_MainChatMessage(const char *message); -void clif_broadcast2(struct block_list *bl, const char *mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target); +void clif_disp_message(struct block_list* src, const char* mes, int len, enum send_target target); +void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, enum send_target target); +void clif_MainChatMessage(const char* message); +void clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target); void clif_heal(int fd,int type,int val); void clif_resurrection(struct block_list *bl,int type); -void clif_map_property(struct map_session_data *sd, enum map_property property); +void clif_map_property(struct map_session_data* sd, enum map_property property); void clif_pvpset(struct map_session_data *sd, int pvprank, int pvpnum,int type); void clif_map_property_mapall(int map, enum map_property property); void clif_refine(int fd, int fail, int index, int val); @@ -586,7 +588,7 @@ void clif_catch_process(struct map_session_data *sd); void clif_pet_roulette(struct map_session_data *sd,int data); void clif_sendegg(struct map_session_data *sd); void clif_send_petstatus(struct map_session_data *sd); -void clif_send_petdata(struct map_session_data *sd, struct pet_data *pd, int type, int param); +void clif_send_petdata(struct map_session_data* sd, struct pet_data* pd, int type, int param); #define clif_pet_equip(sd, pd) clif_send_petdata(sd, pd, 3, (pd)->vd.head_bottom) #define clif_pet_equip_area(pd) clif_send_petdata(NULL, pd, 3, (pd)->vd.head_bottom) #define clif_pet_performance(pd, param) clif_send_petdata(NULL, pd, 4, param) @@ -599,26 +601,26 @@ void clif_friendslist_send(struct map_session_data *sd); void clif_friendslist_reqack(struct map_session_data *sd, struct map_session_data *f_sd, int type); void clif_weather(int m); // [Valaris] -void clif_specialeffect(struct block_list *bl, int type, enum send_target target); // special effects [Valaris] -void clif_specialeffect_single(struct block_list *bl, int type, int fd); -void clif_messagecolor(struct block_list *bl, unsigned long color, const char *msg); // Mob/Npc color talk [SnakeDrak] -void clif_message(struct block_list *bl, const char *msg); -void clif_specialeffect_value(struct block_list *bl, int effect_id, int num, send_target target); +void clif_specialeffect(struct block_list* bl, int type, enum send_target target); // special effects [Valaris] +void clif_specialeffect_single(struct block_list* bl, int type, int fd); +void clif_messagecolor(struct block_list* bl, unsigned long color, const char* msg); // Mob/Npc color talk [SnakeDrak] +void clif_message(struct block_list* bl, const char* msg); +void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, send_target target); void clif_GM_kickack(struct map_session_data *sd, int id); void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd); -void clif_manner_message(struct map_session_data *sd, uint32 type); -void clif_GM_silence(struct map_session_data *sd, struct map_session_data *tsd, uint8 type); +void clif_manner_message(struct map_session_data* sd, uint32 type); +void clif_GM_silence(struct map_session_data* sd, struct map_session_data* tsd, uint8 type); -void clif_disp_overhead(struct map_session_data *sd, const char *mes); +void clif_disp_overhead(struct map_session_data *sd, const char* mes); -void clif_get_weapon_view(struct map_session_data *sd, unsigned short *rhand, unsigned short *lhand); +void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, unsigned short *lhand); void clif_party_xy_remove(struct map_session_data *sd); //Fix for minimap [Kevin] void clif_gospel_info(struct map_session_data *sd, int type); void clif_feel_req(int fd, struct map_session_data *sd, int skilllv); -void clif_starskill(struct map_session_data *sd, const char *mapname, int monster_id, unsigned char star, unsigned char result); -void clif_feel_info(struct map_session_data *sd, unsigned char feel_level, unsigned char type); +void clif_starskill(struct map_session_data* sd, const char* mapname, int monster_id, unsigned char star, unsigned char result); +void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsigned char type); void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int class_, unsigned char type); void clif_mission_info(struct map_session_data *sd, int mob_id, unsigned char progress); void clif_feel_hate_reset(struct map_session_data *sd); @@ -626,30 +628,30 @@ void clif_feel_hate_reset(struct map_session_data *sd); // [blackhole89] void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag); int clif_homskillinfoblock(struct map_session_data *sd); -void clif_homskillup(struct map_session_data *sd, int skill_num); //[orn] -int clif_hom_food(struct map_session_data *sd,int foodid,int fail); //[orn] -void clif_send_homdata(struct map_session_data *sd, int state, int param); //[orn] +void clif_homskillup(struct map_session_data *sd, int skill_num); //[orn] +int clif_hom_food(struct map_session_data *sd,int foodid,int fail); //[orn] +void clif_send_homdata(struct map_session_data *sd, int state, int param); //[orn] -void clif_equiptickack(struct map_session_data *sd, int flag); -void clif_viewequip_ack(struct map_session_data *sd, struct map_session_data *tsd); -void clif_viewequip_fail(struct map_session_data *sd); -void clif_equipcheckbox(struct map_session_data *sd); +void clif_equiptickack(struct map_session_data* sd, int flag); +void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* tsd); +void clif_viewequip_fail(struct map_session_data* sd); +void clif_equipcheckbox(struct map_session_data* sd); -void clif_msg(struct map_session_data *sd, unsigned short id); -void clif_msg_value(struct map_session_data *sd, unsigned short id, int value); -void clif_msg_skill(struct map_session_data *sd, unsigned short skill_id, int msg_id); +void clif_msg(struct map_session_data* sd, unsigned short id); +void clif_msg_value(struct map_session_data* sd, unsigned short id, int value); +void clif_msg_skill(struct map_session_data* sd, unsigned short skill_id, int msg_id); //quest system [Kevin] [Inkfish] -void clif_quest_send_list(struct map_session_data *sd); -void clif_quest_send_mission(struct map_session_data *sd); -void clif_quest_add(struct map_session_data *sd, struct quest *qd, int index); -void clif_quest_delete(struct map_session_data *sd, int quest_id); -void clif_quest_update_status(struct map_session_data *sd, int quest_id, bool active); -void clif_quest_update_objective(struct map_session_data *sd, struct quest *qd, int index); +void clif_quest_send_list(struct map_session_data * sd); +void clif_quest_send_mission(struct map_session_data * sd); +void clif_quest_add(struct map_session_data * sd, struct quest * qd, int index); +void clif_quest_delete(struct map_session_data * sd, int quest_id); +void clif_quest_update_status(struct map_session_data * sd, int quest_id, bool active); +void clif_quest_update_objective(struct map_session_data * sd, struct quest * qd, int index); void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, short state, short color); void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool quest); -int clif_send(const uint8 *buf, int len, struct block_list *bl, enum send_target type); +int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type); int do_init_clif(void); void do_final_clif(void); @@ -678,7 +680,7 @@ void clif_Adopt_reply(struct map_session_data *sd, int type); // MERCENARIES void clif_mercenary_info(struct map_session_data *sd); void clif_mercenary_skillblock(struct map_session_data *sd); -void clif_mercenary_message(struct map_session_data *sd, int message); +void clif_mercenary_message(struct map_session_data* sd, int message); void clif_mercenary_updatestatus(struct map_session_data *sd, int type); // RENTAL SYSTEM @@ -689,40 +691,40 @@ void clif_rental_expired(int fd, int index, int nameid); void clif_readbook(int fd, int book_id, int page); // Show Picker -void clif_party_show_picker(struct map_session_data *sd, struct item *item_data); +void clif_party_show_picker(struct map_session_data * sd, struct item * item_data); // Progress Bar [Inkfish] -void clif_progressbar(struct map_session_data *sd, unsigned long color, unsigned int second); -void clif_progressbar_abort(struct map_session_data *sd); +void clif_progressbar(struct map_session_data * sd, unsigned long color, unsigned int second); +void clif_progressbar_abort(struct map_session_data * sd); void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag); -void clif_PartyBookingDeleteAck(struct map_session_data *sd, int flag); -void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info **results, int count, bool more_result); -void clif_PartyBookingUpdateNotify(struct map_session_data *sd, struct party_booking_ad_info *pb_ad); -void clif_PartyBookingDeleteNotify(struct map_session_data *sd, int index); -void clif_PartyBookingInsertNotify(struct map_session_data *sd, struct party_booking_ad_info *pb_ad); +void clif_PartyBookingDeleteAck(struct map_session_data* sd, int flag); +void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results, int count, bool more_result); +void clif_PartyBookingUpdateNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad); +void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index); +void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad); -void clif_showdigit(struct map_session_data *sd, unsigned char type, int value); +void clif_showdigit(struct map_session_data* sd, unsigned char type, int value); /// Buying Store System -void clif_buyingstore_open(struct map_session_data *sd); -void clif_buyingstore_open_failed(struct map_session_data *sd, unsigned short result, unsigned int weight); -void clif_buyingstore_myitemlist(struct map_session_data *sd); -void clif_buyingstore_entry(struct map_session_data *sd); -void clif_buyingstore_entry_single(struct map_session_data *sd, struct map_session_data *pl_sd); -void clif_buyingstore_disappear_entry(struct map_session_data *sd); -void clif_buyingstore_disappear_entry_single(struct map_session_data *sd, struct map_session_data *pl_sd); -void clif_buyingstore_itemlist(struct map_session_data *sd, struct map_session_data *pl_sd); -void clif_buyingstore_trade_failed_buyer(struct map_session_data *sd, short result); -void clif_buyingstore_update_item(struct map_session_data *sd, unsigned short nameid, unsigned short amount); -void clif_buyingstore_delete_item(struct map_session_data *sd, short index, unsigned short amount, int price); -void clif_buyingstore_trade_failed_seller(struct map_session_data *sd, short result, unsigned short nameid); +void clif_buyingstore_open(struct map_session_data* sd); +void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight); +void clif_buyingstore_myitemlist(struct map_session_data* sd); +void clif_buyingstore_entry(struct map_session_data* sd); +void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd); +void clif_buyingstore_disappear_entry(struct map_session_data* sd); +void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd); +void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_data* pl_sd); +void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result); +void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount); +void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price); +void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid); /// Search Store System -void clif_search_store_info_ack(struct map_session_data *sd); -void clif_search_store_info_failed(struct map_session_data *sd, unsigned char reason); -void clif_open_search_store_info(struct map_session_data *sd); -void clif_search_store_info_click_ack(struct map_session_data *sd, short x, short y); +void clif_search_store_info_ack(struct map_session_data* sd); +void clif_search_store_info_failed(struct map_session_data* sd, unsigned char reason); +void clif_open_search_store_info(struct map_session_data* sd); +void clif_search_store_info_click_ack(struct map_session_data* sd, short x, short y); /** * 3CeAM **/ @@ -731,7 +733,7 @@ void clif_msgtable_num(int fd, int line, int num); int clif_elementalconverter_list(struct map_session_data *sd); -void clif_millenniumshield(struct map_session_data *sd, short shields); +void clif_millenniumshield(struct map_session_data *sd, short shields ); int clif_spellbook_list(struct map_session_data *sd); @@ -745,25 +747,25 @@ int clif_status_load_notick(struct block_list *bl,int type,int flag,int val1, in int clif_status_load_single(int fd, int id,int type,int flag,int val1, int val2, int val3); -int clif_skill_itemlistwindow(struct map_session_data *sd, int skill_id, int skill_lv); +int clif_skill_itemlistwindow( struct map_session_data *sd, int skill_id, int skill_lv ); void clif_elemental_info(struct map_session_data *sd); void clif_elemental_updatestatus(struct map_session_data *sd, int type); void clif_talisman(struct map_session_data *sd, short type); -void clif_snap(struct block_list *bl, short x, short y); -void clif_monster_hp_bar(struct mob_data *md, int fd); +void clif_snap( struct block_list *bl, short x, short y ); +void clif_monster_hp_bar( struct mob_data* md, int fd ); /** * Color Table **/ enum clif_colors { - COLOR_RED, + COLOR_RED, - COLOR_MAX + COLOR_MAX }; unsigned long color_table[COLOR_MAX]; -int clif_colormes(struct map_session_data *sd, enum clif_colors color, const char *msg); +int clif_colormes(struct map_session_data * sd, enum clif_colors color, const char* msg); #define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0; diff --git a/src/map/date.c b/src/map/date.c index 255fabf18..9f2bc4bee 100644 --- a/src/map/date.c +++ b/src/map/date.c @@ -6,66 +6,66 @@ int date_get_year(void) { - time_t t; - struct tm *lt; - t = time(NULL); - lt = localtime(&t); - return lt->tm_year+1900; + time_t t; + struct tm * lt; + t = time(NULL); + lt = localtime(&t); + return lt->tm_year+1900; } int date_get_month(void) { - time_t t; - struct tm *lt; - t = time(NULL); - lt = localtime(&t); - return lt->tm_mon+1; + time_t t; + struct tm * lt; + t = time(NULL); + lt = localtime(&t); + return lt->tm_mon+1; } int date_get_day(void) { - time_t t; - struct tm *lt; - t = time(NULL); - lt = localtime(&t); - return lt->tm_mday; + time_t t; + struct tm * lt; + t = time(NULL); + lt = localtime(&t); + return lt->tm_mday; } int date_get_hour(void) { - time_t t; - struct tm *lt; - t = time(NULL); - lt = localtime(&t); - return lt->tm_hour; + time_t t; + struct tm * lt; + t = time(NULL); + lt = localtime(&t); + return lt->tm_hour; } int date_get_min(void) { - time_t t; - struct tm *lt; - t = time(NULL); - lt = localtime(&t); - return lt->tm_min; + time_t t; + struct tm * lt; + t = time(NULL); + lt = localtime(&t); + return lt->tm_min; } int date_get_sec(void) { - time_t t; - struct tm *lt; - t = time(NULL); - lt = localtime(&t); - return lt->tm_sec; + time_t t; + struct tm * lt; + t = time(NULL); + lt = localtime(&t); + return lt->tm_sec; } int is_day_of_sun(void) { - return date_get_day()%2 == 0; + return date_get_day()%2 == 0; } int is_day_of_moon(void) { - return date_get_day()%2 == 1; + return date_get_day()%2 == 1; } int is_day_of_star(void) { - return date_get_day()%5 == 0; + return date_get_day()%5 == 0; } diff --git a/src/map/duel.c b/src/map/duel.c index 808193dc0..c13d004b0 100644 --- a/src/map/duel.c +++ b/src/map/duel.c @@ -19,157 +19,157 @@ int duel_count = 0; /*========================================== * Duel organizing functions [LuzZza] *------------------------------------------*/ -void duel_savetime(struct map_session_data *sd) +void duel_savetime(struct map_session_data* sd) { - time_t timer; - struct tm *t; - - time(&timer); - t = localtime(&timer); - - pc_setglobalreg(sd, "PC_LAST_DUEL_TIME", t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min); + time_t timer; + struct tm *t; + + time(&timer); + t = localtime(&timer); + + pc_setglobalreg(sd, "PC_LAST_DUEL_TIME", t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min); } -int duel_checktime(struct map_session_data *sd) +int duel_checktime(struct map_session_data* sd) { - int diff; - time_t timer; - struct tm *t; - - time(&timer); + int diff; + time_t timer; + struct tm *t; + + time(&timer); t = localtime(&timer); - - diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min - pc_readglobalreg(sd, "PC_LAST_DUEL_TIME"); - - return !(diff >= 0 && diff < battle_config.duel_time_interval); + + diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min - pc_readglobalreg(sd, "PC_LAST_DUEL_TIME"); + + return !(diff >= 0 && diff < battle_config.duel_time_interval); } -static int duel_showinfo_sub(struct map_session_data *sd, va_list va) +static int duel_showinfo_sub(struct map_session_data* sd, va_list va) { - struct map_session_data *ssd = va_arg(va, struct map_session_data *); - int *p = va_arg(va, int *); - char output[256]; - - if (sd->duel_group != ssd->duel_group) return 0; - - sprintf(output, " %d. %s", ++(*p), sd->status.name); - clif_disp_onlyself(ssd, output, strlen(output)); - return 1; + struct map_session_data *ssd = va_arg(va, struct map_session_data*); + int *p = va_arg(va, int*); + char output[256]; + + if (sd->duel_group != ssd->duel_group) return 0; + + sprintf(output, " %d. %s", ++(*p), sd->status.name); + clif_disp_onlyself(ssd, output, strlen(output)); + return 1; } -void duel_showinfo(const unsigned int did, struct map_session_data *sd) +void duel_showinfo(const unsigned int did, struct map_session_data* sd) { - int p=0; - char output[256]; - - if (duel_list[did].max_players_limit > 0) - sprintf(output, msg_txt(370), //" -- Duels: %d/%d, Members: %d/%d, Max players: %d --" - did, duel_count, - duel_list[did].members_count, - duel_list[did].members_count + duel_list[did].invites_count, - duel_list[did].max_players_limit); - else - sprintf(output, msg_txt(371), //" -- Duels: %d/%d, Members: %d/%d --" - did, duel_count, - duel_list[did].members_count, - duel_list[did].members_count + duel_list[did].invites_count); - - clif_disp_onlyself(sd, output, strlen(output)); - map_foreachpc(duel_showinfo_sub, sd, &p); + int p=0; + char output[256]; + + if(duel_list[did].max_players_limit > 0) + sprintf(output, msg_txt(370), //" -- Duels: %d/%d, Members: %d/%d, Max players: %d --" + did, duel_count, + duel_list[did].members_count, + duel_list[did].members_count + duel_list[did].invites_count, + duel_list[did].max_players_limit); + else + sprintf(output, msg_txt(371), //" -- Duels: %d/%d, Members: %d/%d --" + did, duel_count, + duel_list[did].members_count, + duel_list[did].members_count + duel_list[did].invites_count); + + clif_disp_onlyself(sd, output, strlen(output)); + map_foreachpc(duel_showinfo_sub, sd, &p); } -int duel_create(struct map_session_data *sd, const unsigned int maxpl) +int duel_create(struct map_session_data* sd, const unsigned int maxpl) { - int i=1; - char output[256]; - - while (duel_list[i].members_count > 0 && i < MAX_DUEL) i++; - if (i == MAX_DUEL) return 0; - - duel_count++; - sd->duel_group = i; - duel_list[i].members_count++; - duel_list[i].invites_count = 0; - duel_list[i].max_players_limit = maxpl; - - strcpy(output, msg_txt(372)); // " -- Duel has been created (@invite/@leave) --" - clif_disp_onlyself(sd, output, strlen(output)); - - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - //clif_misceffect2(&sd->bl, 159); - return i; + int i=1; + char output[256]; + + while(duel_list[i].members_count > 0 && i < MAX_DUEL) i++; + if(i == MAX_DUEL) return 0; + + duel_count++; + sd->duel_group = i; + duel_list[i].members_count++; + duel_list[i].invites_count = 0; + duel_list[i].max_players_limit = maxpl; + + strcpy(output, msg_txt(372)); // " -- Duel has been created (@invite/@leave) --" + clif_disp_onlyself(sd, output, strlen(output)); + + clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); + //clif_misceffect2(&sd->bl, 159); + return i; } -void duel_invite(const unsigned int did, struct map_session_data *sd, struct map_session_data *target_sd) +void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd) { - char output[256]; - - // " -- Player %s invites %s to duel --" - sprintf(output, msg_txt(373), sd->status.name, target_sd->status.name); - clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - - target_sd->duel_invite = did; - duel_list[did].invites_count++; - - // "Blue -- Player %s invites you to PVP duel (@accept/@reject) --" - sprintf(output, msg_txt(374), sd->status.name); - clif_broadcast((struct block_list *)target_sd, output, strlen(output)+1, 0x10, SELF); + char output[256]; + + // " -- Player %s invites %s to duel --" + sprintf(output, msg_txt(373), sd->status.name, target_sd->status.name); + clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + + target_sd->duel_invite = did; + duel_list[did].invites_count++; + + // "Blue -- Player %s invites you to PVP duel (@accept/@reject) --" + sprintf(output, msg_txt(374), sd->status.name); + clif_broadcast((struct block_list *)target_sd, output, strlen(output)+1, 0x10, SELF); } -static int duel_leave_sub(struct map_session_data *sd, va_list va) +static int duel_leave_sub(struct map_session_data* sd, va_list va) { - int did = va_arg(va, int); - if (sd->duel_invite == did) - sd->duel_invite = 0; - return 0; + int did = va_arg(va, int); + if (sd->duel_invite == did) + sd->duel_invite = 0; + return 0; } -void duel_leave(const unsigned int did, struct map_session_data *sd) +void duel_leave(const unsigned int did, struct map_session_data* sd) { - char output[256]; - - // " <- Player %s has left duel --" - sprintf(output, msg_txt(375), sd->status.name); - clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - - duel_list[did].members_count--; - - if (duel_list[did].members_count == 0) { - map_foreachpc(duel_leave_sub, did); - duel_count--; - } - - sd->duel_group = 0; - duel_savetime(sd); - clif_map_property(sd, MAPPROPERTY_NOTHING); + char output[256]; + + // " <- Player %s has left duel --" + sprintf(output, msg_txt(375), sd->status.name); + clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + + duel_list[did].members_count--; + + if(duel_list[did].members_count == 0) { + map_foreachpc(duel_leave_sub, did); + duel_count--; + } + + sd->duel_group = 0; + duel_savetime(sd); + clif_map_property(sd, MAPPROPERTY_NOTHING); } -void duel_accept(const unsigned int did, struct map_session_data *sd) +void duel_accept(const unsigned int did, struct map_session_data* sd) { - char output[256]; - - duel_list[did].members_count++; - sd->duel_group = sd->duel_invite; - duel_list[did].invites_count--; - sd->duel_invite = 0; - - // " -> Player %s has accepted duel --" - sprintf(output, msg_txt(376), sd->status.name); - clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - //clif_misceffect2(&sd->bl, 159); + char output[256]; + + duel_list[did].members_count++; + sd->duel_group = sd->duel_invite; + duel_list[did].invites_count--; + sd->duel_invite = 0; + + // " -> Player %s has accepted duel --" + sprintf(output, msg_txt(376), sd->status.name); + clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + + clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); + //clif_misceffect2(&sd->bl, 159); } -void duel_reject(const unsigned int did, struct map_session_data *sd) +void duel_reject(const unsigned int did, struct map_session_data* sd) { - char output[256]; - - // " -- Player %s has rejected duel --" - sprintf(output, msg_txt(377), sd->status.name); - clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - - duel_list[did].invites_count--; - sd->duel_invite = 0; + char output[256]; + + // " -- Player %s has rejected duel --" + sprintf(output, msg_txt(377), sd->status.name); + clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + + duel_list[did].invites_count--; + sd->duel_invite = 0; } void do_final_duel(void) @@ -178,5 +178,5 @@ void do_final_duel(void) void do_init_duel(void) { - memset(&duel_list[0], 0, sizeof(duel_list)); + memset(&duel_list[0], 0, sizeof(duel_list)); } diff --git a/src/map/duel.h b/src/map/duel.h index aeed77d4f..04d8e4e84 100644 --- a/src/map/duel.h +++ b/src/map/duel.h @@ -5,9 +5,9 @@ #define _DUEL_H_ struct duel { - int members_count; - int invites_count; - int max_players_limit; + int members_count; + int invites_count; + int max_players_limit; }; #define MAX_DUEL 1024 @@ -15,13 +15,13 @@ extern struct duel duel_list[MAX_DUEL]; extern int duel_count; //Duel functions // [LuzZza] -int duel_create(struct map_session_data *sd, const unsigned int maxpl); -void duel_invite(const unsigned int did, struct map_session_data *sd, struct map_session_data *target_sd); -void duel_accept(const unsigned int did, struct map_session_data *sd); -void duel_reject(const unsigned int did, struct map_session_data *sd); -void duel_leave(const unsigned int did, struct map_session_data *sd); -void duel_showinfo(const unsigned int did, struct map_session_data *sd); -int duel_checktime(struct map_session_data *sd); +int duel_create(struct map_session_data* sd, const unsigned int maxpl); +void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd); +void duel_accept(const unsigned int did, struct map_session_data* sd); +void duel_reject(const unsigned int did, struct map_session_data* sd); +void duel_leave(const unsigned int did, struct map_session_data* sd); +void duel_showinfo(const unsigned int did, struct map_session_data* sd); +int duel_checktime(struct map_session_data* sd); void do_init_duel(void); void do_final_duel(void); diff --git a/src/map/elemental.c b/src/map/elemental.c index a28982d72..770047138 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -39,815 +39,785 @@ struct s_elemental_db elemental_db[MAX_ELEMENTAL_CLASS]; // Elemental Database -int elemental_search_index(int class_) -{ - int i; - ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, elemental_db[i].class_ == class_); - return (i == MAX_ELEMENTAL_CLASS)?-1:i; +int elemental_search_index(int class_) { + int i; + ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, elemental_db[i].class_ == class_); + return (i == MAX_ELEMENTAL_CLASS)?-1:i; } -bool elemental_class(int class_) -{ - return (bool)(elemental_search_index(class_) > -1); +bool elemental_class(int class_) { + return (bool)(elemental_search_index(class_) > -1); } -struct view_data *elemental_get_viewdata(int class_) { - int i = elemental_search_index(class_); - if (i < 0) - return 0; - - return &elemental_db[i].vd; +struct view_data * elemental_get_viewdata(int class_) { + int i = elemental_search_index(class_); + if( i < 0 ) + return 0; + + return &elemental_db[i].vd; } -int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime) -{ - struct s_elemental ele; - struct s_elemental_db *db; - int i; - - nullpo_retr(1,sd); - - if ((i = elemental_search_index(class_)) < 0) - return 0; - - db = &elemental_db[i]; - memset(&ele,0,sizeof(struct s_elemental)); - - ele.char_id = sd->status.char_id; - ele.class_ = class_; - ele.mode = EL_MODE_PASSIVE; // Initial mode - ele.hp = db->status.max_hp; - ele.sp = db->status.max_sp; - ele.life_time = lifetime; - - // Request Char Server to create this elemental - intif_elemental_create(&ele); - - return 1; +int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime) { + struct s_elemental ele; + struct s_elemental_db *db; + int i; + + nullpo_retr(1,sd); + + if( (i = elemental_search_index(class_)) < 0 ) + return 0; + + db = &elemental_db[i]; + memset(&ele,0,sizeof(struct s_elemental)); + + ele.char_id = sd->status.char_id; + ele.class_ = class_; + ele.mode = EL_MODE_PASSIVE; // Initial mode + ele.hp = db->status.max_hp; + ele.sp = db->status.max_sp; + ele.life_time = lifetime; + + // Request Char Server to create this elemental + intif_elemental_create(&ele); + + return 1; } -int elemental_get_lifetime(struct elemental_data *ed) -{ - const struct TimerData *td; - if (ed == NULL || ed->summon_timer == INVALID_TIMER) - return 0; - - td = get_timer(ed->summon_timer); - return (td != NULL) ? DIFF_TICK(td->tick, gettick()) : 0; +int elemental_get_lifetime(struct elemental_data *ed) { + const struct TimerData * td; + if( ed == NULL || ed->summon_timer == INVALID_TIMER ) + return 0; + + td = get_timer(ed->summon_timer); + return (td != NULL) ? DIFF_TICK(td->tick, gettick()) : 0; } -int elemental_save(struct elemental_data *ed) -{ - ed->elemental.hp = ed->battle_status.hp; - ed->elemental.sp = ed->battle_status.sp; - ed->elemental.life_time = elemental_get_lifetime(ed); - - intif_elemental_save(&ed->elemental); - return 1; +int elemental_save(struct elemental_data *ed) { + ed->elemental.hp = ed->battle_status.hp; + ed->elemental.sp = ed->battle_status.sp; + ed->elemental.life_time = elemental_get_lifetime(ed); + + intif_elemental_save(&ed->elemental); + return 1; } -static int elemental_summon_end(int tid, unsigned int tick, int id, intptr_t data) -{ - struct map_session_data *sd; - struct elemental_data *ed; - - if ((sd = map_id2sd(id)) == NULL) - return 1; - if ((ed = sd->ed) == NULL) - return 1; - - if (ed->summon_timer != tid) { - ShowError("elemental_summon_end %d != %d.\n", ed->summon_timer, tid); - return 0; - } - - ed->summon_timer = INVALID_TIMER; - elemental_delete(ed, 0); // Elemental's summon time is over. - - return 0; +static int elemental_summon_end(int tid, unsigned int tick, int id, intptr_t data) { + struct map_session_data *sd; + struct elemental_data *ed; + + if( (sd = map_id2sd(id)) == NULL ) + return 1; + if( (ed = sd->ed) == NULL ) + return 1; + + if( ed->summon_timer != tid ) { + ShowError("elemental_summon_end %d != %d.\n", ed->summon_timer, tid); + return 0; + } + + ed->summon_timer = INVALID_TIMER; + elemental_delete(ed, 0); // Elemental's summon time is over. + + return 0; } -void elemental_summon_stop(struct elemental_data *ed) -{ - nullpo_retv(ed); - if (ed->summon_timer != INVALID_TIMER) - delete_timer(ed->summon_timer, elemental_summon_end); - ed->summon_timer = INVALID_TIMER; +void elemental_summon_stop(struct elemental_data *ed) { + nullpo_retv(ed); + if( ed->summon_timer != INVALID_TIMER ) + delete_timer(ed->summon_timer, elemental_summon_end); + ed->summon_timer = INVALID_TIMER; } -int elemental_delete(struct elemental_data *ed, int reply) -{ - struct map_session_data *sd; - - nullpo_ret(ed); - - sd = ed->master; - ed->elemental.life_time = 0; - - elemental_clean_effect(ed); - elemental_summon_stop(ed); - - if (!sd) - return unit_free(&ed->bl, 0); - - sd->ed = NULL; - sd->status.ele_id = 0; - - return unit_remove_map(&ed->bl, 0); +int elemental_delete(struct elemental_data *ed, int reply) { + struct map_session_data *sd; + + nullpo_ret(ed); + + sd = ed->master; + ed->elemental.life_time = 0; + + elemental_clean_effect(ed); + elemental_summon_stop(ed); + + if( !sd ) + return unit_free(&ed->bl, 0); + + sd->ed = NULL; + sd->status.ele_id = 0; + + return unit_remove_map(&ed->bl, 0); } -void elemental_summon_init(struct elemental_data *ed) -{ - if (ed->summon_timer == INVALID_TIMER) - ed->summon_timer = add_timer(gettick() + ed->elemental.life_time, elemental_summon_end, ed->master->bl.id, 0); - - ed->regen.state.block = 0; +void elemental_summon_init(struct elemental_data *ed) { + if( ed->summon_timer == INVALID_TIMER ) + ed->summon_timer = add_timer(gettick() + ed->elemental.life_time, elemental_summon_end, ed->master->bl.id, 0); + + ed->regen.state.block = 0; } -int elemental_data_received(struct s_elemental *ele, bool flag) -{ - struct map_session_data *sd; - struct elemental_data *ed; - struct s_elemental_db *db; - int i = elemental_search_index(ele->class_); - - if ((sd = map_charid2sd(ele->char_id)) == NULL) - return 0; - - if (!flag || i < 0) { // Not created - loaded - DB info - sd->status.ele_id = 0; - return 0; - } - - db = &elemental_db[i]; - if (!sd->ed) { // Initialize it after first summon. - sd->ed = ed = (struct elemental_data *)aCalloc(1,sizeof(struct elemental_data)); - ed->bl.type = BL_ELEM; - ed->bl.id = npc_get_new_npc_id(); - ed->master = sd; - ed->db = db; - memcpy(&ed->elemental, ele, sizeof(struct s_elemental)); - status_set_viewdata(&ed->bl, ed->elemental.class_); - ed->vd->head_mid = 10; // Why? - status_change_init(&ed->bl); - unit_dataset(&ed->bl); - ed->ud.dir = sd->ud.dir; - - ed->bl.m = sd->bl.m; - ed->bl.x = sd->bl.x; - ed->bl.y = sd->bl.y; - unit_calc_pos(&ed->bl, sd->bl.x, sd->bl.y, sd->ud.dir); - ed->bl.x = ed->ud.to_x; - ed->bl.y = ed->ud.to_y; - - map_addiddb(&ed->bl); - status_calc_elemental(ed,1); - ed->last_thinktime = gettick(); - ed->summon_timer = INVALID_TIMER; - ed->battle_status.mode = ele->mode = EL_MODE_PASSIVE; // Initial mode. - elemental_summon_init(ed); - } else { - memcpy(&sd->ed->elemental, ele, sizeof(struct s_elemental)); - ed = sd->ed; - } - - sd->status.ele_id = ele->elemental_id; - ed->battle_status.mode = ele->mode = EL_MODE_PASSIVE; // Initial mode. - - if (ed->bl.prev == NULL && sd->bl.prev != NULL) { - map_addblock(&ed->bl); - clif_spawn(&ed->bl); - clif_elemental_info(sd); - clif_elemental_updatestatus(sd,SP_HP); - clif_hpmeter_single(sd->fd,ed->bl.id,ed->battle_status.hp,ed->battle_status.matk_max); - clif_elemental_updatestatus(sd,SP_SP); - } - - return 1; +int elemental_data_received(struct s_elemental *ele, bool flag) { + struct map_session_data *sd; + struct elemental_data *ed; + struct s_elemental_db *db; + int i = elemental_search_index(ele->class_); + + if( (sd = map_charid2sd(ele->char_id)) == NULL ) + return 0; + + if( !flag || i < 0 ) { // Not created - loaded - DB info + sd->status.ele_id = 0; + return 0; + } + + db = &elemental_db[i]; + if( !sd->ed ) { // Initialize it after first summon. + sd->ed = ed = (struct elemental_data*)aCalloc(1,sizeof(struct elemental_data)); + ed->bl.type = BL_ELEM; + ed->bl.id = npc_get_new_npc_id(); + ed->master = sd; + ed->db = db; + memcpy(&ed->elemental, ele, sizeof(struct s_elemental)); + status_set_viewdata(&ed->bl, ed->elemental.class_); + ed->vd->head_mid = 10; // Why? + status_change_init(&ed->bl); + unit_dataset(&ed->bl); + ed->ud.dir = sd->ud.dir; + + ed->bl.m = sd->bl.m; + ed->bl.x = sd->bl.x; + ed->bl.y = sd->bl.y; + unit_calc_pos(&ed->bl, sd->bl.x, sd->bl.y, sd->ud.dir); + ed->bl.x = ed->ud.to_x; + ed->bl.y = ed->ud.to_y; + + map_addiddb(&ed->bl); + status_calc_elemental(ed,1); + ed->last_thinktime = gettick(); + ed->summon_timer = INVALID_TIMER; + ed->battle_status.mode = ele->mode = EL_MODE_PASSIVE; // Initial mode. + elemental_summon_init(ed); + } else { + memcpy(&sd->ed->elemental, ele, sizeof(struct s_elemental)); + ed = sd->ed; + } + + sd->status.ele_id = ele->elemental_id; + ed->battle_status.mode = ele->mode = EL_MODE_PASSIVE; // Initial mode. + + if( ed->bl.prev == NULL && sd->bl.prev != NULL ) { + map_addblock(&ed->bl); + clif_spawn(&ed->bl); + clif_elemental_info(sd); + clif_elemental_updatestatus(sd,SP_HP); + clif_hpmeter_single(sd->fd,ed->bl.id,ed->battle_status.hp,ed->battle_status.matk_max); + clif_elemental_updatestatus(sd,SP_SP); + } + + return 1; } -int elemental_clean_single_effect(struct elemental_data *ed, int skill_num) -{ - struct block_list *bl; - sc_type type = status_skill2sc(skill_num); - - nullpo_ret(ed); - - bl = battle_get_master(&ed->bl); - - if (type) { - switch (type) { - // Just remove status change. - case SC_PYROTECHNIC_OPTION: - case SC_HEATER_OPTION: - case SC_TROPIC_OPTION: - case SC_FIRE_CLOAK_OPTION: - case SC_AQUAPLAY_OPTION: - case SC_WATER_SCREEN_OPTION: - case SC_COOLER_OPTION: - case SC_CHILLY_AIR_OPTION: - case SC_GUST_OPTION: - case SC_WIND_STEP_OPTION: - case SC_BLAST_OPTION: - case SC_WATER_DROP_OPTION: - case SC_WIND_CURTAIN_OPTION: - case SC_WILD_STORM_OPTION: - case SC_PETROLOGY_OPTION: - case SC_SOLID_SKIN_OPTION: - case SC_CURSED_SOIL_OPTION: - case SC_STONE_SHIELD_OPTION: - case SC_UPHEAVAL_OPTION: - case SC_CIRCLE_OF_FIRE_OPTION: - case SC_TIDAL_WEAPON_OPTION: - if (bl) status_change_end(bl,type,INVALID_TIMER); // Master - status_change_end(&ed->bl,type-1,INVALID_TIMER); // Elemental Spirit - break; - case SC_ZEPHYR: - if (bl) status_change_end(bl,type,INVALID_TIMER); - break; - default: - ShowWarning("Invalid SC=%d in elemental_clean_single_effect\n",type); - break; - } - } - if (skill_get_unit_id(skill_num,0)) - skill_clear_unitgroup(&ed->bl); - - return 1; +int elemental_clean_single_effect(struct elemental_data *ed, int skill_num) { + struct block_list *bl; + sc_type type = status_skill2sc(skill_num); + + nullpo_ret(ed); + + bl = battle_get_master(&ed->bl); + + if( type ) { + switch( type ) { + // Just remove status change. + case SC_PYROTECHNIC_OPTION: + case SC_HEATER_OPTION: + case SC_TROPIC_OPTION: + case SC_FIRE_CLOAK_OPTION: + case SC_AQUAPLAY_OPTION: + case SC_WATER_SCREEN_OPTION: + case SC_COOLER_OPTION: + case SC_CHILLY_AIR_OPTION: + case SC_GUST_OPTION: + case SC_WIND_STEP_OPTION: + case SC_BLAST_OPTION: + case SC_WATER_DROP_OPTION: + case SC_WIND_CURTAIN_OPTION: + case SC_WILD_STORM_OPTION: + case SC_PETROLOGY_OPTION: + case SC_SOLID_SKIN_OPTION: + case SC_CURSED_SOIL_OPTION: + case SC_STONE_SHIELD_OPTION: + case SC_UPHEAVAL_OPTION: + case SC_CIRCLE_OF_FIRE_OPTION: + case SC_TIDAL_WEAPON_OPTION: + if( bl ) status_change_end(bl,type,INVALID_TIMER); // Master + status_change_end(&ed->bl,type-1,INVALID_TIMER); // Elemental Spirit + break; + case SC_ZEPHYR: + if( bl ) status_change_end(bl,type,INVALID_TIMER); + break; + default: + ShowWarning("Invalid SC=%d in elemental_clean_single_effect\n",type); + break; + } + } + if( skill_get_unit_id(skill_num,0) ) + skill_clear_unitgroup(&ed->bl); + + return 1; } -int elemental_clean_effect(struct elemental_data *ed) -{ - struct map_session_data *sd; - - nullpo_ret(ed); - - // Elemental side - status_change_end(&ed->bl, SC_TROPIC, INVALID_TIMER); - status_change_end(&ed->bl, SC_HEATER, INVALID_TIMER); - status_change_end(&ed->bl, SC_AQUAPLAY, INVALID_TIMER); - status_change_end(&ed->bl, SC_COOLER, INVALID_TIMER); - status_change_end(&ed->bl, SC_CHILLY_AIR, INVALID_TIMER); - status_change_end(&ed->bl, SC_PYROTECHNIC, INVALID_TIMER); - status_change_end(&ed->bl, SC_FIRE_CLOAK, INVALID_TIMER); - status_change_end(&ed->bl, SC_WATER_DROP, INVALID_TIMER); - status_change_end(&ed->bl, SC_WATER_SCREEN, INVALID_TIMER); - status_change_end(&ed->bl, SC_GUST, INVALID_TIMER); - status_change_end(&ed->bl, SC_WIND_STEP, INVALID_TIMER); - status_change_end(&ed->bl, SC_BLAST, INVALID_TIMER); - status_change_end(&ed->bl, SC_WIND_CURTAIN, INVALID_TIMER); - status_change_end(&ed->bl, SC_WILD_STORM, INVALID_TIMER); - status_change_end(&ed->bl, SC_PETROLOGY, INVALID_TIMER); - status_change_end(&ed->bl, SC_SOLID_SKIN, INVALID_TIMER); - status_change_end(&ed->bl, SC_CURSED_SOIL, INVALID_TIMER); - status_change_end(&ed->bl, SC_STONE_SHIELD, INVALID_TIMER); - status_change_end(&ed->bl, SC_UPHEAVAL, INVALID_TIMER); - status_change_end(&ed->bl, SC_CIRCLE_OF_FIRE, INVALID_TIMER); - status_change_end(&ed->bl, SC_TIDAL_WEAPON, INVALID_TIMER); - - skill_clear_unitgroup(&ed->bl); - - if ((sd = ed->master) == NULL) - return 0; - - // Master side - status_change_end(&sd->bl, SC_TROPIC_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_HEATER_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_AQUAPLAY_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_COOLER_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_CHILLY_AIR_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_PYROTECHNIC_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_FIRE_CLOAK_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WATER_SCREEN_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_GUST_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_BLAST_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WIND_CURTAIN_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WILD_STORM_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_ZEPHYR, INVALID_TIMER); - status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_PETROLOGY_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_SOLID_SKIN_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_CURSED_SOIL_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_STONE_SHIELD_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_UPHEAVAL_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_CIRCLE_OF_FIRE_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_TIDAL_WEAPON_OPTION, INVALID_TIMER); - - return 1; +int elemental_clean_effect(struct elemental_data *ed) { + struct map_session_data *sd; + + nullpo_ret(ed); + + // Elemental side + status_change_end(&ed->bl, SC_TROPIC, INVALID_TIMER); + status_change_end(&ed->bl, SC_HEATER, INVALID_TIMER); + status_change_end(&ed->bl, SC_AQUAPLAY, INVALID_TIMER); + status_change_end(&ed->bl, SC_COOLER, INVALID_TIMER); + status_change_end(&ed->bl, SC_CHILLY_AIR, INVALID_TIMER); + status_change_end(&ed->bl, SC_PYROTECHNIC, INVALID_TIMER); + status_change_end(&ed->bl, SC_FIRE_CLOAK, INVALID_TIMER); + status_change_end(&ed->bl, SC_WATER_DROP, INVALID_TIMER); + status_change_end(&ed->bl, SC_WATER_SCREEN, INVALID_TIMER); + status_change_end(&ed->bl, SC_GUST, INVALID_TIMER); + status_change_end(&ed->bl, SC_WIND_STEP, INVALID_TIMER); + status_change_end(&ed->bl, SC_BLAST, INVALID_TIMER); + status_change_end(&ed->bl, SC_WIND_CURTAIN, INVALID_TIMER); + status_change_end(&ed->bl, SC_WILD_STORM, INVALID_TIMER); + status_change_end(&ed->bl, SC_PETROLOGY, INVALID_TIMER); + status_change_end(&ed->bl, SC_SOLID_SKIN, INVALID_TIMER); + status_change_end(&ed->bl, SC_CURSED_SOIL, INVALID_TIMER); + status_change_end(&ed->bl, SC_STONE_SHIELD, INVALID_TIMER); + status_change_end(&ed->bl, SC_UPHEAVAL, INVALID_TIMER); + status_change_end(&ed->bl, SC_CIRCLE_OF_FIRE, INVALID_TIMER); + status_change_end(&ed->bl, SC_TIDAL_WEAPON, INVALID_TIMER); + + skill_clear_unitgroup(&ed->bl); + + if( (sd = ed->master) == NULL ) + return 0; + + // Master side + status_change_end(&sd->bl, SC_TROPIC_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_HEATER_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_AQUAPLAY_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_COOLER_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_CHILLY_AIR_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_PYROTECHNIC_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_FIRE_CLOAK_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WATER_SCREEN_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_GUST_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_BLAST_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WIND_CURTAIN_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WILD_STORM_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_ZEPHYR, INVALID_TIMER); + status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_PETROLOGY_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_SOLID_SKIN_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_CURSED_SOIL_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_STONE_SHIELD_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_UPHEAVAL_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_CIRCLE_OF_FIRE_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_TIDAL_WEAPON_OPTION, INVALID_TIMER); + + return 1; } -int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick) -{ - short skillnum, skilllv; - int i; - - nullpo_ret(ed); - nullpo_ret(bl); - - if (!ed->master) - return 0; - - if (ed->target_id) - elemental_unlocktarget(ed); // Remove previous target. - - ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&EL_SKILLMODE_AGGRESSIVE)); - if (i == MAX_ELESKILLTREE) - return 0; - - skillnum = ed->db->skill[i].id; - skilllv = ed->db->skill[i].lv; - - if (elemental_skillnotok(skillnum, ed)) - return 0; - - if (ed->ud.skilltimer != INVALID_TIMER) - return 0; - else if (DIFF_TICK(tick, ed->ud.canact_tick) < 0) - return 0; - - ed->target_id = ed->ud.skilltarget = bl->id; // Set new target - ed->last_thinktime = tick; - - // Not in skill range. - if (!battle_check_range(&ed->bl,bl,skill_get_range(skillnum,skilllv))) { - // Try to walk to the target. - if (!unit_walktobl(&ed->bl, bl, skill_get_range(skillnum,skilllv), 2)) - elemental_unlocktarget(ed); - else { - // Walking, waiting to be in range. Client don't handle it, then we must handle it here. - int walk_dist = distance_bl(&ed->bl,bl) - skill_get_range(skillnum,skilllv); - ed->ud.skillid = skillnum; - ed->ud.skilllv = skilllv; - - if (skill_get_inf(skillnum) & INF_GROUND_SKILL) - ed->ud.skilltimer = add_timer(tick+status_get_speed(&ed->bl)*walk_dist, skill_castend_pos, ed->bl.id, 0); - else - ed->ud.skilltimer = add_timer(tick+status_get_speed(&ed->bl)*walk_dist, skill_castend_id, ed->bl.id, 0); - } - return 1; - - } - //Otherwise, just cast the skill. - if (skill_get_inf(skillnum) & INF_GROUND_SKILL) - unit_skilluse_pos(&ed->bl, bl->x, bl->y, skillnum, skilllv); - else - unit_skilluse_id(&ed->bl, bl->id, skillnum, skilllv); - - // Reset target. - ed->target_id = 0; - - return 1; +int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick) { + short skillnum, skilllv; + int i; + + nullpo_ret(ed); + nullpo_ret(bl); + + if( !ed->master ) + return 0; + + if( ed->target_id ) + elemental_unlocktarget(ed); // Remove previous target. + + ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&EL_SKILLMODE_AGGRESSIVE)); + if( i == MAX_ELESKILLTREE ) + return 0; + + skillnum = ed->db->skill[i].id; + skilllv = ed->db->skill[i].lv; + + if( elemental_skillnotok(skillnum, ed) ) + return 0; + + if( ed->ud.skilltimer != INVALID_TIMER ) + return 0; + else if( DIFF_TICK(tick, ed->ud.canact_tick) < 0 ) + return 0; + + ed->target_id = ed->ud.skilltarget = bl->id; // Set new target + ed->last_thinktime = tick; + + // Not in skill range. + if( !battle_check_range(&ed->bl,bl,skill_get_range(skillnum,skilllv)) ) { + // Try to walk to the target. + if( !unit_walktobl(&ed->bl, bl, skill_get_range(skillnum,skilllv), 2) ) + elemental_unlocktarget(ed); + else { + // Walking, waiting to be in range. Client don't handle it, then we must handle it here. + int walk_dist = distance_bl(&ed->bl,bl) - skill_get_range(skillnum,skilllv); + ed->ud.skillid = skillnum; + ed->ud.skilllv = skilllv; + + if( skill_get_inf(skillnum) & INF_GROUND_SKILL ) + ed->ud.skilltimer = add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill_castend_pos, ed->bl.id, 0 ); + else + ed->ud.skilltimer = add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill_castend_id, ed->bl.id, 0 ); + } + return 1; + + } + //Otherwise, just cast the skill. + if( skill_get_inf(skillnum) & INF_GROUND_SKILL ) + unit_skilluse_pos(&ed->bl, bl->x, bl->y, skillnum, skilllv); + else + unit_skilluse_id(&ed->bl, bl->id, skillnum, skilllv); + + // Reset target. + ed->target_id = 0; + + return 1; } /*=============================================================== * Action that elemental perform after changing mode. * Activates one of the skills of the new mode. *-------------------------------------------------------------*/ -int elemental_change_mode_ack(struct elemental_data *ed, int mode) -{ - struct block_list *bl = &ed->master->bl; - short skillnum, skilllv; - int i; - - nullpo_ret(ed); - - if (!bl) - return 0; - - // Select a skill. - ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&mode)); - if (i == MAX_ELESKILLTREE) - return 0; - - skillnum = ed->db->skill[i].id; - skilllv = ed->db->skill[i].lv; - - if (elemental_skillnotok(skillnum, ed)) - return 0; - - if (ed->ud.skilltimer != INVALID_TIMER) - return 0; - else if (DIFF_TICK(gettick(), ed->ud.canact_tick) < 0) - return 0; - - ed->target_id = bl->id; // Set new target - ed->last_thinktime = gettick(); - - if (skill_get_inf(skillnum) & INF_GROUND_SKILL) - unit_skilluse_pos(&ed->bl, bl->x, bl->y, skillnum, skilllv); - else - unit_skilluse_id(&ed->bl,bl->id,skillnum,skilllv); - - ed->target_id = 0; // Reset target after casting the skill to avoid continious attack. - - return 1; +int elemental_change_mode_ack(struct elemental_data *ed, int mode) { + struct block_list *bl = &ed->master->bl; + short skillnum, skilllv; + int i; + + nullpo_ret(ed); + + if( !bl ) + return 0; + + // Select a skill. + ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&mode)); + if( i == MAX_ELESKILLTREE ) + return 0; + + skillnum = ed->db->skill[i].id; + skilllv = ed->db->skill[i].lv; + + if( elemental_skillnotok(skillnum, ed) ) + return 0; + + if( ed->ud.skilltimer != INVALID_TIMER ) + return 0; + else if( DIFF_TICK(gettick(), ed->ud.canact_tick) < 0 ) + return 0; + + ed->target_id = bl->id; // Set new target + ed->last_thinktime = gettick(); + + if( skill_get_inf(skillnum) & INF_GROUND_SKILL ) + unit_skilluse_pos(&ed->bl, bl->x, bl->y, skillnum, skilllv); + else + unit_skilluse_id(&ed->bl,bl->id,skillnum,skilllv); + + ed->target_id = 0; // Reset target after casting the skill to avoid continious attack. + + return 1; } /*=============================================================== * Change elemental mode. *-------------------------------------------------------------*/ -int elemental_change_mode(struct elemental_data *ed, int mode) -{ - nullpo_ret(ed); - - // Remove target - elemental_unlocktarget(ed); - - // Removes the effects of the previous mode. - if (ed->elemental.mode != mode) elemental_clean_effect(ed); - - ed->battle_status.mode = ed->elemental.mode = mode; - - // Normalize elemental mode to elemental skill mode. - if (mode == EL_MODE_AGGRESSIVE) mode = EL_SKILLMODE_AGGRESSIVE; // Aggressive spirit mode -> Aggressive spirit skill. - else if (mode == EL_MODE_ASSIST) mode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill. - else mode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill. - - // Use a skill inmediately after every change mode. - if (mode != EL_SKILLMODE_AGGRESSIVE) - elemental_change_mode_ack(ed,mode); - return 1; +int elemental_change_mode(struct elemental_data *ed, int mode) { + nullpo_ret(ed); + + // Remove target + elemental_unlocktarget(ed); + + // Removes the effects of the previous mode. + if(ed->elemental.mode != mode ) elemental_clean_effect(ed); + + ed->battle_status.mode = ed->elemental.mode = mode; + + // Normalize elemental mode to elemental skill mode. + if( mode == EL_MODE_AGGRESSIVE ) mode = EL_SKILLMODE_AGGRESSIVE; // Aggressive spirit mode -> Aggressive spirit skill. + else if( mode == EL_MODE_ASSIST ) mode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill. + else mode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill. + + // Use a skill inmediately after every change mode. + if( mode != EL_SKILLMODE_AGGRESSIVE ) + elemental_change_mode_ack(ed,mode); + return 1; } -void elemental_heal(struct elemental_data *ed, int hp, int sp) -{ - if (hp) - clif_elemental_updatestatus(ed->master, SP_HP); - if (sp) - clif_elemental_updatestatus(ed->master, SP_SP); +void elemental_heal(struct elemental_data *ed, int hp, int sp) { + if( hp ) + clif_elemental_updatestatus(ed->master, SP_HP); + if( sp ) + clif_elemental_updatestatus(ed->master, SP_SP); } -int elemental_dead(struct elemental_data *ed) -{ - elemental_delete(ed, 1); - return 0; +int elemental_dead(struct elemental_data *ed) { + elemental_delete(ed, 1); + return 0; } -int elemental_unlocktarget(struct elemental_data *ed) -{ - nullpo_ret(ed); - - ed->target_id = 0; - elemental_stop_attack(ed); - elemental_stop_walking(ed,1); - return 0; +int elemental_unlocktarget(struct elemental_data *ed) { + nullpo_ret(ed); + + ed->target_id = 0; + elemental_stop_attack(ed); + elemental_stop_walking(ed,1); + return 0; } -int elemental_skillnotok(int skillid, struct elemental_data *ed) -{ - int i = skill_get_index(skillid); - nullpo_retr(1,ed); - - if (i == 0) - return 1; // invalid skill id - - return skillnotok(skillid, ed->master); +int elemental_skillnotok(int skillid, struct elemental_data *ed) { + int i = skill_get_index(skillid); + nullpo_retr(1,ed); + + if (i == 0) + return 1; // invalid skill id + + return skillnotok(skillid, ed->master); } -int elemental_set_target(struct map_session_data *sd, struct block_list *bl) -{ - struct elemental_data *ed = sd->ed; - - nullpo_ret(ed); - nullpo_ret(bl); - - if (ed->bl.m != bl->m || !check_distance_bl(&ed->bl, bl, ed->db->range2)) - return 0; - - if (!status_check_skilluse(&ed->bl, bl, 0, 0)) - return 0; - - if (ed->target_id == 0) - ed->target_id = bl->id; - - return 1; +int elemental_set_target( struct map_session_data *sd, struct block_list *bl ) { + struct elemental_data *ed = sd->ed; + + nullpo_ret(ed); + nullpo_ret(bl); + + if( ed->bl.m != bl->m || !check_distance_bl(&ed->bl, bl, ed->db->range2) ) + return 0; + + if( !status_check_skilluse(&ed->bl, bl, 0, 0) ) + return 0; + + if( ed->target_id == 0 ) + ed->target_id = bl->id; + + return 1; } -static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) -{ - struct elemental_data *ed; - struct block_list **target; - int dist; - - nullpo_ret(bl); - - ed = va_arg(ap,struct elemental_data *); - target = va_arg(ap,struct block_list **); - - //If can't seek yet, not an enemy, or you can't attack it, skip. - if ((*target) == bl || !status_check_skilluse(&ed->bl, bl, 0, 0)) - return 0; - - if (battle_check_target(&ed->bl,bl,BCT_ENEMY) <= 0) - return 0; - - switch (bl->type) { - case BL_PC: - if (!map_flag_vs(ed->bl.m)) - return 0; - default: - dist = distance_bl(&ed->bl, bl); - if (((*target) == NULL || !check_distance_bl(&ed->bl, *target, dist)) && battle_check_range(&ed->bl,bl,ed->db->range2)) { //Pick closest target? - (*target) = bl; - ed->target_id = bl->id; - ed->min_chase = dist + ed->db->range3; - if (ed->min_chase > AREA_SIZE) - ed->min_chase = AREA_SIZE; - return 1; - } - break; - } - return 0; +static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) { + struct elemental_data *ed; + struct block_list **target; + int dist; + + nullpo_ret(bl); + + ed = va_arg(ap,struct elemental_data *); + target = va_arg(ap,struct block_list**); + + //If can't seek yet, not an enemy, or you can't attack it, skip. + if( (*target) == bl || !status_check_skilluse(&ed->bl, bl, 0, 0) ) + return 0; + + if( battle_check_target(&ed->bl,bl,BCT_ENEMY) <= 0 ) + return 0; + + switch( bl->type ) { + case BL_PC: + if( !map_flag_vs(ed->bl.m) ) + return 0; + default: + dist = distance_bl(&ed->bl, bl); + if( ((*target) == NULL || !check_distance_bl(&ed->bl, *target, dist)) && battle_check_range(&ed->bl,bl,ed->db->range2) ) { //Pick closest target? + (*target) = bl; + ed->target_id = bl->id; + ed->min_chase = dist + ed->db->range3; + if( ed->min_chase > AREA_SIZE ) + ed->min_chase = AREA_SIZE; + return 1; + } + break; + } + return 0; } -static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, unsigned int tick) -{ - struct block_list *target = NULL; - int master_dist, view_range, mode; - - nullpo_ret(ed); - nullpo_ret(sd); - - if (ed->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL) - return 0; - - if (DIFF_TICK(tick,ed->last_thinktime) < MIN_ELETHINKTIME) - return 0; - - ed->last_thinktime = tick; - - if (ed->ud.skilltimer != INVALID_TIMER) - return 0; - - if (ed->ud.walktimer != INVALID_TIMER && ed->ud.walkpath.path_pos <= 2) - return 0; //No thinking when you just started to walk. - - if (ed->ud.walkpath.path_pos < ed->ud.walkpath.path_len && ed->ud.target == sd->bl.id) - return 0; //No thinking until be near the master. - - if (ed->sc.count && ed->sc.data[SC_BLIND]) - view_range = 3; - else - view_range = ed->db->range2; - - mode = status_get_mode(&ed->bl); - - master_dist = distance_bl(&sd->bl, &ed->bl); - if (master_dist > AREA_SIZE) { // Master out of vision range. - elemental_unlocktarget(ed); - unit_warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,CLR_TELEPORT); - return 0; - } else if (master_dist > MAX_ELEDISTANCE) { // Master too far, chase. - short x = sd->bl.x, y = sd->bl.y; - if (ed->target_id) - elemental_unlocktarget(ed); - if (ed->ud.walktimer != INVALID_TIMER && ed->ud.target == sd->bl.id) - return 0; //Already walking to him - if (DIFF_TICK(tick, ed->ud.canmove_tick) < 0) - return 0; //Can't move yet. - if (map_search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1) - && unit_walktoxy(&ed->bl, x, y, 0)) - return 0; - } - - if (mode == EL_MODE_AGGRESSIVE) { - target = map_id2bl(ed->ud.target); - - if (!target) - map_foreachinrange(elemental_ai_sub_timer_activesearch, &ed->bl, view_range, BL_CHAR, ed, &target, status_get_mode(&ed->bl)); - - if (!target) { //No targets available. - elemental_unlocktarget(ed); - return 1; - } - - if (battle_check_range(&ed->bl,target,view_range) && rnd()%100 < 2) { // 2% chance to cast attack skill. - if (elemental_action(ed,target,tick)) - return 1; - } - - //Attempt to attack. - //At this point we know the target is attackable, we just gotta check if the range matches. - if (ed->ud.target == target->id && ed->ud.attacktimer != INVALID_TIMER) //Already locked. - return 1; - - if (battle_check_range(&ed->bl, target, ed->base_status.rhw.range)) { //Target within range, engage - unit_attack(&ed->bl,target->id,1); - return 1; - } - - //Follow up if possible. - if (!unit_walktobl(&ed->bl, target, ed->base_status.rhw.range, 2)) - elemental_unlocktarget(ed); - } - - return 0; +static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, unsigned int tick) { + struct block_list *target = NULL; + int master_dist, view_range, mode; + + nullpo_ret(ed); + nullpo_ret(sd); + + if( ed->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL ) + return 0; + + if( DIFF_TICK(tick,ed->last_thinktime) < MIN_ELETHINKTIME ) + return 0; + + ed->last_thinktime = tick; + + if( ed->ud.skilltimer != INVALID_TIMER ) + return 0; + + if( ed->ud.walktimer != INVALID_TIMER && ed->ud.walkpath.path_pos <= 2 ) + return 0; //No thinking when you just started to walk. + + if(ed->ud.walkpath.path_pos < ed->ud.walkpath.path_len && ed->ud.target == sd->bl.id) + return 0; //No thinking until be near the master. + + if( ed->sc.count && ed->sc.data[SC_BLIND] ) + view_range = 3; + else + view_range = ed->db->range2; + + mode = status_get_mode(&ed->bl); + + master_dist = distance_bl(&sd->bl, &ed->bl); + if( master_dist > AREA_SIZE ) { // Master out of vision range. + elemental_unlocktarget(ed); + unit_warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,CLR_TELEPORT); + return 0; + } else if( master_dist > MAX_ELEDISTANCE ) { // Master too far, chase. + short x = sd->bl.x, y = sd->bl.y; + if( ed->target_id ) + elemental_unlocktarget(ed); + if( ed->ud.walktimer != INVALID_TIMER && ed->ud.target == sd->bl.id ) + return 0; //Already walking to him + if( DIFF_TICK(tick, ed->ud.canmove_tick) < 0 ) + return 0; //Can't move yet. + if( map_search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1) + && unit_walktoxy(&ed->bl, x, y, 0) ) + return 0; + } + + if( mode == EL_MODE_AGGRESSIVE ) { + target = map_id2bl(ed->ud.target); + + if( !target ) + map_foreachinrange(elemental_ai_sub_timer_activesearch, &ed->bl, view_range, BL_CHAR, ed, &target, status_get_mode(&ed->bl)); + + if( !target ) { //No targets available. + elemental_unlocktarget(ed); + return 1; + } + + if( battle_check_range(&ed->bl,target,view_range) && rnd()%100 < 2 ) { // 2% chance to cast attack skill. + if( elemental_action(ed,target,tick) ) + return 1; + } + + //Attempt to attack. + //At this point we know the target is attackable, we just gotta check if the range matches. + if( ed->ud.target == target->id && ed->ud.attacktimer != INVALID_TIMER ) //Already locked. + return 1; + + if( battle_check_range(&ed->bl, target, ed->base_status.rhw.range) ) {//Target within range, engage + unit_attack(&ed->bl,target->id,1); + return 1; + } + + //Follow up if possible. + if( !unit_walktobl(&ed->bl, target, ed->base_status.rhw.range, 2) ) + elemental_unlocktarget(ed); + } + + return 0; } -static int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) -{ - unsigned int tick = va_arg(ap,unsigned int); - if (sd->status.ele_id && sd->ed) - elemental_ai_sub_timer(sd->ed,sd,tick); - - return 0; +static int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) { + unsigned int tick = va_arg(ap,unsigned int); + if(sd->status.ele_id && sd->ed) + elemental_ai_sub_timer(sd->ed,sd,tick); + + return 0; } -static int elemental_ai_timer(int tid, unsigned int tick, int id, intptr_t data) -{ - map_foreachpc(elemental_ai_sub_foreachclient,tick); - return 0; +static int elemental_ai_timer(int tid, unsigned int tick, int id, intptr_t data) { + map_foreachpc(elemental_ai_sub_foreachclient,tick); + return 0; } -int read_elementaldb(void) -{ - FILE *fp; - char line[1024], *p; - char *str[26]; - int i, j = 0, k = 0, ele; - struct s_elemental_db *db; - struct status_data *status; - - sprintf(line, "%s/%s", db_path, "elemental_db.txt"); - memset(elemental_db,0,sizeof(elemental_db)); - - fp = fopen(line, "r"); - if (!fp) { - ShowError("read_elementaldb : can't read elemental_db.txt\n"); - return -1; - } - - while (fgets(line, sizeof(line), fp) && j < MAX_ELEMENTAL_CLASS) { - k++; - if (line[0] == '/' && line[1] == '/') - continue; - - if (line[0] == '\0' || line[0] == '\n' || line[0] == '\r') - continue; - - i = 0; - p = strtok(line, ","); - while (p != NULL && i < 26) { - str[i++] = p; - p = strtok(NULL, ","); - } - if (i < 26) { - ShowError("read_elementaldb : Incorrect number of columns at elemental_db.txt line %d.\n", k); - continue; - } - - db = &elemental_db[j]; - db->class_ = atoi(str[0]); - strncpy(db->sprite, str[1], NAME_LENGTH); - strncpy(db->name, str[2], NAME_LENGTH); - db->lv = atoi(str[3]); - - status = &db->status; - db->vd.class_ = db->class_; - - status->max_hp = atoi(str[4]); - status->max_sp = atoi(str[5]); - status->rhw.range = atoi(str[6]); - status->rhw.atk = atoi(str[7]); - status->rhw.atk2 = status->rhw.atk + atoi(str[8]); - status->def = atoi(str[9]); - status->mdef = atoi(str[10]); - status->str = atoi(str[11]); - status->agi = atoi(str[12]); - status->vit = atoi(str[13]); - status->int_ = atoi(str[14]); - status->dex = atoi(str[15]); - status->luk = atoi(str[16]); - db->range2 = atoi(str[17]); - db->range3 = atoi(str[18]); - status->size = atoi(str[19]); - status->race = atoi(str[20]); - - ele = atoi(str[21]); - status->def_ele = ele%10; - status->ele_lv = ele/20; - if (status->def_ele >= ELE_MAX) { - ShowWarning("Elemental %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1); - status->def_ele = ELE_NEUTRAL; - } - if (status->ele_lv < 1 || status->ele_lv > 4) { - ShowWarning("Elemental %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv); - status->ele_lv = 1; - } - - status->aspd_rate = 1000; - status->speed = atoi(str[22]); - status->adelay = atoi(str[23]); - status->amotion = atoi(str[24]); - status->dmotion = atoi(str[25]); - - j++; - } - - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' elementals in '"CL_WHITE"db/elemental_db.txt"CL_RESET"'.\n",j); - - return 0; +int read_elementaldb(void) { + FILE *fp; + char line[1024], *p; + char *str[26]; + int i, j = 0, k = 0, ele; + struct s_elemental_db *db; + struct status_data *status; + + sprintf(line, "%s/%s", db_path, "elemental_db.txt"); + memset(elemental_db,0,sizeof(elemental_db)); + + fp = fopen(line, "r"); + if( !fp ) { + ShowError("read_elementaldb : can't read elemental_db.txt\n"); + return -1; + } + + while( fgets(line, sizeof(line), fp) && j < MAX_ELEMENTAL_CLASS ) { + k++; + if( line[0] == '/' && line[1] == '/' ) + continue; + + if( line[0] == '\0' || line[0] == '\n' || line[0] == '\r') + continue; + + i = 0; + p = strtok(line, ","); + while( p != NULL && i < 26 ) { + str[i++] = p; + p = strtok(NULL, ","); + } + if( i < 26 ) { + ShowError("read_elementaldb : Incorrect number of columns at elemental_db.txt line %d.\n", k); + continue; + } + + db = &elemental_db[j]; + db->class_ = atoi(str[0]); + strncpy(db->sprite, str[1], NAME_LENGTH); + strncpy(db->name, str[2], NAME_LENGTH); + db->lv = atoi(str[3]); + + status = &db->status; + db->vd.class_ = db->class_; + + status->max_hp = atoi(str[4]); + status->max_sp = atoi(str[5]); + status->rhw.range = atoi(str[6]); + status->rhw.atk = atoi(str[7]); + status->rhw.atk2 = status->rhw.atk + atoi(str[8]); + status->def = atoi(str[9]); + status->mdef = atoi(str[10]); + status->str = atoi(str[11]); + status->agi = atoi(str[12]); + status->vit = atoi(str[13]); + status->int_ = atoi(str[14]); + status->dex = atoi(str[15]); + status->luk = atoi(str[16]); + db->range2 = atoi(str[17]); + db->range3 = atoi(str[18]); + status->size = atoi(str[19]); + status->race = atoi(str[20]); + + ele = atoi(str[21]); + status->def_ele = ele%10; + status->ele_lv = ele/20; + if( status->def_ele >= ELE_MAX ) { + ShowWarning("Elemental %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1); + status->def_ele = ELE_NEUTRAL; + } + if( status->ele_lv < 1 || status->ele_lv > 4 ) { + ShowWarning("Elemental %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv); + status->ele_lv = 1; + } + + status->aspd_rate = 1000; + status->speed = atoi(str[22]); + status->adelay = atoi(str[23]); + status->amotion = atoi(str[24]); + status->dmotion = atoi(str[25]); + + j++; + } + + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' elementals in '"CL_WHITE"db/elemental_db.txt"CL_RESET"'.\n",j); + + return 0; } -int read_elemental_skilldb(void) -{ - FILE *fp; - char line[1024], *p; - char *str[4]; - struct s_elemental_db *db; - int i, j = 0, k = 0, class_; - int skillid, skilllv, skillmode; - - sprintf(line, "%s/%s", db_path, "elemental_skill_db.txt"); - fp = fopen(line, "r"); - if (!fp) { - ShowError("read_elemental_skilldb : can't read elemental_skill_db.txt\n"); - return -1; - } - - while (fgets(line, sizeof(line), fp)) { - k++; - if (line[0] == '/' && line[1] == '/') - continue; - - if (line[0] == '\0' || line[0] == '\n' || line[0] == '\r') - continue; - - i = 0; - p = strtok(line, ","); - while (p != NULL && i < 4) { - str[i++] = p; - p = strtok(NULL, ","); - } - if (i < 4) { - ShowError("read_elemental_skilldb : Incorrect number of columns at elemental_skill_db.txt line %d.\n", k); - continue; - } - - class_ = atoi(str[0]); - ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, class_ == elemental_db[i].class_); - if (i == MAX_ELEMENTAL_CLASS) { - ShowError("read_elemental_skilldb : Class not found in elemental_db for skill entry, line %d.\n", k); - continue; - } - - skillid = atoi(str[1]); - if (skillid < EL_SKILLBASE || skillid >= EL_SKILLBASE + MAX_ELEMENTALSKILL) { - ShowError("read_elemental_skilldb : Skill out of range, line %d.\n", k); - continue; - } - - db = &elemental_db[i]; - skilllv = atoi(str[2]); - - skillmode = atoi(str[3]); - if (skillmode < EL_SKILLMODE_PASIVE || skillmode > EL_SKILLMODE_AGGRESSIVE) { - ShowError("read_elemental_skilldb : Skillmode out of range, line %d.\n",k); - continue; - } - ARR_FIND(0, MAX_ELESKILLTREE, i, db->skill[i].id == 0 || db->skill[i].id == skillid); - if (i == MAX_ELESKILLTREE) { - ShowWarning("Unable to load skill %d into Elemental %d's tree. Maximum number of skills per elemental has been reached.\n", skillid, class_); - continue; - } - db->skill[i].id = skillid; - db->skill[i].lv = skilllv; - db->skill[i].mode = skillmode; - j++; - } - - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"db/elemental_skill_db.txt"CL_RESET"'.\n",j); - return 0; +int read_elemental_skilldb(void) { + FILE *fp; + char line[1024], *p; + char *str[4]; + struct s_elemental_db *db; + int i, j = 0, k = 0, class_; + int skillid, skilllv, skillmode; + + sprintf(line, "%s/%s", db_path, "elemental_skill_db.txt"); + fp = fopen(line, "r"); + if( !fp ) { + ShowError("read_elemental_skilldb : can't read elemental_skill_db.txt\n"); + return -1; + } + + while( fgets(line, sizeof(line), fp) ) { + k++; + if( line[0] == '/' && line[1] == '/' ) + continue; + + if( line[0] == '\0' || line[0] == '\n' || line[0] == '\r') + continue; + + i = 0; + p = strtok(line, ","); + while( p != NULL && i < 4 ) { + str[i++] = p; + p = strtok(NULL, ","); + } + if( i < 4 ) { + ShowError("read_elemental_skilldb : Incorrect number of columns at elemental_skill_db.txt line %d.\n", k); + continue; + } + + class_ = atoi(str[0]); + ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, class_ == elemental_db[i].class_); + if( i == MAX_ELEMENTAL_CLASS ) { + ShowError("read_elemental_skilldb : Class not found in elemental_db for skill entry, line %d.\n", k); + continue; + } + + skillid = atoi(str[1]); + if( skillid < EL_SKILLBASE || skillid >= EL_SKILLBASE + MAX_ELEMENTALSKILL ) { + ShowError("read_elemental_skilldb : Skill out of range, line %d.\n", k); + continue; + } + + db = &elemental_db[i]; + skilllv = atoi(str[2]); + + skillmode = atoi(str[3]); + if( skillmode < EL_SKILLMODE_PASIVE || skillmode > EL_SKILLMODE_AGGRESSIVE ) { + ShowError("read_elemental_skilldb : Skillmode out of range, line %d.\n",k); + continue; + } + ARR_FIND( 0, MAX_ELESKILLTREE, i, db->skill[i].id == 0 || db->skill[i].id == skillid ); + if( i == MAX_ELESKILLTREE ) { + ShowWarning("Unable to load skill %d into Elemental %d's tree. Maximum number of skills per elemental has been reached.\n", skillid, class_); + continue; + } + db->skill[i].id = skillid; + db->skill[i].lv = skilllv; + db->skill[i].mode = skillmode; + j++; + } + + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"db/elemental_skill_db.txt"CL_RESET"'.\n",j); + return 0; } -void reload_elementaldb(void) -{ - read_elementaldb(); - reload_elemental_skilldb(); +void reload_elementaldb(void) { + read_elementaldb(); + reload_elemental_skilldb(); } -void reload_elemental_skilldb(void) -{ - read_elemental_skilldb(); +void reload_elemental_skilldb(void) { + read_elemental_skilldb(); } -int do_init_elemental(void) -{ - read_elementaldb(); - read_elemental_skilldb(); - - add_timer_func_list(elemental_ai_timer,"elemental_ai_timer"); - add_timer_interval(gettick()+MIN_ELETHINKTIME,elemental_ai_timer,0,0,MIN_ELETHINKTIME); - - return 0; +int do_init_elemental(void) { + read_elementaldb(); + read_elemental_skilldb(); + + add_timer_func_list(elemental_ai_timer,"elemental_ai_timer"); + add_timer_interval(gettick()+MIN_ELETHINKTIME,elemental_ai_timer,0,0,MIN_ELETHINKTIME); + + return 0; } -void do_final_elemental(void) -{ - return; +void do_final_elemental(void) { + return; } diff --git a/src/map/elemental.h b/src/map/elemental.h index 221ae3b9f..1f99bcba9 100644 --- a/src/map/elemental.h +++ b/src/map/elemental.h @@ -20,44 +20,44 @@ #define EL_SKILLMODE_AGGRESSIVE 0x4 struct elemental_skill { - unsigned short id, lv; - short mode; + unsigned short id, lv; + short mode; }; struct s_elemental_db { - int class_; - char sprite[NAME_LENGTH], name[NAME_LENGTH]; - unsigned short lv; - short range2, range3; - struct status_data status; - struct view_data vd; - struct elemental_skill skill[MAX_ELESKILLTREE]; + int class_; + char sprite[NAME_LENGTH], name[NAME_LENGTH]; + unsigned short lv; + short range2, range3; + struct status_data status; + struct view_data vd; + struct elemental_skill skill[MAX_ELESKILLTREE]; }; extern struct s_elemental_db elemental_db[MAX_ELEMENTAL_CLASS]; struct elemental_data { - struct block_list bl; - struct unit_data ud; - struct view_data *vd; - struct status_data base_status, battle_status; - struct status_change sc; - struct regen_data regen; - - struct s_elemental_db *db; - struct s_elemental elemental; - - struct map_session_data *master; - int summon_timer; - int skill_timer; - - unsigned last_thinktime, last_linktime; - short min_chase; - int target_id, attacked_id; + struct block_list bl; + struct unit_data ud; + struct view_data *vd; + struct status_data base_status, battle_status; + struct status_change sc; + struct regen_data regen; + + struct s_elemental_db *db; + struct s_elemental elemental; + + struct map_session_data *master; + int summon_timer; + int skill_timer; + + unsigned last_thinktime, last_linktime; + short min_chase; + int target_id, attacked_id; }; bool elemental_class(int class_); -struct view_data *elemental_get_viewdata(int class_); +struct view_data * elemental_get_viewdata(int class_); int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime); int elemental_data_received(struct s_elemental *ele, bool flag); @@ -76,7 +76,7 @@ int elemental_get_lifetime(struct elemental_data *ed); int elemental_unlocktarget(struct elemental_data *ed); int elemental_skillnotok(int skillid, struct elemental_data *ed); -int elemental_set_target(struct map_session_data *sd, struct block_list *bl); +int elemental_set_target( struct map_session_data *sd, struct block_list *bl ); int elemental_clean_single_effect(struct elemental_data *ed, int skill_num); int elemental_clean_effect(struct elemental_data *ed); int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick); diff --git a/src/map/guild.c b/src/map/guild.c index b276114be..9eeae7cf1 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -29,37 +29,37 @@ #include <string.h> -static DBMap *guild_db; // int guild_id -> struct guild* -static DBMap *castle_db; // int castle_id -> struct guild_castle* -static DBMap *guild_expcache_db; // int char_id -> struct guild_expcache* -static DBMap *guild_infoevent_db; // int guild_id -> struct eventlist* +static DBMap* guild_db; // int guild_id -> struct guild* +static DBMap* castle_db; // int castle_id -> struct guild_castle* +static DBMap* guild_expcache_db; // int char_id -> struct guild_expcache* +static DBMap* guild_infoevent_db; // int guild_id -> struct eventlist* struct eventlist { - char name[EVENT_NAME_LENGTH]; - struct eventlist *next; + char name[EVENT_NAME_LENGTH]; + struct eventlist *next; }; //Constant related to the flash of the Guild EXP cache -#define GUILD_SEND_XY_INVERVAL 5000 // Interval of sending coordinates and HP +#define GUILD_SEND_XY_INVERVAL 5000 // Interval of sending coordinates and HP #define GUILD_PAYEXP_INVERVAL 10000 //Interval (maximum survival time of the cache, in milliseconds) #define GUILD_PAYEXP_LIST 8192 //The maximum number of cache //Guild EXP cache struct guild_expcache { - int guild_id, account_id, char_id; - uint64 exp; + int guild_id, account_id, char_id; + uint64 exp; }; static struct eri *expcache_ers; //For handling of guild exp payment. #define MAX_GUILD_SKILL_REQUIRE 5 -struct { - int id; - int max; - struct { - short id; - short lv; - } need[MAX_GUILD_SKILL_REQUIRE]; +struct{ + int id; + int max; + struct{ + short id; + short lv; + }need[MAX_GUILD_SKILL_REQUIRE]; } guild_skill_tree[MAX_GUILDSKILL]; int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data); @@ -72,34 +72,33 @@ unsigned short guild_flags_count; /*========================================== * Retrieves and validates the sd pointer for this guild member [Skotlex] *------------------------------------------*/ -static TBL_PC *guild_sd_check(int guild_id, int account_id, int char_id) +static TBL_PC* guild_sd_check(int guild_id, int account_id, int char_id) { - TBL_PC *sd = map_id2sd(account_id); + TBL_PC* sd = map_id2sd(account_id); - if (!(sd && sd->status.char_id == char_id)) - return NULL; + if (!(sd && sd->status.char_id == char_id)) + return NULL; - if (sd->status.guild_id != guild_id) { - //If player belongs to a different guild, kick him out. - intif_guild_leave(guild_id,account_id,char_id,0,"** Guild Mismatch **"); - return NULL; - } + if (sd->status.guild_id != guild_id) + { //If player belongs to a different guild, kick him out. + intif_guild_leave(guild_id,account_id,char_id,0,"** Guild Mismatch **"); + return NULL; + } - return sd; + return sd; } -// Modified [Komurka] -int guild_skill_get_max(int id) + // Modified [Komurka] +int guild_skill_get_max (int id) { - if (id < GD_SKILLBASE || id >= GD_SKILLBASE+MAX_GUILDSKILL) - return 0; - return guild_skill_tree[id-GD_SKILLBASE].max; + if (id < GD_SKILLBASE || id >= GD_SKILLBASE+MAX_GUILDSKILL) + return 0; + return guild_skill_tree[id-GD_SKILLBASE].max; } // Retrive skilllv learned by guild -int guild_checkskill(struct guild *g, int id) -{ +int guild_checkskill(struct guild *g, int id) { int idx = id - GD_SKILLBASE; if (idx < 0 || idx >= MAX_GUILDSKILL) return 0; @@ -109,33 +108,34 @@ int guild_checkskill(struct guild *g, int id) /*========================================== * guild_skill_tree.txt reading - from jA [Komurka] *------------------------------------------*/ -static bool guild_read_guildskill_tree_db(char *split[], int columns, int current) -{ - // <skill id>,<max lv>,<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5> - int k, id, skillid; +static bool guild_read_guildskill_tree_db(char* split[], int columns, int current) +{// <skill id>,<max lv>,<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5> + int k, id, skillid; - skillid = atoi(split[0]); - id = skillid - GD_SKILLBASE; + skillid = atoi(split[0]); + id = skillid - GD_SKILLBASE; - if (id < 0 || id >= MAX_GUILDSKILL) { - ShowWarning("guild_read_guildskill_tree_db: Invalid skill id %d.\n", skillid); - return false; - } + if( id < 0 || id >= MAX_GUILDSKILL ) + { + ShowWarning("guild_read_guildskill_tree_db: Invalid skill id %d.\n", skillid); + return false; + } - guild_skill_tree[id].id = skillid; - guild_skill_tree[id].max = atoi(split[1]); + guild_skill_tree[id].id = skillid; + guild_skill_tree[id].max = atoi(split[1]); - if (guild_skill_tree[id].id == GD_GLORYGUILD && battle_config.require_glory_guild && guild_skill_tree[id].max == 0) { - // enable guild's glory when required for emblems - guild_skill_tree[id].max = 1; - } + if( guild_skill_tree[id].id == GD_GLORYGUILD && battle_config.require_glory_guild && guild_skill_tree[id].max == 0 ) + {// enable guild's glory when required for emblems + guild_skill_tree[id].max = 1; + } - for (k = 0; k < MAX_GUILD_SKILL_REQUIRE; k++) { - guild_skill_tree[id].need[k].id = atoi(split[k*2+2]); - guild_skill_tree[id].need[k].lv = atoi(split[k*2+3]); - } + for( k = 0; k < MAX_GUILD_SKILL_REQUIRE; k++ ) + { + guild_skill_tree[id].need[k].id = atoi(split[k*2+2]); + guild_skill_tree[id].need[k].lv = atoi(split[k*2+3]); + } - return true; + return true; } /*========================================== @@ -143,179 +143,186 @@ static bool guild_read_guildskill_tree_db(char *split[], int columns, int curren *------------------------------------------*/ int guild_check_skill_require(struct guild *g,int id) { - int i; - int idx = id-GD_SKILLBASE; + int i; + int idx = id-GD_SKILLBASE; - if (g == NULL) - return 0; + if(g == NULL) + return 0; - if (idx < 0 || idx >= MAX_GUILDSKILL) - return 0; + if (idx < 0 || idx >= MAX_GUILDSKILL) + return 0; - for (i=0; i<MAX_GUILD_SKILL_REQUIRE; i++) { - if (guild_skill_tree[idx].need[i].id == 0) break; - if (guild_skill_tree[idx].need[i].lv > guild_checkskill(g,guild_skill_tree[idx].need[i].id)) - return 0; - } - return 1; + for(i=0;i<MAX_GUILD_SKILL_REQUIRE;i++) + { + if(guild_skill_tree[idx].need[i].id == 0) break; + if(guild_skill_tree[idx].need[i].lv > guild_checkskill(g,guild_skill_tree[idx].need[i].id)) + return 0; + } + return 1; } -static bool guild_read_castledb(char *str[], int columns, int current) -{ - // <castle id>,<map name>,<castle name>,<castle event>[,<reserved/unused switch flag>] - struct guild_castle *gc; - int mapindex = mapindex_name2id(str[1]); +static bool guild_read_castledb(char* str[], int columns, int current) +{// <castle id>,<map name>,<castle name>,<castle event>[,<reserved/unused switch flag>] + struct guild_castle *gc; + int mapindex = mapindex_name2id(str[1]); - if (map_mapindex2mapid(mapindex) < 0) // Map not found or on another map-server - return false; + if (map_mapindex2mapid(mapindex) < 0) // Map not found or on another map-server + return false; - CREATE(gc, struct guild_castle, 1); - gc->castle_id = atoi(str[0]); - gc->mapindex = mapindex; - safestrncpy(gc->castle_name, str[2], sizeof(gc->castle_name)); - safestrncpy(gc->castle_event, str[3], sizeof(gc->castle_event)); + CREATE(gc, struct guild_castle, 1); + gc->castle_id = atoi(str[0]); + gc->mapindex = mapindex; + safestrncpy(gc->castle_name, str[2], sizeof(gc->castle_name)); + safestrncpy(gc->castle_event, str[3], sizeof(gc->castle_event)); - idb_put(castle_db,gc->castle_id,gc); + idb_put(castle_db,gc->castle_id,gc); - //intif_guild_castle_info(gc->castle_id); + //intif_guild_castle_info(gc->castle_id); - return true; + return true; } /// lookup: guild id -> guild* -struct guild *guild_search(int guild_id) { - return (struct guild *)idb_get(guild_db,guild_id); +struct guild* guild_search(int guild_id) +{ + return (struct guild*)idb_get(guild_db,guild_id); } /// lookup: guild name -> guild* -struct guild *guild_searchname(char *str) { - struct guild *g; - DBIterator *iter = db_iterator(guild_db); +struct guild* guild_searchname(char* str) +{ + struct guild* g; + DBIterator *iter = db_iterator(guild_db); - for (g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter)) { - if (strcmpi(g->name, str) == 0) - break; - } - dbi_destroy(iter); + for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) + { + if( strcmpi(g->name, str) == 0 ) + break; + } + dbi_destroy(iter); - return g; + return g; } /// lookup: castle id -> castle* -struct guild_castle *guild_castle_search(int gcid) { - return (struct guild_castle *)idb_get(castle_db,gcid); +struct guild_castle* guild_castle_search(int gcid) +{ + return (struct guild_castle*)idb_get(castle_db,gcid); } /// lookup: map index -> castle* -struct guild_castle *guild_mapindex2gc(short mapindex) { - struct guild_castle *gc; - DBIterator *iter = db_iterator(castle_db); +struct guild_castle* guild_mapindex2gc(short mapindex) +{ + struct guild_castle* gc; + DBIterator *iter = db_iterator(castle_db); - for (gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) { - if (gc->mapindex == mapindex) - break; - } - dbi_destroy(iter); + for( gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter) ) + { + if( gc->mapindex == mapindex ) + break; + } + dbi_destroy(iter); - return gc; + return gc; } /// lookup: map name -> castle* -struct guild_castle *guild_mapname2gc(const char *mapname) { - return guild_mapindex2gc(mapindex_name2id(mapname)); +struct guild_castle* guild_mapname2gc(const char* mapname) +{ + return guild_mapindex2gc(mapindex_name2id(mapname)); } -struct map_session_data *guild_getavailablesd(struct guild *g) { - int i; +struct map_session_data* guild_getavailablesd(struct guild* g) +{ + int i; - nullpo_retr(NULL, g); + nullpo_retr(NULL, g); - ARR_FIND(0, g->max_member, i, g->member[i].sd != NULL); - return(i < g->max_member) ? g->member[i].sd : NULL; + ARR_FIND( 0, g->max_member, i, g->member[i].sd != NULL ); + return( i < g->max_member ) ? g->member[i].sd : NULL; } /// lookup: player AID/CID -> member index int guild_getindex(struct guild *g,int account_id,int char_id) { - int i; + int i; - if (g == NULL) - return -1; + if( g == NULL ) + return -1; - ARR_FIND(0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id); - return(i < g->max_member) ? i : -1; + ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id ); + return( i < g->max_member ) ? i : -1; } /// lookup: player sd -> member position -int guild_getposition(struct guild *g, struct map_session_data *sd) +int guild_getposition(struct guild* g, struct map_session_data* sd) { - int i; - - if (g == NULL && (g=guild_search(sd->status.guild_id)) == NULL) - return -1; + int i; - ARR_FIND(0, g->max_member, i, g->member[i].account_id == sd->status.account_id && g->member[i].char_id == sd->status.char_id); - return(i < g->max_member) ? g->member[i].position : -1; + if( g == NULL && (g=guild_search(sd->status.guild_id)) == NULL ) + return -1; + + ARR_FIND( 0, g->max_member, i, g->member[i].account_id == sd->status.account_id && g->member[i].char_id == sd->status.char_id ); + return( i < g->max_member ) ? g->member[i].position : -1; } //Creation of member information void guild_makemember(struct guild_member *m,struct map_session_data *sd) { - nullpo_retv(sd); + nullpo_retv(sd); - memset(m,0,sizeof(struct guild_member)); - m->account_id =sd->status.account_id; - m->char_id =sd->status.char_id; - m->hair =sd->status.hair; - m->hair_color =sd->status.hair_color; - m->gender =sd->status.sex; - m->class_ =sd->status.class_; - m->lv =sd->status.base_level; - // m->exp =0; - // m->exp_payper =0; - m->online =1; - m->position =MAX_GUILDPOSITION-1; - memcpy(m->name,sd->status.name,NAME_LENGTH); - return; + memset(m,0,sizeof(struct guild_member)); + m->account_id =sd->status.account_id; + m->char_id =sd->status.char_id; + m->hair =sd->status.hair; + m->hair_color =sd->status.hair_color; + m->gender =sd->status.sex; + m->class_ =sd->status.class_; + m->lv =sd->status.base_level; +// m->exp =0; +// m->exp_payper =0; + m->online =1; + m->position =MAX_GUILDPOSITION-1; + memcpy(m->name,sd->status.name,NAME_LENGTH); + return; } /** * Server cache to be flushed to inter the Guild EXP * @see DBApply */ -int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) -{ - int i; - struct guild_expcache *c; - struct guild *g; - - c = db_data2ptr(data); - - if ( - (g = guild_search(c->guild_id)) == NULL || - (i = guild_getindex(g, c->account_id, c->char_id)) < 0 - ) { - ers_free(expcache_ers, c); - return 0; - } - - if (g->member[i].exp > UINT64_MAX - c->exp) - g->member[i].exp = UINT64_MAX; - else - g->member[i].exp+= c->exp; - - intif_guild_change_memberinfo(g->guild_id,c->account_id,c->char_id, - GMI_EXP,&g->member[i].exp,sizeof(g->member[i].exp)); - c->exp=0; - - ers_free(expcache_ers, c); - return 0; +int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) { + int i; + struct guild_expcache *c; + struct guild *g; + + c = db_data2ptr(data); + + if ( + (g = guild_search(c->guild_id)) == NULL || + (i = guild_getindex(g, c->account_id, c->char_id)) < 0 + ) { + ers_free(expcache_ers, c); + return 0; + } + + if (g->member[i].exp > UINT64_MAX - c->exp) + g->member[i].exp = UINT64_MAX; + else + g->member[i].exp+= c->exp; + + intif_guild_change_memberinfo(g->guild_id,c->account_id,c->char_id, + GMI_EXP,&g->member[i].exp,sizeof(g->member[i].exp)); + c->exp=0; + + ers_free(expcache_ers, c); + return 0; } int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data) { - guild_expcache_db->clear(guild_expcache_db,guild_payexp_timer_sub); - return 0; + guild_expcache_db->clear(guild_expcache_db,guild_payexp_timer_sub); + return 0; } /** @@ -324,218 +331,226 @@ int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data) */ int guild_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) { - struct guild *g = db_data2ptr(data); - int i; + struct guild *g = db_data2ptr(data); + int i; - nullpo_ret(g); + nullpo_ret(g); - if (!g->connect_member) { - // no members connected to this guild so do not iterate - return 0; - } + if( !g->connect_member ) + {// no members connected to this guild so do not iterate + return 0; + } - for (i=0; i<g->max_member; i++) { - struct map_session_data *sd = g->member[i].sd; - if (sd != NULL && sd->fd && (sd->guild_x != sd->bl.x || sd->guild_y != sd->bl.y) && !sd->bg_id) { - clif_guild_xy(sd); - sd->guild_x = sd->bl.x; - sd->guild_y = sd->bl.y; - } - } - return 0; + for(i=0;i<g->max_member;i++){ + struct map_session_data* sd = g->member[i].sd; + if( sd != NULL && sd->fd && (sd->guild_x != sd->bl.x || sd->guild_y != sd->bl.y) && !sd->bg_id ) + { + clif_guild_xy(sd); + sd->guild_x = sd->bl.x; + sd->guild_y = sd->bl.y; + } + } + return 0; } //Code from party_send_xy_timer [Skotlex] static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) { - guild_db->foreach(guild_db,guild_send_xy_timer_sub,tick); - return 0; + guild_db->foreach(guild_db,guild_send_xy_timer_sub,tick); + return 0; } int guild_send_dot_remove(struct map_session_data *sd) { - if (sd->status.guild_id) - clif_guild_xy_remove(sd); - return 0; + if (sd->status.guild_id) + clif_guild_xy_remove(sd); + return 0; } //------------------------------------------------------------------------ int guild_create(struct map_session_data *sd, const char *name) { - char tname[NAME_LENGTH]; - struct guild_member m; - nullpo_ret(sd); + char tname[NAME_LENGTH]; + struct guild_member m; + nullpo_ret(sd); - safestrncpy(tname, name, NAME_LENGTH); - trim(tname); + safestrncpy(tname, name, NAME_LENGTH); + trim(tname); - if (!tname[0]) - return 0; // empty name + if( !tname[0] ) + return 0; // empty name - if (sd->status.guild_id) { - // already in a guild - clif_guild_created(sd,1); - return 0; - } - if (battle_config.guild_emperium_check && pc_search_inventory(sd,714) == -1) { - // item required - clif_guild_created(sd,3); - return 0; - } + if( sd->status.guild_id ) + {// already in a guild + clif_guild_created(sd,1); + return 0; + } + if( battle_config.guild_emperium_check && pc_search_inventory(sd,714) == -1 ) + {// item required + clif_guild_created(sd,3); + return 0; + } - guild_makemember(&m,sd); - m.position=0; - intif_guild_create(name,&m); - return 1; + guild_makemember(&m,sd); + m.position=0; + intif_guild_create(name,&m); + return 1; } //Whether or not to create guild int guild_created(int account_id,int guild_id) { - struct map_session_data *sd=map_id2sd(account_id); + struct map_session_data *sd=map_id2sd(account_id); - if (sd==NULL) - return 0; - if (!guild_id) { + if(sd==NULL) + return 0; + if(!guild_id) { clif_guild_created(sd, 2); // Creation failure (presence of the same name Guild) - return 0; - } - //struct guild *g; - sd->status.guild_id=guild_id; - clif_guild_created(sd,0); - if (battle_config.guild_emperium_check) - pc_delitem(sd,pc_search_inventory(sd,ITEMID_EMPERIUM),1,0,0,LOG_TYPE_CONSUME); //emperium consumption - return 0; + return 0; + } + //struct guild *g; + sd->status.guild_id=guild_id; + clif_guild_created(sd,0); + if(battle_config.guild_emperium_check) + pc_delitem(sd,pc_search_inventory(sd,ITEMID_EMPERIUM),1,0,0,LOG_TYPE_CONSUME); //emperium consumption + return 0; } //Information request int guild_request_info(int guild_id) { - return intif_guild_request_info(guild_id); + return intif_guild_request_info(guild_id); } //Information request with event int guild_npc_request_info(int guild_id,const char *event) { - if (guild_search(guild_id)) { - if (event && *event) - npc_event_do(event); + if( guild_search(guild_id) ) + { + if( event && *event ) + npc_event_do(event); - return 0; - } + return 0; + } - if (event && *event) { - struct eventlist *ev; - DBData prev; - ev=(struct eventlist *)aCalloc(sizeof(struct eventlist),1); - memcpy(ev->name,event,strlen(event)); - //The one in the db (if present) becomes the next event from this. - if (guild_infoevent_db->put(guild_infoevent_db, db_i2key(guild_id), db_ptr2data(ev), &prev)) - ev->next = db_data2ptr(&prev); - } + if( event && *event ) + { + struct eventlist *ev; + DBData prev; + ev=(struct eventlist *)aCalloc(sizeof(struct eventlist),1); + memcpy(ev->name,event,strlen(event)); + //The one in the db (if present) becomes the next event from this. + if (guild_infoevent_db->put(guild_infoevent_db, db_i2key(guild_id), db_ptr2data(ev), &prev)) + ev->next = db_data2ptr(&prev); + } - return guild_request_info(guild_id); + return guild_request_info(guild_id); } //Confirmation of the character belongs to guild int guild_check_member(struct guild *g) { - int i; - struct map_session_data *sd; - struct s_mapiterator *iter; + int i; + struct map_session_data *sd; + struct s_mapiterator* iter; - nullpo_ret(g); + nullpo_ret(g); - iter = mapit_getallusers(); - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) { - if (sd->status.guild_id != g->guild_id) - continue; + iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + { + if( sd->status.guild_id != g->guild_id ) + continue; - i = guild_getindex(g,sd->status.account_id,sd->status.char_id); - if (i < 0) { - sd->status.guild_id=0; - sd->guild_emblem_id=0; - ShowWarning("guild: check_member %d[%s] is not member\n",sd->status.account_id,sd->status.name); - } - } - mapit_free(iter); + i = guild_getindex(g,sd->status.account_id,sd->status.char_id); + if (i < 0) { + sd->status.guild_id=0; + sd->guild_emblem_id=0; + ShowWarning("guild: check_member %d[%s] is not member\n",sd->status.account_id,sd->status.name); + } + } + mapit_free(iter); - return 0; + return 0; } //Delete association with guild_id for all characters int guild_recv_noinfo(int guild_id) { - struct map_session_data *sd; - struct s_mapiterator *iter; + struct map_session_data *sd; + struct s_mapiterator* iter; - iter = mapit_getallusers(); - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) { - if (sd->status.guild_id == guild_id) - sd->status.guild_id = 0; // erase guild - } - mapit_free(iter); + iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + { + if( sd->status.guild_id == guild_id ) + sd->status.guild_id = 0; // erase guild + } + mapit_free(iter); - return 0; + return 0; } //Get and display information for all member int guild_recv_info(struct guild *sg) { - struct guild *g,before; - int i,bm,m; - DBData data; - struct map_session_data *sd; - bool guild_new = false; + struct guild *g,before; + int i,bm,m; + DBData data; + struct map_session_data *sd; + bool guild_new = false; - nullpo_ret(sg); + nullpo_ret(sg); - if ((g = (struct guild *)idb_get(guild_db,sg->guild_id))==NULL) { - guild_new = true; - g=(struct guild *)aCalloc(1,sizeof(struct guild)); - idb_put(guild_db,sg->guild_id,g); - before=*sg; + if((g = (struct guild*)idb_get(guild_db,sg->guild_id))==NULL) + { + guild_new = true; + g=(struct guild *)aCalloc(1,sizeof(struct guild)); + idb_put(guild_db,sg->guild_id,g); + before=*sg; //Perform the check on the user because the first load - guild_check_member(sg); - if ((sd = map_nick2sd(sg->master)) != NULL) { - //If the guild master is online the first time the guild_info is received, - //that means he was the first to join, so apply guild skill blocking here. - if (battle_config.guild_skill_relog_delay) - guild_block_skill(sd, 300000); - - //Also set the guild master flag. - sd->state.gmaster_flag = g; - clif_charnameupdate(sd); // [LuzZza] - clif_guild_masterormember(sd); - } - } else - before=*g; - memcpy(g,sg,sizeof(struct guild)); - - if (g->max_member > MAX_GUILD) { - ShowError("guild_recv_info: Received guild with %d members, but MAX_GUILD is only %d. Extra guild-members have been lost!\n", g->max_member, MAX_GUILD); - g->max_member = MAX_GUILD; - } - - for (i=bm=m=0; i<g->max_member; i++) { - if (g->member[i].account_id>0) { - sd = g->member[i].sd = guild_sd_check(g->guild_id, g->member[i].account_id, g->member[i].char_id); - if (sd) clif_charnameupdate(sd); // [LuzZza] - m++; - } else - g->member[i].sd=NULL; - if (before.member[i].account_id>0) - bm++; - } + guild_check_member(sg); + if ((sd = map_nick2sd(sg->master)) != NULL) + { + //If the guild master is online the first time the guild_info is received, + //that means he was the first to join, so apply guild skill blocking here. + if( battle_config.guild_skill_relog_delay ) + guild_block_skill(sd, 300000); + + //Also set the guild master flag. + sd->state.gmaster_flag = g; + clif_charnameupdate(sd); // [LuzZza] + clif_guild_masterormember(sd); + } + }else + before=*g; + memcpy(g,sg,sizeof(struct guild)); + + if(g->max_member > MAX_GUILD) + { + ShowError("guild_recv_info: Received guild with %d members, but MAX_GUILD is only %d. Extra guild-members have been lost!\n", g->max_member, MAX_GUILD); + g->max_member = MAX_GUILD; + } + + for(i=bm=m=0;i<g->max_member;i++){ + if(g->member[i].account_id>0){ + sd = g->member[i].sd = guild_sd_check(g->guild_id, g->member[i].account_id, g->member[i].char_id); + if (sd) clif_charnameupdate(sd); // [LuzZza] + m++; + }else + g->member[i].sd=NULL; + if(before.member[i].account_id>0) + bm++; + } for (i = 0; i < g->max_member; i++) { //Transmission of information at all members - sd = g->member[i].sd; - if (sd==NULL) - continue; + sd = g->member[i].sd; + if( sd==NULL ) + continue; if (before.guild_lv != g->guild_lv || bm != m || - before.max_member != g->max_member) { + before.max_member != g->max_member) { clif_guild_basicinfo(sd); //Submit basic information clif_guild_emblem(sd, g); //Submit emblem } @@ -555,122 +570,126 @@ int guild_recv_info(struct guild *sg) } //Occurrence of an event - if (guild_infoevent_db->remove(guild_infoevent_db, db_i2key(sg->guild_id), &data)) { - struct eventlist *ev = db_data2ptr(&data), *ev2; - while (ev) { - npc_event_do(ev->name); - ev2=ev->next; - aFree(ev); - ev=ev2; - } - } + if (guild_infoevent_db->remove(guild_infoevent_db, db_i2key(sg->guild_id), &data)) + { + struct eventlist *ev = db_data2ptr(&data), *ev2; + while(ev){ + npc_event_do(ev->name); + ev2=ev->next; + aFree(ev); + ev=ev2; + } + } - return 0; + return 0; } /*============================================= * Player sd send a guild invatation to player tsd to join his guild *--------------------------------------------*/ -int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) -{ +int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) { struct guild *g; int i; - nullpo_ret(sd); + nullpo_ret(sd); - g=guild_search(sd->status.guild_id); + g=guild_search(sd->status.guild_id); - if (tsd==NULL || g==NULL) - return 0; + if(tsd==NULL || g==NULL) + return 0; - if ((i=guild_getposition(g,sd))<0 || !(g->position[i].mode&0x0001)) - return 0; //Invite permission. + if( (i=guild_getposition(g,sd))<0 || !(g->position[i].mode&0x0001) ) + return 0; //Invite permission. - if (!battle_config.invite_request_check) { + if(!battle_config.invite_request_check) { if (tsd->party_invite > 0 || tsd->trade_partner || tsd->adopt_invite) { //checking if there no other invitation pending - clif_guild_inviteack(sd,0); - return 0; - } - } - - if (!tsd->fd) { //You can't invite someone who has already disconnected. - clif_guild_inviteack(sd,1); - return 0; - } - - if (tsd->status.guild_id>0 || - tsd->guild_invite>0 || - ((agit_flag || agit2_flag) && map[tsd->bl.m].flag.gvg_castle)) { - //Can't invite people inside castles. [Skotlex] - clif_guild_inviteack(sd,0); - return 0; - } + clif_guild_inviteack(sd,0); + return 0; + } + } + + if (!tsd->fd) { //You can't invite someone who has already disconnected. + clif_guild_inviteack(sd,1); + return 0; + } + + if(tsd->status.guild_id>0 || + tsd->guild_invite>0 || + ((agit_flag || agit2_flag) && map[tsd->bl.m].flag.gvg_castle)) + { //Can't invite people inside castles. [Skotlex] + clif_guild_inviteack(sd,0); + return 0; + } //search an empty spot in guild - ARR_FIND(0, g->max_member, i, g->member[i].account_id == 0); - if (i==g->max_member) { - clif_guild_inviteack(sd,3); - return 0; - } + ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 ); + if(i==g->max_member){ + clif_guild_inviteack(sd,3); + return 0; + } - tsd->guild_invite=sd->status.guild_id; - tsd->guild_invite_account=sd->status.account_id; + tsd->guild_invite=sd->status.guild_id; + tsd->guild_invite_account=sd->status.account_id; - clif_guild_invite(tsd,g); - return 0; + clif_guild_invite(tsd,g); + return 0; } /// Guild invitation reply. /// flag: 0:rejected, 1:accepted -int guild_reply_invite(struct map_session_data *sd, int guild_id, int flag) -{ - struct map_session_data *tsd; - - nullpo_ret(sd); - - // subsequent requests may override the value - if (sd->guild_invite != guild_id) - return 0; // mismatch - - // look up the person who sent the invite - //NOTE: this can be NULL because the person might have logged off in the meantime - tsd = map_id2sd(sd->guild_invite_account); - - if (sd->status.guild_id > 0) { // [Paradox924X] - // Already in another guild. - if (tsd) clif_guild_inviteack(tsd,0); - return 0; - } else if (flag == 0) { - // rejected - sd->guild_invite = 0; - sd->guild_invite_account = 0; - if (tsd) clif_guild_inviteack(tsd,1); - } else { - // accepted - struct guild_member m; - struct guild *g; - int i; - - if ((g=guild_search(guild_id)) == NULL) { - sd->guild_invite = 0; - sd->guild_invite_account = 0; - return 0; - } - - ARR_FIND(0, g->max_member, i, g->member[i].account_id == 0); - if (i == g->max_member) { - sd->guild_invite = 0; - sd->guild_invite_account = 0; - if (tsd) clif_guild_inviteack(tsd,3); - return 0; - } - - guild_makemember(&m,sd); - intif_guild_addmember(guild_id, &m); - //TODO: send a minimap update to this player - } - - return 0; +int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) +{ + struct map_session_data* tsd; + + nullpo_ret(sd); + + // subsequent requests may override the value + if( sd->guild_invite != guild_id ) + return 0; // mismatch + + // look up the person who sent the invite + //NOTE: this can be NULL because the person might have logged off in the meantime + tsd = map_id2sd(sd->guild_invite_account); + + if ( sd->status.guild_id > 0 ) // [Paradox924X] + { // Already in another guild. + if ( tsd ) clif_guild_inviteack(tsd,0); + return 0; + } + else if( flag == 0 ) + {// rejected + sd->guild_invite = 0; + sd->guild_invite_account = 0; + if( tsd ) clif_guild_inviteack(tsd,1); + } + else + {// accepted + struct guild_member m; + struct guild* g; + int i; + + if( (g=guild_search(guild_id)) == NULL ) + { + sd->guild_invite = 0; + sd->guild_invite_account = 0; + return 0; + } + + ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 ); + if( i == g->max_member ) + { + sd->guild_invite = 0; + sd->guild_invite_account = 0; + if( tsd ) clif_guild_inviteack(tsd,3); + return 0; + } + + guild_makemember(&m,sd); + intif_guild_addmember(guild_id, &m); + //TODO: send a minimap update to this player + } + + return 0; } //Invoked when a player joins. @@ -679,25 +698,25 @@ int guild_reply_invite(struct map_session_data *sd, int guild_id, int flag) //- Player must be authed and must belong to a guild before invoking this method void guild_member_joined(struct map_session_data *sd) { - struct guild *g; - int i; - g=guild_search(sd->status.guild_id); - if (!g) { - guild_request_info(sd->status.guild_id); - return; - } - if (strcmp(sd->status.name,g->master) == 0) { - // set the Guild Master flag - sd->state.gmaster_flag = g; - // prevent Guild Skills from being used directly after relog - if (battle_config.guild_skill_relog_delay) - guild_block_skill(sd, 300000); - } - i = guild_getindex(g, sd->status.account_id, sd->status.char_id); - if (i == -1) - sd->status.guild_id = 0; - else - g->member[i].sd = sd; + struct guild* g; + int i; + g=guild_search(sd->status.guild_id); + if (!g) { + guild_request_info(sd->status.guild_id); + return; + } + if (strcmp(sd->status.name,g->master) == 0) + { // set the Guild Master flag + sd->state.gmaster_flag = g; + // prevent Guild Skills from being used directly after relog + if( battle_config.guild_skill_relog_delay ) + guild_block_skill(sd, 300000); + } + i = guild_getindex(g, sd->status.account_id, sd->status.char_id); + if (i == -1) + sd->status.guild_id = 0; + else + g->member[i].sd = sd; } /*========================================== @@ -705,246 +724,245 @@ void guild_member_joined(struct map_session_data *sd) *----------------------------------------*/ int guild_member_added(int guild_id,int account_id,int char_id,int flag) { - struct map_session_data *sd= map_id2sd(account_id),*sd2; - struct guild *g; + struct map_session_data *sd= map_id2sd(account_id),*sd2; + struct guild *g; - if ((g=guild_search(guild_id))==NULL) - return 0; + if( (g=guild_search(guild_id))==NULL ) + return 0; - if (sd==NULL || sd->guild_invite==0) { + if(sd==NULL || sd->guild_invite==0){ // cancel if player not present or invalide guild_id invitation - if (flag == 0) { - ShowError("guild: member added error %d is not online\n",account_id); - intif_guild_leave(guild_id,account_id,char_id,0,"** Data Error **"); - } - return 0; - } - sd2 = map_id2sd(sd->guild_invite_account); - sd->guild_invite = 0; - sd->guild_invite_account = 0; + if (flag == 0) { + ShowError("guild: member added error %d is not online\n",account_id); + intif_guild_leave(guild_id,account_id,char_id,0,"** Data Error **"); + } + return 0; + } + sd2 = map_id2sd(sd->guild_invite_account); + sd->guild_invite = 0; + sd->guild_invite_account = 0; if (flag == 1) { //failure - if (sd2!=NULL) - clif_guild_inviteack(sd2,3); - return 0; - } + if( sd2!=NULL ) + clif_guild_inviteack(sd2,3); + return 0; + } //if all ok add player to guild - sd->status.guild_id = g->guild_id; - sd->guild_emblem_id = g->emblem_id; - //Packets which were sent in the previous 'guild_sent' implementation. - clif_guild_belonginfo(sd,g); - clif_guild_notice(sd,g); + sd->status.guild_id = g->guild_id; + sd->guild_emblem_id = g->emblem_id; + //Packets which were sent in the previous 'guild_sent' implementation. + clif_guild_belonginfo(sd,g); + clif_guild_notice(sd,g); - //TODO: send new emblem info to others + //TODO: send new emblem info to others - if (sd2!=NULL) - clif_guild_inviteack(sd2,2); + if( sd2!=NULL ) + clif_guild_inviteack(sd2,2); - //Next line commented because it do nothing, look at guild_recv_info [LuzZza] - //clif_charnameupdate(sd); //Update display name [Skotlex] + //Next line commented because it do nothing, look at guild_recv_info [LuzZza] + //clif_charnameupdate(sd); //Update display name [Skotlex] - return 0; + return 0; } /*========================================== * Player request leaving a given guild_id *----------------------------------------*/ -int guild_leave(struct map_session_data *sd, int guild_id, int account_id, int char_id, const char *mes) +int guild_leave(struct map_session_data* sd, int guild_id, int account_id, int char_id, const char* mes) { - struct guild *g; + struct guild *g; - nullpo_ret(sd); + nullpo_ret(sd); - g = guild_search(sd->status.guild_id); + g = guild_search(sd->status.guild_id); - if (g==NULL) - return 0; + if(g==NULL) + return 0; - if (sd->status.account_id!=account_id || - sd->status.char_id!=char_id || sd->status.guild_id!=guild_id || - ((agit_flag || agit2_flag) && map[sd->bl.m].flag.gvg_castle)) - return 0; + if(sd->status.account_id!=account_id || + sd->status.char_id!=char_id || sd->status.guild_id!=guild_id || + ((agit_flag || agit2_flag) && map[sd->bl.m].flag.gvg_castle)) + return 0; - intif_guild_leave(sd->status.guild_id, sd->status.account_id, sd->status.char_id,0,mes); - return 0; + intif_guild_leave(sd->status.guild_id, sd->status.account_id, sd->status.char_id,0,mes); + return 0; } /*========================================== * Request remove a player to a given guild_id *----------------------------------------*/ -int guild_expulsion(struct map_session_data *sd, int guild_id, int account_id, int char_id, const char *mes) +int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, int char_id, const char* mes) { - struct map_session_data *tsd; - struct guild *g; - int i,ps; + struct map_session_data *tsd; + struct guild *g; + int i,ps; - nullpo_ret(sd); + nullpo_ret(sd); - g = guild_search(sd->status.guild_id); + g = guild_search(sd->status.guild_id); - if (g==NULL) - return 0; + if(g==NULL) + return 0; - if (sd->status.guild_id!=guild_id) - return 0; + if(sd->status.guild_id!=guild_id) + return 0; - if ((ps=guild_getposition(g,sd))<0 || !(g->position[ps].mode&0x0010)) - return 0; //Expulsion permission + if( (ps=guild_getposition(g,sd))<0 || !(g->position[ps].mode&0x0010) ) + return 0; //Expulsion permission - //Can't leave inside guild castles. - if ((tsd = map_id2sd(account_id)) && - tsd->status.char_id == char_id && - ((agit_flag || agit2_flag) && map[tsd->bl.m].flag.gvg_castle)) - return 0; + //Can't leave inside guild castles. + if ((tsd = map_id2sd(account_id)) && + tsd->status.char_id == char_id && + ((agit_flag || agit2_flag) && map[tsd->bl.m].flag.gvg_castle)) + return 0; - // find the member and perform expulsion - i = guild_getindex(g, account_id, char_id); - if (i != -1 && strcmp(g->member[i].name,g->master) != 0) //Can't expel the GL! - intif_guild_leave(g->guild_id,account_id,char_id,1,mes); + // find the member and perform expulsion + i = guild_getindex(g, account_id, char_id); + if( i != -1 && strcmp(g->member[i].name,g->master) != 0 ) //Can't expel the GL! + intif_guild_leave(g->guild_id,account_id,char_id,1,mes); - return 0; + return 0; } -int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, const char *name, const char *mes) +int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, const char* name, const char* mes) { - int i; - struct guild *g = guild_search(guild_id); - struct map_session_data *sd = map_charid2sd(char_id); - struct map_session_data *online_member_sd; - - if (g == NULL) - return 0; // no such guild (error!) - - i = guild_getindex(g, account_id, char_id); - if (i == -1) - return 0; // not a member (inconsistency!) - - online_member_sd = guild_getavailablesd(g); - if (online_member_sd == NULL) - return 0; // noone online to inform - - if (!flag) - clif_guild_leave(online_member_sd, name, mes); - else - clif_guild_expulsion(online_member_sd, name, mes, account_id); - - // remove member from guild - memset(&g->member[i],0,sizeof(struct guild_member)); - clif_guild_memberlist(online_member_sd); - - // update char, if online - if (sd != NULL && sd->status.guild_id == guild_id) { - // do stuff that needs the guild_id first, BEFORE we wipe it - if (sd->state.storage_flag == 2) //Close the guild storage. - storage_guild_storageclose(sd); - guild_send_dot_remove(sd); - - sd->status.guild_id = 0; - sd->guild_emblem_id = 0; - - clif_charnameupdate(sd); //Update display name [Skotlex] - //TODO: send emblem update to self and people around - } - return 0; -} + int i; + struct guild* g = guild_search(guild_id); + struct map_session_data* sd = map_charid2sd(char_id); + struct map_session_data* online_member_sd; -int guild_send_memberinfoshort(struct map_session_data *sd,int online) -{ - // cleaned up [LuzZza] - struct guild *g; + if(g == NULL) + return 0; // no such guild (error!) + + i = guild_getindex(g, account_id, char_id); + if( i == -1 ) + return 0; // not a member (inconsistency!) - nullpo_ret(sd); + online_member_sd = guild_getavailablesd(g); + if(online_member_sd == NULL) + return 0; // noone online to inform - if (sd->status.guild_id <= 0) - return 0; + if(!flag) + clif_guild_leave(online_member_sd, name, mes); + else + clif_guild_expulsion(online_member_sd, name, mes, account_id); - if (!(g = guild_search(sd->status.guild_id))) - return 0; + // remove member from guild + memset(&g->member[i],0,sizeof(struct guild_member)); + clif_guild_memberlist(online_member_sd); - intif_guild_memberinfoshort(g->guild_id, - sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class_); + // update char, if online + if(sd != NULL && sd->status.guild_id == guild_id) + { + // do stuff that needs the guild_id first, BEFORE we wipe it + if (sd->state.storage_flag == 2) //Close the guild storage. + storage_guild_storageclose(sd); + guild_send_dot_remove(sd); - if (!online) { - int i=guild_getindex(g,sd->status.account_id,sd->status.char_id); - if (i>=0) - g->member[i].sd=NULL; - else - ShowError("guild_send_memberinfoshort: Failed to locate member %d:%d in guild %d!\n", sd->status.account_id, sd->status.char_id, g->guild_id); - return 0; - } + sd->status.guild_id = 0; + sd->guild_emblem_id = 0; + + clif_charnameupdate(sd); //Update display name [Skotlex] + //TODO: send emblem update to self and people around + } + return 0; +} - if (sd->state.connect_new) { - //Note that this works because it is invoked in parse_LoadEndAck before connect_new is cleared. - clif_guild_belonginfo(sd,g); - clif_guild_notice(sd,g); - sd->guild_emblem_id = g->emblem_id; - } - return 0; +int guild_send_memberinfoshort(struct map_session_data *sd,int online) +{ // cleaned up [LuzZza] + struct guild *g; + + nullpo_ret(sd); + + if(sd->status.guild_id <= 0) + return 0; + + if(!(g = guild_search(sd->status.guild_id))) + return 0; + + intif_guild_memberinfoshort(g->guild_id, + sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class_); + + if(!online){ + int i=guild_getindex(g,sd->status.account_id,sd->status.char_id); + if(i>=0) + g->member[i].sd=NULL; + else + ShowError("guild_send_memberinfoshort: Failed to locate member %d:%d in guild %d!\n", sd->status.account_id, sd->status.char_id, g->guild_id); + return 0; + } + + if(sd->state.connect_new) + { //Note that this works because it is invoked in parse_LoadEndAck before connect_new is cleared. + clif_guild_belonginfo(sd,g); + clif_guild_notice(sd,g); + sd->guild_emblem_id = g->emblem_id; + } + return 0; } int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) -{ - // cleaned up [LuzZza] - - int i,alv,c,idx=-1,om=0,oldonline=-1; - struct guild *g = guild_search(guild_id); - - if (g == NULL) - return 0; - - for (i=0,alv=0,c=0,om=0; i<g->max_member; i++) { - struct guild_member *m=&g->member[i]; - if (!m->account_id) continue; - if (m->account_id==account_id && m->char_id==char_id) { - oldonline=m->online; - m->online=online; - m->lv=lv; - m->class_=class_; - idx=i; - } - alv+=m->lv; - c++; - if (m->online) - om++; - } - - if (idx == -1 || c == 0) { +{ // cleaned up [LuzZza] + + int i,alv,c,idx=-1,om=0,oldonline=-1; + struct guild *g = guild_search(guild_id); + + if(g == NULL) + return 0; + + for(i=0,alv=0,c=0,om=0;i<g->max_member;i++){ + struct guild_member *m=&g->member[i]; + if(!m->account_id) continue; + if(m->account_id==account_id && m->char_id==char_id ){ + oldonline=m->online; + m->online=online; + m->lv=lv; + m->class_=class_; + idx=i; + } + alv+=m->lv; + c++; + if(m->online) + om++; + } + + if(idx == -1 || c == 0) { //Treat char_id who doesn't match guild_id (not found as member) - struct map_session_data *sd = map_id2sd(account_id); - if (sd && sd->status.char_id == char_id) { - sd->status.guild_id=0; - sd->guild_emblem_id=0; - } - ShowWarning("guild: not found member %d,%d on %d[%s]\n", account_id,char_id,guild_id,g->name); - return 0; - } - - g->average_lv=alv/c; - g->connect_member=om; - - //Ensure validity of pointer (ie: player logs in/out, changes map-server) - g->member[idx].sd = guild_sd_check(guild_id, account_id, char_id); - - if (oldonline!=online) - clif_guild_memberlogin_notice(g, idx, online); - - if (!g->member[idx].sd) - return 0; - - //Send XY dot updates. [Skotlex] - //Moved from guild_send_memberinfoshort [LuzZza] - for (i=0; i < g->max_member; i++) { - - if (!g->member[i].sd || i == idx || - g->member[i].sd->bl.m != g->member[idx].sd->bl.m) - continue; - - clif_guild_xy_single(g->member[idx].sd->fd, g->member[i].sd); - clif_guild_xy_single(g->member[i].sd->fd, g->member[idx].sd); - } - - return 0; + struct map_session_data *sd = map_id2sd(account_id); + if(sd && sd->status.char_id == char_id) { + sd->status.guild_id=0; + sd->guild_emblem_id=0; + } + ShowWarning("guild: not found member %d,%d on %d[%s]\n", account_id,char_id,guild_id,g->name); + return 0; + } + + g->average_lv=alv/c; + g->connect_member=om; + + //Ensure validity of pointer (ie: player logs in/out, changes map-server) + g->member[idx].sd = guild_sd_check(guild_id, account_id, char_id); + + if(oldonline!=online) + clif_guild_memberlogin_notice(g, idx, online); + + if(!g->member[idx].sd) + return 0; + + //Send XY dot updates. [Skotlex] + //Moved from guild_send_memberinfoshort [LuzZza] + for(i=0; i < g->max_member; i++) { + + if(!g->member[i].sd || i == idx || + g->member[i].sd->bl.m != g->member[idx].sd->bl.m) + continue; + + clif_guild_xy_single(g->member[idx].sd->fd, g->member[i].sd); + clif_guild_xy_single(g->member[i].sd->fd, g->member[idx].sd); + } + + return 0; } /*==================================================== @@ -952,17 +970,17 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin *---------------------------------------------------*/ int guild_send_message(struct map_session_data *sd,const char *mes,int len) { - nullpo_ret(sd); + nullpo_ret(sd); - 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); + 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); - // Chat logging type 'G' / Guild Chat - log_chat(LOG_CHAT_GUILD, sd->status.guild_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes); + // Chat logging type 'G' / Guild Chat + log_chat(LOG_CHAT_GUILD, sd->status.guild_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes); - return 0; + return 0; } /*==================================================== @@ -970,11 +988,11 @@ int guild_send_message(struct map_session_data *sd,const char *mes,int len) *---------------------------------------------------*/ int guild_recv_message(int guild_id,int account_id,const char *mes,int len) { - struct guild *g; - if ((g=guild_search(guild_id))==NULL) - return 0; - clif_guild_message(g,account_id,mes,len); - return 0; + struct guild *g; + if( (g=guild_search(guild_id))==NULL) + return 0; + clif_guild_message(g,account_id,mes,len); + return 0; } /*==================================================== @@ -982,7 +1000,7 @@ int guild_recv_message(int guild_id,int account_id,const char *mes,int len) *---------------------------------------------------*/ int guild_change_memberposition(int guild_id,int account_id,int char_id,short idx) { - return intif_guild_change_memberinfo(guild_id,account_id,char_id,GMI_POSITION,&idx,sizeof(idx)); + return intif_guild_change_memberinfo(guild_id,account_id,char_id,GMI_POSITION,&idx,sizeof(idx)); } /*==================================================== @@ -990,32 +1008,32 @@ int guild_change_memberposition(int guild_id,int account_id,int char_id,short id *---------------------------------------------------*/ int guild_memberposition_changed(struct guild *g,int idx,int pos) { - nullpo_ret(g); - - g->member[idx].position=pos; - clif_guild_memberpositionchanged(g,idx); + nullpo_ret(g); - // Update char position in client [LuzZza] - if (g->member[idx].sd != NULL) - clif_charnameupdate(g->member[idx].sd); - return 0; + g->member[idx].position=pos; + clif_guild_memberpositionchanged(g,idx); + + // Update char position in client [LuzZza] + if(g->member[idx].sd != NULL) + clif_charnameupdate(g->member[idx].sd); + return 0; } /*==================================================== * Change guild title or member *---------------------------------------------------*/ int guild_change_position(int guild_id,int idx, - int mode,int exp_mode,const char *name) + int mode,int exp_mode,const char *name) { - struct guild_position p; + struct guild_position p; - exp_mode = cap_value(exp_mode, 0, battle_config.guild_exp_limit); - //Mode 0x01 <- Invite - //Mode 0x10 <- Expel. - p.mode=mode&0x11; - p.exp_mode=exp_mode; - safestrncpy(p.name,name,NAME_LENGTH); - return intif_guild_position(guild_id,idx,&p); + exp_mode = cap_value(exp_mode, 0, battle_config.guild_exp_limit); + //Mode 0x01 <- Invite + //Mode 0x10 <- Expel. + p.mode=mode&0x11; + p.exp_mode=exp_mode; + safestrncpy(p.name,name,NAME_LENGTH); + return intif_guild_position(guild_id,idx,&p); } /*==================================================== @@ -1023,18 +1041,18 @@ int guild_change_position(int guild_id,int idx, *---------------------------------------------------*/ int guild_position_changed(int guild_id,int idx,struct guild_position *p) { - struct guild *g=guild_search(guild_id); - int i; - if (g==NULL) - return 0; - memcpy(&g->position[idx],p,sizeof(struct guild_position)); - clif_guild_positionchanged(g,idx); - - // Update char name in client [LuzZza] - for (i=0; i<g->max_member; i++) - if (g->member[i].position == idx && g->member[i].sd != NULL) - clif_charnameupdate(g->member[i].sd); - return 0; + struct guild *g=guild_search(guild_id); + int i; + if(g==NULL) + return 0; + memcpy(&g->position[idx],p,sizeof(struct guild_position)); + clif_guild_positionchanged(g,idx); + + // Update char name in client [LuzZza] + for(i=0;i<g->max_member;i++) + if(g->member[i].position == idx && g->member[i].sd != NULL) + clif_charnameupdate(g->member[i].sd); + return 0; } /*==================================================== @@ -1042,11 +1060,11 @@ int guild_position_changed(int guild_id,int idx,struct guild_position *p) *---------------------------------------------------*/ int guild_change_notice(struct map_session_data *sd,int guild_id,const char *mes1,const char *mes2) { - nullpo_ret(sd); + nullpo_ret(sd); - if (guild_id!=sd->status.guild_id) - return 0; - return intif_guild_notice(guild_id,mes1,mes2); + if(guild_id!=sd->status.guild_id) + return 0; + return intif_guild_notice(guild_id,mes1,mes2); } /*==================================================== @@ -1054,20 +1072,20 @@ int guild_change_notice(struct map_session_data *sd,int guild_id,const char *mes *---------------------------------------------------*/ int guild_notice_changed(int guild_id,const char *mes1,const char *mes2) { - int i; - struct map_session_data *sd; - struct guild *g=guild_search(guild_id); - if (g==NULL) - return 0; + int i; + struct map_session_data *sd; + struct guild *g=guild_search(guild_id); + if(g==NULL) + return 0; - memcpy(g->mes1,mes1,MAX_GUILDMES1); - memcpy(g->mes2,mes2,MAX_GUILDMES2); + memcpy(g->mes1,mes1,MAX_GUILDMES1); + memcpy(g->mes2,mes2,MAX_GUILDMES2); - for (i=0; i<g->max_member; i++) { - if ((sd=g->member[i].sd)!=NULL) - clif_guild_notice(sd,g); - } - return 0; + for(i=0;i<g->max_member;i++){ + if((sd=g->member[i].sd)!=NULL) + clif_guild_notice(sd,g); + } + return 0; } /*==================================================== @@ -1075,16 +1093,16 @@ int guild_notice_changed(int guild_id,const char *mes1,const char *mes2) *---------------------------------------------------*/ int guild_change_emblem(struct map_session_data *sd,int len,const char *data) { - struct guild *g; - nullpo_ret(sd); + struct guild *g; + nullpo_ret(sd); - 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,USESKILL_FAIL_LEVEL,0); - return 0; - } + 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,USESKILL_FAIL_LEVEL,0); + return 0; + } - return intif_guild_emblem(sd->status.guild_id,len,data); + return intif_guild_emblem(sd->status.guild_id,len,data); } /*==================================================== @@ -1092,59 +1110,60 @@ int guild_change_emblem(struct map_session_data *sd,int len,const char *data) *---------------------------------------------------*/ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) { - int i; - struct map_session_data *sd; - struct guild *g=guild_search(guild_id); - if (g==NULL) - return 0; - - memcpy(g->emblem_data,data,len); - g->emblem_len=len; - g->emblem_id=emblem_id; - - for (i=0; i<g->max_member; i++) { - if ((sd=g->member[i].sd)!=NULL) { - sd->guild_emblem_id=emblem_id; - clif_guild_belonginfo(sd,g); - clif_guild_emblem(sd,g); - clif_guild_emblem_area(&sd->bl); - } - } - { - // update guardians (mobs) - DBIterator *iter = db_iterator(castle_db); - struct guild_castle *gc; - for (gc = (struct guild_castle *)dbi_first(iter) ; dbi_exists(iter); gc = (struct guild_castle *)dbi_next(iter)) { - if (gc->guild_id != guild_id) - continue; - // update permanent guardians - for (i = 0; i < ARRAYLENGTH(gc->guardian); ++i) { - TBL_MOB *md = (gc->guardian[i].id ? map_id2md(gc->guardian[i].id) : NULL); - if (md == NULL || md->guardian_data == NULL) - continue; - md->guardian_data->emblem_id = emblem_id; - clif_guild_emblem_area(&md->bl); - } - // update temporary guardians - for (i = 0; i < gc->temp_guardians_max; ++i) { - TBL_MOB *md = (gc->temp_guardians[i] ? map_id2md(gc->temp_guardians[i]) : NULL); - if (md == NULL || md->guardian_data == NULL) - continue; - md->guardian_data->emblem_id = emblem_id; - clif_guild_emblem_area(&md->bl); - } - } - dbi_destroy(iter); - } - { - // update npcs (flags or other npcs that used flagemblem to attach to this guild) - for (i = 0; i < guild_flags_count; i++) { - if (guild_flags[i] && guild_flags[i]->u.scr.guild_id == guild_id) { - clif_guild_emblem_area(&guild_flags[i]->bl); - } - } - } - return 0; + int i; + struct map_session_data *sd; + struct guild *g=guild_search(guild_id); + if(g==NULL) + return 0; + + memcpy(g->emblem_data,data,len); + g->emblem_len=len; + g->emblem_id=emblem_id; + + for(i=0;i<g->max_member;i++){ + if((sd=g->member[i].sd)!=NULL){ + sd->guild_emblem_id=emblem_id; + clif_guild_belonginfo(sd,g); + clif_guild_emblem(sd,g); + clif_guild_emblem_area(&sd->bl); + } + } + {// update guardians (mobs) + DBIterator* iter = db_iterator(castle_db); + struct guild_castle* gc; + for( gc = (struct guild_castle*)dbi_first(iter) ; dbi_exists(iter); gc = (struct guild_castle*)dbi_next(iter) ) + { + if( gc->guild_id != guild_id ) + continue; + // update permanent guardians + for( i = 0; i < ARRAYLENGTH(gc->guardian); ++i ) + { + TBL_MOB* md = (gc->guardian[i].id ? map_id2md(gc->guardian[i].id) : NULL); + if( md == NULL || md->guardian_data == NULL ) + continue; + md->guardian_data->emblem_id = emblem_id; + clif_guild_emblem_area(&md->bl); + } + // update temporary guardians + for( i = 0; i < gc->temp_guardians_max; ++i ) + { + TBL_MOB* md = (gc->temp_guardians[i] ? map_id2md(gc->temp_guardians[i]) : NULL); + if( md == NULL || md->guardian_data == NULL ) + continue; + md->guardian_data->emblem_id = emblem_id; + clif_guild_emblem_area(&md->bl); + } + } + dbi_destroy(iter); + } + {// update npcs (flags or other npcs that used flagemblem to attach to this guild) + for( i = 0; i < guild_flags_count; i++ ) { + if( guild_flags[i] && guild_flags[i]->u.scr.guild_id == guild_id ) { + clif_guild_emblem_area(&guild_flags[i]->bl); + } + } + } + return 0; } /** @@ -1152,15 +1171,15 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) */ static DBData create_expcache(DBKey key, va_list args) { - struct guild_expcache *c; - struct map_session_data *sd = va_arg(args, struct map_session_data *); + struct guild_expcache *c; + struct map_session_data *sd = va_arg(args, struct map_session_data*); - c = ers_alloc(expcache_ers, 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 = 0; - return db_ptr2data(c); + c = ers_alloc(expcache_ers, 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 = 0; + return db_ptr2data(c); } /*==================================================== @@ -1168,33 +1187,33 @@ static DBData create_expcache(DBKey key, va_list args) *---------------------------------------------------*/ unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) { - struct guild *g; - struct guild_expcache *c; - int per; - - nullpo_ret(sd); - - if (!exp) return 0; - - if (sd->status.guild_id == 0 || - (g = guild_search(sd->status.guild_id)) == NULL || - (per = guild_getposition(g,sd)) < 0 || - (per = g->position[per].exp_mode) < 1) - return 0; - - - if (per < 100) - exp = exp * per / 100; - //Otherwise tax everything. - - c = db_data2ptr(guild_expcache_db->ensure(guild_expcache_db, db_i2key(sd->status.char_id), create_expcache, sd)); - - if (c->exp > UINT64_MAX - exp) - c->exp = UINT64_MAX; - else - c->exp += exp; - - return exp; + struct guild *g; + struct guild_expcache *c; + int per; + + nullpo_ret(sd); + + if (!exp) return 0; + + if (sd->status.guild_id == 0 || + (g = guild_search(sd->status.guild_id)) == NULL || + (per = guild_getposition(g,sd)) < 0 || + (per = g->position[per].exp_mode) < 1) + return 0; + + + if (per < 100) + exp = exp * per / 100; + //Otherwise tax everything. + + c = db_data2ptr(guild_expcache_db->ensure(guild_expcache_db, db_i2key(sd->status.char_id), create_expcache, sd)); + + if (c->exp > UINT64_MAX - exp) + c->exp = UINT64_MAX; + else + c->exp += exp; + + return exp; } /*==================================================== @@ -1204,42 +1223,42 @@ unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) *---------------------------------------------------*/ int guild_getexp(struct map_session_data *sd,int exp) { - struct guild_expcache *c; - nullpo_ret(sd); + struct guild_expcache *c; + nullpo_ret(sd); - if (sd->status.guild_id == 0 || guild_search(sd->status.guild_id) == NULL) - return 0; + if (sd->status.guild_id == 0 || guild_search(sd->status.guild_id) == NULL) + return 0; - c = db_data2ptr(guild_expcache_db->ensure(guild_expcache_db, db_i2key(sd->status.char_id), create_expcache, sd)); - if (c->exp > UINT64_MAX - exp) - c->exp = UINT64_MAX; - else - c->exp += exp; - return exp; + c = db_data2ptr(guild_expcache_db->ensure(guild_expcache_db, db_i2key(sd->status.char_id), create_expcache, sd)); + if (c->exp > UINT64_MAX - exp) + c->exp = UINT64_MAX; + else + c->exp += exp; + return exp; } /*==================================================== * Ask to increase guildskill skill_num *---------------------------------------------------*/ -int guild_skillup(TBL_PC *sd, int skill_num) +int guild_skillup(TBL_PC* sd, int skill_num) { - struct guild *g; - int idx = skill_num - GD_SKILLBASE; - int max = guild_skill_get_max(skill_num); + struct guild* g; + int idx = skill_num - GD_SKILLBASE; + int max = guild_skill_get_max(skill_num); - nullpo_ret(sd); + nullpo_ret(sd); - if (idx < 0 || idx >= MAX_GUILDSKILL || // not a guild skill - sd->status.guild_id == 0 || (g=guild_search(sd->status.guild_id)) == NULL || // no guild - strcmp(sd->status.name, g->master)) // not the guild master - return 0; + if( idx < 0 || idx >= MAX_GUILDSKILL || // not a guild skill + sd->status.guild_id == 0 || (g=guild_search(sd->status.guild_id)) == NULL || // no guild + strcmp(sd->status.name, g->master) ) // not the guild master + return 0; - if (g->skill_point > 0 && - g->skill[idx].id != 0 && - g->skill[idx].lv < max) - intif_guild_skillup(g->guild_id, skill_num, sd->status.account_id, max); + if( g->skill_point > 0 && + g->skill[idx].id != 0 && + g->skill[idx].lv < max ) + intif_guild_skillup(g->guild_id, skill_num, sd->status.account_id, max); - return 0; + return 0; } /*==================================================== @@ -1247,100 +1266,99 @@ int guild_skillup(TBL_PC *sd, int skill_num) *---------------------------------------------------*/ int guild_skillupack(int guild_id,int skill_num,int account_id) { - struct map_session_data *sd=map_id2sd(account_id); - struct guild *g=guild_search(guild_id); - int i; - if (g==NULL) - return 0; - if (sd != NULL) { - clif_guild_skillup(sd,skill_num,g->skill[skill_num-GD_SKILLBASE].lv); - - /* Guild Aura handling */ - switch (skill_num) { - case GD_LEADERSHIP: - case GD_GLORYWOUNDS: - case GD_SOULCOLD: - case GD_HAWKEYES: - guild_guildaura_refresh(sd,skill_num,g->skill[skill_num-GD_SKILLBASE].lv); - break; - } - } - - // Inform all members - for (i=0; i<g->max_member; i++) - if ((sd=g->member[i].sd)!=NULL) - clif_guild_skillinfo(sd); - - return 0; -} - -void guild_guildaura_refresh(struct map_session_data *sd, int skill_num, int skill_lv) -{ - struct skill_unit_group *group = NULL; - int type = status_skill2sc(skill_num); - if (!(battle_config.guild_aura&((agit_flag || agit2_flag)?2:1)) && - !(battle_config.guild_aura&(map_flag_gvg2(sd->bl.m)?8:4))) - return; - if (skill_lv <= 0) - return; - if (sd->sc.data[type] && (group = skill_id2group(sd->sc.data[type]->val4))) { - skill_delunitgroup(group); - status_change_end(&sd->bl,type,INVALID_TIMER); - } - group = skill_unitsetting(&sd->bl,skill_num,skill_lv,sd->bl.x,sd->bl.y,0); - if (group) { - sc_start4(&sd->bl,type,100,(battle_config.guild_aura&16)?0:skill_lv,0,0,group->group_id,600000);//duration doesn't matter these status never end with val4 - } - return; + struct map_session_data *sd=map_id2sd(account_id); + struct guild *g=guild_search(guild_id); + int i; + if(g==NULL) + return 0; + if( sd != NULL ) { + clif_guild_skillup(sd,skill_num,g->skill[skill_num-GD_SKILLBASE].lv); + + /* Guild Aura handling */ + switch( skill_num ) { + case GD_LEADERSHIP: + case GD_GLORYWOUNDS: + case GD_SOULCOLD: + case GD_HAWKEYES: + guild_guildaura_refresh(sd,skill_num,g->skill[skill_num-GD_SKILLBASE].lv); + break; + } + } + + // Inform all members + for(i=0;i<g->max_member;i++) + if((sd=g->member[i].sd)!=NULL) + clif_guild_skillinfo(sd); + + return 0; +} + +void guild_guildaura_refresh(struct map_session_data *sd, int skill_num, int skill_lv) { + struct skill_unit_group* group = NULL; + int type = status_skill2sc(skill_num); + if( !(battle_config.guild_aura&((agit_flag || agit2_flag)?2:1)) && + !(battle_config.guild_aura&(map_flag_gvg2(sd->bl.m)?8:4)) ) + return; + if( skill_lv <= 0 ) + return; + if( sd->sc.data[type] && (group = skill_id2group(sd->sc.data[type]->val4)) ) { + skill_delunitgroup(group); + status_change_end(&sd->bl,type,INVALID_TIMER); + } + group = skill_unitsetting(&sd->bl,skill_num,skill_lv,sd->bl.x,sd->bl.y,0); + if( group ) { + sc_start4(&sd->bl,type,100,(battle_config.guild_aura&16)?0:skill_lv,0,0,group->group_id,600000);//duration doesn't matter these status never end with val4 + } + return; } /*==================================================== * Count number of relations the guild has. * Flag: - * 0 = allied - * 1 = enemy + * 0 = allied + * 1 = enemy *---------------------------------------------------*/ int guild_get_alliance_count(struct guild *g,int flag) { - int i,c; + int i,c; - nullpo_ret(g); + nullpo_ret(g); - for (i=c=0; i<MAX_GUILDALLIANCE; i++) { - if (g->alliance[i].guild_id>0 && - g->alliance[i].opposition==flag) - c++; - } - return c; + for(i=c=0;i<MAX_GUILDALLIANCE;i++){ + if( g->alliance[i].guild_id>0 && + g->alliance[i].opposition==flag ) + c++; + } + return c; } // Blocks all guild skills which have a common delay time. void guild_block_skill(struct map_session_data *sd, int time) { - int skill_num[] = { GD_BATTLEORDER, GD_REGENERATION, GD_RESTORE, GD_EMERGENCYCALL }; - int i; - for (i = 0; i < 4; i++) - skill_blockpc_start_(sd, skill_num[i], time , true); + int skill_num[] = { GD_BATTLEORDER, GD_REGENERATION, GD_RESTORE, GD_EMERGENCYCALL }; + int i; + for (i = 0; i < 4; i++) + skill_blockpc_start_(sd, skill_num[i], time , true); } /*==================================================== * Check relation between guild_id1 and guild_id2. * Flag: - * 0 = allied - * 1 = enemy + * 0 = allied + * 1 = enemy * Returns true if yes. *---------------------------------------------------*/ int guild_check_alliance(int guild_id1, int guild_id2, int flag) { - struct guild *g; - int i; + struct guild *g; + int i; - g = guild_search(guild_id1); - if (g == NULL) - return 0; + g = guild_search(guild_id1); + if (g == NULL) + return 0; - ARR_FIND(0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id2 && g->alliance[i].opposition == flag); - return(i < MAX_GUILDALLIANCE) ? 1 : 0; + ARR_FIND( 0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id2 && g->alliance[i].opposition == flag ); + return( i < MAX_GUILDALLIANCE ) ? 1 : 0; } /*==================================================== @@ -1348,57 +1366,57 @@ int guild_check_alliance(int guild_id1, int guild_id2, int flag) *---------------------------------------------------*/ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd) { - struct guild *g[2]; - int i; + struct guild *g[2]; + int i; - if (agit_flag || agit2_flag) { // Disable alliance creation during woe [Valaris] - clif_displaymessage(sd->fd,msg_txt(676)); //"Alliances cannot be made during Guild Wars!" - return 0; - } // end addition [Valaris] + if(agit_flag || agit2_flag) { // Disable alliance creation during woe [Valaris] + clif_displaymessage(sd->fd,msg_txt(676)); //"Alliances cannot be made during Guild Wars!" + return 0; + } // end addition [Valaris] - nullpo_ret(sd); + nullpo_ret(sd); - if (tsd==NULL || tsd->status.guild_id<=0) - return 0; + if(tsd==NULL || tsd->status.guild_id<=0) + return 0; - g[0]=guild_search(sd->status.guild_id); - g[1]=guild_search(tsd->status.guild_id); + g[0]=guild_search(sd->status.guild_id); + g[1]=guild_search(tsd->status.guild_id); - if (g[0]==NULL || g[1]==NULL) - return 0; + if(g[0]==NULL || g[1]==NULL) + return 0; - // Prevent creation alliance with same guilds [LuzZza] - if (sd->status.guild_id == tsd->status.guild_id) - return 0; + // Prevent creation alliance with same guilds [LuzZza] + if(sd->status.guild_id == tsd->status.guild_id) + return 0; - if (guild_get_alliance_count(g[0],0) >= battle_config.max_guild_alliance) { - clif_guild_allianceack(sd,4); - return 0; - } - if (guild_get_alliance_count(g[1],0) >= battle_config.max_guild_alliance) { - clif_guild_allianceack(sd,3); - return 0; - } + if( guild_get_alliance_count(g[0],0) >= battle_config.max_guild_alliance ) { + clif_guild_allianceack(sd,4); + return 0; + } + if( guild_get_alliance_count(g[1],0) >= battle_config.max_guild_alliance ) { + clif_guild_allianceack(sd,3); + return 0; + } - if (tsd->guild_alliance>0) { - clif_guild_allianceack(sd,1); - return 0; - } + if( tsd->guild_alliance>0 ){ + clif_guild_allianceack(sd,1); + return 0; + } for (i = 0; i < MAX_GUILDALLIANCE; i++) { // check if already allied - if (g[0]->alliance[i].guild_id==tsd->status.guild_id && - g[0]->alliance[i].opposition==0) { - clif_guild_allianceack(sd,0); - return 0; - } - } + if( g[0]->alliance[i].guild_id==tsd->status.guild_id && + g[0]->alliance[i].opposition==0){ + clif_guild_allianceack(sd,0); + return 0; + } + } - tsd->guild_alliance=sd->status.guild_id; - tsd->guild_alliance_account=sd->status.account_id; + tsd->guild_alliance=sd->status.guild_id; + tsd->guild_alliance_account=sd->status.account_id; - clif_guild_reqalliance(tsd,sd->status.account_id,g[0]->name); - return 0; + clif_guild_reqalliance(tsd,sd->status.account_id,g[0]->name); + return 0; } /*==================================================== @@ -1406,60 +1424,60 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd) *---------------------------------------------------*/ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag) { - struct map_session_data *tsd; + struct map_session_data *tsd; - nullpo_ret(sd); - tsd= map_id2sd(account_id); - if (!tsd) { //Character left? Cancel alliance. - clif_guild_allianceack(sd,3); - return 0; - } + nullpo_ret(sd); + tsd= map_id2sd( account_id ); + if (!tsd) { //Character left? Cancel alliance. + clif_guild_allianceack(sd,3); + return 0; + } if (sd->guild_alliance != tsd->status.guild_id) // proposed guild_id alliance doesn't match tsd guildid - return 0; + return 0; if (flag == 1) { // consent - int i; + int i; struct guild *g, *tg; // Reconfirm the number of alliance - g=guild_search(sd->status.guild_id); - tg=guild_search(tsd->status.guild_id); - - if (g==NULL || guild_get_alliance_count(g,0) >= battle_config.max_guild_alliance) { - clif_guild_allianceack(sd,4); - clif_guild_allianceack(tsd,3); - return 0; - } - if (tg==NULL || guild_get_alliance_count(tg,0) >= battle_config.max_guild_alliance) { - clif_guild_allianceack(sd,3); - clif_guild_allianceack(tsd,4); - return 0; - } - - for (i=0; i<MAX_GUILDALLIANCE; i++) { - if (g->alliance[i].guild_id==tsd->status.guild_id && - g->alliance[i].opposition==1) - intif_guild_alliance(sd->status.guild_id,tsd->status.guild_id, - sd->status.account_id,tsd->status.account_id,9); - } - for (i=0; i<MAX_GUILDALLIANCE; i++) { - if (tg->alliance[i].guild_id==sd->status.guild_id && - tg->alliance[i].opposition==1) - intif_guild_alliance(tsd->status.guild_id,sd->status.guild_id, - tsd->status.account_id,sd->status.account_id,9); - } + g=guild_search(sd->status.guild_id); + tg=guild_search(tsd->status.guild_id); + + if(g==NULL || guild_get_alliance_count(g,0) >= battle_config.max_guild_alliance){ + clif_guild_allianceack(sd,4); + clif_guild_allianceack(tsd,3); + return 0; + } + if(tg==NULL || guild_get_alliance_count(tg,0) >= battle_config.max_guild_alliance){ + clif_guild_allianceack(sd,3); + clif_guild_allianceack(tsd,4); + return 0; + } + + for(i=0;i<MAX_GUILDALLIANCE;i++){ + if(g->alliance[i].guild_id==tsd->status.guild_id && + g->alliance[i].opposition==1) + intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id, + sd->status.account_id,tsd->status.account_id,9 ); + } + for(i=0;i<MAX_GUILDALLIANCE;i++){ + if(tg->alliance[i].guild_id==sd->status.guild_id && + tg->alliance[i].opposition==1) + intif_guild_alliance( tsd->status.guild_id,sd->status.guild_id, + tsd->status.account_id,sd->status.account_id,9 ); + } // inform other servers - intif_guild_alliance(sd->status.guild_id,tsd->status.guild_id, - sd->status.account_id,tsd->status.account_id,0); - return 0; + intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id, + sd->status.account_id,tsd->status.account_id,0 ); + return 0; } else { // deny - sd->guild_alliance=0; - sd->guild_alliance_account=0; - if (tsd!=NULL) - clif_guild_allianceack(tsd,3); - } - return 0; + sd->guild_alliance=0; + sd->guild_alliance_account=0; + if(tsd!=NULL) + clif_guild_allianceack(tsd,3); + } + return 0; } /*==================================================== @@ -1467,15 +1485,15 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag) *---------------------------------------------------*/ int guild_delalliance(struct map_session_data *sd,int guild_id,int flag) { - nullpo_ret(sd); + nullpo_ret(sd); - if (agit_flag || agit2_flag) { // Disable alliance breaking during woe [Valaris] - clif_displaymessage(sd->fd,msg_txt(677)); //"Alliances cannot be broken during Guild Wars!" - return 0; - } // end addition [Valaris] + if(agit_flag || agit2_flag) { // Disable alliance breaking during woe [Valaris] + clif_displaymessage(sd->fd,msg_txt(677)); //"Alliances cannot be broken during Guild Wars!" + return 0; + } // end addition [Valaris] - intif_guild_alliance(sd->status.guild_id,guild_id,sd->status.account_id,0,flag|8); - return 0; + intif_guild_alliance( sd->status.guild_id,guild_id,sd->status.account_id,0,flag|8 ); + return 0; } /*==================================================== @@ -1483,42 +1501,42 @@ int guild_delalliance(struct map_session_data *sd,int guild_id,int flag) *---------------------------------------------------*/ int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd) { - struct guild *g; - int i; + struct guild *g; + int i; - nullpo_ret(sd); + nullpo_ret(sd); - g=guild_search(sd->status.guild_id); - if (g==NULL || tsd==NULL) - return 0; + g=guild_search(sd->status.guild_id); + if(g==NULL || tsd==NULL) + return 0; - // Prevent creation opposition with same guilds [LuzZza] - if (sd->status.guild_id == tsd->status.guild_id) - return 0; + // Prevent creation opposition with same guilds [LuzZza] + if(sd->status.guild_id == tsd->status.guild_id) + return 0; - if (guild_get_alliance_count(g,1) >= battle_config.max_guild_alliance) { - clif_guild_oppositionack(sd,1); - return 0; - } + if( guild_get_alliance_count(g,1) >= battle_config.max_guild_alliance ) { + clif_guild_oppositionack(sd,1); + return 0; + } for (i = 0; i < MAX_GUILDALLIANCE; i++) { // checking relations - if (g->alliance[i].guild_id==tsd->status.guild_id) { + if(g->alliance[i].guild_id==tsd->status.guild_id){ if (g->alliance[i].opposition == 1) { // check if not already hostile - clif_guild_oppositionack(sd,2); - return 0; - } - if (agit_flag || agit2_flag) // Prevent the changing of alliances to oppositions during WoE. - return 0; - //Change alliance to opposition. - intif_guild_alliance(sd->status.guild_id,tsd->status.guild_id, - sd->status.account_id,tsd->status.account_id,8); - } - } + clif_guild_oppositionack(sd,2); + return 0; + } + if(agit_flag || agit2_flag) // Prevent the changing of alliances to oppositions during WoE. + return 0; + //Change alliance to opposition. + intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id, + sd->status.account_id,tsd->status.account_id,8 ); + } + } // inform other serv - intif_guild_alliance(sd->status.guild_id,tsd->status.guild_id, - sd->status.account_id,tsd->status.account_id,1); - return 0; + intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id, + sd->status.account_id,tsd->status.account_id,1 ); + return 0; } /*==================================================== @@ -1526,74 +1544,79 @@ int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd) *---------------------------------------------------*/ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag,const char *name1,const char *name2) { - struct guild *g[2]; - 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); - - if (sd[0]!=NULL && (flag&0x0f)==0) { - sd[0]->guild_alliance=0; - sd[0]->guild_alliance_account=0; - } + struct guild *g[2]; + 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); + + if(sd[0]!=NULL && (flag&0x0f)==0){ + sd[0]->guild_alliance=0; + sd[0]->guild_alliance_account=0; + } if (flag & 0x70) { // failure - for (i=0; i<2-(flag&1); i++) - if (sd[i]!=NULL) - clif_guild_allianceack(sd[i],((flag>>4)==i+1)?3:4); - return 0; - } + for(i=0;i<2-(flag&1);i++) + if( sd[i]!=NULL ) + clif_guild_allianceack(sd[i],((flag>>4)==i+1)?3:4); + return 0; + } if (!(flag & 0x08)) { // new relationship - for (i=0; i<2-(flag&1); i++) { - if (g[i]!=NULL) { - ARR_FIND(0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == 0); - if (j < MAX_GUILDALLIANCE) { - g[i]->alliance[j].guild_id=guild_id[1-i]; - memcpy(g[i]->alliance[j].name,guild_name[1-i],NAME_LENGTH); - g[i]->alliance[j].opposition=flag&1; - } - } - } + for(i=0;i<2-(flag&1);i++) + { + if(g[i]!=NULL) + { + ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == 0 ); + if( j < MAX_GUILDALLIANCE ) + { + g[i]->alliance[j].guild_id=guild_id[1-i]; + memcpy(g[i]->alliance[j].name,guild_name[1-i],NAME_LENGTH); + g[i]->alliance[j].opposition=flag&1; + } + } + } } else { // remove relationship - for (i=0; i<2-(flag&1); i++) { - if (g[i]!=NULL) { - ARR_FIND(0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == guild_id[1-i] && g[i]->alliance[j].opposition == (flag&1)); - if (j < MAX_GUILDALLIANCE) - g[i]->alliance[j].guild_id = 0; - } + for(i=0;i<2-(flag&1);i++) + { + if(g[i]!=NULL) + { + ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == guild_id[1-i] && g[i]->alliance[j].opposition == (flag&1) ); + if( j < MAX_GUILDALLIANCE ) + g[i]->alliance[j].guild_id = 0; + } if (sd[i] != NULL) // notify players - clif_guild_delalliance(sd[i],guild_id[1-i],(flag&1)); - } - } + clif_guild_delalliance(sd[i],guild_id[1-i],(flag&1)); + } + } if ((flag & 0x0f) == 0) { // alliance notification - if (sd[1]!=NULL) - clif_guild_allianceack(sd[1],2); + if( sd[1]!=NULL ) + clif_guild_allianceack(sd[1],2); } else if ((flag & 0x0f) == 1) { // enemy notification - if (sd[0]!=NULL) - clif_guild_oppositionack(sd[0],0); - } + if( sd[0]!=NULL ) + clif_guild_oppositionack(sd[0],0); + } for (i = 0; i < 2 - (flag & 1); i++) { // Retransmission of the relationship list to all members - struct map_session_data *sd; - if (g[i]!=NULL) - for (j=0; j<g[i]->max_member; j++) - if ((sd=g[i]->member[j].sd)!=NULL) - clif_guild_allianceinfo(sd); - } - return 0; + struct map_session_data *sd; + if(g[i]!=NULL) + for(j=0;j<g[i]->max_member;j++) + if((sd=g[i]->member[j].sd)!=NULL) + clif_guild_allianceinfo(sd); + } + return 0; } /** @@ -1602,23 +1625,23 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id */ int guild_broken_sub(DBKey key, DBData *data, va_list ap) { - struct guild *g = db_data2ptr(data); - int guild_id=va_arg(ap,int); - int i,j; - struct map_session_data *sd=NULL; + struct guild *g = db_data2ptr(data); + int guild_id=va_arg(ap,int); + int i,j; + struct map_session_data *sd=NULL; - nullpo_ret(g); + nullpo_ret(g); - for (i=0; i<MAX_GUILDALLIANCE; i++) { // Destroy all relationships - if (g->alliance[i].guild_id==guild_id) { - for (j=0; j<g->max_member; j++) - if ((sd=g->member[j].sd)!=NULL) - clif_guild_delalliance(sd,guild_id,g->alliance[i].opposition); - intif_guild_alliance(g->guild_id, guild_id,0,0,g->alliance[i].opposition|8); - g->alliance[i].guild_id=0; - } - } - return 0; + for(i=0;i<MAX_GUILDALLIANCE;i++){ // Destroy all relationships + if(g->alliance[i].guild_id==guild_id){ + for(j=0;j<g->max_member;j++) + if( (sd=g->member[j].sd)!=NULL ) + clif_guild_delalliance(sd,guild_id,g->alliance[i].opposition); + intif_guild_alliance(g->guild_id, guild_id,0,0,g->alliance[i].opposition|8); + g->alliance[i].guild_id=0; + } + } + return 0; } /** @@ -1627,120 +1650,124 @@ int guild_broken_sub(DBKey key, DBData *data, va_list ap) */ int castle_guild_broken_sub(DBKey key, DBData *data, va_list ap) { - char name[EVENT_NAME_LENGTH]; - struct guild_castle *gc = db_data2ptr(data); - int guild_id = va_arg(ap, int); + char name[EVENT_NAME_LENGTH]; + struct guild_castle *gc = db_data2ptr(data); + int guild_id = va_arg(ap, int); - nullpo_ret(gc); + nullpo_ret(gc); - if (gc->guild_id == guild_id) { - // We call castle_event::OnGuildBreak of all castles of the guild - // You can set all castle_events in the 'db/castle_db.txt' - safestrncpy(name, gc->castle_event, sizeof(name)); - npc_event_do(strcat(name, "::OnGuildBreak")); + if (gc->guild_id == guild_id) { + // We call castle_event::OnGuildBreak of all castles of the guild + // You can set all castle_events in the 'db/castle_db.txt' + safestrncpy(name, gc->castle_event, sizeof(name)); + npc_event_do(strcat(name, "::OnGuildBreak")); - //Save the new 'owner', this should invoke guardian clean up and other such things. - guild_castledatasave(gc->castle_id, 1, 0); - } - return 0; + //Save the new 'owner', this should invoke guardian clean up and other such things. + guild_castledatasave(gc->castle_id, 1, 0); + } + return 0; } //Invoked on /breakguild "Guild name" int guild_broken(int guild_id,int flag) { - struct guild *g = guild_search(guild_id); - struct map_session_data *sd = NULL; - int i; + struct guild *g = guild_search(guild_id); + struct map_session_data *sd = NULL; + int i; - if (flag!=0 || g==NULL) - return 0; + if(flag!=0 || g==NULL) + return 0; - for (i=0; i<g->max_member; i++) { // Destroy all relationships - if ((sd=g->member[i].sd)!=NULL) { - if (sd->state.storage_flag == 2) - storage_guild_storage_quit(sd,1); - sd->status.guild_id=0; - clif_guild_broken(g->member[i].sd,0); - clif_charnameupdate(sd); // [LuzZza] - } - } + for(i=0;i<g->max_member;i++){ // Destroy all relationships + if((sd=g->member[i].sd)!=NULL){ + if(sd->state.storage_flag == 2) + storage_guild_storage_quit(sd,1); + sd->status.guild_id=0; + clif_guild_broken(g->member[i].sd,0); + clif_charnameupdate(sd); // [LuzZza] + } + } - guild_db->foreach(guild_db,guild_broken_sub,guild_id); - castle_db->foreach(castle_db,castle_guild_broken_sub,guild_id); - guild_storage_delete(guild_id); - idb_remove(guild_db,guild_id); - return 0; + guild_db->foreach(guild_db,guild_broken_sub,guild_id); + castle_db->foreach(castle_db,castle_guild_broken_sub,guild_id); + guild_storage_delete(guild_id); + idb_remove(guild_db,guild_id); + return 0; } //Changes the Guild Master to the specified player. [Skotlex] int guild_gm_change(int guild_id, struct map_session_data *sd) { - struct guild *g; - nullpo_ret(sd); + struct guild *g; + nullpo_ret(sd); - if (sd->status.guild_id != guild_id) - return 0; + if (sd->status.guild_id != guild_id) + return 0; + + g=guild_search(guild_id); - g=guild_search(guild_id); + nullpo_ret(g); - nullpo_ret(g); - - if (strcmp(g->master, sd->status.name) == 0) //Nothing to change. - return 0; + if (strcmp(g->master, sd->status.name) == 0) //Nothing to change. + return 0; - //Notify servers that master has changed. - intif_guild_change_gm(guild_id, sd->status.name, strlen(sd->status.name)+1); - return 1; + //Notify servers that master has changed. + intif_guild_change_gm(guild_id, sd->status.name, strlen(sd->status.name)+1); + return 1; } //Notification from Char server that a guild's master has changed. [Skotlex] int guild_gm_changed(int guild_id, int account_id, int char_id) { - struct guild *g; - struct guild_member gm; - int pos, i; - - g=guild_search(guild_id); - - if (!g) - return 0; - - for (pos=0; pos<g->max_member && !( - g->member[pos].account_id==account_id && - g->member[pos].char_id==char_id); - pos++); - - if (pos == 0 || pos == g->max_member) return 0; - - memcpy(&gm, &g->member[pos], sizeof(struct guild_member)); - memcpy(&g->member[pos], &g->member[0], sizeof(struct guild_member)); - memcpy(&g->member[0], &gm, sizeof(struct guild_member)); - - g->member[pos].position = g->member[0].position; - g->member[0].position = 0; //Position 0: guild Master. - strcpy(g->master, g->member[0].name); - - if (g->member[pos].sd && g->member[pos].sd->fd) { - clif_displaymessage(g->member[pos].sd->fd, msg_txt(678)); //"You no longer are the Guild Master." - g->member[pos].sd->state.gmaster_flag = 0; - } - - if (g->member[0].sd && g->member[0].sd->fd) { - clif_displaymessage(g->member[0].sd->fd, msg_txt(679)); //"You have become the Guild Master!" - g->member[0].sd->state.gmaster_flag = g; - //Block his skills for 5 minutes to prevent abuse. - guild_block_skill(g->member[0].sd, 300000); - } - - // announce the change to all guild members - for (i = 0; i < g->max_member; i++) { - if (g->member[i].sd && g->member[i].sd->fd) { - clif_guild_basicinfo(g->member[i].sd); - clif_guild_memberlist(g->member[i].sd); - } - } - - return 1; + struct guild *g; + struct guild_member gm; + int pos, i; + + g=guild_search(guild_id); + + if (!g) + return 0; + + for(pos=0; pos<g->max_member && !( + g->member[pos].account_id==account_id && + g->member[pos].char_id==char_id); + pos++); + + if (pos == 0 || pos == g->max_member) return 0; + + memcpy(&gm, &g->member[pos], sizeof (struct guild_member)); + memcpy(&g->member[pos], &g->member[0], sizeof(struct guild_member)); + memcpy(&g->member[0], &gm, sizeof(struct guild_member)); + + g->member[pos].position = g->member[0].position; + g->member[0].position = 0; //Position 0: guild Master. + strcpy(g->master, g->member[0].name); + + if (g->member[pos].sd && g->member[pos].sd->fd) + { + clif_displaymessage(g->member[pos].sd->fd, msg_txt(678)); //"You no longer are the Guild Master." + g->member[pos].sd->state.gmaster_flag = 0; + } + + if (g->member[0].sd && g->member[0].sd->fd) + { + clif_displaymessage(g->member[0].sd->fd, msg_txt(679)); //"You have become the Guild Master!" + g->member[0].sd->state.gmaster_flag = g; + //Block his skills for 5 minutes to prevent abuse. + guild_block_skill(g->member[0].sd, 300000); + } + + // announce the change to all guild members + for( i = 0; i < g->max_member; i++ ) + { + if( g->member[i].sd && g->member[i].sd->fd ) + { + clif_guild_basicinfo(g->member[i].sd); + clif_guild_memberlist(g->member[i].sd); + } + } + + return 1; } /*==================================================== @@ -1748,30 +1775,30 @@ int guild_gm_changed(int guild_id, int account_id, int char_id) *---------------------------------------------------*/ int guild_break(struct map_session_data *sd,char *name) { - struct guild *g; - int i; + struct guild *g; + int i; - nullpo_ret(sd); + nullpo_ret(sd); - if ((g=guild_search(sd->status.guild_id))==NULL) - return 0; - if (strcmp(g->name,name)!=0) - return 0; - if (!sd->state.gmaster_flag) - return 0; - for (i=0; i<g->max_member; i++) { - if (g->member[i].account_id>0 && ( - g->member[i].account_id!=sd->status.account_id || - g->member[i].char_id!=sd->status.char_id)) - break; - } - if (i<g->max_member) { - clif_guild_broken(sd,2); - return 0; - } + if( (g=guild_search(sd->status.guild_id))==NULL ) + return 0; + if(strcmp(g->name,name)!=0) + return 0; + if(!sd->state.gmaster_flag) + return 0; + for(i=0;i<g->max_member;i++){ + if( g->member[i].account_id>0 && ( + g->member[i].account_id!=sd->status.account_id || + g->member[i].char_id!=sd->status.char_id )) + break; + } + if(i<g->max_member){ + clif_guild_broken(sd,2); + return 0; + } - intif_guild_break(g->guild_id); - return 0; + intif_guild_break(g->guild_id); + return 0; } /** @@ -1780,24 +1807,24 @@ int guild_break(struct map_session_data *sd,char *name) */ void guild_castle_map_init(void) { - DBIterator *iter = NULL; - int num = db_size(castle_db); + DBIterator* iter = NULL; + int num = db_size(castle_db); - if (num > 0) { - struct guild_castle *gc = NULL; - int *castle_ids, *cursor; + if (num > 0) { + struct guild_castle* gc = NULL; + int *castle_ids, *cursor; - CREATE(castle_ids, int, num); - cursor = castle_ids; - iter = db_iterator(castle_db); - for (gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) { - *(cursor++) = gc->castle_id; - } - dbi_destroy(iter); - if (intif_guild_castle_dataload(num, castle_ids)) - ShowStatus("Requested '"CL_WHITE"%d"CL_RESET"' guild castles from char-server...\n", num); - aFree(castle_ids); - } + CREATE(castle_ids, int, num); + cursor = castle_ids; + iter = db_iterator(castle_db); + for (gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) { + *(cursor++) = gc->castle_id; + } + dbi_destroy(iter); + if (intif_guild_castle_dataload(num, castle_ids)) + ShowStatus("Requested '"CL_WHITE"%d"CL_RESET"' guild castles from char-server...\n", num); + aFree(castle_ids); + } } /** @@ -1810,325 +1837,311 @@ void guild_castle_map_init(void) */ int guild_castledatasave(int castle_id, int index, int value) { - struct guild_castle *gc = guild_castle_search(castle_id); - - if (gc == NULL) { - ShowWarning("guild_castledatasave: guild castle '%d' not found\n", castle_id); - return 0; - } - - switch (index) { - case 1: { // The castle's owner has changed? Update or remove Guardians too. [Skotlex] - int i; - struct mob_data *gd; - gc->guild_id = value; - for (i = 0; i < MAX_GUARDIANS; i++) - if (gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL) - mob_guardian_guildchange(gd); - break; - } - case 2: - gc->economy = value; - break; - case 3: { // defense invest change -> recalculate guardian hp - int i; - struct mob_data *gd; - gc->defense = value; - for (i = 0; i < MAX_GUARDIANS; i++) - if (gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL) - status_calc_mob(gd, 0); - break; - } - case 4: - gc->triggerE = value; - break; - case 5: - gc->triggerD = value; - break; - case 6: - gc->nextTime = value; - break; - case 7: - gc->payTime = value; - break; - case 8: - gc->createTime = value; - break; - case 9: - gc->visibleC = value; - break; - default: - if (index > 9 && index <= 9+MAX_GUARDIANS) { - gc->guardian[index-10].visible = value; - break; - } - ShowWarning("guild_castledatasave: index = '%d' is out of allowed range\n", index); - return 0; - } - - if (!intif_guild_castle_datasave(castle_id, index, value)) { - guild_castle_reconnect(castle_id, index, value); - } - return 0; + struct guild_castle *gc = guild_castle_search(castle_id); + + if (gc == NULL) { + ShowWarning("guild_castledatasave: guild castle '%d' not found\n", castle_id); + return 0; + } + + switch (index) { + case 1: // The castle's owner has changed? Update or remove Guardians too. [Skotlex] + { + int i; + struct mob_data *gd; + gc->guild_id = value; + for (i = 0; i < MAX_GUARDIANS; i++) + if (gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL) + mob_guardian_guildchange(gd); + break; + } + case 2: + gc->economy = value; break; + case 3: // defense invest change -> recalculate guardian hp + { + int i; + struct mob_data *gd; + gc->defense = value; + for (i = 0; i < MAX_GUARDIANS; i++) + if (gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL) + status_calc_mob(gd, 0); + break; + } + case 4: + gc->triggerE = value; break; + case 5: + gc->triggerD = value; break; + case 6: + gc->nextTime = value; break; + case 7: + gc->payTime = value; break; + case 8: + gc->createTime = value; break; + case 9: + gc->visibleC = value; break; + default: + if (index > 9 && index <= 9+MAX_GUARDIANS) { + gc->guardian[index-10].visible = value; + break; + } + ShowWarning("guild_castledatasave: index = '%d' is out of allowed range\n", index); + return 0; + } + + if (!intif_guild_castle_datasave(castle_id, index, value)) { + guild_castle_reconnect(castle_id, index, value); + } + return 0; } void guild_castle_reconnect_sub(void *key, void *data, va_list ap) { - int castle_id = GetWord((int)__64BPRTSIZE(key), 0); - int index = GetWord((int)__64BPRTSIZE(key), 1); - intif_guild_castle_datasave(castle_id, index, *(int *)data); - aFree(data); + int castle_id = GetWord((int)__64BPRTSIZE(key), 0); + int index = GetWord((int)__64BPRTSIZE(key), 1); + intif_guild_castle_datasave(castle_id, index, *(int *)data); + aFree(data); } /** - * Saves pending guild castle data changes when char-server is + * Saves pending guild castle data changes when char-server is * disconnected. * On reconnect pushes all changes to char-server for saving. */ void guild_castle_reconnect(int castle_id, int index, int value) { - static struct linkdb_node *gc_save_pending = NULL; + static struct linkdb_node *gc_save_pending = NULL; - if (castle_id < 0) { // char-server reconnected - linkdb_foreach(&gc_save_pending, guild_castle_reconnect_sub); - linkdb_final(&gc_save_pending); - } else { - int *data; - CREATE(data, int, 1); - *data = value; - linkdb_replace(&gc_save_pending, (void *)__64BPRTSIZE((MakeDWord(castle_id, index))), data); - } + if (castle_id < 0) { // char-server reconnected + linkdb_foreach(&gc_save_pending, guild_castle_reconnect_sub); + linkdb_final(&gc_save_pending); + } else { + int *data; + CREATE(data, int, 1); + *data = value; + linkdb_replace(&gc_save_pending, (void*)__64BPRTSIZE((MakeDWord(castle_id, index))), data); + } } // Load castle data then invoke OnAgitInit* on last int guild_castledataloadack(int len, struct guild_castle *gc) { - int i; - int n = (len-4) / sizeof(struct guild_castle); - int ev; - - nullpo_ret(gc); - - //Last owned castle in the list invokes ::OnAgitInit - for (i = n-1; i >= 0 && !(gc[i].guild_id); --i); - ev = i; // offset of castle or -1 - - if (ev < 0) { //No castles owned, invoke OnAgitInit as it is. - npc_event_doall("OnAgitInit"); - npc_event_doall("OnAgitInit2"); - } else // load received castles into memory, one by one - for (i = 0; i < n; i++, gc++) { - struct guild_castle *c = guild_castle_search(gc->castle_id); - if (!c) { - ShowError("guild_castledataloadack: castle id=%d not found.\n", gc->castle_id); - continue; - } - - // update map-server castle data with new info - memcpy(&c->guild_id, &gc->guild_id, sizeof(struct guild_castle) - offsetof(struct guild_castle, guild_id)); - - if (c->guild_id) { - if (i != ev) - guild_request_info(c->guild_id); - else { // last owned one - guild_npc_request_info(c->guild_id, "::OnAgitInit"); - guild_npc_request_info(c->guild_id, "::OnAgitInit2"); - } - } - } - ShowStatus("Received '"CL_WHITE"%d"CL_RESET"' guild castles from char-server.\n", n); - return 0; + int i; + int n = (len-4) / sizeof(struct guild_castle); + int ev; + + nullpo_ret(gc); + + //Last owned castle in the list invokes ::OnAgitInit + for( i = n-1; i >= 0 && !(gc[i].guild_id); --i ); + ev = i; // offset of castle or -1 + + if( ev < 0 ) { //No castles owned, invoke OnAgitInit as it is. + npc_event_doall("OnAgitInit"); + npc_event_doall("OnAgitInit2"); + } + else // load received castles into memory, one by one + for( i = 0; i < n; i++, gc++ ) + { + struct guild_castle *c = guild_castle_search(gc->castle_id); + if (!c) { + ShowError("guild_castledataloadack: castle id=%d not found.\n", gc->castle_id); + continue; + } + + // update map-server castle data with new info + memcpy(&c->guild_id, &gc->guild_id, sizeof(struct guild_castle) - offsetof(struct guild_castle, guild_id)); + + if( c->guild_id ) + { + if( i != ev ) + guild_request_info(c->guild_id); + else { // last owned one + guild_npc_request_info(c->guild_id, "::OnAgitInit"); + guild_npc_request_info(c->guild_id, "::OnAgitInit2"); + } + } + } + ShowStatus("Received '"CL_WHITE"%d"CL_RESET"' guild castles from char-server.\n", n); + return 0; } /*==================================================== * Start normal woe and triggers all npc OnAgitStart *---------------------------------------------------*/ void guild_agit_start(void) -{ - // Run All NPC_Event[OnAgitStart] - int c = npc_event_doall("OnAgitStart"); - ShowStatus("NPC_Event:[OnAgitStart] Run (%d) Events by @AgitStart.\n",c); +{ // Run All NPC_Event[OnAgitStart] + int c = npc_event_doall("OnAgitStart"); + ShowStatus("NPC_Event:[OnAgitStart] Run (%d) Events by @AgitStart.\n",c); } /*==================================================== * End normal woe and triggers all npc OnAgitEnd *---------------------------------------------------*/ void guild_agit_end(void) -{ - // Run All NPC_Event[OnAgitEnd] - int c = npc_event_doall("OnAgitEnd"); - ShowStatus("NPC_Event:[OnAgitEnd] Run (%d) Events by @AgitEnd.\n",c); +{ // Run All NPC_Event[OnAgitEnd] + int c = npc_event_doall("OnAgitEnd"); + ShowStatus("NPC_Event:[OnAgitEnd] Run (%d) Events by @AgitEnd.\n",c); } /*==================================================== * Start woe2 and triggers all npc OnAgitStart2 *---------------------------------------------------*/ void guild_agit2_start(void) -{ - // Run All NPC_Event[OnAgitStart2] - int c = npc_event_doall("OnAgitStart2"); - ShowStatus("NPC_Event:[OnAgitStart2] Run (%d) Events by @AgitStart2.\n",c); +{ // Run All NPC_Event[OnAgitStart2] + int c = npc_event_doall("OnAgitStart2"); + ShowStatus("NPC_Event:[OnAgitStart2] Run (%d) Events by @AgitStart2.\n",c); } /*==================================================== * End woe2 and triggers all npc OnAgitEnd2 *---------------------------------------------------*/ void guild_agit2_end(void) -{ - // Run All NPC_Event[OnAgitEnd2] - int c = npc_event_doall("OnAgitEnd2"); - ShowStatus("NPC_Event:[OnAgitEnd2] Run (%d) Events by @AgitEnd2.\n",c); +{ // Run All NPC_Event[OnAgitEnd2] + int c = npc_event_doall("OnAgitEnd2"); + ShowStatus("NPC_Event:[OnAgitEnd2] Run (%d) Events by @AgitEnd2.\n",c); } // How many castles does this guild have? int guild_checkcastles(struct guild *g) { - int nb_cas = 0; - struct guild_castle *gc = NULL; - DBIterator *iter = db_iterator(castle_db); + int nb_cas = 0; + struct guild_castle* gc = NULL; + DBIterator *iter = db_iterator(castle_db); - for (gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) { - if (gc->guild_id == g->guild_id) { - nb_cas++; - } - } - dbi_destroy(iter); - return nb_cas; + for (gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) { + if (gc->guild_id == g->guild_id) { + nb_cas++; + } + } + dbi_destroy(iter); + return nb_cas; } // Are these two guilds allied? bool guild_isallied(int guild_id, int guild_id2) { - int i; - struct guild *g = guild_search(guild_id); - nullpo_ret(g); - - ARR_FIND(0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id2); - return(i < MAX_GUILDALLIANCE && g->alliance[i].opposition == 0); -} - -void guild_flag_add(struct npc_data *nd) -{ - int i; - - /* check */ - for (i = 0; i < guild_flags_count; i++) { - if (guild_flags[i] && guild_flags[i]->bl.id == nd->bl.id) { - return;/* exists, most likely updated the id. */ - } - } - - i = guild_flags_count;/* save the current slot */ - /* add */ - RECREATE(guild_flags,struct npc_data *,++guild_flags_count); - /* save */ - guild_flags[i] = nd; -} - -void guild_flag_remove(struct npc_data *nd) -{ - int i, cursor; - if (guild_flags_count == 0) - return; - /* find it */ - for (i = 0; i < guild_flags_count; i++) { - if (guild_flags[i] && guild_flags[i]->bl.id == nd->bl.id) { /* found */ - guild_flags[i] = NULL; - break; - } - } - - /* compact list */ - for (i = 0, cursor = 0; i < guild_flags_count; i++) { - if (guild_flags[i] == NULL) - continue; - - if (cursor != i) { - memmove(&guild_flags[cursor], &guild_flags[i], sizeof(struct npc_data *)); - } - - cursor++; - } + int i; + struct guild* g = guild_search(guild_id); + nullpo_ret(g); + + ARR_FIND( 0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id2 ); + return( i < MAX_GUILDALLIANCE && g->alliance[i].opposition == 0 ); +} + +void guild_flag_add(struct npc_data *nd) { + int i; + + /* check */ + for( i = 0; i < guild_flags_count; i++ ) { + if( guild_flags[i] && guild_flags[i]->bl.id == nd->bl.id ) { + return;/* exists, most likely updated the id. */ + } + } + + i = guild_flags_count;/* save the current slot */ + /* add */ + RECREATE(guild_flags,struct npc_data*,++guild_flags_count); + /* save */ + guild_flags[i] = nd; +} + +void guild_flag_remove(struct npc_data *nd) { + int i, cursor; + if( guild_flags_count == 0 ) + return; + /* find it */ + for( i = 0; i < guild_flags_count; i++ ) { + if( guild_flags[i] && guild_flags[i]->bl.id == nd->bl.id ) {/* found */ + guild_flags[i] = NULL; + break; + } + } + + /* compact list */ + for( i = 0, cursor = 0; i < guild_flags_count; i++ ) { + if( guild_flags[i] == NULL ) + continue; + + if( cursor != i ) { + memmove(&guild_flags[cursor], &guild_flags[i], sizeof(struct npc_data*)); + } + + cursor++; + } } /** * @see DBApply */ -static int eventlist_db_final(DBKey key, DBData *data, va_list ap) -{ - struct eventlist *next = NULL; - struct eventlist *current = db_data2ptr(data); - while (current != NULL) { - next = current->next; - aFree(current); - current = next; - } - return 0; +static int eventlist_db_final(DBKey key, DBData *data, va_list ap) { + struct eventlist *next = NULL; + struct eventlist *current = db_data2ptr(data); + while (current != NULL) { + next = current->next; + aFree(current); + current = next; + } + return 0; } /** * @see DBApply */ -static int guild_expcache_db_final(DBKey key, DBData *data, va_list ap) -{ - ers_free(expcache_ers, db_data2ptr(data)); - return 0; +static int guild_expcache_db_final(DBKey key, DBData *data, va_list ap) { + ers_free(expcache_ers, db_data2ptr(data)); + return 0; } /** * @see DBApply */ -static int guild_castle_db_final(DBKey key, DBData *data, va_list ap) -{ - struct guild_castle *gc = db_data2ptr(data); - if (gc->temp_guardians) - aFree(gc->temp_guardians); - aFree(gc); - return 0; +static int guild_castle_db_final(DBKey key, DBData *data, va_list ap) { + struct guild_castle* gc = db_data2ptr(data); + if( gc->temp_guardians ) + aFree(gc->temp_guardians); + aFree(gc); + return 0; } /* called when scripts are reloaded/unloaded */ -void guild_flags_clear(void) -{ - int i; - for (i = 0; i < guild_flags_count; i++) { - if (guild_flags[i]) - guild_flags[i] = NULL; - } - - guild_flags_count = 0; -} - -void do_init_guild(void) -{ - guild_db = idb_alloc(DB_OPT_RELEASE_DATA); - castle_db = idb_alloc(DB_OPT_BASE); - guild_expcache_db = idb_alloc(DB_OPT_BASE); - guild_infoevent_db = idb_alloc(DB_OPT_BASE); - expcache_ers = ers_new(sizeof(struct guild_expcache),"guild.c::expcache_ers",ERS_OPT_NONE); - - guild_flags_count = 0; - - sv_readdb(db_path, "castle_db.txt", ',', 4, 5, -1, &guild_read_castledb); - - memset(guild_skill_tree,0,sizeof(guild_skill_tree)); - sv_readdb(db_path, "guild_skill_tree.txt", ',', 2+MAX_GUILD_SKILL_REQUIRE*2, 2+MAX_GUILD_SKILL_REQUIRE*2, -1, &guild_read_guildskill_tree_db); //guild skill tree [Komurka] - - add_timer_func_list(guild_payexp_timer,"guild_payexp_timer"); - add_timer_func_list(guild_send_xy_timer, "guild_send_xy_timer"); - add_timer_interval(gettick()+GUILD_PAYEXP_INVERVAL,guild_payexp_timer,0,0,GUILD_PAYEXP_INVERVAL); - add_timer_interval(gettick()+GUILD_SEND_XY_INVERVAL,guild_send_xy_timer,0,0,GUILD_SEND_XY_INVERVAL); -} - -void do_final_guild(void) -{ - - db_destroy(guild_db); - castle_db->destroy(castle_db,guild_castle_db_final); - guild_expcache_db->destroy(guild_expcache_db,guild_expcache_db_final); - guild_infoevent_db->destroy(guild_infoevent_db,eventlist_db_final); - ers_destroy(expcache_ers); - - aFree(guild_flags);/* never empty; created on boot */ +void guild_flags_clear(void) { + int i; + for( i = 0; i < guild_flags_count; i++ ) { + if( guild_flags[i] ) + guild_flags[i] = NULL; + } + + guild_flags_count = 0; +} + +void do_init_guild(void) { + guild_db = idb_alloc(DB_OPT_RELEASE_DATA); + castle_db = idb_alloc(DB_OPT_BASE); + guild_expcache_db = idb_alloc(DB_OPT_BASE); + guild_infoevent_db = idb_alloc(DB_OPT_BASE); + expcache_ers = ers_new(sizeof(struct guild_expcache),"guild.c::expcache_ers",ERS_OPT_NONE); + + guild_flags_count = 0; + + sv_readdb(db_path, "castle_db.txt", ',', 4, 5, -1, &guild_read_castledb); + + memset(guild_skill_tree,0,sizeof(guild_skill_tree)); + sv_readdb(db_path, "guild_skill_tree.txt", ',', 2+MAX_GUILD_SKILL_REQUIRE*2, 2+MAX_GUILD_SKILL_REQUIRE*2, -1, &guild_read_guildskill_tree_db); //guild skill tree [Komurka] + + add_timer_func_list(guild_payexp_timer,"guild_payexp_timer"); + add_timer_func_list(guild_send_xy_timer, "guild_send_xy_timer"); + add_timer_interval(gettick()+GUILD_PAYEXP_INVERVAL,guild_payexp_timer,0,0,GUILD_PAYEXP_INVERVAL); + add_timer_interval(gettick()+GUILD_SEND_XY_INVERVAL,guild_send_xy_timer,0,0,GUILD_SEND_XY_INVERVAL); +} + +void do_final_guild(void) { + + db_destroy(guild_db); + castle_db->destroy(castle_db,guild_castle_db_final); + guild_expcache_db->destroy(guild_expcache_db,guild_expcache_db_final); + guild_infoevent_db->destroy(guild_infoevent_db,eventlist_db_final); + ers_destroy(expcache_ers); + + aFree(guild_flags);/* never empty; created on boot */ } diff --git a/src/map/guild.h b/src/map/guild.h index ecae8a30e..3e7b98f59 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -15,12 +15,12 @@ struct mob_data; //For quick linking to a guardian's info. [Skotlex] struct guardian_data { - int number; //0-MAX_GUARDIANS-1 = Guardians. MAX_GUARDIANS = Emperium. - int guild_id; - int emblem_id; - int guardup_lv; //Level of GD_GUARDUP skill. - char guild_name[NAME_LENGTH]; - struct guild_castle *castle; + int number; //0-MAX_GUARDIANS-1 = Guardians. MAX_GUARDIANS = Emperium. + int guild_id; + int emblem_id; + int guardup_lv; //Level of GD_GUARDUP skill. + char guild_name[NAME_LENGTH]; + struct guild_castle* castle; }; int guild_skill_get_max(int id); @@ -35,8 +35,8 @@ struct guild *guild_search(int guild_id); struct guild *guild_searchname(char *str); struct guild_castle *guild_castle_search(int gcid); -struct guild_castle *guild_mapname2gc(const char *mapname); -struct guild_castle *guild_mapindex2gc(short mapindex); +struct guild_castle* guild_mapname2gc(const char* mapname); +struct guild_castle* guild_mapindex2gc(short mapindex); struct map_session_data *guild_getavailablesd(struct guild *g); int guild_getindex(struct guild *g,int account_id,int char_id); @@ -55,18 +55,18 @@ int guild_reply_invite(struct map_session_data *sd,int guild_id,int flag); void guild_member_joined(struct map_session_data *sd); int guild_member_added(int guild_id,int account_id,int char_id,int flag); int guild_leave(struct map_session_data *sd,int guild_id, - int account_id,int char_id,const char *mes); + int account_id,int char_id,const char *mes); int guild_member_withdraw(int guild_id,int account_id,int char_id,int flag, - const char *name,const char *mes); + const char *name,const char *mes); int guild_expulsion(struct map_session_data *sd,int guild_id, - int account_id,int char_id,const char *mes); -int guild_skillup(struct map_session_data *sd, int skill_num); + int account_id,int char_id,const char *mes); +int guild_skillup(struct map_session_data* sd, int skill_num); void guild_block_skill(struct map_session_data *sd, int time); int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd); int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag); int guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2); int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id2, - int flag,const char *name1,const char *name2); + 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,struct map_session_data *tsd); int guild_check_alliance(int guild_id1, int guild_id2, int flag); diff --git a/src/map/homunculus.c b/src/map/homunculus.c index fda53e18d..ab3d811b2 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -39,7 +39,7 @@ #include <string.h> #include <math.h> -struct s_homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; //[orn] +struct s_homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; //[orn] struct homun_skill_tree_entry hskill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE]; static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr_t data); @@ -49,61 +49,39 @@ static unsigned int hexptbl[MAX_LEVEL]; //For holding the view data of npc classes. [Skotlex] static struct view_data hom_viewdb[MAX_HOMUNCULUS_CLASS]; -struct view_data *merc_get_hom_viewdata(int class_) { - //Returns the viewdata for homunculus - if (homdb_checkid(class_)) - return &hom_viewdb[class_-HM_CLASS_BASE]; - return NULL; +struct view_data* merc_get_hom_viewdata(int class_) +{ //Returns the viewdata for homunculus + if (homdb_checkid(class_)) + return &hom_viewdb[class_-HM_CLASS_BASE]; + return NULL; } int hom_class2mapid(int hom_class) { - switch (hom_class) { - // Normal Homunculus - case 6001: - case 6005: - return MAPID_LIF; - case 6002: - case 6006: - return MAPID_AMISTR; - case 6003: - case 6007: - return MAPID_FILIR; - case 6004: - case 6008: - return MAPID_VANILMIRTH; - // Evolved Homunculus - case 6009: - case 6013: - return MAPID_LIF_E; - case 6010: - case 6014: - return MAPID_AMISTR_E; - case 6011: - case 6015: - return MAPID_FILIR_E; - case 6012: - case 6016: - return MAPID_VANILMIRTH_E; - // Homunculus S - case 6048: - return MAPID_EIRA; - case 6049: - return MAPID_BAYERI; - case 6050: - return MAPID_SERA; - case 6051: - return MAPID_DIETER; - case 6052: - return MAPID_ELANOR; - - default: - return -1; - } + switch(hom_class) + { + // Normal Homunculus + case 6001: case 6005: return MAPID_LIF; + case 6002: case 6006: return MAPID_AMISTR; + case 6003: case 6007: return MAPID_FILIR; + case 6004: case 6008: return MAPID_VANILMIRTH; + // Evolved Homunculus + case 6009: case 6013: return MAPID_LIF_E; + case 6010: case 6014: return MAPID_AMISTR_E; + case 6011: case 6015: return MAPID_FILIR_E; + case 6012: case 6016: return MAPID_VANILMIRTH_E; + // Homunculus S + case 6048: return MAPID_EIRA; + case 6049: return MAPID_BAYERI; + case 6050: return MAPID_SERA; + case 6051: return MAPID_DIETER; + case 6052: return MAPID_ELANOR; + + default: return -1; + } } -int hom_addspiritball(TBL_HOM *hd, int max) -{ +int hom_addspiritball(TBL_HOM *hd, int max) { nullpo_ret(hd); if (max > MAX_SKILL_LEVEL) @@ -112,17 +90,17 @@ int hom_addspiritball(TBL_HOM *hd, int max) hd->spiritball = 0; if (hd->spiritball && hd->spiritball >= max) { - hd->spiritball = max; - } else + hd->spiritball = max; + } + else hd->spiritball++; - + clif_spiritball(&hd->bl); return 0; } -int hom_delspiritball(TBL_HOM *hd, int count, int type) -{ +int hom_delspiritball(TBL_HOM *hd, int count, int type) { nullpo_ret(hd); if (hd->spiritball <= 0) { @@ -135,7 +113,7 @@ int hom_delspiritball(TBL_HOM *hd, int count, int type) count = MAX_SKILL_LEVEL; if (count > hd->spiritball) count = hd->spiritball; - + hd->spiritball -= count; if (!type) clif_spiritball(&hd->bl); @@ -143,1154 +121,1164 @@ int hom_delspiritball(TBL_HOM *hd, int count, int type) return 0; } -void merc_damage(struct homun_data *hd) -{ - clif_hominfo(hd->master,hd,0); +void merc_damage(struct homun_data *hd) { + clif_hominfo(hd->master,hd,0); } int merc_hom_dead(struct homun_data *hd) { - //There's no intimacy penalties on death (from Tharis) - struct map_session_data *sd = hd->master; + //There's no intimacy penalties on death (from Tharis) + struct map_session_data *sd = hd->master; - clif_emotion(&hd->bl, E_WAH); + clif_emotion(&hd->bl, E_WAH); - //Delete timers when dead. - merc_hom_hungry_timer_delete(hd); - hd->homunculus.hp = 0; + //Delete timers when dead. + merc_hom_hungry_timer_delete(hd); + hd->homunculus.hp = 0; - if (!sd) //unit remove map will invoke unit free - return 3; + if (!sd) //unit remove map will invoke unit free + return 3; - clif_emotion(&sd->bl, E_SOB); - //Remove from map (if it has no intimacy, it is auto-removed from memory) - return 3; + clif_emotion(&sd->bl, E_SOB); + //Remove from map (if it has no intimacy, it is auto-removed from memory) + return 3; } //Vaporize a character's homun. If flag, HP needs to be 80% or above. int merc_hom_vaporize(struct map_session_data *sd, int flag) { - struct homun_data *hd; - - nullpo_ret(sd); - - hd = sd->hd; - if (!hd || hd->homunculus.vaporize) - return 0; - - if (status_isdead(&hd->bl)) - return 0; //Can't vaporize a dead homun. - - if (flag && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80) - return 0; - - hd->regen.state.block = 3; //Block regen while vaporized. - //Delete timers when vaporized. - merc_hom_hungry_timer_delete(hd); - hd->homunculus.vaporize = 1; - if (battle_config.hom_setting&0x40) - memset(hd->blockskill, 0, sizeof(hd->blockskill)); - clif_hominfo(sd, sd->hd, 0); - merc_save(hd); - return unit_remove_map(&hd->bl, CLR_OUTSIGHT); + struct homun_data *hd; + + nullpo_ret(sd); + + hd = sd->hd; + if (!hd || hd->homunculus.vaporize) + return 0; + + if (status_isdead(&hd->bl)) + return 0; //Can't vaporize a dead homun. + + if (flag && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80) + return 0; + + hd->regen.state.block = 3; //Block regen while vaporized. + //Delete timers when vaporized. + merc_hom_hungry_timer_delete(hd); + hd->homunculus.vaporize = 1; + if(battle_config.hom_setting&0x40) + memset(hd->blockskill, 0, sizeof(hd->blockskill)); + clif_hominfo(sd, sd->hd, 0); + merc_save(hd); + return unit_remove_map(&hd->bl, CLR_OUTSIGHT); } -//delete a homunculus, completely "killing it". +//delete a homunculus, completely "killing it". //Emote is the emotion the master should use, send negative to disable. int merc_hom_delete(struct homun_data *hd, int emote) { - struct map_session_data *sd; - nullpo_ret(hd); - sd = hd->master; - - if (!sd) - return unit_free(&hd->bl,CLR_DEAD); - - if (emote >= 0) - clif_emotion(&sd->bl, emote); - - //This makes it be deleted right away. - hd->homunculus.intimacy = 0; - // Send homunculus_dead to client - hd->homunculus.hp = 0; - clif_hominfo(sd, hd, 0); - return unit_remove_map(&hd->bl,CLR_OUTSIGHT); + struct map_session_data *sd; + nullpo_ret(hd); + sd = hd->master; + + if (!sd) + return unit_free(&hd->bl,CLR_DEAD); + + if (emote >= 0) + clif_emotion(&sd->bl, emote); + + //This makes it be deleted right away. + hd->homunculus.intimacy = 0; + // Send homunculus_dead to client + hd->homunculus.hp = 0; + clif_hominfo(sd, hd, 0); + return unit_remove_map(&hd->bl,CLR_OUTSIGHT); } int merc_hom_calc_skilltree(struct homun_data *hd, int flag_evolve) { - int i, id = 0; - int j, f = 1; - int c = 0; - - nullpo_ret(hd); - /* load previous homunculus form skills first. */ - if (hd->homunculus.prev_class != 0) { - c = hd->homunculus.prev_class - HM_CLASS_BASE; - - for (i = 0; i < MAX_SKILL_TREE && (id = hskill_tree[c][i].id) > 0; i++) { - if (hd->homunculus.hskill[ id - HM_SKILLBASE ].id) - continue; //Skill already known. - if (!battle_config.skillfree) { - for (j = 0; j < MAX_PC_SKILL_REQUIRE; j++) { - if (hskill_tree[c][i].need[j].id && - merc_hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv) { - f = 0; - break; - } - } - } - if (f) - hd->homunculus.hskill[id-HM_SKILLBASE].id = id; - } - - f = 1; - } - - c = hd->homunculus.class_ - HM_CLASS_BASE; - - for (i = 0; i < MAX_SKILL_TREE && (id = hskill_tree[c][i].id) > 0; i++) { - if (hd->homunculus.hskill[ id - HM_SKILLBASE ].id) - continue; //Skill already known. - j = (flag_evolve) ? 10 : hd->homunculus.intimacy; - if (j < hskill_tree[c][i].intimacylv) - continue; - if (!battle_config.skillfree) { - for (j = 0; j < MAX_PC_SKILL_REQUIRE; j++) { - if (hskill_tree[c][i].need[j].id && - merc_hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv) { - f = 0; - break; - } - } - } - if (f) - hd->homunculus.hskill[id-HM_SKILLBASE].id = id; - } - - if (hd->master) - clif_homskillinfoblock(hd->master); - return 0; + int i, id = 0; + int j, f = 1; + int c = 0; + + nullpo_ret(hd); + /* load previous homunculus form skills first. */ + if( hd->homunculus.prev_class != 0 ) { + c = hd->homunculus.prev_class - HM_CLASS_BASE; + + for( i = 0; i < MAX_SKILL_TREE && ( id = hskill_tree[c][i].id ) > 0; i++ ) { + if( hd->homunculus.hskill[ id - HM_SKILLBASE ].id ) + continue; //Skill already known. + if(!battle_config.skillfree) { + for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) { + if( hskill_tree[c][i].need[j].id && + merc_hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv ) { + f = 0; + break; + } + } + } + if ( f ) + hd->homunculus.hskill[id-HM_SKILLBASE].id = id; + } + + f = 1; + } + + c = hd->homunculus.class_ - HM_CLASS_BASE; + + for( i = 0; i < MAX_SKILL_TREE && ( id = hskill_tree[c][i].id ) > 0; i++ ) { + if( hd->homunculus.hskill[ id - HM_SKILLBASE ].id ) + continue; //Skill already known. + j = ( flag_evolve ) ? 10 : hd->homunculus.intimacy; + if( j < hskill_tree[c][i].intimacylv ) + continue; + if(!battle_config.skillfree) { + for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) { + if( hskill_tree[c][i].need[j].id && + merc_hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv ) { + f = 0; + break; + } + } + } + if ( f ) + hd->homunculus.hskill[id-HM_SKILLBASE].id = id; + } + + if( hd->master ) + clif_homskillinfoblock(hd->master); + return 0; } int merc_hom_checkskill(struct homun_data *hd,int skill_id) { - int i = skill_id - HM_SKILLBASE; - if (!hd) - return 0; + int i = skill_id - HM_SKILLBASE; + if(!hd) + return 0; - if (hd->homunculus.hskill[i].id == skill_id) - return (hd->homunculus.hskill[i].lv); + if(hd->homunculus.hskill[i].id == skill_id) + return (hd->homunculus.hskill[i].lv); - return 0; + return 0; } -int merc_skill_tree_get_max(int id, int b_class) -{ - int i, skillid; - b_class -= HM_CLASS_BASE; - for (i=0; (skillid=hskill_tree[b_class][i].id)>0; i++) - if (id == skillid) - return hskill_tree[b_class][i].max; - return skill_get_max(id); +int merc_skill_tree_get_max(int id, int b_class){ + int i, skillid; + b_class -= HM_CLASS_BASE; + for(i=0;(skillid=hskill_tree[b_class][i].id)>0;i++) + if (id == skillid) + return hskill_tree[b_class][i].max; + return skill_get_max(id); } void merc_hom_skillup(struct homun_data *hd,int skillnum) { - int i = 0 ; - nullpo_retv(hd); - - if (hd->homunculus.vaporize) - return; - - i = skillnum - HM_SKILLBASE; - if (hd->homunculus.skillpts > 0 && - hd->homunculus.hskill[i].id && - hd->homunculus.hskill[i].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] - hd->homunculus.hskill[i].lv < merc_skill_tree_get_max(skillnum, hd->homunculus.class_) - ) { - hd->homunculus.hskill[i].lv++; - hd->homunculus.skillpts-- ; - status_calc_homunculus(hd,0); - if (hd->master) { - clif_homskillup(hd->master, skillnum); - clif_hominfo(hd->master,hd,0); - clif_homskillinfoblock(hd->master); - } - } + int i = 0 ; + nullpo_retv(hd); + + if(hd->homunculus.vaporize) + return; + + i = skillnum - HM_SKILLBASE; + if(hd->homunculus.skillpts > 0 && + hd->homunculus.hskill[i].id && + hd->homunculus.hskill[i].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] + hd->homunculus.hskill[i].lv < merc_skill_tree_get_max(skillnum, hd->homunculus.class_) + ) + { + hd->homunculus.hskill[i].lv++; + hd->homunculus.skillpts-- ; + status_calc_homunculus(hd,0); + if (hd->master) { + clif_homskillup(hd->master, skillnum); + clif_hominfo(hd->master,hd,0); + clif_homskillinfoblock(hd->master); + } + } } int merc_hom_levelup(struct homun_data *hd) { - struct s_homunculus *hom; - struct h_stats *min, *max; - int growth_str, growth_agi, growth_vit, growth_int, growth_dex, growth_luk ; - int growth_max_hp, growth_max_sp ; - char output[256] ; - int m_class; - - if ((m_class = hom_class2mapid(hd->homunculus.class_)) == -1) { - ShowError("merc_hom_levelup: Invalid class %d. \n", hd->homunculus.class_); - return 0; - } - - if ((m_class&HOM_REG) && (hd->homunculus.level >= battle_config.hom_max_level || ((m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level) || !hd->exp_next || hd->homunculus.exp < hd->exp_next)) - return 0; - - hom = &hd->homunculus; - hom->level++ ; - if (!(hom->level % 3)) - hom->skillpts++ ; //1 skillpoint each 3 base level - - hom->exp -= hd->exp_next ; - hd->exp_next = hexptbl[hom->level - 1] ; - - max = &hd->homunculusDB->gmax; - min = &hd->homunculusDB->gmin; - - growth_max_hp = rnd_value(min->HP, max->HP); - growth_max_sp = rnd_value(min->SP, max->SP); - growth_str = rnd_value(min->str, max->str); - growth_agi = rnd_value(min->agi, max->agi); - growth_vit = rnd_value(min->vit, max->vit); - growth_dex = rnd_value(min->dex, max->dex); - growth_int = rnd_value(min->int_,max->int_); - growth_luk = rnd_value(min->luk, max->luk); - - //Aegis discards the decimals in the stat growth values! - growth_str-=growth_str%10; - growth_agi-=growth_agi%10; - growth_vit-=growth_vit%10; - growth_dex-=growth_dex%10; - growth_int-=growth_int%10; - growth_luk-=growth_luk%10; - - hom->max_hp += growth_max_hp; - hom->max_sp += growth_max_sp; - hom->str += growth_str; - hom->agi += growth_agi; - hom->vit += growth_vit; - hom->dex += growth_dex; - hom->int_+= growth_int; - hom->luk += growth_luk; - - if (battle_config.homunculus_show_growth) { - sprintf(output, - "Growth: hp:%d sp:%d str(%.2f) agi(%.2f) vit(%.2f) int(%.2f) dex(%.2f) luk(%.2f) ", - growth_max_hp, growth_max_sp, - growth_str/10.0, growth_agi/10.0, growth_vit/10.0, - growth_int/10.0, growth_dex/10.0, growth_luk/10.0); - clif_disp_onlyself(hd->master,output,strlen(output)); - } - return 1 ; + struct s_homunculus *hom; + struct h_stats *min, *max; + int growth_str, growth_agi, growth_vit, growth_int, growth_dex, growth_luk ; + int growth_max_hp, growth_max_sp ; + char output[256] ; + int m_class; + + if((m_class = hom_class2mapid(hd->homunculus.class_)) == -1) { + ShowError("merc_hom_levelup: Invalid class %d. \n", hd->homunculus.class_); + return 0; + } + + if((m_class&HOM_REG) && (hd->homunculus.level >= battle_config.hom_max_level || ((m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level) || !hd->exp_next || hd->homunculus.exp < hd->exp_next)) + return 0; + + hom = &hd->homunculus; + hom->level++ ; + if (!(hom->level % 3)) + hom->skillpts++ ; //1 skillpoint each 3 base level + + hom->exp -= hd->exp_next ; + hd->exp_next = hexptbl[hom->level - 1] ; + + max = &hd->homunculusDB->gmax; + min = &hd->homunculusDB->gmin; + + growth_max_hp = rnd_value(min->HP, max->HP); + growth_max_sp = rnd_value(min->SP, max->SP); + growth_str = rnd_value(min->str, max->str); + growth_agi = rnd_value(min->agi, max->agi); + growth_vit = rnd_value(min->vit, max->vit); + growth_dex = rnd_value(min->dex, max->dex); + growth_int = rnd_value(min->int_,max->int_); + growth_luk = rnd_value(min->luk, max->luk); + + //Aegis discards the decimals in the stat growth values! + growth_str-=growth_str%10; + growth_agi-=growth_agi%10; + growth_vit-=growth_vit%10; + growth_dex-=growth_dex%10; + growth_int-=growth_int%10; + growth_luk-=growth_luk%10; + + hom->max_hp += growth_max_hp; + hom->max_sp += growth_max_sp; + hom->str += growth_str; + hom->agi += growth_agi; + hom->vit += growth_vit; + hom->dex += growth_dex; + hom->int_+= growth_int; + hom->luk += growth_luk; + + if ( battle_config.homunculus_show_growth ) { + sprintf(output, + "Growth: hp:%d sp:%d str(%.2f) agi(%.2f) vit(%.2f) int(%.2f) dex(%.2f) luk(%.2f) ", + growth_max_hp, growth_max_sp, + growth_str/10.0, growth_agi/10.0, growth_vit/10.0, + growth_int/10.0, growth_dex/10.0, growth_luk/10.0); + clif_disp_onlyself(hd->master,output,strlen(output)); + } + return 1 ; } int merc_hom_change_class(struct homun_data *hd, short class_) { - int i; - i = search_homunculusDB_index(class_,HOMUNCULUS_CLASS); - if (i < 0) - return 0; - hd->homunculusDB = &homunculus_db[i]; - hd->homunculus.class_ = class_; - status_set_viewdata(&hd->bl, class_); - merc_hom_calc_skilltree(hd, 1); - return 1; + int i; + i = search_homunculusDB_index(class_,HOMUNCULUS_CLASS); + if(i < 0) + return 0; + hd->homunculusDB = &homunculus_db[i]; + hd->homunculus.class_ = class_; + status_set_viewdata(&hd->bl, class_); + merc_hom_calc_skilltree(hd, 1); + return 1; } int merc_hom_evolution(struct homun_data *hd) { - struct s_homunculus *hom; - struct h_stats *max, *min; - struct map_session_data *sd; - nullpo_ret(hd); - - if (!hd->homunculusDB->evo_class || hd->homunculus.class_ == hd->homunculusDB->evo_class) { - clif_emotion(&hd->bl, E_SWT); - return 0 ; - } - sd = hd->master; - if (!sd) - return 0; - - if (!merc_hom_change_class(hd, hd->homunculusDB->evo_class)) { - ShowError("merc_hom_evolution: Can't evolve homunc from %d to %d", hd->homunculus.class_, hd->homunculusDB->evo_class); - return 0; - } - - //Apply evolution bonuses - hom = &hd->homunculus; - max = &hd->homunculusDB->emax; - min = &hd->homunculusDB->emin; - hom->max_hp += rnd_value(min->HP, max->HP); - hom->max_sp += rnd_value(min->SP, max->SP); - hom->str += 10*rnd_value(min->str, max->str); - hom->agi += 10*rnd_value(min->agi, max->agi); - hom->vit += 10*rnd_value(min->vit, max->vit); - hom->int_+= 10*rnd_value(min->int_,max->int_); - hom->dex += 10*rnd_value(min->dex, max->dex); - hom->luk += 10*rnd_value(min->luk, max->luk); - hom->intimacy = 500; - - unit_remove_map(&hd->bl, CLR_OUTSIGHT); - map_addblock(&hd->bl); - - clif_spawn(&hd->bl); - clif_emotion(&sd->bl, E_NO1); - clif_specialeffect(&hd->bl,568,AREA); - - //status_Calc flag&1 will make current HP/SP be reloaded from hom structure - hom->hp = hd->battle_status.hp; - hom->sp = hd->battle_status.sp; - status_calc_homunculus(hd,1); - - if (!(battle_config.hom_setting&0x2)) - skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately - - return 1 ; + struct s_homunculus *hom; + struct h_stats *max, *min; + struct map_session_data *sd; + nullpo_ret(hd); + + if(!hd->homunculusDB->evo_class || hd->homunculus.class_ == hd->homunculusDB->evo_class) + { + clif_emotion(&hd->bl, E_SWT); + return 0 ; + } + sd = hd->master; + if (!sd) + return 0; + + if (!merc_hom_change_class(hd, hd->homunculusDB->evo_class)) { + ShowError("merc_hom_evolution: Can't evolve homunc from %d to %d", hd->homunculus.class_, hd->homunculusDB->evo_class); + return 0; + } + + //Apply evolution bonuses + hom = &hd->homunculus; + max = &hd->homunculusDB->emax; + min = &hd->homunculusDB->emin; + hom->max_hp += rnd_value(min->HP, max->HP); + hom->max_sp += rnd_value(min->SP, max->SP); + hom->str += 10*rnd_value(min->str, max->str); + hom->agi += 10*rnd_value(min->agi, max->agi); + hom->vit += 10*rnd_value(min->vit, max->vit); + hom->int_+= 10*rnd_value(min->int_,max->int_); + hom->dex += 10*rnd_value(min->dex, max->dex); + hom->luk += 10*rnd_value(min->luk, max->luk); + hom->intimacy = 500; + + unit_remove_map(&hd->bl, CLR_OUTSIGHT); + map_addblock(&hd->bl); + + clif_spawn(&hd->bl); + clif_emotion(&sd->bl, E_NO1); + clif_specialeffect(&hd->bl,568,AREA); + + //status_Calc flag&1 will make current HP/SP be reloaded from hom structure + hom->hp = hd->battle_status.hp; + hom->sp = hd->battle_status.sp; + status_calc_homunculus(hd,1); + + if (!(battle_config.hom_setting&0x2)) + skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately + + return 1 ; } int hom_mutate(struct homun_data *hd, int homun_id) { - struct s_homunculus *hom; - struct map_session_data *sd; - int m_class, m_id, prev_class = 0; - nullpo_ret(hd); - - m_class = hom_class2mapid(hd->homunculus.class_); - m_id = hom_class2mapid(homun_id); - - if (m_class == -1 || m_id == -1 || !(m_class&HOM_EVO) || !(m_id&HOM_S)) { - clif_emotion(&hd->bl, E_SWT); - return 0; - } - - sd = hd->master; - if (!sd) - return 0; - - prev_class = hd->homunculus.class_; - - if (!merc_hom_change_class(hd, homun_id)) { - ShowError("hom_mutate: Can't evolve homunc from %d to %d", hd->homunculus.class_, homun_id); - return 0; - } - - unit_remove_map(&hd->bl, CLR_OUTSIGHT); - map_addblock(&hd->bl); - - clif_spawn(&hd->bl); - clif_emotion(&sd->bl, E_NO1); - clif_specialeffect(&hd->bl,568,AREA); - - - //status_Calc flag&1 will make current HP/SP be reloaded from hom structure - hom = &hd->homunculus; - hom->hp = hd->battle_status.hp; - hom->sp = hd->battle_status.sp; - hom->prev_class = prev_class; - status_calc_homunculus(hd,1); - - if (!(battle_config.hom_setting&0x2)) - skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately - - return 1; + struct s_homunculus *hom; + struct map_session_data *sd; + int m_class, m_id, prev_class = 0; + nullpo_ret(hd); + + m_class = hom_class2mapid(hd->homunculus.class_); + m_id = hom_class2mapid(homun_id); + + if( m_class == -1 || m_id == -1 || !(m_class&HOM_EVO) || !(m_id&HOM_S) ) { + clif_emotion(&hd->bl, E_SWT); + return 0; + } + + sd = hd->master; + if (!sd) + return 0; + + prev_class = hd->homunculus.class_; + + if (!merc_hom_change_class(hd, homun_id)) { + ShowError("hom_mutate: Can't evolve homunc from %d to %d", hd->homunculus.class_, homun_id); + return 0; + } + + unit_remove_map(&hd->bl, CLR_OUTSIGHT); + map_addblock(&hd->bl); + + clif_spawn(&hd->bl); + clif_emotion(&sd->bl, E_NO1); + clif_specialeffect(&hd->bl,568,AREA); + + + //status_Calc flag&1 will make current HP/SP be reloaded from hom structure + hom = &hd->homunculus; + hom->hp = hd->battle_status.hp; + hom->sp = hd->battle_status.sp; + hom->prev_class = prev_class; + status_calc_homunculus(hd,1); + + if (!(battle_config.hom_setting&0x2)) + skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately + + return 1; } int merc_hom_gainexp(struct homun_data *hd,int exp) { - int m_class; - - if (hd->homunculus.vaporize) - return 1; - - if ((m_class = hom_class2mapid(hd->homunculus.class_)) == -1) { - ShowError("merc_hom_gainexp: Invalid class %d. \n", hd->homunculus.class_); - return 0; - } - - if (hd->exp_next == 0 || - ((m_class&HOM_REG) && hd->homunculus.level >= battle_config.hom_max_level) || - ((m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level)) { - hd->homunculus.exp = 0; - return 0; - } - - hd->homunculus.exp += exp; - - if (hd->homunculus.exp < hd->exp_next) { - clif_hominfo(hd->master,hd,0); - return 0; - } - - //levelup - do { - merc_hom_levelup(hd) ; - } while (hd->homunculus.exp > hd->exp_next && hd->exp_next != 0); - - if (hd->exp_next == 0) - hd->homunculus.exp = 0 ; - - clif_specialeffect(&hd->bl,568,AREA); - status_calc_homunculus(hd,0); - status_percent_heal(&hd->bl, 100, 100); - return 0; + int m_class; + + if(hd->homunculus.vaporize) + return 1; + + if((m_class = hom_class2mapid(hd->homunculus.class_)) == -1) { + ShowError("merc_hom_gainexp: Invalid class %d. \n", hd->homunculus.class_); + return 0; + } + + if( hd->exp_next == 0 || + ((m_class&HOM_REG) && hd->homunculus.level >= battle_config.hom_max_level) || + ((m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level) ) { + hd->homunculus.exp = 0; + return 0; + } + + hd->homunculus.exp += exp; + + if(hd->homunculus.exp < hd->exp_next) { + clif_hominfo(hd->master,hd,0); + return 0; + } + + //levelup + do + { + merc_hom_levelup(hd) ; + } + while(hd->homunculus.exp > hd->exp_next && hd->exp_next != 0 ); + + if( hd->exp_next == 0 ) + hd->homunculus.exp = 0 ; + + clif_specialeffect(&hd->bl,568,AREA); + status_calc_homunculus(hd,0); + status_percent_heal(&hd->bl, 100, 100); + return 0; } // Return the new value -int merc_hom_increase_intimacy(struct homun_data *hd, unsigned int value) +int merc_hom_increase_intimacy(struct homun_data * hd, unsigned int value) { - if (battle_config.homunculus_friendly_rate != 100) - value = (value * battle_config.homunculus_friendly_rate) / 100; - - if (hd->homunculus.intimacy + value <= 100000) - hd->homunculus.intimacy += value; - else - hd->homunculus.intimacy = 100000; - return hd->homunculus.intimacy; + if (battle_config.homunculus_friendly_rate != 100) + value = (value * battle_config.homunculus_friendly_rate) / 100; + + if (hd->homunculus.intimacy + value <= 100000) + hd->homunculus.intimacy += value; + else + hd->homunculus.intimacy = 100000; + return hd->homunculus.intimacy; } // Return 0 if decrease fails or intimacy became 0 else the new value -int merc_hom_decrease_intimacy(struct homun_data *hd, unsigned int value) +int merc_hom_decrease_intimacy(struct homun_data * hd, unsigned int value) { - if (hd->homunculus.intimacy >= value) - hd->homunculus.intimacy -= value; - else - hd->homunculus.intimacy = 0; + if (hd->homunculus.intimacy >= value) + hd->homunculus.intimacy -= value; + else + hd->homunculus.intimacy = 0; - return hd->homunculus.intimacy; + return hd->homunculus.intimacy; } -void merc_hom_heal(struct homun_data *hd) -{ - clif_hominfo(hd->master,hd,0); +void merc_hom_heal(struct homun_data *hd) { + clif_hominfo(hd->master,hd,0); } void merc_save(struct homun_data *hd) { - // copy data that must be saved in homunculus struct ( hp / sp ) - TBL_PC *sd = hd->master; - //Do not check for max_hp/max_sp caps as current could be higher to max due - //to status changes/skills (they will be capped as needed upon stat - //calculation on login) - hd->homunculus.hp = hd->battle_status.hp; - hd->homunculus.sp = hd->battle_status.sp; - intif_homunculus_requestsave(sd->status.account_id, &hd->homunculus); + // copy data that must be saved in homunculus struct ( hp / sp ) + TBL_PC * sd = hd->master; + //Do not check for max_hp/max_sp caps as current could be higher to max due + //to status changes/skills (they will be capped as needed upon stat + //calculation on login) + hd->homunculus.hp = hd->battle_status.hp; + hd->homunculus.sp = hd->battle_status.sp; + intif_homunculus_requestsave(sd->status.account_id, &hd->homunculus); } int merc_menu(struct map_session_data *sd,int menunum) { - nullpo_ret(sd); - if (sd->hd == NULL) - return 1; - - switch (menunum) { - case 0: - break; - case 1: - merc_hom_food(sd, sd->hd); - break; - case 2: - merc_hom_delete(sd->hd, -1); - break; - default: - ShowError("merc_menu : unknown menu choice : %d\n", menunum) ; - break; - } - return 0; + nullpo_ret(sd); + if (sd->hd == NULL) + return 1; + + switch(menunum) { + case 0: + break; + case 1: + merc_hom_food(sd, sd->hd); + break; + case 2: + merc_hom_delete(sd->hd, -1); + break; + default: + ShowError("merc_menu : unknown menu choice : %d\n", menunum) ; + break; + } + return 0; } int merc_hom_food(struct map_session_data *sd, struct homun_data *hd) { - int i, foodID, emotion; - - if (hd->homunculus.vaporize) - return 1 ; - - foodID = hd->homunculusDB->foodID; - i = pc_search_inventory(sd,foodID); - if (i < 0) { - clif_hom_food(sd,foodID,0); - return 1; - } - pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); - - if (hd->homunculus.hunger >= 91) { - merc_hom_decrease_intimacy(hd, 50); - emotion = E_WAH; - } else if (hd->homunculus.hunger >= 76) { - merc_hom_decrease_intimacy(hd, 5); - emotion = E_SWT2; - } else if (hd->homunculus.hunger >= 26) { - merc_hom_increase_intimacy(hd, 75); - emotion = E_HO; - } else if (hd->homunculus.hunger >= 11) { - merc_hom_increase_intimacy(hd, 100); - emotion = E_HO; - } else { - merc_hom_increase_intimacy(hd, 50); - emotion = E_HO; - } - - hd->homunculus.hunger += 10; //dunno increase value for each food - if (hd->homunculus.hunger > 100) - hd->homunculus.hunger = 100; - - clif_emotion(&hd->bl,emotion); - clif_send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger); - clif_send_homdata(sd,SP_INTIMATE,hd->homunculus.intimacy / 100); - clif_hom_food(sd,foodID,1); - - // Too much food :/ - if (hd->homunculus.intimacy == 0) - return merc_hom_delete(sd->hd, E_OMG); - - return 0; + int i, foodID, emotion; + + if(hd->homunculus.vaporize) + return 1 ; + + foodID = hd->homunculusDB->foodID; + i = pc_search_inventory(sd,foodID); + if(i < 0) { + clif_hom_food(sd,foodID,0); + return 1; + } + pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); + + if ( hd->homunculus.hunger >= 91 ) { + merc_hom_decrease_intimacy(hd, 50); + emotion = E_WAH; + } else if ( hd->homunculus.hunger >= 76 ) { + merc_hom_decrease_intimacy(hd, 5); + emotion = E_SWT2; + } else if ( hd->homunculus.hunger >= 26 ) { + merc_hom_increase_intimacy(hd, 75); + emotion = E_HO; + } else if ( hd->homunculus.hunger >= 11 ) { + merc_hom_increase_intimacy(hd, 100); + emotion = E_HO; + } else { + merc_hom_increase_intimacy(hd, 50); + emotion = E_HO; + } + + hd->homunculus.hunger += 10; //dunno increase value for each food + if(hd->homunculus.hunger > 100) + hd->homunculus.hunger = 100; + + clif_emotion(&hd->bl,emotion); + clif_send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger); + clif_send_homdata(sd,SP_INTIMATE,hd->homunculus.intimacy / 100); + clif_hom_food(sd,foodID,1); + + // Too much food :/ + if(hd->homunculus.intimacy == 0) + return merc_hom_delete(sd->hd, E_OMG); + + return 0; } static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd; - struct homun_data *hd; - - sd=map_id2sd(id); - if (!sd) - return 1; - - if (!sd->status.hom_id || !(hd=sd->hd)) - return 1; - - if (hd->hungry_timer != tid) { - ShowError("merc_hom_hungry_timer %d != %d\n",hd->hungry_timer,tid); - return 0; - } - - hd->hungry_timer = INVALID_TIMER; - - hd->homunculus.hunger-- ; - if (hd->homunculus.hunger <= 10) { - clif_emotion(&hd->bl, E_AN); - } else if (hd->homunculus.hunger == 25) { - clif_emotion(&hd->bl, E_HMM); - } else if (hd->homunculus.hunger == 75) { - clif_emotion(&hd->bl, E_OK); - } - - if (hd->homunculus.hunger < 0) { - hd->homunculus.hunger = 0; - // Delete the homunculus if intimacy <= 100 - if (!merc_hom_decrease_intimacy(hd, 100)) - return merc_hom_delete(hd, E_OMG); - clif_send_homdata(sd,SP_INTIMATE,hd->homunculus.intimacy / 100); - } - - clif_send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger); - hd->hungry_timer = add_timer(tick+hd->homunculusDB->hungryDelay,merc_hom_hungry,sd->bl.id,0); //simple Fix albator - return 0; + struct map_session_data *sd; + struct homun_data *hd; + + sd=map_id2sd(id); + if(!sd) + return 1; + + if(!sd->status.hom_id || !(hd=sd->hd)) + return 1; + + if(hd->hungry_timer != tid){ + ShowError("merc_hom_hungry_timer %d != %d\n",hd->hungry_timer,tid); + return 0; + } + + hd->hungry_timer = INVALID_TIMER; + + hd->homunculus.hunger-- ; + if(hd->homunculus.hunger <= 10) { + clif_emotion(&hd->bl, E_AN); + } else if(hd->homunculus.hunger == 25) { + clif_emotion(&hd->bl, E_HMM); + } else if(hd->homunculus.hunger == 75) { + clif_emotion(&hd->bl, E_OK); + } + + if(hd->homunculus.hunger < 0) { + hd->homunculus.hunger = 0; + // Delete the homunculus if intimacy <= 100 + if ( !merc_hom_decrease_intimacy(hd, 100) ) + return merc_hom_delete(hd, E_OMG); + clif_send_homdata(sd,SP_INTIMATE,hd->homunculus.intimacy / 100); + } + + clif_send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger); + hd->hungry_timer = add_timer(tick+hd->homunculusDB->hungryDelay,merc_hom_hungry,sd->bl.id,0); //simple Fix albator + return 0; } int merc_hom_hungry_timer_delete(struct homun_data *hd) { - nullpo_ret(hd); - if (hd->hungry_timer != INVALID_TIMER) { - delete_timer(hd->hungry_timer,merc_hom_hungry); - hd->hungry_timer = INVALID_TIMER; - } - return 1; + nullpo_ret(hd); + if(hd->hungry_timer != INVALID_TIMER) { + delete_timer(hd->hungry_timer,merc_hom_hungry); + hd->hungry_timer = INVALID_TIMER; + } + return 1; } int merc_hom_change_name(struct map_session_data *sd,char *name) { - int i; - struct homun_data *hd; - nullpo_retr(1, sd); - - hd = sd->hd; - if (!merc_is_hom_active(hd)) - return 1; - if (hd->homunculus.rename_flag && !battle_config.hom_rename) - return 1; - - for (i=0; i<NAME_LENGTH && name[i]; i++) { - if (!(name[i]&0xe0) || name[i]==0x7f) - return 1; - } - - return intif_rename_hom(sd, name); + int i; + struct homun_data *hd; + nullpo_retr(1, sd); + + hd = sd->hd; + if (!merc_is_hom_active(hd)) + return 1; + if(hd->homunculus.rename_flag && !battle_config.hom_rename) + return 1; + + for(i=0;i<NAME_LENGTH && name[i];i++){ + if( !(name[i]&0xe0) || name[i]==0x7f) + return 1; + } + + return intif_rename_hom(sd, name); } -int merc_hom_change_name_ack(struct map_session_data *sd, char *name, int flag) +int merc_hom_change_name_ack(struct map_session_data *sd, char* name, int flag) { - struct homun_data *hd = sd->hd; - if (!merc_is_hom_active(hd)) return 0; - - normalize_name(name," ");//bugreport:3032 - - if (!flag || !strlen(name)) { - clif_displaymessage(sd->fd, msg_txt(280)); // You cannot use this name - return 0; - } - strncpy(hd->homunculus.name,name,NAME_LENGTH); - clif_charnameack(0,&hd->bl); - hd->homunculus.rename_flag = 1; - clif_hominfo(sd,hd,0); - return 1; + struct homun_data *hd = sd->hd; + if (!merc_is_hom_active(hd)) return 0; + + normalize_name(name," ");//bugreport:3032 + + if ( !flag || !strlen(name) ) { + clif_displaymessage(sd->fd, msg_txt(280)); // You cannot use this name + return 0; + } + strncpy(hd->homunculus.name,name,NAME_LENGTH); + clif_charnameack (0,&hd->bl); + hd->homunculus.rename_flag = 1; + clif_hominfo(sd,hd,0); + return 1; } int search_homunculusDB_index(int key,int type) { - int i; - - for (i=0; i<MAX_HOMUNCULUS_CLASS; i++) { - if (homunculus_db[i].base_class <= 0) - continue; - switch (type) { - case HOMUNCULUS_CLASS: - if (homunculus_db[i].base_class == key || - homunculus_db[i].evo_class == key) - return i; - break; - case HOMUNCULUS_FOOD: - if (homunculus_db[i].foodID == key) - return i; - break; - default: - return -1; - } - } - return -1; + int i; + + for(i=0;i<MAX_HOMUNCULUS_CLASS;i++) { + if(homunculus_db[i].base_class <= 0) + continue; + switch(type) { + case HOMUNCULUS_CLASS: + if(homunculus_db[i].base_class == key || + homunculus_db[i].evo_class == key) + return i; + break; + case HOMUNCULUS_FOOD: + if(homunculus_db[i].foodID == key) + return i; + break; + default: + return -1; + } + } + return -1; } // Create homunc structure int merc_hom_alloc(struct map_session_data *sd, struct s_homunculus *hom) { - struct homun_data *hd; - int i = 0; - - nullpo_retr(1, sd); - - Assert((sd->status.hom_id == 0 || sd->hd == 0) || sd->hd->master == sd); - - i = search_homunculusDB_index(hom->class_,HOMUNCULUS_CLASS); - if (i < 0) { - ShowError("merc_hom_alloc: unknown class [%d] for homunculus '%s', requesting deletion.\n", hom->class_, hom->name); - sd->status.hom_id = 0; - intif_homunculus_requestdelete(hom->hom_id); - return 1; - } - sd->hd = hd = (struct homun_data *)aCalloc(1,sizeof(struct homun_data)); - hd->bl.type = BL_HOM; - hd->bl.id = npc_get_new_npc_id(); - - hd->master = sd; - hd->homunculusDB = &homunculus_db[i]; - memcpy(&hd->homunculus, hom, sizeof(struct s_homunculus)); - hd->exp_next = hexptbl[hd->homunculus.level - 1]; - - status_set_viewdata(&hd->bl, hd->homunculus.class_); - status_change_init(&hd->bl); - unit_dataset(&hd->bl); - hd->ud.dir = sd->ud.dir; - - // Find a random valid pos around the player - hd->bl.m = sd->bl.m; - hd->bl.x = sd->bl.x; - hd->bl.y = sd->bl.y; - unit_calc_pos(&hd->bl, sd->bl.x, sd->bl.y, sd->ud.dir); - hd->bl.x = hd->ud.to_x; - hd->bl.y = hd->ud.to_y; - - map_addiddb(&hd->bl); - status_calc_homunculus(hd,1); - - hd->hungry_timer = INVALID_TIMER; - return 0; + struct homun_data *hd; + int i = 0; + + nullpo_retr(1, sd); + + Assert((sd->status.hom_id == 0 || sd->hd == 0) || sd->hd->master == sd); + + i = search_homunculusDB_index(hom->class_,HOMUNCULUS_CLASS); + if(i < 0) { + ShowError("merc_hom_alloc: unknown class [%d] for homunculus '%s', requesting deletion.\n", hom->class_, hom->name); + sd->status.hom_id = 0; + intif_homunculus_requestdelete(hom->hom_id); + return 1; + } + sd->hd = hd = (struct homun_data*)aCalloc(1,sizeof(struct homun_data)); + hd->bl.type = BL_HOM; + hd->bl.id = npc_get_new_npc_id(); + + hd->master = sd; + hd->homunculusDB = &homunculus_db[i]; + memcpy(&hd->homunculus, hom, sizeof(struct s_homunculus)); + hd->exp_next = hexptbl[hd->homunculus.level - 1]; + + status_set_viewdata(&hd->bl, hd->homunculus.class_); + status_change_init(&hd->bl); + unit_dataset(&hd->bl); + hd->ud.dir = sd->ud.dir; + + // Find a random valid pos around the player + hd->bl.m = sd->bl.m; + hd->bl.x = sd->bl.x; + hd->bl.y = sd->bl.y; + unit_calc_pos(&hd->bl, sd->bl.x, sd->bl.y, sd->ud.dir); + hd->bl.x = hd->ud.to_x; + hd->bl.y = hd->ud.to_y; + + map_addiddb(&hd->bl); + status_calc_homunculus(hd,1); + + hd->hungry_timer = INVALID_TIMER; + return 0; } -void merc_hom_init_timers(struct homun_data *hd) +void merc_hom_init_timers(struct homun_data * hd) { - if (hd->hungry_timer == INVALID_TIMER) - hd->hungry_timer = add_timer(gettick()+hd->homunculusDB->hungryDelay,merc_hom_hungry,hd->master->bl.id,0); - hd->regen.state.block = 0; //Restore HP/SP block. + if (hd->hungry_timer == INVALID_TIMER) + hd->hungry_timer = add_timer(gettick()+hd->homunculusDB->hungryDelay,merc_hom_hungry,hd->master->bl.id,0); + hd->regen.state.block = 0; //Restore HP/SP block. } int merc_call_homunculus(struct map_session_data *sd) { - struct homun_data *hd; - - if (!sd->status.hom_id) //Create a new homun. - return merc_create_homunculus_request(sd, HM_CLASS_BASE + rnd_value(0, 7)) ; - - // If homunc not yet loaded, load it - if (!sd->hd) - return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); - - hd = sd->hd; - - if (!hd->homunculus.vaporize) - return 0; //Can't use this if homun wasn't vaporized. - - merc_hom_init_timers(hd); - hd->homunculus.vaporize = 0; - if (hd->bl.prev == NULL) { - //Spawn him - hd->bl.x = sd->bl.x; - hd->bl.y = sd->bl.y; - hd->bl.m = sd->bl.m; - map_addblock(&hd->bl); - clif_spawn(&hd->bl); - clif_send_homdata(sd,SP_ACK,0); - clif_hominfo(sd,hd,1); - clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89] - clif_homskillinfoblock(sd); - if (battle_config.slaves_inherit_speed&1) - status_calc_bl(&hd->bl, SCB_SPEED); - merc_save(hd); - } else - //Warp him to master. - unit_warp(&hd->bl,sd->bl.m, sd->bl.x, sd->bl.y,CLR_OUTSIGHT); - return 1; + struct homun_data *hd; + + if (!sd->status.hom_id) //Create a new homun. + return merc_create_homunculus_request(sd, HM_CLASS_BASE + rnd_value(0, 7)) ; + + // If homunc not yet loaded, load it + if (!sd->hd) + return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); + + hd = sd->hd; + + if (!hd->homunculus.vaporize) + return 0; //Can't use this if homun wasn't vaporized. + + merc_hom_init_timers(hd); + hd->homunculus.vaporize = 0; + if (hd->bl.prev == NULL) + { //Spawn him + hd->bl.x = sd->bl.x; + hd->bl.y = sd->bl.y; + hd->bl.m = sd->bl.m; + map_addblock(&hd->bl); + clif_spawn(&hd->bl); + clif_send_homdata(sd,SP_ACK,0); + clif_hominfo(sd,hd,1); + clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89] + clif_homskillinfoblock(sd); + if (battle_config.slaves_inherit_speed&1) + status_calc_bl(&hd->bl, SCB_SPEED); + merc_save(hd); + } else + //Warp him to master. + unit_warp(&hd->bl,sd->bl.m, sd->bl.x, sd->bl.y,CLR_OUTSIGHT); + return 1; } // Recv homunculus data from char server int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag) { - struct map_session_data *sd; - struct homun_data *hd; - - sd = map_id2sd(account_id); - if (!sd) - return 0; - if (sd->status.char_id != sh->char_id) { - if (sd->status.hom_id == sh->hom_id) - sh->char_id = sd->status.char_id; //Correct char id. - else - return 0; - } - if (!flag) { // Failed to load - sd->status.hom_id = 0; - return 0; - } - - if (!sd->status.hom_id) //Hom just created. - sd->status.hom_id = sh->hom_id; - if (sd->hd) //uh? Overwrite the data. - memcpy(&sd->hd->homunculus, sh, sizeof(struct s_homunculus)); - else - merc_hom_alloc(sd, sh); - - hd = sd->hd; - if (hd && hd->homunculus.hp && !hd->homunculus.vaporize && hd->bl.prev == NULL && sd->bl.prev != NULL) { - map_addblock(&hd->bl); - clif_spawn(&hd->bl); - clif_send_homdata(sd,SP_ACK,0); - clif_hominfo(sd,hd,1); - clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89] - clif_homskillinfoblock(sd); - merc_hom_init_timers(hd); - } - return 1; + struct map_session_data *sd; + struct homun_data *hd; + + sd = map_id2sd(account_id); + if(!sd) + return 0; + if (sd->status.char_id != sh->char_id) + { + if (sd->status.hom_id == sh->hom_id) + sh->char_id = sd->status.char_id; //Correct char id. + else + return 0; + } + if(!flag) { // Failed to load + sd->status.hom_id = 0; + return 0; + } + + if (!sd->status.hom_id) //Hom just created. + sd->status.hom_id = sh->hom_id; + if (sd->hd) //uh? Overwrite the data. + memcpy(&sd->hd->homunculus, sh, sizeof(struct s_homunculus)); + else + merc_hom_alloc(sd, sh); + + hd = sd->hd; + if(hd && hd->homunculus.hp && !hd->homunculus.vaporize && hd->bl.prev == NULL && sd->bl.prev != NULL) + { + map_addblock(&hd->bl); + clif_spawn(&hd->bl); + clif_send_homdata(sd,SP_ACK,0); + clif_hominfo(sd,hd,1); + clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89] + clif_homskillinfoblock(sd); + merc_hom_init_timers(hd); + } + return 1; } // Ask homunculus creation to char server int merc_create_homunculus_request(struct map_session_data *sd, int class_) { - struct s_homunculus homun; - struct h_stats *base; - int i; - - nullpo_retr(1, sd); - - i = search_homunculusDB_index(class_,HOMUNCULUS_CLASS); - if (i < 0) return 0; - - memset(&homun, 0, sizeof(struct s_homunculus)); - //Initial data - strncpy(homun.name, homunculus_db[i].name, NAME_LENGTH-1); - homun.class_ = class_; - homun.level = 1; - homun.hunger = 32; //32% - homun.intimacy = 2100; //21/1000 - homun.char_id = sd->status.char_id; - - homun.hp = 10 ; - base = &homunculus_db[i].base; - homun.max_hp = base->HP; - homun.max_sp = base->SP; - homun.str = base->str *10; - homun.agi = base->agi *10; - homun.vit = base->vit *10; - homun.int_= base->int_*10; - homun.dex = base->dex *10; - homun.luk = base->luk *10; - - // Request homunculus creation - intif_homunculus_create(sd->status.account_id, &homun); - return 1; + struct s_homunculus homun; + struct h_stats *base; + int i; + + nullpo_retr(1, sd); + + i = search_homunculusDB_index(class_,HOMUNCULUS_CLASS); + if(i < 0) return 0; + + memset(&homun, 0, sizeof(struct s_homunculus)); + //Initial data + strncpy(homun.name, homunculus_db[i].name, NAME_LENGTH-1); + homun.class_ = class_; + homun.level = 1; + homun.hunger = 32; //32% + homun.intimacy = 2100; //21/1000 + homun.char_id = sd->status.char_id; + + homun.hp = 10 ; + base = &homunculus_db[i].base; + homun.max_hp = base->HP; + homun.max_sp = base->SP; + homun.str = base->str *10; + homun.agi = base->agi *10; + homun.vit = base->vit *10; + homun.int_= base->int_*10; + homun.dex = base->dex *10; + homun.luk = base->luk *10; + + // Request homunculus creation + intif_homunculus_create(sd->status.account_id, &homun); + return 1; } -int merc_resurrect_homunculus(struct map_session_data *sd, unsigned char per, short x, short y) +int merc_resurrect_homunculus(struct map_session_data* sd, unsigned char per, short x, short y) { - struct homun_data *hd; - nullpo_ret(sd); - - if (!sd->status.hom_id) - return 0; // no homunculus - - if (!sd->hd) //Load homun data; - return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); - - hd = sd->hd; - - if (hd->homunculus.vaporize) - return 0; // vaporized homunculi need to be 'called' - - if (!status_isdead(&hd->bl)) - return 0; // already alive - - merc_hom_init_timers(hd); - - if (!hd->bl.prev) { - //Add it back to the map. - hd->bl.m = sd->bl.m; - hd->bl.x = x; - hd->bl.y = y; - map_addblock(&hd->bl); - clif_spawn(&hd->bl); - } - status_revive(&hd->bl, per, 0); - return 1; + struct homun_data* hd; + nullpo_ret(sd); + + if (!sd->status.hom_id) + return 0; // no homunculus + + if (!sd->hd) //Load homun data; + return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); + + hd = sd->hd; + + if (hd->homunculus.vaporize) + return 0; // vaporized homunculi need to be 'called' + + if (!status_isdead(&hd->bl)) + return 0; // already alive + + merc_hom_init_timers(hd); + + if (!hd->bl.prev) + { //Add it back to the map. + hd->bl.m = sd->bl.m; + hd->bl.x = x; + hd->bl.y = y; + map_addblock(&hd->bl); + clif_spawn(&hd->bl); + } + status_revive(&hd->bl, per, 0); + return 1; } void merc_hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp) { - struct map_session_data *sd = hd->master; - hd->homunculus.hp = hd->battle_status.hp; - if (!sd) - return; - clif_send_homdata(sd,SP_ACK,0); - clif_hominfo(sd,hd,1); - clif_hominfo(sd,hd,0); - clif_homskillinfoblock(sd); + struct map_session_data *sd = hd->master; + hd->homunculus.hp = hd->battle_status.hp; + if (!sd) + return; + clif_send_homdata(sd,SP_ACK,0); + clif_hominfo(sd,hd,1); + clif_hominfo(sd,hd,0); + clif_homskillinfoblock(sd); } void merc_reset_stats(struct homun_data *hd) -{ - //Resets a homunc stats back to zero (but doesn't touches hunger or intimacy) - struct s_homunculus_db *db; - struct s_homunculus *hom; - struct h_stats *base; - hom = &hd->homunculus; - db = hd->homunculusDB; - base = &db->base; - hom->level = 1; - hom->hp = 10; - hom->max_hp = base->HP; - hom->max_sp = base->SP; - hom->str = base->str *10; - hom->agi = base->agi *10; - hom->vit = base->vit *10; - hom->int_= base->int_*10; - hom->dex = base->dex *10; - hom->luk = base->luk *10; - hom->exp = 0; - hd->exp_next = hexptbl[0]; - memset(&hd->homunculus.hskill, 0, sizeof hd->homunculus.hskill); - hd->homunculus.skillpts = 0; +{ //Resets a homunc stats back to zero (but doesn't touches hunger or intimacy) + struct s_homunculus_db *db; + struct s_homunculus *hom; + struct h_stats *base; + hom = &hd->homunculus; + db = hd->homunculusDB; + base = &db->base; + hom->level = 1; + hom->hp = 10; + hom->max_hp = base->HP; + hom->max_sp = base->SP; + hom->str = base->str *10; + hom->agi = base->agi *10; + hom->vit = base->vit *10; + hom->int_= base->int_*10; + hom->dex = base->dex *10; + hom->luk = base->luk *10; + hom->exp = 0; + hd->exp_next = hexptbl[0]; + memset(&hd->homunculus.hskill, 0, sizeof hd->homunculus.hskill); + hd->homunculus.skillpts = 0; } int merc_hom_shuffle(struct homun_data *hd) { - struct map_session_data *sd; - int lv, i, skillpts; - unsigned int exp; - struct s_skill b_skill[MAX_HOMUNSKILL]; - - if (!merc_is_hom_active(hd)) - return 0; - - sd = hd->master; - lv = hd->homunculus.level; - exp = hd->homunculus.exp; - memcpy(&b_skill, &hd->homunculus.hskill, sizeof(b_skill)); - skillpts = hd->homunculus.skillpts; - //Reset values to level 1. - merc_reset_stats(hd); - //Level it back up - for (i = 1; i < lv && hd->exp_next; i++) { - hd->homunculus.exp += hd->exp_next; - merc_hom_levelup(hd); - } - - if (hd->homunculus.class_ == hd->homunculusDB->evo_class) { - //Evolved bonuses - struct s_homunculus *hom = &hd->homunculus; - struct h_stats *max = &hd->homunculusDB->emax, *min = &hd->homunculusDB->emin; - hom->max_hp += rnd_value(min->HP, max->HP); - hom->max_sp += rnd_value(min->SP, max->SP); - hom->str += 10*rnd_value(min->str, max->str); - hom->agi += 10*rnd_value(min->agi, max->agi); - hom->vit += 10*rnd_value(min->vit, max->vit); - hom->int_+= 10*rnd_value(min->int_,max->int_); - hom->dex += 10*rnd_value(min->dex, max->dex); - hom->luk += 10*rnd_value(min->luk, max->luk); - } - - hd->homunculus.exp = exp; - memcpy(&hd->homunculus.hskill, &b_skill, sizeof(b_skill)); - hd->homunculus.skillpts = skillpts; - clif_homskillinfoblock(sd); - status_calc_homunculus(hd,0); - status_percent_heal(&hd->bl, 100, 100); - clif_specialeffect(&hd->bl,568,AREA); - - return 1; + struct map_session_data *sd; + int lv, i, skillpts; + unsigned int exp; + struct s_skill b_skill[MAX_HOMUNSKILL]; + + if (!merc_is_hom_active(hd)) + return 0; + + sd = hd->master; + lv = hd->homunculus.level; + exp = hd->homunculus.exp; + memcpy(&b_skill, &hd->homunculus.hskill, sizeof(b_skill)); + skillpts = hd->homunculus.skillpts; + //Reset values to level 1. + merc_reset_stats(hd); + //Level it back up + for (i = 1; i < lv && hd->exp_next; i++){ + hd->homunculus.exp += hd->exp_next; + merc_hom_levelup(hd); + } + + if(hd->homunculus.class_ == hd->homunculusDB->evo_class) { + //Evolved bonuses + struct s_homunculus *hom = &hd->homunculus; + struct h_stats *max = &hd->homunculusDB->emax, *min = &hd->homunculusDB->emin; + hom->max_hp += rnd_value(min->HP, max->HP); + hom->max_sp += rnd_value(min->SP, max->SP); + hom->str += 10*rnd_value(min->str, max->str); + hom->agi += 10*rnd_value(min->agi, max->agi); + hom->vit += 10*rnd_value(min->vit, max->vit); + hom->int_+= 10*rnd_value(min->int_,max->int_); + hom->dex += 10*rnd_value(min->dex, max->dex); + hom->luk += 10*rnd_value(min->luk, max->luk); + } + + hd->homunculus.exp = exp; + memcpy(&hd->homunculus.hskill, &b_skill, sizeof(b_skill)); + hd->homunculus.skillpts = skillpts; + clif_homskillinfoblock(sd); + status_calc_homunculus(hd,0); + status_percent_heal(&hd->bl, 100, 100); + clif_specialeffect(&hd->bl,568,AREA); + + return 1; } -static bool read_homunculusdb_sub(char *str[], int columns, int current) +static bool read_homunculusdb_sub(char* str[], int columns, int current) { - int classid; - struct s_homunculus_db *db; - - //Base Class,Evo Class - classid = atoi(str[0]); - if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX) { - ShowError("read_homunculusdb : Invalid class %d\n", classid); - return false; - } - db = &homunculus_db[current]; - db->base_class = classid; - classid = atoi(str[1]); - if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX) { - db->base_class = 0; - ShowError("read_homunculusdb : Invalid class %d\n", classid); - return false; - } - db->evo_class = classid; - //Name, Food, Hungry Delay, Base Size, Evo Size, Race, Element, ASPD - strncpy(db->name,str[2],NAME_LENGTH-1); - db->foodID = atoi(str[3]); - db->hungryDelay = atoi(str[4]); - db->base_size = atoi(str[5]); - db->evo_size = atoi(str[6]); - db->race = atoi(str[7]); - db->element = atoi(str[8]); - db->baseASPD = atoi(str[9]); - //base HP, SP, str, agi, vit, int, dex, luk - db->base.HP = atoi(str[10]); - db->base.SP = atoi(str[11]); - db->base.str = atoi(str[12]); - db->base.agi = atoi(str[13]); - db->base.vit = atoi(str[14]); - db->base.int_= atoi(str[15]); - db->base.dex = atoi(str[16]); - db->base.luk = atoi(str[17]); - //Growth Min/Max HP, SP, str, agi, vit, int, dex, luk - db->gmin.HP = atoi(str[18]); - db->gmax.HP = atoi(str[19]); - db->gmin.SP = atoi(str[20]); - db->gmax.SP = atoi(str[21]); - db->gmin.str = atoi(str[22]); - db->gmax.str = atoi(str[23]); - db->gmin.agi = atoi(str[24]); - db->gmax.agi = atoi(str[25]); - db->gmin.vit = atoi(str[26]); - db->gmax.vit = atoi(str[27]); - db->gmin.int_= atoi(str[28]); - db->gmax.int_= atoi(str[29]); - db->gmin.dex = atoi(str[30]); - db->gmax.dex = atoi(str[31]); - db->gmin.luk = atoi(str[32]); - db->gmax.luk = atoi(str[33]); - //Evolution Min/Max HP, SP, str, agi, vit, int, dex, luk - db->emin.HP = atoi(str[34]); - db->emax.HP = atoi(str[35]); - db->emin.SP = atoi(str[36]); - db->emax.SP = atoi(str[37]); - db->emin.str = atoi(str[38]); - db->emax.str = atoi(str[39]); - db->emin.agi = atoi(str[40]); - db->emax.agi = atoi(str[41]); - db->emin.vit = atoi(str[42]); - db->emax.vit = atoi(str[43]); - db->emin.int_= atoi(str[44]); - db->emax.int_= atoi(str[45]); - db->emin.dex = atoi(str[46]); - db->emax.dex = atoi(str[47]); - db->emin.luk = atoi(str[48]); - db->emax.luk = atoi(str[49]); - - //Check that the min/max values really are below the other one. - if (db->gmin.HP > db->gmax.HP) - db->gmin.HP = db->gmax.HP; - if (db->gmin.SP > db->gmax.SP) - db->gmin.SP = db->gmax.SP; - if (db->gmin.str > db->gmax.str) - db->gmin.str = db->gmax.str; - if (db->gmin.agi > db->gmax.agi) - db->gmin.agi = db->gmax.agi; - if (db->gmin.vit > db->gmax.vit) - db->gmin.vit = db->gmax.vit; - if (db->gmin.int_> db->gmax.int_) - db->gmin.int_= db->gmax.int_; - if (db->gmin.dex > db->gmax.dex) - db->gmin.dex = db->gmax.dex; - if (db->gmin.luk > db->gmax.luk) - db->gmin.luk = db->gmax.luk; - - if (db->emin.HP > db->emax.HP) - db->emin.HP = db->emax.HP; - if (db->emin.SP > db->emax.SP) - db->emin.SP = db->emax.SP; - if (db->emin.str > db->emax.str) - db->emin.str = db->emax.str; - if (db->emin.agi > db->emax.agi) - db->emin.agi = db->emax.agi; - if (db->emin.vit > db->emax.vit) - db->emin.vit = db->emax.vit; - if (db->emin.int_> db->emax.int_) - db->emin.int_= db->emax.int_; - if (db->emin.dex > db->emax.dex) - db->emin.dex = db->emax.dex; - if (db->emin.luk > db->emax.luk) - db->emin.luk = db->emax.luk; - - return true; + int classid; + struct s_homunculus_db *db; + + //Base Class,Evo Class + classid = atoi(str[0]); + if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX) + { + ShowError("read_homunculusdb : Invalid class %d\n", classid); + return false; + } + db = &homunculus_db[current]; + db->base_class = classid; + classid = atoi(str[1]); + if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX) + { + db->base_class = 0; + ShowError("read_homunculusdb : Invalid class %d\n", classid); + return false; + } + db->evo_class = classid; + //Name, Food, Hungry Delay, Base Size, Evo Size, Race, Element, ASPD + strncpy(db->name,str[2],NAME_LENGTH-1); + db->foodID = atoi(str[3]); + db->hungryDelay = atoi(str[4]); + db->base_size = atoi(str[5]); + db->evo_size = atoi(str[6]); + db->race = atoi(str[7]); + db->element = atoi(str[8]); + db->baseASPD = atoi(str[9]); + //base HP, SP, str, agi, vit, int, dex, luk + db->base.HP = atoi(str[10]); + db->base.SP = atoi(str[11]); + db->base.str = atoi(str[12]); + db->base.agi = atoi(str[13]); + db->base.vit = atoi(str[14]); + db->base.int_= atoi(str[15]); + db->base.dex = atoi(str[16]); + db->base.luk = atoi(str[17]); + //Growth Min/Max HP, SP, str, agi, vit, int, dex, luk + db->gmin.HP = atoi(str[18]); + db->gmax.HP = atoi(str[19]); + db->gmin.SP = atoi(str[20]); + db->gmax.SP = atoi(str[21]); + db->gmin.str = atoi(str[22]); + db->gmax.str = atoi(str[23]); + db->gmin.agi = atoi(str[24]); + db->gmax.agi = atoi(str[25]); + db->gmin.vit = atoi(str[26]); + db->gmax.vit = atoi(str[27]); + db->gmin.int_= atoi(str[28]); + db->gmax.int_= atoi(str[29]); + db->gmin.dex = atoi(str[30]); + db->gmax.dex = atoi(str[31]); + db->gmin.luk = atoi(str[32]); + db->gmax.luk = atoi(str[33]); + //Evolution Min/Max HP, SP, str, agi, vit, int, dex, luk + db->emin.HP = atoi(str[34]); + db->emax.HP = atoi(str[35]); + db->emin.SP = atoi(str[36]); + db->emax.SP = atoi(str[37]); + db->emin.str = atoi(str[38]); + db->emax.str = atoi(str[39]); + db->emin.agi = atoi(str[40]); + db->emax.agi = atoi(str[41]); + db->emin.vit = atoi(str[42]); + db->emax.vit = atoi(str[43]); + db->emin.int_= atoi(str[44]); + db->emax.int_= atoi(str[45]); + db->emin.dex = atoi(str[46]); + db->emax.dex = atoi(str[47]); + db->emin.luk = atoi(str[48]); + db->emax.luk = atoi(str[49]); + + //Check that the min/max values really are below the other one. + if(db->gmin.HP > db->gmax.HP) + db->gmin.HP = db->gmax.HP; + if(db->gmin.SP > db->gmax.SP) + db->gmin.SP = db->gmax.SP; + if(db->gmin.str > db->gmax.str) + db->gmin.str = db->gmax.str; + if(db->gmin.agi > db->gmax.agi) + db->gmin.agi = db->gmax.agi; + if(db->gmin.vit > db->gmax.vit) + db->gmin.vit = db->gmax.vit; + if(db->gmin.int_> db->gmax.int_) + db->gmin.int_= db->gmax.int_; + if(db->gmin.dex > db->gmax.dex) + db->gmin.dex = db->gmax.dex; + if(db->gmin.luk > db->gmax.luk) + db->gmin.luk = db->gmax.luk; + + if(db->emin.HP > db->emax.HP) + db->emin.HP = db->emax.HP; + if(db->emin.SP > db->emax.SP) + db->emin.SP = db->emax.SP; + if(db->emin.str > db->emax.str) + db->emin.str = db->emax.str; + if(db->emin.agi > db->emax.agi) + db->emin.agi = db->emax.agi; + if(db->emin.vit > db->emax.vit) + db->emin.vit = db->emax.vit; + if(db->emin.int_> db->emax.int_) + db->emin.int_= db->emax.int_; + if(db->emin.dex > db->emax.dex) + db->emin.dex = db->emax.dex; + if(db->emin.luk > db->emax.luk) + db->emin.luk = db->emax.luk; + + return true; } int read_homunculusdb(void) { - int i; - const char *filename[]= {"homunculus_db.txt","homunculus_db2.txt"}; + int i; + const char *filename[]={"homunculus_db.txt","homunculus_db2.txt"}; - memset(homunculus_db,0,sizeof(homunculus_db)); - for (i = 0; i<ARRAYLENGTH(filename); i++) { - char path[256]; + memset(homunculus_db,0,sizeof(homunculus_db)); + for(i = 0; i<ARRAYLENGTH(filename); i++) + { + char path[256]; - if (i > 0) { - sprintf(path, "%s/%s", db_path, filename[i]); + if( i > 0 ) + { + sprintf(path, "%s/%s", db_path, filename[i]); - if (!exists(path)) { - continue; - } - } + if( !exists(path) ) + { + continue; + } + } - sv_readdb(db_path, filename[i], ',', 50, 50, MAX_HOMUNCULUS_CLASS, &read_homunculusdb_sub); - } + sv_readdb(db_path, filename[i], ',', 50, 50, MAX_HOMUNCULUS_CLASS, &read_homunculusdb_sub); + } - return 0; + return 0; } -static bool read_homunculus_skilldb_sub(char *split[], int columns, int current) -{ - // <hom class>,<skill id>,<max level>[,<job level>],<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>,<intimacy lv req> - int k, classid; - int j; - int minJobLevelPresent = 0; - - if (columns == 14) - minJobLevelPresent = 1; // MinJobLvl has been added - - // check for bounds [celest] - classid = atoi(split[0]) - HM_CLASS_BASE; - if (classid >= MAX_HOMUNCULUS_CLASS) { - ShowWarning("read_homunculus_skilldb: Invalud homunculus class %d.\n", atoi(split[0])); - return false; - } - - k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex] - // Search an empty line or a line with the same skill_id (stored in j) - ARR_FIND(0, MAX_SKILL_TREE, j, !hskill_tree[classid][j].id || hskill_tree[classid][j].id == k); - if (j == MAX_SKILL_TREE) { - ShowWarning("Unable to load skill %d into homunculus %d's tree. Maximum number of skills per class has been reached.\n", k, classid); - return false; - } - - hskill_tree[classid][j].id = k; - hskill_tree[classid][j].max = atoi(split[2]); - if (minJobLevelPresent) - hskill_tree[classid][j].joblv = atoi(split[3]); - - for (k = 0; k < MAX_PC_SKILL_REQUIRE; k++) { - hskill_tree[classid][j].need[k].id = atoi(split[3+k*2+minJobLevelPresent]); - hskill_tree[classid][j].need[k].lv = atoi(split[3+k*2+minJobLevelPresent+1]); - } - - hskill_tree[classid][j].intimacylv = atoi(split[13+minJobLevelPresent]); - - return true; +static bool read_homunculus_skilldb_sub(char* split[], int columns, int current) +{// <hom class>,<skill id>,<max level>[,<job level>],<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>,<intimacy lv req> + int k, classid; + int j; + int minJobLevelPresent = 0; + + if( columns == 14 ) + minJobLevelPresent = 1; // MinJobLvl has been added + + // check for bounds [celest] + classid = atoi(split[0]) - HM_CLASS_BASE; + if ( classid >= MAX_HOMUNCULUS_CLASS ) + { + ShowWarning("read_homunculus_skilldb: Invalud homunculus class %d.\n", atoi(split[0])); + return false; + } + + k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex] + // Search an empty line or a line with the same skill_id (stored in j) + ARR_FIND( 0, MAX_SKILL_TREE, j, !hskill_tree[classid][j].id || hskill_tree[classid][j].id == k ); + if (j == MAX_SKILL_TREE) + { + ShowWarning("Unable to load skill %d into homunculus %d's tree. Maximum number of skills per class has been reached.\n", k, classid); + return false; + } + + hskill_tree[classid][j].id = k; + hskill_tree[classid][j].max = atoi(split[2]); + if (minJobLevelPresent) + hskill_tree[classid][j].joblv = atoi(split[3]); + + for( k = 0; k < MAX_PC_SKILL_REQUIRE; k++ ) + { + hskill_tree[classid][j].need[k].id = atoi(split[3+k*2+minJobLevelPresent]); + hskill_tree[classid][j].need[k].lv = atoi(split[3+k*2+minJobLevelPresent+1]); + } + + hskill_tree[classid][j].intimacylv = atoi(split[13+minJobLevelPresent]); + + return true; } int read_homunculus_skilldb(void) { - memset(hskill_tree,0,sizeof(hskill_tree)); - sv_readdb(db_path, "homun_skill_tree.txt", ',', 13, 15, -1, &read_homunculus_skilldb_sub); + memset(hskill_tree,0,sizeof(hskill_tree)); + sv_readdb(db_path, "homun_skill_tree.txt", ',', 13, 15, -1, &read_homunculus_skilldb_sub); - return 0; + return 0; } void read_homunculus_expdb(void) { - FILE *fp; - char line[1024]; - int i, j=0; - char *filename[]= { - DBPATH"exp_homun.txt", - "exp_homun2.txt" - }; - - memset(hexptbl,0,sizeof(hexptbl)); - for (i=0; i<2; i++) { - sprintf(line, "%s/%s", db_path, filename[i]); - fp=fopen(line,"r"); - if (fp == NULL) { - if (i != 0) - continue; - ShowError("can't read %s\n",line); - return; - } - while (fgets(line, sizeof(line), fp) && j < MAX_LEVEL) { - if (line[0] == '/' && line[1] == '/') - continue; - - hexptbl[j] = strtoul(line, NULL, 10); - if (!hexptbl[j++]) - break; - } - if (hexptbl[MAX_LEVEL - 1]) { // Last permitted level have to be 0! - ShowWarning("read_hexptbl: Reached max level in exp_homun [%d]. Remaining lines were not read.\n ", MAX_LEVEL); - hexptbl[MAX_LEVEL - 1] = 0; - } - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' levels in '"CL_WHITE"%s"CL_RESET"'.\n", j, filename[i]); - } + FILE *fp; + char line[1024]; + int i, j=0; + char *filename[]={ + DBPATH"exp_homun.txt", + "exp_homun2.txt"}; + + memset(hexptbl,0,sizeof(hexptbl)); + for(i=0; i<2; i++){ + sprintf(line, "%s/%s", db_path, filename[i]); + fp=fopen(line,"r"); + if(fp == NULL){ + if(i != 0) + continue; + ShowError("can't read %s\n",line); + return; + } + while(fgets(line, sizeof(line), fp) && j < MAX_LEVEL) + { + if(line[0] == '/' && line[1] == '/') + continue; + + hexptbl[j] = strtoul(line, NULL, 10); + if (!hexptbl[j++]) + break; + } + if (hexptbl[MAX_LEVEL - 1]) // Last permitted level have to be 0! + { + ShowWarning("read_hexptbl: Reached max level in exp_homun [%d]. Remaining lines were not read.\n ", MAX_LEVEL); + hexptbl[MAX_LEVEL - 1] = 0; + } + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' levels in '"CL_WHITE"%s"CL_RESET"'.\n", j, filename[i]); + } } void merc_reload(void) { - read_homunculusdb(); - read_homunculus_expdb(); + read_homunculusdb(); + read_homunculus_expdb(); } void merc_skill_reload(void) { - read_homunculus_skilldb(); + read_homunculus_skilldb(); } int do_init_merc(void) { - int class_; - read_homunculusdb(); - read_homunculus_expdb(); - read_homunculus_skilldb(); - // Add homunc timer function to timer func list [Toms] - add_timer_func_list(merc_hom_hungry, "merc_hom_hungry"); - - //Stock view data for homuncs - memset(&hom_viewdb, 0, sizeof(hom_viewdb)); - for (class_ = 0; class_ < ARRAYLENGTH(hom_viewdb); class_++) - hom_viewdb[class_].class_ = HM_CLASS_BASE+class_; - return 0; + int class_; + read_homunculusdb(); + read_homunculus_expdb(); + read_homunculus_skilldb(); + // Add homunc timer function to timer func list [Toms] + add_timer_func_list(merc_hom_hungry, "merc_hom_hungry"); + + //Stock view data for homuncs + memset(&hom_viewdb, 0, sizeof(hom_viewdb)); + for (class_ = 0; class_ < ARRAYLENGTH(hom_viewdb); class_++) + hom_viewdb[class_].class_ = HM_CLASS_BASE+class_; + return 0; } int do_final_merc(void); diff --git a/src/map/homunculus.h b/src/map/homunculus.h index d9fbfa9cc..e46420692 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -8,57 +8,57 @@ #include "unit.h" // struct unit_data struct h_stats { - unsigned int HP, SP; - unsigned short str, agi, vit, int_, dex, luk; + unsigned int HP, SP; + unsigned short str, agi, vit, int_, dex, luk; }; struct s_homunculus_db { - int base_class, evo_class; - char name[NAME_LENGTH]; - struct h_stats base, gmin, gmax, emin, emax; - int foodID ; - int baseASPD ; - long hungryDelay ; - unsigned char element, race, base_size, evo_size; + int base_class, evo_class; + char name[NAME_LENGTH]; + struct h_stats base, gmin, gmax, emin, emax; + int foodID ; + int baseASPD ; + long hungryDelay ; + unsigned char element, race, base_size, evo_size; }; extern struct s_homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; enum { HOMUNCULUS_CLASS, HOMUNCULUS_FOOD }; enum { - SP_ACK = 0x0, - SP_INTIMATE = 0x1, - SP_HUNGRY = 0x2, + SP_ACK = 0x0, + SP_INTIMATE = 0x1, + SP_HUNGRY = 0x2, }; struct homun_data { - struct block_list bl; - struct unit_data ud; - struct view_data *vd; - struct status_data base_status, battle_status; - struct status_change sc; - struct regen_data regen; - struct s_homunculus_db *homunculusDB; //[orn] - struct s_homunculus homunculus; //[orn] - - struct map_session_data *master; //pointer back to its master - int hungry_timer; //[orn] - unsigned int exp_next; - char blockskill[MAX_SKILL]; // [orn] - + struct block_list bl; + struct unit_data ud; + struct view_data *vd; + struct status_data base_status, battle_status; + struct status_change sc; + struct regen_data regen; + struct s_homunculus_db *homunculusDB; //[orn] + struct s_homunculus homunculus; //[orn] + + struct map_session_data *master; //pointer back to its master + int hungry_timer; //[orn] + unsigned int exp_next; + char blockskill[MAX_SKILL]; // [orn] + int spiritball; //for homun S [lighta] }; #define MAX_HOM_SKILL_REQUIRE 5 struct homun_skill_tree_entry { - short id; - unsigned char max; - unsigned char joblv; - short intimacylv; - struct { - short id; - unsigned char lv; - } need[MAX_HOM_SKILL_REQUIRE]; + short id; + unsigned char max; + unsigned char joblv; + short intimacylv; + struct { + short id; + unsigned char lv; + } need[MAX_HOM_SKILL_REQUIRE]; }; // Celest #define HOM_EVO 0x100 //256 @@ -67,22 +67,22 @@ struct homun_skill_tree_entry { #define HOM_REG 0x1000 //4096 enum { - // Normal Homunculus - MAPID_LIF = HOM_REG|0x0, - MAPID_AMISTR, - MAPID_FILIR, - MAPID_VANILMIRTH, - // Evolved Homunulus - MAPID_LIF_E = HOM_REG|HOM_EVO|0x0, - MAPID_AMISTR_E, - MAPID_FILIR_E, - MAPID_VANILMIRTH_E, - // Homunculus S - MAPID_EIRA = HOM_S|0x0, - MAPID_BAYERI, - MAPID_SERA, - MAPID_DIETER, - MAPID_ELANOR, +// Normal Homunculus + MAPID_LIF = HOM_REG|0x0, + MAPID_AMISTR, + MAPID_FILIR, + MAPID_VANILMIRTH, +// Evolved Homunulus + MAPID_LIF_E = HOM_REG|HOM_EVO|0x0, + MAPID_AMISTR_E, + MAPID_FILIR_E, + MAPID_VANILMIRTH_E, +// Homunculus S + MAPID_EIRA = HOM_S|0x0, + MAPID_BAYERI, + MAPID_SERA, + MAPID_DIETER, + MAPID_ELANOR, }; #define homdb_checkid(id) (id >= HM_CLASS_BASE && id <= HM_CLASS_MAX) @@ -91,7 +91,7 @@ enum { #define merc_is_hom_active(x) (x && x->homunculus.vaporize != 1 && x->battle_status.hp > 0) int do_init_merc(void); int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag); //albator -struct view_data *merc_get_hom_viewdata(int class_); +struct view_data* merc_get_hom_viewdata(int class_); int hom_class2mapid(int hom_class); void merc_damage(struct homun_data *hd); int merc_hom_dead(struct homun_data *hd); @@ -116,13 +116,13 @@ int merc_menu(struct map_session_data *sd,int menunum); int merc_hom_food(struct map_session_data *sd, struct homun_data *hd); int merc_hom_hungry_timer_delete(struct homun_data *hd); int merc_hom_change_name(struct map_session_data *sd,char *name); -int merc_hom_change_name_ack(struct map_session_data *sd, char *name, int flag); +int merc_hom_change_name_ack(struct map_session_data *sd, char* name, int flag); #define merc_stop_walking(hd, type) unit_stop_walking(&(hd)->bl, type) #define merc_stop_attack(hd) unit_stop_attack(&(hd)->bl) -int merc_hom_increase_intimacy(struct homun_data *hd, unsigned int value); -int merc_hom_decrease_intimacy(struct homun_data *hd, unsigned int value); +int merc_hom_increase_intimacy(struct homun_data * hd, unsigned int value); +int merc_hom_decrease_intimacy(struct homun_data * hd, unsigned int value); int merc_skill_tree_get_max(int id, int b_class); -void merc_hom_init_timers(struct homun_data *hd); +void merc_hom_init_timers(struct homun_data * hd); void merc_skill_reload(void); void merc_reload(void); diff --git a/src/map/instance.c b/src/map/instance.c index 10d4a8d6a..f5ae125a6 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -31,17 +31,17 @@ struct s_instance instance[MAX_INSTANCE]; /// Checks whether given instance id is valid or not. static bool instance_is_valid(int instance_id) { - if (instance_id < 1 || instance_id >= ARRAYLENGTH(instance)) { - // out of range - return false; - } + if( instance_id < 1 || instance_id >= ARRAYLENGTH(instance) ) + {// out of range + return false; + } - if (instance[instance_id].state == INSTANCE_FREE) { - // uninitialized/freed instance slot - return false; - } + if( instance[instance_id].state == INSTANCE_FREE ) + {// uninitialized/freed instance slot + return false; + } - return true; + return true; } @@ -53,42 +53,44 @@ static bool instance_is_valid(int instance_id) *--------------------------------------*/ int instance_create(int party_id, const char *name) { - int i; - struct party_data *p; - - if ((p = party_search(party_id)) == NULL) { - ShowError("instance_create: party %d not found for instance '%s'.\n", party_id, name); - return -2; - } - - if (p->instance_id) - return -4; // Party already instancing - - // Searching a Free Instance - // 0 is ignored as this mean "no instance" on maps - ARR_FIND(1, MAX_INSTANCE, i, instance[i].state == INSTANCE_FREE); - if (i == MAX_INSTANCE) { - ShowError("instance_create: no free instances, consider increasing MAX_INSTANCE.\n"); - return -3; - } - - instance[i].state = INSTANCE_IDLE; - instance[i].instance_id = i; - instance[i].idle_timer = INVALID_TIMER; - instance[i].idle_timeout = instance[i].idle_timeoutval = 0; - instance[i].progress_timer = INVALID_TIMER; - instance[i].progress_timeout = 0; - instance[i].users = 0; - instance[i].party_id = party_id; - instance[i].vars = idb_alloc(DB_OPT_RELEASE_DATA); - - safestrncpy(instance[i].name, name, sizeof(instance[i].name)); - memset(instance[i].map, 0x00, sizeof(instance[i].map)); - p->instance_id = i; - - clif_instance(i, 1, 0); // Start instancing window - ShowInfo("[Instance] Created: %s.\n", name); - return i; + int i; + struct party_data* p; + + if( ( p = party_search(party_id) ) == NULL ) + { + ShowError("instance_create: party %d not found for instance '%s'.\n", party_id, name); + return -2; + } + + if( p->instance_id ) + return -4; // Party already instancing + + // Searching a Free Instance + // 0 is ignored as this mean "no instance" on maps + ARR_FIND(1, MAX_INSTANCE, i, instance[i].state == INSTANCE_FREE); + if( i == MAX_INSTANCE ) + { + ShowError("instance_create: no free instances, consider increasing MAX_INSTANCE.\n"); + return -3; + } + + instance[i].state = INSTANCE_IDLE; + instance[i].instance_id = i; + instance[i].idle_timer = INVALID_TIMER; + instance[i].idle_timeout = instance[i].idle_timeoutval = 0; + instance[i].progress_timer = INVALID_TIMER; + instance[i].progress_timeout = 0; + instance[i].users = 0; + instance[i].party_id = party_id; + instance[i].vars = idb_alloc(DB_OPT_RELEASE_DATA); + + safestrncpy( instance[i].name, name, sizeof(instance[i].name) ); + memset( instance[i].map, 0x00, sizeof(instance[i].map) ); + p->instance_id = i; + + clif_instance(i, 1, 0); // Start instancing window + ShowInfo("[Instance] Created: %s.\n", name); + return i; } /*-------------------------------------- @@ -96,68 +98,72 @@ int instance_create(int party_id, const char *name) *--------------------------------------*/ int instance_add_map(const char *name, int instance_id, bool usebasename) { - int m = map_mapname2mapid(name), i, im = -1; - size_t num_cell, size; - - if (m < 0) - return -1; // source map not found - - if (!instance_is_valid(instance_id)) { - ShowError("instance_add_map: trying to attach '%s' map to non-existing instance %d.\n", name, instance_id); - return -1; - } - if (instance[instance_id].num_map >= MAX_MAP_PER_INSTANCE) { - ShowError("instance_add_map: trying to add '%s' map to instance %d (%s) failed. Please increase MAX_MAP_PER_INSTANCE.\n", name, instance_id, instance[instance_id].name); - return -2; - } - if (map[m].instance_id != 0) { - // Source map already belong to a Instance. - ShowError("instance_add_map: trying to instance already instanced map %s.\n", name); - return -4; - } - - ARR_FIND(instance_start, map_num, i, !map[i].name[0]); // Searching for a Free Map - if (i < map_num) im = i; // Unused map found (old instance) - else if (map_num - 1 >= MAX_MAP_PER_SERVER) { - // No more free maps - ShowError("instance_add_map: no more free space to create maps on this server.\n"); - return -5; - } else im = map_num++; // Using next map index - - memcpy(&map[im], &map[m], sizeof(struct map_data)); // Copy source map - snprintf(map[im].name, MAP_NAME_LENGTH, (usebasename ? "%.3d#%s" : "%.3d%s"), instance_id, name); // Generate Name for Instance Map - map[im].index = mapindex_addmap(-1, map[im].name); // Add map index - - if (!map[im].index) { - map[im].name[0] = '\0'; - ShowError("instance_add_map: no more free map indexes.\n"); - return -3; // No free map index - } - - // Reallocate cells - num_cell = map[im].xs * map[im].ys; - CREATE(map[im].cell, struct mapcell, num_cell); - memcpy(map[im].cell, map[m].cell, num_cell * sizeof(struct mapcell)); - - size = map[im].bxs * map[im].bys * sizeof(struct block_list *); - map[im].block = (struct block_list **)aCalloc(size, 1); - map[im].block_mob = (struct block_list **)aCalloc(size, 1); - - memset(map[im].npc, 0x00, sizeof(map[i].npc)); - map[im].npc_num = 0; - - memset(map[im].moblist, 0x00, sizeof(map[im].moblist)); - map[im].mob_delete_timer = INVALID_TIMER; - - map[im].m = im; - map[im].instance_id = instance_id; - map[im].instance_src_map = m; - map[m].flag.src4instance = 1; // Flag this map as a src map for instances - - instance[instance_id].map[instance[instance_id].num_map++] = im; // Attach to actual instance - map_addmap2db(&map[im]); - - return im; + int m = map_mapname2mapid(name), i, im = -1; + size_t num_cell, size; + + if( m < 0 ) + return -1; // source map not found + + if( !instance_is_valid(instance_id) ) + { + ShowError("instance_add_map: trying to attach '%s' map to non-existing instance %d.\n", name, instance_id); + return -1; + } + if( instance[instance_id].num_map >= MAX_MAP_PER_INSTANCE ) + { + ShowError("instance_add_map: trying to add '%s' map to instance %d (%s) failed. Please increase MAX_MAP_PER_INSTANCE.\n", name, instance_id, instance[instance_id].name); + return -2; + } + if( map[m].instance_id != 0 ) + { // Source map already belong to a Instance. + ShowError("instance_add_map: trying to instance already instanced map %s.\n", name); + return -4; + } + + ARR_FIND( instance_start, map_num, i, !map[i].name[0] ); // Searching for a Free Map + if( i < map_num ) im = i; // Unused map found (old instance) + else if( map_num - 1 >= MAX_MAP_PER_SERVER ) + { // No more free maps + ShowError("instance_add_map: no more free space to create maps on this server.\n"); + return -5; + } + else im = map_num++; // Using next map index + + memcpy( &map[im], &map[m], sizeof(struct map_data) ); // Copy source map + snprintf(map[im].name, MAP_NAME_LENGTH, (usebasename ? "%.3d#%s" : "%.3d%s"), instance_id, name); // Generate Name for Instance Map + map[im].index = mapindex_addmap(-1, map[im].name); // Add map index + + if( !map[im].index ) + { + map[im].name[0] = '\0'; + ShowError("instance_add_map: no more free map indexes.\n"); + return -3; // No free map index + } + + // Reallocate cells + num_cell = map[im].xs * map[im].ys; + CREATE( map[im].cell, struct mapcell, num_cell ); + memcpy( map[im].cell, map[m].cell, num_cell * sizeof(struct mapcell) ); + + size = map[im].bxs * map[im].bys * sizeof(struct block_list*); + map[im].block = (struct block_list**)aCalloc(size, 1); + map[im].block_mob = (struct block_list**)aCalloc(size, 1); + + memset(map[im].npc, 0x00, sizeof(map[i].npc)); + map[im].npc_num = 0; + + memset(map[im].moblist, 0x00, sizeof(map[im].moblist)); + map[im].mob_delete_timer = INVALID_TIMER; + + map[im].m = im; + map[im].instance_id = instance_id; + map[im].instance_src_map = m; + map[m].flag.src4instance = 1; // Flag this map as a src map for instances + + instance[instance_id].map[instance[instance_id].num_map++] = im; // Attach to actual instance + map_addmap2db(&map[im]); + + return im; } /*-------------------------------------- @@ -167,17 +173,19 @@ int instance_add_map(const char *name, int instance_id, bool usebasename) *--------------------------------------*/ int instance_map2imap(int m, int instance_id) { - int i; - - if (!instance_is_valid(instance_id)) { - return -1; - } - - for (i = 0; i < instance[instance_id].num_map; i++) { - if (instance[instance_id].map[i] && map[instance[instance_id].map[i]].instance_src_map == m) - return instance[instance_id].map[i]; - } - return -1; + int i; + + if( !instance_is_valid(instance_id) ) + { + return -1; + } + + for( i = 0; i < instance[instance_id].num_map; i++ ) + { + if( instance[instance_id].map[i] && map[instance[instance_id].map[i]].instance_src_map == m ) + return instance[instance_id].map[i]; + } + return -1; } /*-------------------------------------- @@ -187,31 +195,31 @@ int instance_map2imap(int m, int instance_id) *--------------------------------------*/ int instance_mapid2imapid(int m, int instance_id) { - if (map[m].flag.src4instance == 0) - return m; // not instances found for this map - else if (map[m].instance_id) { - // This map is a instance, not a src map instance - ShowError("map_instance_mapid2imapid: already instanced (%d / %d)\n", m, instance_id); - return -1; - } - - if (!instance_is_valid(instance_id)) - return -1; - - return instance_map2imap(m, instance_id); + if( map[m].flag.src4instance == 0 ) + return m; // not instances found for this map + else if( map[m].instance_id ) + { // This map is a instance, not a src map instance + ShowError("map_instance_mapid2imapid: already instanced (%d / %d)\n", m, instance_id); + return -1; + } + + if( !instance_is_valid(instance_id) ) + return -1; + + return instance_map2imap(m, instance_id); } /*-------------------------------------- * map_instance_map_npcsub * Used on Init instance. Duplicates each script on source map *--------------------------------------*/ -int instance_map_npcsub(struct block_list *bl, va_list args) +int instance_map_npcsub(struct block_list* bl, va_list args) { - struct npc_data *nd = (struct npc_data *)bl; - int m = va_arg(args, int); // Destination Map + struct npc_data* nd = (struct npc_data*)bl; + int m = va_arg(args, int); // Destination Map - npc_duplicate4instance(nd, m); - return 1; + npc_duplicate4instance(nd, m); + return 1; } /*-------------------------------------- @@ -219,59 +227,58 @@ int instance_map_npcsub(struct block_list *bl, va_list args) *--------------------------------------*/ void instance_init(int instance_id) { - int i; + int i; - if (!instance_is_valid(instance_id)) - return; // nothing to do + if( !instance_is_valid(instance_id) ) + return; // nothing to do - for (i = 0; i < instance[instance_id].num_map; i++) - map_foreachinmap(instance_map_npcsub, map[instance[instance_id].map[i]].instance_src_map, BL_NPC, instance[instance_id].map[i]); + for( i = 0; i < instance[instance_id].num_map; i++ ) + map_foreachinmap(instance_map_npcsub, map[instance[instance_id].map[i]].instance_src_map, BL_NPC, instance[instance_id].map[i]); - instance[instance_id].state = INSTANCE_BUSY; - ShowInfo("[Instance] Initialized %s.\n", instance[instance_id].name); + instance[instance_id].state = INSTANCE_BUSY; + ShowInfo("[Instance] Initialized %s.\n", instance[instance_id].name); } /*-------------------------------------- * Used on instance deleting process. * Warps all players on each instance map to its save points. *--------------------------------------*/ -int instance_del_load(struct map_session_data *sd, va_list args) +int instance_del_load(struct map_session_data* sd, va_list args) { - int m = va_arg(args,int); - if (!sd || sd->bl.m != m) - return 0; + int m = va_arg(args,int); + if( !sd || sd->bl.m != m ) + return 0; - pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_OUTSIGHT); - return 1; + pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_OUTSIGHT); + return 1; } /* for npcs behave differently when being unloaded within a instance */ -int instance_cleanup_sub(struct block_list *bl, va_list ap) -{ - nullpo_ret(bl); - - switch (bl->type) { - case BL_PC: - map_quit((struct map_session_data *) bl); - break; - case BL_NPC: - npc_unload((struct npc_data *)bl,true); - break; - case BL_MOB: - unit_free(bl,CLR_OUTSIGHT); - break; - case BL_PET: - //There is no need for this, the pet is removed together with the player. [Skotlex] - break; - case BL_ITEM: - map_clearflooritem(bl); - break; - case BL_SKILL: - skill_delunit((struct skill_unit *) bl); - break; - } - - return 1; +int instance_cleanup_sub(struct block_list *bl, va_list ap) { + nullpo_ret(bl); + + switch(bl->type) { + case BL_PC: + map_quit((struct map_session_data *) bl); + break; + case BL_NPC: + npc_unload((struct npc_data *)bl,true); + break; + case BL_MOB: + unit_free(bl,CLR_OUTSIGHT); + break; + case BL_PET: + //There is no need for this, the pet is removed together with the player. [Skotlex] + break; + case BL_ITEM: + map_clearflooritem(bl); + break; + case BL_SKILL: + skill_delunit((struct skill_unit *) bl); + break; + } + + return 1; } /*-------------------------------------- @@ -279,43 +286,46 @@ int instance_cleanup_sub(struct block_list *bl, va_list ap) *--------------------------------------*/ void instance_del_map(int m) { - int i; - if (m <= 0 || !map[m].instance_id) { - ShowError("Tried to remove non-existing instance map (%d)\n", m); - return; - } - - map_foreachpc(instance_del_load, m); - map_foreachinmap(instance_cleanup_sub, m, BL_ALL); - - if (map[m].mob_delete_timer != INVALID_TIMER) - delete_timer(map[m].mob_delete_timer, map_removemobs_timer); - - mapindex_removemap(map[m].index); - - // Free memory - aFree(map[m].cell); - aFree(map[m].block); - aFree(map[m].block_mob); - - // Remove from instance - for (i = 0; i < instance[map[m].instance_id].num_map; i++) { - if (instance[map[m].instance_id].map[i] == m) { - instance[map[m].instance_id].num_map--; - for (; i < instance[map[m].instance_id].num_map; i++) - instance[map[m].instance_id].map[i] = instance[map[m].instance_id].map[i+1]; - i = -1; - break; - } - } - if (i == instance[map[m].instance_id].num_map) - ShowError("map_instance_del: failed to remove %s from instance list (%s): %d\n", map[m].name, instance[map[m].instance_id].name, m); - - map_removemapdb(&map[m]); - memset(&map[m], 0x00, sizeof(map[0])); - - /* for it is default and makes it not try to delete a non-existent timer since we did not delete this entry. */ - map[m].mob_delete_timer = INVALID_TIMER; + int i; + if( m <= 0 || !map[m].instance_id ) + { + ShowError("Tried to remove non-existing instance map (%d)\n", m); + return; + } + + map_foreachpc(instance_del_load, m); + map_foreachinmap(instance_cleanup_sub, m, BL_ALL); + + if( map[m].mob_delete_timer != INVALID_TIMER ) + delete_timer(map[m].mob_delete_timer, map_removemobs_timer); + + mapindex_removemap( map[m].index ); + + // Free memory + aFree(map[m].cell); + aFree(map[m].block); + aFree(map[m].block_mob); + + // Remove from instance + for( i = 0; i < instance[map[m].instance_id].num_map; i++ ) + { + if( instance[map[m].instance_id].map[i] == m ) + { + instance[map[m].instance_id].num_map--; + for( ; i < instance[map[m].instance_id].num_map; i++ ) + instance[map[m].instance_id].map[i] = instance[map[m].instance_id].map[i+1]; + i = -1; + break; + } + } + if( i == instance[map[m].instance_id].num_map ) + ShowError("map_instance_del: failed to remove %s from instance list (%s): %d\n", map[m].name, instance[map[m].instance_id].name, m); + + map_removemapdb(&map[m]); + memset(&map[m], 0x00, sizeof(map[0])); + + /* for it is default and makes it not try to delete a non-existent timer since we did not delete this entry. */ + map[m].mob_delete_timer = INVALID_TIMER; } /*-------------------------------------- @@ -323,8 +333,8 @@ void instance_del_map(int m) *--------------------------------------*/ int instance_destroy_timer(int tid, unsigned int tick, int id, intptr_t data) { - instance_destroy(id); - return 0; + instance_destroy(id); + return 0; } /*-------------------------------------- @@ -332,45 +342,45 @@ int instance_destroy_timer(int tid, unsigned int tick, int id, intptr_t data) *--------------------------------------*/ void instance_destroy(int instance_id) { - int last = 0, type; - struct party_data *p; - time_t now = time(NULL); + int last = 0, type; + struct party_data *p; + time_t now = time(NULL); - if (!instance_is_valid(instance_id)) - return; // nothing to do + if( !instance_is_valid(instance_id) ) + return; // nothing to do - if (instance[instance_id].progress_timeout && instance[instance_id].progress_timeout <= now) - type = 1; - else if (instance[instance_id].idle_timeout && instance[instance_id].idle_timeout <= now) - type = 2; - else - type = 3; + if( instance[instance_id].progress_timeout && instance[instance_id].progress_timeout <= now ) + type = 1; + else if( instance[instance_id].idle_timeout && instance[instance_id].idle_timeout <= now ) + type = 2; + else + type = 3; - clif_instance(instance_id, 5, type); // Report users this instance has been destroyed + clif_instance(instance_id, 5, type); // Report users this instance has been destroyed - while (instance[instance_id].num_map && last != instance[instance_id].map[0]) { - // Remove all maps from instance - last = instance[instance_id].map[0]; - instance_del_map(instance[instance_id].map[0]); - } + while( instance[instance_id].num_map && last != instance[instance_id].map[0] ) + { // Remove all maps from instance + last = instance[instance_id].map[0]; + instance_del_map( instance[instance_id].map[0] ); + } - if (instance[instance_id].vars) - db_destroy(instance[instance_id].vars); + if( instance[instance_id].vars ) + db_destroy(instance[instance_id].vars); - if (instance[instance_id].progress_timer != INVALID_TIMER) - delete_timer(instance[instance_id].progress_timer, instance_destroy_timer); - if (instance[instance_id].idle_timer != INVALID_TIMER) - delete_timer(instance[instance_id].idle_timer, instance_destroy_timer); + if( instance[instance_id].progress_timer != INVALID_TIMER ) + delete_timer( instance[instance_id].progress_timer, instance_destroy_timer); + if( instance[instance_id].idle_timer != INVALID_TIMER ) + delete_timer( instance[instance_id].idle_timer, instance_destroy_timer); - instance[instance_id].vars = NULL; + instance[instance_id].vars = NULL; - if (instance[instance_id].party_id && (p = party_search(instance[instance_id].party_id)) != NULL) - p->instance_id = 0; // Update Party information + if( instance[instance_id].party_id && (p = party_search(instance[instance_id].party_id)) != NULL ) + p->instance_id = 0; // Update Party information - ShowInfo("[Instance] Destroyed %s.\n", instance[instance_id].name); - memset(&instance[instance_id], 0x00, sizeof(instance[0])); + ShowInfo("[Instance] Destroyed %s.\n", instance[instance_id].name); + memset( &instance[instance_id], 0x00, sizeof(instance[0]) ); - instance[instance_id].state = INSTANCE_FREE; + instance[instance_id].state = INSTANCE_FREE; } /*-------------------------------------- @@ -378,25 +388,28 @@ void instance_destroy(int instance_id) *--------------------------------------*/ void instance_check_idle(int instance_id) { - bool idle = true; - time_t now = time(NULL); - - if (!instance_is_valid(instance_id) || instance[instance_id].idle_timeoutval == 0) - return; - - if (instance[instance_id].users) - idle = false; - - if (instance[instance_id].idle_timer != INVALID_TIMER && !idle) { - delete_timer(instance[instance_id].idle_timer, instance_destroy_timer); - instance[instance_id].idle_timer = INVALID_TIMER; - instance[instance_id].idle_timeout = 0; - clif_instance(instance_id, 3, 0); // Notify instance users normal instance expiration - } else if (instance[instance_id].idle_timer == INVALID_TIMER && idle) { - instance[instance_id].idle_timeout = now + instance[instance_id].idle_timeoutval; - instance[instance_id].idle_timer = add_timer(gettick() + (unsigned int)instance[instance_id].idle_timeoutval * 1000, instance_destroy_timer, instance_id, 0); - clif_instance(instance_id, 4, 0); // Notify instance users it will be destroyed of no user join it again in "X" time - } + bool idle = true; + time_t now = time(NULL); + + if( !instance_is_valid(instance_id) || instance[instance_id].idle_timeoutval == 0 ) + return; + + if( instance[instance_id].users ) + idle = false; + + if( instance[instance_id].idle_timer != INVALID_TIMER && !idle ) + { + delete_timer(instance[instance_id].idle_timer, instance_destroy_timer); + instance[instance_id].idle_timer = INVALID_TIMER; + instance[instance_id].idle_timeout = 0; + clif_instance(instance_id, 3, 0); // Notify instance users normal instance expiration + } + else if( instance[instance_id].idle_timer == INVALID_TIMER && idle ) + { + instance[instance_id].idle_timeout = now + instance[instance_id].idle_timeoutval; + instance[instance_id].idle_timer = add_timer( gettick() + (unsigned int)instance[instance_id].idle_timeoutval * 1000, instance_destroy_timer, instance_id, 0); + clif_instance(instance_id, 4, 0); // Notify instance users it will be destroyed of no user join it again in "X" time + } } /*-------------------------------------- @@ -404,36 +417,42 @@ void instance_check_idle(int instance_id) *--------------------------------------*/ void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsigned int idle_timeout) { - time_t now = time(0); - - if (!instance_is_valid(instance_id)) - return; - - if (instance[instance_id].progress_timer != INVALID_TIMER) - delete_timer(instance[instance_id].progress_timer, instance_destroy_timer); - if (instance[instance_id].idle_timer != INVALID_TIMER) - delete_timer(instance[instance_id].idle_timer, instance_destroy_timer); - - if (progress_timeout) { - instance[instance_id].progress_timeout = now + progress_timeout; - instance[instance_id].progress_timer = add_timer(gettick() + progress_timeout * 1000, instance_destroy_timer, instance_id, 0); - } else { - instance[instance_id].progress_timeout = 0; - instance[instance_id].progress_timer = INVALID_TIMER; - } - - if (idle_timeout) { - instance[instance_id].idle_timeoutval = idle_timeout; - instance[instance_id].idle_timer = INVALID_TIMER; - instance_check_idle(instance_id); - } else { - instance[instance_id].idle_timeoutval = 0; - instance[instance_id].idle_timeout = 0; - instance[instance_id].idle_timer = INVALID_TIMER; - } - - if (instance[instance_id].idle_timer == INVALID_TIMER && instance[instance_id].progress_timer != INVALID_TIMER) - clif_instance(instance_id, 3, 0); + time_t now = time(0); + + if( !instance_is_valid(instance_id) ) + return; + + if( instance[instance_id].progress_timer != INVALID_TIMER ) + delete_timer( instance[instance_id].progress_timer, instance_destroy_timer); + if( instance[instance_id].idle_timer != INVALID_TIMER ) + delete_timer( instance[instance_id].idle_timer, instance_destroy_timer); + + if( progress_timeout ) + { + instance[instance_id].progress_timeout = now + progress_timeout; + instance[instance_id].progress_timer = add_timer( gettick() + progress_timeout * 1000, instance_destroy_timer, instance_id, 0); + } + else + { + instance[instance_id].progress_timeout = 0; + instance[instance_id].progress_timer = INVALID_TIMER; + } + + if( idle_timeout ) + { + instance[instance_id].idle_timeoutval = idle_timeout; + instance[instance_id].idle_timer = INVALID_TIMER; + instance_check_idle(instance_id); + } + else + { + instance[instance_id].idle_timeoutval = 0; + instance[instance_id].idle_timeout = 0; + instance[instance_id].idle_timer = INVALID_TIMER; + } + + if( instance[instance_id].idle_timer == INVALID_TIMER && instance[instance_id].progress_timer != INVALID_TIMER ) + clif_instance(instance_id, 3, 0); } /*-------------------------------------- @@ -441,28 +460,28 @@ void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsign *--------------------------------------*/ void instance_check_kick(struct map_session_data *sd) { - int m = sd->bl.m; - - clif_instance_leave(sd->fd); - if (map[m].instance_id) { - // User was on the instance map - if (map[m].save.map) - pc_setpos(sd, map[m].save.map, map[m].save.x, map[m].save.y, CLR_TELEPORT); - else - pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); - } + int m = sd->bl.m; + + clif_instance_leave(sd->fd); + if( map[m].instance_id ) + { // User was on the instance map + if( map[m].save.map ) + pc_setpos(sd, map[m].save.map, map[m].save.x, map[m].save.y, CLR_TELEPORT); + else + pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); + } } void do_final_instance(void) { - int i; + int i; - for (i = 1; i < MAX_INSTANCE; i++) - instance_destroy(i); + for( i = 1; i < MAX_INSTANCE; i++ ) + instance_destroy(i); } void do_init_instance(void) { - memset(instance, 0x00, sizeof(instance)); - add_timer_func_list(instance_destroy_timer, "instance_destroy_timer"); + memset(instance, 0x00, sizeof(instance)); + add_timer_func_list(instance_destroy_timer, "instance_destroy_timer"); } diff --git a/src/map/instance.h b/src/map/instance.h index cfb1d0b77..f8f7387f7 100644 --- a/src/map/instance.h +++ b/src/map/instance.h @@ -12,22 +12,22 @@ typedef enum instance_state { INSTANCE_FREE, INSTANCE_IDLE, INSTANCE_BUSY } instance_state; struct s_instance { - char name[INSTANCE_NAME_LENGTH]; // Instance Name - required for clif functions. - instance_state state; - short instance_id; - int party_id; - - int map[MAX_MAP_PER_INSTANCE]; - int num_map; - int users; - - struct DBMap *vars; // Instance Variable for scripts - - int progress_timer; - time_t progress_timeout; - - int idle_timer; - time_t idle_timeout, idle_timeoutval; + char name[INSTANCE_NAME_LENGTH]; // Instance Name - required for clif functions. + instance_state state; + short instance_id; + int party_id; + + int map[MAX_MAP_PER_INSTANCE]; + int num_map; + int users; + + struct DBMap* vars; // Instance Variable for scripts + + int progress_timer; + time_t progress_timeout; + + int idle_timer; + time_t idle_timeout, idle_timeoutval; }; extern int instance_start; diff --git a/src/map/intif.c b/src/map/intif.c index 8c66db6be..3bbb92216 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -33,735 +33,735 @@ #include <string.h> -static const int packet_len_table[]= { - -1,-1,27,-1, -1, 0,37,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f - 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 - 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 - 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830 - -1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840 - -1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] - -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish] - -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil] - 11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 - -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] +static const int packet_len_table[]={ + -1,-1,27,-1, -1, 0,37,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f + 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 + 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 + 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830 + -1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840 + -1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] + -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish] + -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil] + 11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 + -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] }; extern int char_fd; // inter server Fd used for char_fd -#define inter_fd char_fd // alias +#define inter_fd char_fd // alias //----------------------------------------------------------------- // Send to inter server int CheckForCharServer(void) { - return ((char_fd <= 0) || session[char_fd] == NULL || session[char_fd]->wdata == NULL); + return ((char_fd <= 0) || 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; - WFIFOHEAD(inter_fd, 24 + NAME_LENGTH); - WFIFOW(inter_fd,0) = 0x3080; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOW(inter_fd,10) = pet_class; - WFIFOW(inter_fd,12) = pet_lv; - WFIFOW(inter_fd,14) = pet_egg_id; - WFIFOW(inter_fd,16) = pet_equip; - WFIFOW(inter_fd,18) = intimate; - WFIFOW(inter_fd,20) = hungry; - WFIFOB(inter_fd,22) = rename_flag; - WFIFOB(inter_fd,23) = incuvate; - memcpy(WFIFOP(inter_fd,24),pet_name,NAME_LENGTH); - WFIFOSET(inter_fd,24+NAME_LENGTH); - - return 0; + short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name) +{ + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 24 + NAME_LENGTH); + WFIFOW(inter_fd,0) = 0x3080; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOW(inter_fd,10) = pet_class; + WFIFOW(inter_fd,12) = pet_lv; + WFIFOW(inter_fd,14) = pet_egg_id; + WFIFOW(inter_fd,16) = pet_equip; + WFIFOW(inter_fd,18) = intimate; + WFIFOW(inter_fd,20) = hungry; + WFIFOB(inter_fd,22) = rename_flag; + WFIFOB(inter_fd,23) = incuvate; + memcpy(WFIFOP(inter_fd,24),pet_name,NAME_LENGTH); + WFIFOSET(inter_fd,24+NAME_LENGTH); + + return 0; } int intif_request_petdata(int account_id,int char_id,int pet_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 14); - WFIFOW(inter_fd,0) = 0x3081; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOL(inter_fd,10) = pet_id; - WFIFOSET(inter_fd,14); + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 14); + WFIFOW(inter_fd,0) = 0x3081; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOL(inter_fd,10) = pet_id; + WFIFOSET(inter_fd,14); - return 0; + return 0; } int intif_save_petdata(int account_id,struct s_pet *p) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct s_pet) + 8); - WFIFOW(inter_fd,0) = 0x3082; - WFIFOW(inter_fd,2) = sizeof(struct s_pet) + 8; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8),p,sizeof(struct s_pet)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct s_pet) + 8); + WFIFOW(inter_fd,0) = 0x3082; + WFIFOW(inter_fd,2) = sizeof(struct s_pet) + 8; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8),p,sizeof(struct s_pet)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; + return 0; } int intif_delete_petdata(int pet_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3083; - WFIFOL(inter_fd,2) = pet_id; - WFIFOSET(inter_fd,6); + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3083; + WFIFOL(inter_fd,2) = pet_id; + WFIFOSET(inter_fd,6); - return 1; + return 1; } int intif_rename(struct map_session_data *sd, int type, char *name) { - if (CheckForCharServer()) - return 1; + if (CheckForCharServer()) + return 1; - WFIFOHEAD(inter_fd,NAME_LENGTH+12); - WFIFOW(inter_fd,0) = 0x3006; - WFIFOL(inter_fd,2) = sd->status.account_id; - WFIFOL(inter_fd,6) = sd->status.char_id; - WFIFOB(inter_fd,10) = type; //Type: 0 - PC, 1 - PET, 2 - HOM - memcpy(WFIFOP(inter_fd,11),name, NAME_LENGTH); - WFIFOSET(inter_fd,NAME_LENGTH+12); - return 0; + WFIFOHEAD(inter_fd,NAME_LENGTH+12); + WFIFOW(inter_fd,0) = 0x3006; + WFIFOL(inter_fd,2) = sd->status.account_id; + WFIFOL(inter_fd,6) = sd->status.char_id; + WFIFOB(inter_fd,10) = type; //Type: 0 - PC, 1 - PET, 2 - HOM + memcpy(WFIFOP(inter_fd,11),name, NAME_LENGTH); + WFIFOSET(inter_fd,NAME_LENGTH+12); + return 0; } // GM Send a message -int intif_broadcast(const char *mes, int len, int type) -{ - int lp = type ? 4 : 0; - - // Send to the local players - clif_broadcast(NULL, mes, len, type, ALL_CLIENT); - - if (CheckForCharServer()) - return 0; - - if (other_mapserver_count < 1) - return 0; //No need to send. - - WFIFOHEAD(inter_fd, 16 + lp + len); - WFIFOW(inter_fd,0) = 0x3000; - WFIFOW(inter_fd,2) = 16 + lp + len; - WFIFOL(inter_fd,4) = 0xFF000000; // 0xFF000000 color signals standard broadcast - WFIFOW(inter_fd,8) = 0; // fontType not used with standard broadcast - WFIFOW(inter_fd,10) = 0; // fontSize not used with standard broadcast - WFIFOW(inter_fd,12) = 0; // fontAlign not used with standard broadcast - WFIFOW(inter_fd,14) = 0; // fontY not used with standard broadcast - if (type == 0x10) // bc_blue - WFIFOL(inter_fd,16) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. - else if (type == 0x20) // bc_woe - WFIFOL(inter_fd,16) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. - memcpy(WFIFOP(inter_fd,16 + lp), mes, len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; -} - -int intif_broadcast2(const char *mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY) -{ - // Send to the local players - if (fontColor == 0xFE000000) // This is main chat message [LuzZza] - clif_MainChatMessage(mes); - else - clif_broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT); - - if (CheckForCharServer()) - return 0; - - if (other_mapserver_count < 1) - return 0; //No need to send. - - WFIFOHEAD(inter_fd, 16 + len); - WFIFOW(inter_fd,0) = 0x3000; - WFIFOW(inter_fd,2) = 16 + len; - WFIFOL(inter_fd,4) = fontColor; - WFIFOW(inter_fd,8) = fontType; - WFIFOW(inter_fd,10) = fontSize; - WFIFOW(inter_fd,12) = fontAlign; - WFIFOW(inter_fd,14) = fontY; - memcpy(WFIFOP(inter_fd,16), mes, len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; +int intif_broadcast(const char* mes, int len, int type) +{ + int lp = type ? 4 : 0; + + // Send to the local players + clif_broadcast(NULL, mes, len, type, ALL_CLIENT); + + if (CheckForCharServer()) + return 0; + + if (other_mapserver_count < 1) + return 0; //No need to send. + + WFIFOHEAD(inter_fd, 16 + lp + len); + WFIFOW(inter_fd,0) = 0x3000; + WFIFOW(inter_fd,2) = 16 + lp + len; + WFIFOL(inter_fd,4) = 0xFF000000; // 0xFF000000 color signals standard broadcast + WFIFOW(inter_fd,8) = 0; // fontType not used with standard broadcast + WFIFOW(inter_fd,10) = 0; // fontSize not used with standard broadcast + WFIFOW(inter_fd,12) = 0; // fontAlign not used with standard broadcast + WFIFOW(inter_fd,14) = 0; // fontY not used with standard broadcast + if (type == 0x10) // bc_blue + WFIFOL(inter_fd,16) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. + else if (type == 0x20) // bc_woe + WFIFOL(inter_fd,16) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. + memcpy(WFIFOP(inter_fd,16 + lp), mes, len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; +} + +int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY) +{ + // Send to the local players + if (fontColor == 0xFE000000) // This is main chat message [LuzZza] + clif_MainChatMessage(mes); + else + clif_broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT); + + if (CheckForCharServer()) + return 0; + + if (other_mapserver_count < 1) + return 0; //No need to send. + + WFIFOHEAD(inter_fd, 16 + len); + WFIFOW(inter_fd,0) = 0x3000; + WFIFOW(inter_fd,2) = 16 + len; + WFIFOL(inter_fd,4) = fontColor; + WFIFOW(inter_fd,8) = fontType; + WFIFOW(inter_fd,10) = fontSize; + WFIFOW(inter_fd,12) = fontAlign; + WFIFOW(inter_fd,14) = fontY; + memcpy(WFIFOP(inter_fd,16), mes, len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; } /// send a message using the main chat system /// <sd> the source of message /// <message> the message that was sent -int intif_main_message(struct map_session_data *sd, const char *message) +int intif_main_message(struct map_session_data* sd, const char* message) { - char output[256]; + char output[256]; - nullpo_ret(sd); + nullpo_ret(sd); - // format the message for main broadcasting - snprintf(output, sizeof(output), msg_txt(386), sd->status.name, message); + // format the message for main broadcasting + snprintf( output, sizeof(output), msg_txt(386), sd->status.name, message ); - // send the message using the inter-server broadcast service - intif_broadcast2(output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0); + // send the message using the inter-server broadcast service + intif_broadcast2( output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0 ); - // log the chat message - log_chat(LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message); + // log the chat message + log_chat( LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message ); - return 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_ret(sd); - if (CheckForCharServer()) - return 0; + nullpo_ret(sd); + if (CheckForCharServer()) + return 0; - if (other_mapserver_count < 1) { - //Character not found. - clif_wis_end(sd->fd, 1); - return 0; - } + if (other_mapserver_count < 1) + { //Character not found. + clif_wis_end(sd->fd, 1); + return 0; + } - WFIFOHEAD(inter_fd,mes_len + 52); - WFIFOW(inter_fd,0) = 0x3001; - WFIFOW(inter_fd,2) = mes_len + 52; - memcpy(WFIFOP(inter_fd,4), sd->status.name, NAME_LENGTH); - memcpy(WFIFOP(inter_fd,4+NAME_LENGTH), nick, NAME_LENGTH); - memcpy(WFIFOP(inter_fd,4+2*NAME_LENGTH), mes, mes_len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + WFIFOHEAD(inter_fd,mes_len + 52); + WFIFOW(inter_fd,0) = 0x3001; + WFIFOW(inter_fd,2) = mes_len + 52; + memcpy(WFIFOP(inter_fd,4), sd->status.name, NAME_LENGTH); + memcpy(WFIFOP(inter_fd,4+NAME_LENGTH), nick, NAME_LENGTH); + memcpy(WFIFOP(inter_fd,4+2*NAME_LENGTH), mes, mes_len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - if (battle_config.etc_log) - ShowInfo("intif_wis_message from %s to %s (message: '%s')\n", sd->status.name, nick, mes); + if (battle_config.etc_log) + ShowInfo("intif_wis_message from %s to %s (message: '%s')\n", sd->status.name, nick, mes); - return 0; + return 0; } // The reply of Wisp/page int intif_wis_replay(int id, int flag) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,7); - 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 - WFIFOSET(inter_fd,7); + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,7); + 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 + WFIFOSET(inter_fd,7); - if (battle_config.etc_log) - ShowInfo("intif_wis_replay: id: %d, flag:%d\n", id, flag); + if (battle_config.etc_log) + ShowInfo("intif_wis_replay: id: %d, flag:%d\n", id, flag); - return 0; + return 0; } // The transmission of GM only Wisp/Page from server to inter-server int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes) { - int mes_len; - if (CheckForCharServer()) - return 0; - mes_len = strlen(mes) + 1; // + null - WFIFOHEAD(inter_fd, mes_len + 32); - WFIFOW(inter_fd,0) = 0x3003; - WFIFOW(inter_fd,2) = mes_len + 32; - memcpy(WFIFOP(inter_fd,4), wisp_name, NAME_LENGTH); - WFIFOL(inter_fd,4+NAME_LENGTH) = permission; - memcpy(WFIFOP(inter_fd,8+NAME_LENGTH), mes, mes_len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + int mes_len; + if (CheckForCharServer()) + return 0; + mes_len = strlen(mes) + 1; // + null + WFIFOHEAD(inter_fd, mes_len + 32); + WFIFOW(inter_fd,0) = 0x3003; + WFIFOW(inter_fd,2) = mes_len + 32; + memcpy(WFIFOP(inter_fd,4), wisp_name, NAME_LENGTH); + WFIFOL(inter_fd,4+NAME_LENGTH) = permission; + memcpy(WFIFOP(inter_fd,8+NAME_LENGTH), mes, mes_len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - if (battle_config.etc_log) - ShowNotice("intif_wis_message_to_gm: from: '%s', required permission: %d, message: '%s'.\n", wisp_name, permission, mes); + if (battle_config.etc_log) + ShowNotice("intif_wis_message_to_gm: from: '%s', required permission: %d, message: '%s'.\n", wisp_name, permission, mes); - return 0; + return 0; } -int intif_regtostr(char *str, struct global_reg *reg, int qty) +int intif_regtostr(char* str, struct global_reg *reg, int qty) { - int len =0, i; + int len =0, i; - for (i = 0; i < qty; i++) { - len+= sprintf(str+len, "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. - len+= sprintf(str+len, "%s", reg[i].value)+1; - } - return len; + for (i = 0; i < qty; i++) { + len+= sprintf(str+len, "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. + len+= sprintf(str+len, "%s", reg[i].value)+1; + } + return len; } //Request for saving registry values. int intif_saveregistry(struct map_session_data *sd, int type) { - struct global_reg *reg; - int count; - int i, p; - - if (CheckForCharServer()) - return -1; - - switch (type) { - case 3: //Character reg - reg = sd->save_reg.global; - count = sd->save_reg.global_num; - sd->state.reg_dirty &= ~0x4; - break; - case 2: //Account reg - reg = sd->save_reg.account; - count = sd->save_reg.account_num; - sd->state.reg_dirty &= ~0x2; - break; - case 1: //Account2 reg - reg = sd->save_reg.account2; - count = sd->save_reg.account2_num; - sd->state.reg_dirty &= ~0x1; - break; - default: //Broken code? - ShowError("intif_saveregistry: Invalid type %d\n", type); - return -1; - } - WFIFOHEAD(inter_fd, 288 * MAX_REG_NUM+13); - WFIFOW(inter_fd,0)=0x3004; - WFIFOL(inter_fd,4)=sd->status.account_id; - WFIFOL(inter_fd,8)=sd->status.char_id; - WFIFOB(inter_fd,12)=type; - for (p = 13, i = 0; i < count; i++) { - if (reg[i].str[0] != '\0' && reg[i].value[0] != '\0') { - p+= sprintf((char *)WFIFOP(inter_fd,p), "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. - p+= sprintf((char *)WFIFOP(inter_fd,p), "%s", reg[i].value)+1; - } - } - WFIFOW(inter_fd,2)=p; - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; + struct global_reg *reg; + int count; + int i, p; + + if (CheckForCharServer()) + return -1; + + switch (type) { + case 3: //Character reg + reg = sd->save_reg.global; + count = sd->save_reg.global_num; + sd->state.reg_dirty &= ~0x4; + break; + case 2: //Account reg + reg = sd->save_reg.account; + count = sd->save_reg.account_num; + sd->state.reg_dirty &= ~0x2; + break; + case 1: //Account2 reg + reg = sd->save_reg.account2; + count = sd->save_reg.account2_num; + sd->state.reg_dirty &= ~0x1; + break; + default: //Broken code? + ShowError("intif_saveregistry: Invalid type %d\n", type); + return -1; + } + WFIFOHEAD(inter_fd, 288 * MAX_REG_NUM+13); + WFIFOW(inter_fd,0)=0x3004; + WFIFOL(inter_fd,4)=sd->status.account_id; + WFIFOL(inter_fd,8)=sd->status.char_id; + WFIFOB(inter_fd,12)=type; + for( p = 13, i = 0; i < count; i++ ) { + if (reg[i].str[0] != '\0' && reg[i].value[0] != '\0') { + p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. + p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].value)+1; + } + } + WFIFOW(inter_fd,2)=p; + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; } //Request the registries for this player. int intif_request_registry(struct map_session_data *sd, int flag) { - nullpo_ret(sd); + nullpo_ret(sd); - sd->save_reg.account2_num = -1; - sd->save_reg.account_num = -1; - sd->save_reg.global_num = -1; + sd->save_reg.account2_num = -1; + sd->save_reg.account_num = -1; + sd->save_reg.global_num = -1; - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3005; - WFIFOL(inter_fd,2) = sd->status.account_id; - WFIFOL(inter_fd,6) = sd->status.char_id; - WFIFOB(inter_fd,10) = (flag&1?1:0); //Request Acc Reg 2 - WFIFOB(inter_fd,11) = (flag&2?1:0); //Request Acc Reg - WFIFOB(inter_fd,12) = (flag&4?1:0); //Request Char Reg - WFIFOSET(inter_fd,13); + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3005; + WFIFOL(inter_fd,2) = sd->status.account_id; + WFIFOL(inter_fd,6) = sd->status.char_id; + WFIFOB(inter_fd,10) = (flag&1?1:0); //Request Acc Reg 2 + WFIFOB(inter_fd,11) = (flag&2?1:0); //Request Acc Reg + WFIFOB(inter_fd,12) = (flag&4?1:0); //Request Char Reg + WFIFOSET(inter_fd,13); - return 0; + return 0; } int intif_request_guild_storage(int account_id,int guild_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3018; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = guild_id; - WFIFOSET(inter_fd,10); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3018; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = guild_id; + WFIFOSET(inter_fd,10); + return 0; } int intif_send_guild_storage(int account_id,struct guild_storage *gstor) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,sizeof(struct guild_storage)+12); - WFIFOW(inter_fd,0) = 0x3019; - WFIFOW(inter_fd,2) = (unsigned short)sizeof(struct guild_storage)+12; - WFIFOL(inter_fd,4) = account_id; - WFIFOL(inter_fd,8) = gstor->guild_id; - memcpy(WFIFOP(inter_fd,12),gstor, sizeof(struct guild_storage)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,sizeof(struct guild_storage)+12); + WFIFOW(inter_fd,0) = 0x3019; + WFIFOW(inter_fd,2) = (unsigned short)sizeof(struct guild_storage)+12; + WFIFOL(inter_fd,4) = account_id; + WFIFOL(inter_fd,8) = gstor->guild_id; + memcpy( WFIFOP(inter_fd,12),gstor, sizeof(struct guild_storage) ); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; } // Party creation request int intif_create_party(struct party_member *member,char *name,int item,int item2) { - if (CheckForCharServer()) - return 0; - nullpo_ret(member); + if (CheckForCharServer()) + return 0; + nullpo_ret(member); - WFIFOHEAD(inter_fd,64); - WFIFOW(inter_fd,0) = 0x3020; - WFIFOW(inter_fd,2) = 30+sizeof(struct party_member); - memcpy(WFIFOP(inter_fd,4),name, NAME_LENGTH); - WFIFOB(inter_fd,28)= item; - WFIFOB(inter_fd,29)= item2; - memcpy(WFIFOP(inter_fd,30), member, sizeof(struct party_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); - return 0; + WFIFOHEAD(inter_fd,64); + WFIFOW(inter_fd,0) = 0x3020; + WFIFOW(inter_fd,2) = 30+sizeof(struct party_member); + memcpy(WFIFOP(inter_fd,4),name, NAME_LENGTH); + WFIFOB(inter_fd,28)= item; + WFIFOB(inter_fd,29)= item2; + memcpy(WFIFOP(inter_fd,30), member, sizeof(struct party_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); + return 0; } // Party information request int intif_request_partyinfo(int party_id, int char_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3021; - WFIFOL(inter_fd,2) = party_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOSET(inter_fd,10); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3021; + WFIFOL(inter_fd,2) = party_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOSET(inter_fd,10); + return 0; } // Request to add a member to party int intif_party_addmember(int party_id,struct party_member *member) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,42); - WFIFOW(inter_fd,0)=0x3022; - WFIFOW(inter_fd,2)=8+sizeof(struct party_member); - WFIFOL(inter_fd,4)=party_id; - memcpy(WFIFOP(inter_fd,8),member,sizeof(struct party_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); - return 1; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,42); + WFIFOW(inter_fd,0)=0x3022; + WFIFOW(inter_fd,2)=8+sizeof(struct party_member); + WFIFOL(inter_fd,4)=party_id; + memcpy(WFIFOP(inter_fd,8),member,sizeof(struct party_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); + return 1; } // Request to change party configuration (exp,item share) int intif_party_changeoption(int party_id,int account_id,int exp,int item) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,14); - WFIFOW(inter_fd,0)=0x3023; - WFIFOL(inter_fd,2)=party_id; - WFIFOL(inter_fd,6)=account_id; - WFIFOW(inter_fd,10)=exp; - WFIFOW(inter_fd,12)=item; - WFIFOSET(inter_fd,14); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,14); + WFIFOW(inter_fd,0)=0x3023; + WFIFOL(inter_fd,2)=party_id; + WFIFOL(inter_fd,6)=account_id; + WFIFOW(inter_fd,10)=exp; + WFIFOW(inter_fd,12)=item; + WFIFOSET(inter_fd,14); + return 0; } // Request to leave party int intif_party_leave(int party_id,int account_id, int char_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,14); - WFIFOW(inter_fd,0)=0x3024; - WFIFOL(inter_fd,2)=party_id; - WFIFOL(inter_fd,6)=account_id; - WFIFOL(inter_fd,10)=char_id; - WFIFOSET(inter_fd,14); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,14); + WFIFOW(inter_fd,0)=0x3024; + WFIFOL(inter_fd,2)=party_id; + WFIFOL(inter_fd,6)=account_id; + WFIFOL(inter_fd,10)=char_id; + WFIFOSET(inter_fd,14); + return 0; } // Request keeping party for new map ?? int intif_party_changemap(struct map_session_data *sd,int online) { - int m, mapindex; + int m, mapindex; - if (CheckForCharServer()) - return 0; - if (!sd) - return 0; + if (CheckForCharServer()) + return 0; + if(!sd) + return 0; - if ((m=map_mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id) - mapindex = map[map[m].instance_src_map].index; - else - mapindex = sd->mapindex; + if( (m=map_mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id ) + mapindex = map[map[m].instance_src_map].index; + else + mapindex = sd->mapindex; - WFIFOHEAD(inter_fd,19); - WFIFOW(inter_fd,0)=0x3025; - WFIFOL(inter_fd,2)=sd->status.party_id; - WFIFOL(inter_fd,6)=sd->status.account_id; - WFIFOL(inter_fd,10)=sd->status.char_id; - WFIFOW(inter_fd,14)=mapindex; - WFIFOB(inter_fd,16)=online; - WFIFOW(inter_fd,17)=sd->status.base_level; - WFIFOSET(inter_fd,19); - return 1; + WFIFOHEAD(inter_fd,19); + WFIFOW(inter_fd,0)=0x3025; + WFIFOL(inter_fd,2)=sd->status.party_id; + WFIFOL(inter_fd,6)=sd->status.account_id; + WFIFOL(inter_fd,10)=sd->status.char_id; + WFIFOW(inter_fd,14)=mapindex; + WFIFOB(inter_fd,16)=online; + WFIFOW(inter_fd,17)=sd->status.base_level; + WFIFOSET(inter_fd,19); + return 1; } // Request breaking party int intif_break_party(int party_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0)=0x3026; - WFIFOL(inter_fd,2)=party_id; - WFIFOSET(inter_fd,6); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0)=0x3026; + WFIFOL(inter_fd,2)=party_id; + WFIFOSET(inter_fd,6); + return 0; } // Sending party chat int intif_party_message(int party_id,int account_id,const char *mes,int len) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - if (other_mapserver_count < 1) - return 0; //No need to send. + if (other_mapserver_count < 1) + return 0; //No need to send. - WFIFOHEAD(inter_fd,len + 12); - WFIFOW(inter_fd,0)=0x3027; - WFIFOW(inter_fd,2)=len+12; - WFIFOL(inter_fd,4)=party_id; - WFIFOL(inter_fd,8)=account_id; - memcpy(WFIFOP(inter_fd,12),mes,len); - WFIFOSET(inter_fd,len+12); - return 0; + WFIFOHEAD(inter_fd,len + 12); + WFIFOW(inter_fd,0)=0x3027; + WFIFOW(inter_fd,2)=len+12; + WFIFOL(inter_fd,4)=party_id; + WFIFOL(inter_fd,8)=account_id; + memcpy(WFIFOP(inter_fd,12),mes,len); + WFIFOSET(inter_fd,len+12); + return 0; } // Request a new leader for party int intif_party_leaderchange(int party_id,int account_id,int char_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,14); - WFIFOW(inter_fd,0)=0x3029; - WFIFOL(inter_fd,2)=party_id; - WFIFOL(inter_fd,6)=account_id; - WFIFOL(inter_fd,10)=char_id; - WFIFOSET(inter_fd,14); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,14); + WFIFOW(inter_fd,0)=0x3029; + WFIFOL(inter_fd,2)=party_id; + WFIFOL(inter_fd,6)=account_id; + WFIFOL(inter_fd,10)=char_id; + WFIFOSET(inter_fd,14); + return 0; } // Request a Guild creation int intif_guild_create(const char *name,const struct guild_member *master) { - if (CheckForCharServer()) - return 0; - nullpo_ret(master); + if (CheckForCharServer()) + return 0; + nullpo_ret(master); - WFIFOHEAD(inter_fd,sizeof(struct guild_member)+(8+NAME_LENGTH)); - WFIFOW(inter_fd,0)=0x3030; - WFIFOW(inter_fd,2)=sizeof(struct guild_member)+(8+NAME_LENGTH); - WFIFOL(inter_fd,4)=master->account_id; - memcpy(WFIFOP(inter_fd,8),name,NAME_LENGTH); - memcpy(WFIFOP(inter_fd,8+NAME_LENGTH),master,sizeof(struct guild_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; + WFIFOHEAD(inter_fd,sizeof(struct guild_member)+(8+NAME_LENGTH)); + WFIFOW(inter_fd,0)=0x3030; + WFIFOW(inter_fd,2)=sizeof(struct guild_member)+(8+NAME_LENGTH); + WFIFOL(inter_fd,4)=master->account_id; + memcpy(WFIFOP(inter_fd,8),name,NAME_LENGTH); + memcpy(WFIFOP(inter_fd,8+NAME_LENGTH),master,sizeof(struct guild_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; } // Request Guild information int intif_guild_request_info(int guild_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3031; - WFIFOL(inter_fd,2) = guild_id; - WFIFOSET(inter_fd,6); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3031; + WFIFOL(inter_fd,2) = guild_id; + WFIFOSET(inter_fd,6); + return 0; } // Request to add member to the guild int intif_guild_addmember(int guild_id,struct guild_member *m) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,sizeof(struct guild_member)+8); - WFIFOW(inter_fd,0) = 0x3032; - WFIFOW(inter_fd,2) = sizeof(struct guild_member)+8; - WFIFOL(inter_fd,4) = guild_id; - memcpy(WFIFOP(inter_fd,8),m,sizeof(struct guild_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,sizeof(struct guild_member)+8); + WFIFOW(inter_fd,0) = 0x3032; + WFIFOW(inter_fd,2) = sizeof(struct guild_member)+8; + WFIFOL(inter_fd,4) = guild_id; + memcpy(WFIFOP(inter_fd,8),m,sizeof(struct guild_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; } // Request a new leader for guild -int intif_guild_change_gm(int guild_id, const char *name, int len) +int intif_guild_change_gm(int guild_id, const char* name, int len) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, len + 8); - WFIFOW(inter_fd, 0)=0x3033; - WFIFOW(inter_fd, 2)=len+8; - WFIFOL(inter_fd, 4)=guild_id; - memcpy(WFIFOP(inter_fd,8),name,len); - WFIFOSET(inter_fd,len+8); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, len + 8); + WFIFOW(inter_fd, 0)=0x3033; + WFIFOW(inter_fd, 2)=len+8; + WFIFOL(inter_fd, 4)=guild_id; + memcpy(WFIFOP(inter_fd,8),name,len); + WFIFOSET(inter_fd,len+8); + return 0; } // Request to leave guild int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const char *mes) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 55); - WFIFOW(inter_fd, 0) = 0x3034; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOL(inter_fd, 6) = account_id; - WFIFOL(inter_fd,10) = char_id; - WFIFOB(inter_fd,14) = flag; - safestrncpy((char *)WFIFOP(inter_fd,15),mes,40); - WFIFOSET(inter_fd,55); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 55); + WFIFOW(inter_fd, 0) = 0x3034; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOL(inter_fd, 6) = account_id; + WFIFOL(inter_fd,10) = char_id; + WFIFOB(inter_fd,14) = flag; + safestrncpy((char*)WFIFOP(inter_fd,15),mes,40); + WFIFOSET(inter_fd,55); + return 0; } //Update request / Lv online status of the guild members int intif_guild_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 19); - 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_; - WFIFOSET(inter_fd,19); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 19); + 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_; + WFIFOSET(inter_fd,19); + return 0; } //Guild disbanded notification int intif_guild_break(int guild_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 6); - WFIFOW(inter_fd, 0) = 0x3036; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOSET(inter_fd,6); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 6); + WFIFOW(inter_fd, 0) = 0x3036; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOSET(inter_fd,6); + return 0; } // Send a guild message int intif_guild_message(int guild_id,int account_id,const char *mes,int len) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - if (other_mapserver_count < 1) - return 0; //No need to send. + if (other_mapserver_count < 1) + return 0; //No need to send. - WFIFOHEAD(inter_fd, len + 12); - 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); + WFIFOHEAD(inter_fd, len + 12); + 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; + return 0; } // Request a change of Guild basic information int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, len + 10); - WFIFOW(inter_fd,0)=0x3039; - WFIFOW(inter_fd,2)=len+10; - WFIFOL(inter_fd,4)=guild_id; - WFIFOW(inter_fd,8)=type; - memcpy(WFIFOP(inter_fd,10),data,len); - WFIFOSET(inter_fd,len+10); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, len + 10); + WFIFOW(inter_fd,0)=0x3039; + WFIFOW(inter_fd,2)=len+10; + WFIFOL(inter_fd,4)=guild_id; + WFIFOW(inter_fd,8)=type; + memcpy(WFIFOP(inter_fd,10),data,len); + WFIFOSET(inter_fd,len+10); + return 0; } // Request a change of Guild member information 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; - WFIFOHEAD(inter_fd, len + 18); - WFIFOW(inter_fd, 0)=0x303a; - WFIFOW(inter_fd, 2)=len+18; - WFIFOL(inter_fd, 4)=guild_id; - WFIFOL(inter_fd, 8)=account_id; - WFIFOL(inter_fd,12)=char_id; - WFIFOW(inter_fd,16)=type; - memcpy(WFIFOP(inter_fd,18),data,len); - WFIFOSET(inter_fd,len+18); - return 0; + int type,const void *data,int len) +{ + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, len + 18); + WFIFOW(inter_fd, 0)=0x303a; + WFIFOW(inter_fd, 2)=len+18; + WFIFOL(inter_fd, 4)=guild_id; + WFIFOL(inter_fd, 8)=account_id; + WFIFOL(inter_fd,12)=char_id; + WFIFOW(inter_fd,16)=type; + memcpy(WFIFOP(inter_fd,18),data,len); + WFIFOSET(inter_fd,len+18); + return 0; } // Request a change of Guild title int intif_guild_position(int guild_id,int idx,struct guild_position *p) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct guild_position)+12); - WFIFOW(inter_fd,0)=0x303b; - WFIFOW(inter_fd,2)=sizeof(struct guild_position)+12; - WFIFOL(inter_fd,4)=guild_id; - WFIFOL(inter_fd,8)=idx; - memcpy(WFIFOP(inter_fd,12),p,sizeof(struct guild_position)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct guild_position)+12); + WFIFOW(inter_fd,0)=0x303b; + WFIFOW(inter_fd,2)=sizeof(struct guild_position)+12; + WFIFOL(inter_fd,4)=guild_id; + WFIFOL(inter_fd,8)=idx; + memcpy(WFIFOP(inter_fd,12),p,sizeof(struct guild_position)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; } // Request an update of Guildskill skillnum int intif_guild_skillup(int guild_id, int skill_num, int account_id, int max) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 18); - WFIFOW(inter_fd, 0) = 0x303c; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOL(inter_fd, 6) = skill_num; - WFIFOL(inter_fd, 10) = account_id; - WFIFOL(inter_fd, 14) = max; - WFIFOSET(inter_fd, 18); - return 0; + if( CheckForCharServer() ) + return 0; + WFIFOHEAD(inter_fd, 18); + WFIFOW(inter_fd, 0) = 0x303c; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOL(inter_fd, 6) = skill_num; + WFIFOL(inter_fd, 10) = account_id; + WFIFOL(inter_fd, 14) = max; + WFIFOSET(inter_fd, 18); + return 0; } // Request a new guild relationship int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,19); - WFIFOW(inter_fd, 0)=0x303d; - WFIFOL(inter_fd, 2)=guild_id1; - WFIFOL(inter_fd, 6)=guild_id2; - WFIFOL(inter_fd,10)=account_id1; - WFIFOL(inter_fd,14)=account_id2; - WFIFOB(inter_fd,18)=flag; - WFIFOSET(inter_fd,19); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,19); + WFIFOW(inter_fd, 0)=0x303d; + WFIFOL(inter_fd, 2)=guild_id1; + WFIFOL(inter_fd, 6)=guild_id2; + WFIFOL(inter_fd,10)=account_id1; + WFIFOL(inter_fd,14)=account_id2; + WFIFOB(inter_fd,18)=flag; + WFIFOSET(inter_fd,19); + return 0; } // Request to change guild notice int intif_guild_notice(int guild_id,const char *mes1,const char *mes2) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,186); - WFIFOW(inter_fd,0)=0x303e; - WFIFOL(inter_fd,2)=guild_id; - memcpy(WFIFOP(inter_fd,6),mes1,MAX_GUILDMES1); - memcpy(WFIFOP(inter_fd,66),mes2,MAX_GUILDMES2); - WFIFOSET(inter_fd,186); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,186); + WFIFOW(inter_fd,0)=0x303e; + WFIFOL(inter_fd,2)=guild_id; + memcpy(WFIFOP(inter_fd,6),mes1,MAX_GUILDMES1); + memcpy(WFIFOP(inter_fd,66),mes2,MAX_GUILDMES2); + WFIFOSET(inter_fd,186); + return 0; } // Request to change guild emblem 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; - WFIFOHEAD(inter_fd,len + 12); - WFIFOW(inter_fd,0)=0x303f; - WFIFOW(inter_fd,2)=len+12; - WFIFOL(inter_fd,4)=guild_id; - WFIFOL(inter_fd,8)=0; - memcpy(WFIFOP(inter_fd,12),data,len); - WFIFOSET(inter_fd,len+12); - return 0; + if (CheckForCharServer()) + return 0; + if(guild_id<=0 || len<0 || len>2000) + return 0; + WFIFOHEAD(inter_fd,len + 12); + WFIFOW(inter_fd,0)=0x303f; + WFIFOW(inter_fd,2)=len+12; + WFIFOL(inter_fd,4)=guild_id; + WFIFOL(inter_fd,8)=0; + memcpy(WFIFOP(inter_fd,12),data,len); + WFIFOSET(inter_fd,len+12); + return 0; } /** @@ -771,29 +771,29 @@ int intif_guild_emblem(int guild_id,int len,const char *data) */ int intif_guild_castle_dataload(int num, int *castle_ids) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 4 + num * sizeof(int)); - WFIFOW(inter_fd, 0) = 0x3040; - WFIFOW(inter_fd, 2) = 4 + num * sizeof(int); - memcpy(WFIFOP(inter_fd, 4), castle_ids, num * sizeof(int)); - WFIFOSET(inter_fd, WFIFOW(inter_fd, 2)); - return 1; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 4 + num * sizeof(int)); + WFIFOW(inter_fd, 0) = 0x3040; + WFIFOW(inter_fd, 2) = 4 + num * sizeof(int); + memcpy(WFIFOP(inter_fd, 4), castle_ids, num * sizeof(int)); + WFIFOSET(inter_fd, WFIFOW(inter_fd, 2)); + return 1; } // Request change castle guild owner and save data int intif_guild_castle_datasave(int castle_id,int index, int value) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,9); - WFIFOW(inter_fd,0)=0x3041; - WFIFOW(inter_fd,2)=castle_id; - WFIFOB(inter_fd,4)=index; - WFIFOL(inter_fd,5)=value; - WFIFOSET(inter_fd,9); - return 1; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,9); + WFIFOW(inter_fd,0)=0x3041; + WFIFOW(inter_fd,2)=castle_id; + WFIFOB(inter_fd,4)=index; + WFIFOL(inter_fd,5)=value; + WFIFOSET(inter_fd,9); + return 1; } //----------------------------------------------------------------- @@ -802,52 +802,52 @@ int intif_guild_castle_datasave(int castle_id,int index, int value) int intif_homunculus_create(int account_id, struct s_homunculus *sh) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); - WFIFOW(inter_fd,0) = 0x3090; - WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); + WFIFOW(inter_fd,0) = 0x3090; + WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; } int intif_homunculus_requestload(int account_id, int homun_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 10); - WFIFOW(inter_fd,0) = 0x3091; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = homun_id; - WFIFOSET(inter_fd, 10); - return 1; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 10); + WFIFOW(inter_fd,0) = 0x3091; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = homun_id; + WFIFOSET(inter_fd, 10); + return 1; } -int intif_homunculus_requestsave(int account_id, struct s_homunculus *sh) +int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); - WFIFOW(inter_fd,0) = 0x3092; - WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); + WFIFOW(inter_fd,0) = 0x3092; + WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; } int intif_homunculus_requestdelete(int homun_id) { - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 6); - WFIFOW(inter_fd, 0) = 0x3093; - WFIFOL(inter_fd,2) = homun_id; - WFIFOSET(inter_fd,6); - return 0; + if (CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 6); + WFIFOW(inter_fd, 0) = 0x3093; + WFIFOL(inter_fd,2) = homun_id; + WFIFOSET(inter_fd,6); + return 0; } @@ -858,509 +858,489 @@ int intif_homunculus_requestdelete(int homun_id) // Wisp/Page reception // rewritten by [Yor] int intif_parse_WisMessage(int fd) { - struct map_session_data *sd; - char *wisp_source; - char name[NAME_LENGTH]; - int id, i; - - id=RFIFOL(fd,4); - - safestrncpy(name, (char *)RFIFOP(fd,32), NAME_LENGTH); - sd = map_nick2sd(name); - if (sd == NULL || strcmp(sd->status.name, name) != 0) { - //Not found - intif_wis_replay(id,1); - return 0; - } - if (sd->state.ignoreAll) { - intif_wis_replay(id, 2); - return 0; - } - wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor] - for (i=0; i < MAX_IGNORE_LIST && - sd->ignore[i].name[0] != '\0' && - strcmp(sd->ignore[i].name, wisp_source) != 0 - ; i++); - - if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0') { - //Ignored - intif_wis_replay(id, 2); - return 0; - } - //Success to send whisper. - clif_wis_message(sd->fd, wisp_source, (char *)RFIFOP(fd,56),RFIFOW(fd,2)-56); - intif_wis_replay(id,0); // succes - return 0; + struct map_session_data* sd; + char *wisp_source; + char name[NAME_LENGTH]; + int id, i; + + id=RFIFOL(fd,4); + + safestrncpy(name, (char*)RFIFOP(fd,32), NAME_LENGTH); + sd = map_nick2sd(name); + if(sd == NULL || strcmp(sd->status.name, name) != 0) + { //Not found + intif_wis_replay(id,1); + return 0; + } + if(sd->state.ignoreAll) { + intif_wis_replay(id, 2); + return 0; + } + wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor] + for(i=0; i < MAX_IGNORE_LIST && + sd->ignore[i].name[0] != '\0' && + strcmp(sd->ignore[i].name, wisp_source) != 0 + ; i++); + + if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0') + { //Ignored + intif_wis_replay(id, 2); + return 0; + } + //Success to send whisper. + clif_wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56); + intif_wis_replay(id,0); // succes + return 0; } // Wisp/page transmission result reception int intif_parse_WisEnd(int fd) { - struct map_session_data *sd; + struct map_session_data* sd; - if (battle_config.etc_log) - ShowInfo("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 = (struct map_session_data *)map_nick2sd((char *) RFIFOP(fd,2)); - if (sd != NULL) - clif_wis_end(sd->fd, RFIFOB(fd,26)); + if (battle_config.etc_log) + ShowInfo("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 = (struct map_session_data *)map_nick2sd((char *) RFIFOP(fd,2)); + if (sd != NULL) + clif_wis_end(sd->fd, RFIFOB(fd,26)); - return 0; + return 0; } -static int mapif_parse_WisToGM_sub(struct map_session_data *sd,va_list va) +static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) { - int permission = va_arg(va, int); - char *wisp_name; - char *message; - int len; + int permission = va_arg(va, int); + char *wisp_name; + char *message; + int len; - if (!pc_has_permission(sd, permission)) - return 0; - wisp_name = va_arg(va, char *); - message = va_arg(va, char *); - len = va_arg(va, int); - clif_wis_message(sd->fd, wisp_name, message, len); - return 1; + if (!pc_has_permission(sd, permission)) + return 0; + wisp_name = va_arg(va, char*); + message = va_arg(va, char*); + len = va_arg(va, int); + clif_wis_message(sd->fd, wisp_name, message, len); + return 1; } // Received wisp message from map-server via char-server for ALL gm // 0x3003/0x3803 <packet_len>.w <wispname>.24B <permission>.l <message>.?B int mapif_parse_WisToGM(int fd) { - int permission, mes_len; - char Wisp_name[NAME_LENGTH]; - char mbuf[255]; - char *message; + int permission, mes_len; + char Wisp_name[NAME_LENGTH]; + char mbuf[255]; + char *message; - mes_len = RFIFOW(fd,2) - 32; - message = (char *)(mes_len >= 255 ? (char *) aMalloc(mes_len) : mbuf); + mes_len = RFIFOW(fd,2) - 32; + message = (char *) (mes_len >= 255 ? (char *) aMalloc(mes_len) : mbuf); - permission = RFIFOL(fd,28); - safestrncpy(Wisp_name, (char *)RFIFOP(fd,4), NAME_LENGTH); - safestrncpy(message, (char *)RFIFOP(fd,32), mes_len); - // information is sent to all online GM - map_foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len); + permission = RFIFOL(fd,28); + safestrncpy(Wisp_name, (char*)RFIFOP(fd,4), NAME_LENGTH); + safestrncpy(message, (char*)RFIFOP(fd,32), mes_len); + // information is sent to all online GM + map_foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len); - if (message != mbuf) - aFree(message); - return 0; + if (message != mbuf) + aFree(message); + return 0; } // Request player registre int intif_parse_Registers(int fd) { - int j,p,len,max, flag; - struct map_session_data *sd; - struct global_reg *reg; - int *qty; - int account_id = RFIFOL(fd,4), char_id = RFIFOL(fd,8); - struct auth_node *node = chrif_auth_check(account_id, char_id, ST_LOGIN); - if (node) - sd = node->sd; - else { //Normally registries should arrive for in log-in chars. - sd = map_id2sd(account_id); - if (sd && RFIFOB(fd,12) == 3 && sd->status.char_id != char_id) - sd = NULL; //Character registry from another character. - } - if (!sd) return 1; - - flag = (sd->save_reg.global_num == -1 || sd->save_reg.account_num == -1 || sd->save_reg.account2_num == -1); - - switch (RFIFOB(fd,12)) { - case 3: //Character Registry - reg = sd->save_reg.global; - qty = &sd->save_reg.global_num; - max = GLOBAL_REG_NUM; - break; - case 2: //Account Registry - reg = sd->save_reg.account; - qty = &sd->save_reg.account_num; - max = ACCOUNT_REG_NUM; - break; - case 1: //Account2 Registry - reg = sd->save_reg.account2; - qty = &sd->save_reg.account2_num; - max = ACCOUNT_REG2_NUM; - break; - default: - ShowError("intif_parse_Registers: Unrecognized type %d\n",RFIFOB(fd,12)); - return 0; - } - for (j=0,p=13; j<max && p<RFIFOW(fd,2); j++) { - sscanf((char *)RFIFOP(fd,p), "%31c%n", reg[j].str,&len); - reg[j].str[len]='\0'; - p += len+1; //+1 to skip the '\0' between strings. - sscanf((char *)RFIFOP(fd,p), "%255c%n", reg[j].value,&len); - reg[j].value[len]='\0'; - p += len+1; - } - *qty = j; - - if (flag && sd->save_reg.global_num > -1 && sd->save_reg.account_num > -1 && sd->save_reg.account2_num > -1) - pc_reg_received(sd); //Received all registry values, execute init scripts and what-not. [Skotlex] - return 1; + int j,p,len,max, flag; + struct map_session_data *sd; + struct global_reg *reg; + int *qty; + int account_id = RFIFOL(fd,4), char_id = RFIFOL(fd,8); + struct auth_node *node = chrif_auth_check(account_id, char_id, ST_LOGIN); + if (node) + sd = node->sd; + else { //Normally registries should arrive for in log-in chars. + sd = map_id2sd(account_id); + if (sd && RFIFOB(fd,12) == 3 && sd->status.char_id != char_id) + sd = NULL; //Character registry from another character. + } + if (!sd) return 1; + + flag = (sd->save_reg.global_num == -1 || sd->save_reg.account_num == -1 || sd->save_reg.account2_num == -1); + + switch (RFIFOB(fd,12)) { + case 3: //Character Registry + reg = sd->save_reg.global; + qty = &sd->save_reg.global_num; + max = GLOBAL_REG_NUM; + break; + case 2: //Account Registry + reg = sd->save_reg.account; + qty = &sd->save_reg.account_num; + max = ACCOUNT_REG_NUM; + break; + case 1: //Account2 Registry + reg = sd->save_reg.account2; + qty = &sd->save_reg.account2_num; + max = ACCOUNT_REG2_NUM; + break; + default: + ShowError("intif_parse_Registers: Unrecognized type %d\n",RFIFOB(fd,12)); + return 0; + } + for(j=0,p=13;j<max && p<RFIFOW(fd,2);j++){ + sscanf((char*)RFIFOP(fd,p), "%31c%n", reg[j].str,&len); + reg[j].str[len]='\0'; + p += len+1; //+1 to skip the '\0' between strings. + sscanf((char*)RFIFOP(fd,p), "%255c%n", reg[j].value,&len); + reg[j].value[len]='\0'; + p += len+1; + } + *qty = j; + + if (flag && sd->save_reg.global_num > -1 && sd->save_reg.account_num > -1 && sd->save_reg.account2_num > -1) + pc_reg_received(sd); //Received all registry values, execute init scripts and what-not. [Skotlex] + return 1; } int intif_parse_LoadGuildStorage(int fd) { - struct guild_storage *gstor; - struct map_session_data *sd; - int guild_id; - - guild_id = RFIFOL(fd,8); - if (guild_id <= 0) - return 1; - sd=map_id2sd(RFIFOL(fd,4)); - if (sd==NULL) { - ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4)); - return 1; - } - gstor=guild2storage(guild_id); - if (!gstor) { - ShowWarning("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",guild_id); - return 1; - } - if (gstor->storage_status == 1) { // Already open.. lets ignore this update - ShowWarning("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id); - return 1; - } - if (gstor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex] - ShowWarning("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id); - return 1; - } - if (RFIFOW(fd,2)-12 != sizeof(struct guild_storage)) { - ShowError("intif_parse_LoadGuildStorage: data size error %d %d\n",RFIFOW(fd,2)-12 , sizeof(struct guild_storage)); - gstor->storage_status = 0; - return 1; - } - - memcpy(gstor,RFIFOP(fd,12),sizeof(struct guild_storage)); - storage_guild_storageopen(sd); - return 0; + struct guild_storage *gstor; + struct map_session_data *sd; + int guild_id; + + guild_id = RFIFOL(fd,8); + if(guild_id <= 0) + return 1; + sd=map_id2sd( RFIFOL(fd,4) ); + if(sd==NULL){ + ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4)); + return 1; + } + gstor=guild2storage(guild_id); + if(!gstor) { + ShowWarning("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",guild_id); + return 1; + } + if (gstor->storage_status == 1) { // Already open.. lets ignore this update + ShowWarning("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id); + return 1; + } + if (gstor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex] + ShowWarning("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id); + return 1; + } + if( RFIFOW(fd,2)-12 != sizeof(struct guild_storage) ){ + ShowError("intif_parse_LoadGuildStorage: data size error %d %d\n",RFIFOW(fd,2)-12 , sizeof(struct guild_storage)); + gstor->storage_status = 0; + return 1; + } + + memcpy(gstor,RFIFOP(fd,12),sizeof(struct guild_storage)); + storage_guild_storageopen(sd); + return 0; } // ACK guild_storage saved int intif_parse_SaveGuildStorage(int fd) { - storage_guild_storagesaved(/*RFIFOL(fd,2), */RFIFOL(fd,6)); - return 0; + storage_guild_storagesaved(/*RFIFOL(fd,2), */RFIFOL(fd,6)); + return 0; } // ACK party creation int intif_parse_PartyCreated(int fd) { - if (battle_config.etc_log) - ShowInfo("intif: party created by account %d\n\n", RFIFOL(fd,2)); - party_created(RFIFOL(fd,2), RFIFOL(fd,6),RFIFOB(fd,10),RFIFOL(fd,11), (char *)RFIFOP(fd,15)); - return 0; + if(battle_config.etc_log) + ShowInfo("intif: party created by account %d\n\n", RFIFOL(fd,2)); + party_created(RFIFOL(fd,2), RFIFOL(fd,6),RFIFOB(fd,10),RFIFOL(fd,11), (char *)RFIFOP(fd,15)); + return 0; } // Receive party info int intif_parse_PartyInfo(int fd) { - if (RFIFOW(fd,2) == 12) { - ShowWarning("intif: party noinfo (char_id=%d party_id=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8)); - party_recv_noinfo(RFIFOL(fd,8), RFIFOL(fd,4)); - return 0; - } + if( RFIFOW(fd,2) == 12 ){ + ShowWarning("intif: party noinfo (char_id=%d party_id=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8)); + party_recv_noinfo(RFIFOL(fd,8), RFIFOL(fd,4)); + return 0; + } - if (RFIFOW(fd,2) != 8+sizeof(struct party)) - ShowError("intif: party info : data size error (char_id=%d party_id=%d packet_len=%d expected_len=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8), RFIFOW(fd,2), 8+sizeof(struct party)); - party_recv_info((struct party *)RFIFOP(fd,8), RFIFOL(fd,4)); - return 0; + if( RFIFOW(fd,2) != 8+sizeof(struct party) ) + ShowError("intif: party info : data size error (char_id=%d party_id=%d packet_len=%d expected_len=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8), RFIFOW(fd,2), 8+sizeof(struct party)); + party_recv_info((struct party *)RFIFOP(fd,8), RFIFOL(fd,4)); + return 0; } // ACK adding party member int intif_parse_PartyMemberAdded(int fd) { - if (battle_config.etc_log) - ShowInfo("intif: party member added Party (%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - party_member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10), RFIFOB(fd, 14)); - return 0; + if(battle_config.etc_log) + ShowInfo("intif: party member added Party (%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + party_member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10), RFIFOB(fd, 14)); + return 0; } // ACK changing party option int intif_parse_PartyOptionChanged(int fd) { - party_optionchanged(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12),RFIFOB(fd,14)); - return 0; + party_optionchanged(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12),RFIFOB(fd,14)); + return 0; } // ACK member leaving party int intif_parse_PartyMemberWithdraw(int fd) { - if (battle_config.etc_log) - ShowInfo("intif: party member withdraw: Party(%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - party_member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - return 0; + if(battle_config.etc_log) + ShowInfo("intif: party member withdraw: Party(%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + party_member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + return 0; } // ACK party break int intif_parse_PartyBroken(int fd) { - party_broken(RFIFOL(fd,2)); - return 0; + party_broken(RFIFOL(fd,2)); + return 0; } // ACK party on new map int intif_parse_PartyMove(int fd) { - party_recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOW(fd,14),RFIFOB(fd,16),RFIFOW(fd,17)); - return 0; + party_recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOW(fd,14),RFIFOB(fd,16),RFIFOW(fd,17)); + return 0; } // ACK party messages int intif_parse_PartyMessage(int fd) { - party_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); - return 0; + party_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); + return 0; } // ACK guild creation int intif_parse_GuildCreated(int fd) { - guild_created(RFIFOL(fd,2),RFIFOL(fd,6)); - return 0; + guild_created(RFIFOL(fd,2),RFIFOL(fd,6)); + return 0; } // ACK guild infos int intif_parse_GuildInfo(int fd) { - if (RFIFOW(fd,2) == 8) { - ShowWarning("intif: guild noinfo %d\n",RFIFOL(fd,4)); - guild_recv_noinfo(RFIFOL(fd,4)); - return 0; - } - if (RFIFOW(fd,2)!=sizeof(struct guild)+4) - ShowError("intif: guild info : data size error Gid: %d recv size: %d Expected size: %d\n",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild)+4); - guild_recv_info((struct guild *)RFIFOP(fd,4)); - return 0; + if(RFIFOW(fd,2) == 8) { + ShowWarning("intif: guild noinfo %d\n",RFIFOL(fd,4)); + guild_recv_noinfo(RFIFOL(fd,4)); + return 0; + } + if( RFIFOW(fd,2)!=sizeof(struct guild)+4 ) + ShowError("intif: guild info : data size error Gid: %d recv size: %d Expected size: %d\n",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild)+4); + guild_recv_info((struct guild *)RFIFOP(fd,4)); + return 0; } // ACK adding guild member int intif_parse_GuildMemberAdded(int fd) { - if (battle_config.etc_log) - ShowInfo("intif: guild member added %d %d %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); - guild_member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); - return 0; + if(battle_config.etc_log) + ShowInfo("intif: guild member added %d %d %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); + guild_member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); + return 0; } // ACK member leaving guild int intif_parse_GuildMemberWithdraw(int fd) { - guild_member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(char *)RFIFOP(fd,55),(char *)RFIFOP(fd,15)); - return 0; + guild_member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(char *)RFIFOP(fd,55),(char *)RFIFOP(fd,15)); + return 0; } // ACK guild member basic info int intif_parse_GuildMemberInfoShort(int fd) { - guild_recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17)); - return 0; + guild_recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17)); + return 0; } // ACK guild break int intif_parse_GuildBroken(int fd) { - guild_broken(RFIFOL(fd,2),RFIFOB(fd,6)); - return 0; + guild_broken(RFIFOL(fd,2),RFIFOB(fd,6)); + return 0; } // basic guild info change notice // 0x3839 <packet len>.w <guild id>.l <type>.w <data>.?b int intif_parse_GuildBasicInfoChanged(int fd) { - //int len = RFIFOW(fd,2) - 10; - int guild_id = RFIFOL(fd,4); - int type = RFIFOW(fd,8); - //void* data = RFIFOP(fd,10); + //int len = RFIFOW(fd,2) - 10; + int guild_id = RFIFOL(fd,4); + int type = RFIFOW(fd,8); + //void* data = RFIFOP(fd,10); - struct guild *g = guild_search(guild_id); - if (g == NULL) - return 0; + struct guild* g = guild_search(guild_id); + if( g == NULL ) + return 0; - switch (type) { - case GBI_EXP: - g->exp = RFIFOQ(fd,10); - break; - case GBI_GUILDLV: - g->guild_lv = RFIFOW(fd,10); - break; - case GBI_SKILLPOINT: - g->skill_point = RFIFOL(fd,10); - break; - } + switch(type) { + case GBI_EXP: g->exp = RFIFOQ(fd,10); break; + case GBI_GUILDLV: g->guild_lv = RFIFOW(fd,10); break; + case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break; + } - return 0; + return 0; } // guild member info change notice // 0x383a <packet len>.w <guild id>.l <account id>.l <char id>.l <type>.w <data>.?b int intif_parse_GuildMemberInfoChanged(int fd) { - //int len = RFIFOW(fd,2) - 18; - int guild_id = RFIFOL(fd,4); - int account_id = RFIFOL(fd,8); - int char_id = RFIFOL(fd,12); - int type = RFIFOW(fd,16); - //void* data = RFIFOP(fd,18); - - struct guild *g; - int idx; - - g = guild_search(guild_id); - if (g == NULL) - return 0; - - idx = guild_getindex(g,account_id,char_id); - if (idx == -1) - return 0; - - switch (type) { - case GMI_POSITION: - g->member[idx].position = RFIFOW(fd,18); - guild_memberposition_changed(g,idx,RFIFOW(fd,18)); - break; - case GMI_EXP: - g->member[idx].exp = RFIFOQ(fd,18); - break; - case GMI_HAIR: - g->member[idx].hair = RFIFOW(fd,18); - break; - case GMI_HAIR_COLOR: - g->member[idx].hair_color = RFIFOW(fd,18); - break; - case GMI_GENDER: - g->member[idx].gender = RFIFOW(fd,18); - break; - case GMI_CLASS: - g->member[idx].class_ = RFIFOW(fd,18); - break; - case GMI_LEVEL: - g->member[idx].lv = RFIFOW(fd,18); - break; - } - return 0; + //int len = RFIFOW(fd,2) - 18; + int guild_id = RFIFOL(fd,4); + int account_id = RFIFOL(fd,8); + int char_id = RFIFOL(fd,12); + int type = RFIFOW(fd,16); + //void* data = RFIFOP(fd,18); + + struct guild* g; + int idx; + + g = guild_search(guild_id); + if( g == NULL ) + return 0; + + idx = guild_getindex(g,account_id,char_id); + if( idx == -1 ) + return 0; + + switch( type ) { + case GMI_POSITION: g->member[idx].position = RFIFOW(fd,18); guild_memberposition_changed(g,idx,RFIFOW(fd,18)); break; + case GMI_EXP: g->member[idx].exp = RFIFOQ(fd,18); break; + case GMI_HAIR: g->member[idx].hair = RFIFOW(fd,18); break; + case GMI_HAIR_COLOR: g->member[idx].hair_color = RFIFOW(fd,18); break; + case GMI_GENDER: g->member[idx].gender = RFIFOW(fd,18); break; + case GMI_CLASS: g->member[idx].class_ = RFIFOW(fd,18); break; + case GMI_LEVEL: g->member[idx].lv = RFIFOW(fd,18); break; + } + return 0; } // ACK change of guild title int intif_parse_GuildPosition(int fd) { - if (RFIFOW(fd,2)!=sizeof(struct guild_position)+12) - ShowError("intif: guild info : data size error\n %d %d %d",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild_position)+12); - guild_position_changed(RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); - return 0; + if( RFIFOW(fd,2)!=sizeof(struct guild_position)+12 ) + ShowError("intif: guild info : data size error\n %d %d %d",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild_position)+12); + guild_position_changed(RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); + return 0; } // ACK change of guild skill update int intif_parse_GuildSkillUp(int fd) { - guild_skillupack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - return 0; + guild_skillupack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + return 0; } // ACK change of guild relationship int intif_parse_GuildAlliance(int fd) { - guild_allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43)); - return 0; + guild_allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43)); + return 0; } // ACK change of guild notice int intif_parse_GuildNotice(int fd) { - guild_notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66)); - return 0; + guild_notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66)); + return 0; } // ACK change of guild emblem int intif_parse_GuildEmblem(int fd) { - guild_emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12)); - return 0; + guild_emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12)); + return 0; } // ACK guild message int intif_parse_GuildMessage(int fd) { - guild_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); - return 0; + guild_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); + return 0; } // Reply guild castle data request int intif_parse_GuildCastleDataLoad(int fd) { - return guild_castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4)); + return guild_castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4)); } // ACK change of guildmaster int intif_parse_GuildMasterChanged(int fd) { - return guild_gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + return guild_gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); } // Request pet creation int intif_parse_CreatePet(int fd) { - pet_get_egg(RFIFOL(fd,2),RFIFOL(fd,7),RFIFOB(fd,6)); - return 0; + pet_get_egg(RFIFOL(fd,2),RFIFOL(fd,7),RFIFOB(fd,6)); + return 0; } // ACK pet data int intif_parse_RecvPetData(int fd) { - struct s_pet p; - int len; - len=RFIFOW(fd,2); - if (sizeof(struct s_pet)!=len-9) { - if (battle_config.etc_log) - ShowError("intif: pet data: data size error %d %d\n",sizeof(struct s_pet),len-9); - } else { - memcpy(&p,RFIFOP(fd,9),sizeof(struct s_pet)); - pet_recv_petdata(RFIFOL(fd,4),&p,RFIFOB(fd,8)); - } + struct s_pet p; + int len; + len=RFIFOW(fd,2); + if(sizeof(struct s_pet)!=len-9) { + if(battle_config.etc_log) + ShowError("intif: pet data: data size error %d %d\n",sizeof(struct s_pet),len-9); + } + else{ + memcpy(&p,RFIFOP(fd,9),sizeof(struct s_pet)); + pet_recv_petdata(RFIFOL(fd,4),&p,RFIFOB(fd,8)); + } - return 0; + return 0; } // ACK pet save data int intif_parse_SavePetOk(int fd) { - if (RFIFOB(fd,6) == 1) - ShowError("pet data save failure\n"); + if(RFIFOB(fd,6) == 1) + ShowError("pet data save failure\n"); - return 0; + return 0; } // ACK deleting pet int intif_parse_DeletePetOk(int fd) { - if (RFIFOB(fd,2) == 1) - ShowError("pet data delete failure\n"); + if(RFIFOB(fd,2) == 1) + ShowError("pet data delete failure\n"); - return 0; + return 0; } // ACK changing name resquest, players,pets,hommon int intif_parse_ChangeNameOk(int fd) { - struct map_session_data *sd = NULL; - if ((sd=map_id2sd(RFIFOL(fd,2)))==NULL || - sd->status.char_id != RFIFOL(fd,6)) - return 0; + struct map_session_data *sd = NULL; + if((sd=map_id2sd(RFIFOL(fd,2)))==NULL || + sd->status.char_id != RFIFOL(fd,6)) + return 0; - switch (RFIFOB(fd,10)) { - case 0: //Players [NOT SUPPORTED YET] - break; - case 1: //Pets - pet_change_name_ack(sd, (char *)RFIFOP(fd,12), RFIFOB(fd,11)); - break; - case 2: //Hom - merc_hom_change_name_ack(sd, (char *)RFIFOP(fd,12), RFIFOB(fd,11)); - break; - } - return 0; + switch (RFIFOB(fd,10)) { + case 0: //Players [NOT SUPPORTED YET] + break; + case 1: //Pets + pet_change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); + break; + case 2: //Hom + merc_hom_change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); + break; + } + return 0; } //---------------------------------------------------------------- @@ -1368,46 +1348,46 @@ int intif_parse_ChangeNameOk(int fd) int intif_parse_CreateHomunculus(int fd) { - int len; - len=RFIFOW(fd,2)-9; - if (sizeof(struct s_homunculus)!=len) { - if (battle_config.etc_log) - ShowError("intif: create homun data: data size error %d != %d\n",sizeof(struct s_homunculus),len); - return 0; - } - merc_hom_recv_data(RFIFOL(fd,4), (struct s_homunculus *)RFIFOP(fd,9), RFIFOB(fd,8)) ; - return 0; + int len; + len=RFIFOW(fd,2)-9; + if(sizeof(struct s_homunculus)!=len) { + if(battle_config.etc_log) + ShowError("intif: create homun data: data size error %d != %d\n",sizeof(struct s_homunculus),len); + return 0; + } + merc_hom_recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)) ; + return 0; } int intif_parse_RecvHomunculusData(int fd) { - int len; + int len; - len=RFIFOW(fd,2)-9; + len=RFIFOW(fd,2)-9; - if (sizeof(struct s_homunculus)!=len) { - if (battle_config.etc_log) - ShowError("intif: homun data: data size error %d %d\n",sizeof(struct s_homunculus),len); - return 0; - } - merc_hom_recv_data(RFIFOL(fd,4), (struct s_homunculus *)RFIFOP(fd,9), RFIFOB(fd,8)); - return 0; + if(sizeof(struct s_homunculus)!=len) { + if(battle_config.etc_log) + ShowError("intif: homun data: data size error %d %d\n",sizeof(struct s_homunculus),len); + return 0; + } + merc_hom_recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)); + return 0; } int intif_parse_SaveHomunculusOk(int fd) { - if (RFIFOB(fd,6) != 1) - ShowError("homunculus data save failure for account %d\n", RFIFOL(fd,2)); + if(RFIFOB(fd,6) != 1) + ShowError("homunculus data save failure for account %d\n", RFIFOL(fd,2)); - return 0; + return 0; } int intif_parse_DeleteHomunculusOk(int fd) { - if (RFIFOB(fd,2) != 1) - ShowError("Homunculus data delete failure\n"); + if(RFIFOB(fd,2) != 1) + ShowError("Homunculus data delete failure\n"); - return 0; + return 0; } /************************************** @@ -1418,80 +1398,82 @@ QUESTLOG SYSTEM FUNCTIONS int intif_request_questlog(TBL_PC *sd) { - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3060; - WFIFOL(inter_fd,2) = sd->status.char_id; - WFIFOSET(inter_fd,6); - return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3060; + WFIFOL(inter_fd,2) = sd->status.char_id; + WFIFOSET(inter_fd,6); + return 0; } int intif_parse_questlog(int fd) { - int char_id = RFIFOL(fd, 4); - int i; - TBL_PC *sd = map_charid2sd(char_id); + int char_id = RFIFOL(fd, 4); + int i; + TBL_PC * sd = map_charid2sd(char_id); - //User not online anymore - if (!sd) - return -1; + //User not online anymore + if(!sd) + return -1; - sd->avail_quests = sd->num_quests = (RFIFOW(fd, 2)-8)/sizeof(struct quest); + sd->avail_quests = sd->num_quests = (RFIFOW(fd, 2)-8)/sizeof(struct quest); - memset(&sd->quest_log, 0, sizeof(sd->quest_log)); + memset(&sd->quest_log, 0, sizeof(sd->quest_log)); - for (i = 0; i < sd->num_quests; i++) { - memcpy(&sd->quest_log[i], RFIFOP(fd, i*sizeof(struct quest)+8), sizeof(struct quest)); + for( i = 0; i < sd->num_quests; i++ ) + { + memcpy(&sd->quest_log[i], RFIFOP(fd, i*sizeof(struct quest)+8), sizeof(struct quest)); - sd->quest_index[i] = quest_search_db(sd->quest_log[i].quest_id); + sd->quest_index[i] = quest_search_db(sd->quest_log[i].quest_id); - if (sd->quest_index[i] < 0) { - ShowError("intif_parse_questlog: quest %d not found in DB.\n",sd->quest_log[i].quest_id); - sd->avail_quests--; - sd->num_quests--; - i--; - continue; - } + if( sd->quest_index[i] < 0 ) + { + ShowError("intif_parse_questlog: quest %d not found in DB.\n",sd->quest_log[i].quest_id); + sd->avail_quests--; + sd->num_quests--; + i--; + continue; + } - if (sd->quest_log[i].state == Q_COMPLETE) - sd->avail_quests--; - } + if( sd->quest_log[i].state == Q_COMPLETE ) + sd->avail_quests--; + } - quest_pc_login(sd); + quest_pc_login(sd); - return 0; + return 0; } int intif_parse_questsave(int fd) { - int cid = RFIFOL(fd, 2); - TBL_PC *sd = map_id2sd(cid); + int cid = RFIFOL(fd, 2); + TBL_PC *sd = map_id2sd(cid); - if (!RFIFOB(fd, 6)) - ShowError("intif_parse_questsave: Failed to save quest(s) for character %d!\n", cid); - else if (sd) - sd->save_quest = false; + if( !RFIFOB(fd, 6) ) + ShowError("intif_parse_questsave: Failed to save quest(s) for character %d!\n", cid); + else if( sd ) + sd->save_quest = false; - return 0; + return 0; } int intif_quest_save(TBL_PC *sd) { - int len; + int len; - if (CheckForCharServer()) - return 0; + if(CheckForCharServer()) + return 0; - len = sizeof(struct quest)*sd->num_quests + 8; + len = sizeof(struct quest)*sd->num_quests + 8; - WFIFOHEAD(inter_fd, len); - WFIFOW(inter_fd,0) = 0x3061; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = sd->status.char_id; - if (sd->num_quests) - memcpy(WFIFOP(inter_fd,8), &sd->quest_log, sizeof(struct quest)*sd->num_quests); - WFIFOSET(inter_fd, len); + WFIFOHEAD(inter_fd, len); + WFIFOW(inter_fd,0) = 0x3061; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = sd->status.char_id; + if( sd->num_quests ) + memcpy(WFIFOP(inter_fd,8), &sd->quest_log, sizeof(struct quest)*sd->num_quests); + WFIFOSET(inter_fd, len); - return 0; + return 0; } /*========================================== @@ -1505,449 +1487,462 @@ int intif_quest_save(TBL_PC *sd) *------------------------------------------*/ int intif_Mail_requestinbox(int char_id, unsigned char flag) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,7); - WFIFOW(inter_fd,0) = 0x3048; - WFIFOL(inter_fd,2) = char_id; - WFIFOB(inter_fd,6) = flag; - WFIFOSET(inter_fd,7); + WFIFOHEAD(inter_fd,7); + WFIFOW(inter_fd,0) = 0x3048; + WFIFOL(inter_fd,2) = char_id; + WFIFOB(inter_fd,6) = flag; + WFIFOSET(inter_fd,7); - return 0; + return 0; } int intif_parse_Mail_inboxreceived(int fd) { - struct map_session_data *sd; - unsigned char flag = RFIFOB(fd,8); - - sd = map_charid2sd(RFIFOL(fd,4)); - - if (sd == NULL) { - ShowError("intif_parse_Mail_inboxreceived: char not found %d\n",RFIFOL(fd,4)); - return 1; - } - - if (RFIFOW(fd,2) - 9 != sizeof(struct mail_data)) { - ShowError("intif_parse_Mail_inboxreceived: data size error %d %d\n", RFIFOW(fd,2) - 9, sizeof(struct mail_data)); - return 1; - } - - //FIXME: this operation is not safe [ultramage] - memcpy(&sd->mail.inbox, RFIFOP(fd,9), sizeof(struct mail_data)); - sd->mail.changed = false; // cache is now in sync - - if (flag) - clif_Mail_refreshinbox(sd); - else if (battle_config.mail_show_status && (battle_config.mail_show_status == 1 || sd->mail.inbox.unread)) { - char output[128]; - sprintf(output, msg_txt(510), sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked); - clif_disp_onlyself(sd, output, strlen(output)); - } - return 0; + struct map_session_data *sd; + unsigned char flag = RFIFOB(fd,8); + + sd = map_charid2sd(RFIFOL(fd,4)); + + if (sd == NULL) + { + ShowError("intif_parse_Mail_inboxreceived: char not found %d\n",RFIFOL(fd,4)); + return 1; + } + + if (RFIFOW(fd,2) - 9 != sizeof(struct mail_data)) + { + ShowError("intif_parse_Mail_inboxreceived: data size error %d %d\n", RFIFOW(fd,2) - 9, sizeof(struct mail_data)); + return 1; + } + + //FIXME: this operation is not safe [ultramage] + memcpy(&sd->mail.inbox, RFIFOP(fd,9), sizeof(struct mail_data)); + sd->mail.changed = false; // cache is now in sync + + if (flag) + clif_Mail_refreshinbox(sd); + else if( battle_config.mail_show_status && ( battle_config.mail_show_status == 1 || sd->mail.inbox.unread ) ) + { + char output[128]; + sprintf(output, msg_txt(510), sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked); + clif_disp_onlyself(sd, output, strlen(output)); + } + return 0; } /*------------------------------------------ * Mail Read *------------------------------------------*/ int intif_Mail_read(int mail_id) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3049; - WFIFOL(inter_fd,2) = mail_id; - WFIFOSET(inter_fd,6); + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3049; + WFIFOL(inter_fd,2) = mail_id; + WFIFOSET(inter_fd,6); - return 0; + return 0; } /*------------------------------------------ * Get Attachment *------------------------------------------*/ int intif_Mail_getattach(int char_id, int mail_id) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x304a; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = mail_id; - WFIFOSET(inter_fd, 10); + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x304a; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = mail_id; + WFIFOSET(inter_fd, 10); - return 0; + return 0; } int intif_parse_Mail_getattach(int fd) { - struct map_session_data *sd; - struct item item; - int zeny = RFIFOL(fd,8); + struct map_session_data *sd; + struct item item; + int zeny = RFIFOL(fd,8); - sd = map_charid2sd(RFIFOL(fd,4)); + sd = map_charid2sd( RFIFOL(fd,4) ); - if (sd == NULL) { - ShowError("intif_parse_Mail_getattach: char not found %d\n",RFIFOL(fd,4)); - return 1; - } + if (sd == NULL) + { + ShowError("intif_parse_Mail_getattach: char not found %d\n",RFIFOL(fd,4)); + return 1; + } - if (RFIFOW(fd,2) - 12 != sizeof(struct item)) { - ShowError("intif_parse_Mail_getattach: data size error %d %d\n", RFIFOW(fd,2) - 16, sizeof(struct item)); - return 1; - } + if (RFIFOW(fd,2) - 12 != sizeof(struct item)) + { + ShowError("intif_parse_Mail_getattach: data size error %d %d\n", RFIFOW(fd,2) - 16, sizeof(struct item)); + return 1; + } - memcpy(&item, RFIFOP(fd,12), sizeof(struct item)); + memcpy(&item, RFIFOP(fd,12), sizeof(struct item)); - mail_getattachment(sd, zeny, &item); - return 0; + mail_getattachment(sd, zeny, &item); + return 0; } /*------------------------------------------ * Delete Message *------------------------------------------*/ int intif_Mail_delete(int char_id, int mail_id) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x304b; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = mail_id; - WFIFOSET(inter_fd,10); + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x304b; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = mail_id; + WFIFOSET(inter_fd,10); - return 0; + return 0; } int intif_parse_Mail_delete(int fd) { - int char_id = RFIFOL(fd,2); - int mail_id = RFIFOL(fd,6); - bool failed = RFIFOB(fd,10); - - struct map_session_data *sd = map_charid2sd(char_id); - if (sd == NULL) { - ShowError("intif_parse_Mail_delete: char not found %d\n", char_id); - return 1; - } - - if (!failed) { - int i; - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if (i < MAIL_MAX_INBOX) { - memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); - sd->mail.inbox.amount--; - } - - if (sd->mail.inbox.full) - intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails - } - - clif_Mail_delete(sd->fd, mail_id, failed); - return 0; + int char_id = RFIFOL(fd,2); + int mail_id = RFIFOL(fd,6); + bool failed = RFIFOB(fd,10); + + struct map_session_data *sd = map_charid2sd(char_id); + if (sd == NULL) + { + ShowError("intif_parse_Mail_delete: char not found %d\n", char_id); + return 1; + } + + if (!failed) + { + int i; + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i < MAIL_MAX_INBOX ) + { + memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); + sd->mail.inbox.amount--; + } + + if( sd->mail.inbox.full ) + intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails + } + + clif_Mail_delete(sd->fd, mail_id, failed); + return 0; } /*------------------------------------------ * Return Message *------------------------------------------*/ int intif_Mail_return(int char_id, int mail_id) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x304c; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = mail_id; - WFIFOSET(inter_fd,10); + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x304c; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = mail_id; + WFIFOSET(inter_fd,10); - return 0; + return 0; } int intif_parse_Mail_return(int fd) { - struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); - int mail_id = RFIFOL(fd,6); - short fail = RFIFOB(fd,10); - - if (sd == NULL) { - ShowError("intif_parse_Mail_return: char not found %d\n",RFIFOL(fd,2)); - return 1; - } - - if (!fail) { - int i; - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if (i < MAIL_MAX_INBOX) { - memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); - sd->mail.inbox.amount--; - } - - if (sd->mail.inbox.full) - intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails - } - - clif_Mail_return(sd->fd, mail_id, fail); - return 0; + struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); + int mail_id = RFIFOL(fd,6); + short fail = RFIFOB(fd,10); + + if( sd == NULL ) + { + ShowError("intif_parse_Mail_return: char not found %d\n",RFIFOL(fd,2)); + return 1; + } + + if( !fail ) + { + int i; + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i < MAIL_MAX_INBOX ) + { + memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); + sd->mail.inbox.amount--; + } + + if( sd->mail.inbox.full ) + intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails + } + + clif_Mail_return(sd->fd, mail_id, fail); + return 0; } /*------------------------------------------ * Send Mail *------------------------------------------*/ int intif_Mail_send(int account_id, struct mail_message *msg) { - int len = sizeof(struct mail_message) + 8; + int len = sizeof(struct mail_message) + 8; - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x304d; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8), msg, sizeof(struct mail_message)); - WFIFOSET(inter_fd,len); + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x304d; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8), msg, sizeof(struct mail_message)); + WFIFOSET(inter_fd,len); - return 1; + return 1; } static void intif_parse_Mail_send(int fd) { - struct mail_message msg; - struct map_session_data *sd; - bool fail; - - if (RFIFOW(fd,2) - 4 != sizeof(struct mail_message)) { - ShowError("intif_parse_Mail_send: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct mail_message)); - return; - } - - memcpy(&msg, RFIFOP(fd,4), sizeof(struct mail_message)); - fail = (msg.id == 0); - - // notify sender - sd = map_charid2sd(msg.send_id); - if (sd != NULL) { - if (fail) - mail_deliveryfail(sd, &msg); - else { - clif_Mail_send(sd->fd, false); - if (save_settings&16) - chrif_save(sd, 0); - } - } + struct mail_message msg; + struct map_session_data *sd; + bool fail; + + if( RFIFOW(fd,2) - 4 != sizeof(struct mail_message) ) + { + ShowError("intif_parse_Mail_send: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct mail_message)); + return; + } + + memcpy(&msg, RFIFOP(fd,4), sizeof(struct mail_message)); + fail = (msg.id == 0); + + // notify sender + sd = map_charid2sd(msg.send_id); + if( sd != NULL ) + { + if( fail ) + mail_deliveryfail(sd, &msg); + else + { + clif_Mail_send(sd->fd, false); + if( save_settings&16 ) + chrif_save(sd, 0); + } + } } static void intif_parse_Mail_new(int fd) { - struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); - int mail_id = RFIFOL(fd,6); - const char *sender_name = (char *)RFIFOP(fd,10); - const char *title = (char *)RFIFOP(fd,34); + struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); + int mail_id = RFIFOL(fd,6); + const char* sender_name = (char*)RFIFOP(fd,10); + const char* title = (char*)RFIFOP(fd,34); - if (sd == NULL) - return; + if( sd == NULL ) + return; - sd->mail.changed = true; - clif_Mail_new(sd->fd, mail_id, sender_name, title); + sd->mail.changed = true; + clif_Mail_new(sd->fd, mail_id, sender_name, title); } /*========================================== * AUCTION SYSTEM * By Zephyrus *==========================================*/ -int intif_Auction_requestlist(int char_id, short type, int price, const char *searchtext, short page) +int intif_Auction_requestlist(int char_id, short type, int price, const char* searchtext, short page) { - int len = NAME_LENGTH + 16; + int len = NAME_LENGTH + 16; - if (CheckForCharServer()) - return 0; + if( CheckForCharServer() ) + return 0; - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x3050; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = char_id; - WFIFOW(inter_fd,8) = type; - WFIFOL(inter_fd,10) = price; - WFIFOW(inter_fd,14) = page; - memcpy(WFIFOP(inter_fd,16), searchtext, NAME_LENGTH); - WFIFOSET(inter_fd,len); + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x3050; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = char_id; + WFIFOW(inter_fd,8) = type; + WFIFOL(inter_fd,10) = price; + WFIFOW(inter_fd,14) = page; + memcpy(WFIFOP(inter_fd,16), searchtext, NAME_LENGTH); + WFIFOSET(inter_fd,len); - return 0; + return 0; } static void intif_parse_Auction_results(int fd) { - struct map_session_data *sd = map_charid2sd(RFIFOL(fd,4)); - short count = RFIFOW(fd,8); - short pages = RFIFOW(fd,10); - uint8 *data = RFIFOP(fd,12); + struct map_session_data *sd = map_charid2sd(RFIFOL(fd,4)); + short count = RFIFOW(fd,8); + short pages = RFIFOW(fd,10); + uint8* data = RFIFOP(fd,12); - if (sd == NULL) - return; + if( sd == NULL ) + return; - clif_Auction_results(sd, count, pages, data); + clif_Auction_results(sd, count, pages, data); } int intif_Auction_register(struct auction_data *auction) { - int len = sizeof(struct auction_data) + 4; + int len = sizeof(struct auction_data) + 4; - if (CheckForCharServer()) - return 0; + if( CheckForCharServer() ) + return 0; - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x3051; - WFIFOW(inter_fd,2) = len; - memcpy(WFIFOP(inter_fd,4), auction, sizeof(struct auction_data)); - WFIFOSET(inter_fd,len); + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x3051; + WFIFOW(inter_fd,2) = len; + memcpy(WFIFOP(inter_fd,4), auction, sizeof(struct auction_data)); + WFIFOSET(inter_fd,len); - return 1; + return 1; } static void intif_parse_Auction_register(int fd) { - struct map_session_data *sd; - struct auction_data auction; + struct map_session_data *sd; + struct auction_data auction; - if (RFIFOW(fd,2) - 4 != sizeof(struct auction_data)) { - ShowError("intif_parse_Auction_register: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct auction_data)); - return; - } + if( RFIFOW(fd,2) - 4 != sizeof(struct auction_data) ) + { + ShowError("intif_parse_Auction_register: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct auction_data)); + return; + } - memcpy(&auction, RFIFOP(fd,4), sizeof(struct auction_data)); - if ((sd = map_charid2sd(auction.seller_id)) == NULL) - return; + memcpy(&auction, RFIFOP(fd,4), sizeof(struct auction_data)); + if( (sd = map_charid2sd(auction.seller_id)) == NULL ) + return; - if (auction.auction_id > 0) { - clif_Auction_message(sd->fd, 1); // Confirmation Packet ?? - if (save_settings&32) - chrif_save(sd,0); - } else { - int zeny = auction.hours*battle_config.auction_feeperhour; + if( auction.auction_id > 0 ) + { + clif_Auction_message(sd->fd, 1); // Confirmation Packet ?? + if( save_settings&32 ) + chrif_save(sd,0); + } + else + { + int zeny = auction.hours*battle_config.auction_feeperhour; - clif_Auction_message(sd->fd, 4); - pc_additem(sd, &auction.item, auction.item.amount, LOG_TYPE_AUCTION); + clif_Auction_message(sd->fd, 4); + pc_additem(sd, &auction.item, auction.item.amount, LOG_TYPE_AUCTION); - pc_getzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); - } + pc_getzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); + } } int intif_Auction_cancel(int char_id, unsigned int auction_id) { - if (CheckForCharServer()) - return 0; + if( CheckForCharServer() ) + return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3052; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = auction_id; - WFIFOSET(inter_fd,10); + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3052; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = auction_id; + WFIFOSET(inter_fd,10); - return 0; + return 0; } static void intif_parse_Auction_cancel(int fd) { - struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); - int result = RFIFOB(fd,6); + struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); + int result = RFIFOB(fd,6); - if (sd == NULL) - return; + if( sd == NULL ) + return; - switch (result) { - case 0: - clif_Auction_message(sd->fd, 2); - break; - case 1: - clif_Auction_close(sd->fd, 2); - break; - case 2: - clif_Auction_close(sd->fd, 1); - break; - case 3: - clif_Auction_message(sd->fd, 3); - break; - } + switch( result ) + { + case 0: clif_Auction_message(sd->fd, 2); break; + case 1: clif_Auction_close(sd->fd, 2); break; + case 2: clif_Auction_close(sd->fd, 1); break; + case 3: clif_Auction_message(sd->fd, 3); break; + } } int intif_Auction_close(int char_id, unsigned int auction_id) { - if (CheckForCharServer()) - return 0; + if( CheckForCharServer() ) + return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3053; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = auction_id; - WFIFOSET(inter_fd,10); + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3053; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = auction_id; + WFIFOSET(inter_fd,10); - return 0; + return 0; } static void intif_parse_Auction_close(int fd) { - struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); - unsigned char result = RFIFOB(fd,6); + struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); + unsigned char result = RFIFOB(fd,6); - if (sd == NULL) - return; + if( sd == NULL ) + return; - clif_Auction_close(sd->fd, result); - if (result == 0) { - // FIXME: Leeching off a parse function - clif_parse_Auction_cancelreg(fd, sd); - intif_Auction_requestlist(sd->status.char_id, 6, 0, "", 1); - } + clif_Auction_close(sd->fd, result); + if( result == 0 ) + { + // FIXME: Leeching off a parse function + clif_parse_Auction_cancelreg(fd, sd); + intif_Auction_requestlist(sd->status.char_id, 6, 0, "", 1); + } } -int intif_Auction_bid(int char_id, const char *name, unsigned int auction_id, int bid) +int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, int bid) { - int len = 16 + NAME_LENGTH; + int len = 16 + NAME_LENGTH; - if (CheckForCharServer()) - return 0; + if( CheckForCharServer() ) + return 0; - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x3055; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = char_id; - WFIFOL(inter_fd,8) = auction_id; - WFIFOL(inter_fd,12) = bid; - memcpy(WFIFOP(inter_fd,16), name, NAME_LENGTH); - WFIFOSET(inter_fd,len); + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x3055; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = char_id; + WFIFOL(inter_fd,8) = auction_id; + WFIFOL(inter_fd,12) = bid; + memcpy(WFIFOP(inter_fd,16), name, NAME_LENGTH); + WFIFOSET(inter_fd,len); - return 0; + return 0; } static void intif_parse_Auction_bid(int fd) { - struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); - int bid = RFIFOL(fd,6); - unsigned char result = RFIFOB(fd,10); + struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); + int bid = RFIFOL(fd,6); + unsigned char result = RFIFOB(fd,10); - if (sd == NULL) - return; + if( sd == NULL ) + return; - clif_Auction_message(sd->fd, result); - if (bid > 0) { - pc_getzeny(sd, bid, LOG_TYPE_AUCTION,NULL); - } - if (result == 1) { - // To update the list, display your buy list - clif_parse_Auction_cancelreg(fd, sd); - intif_Auction_requestlist(sd->status.char_id, 7, 0, "", 1); - } + clif_Auction_message(sd->fd, result); + if( bid > 0 ) + { + pc_getzeny(sd, bid, LOG_TYPE_AUCTION,NULL); + } + if( result == 1 ) + { // To update the list, display your buy list + clif_parse_Auction_cancelreg(fd, sd); + intif_Auction_requestlist(sd->status.char_id, 7, 0, "", 1); + } } // Used to send 'You have won the auction' and 'You failed to won the auction' messages static void intif_parse_Auction_message(int fd) { - struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); - unsigned char result = RFIFOB(fd,6); + struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); + unsigned char result = RFIFOB(fd,6); - if (sd == NULL) - return; + if( sd == NULL ) + return; - clif_Auction_message(sd->fd, result); + clif_Auction_message(sd->fd, result); } /*========================================== @@ -1955,86 +1950,87 @@ static void intif_parse_Auction_message(int fd) *------------------------------------------*/ int intif_mercenary_create(struct s_mercenary *merc) { - int size = sizeof(struct s_mercenary) + 4; + int size = sizeof(struct s_mercenary) + 4; - if (CheckForCharServer()) - return 0; + if( CheckForCharServer() ) + return 0; - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x3070; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); - WFIFOSET(inter_fd,size); - return 0; + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x3070; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); + WFIFOSET(inter_fd,size); + return 0; } int intif_parse_mercenary_received(int fd) { - int len = RFIFOW(fd,2) - 5; - if (sizeof(struct s_mercenary) != len) { - if (battle_config.etc_log) - ShowError("intif: create mercenary data size error %d != %d\n", sizeof(struct s_mercenary), len); - return 0; - } + int len = RFIFOW(fd,2) - 5; + if( sizeof(struct s_mercenary) != len ) + { + if( battle_config.etc_log ) + ShowError("intif: create mercenary data size error %d != %d\n", sizeof(struct s_mercenary), len); + return 0; + } - merc_data_received((struct s_mercenary *)RFIFOP(fd,5), RFIFOB(fd,4)); - return 0; + merc_data_received((struct s_mercenary*)RFIFOP(fd,5), RFIFOB(fd,4)); + return 0; } int intif_mercenary_request(int merc_id, int char_id) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3071; - WFIFOL(inter_fd,2) = merc_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOSET(inter_fd,10); - return 0; + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3071; + WFIFOL(inter_fd,2) = merc_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOSET(inter_fd,10); + return 0; } int intif_mercenary_delete(int merc_id) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3072; - WFIFOL(inter_fd,2) = merc_id; - WFIFOSET(inter_fd,6); - return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3072; + WFIFOL(inter_fd,2) = merc_id; + WFIFOSET(inter_fd,6); + return 0; } int intif_parse_mercenary_deleted(int fd) { - if (RFIFOB(fd,2) != 1) - ShowError("Mercenary data delete failure\n"); + if( RFIFOB(fd,2) != 1 ) + ShowError("Mercenary data delete failure\n"); - return 0; + return 0; } int intif_mercenary_save(struct s_mercenary *merc) { - int size = sizeof(struct s_mercenary) + 4; + int size = sizeof(struct s_mercenary) + 4; - if (CheckForCharServer()) - return 0; + if( CheckForCharServer() ) + return 0; - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x3073; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); - WFIFOSET(inter_fd,size); - return 0; + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x3073; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); + WFIFOSET(inter_fd,size); + return 0; } int intif_parse_mercenary_saved(int fd) { - if (RFIFOB(fd,2) != 1) - ShowError("Mercenary data save failure\n"); + if( RFIFOB(fd,2) != 1 ) + ShowError("Mercenary data save failure\n"); - return 0; + return 0; } /*========================================== @@ -2042,122 +2038,121 @@ int intif_parse_mercenary_saved(int fd) *------------------------------------------*/ int intif_elemental_create(struct s_elemental *ele) { - int size = sizeof(struct s_elemental) + 4; + int size = sizeof(struct s_elemental) + 4; - if (CheckForCharServer()) - return 0; + if( CheckForCharServer() ) + return 0; - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x307c; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); - WFIFOSET(inter_fd,size); - return 0; + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x307c; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); + WFIFOSET(inter_fd,size); + return 0; } int intif_parse_elemental_received(int fd) { - int len = RFIFOW(fd,2) - 5; - if (sizeof(struct s_elemental) != len) { - if (battle_config.etc_log) - ShowError("intif: create elemental data size error %d != %d\n", sizeof(struct s_elemental), len); - return 0; - } + int len = RFIFOW(fd,2) - 5; + if( sizeof(struct s_elemental) != len ) + { + if( battle_config.etc_log ) + ShowError("intif: create elemental data size error %d != %d\n", sizeof(struct s_elemental), len); + return 0; + } - elemental_data_received((struct s_elemental *)RFIFOP(fd,5), RFIFOB(fd,4)); - return 0; + elemental_data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4)); + return 0; } int intif_elemental_request(int ele_id, int char_id) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x307d; - WFIFOL(inter_fd,2) = ele_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOSET(inter_fd,10); - return 0; + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x307d; + WFIFOL(inter_fd,2) = ele_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOSET(inter_fd,10); + return 0; } int intif_elemental_delete(int ele_id) { - if (CheckForCharServer()) - return 0; + if (CheckForCharServer()) + return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x307e; - WFIFOL(inter_fd,2) = ele_id; - WFIFOSET(inter_fd,6); - return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x307e; + WFIFOL(inter_fd,2) = ele_id; + WFIFOSET(inter_fd,6); + return 0; } int intif_parse_elemental_deleted(int fd) { - if (RFIFOB(fd,2) != 1) - ShowError("Elemental data delete failure\n"); + if( RFIFOB(fd,2) != 1 ) + ShowError("Elemental data delete failure\n"); - return 0; + return 0; } int intif_elemental_save(struct s_elemental *ele) { - int size = sizeof(struct s_elemental) + 4; + int size = sizeof(struct s_elemental) + 4; - if (CheckForCharServer()) - return 0; + if( CheckForCharServer() ) + return 0; - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x307f; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); - WFIFOSET(inter_fd,size); - return 0; + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x307f; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); + WFIFOSET(inter_fd,size); + return 0; } int intif_parse_elemental_saved(int fd) { - if (RFIFOB(fd,2) != 1) - ShowError("Elemental data save failure\n"); + if( RFIFOB(fd,2) != 1 ) + ShowError("Elemental data save failure\n"); - return 0; + return 0; } -void intif_request_accinfo(int u_fd, int aid, int group_id, char *query) -{ +void intif_request_accinfo( int u_fd, int aid, int group_id, char* query ) { - WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); + WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); - WFIFOW(inter_fd,0) = 0x3007; - WFIFOL(inter_fd,2) = u_fd; - WFIFOL(inter_fd,6) = aid; - WFIFOL(inter_fd,10) = group_id; - safestrncpy((char *)WFIFOP(inter_fd,14), query, NAME_LENGTH); + WFIFOW(inter_fd,0) = 0x3007; + WFIFOL(inter_fd,2) = u_fd; + WFIFOL(inter_fd,6) = aid; + WFIFOL(inter_fd,10) = group_id; + safestrncpy(WFIFOP(inter_fd,14), query, NAME_LENGTH); - WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); + WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); - return; + return; } -void intif_parse_MessageToFD(int fd) -{ - int u_fd = RFIFOL(fd,4); +void intif_parse_MessageToFD(int fd) { + int u_fd = RFIFOL(fd,4); - if (session[u_fd] && session[u_fd]->session_data) { - int aid = RFIFOL(fd,8); - struct map_session_data *sd = session[u_fd]->session_data; - /* matching e.g. previous fd owner didn't dc during request or is still the same */ - if (sd->bl.id == aid) { - char msg[512]; - safestrncpy(msg, (char *)RFIFOP(fd,12), RFIFOW(fd,2) - 12); - clif_displaymessage(u_fd,msg); - } + if( session[u_fd] && session[u_fd]->session_data ) { + int aid = RFIFOL(fd,8); + struct map_session_data * sd = session[u_fd]->session_data; + /* matching e.g. previous fd owner didn't dc during request or is still the same */ + if( sd->bl.id == aid ) { + char msg[512]; + safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12); + clif_displaymessage(u_fd,msg); + } - } + } - return; + return; } //----------------------------------------------------------------- @@ -2166,227 +2161,107 @@ void intif_parse_MessageToFD(int fd) // 1, 2 if there are not enough to return the length of the packet if the packet processing int intif_parse(int fd) { - int packet_len, cmd; - cmd = RFIFOW(fd,0); + int packet_len, cmd; + cmd = RFIFOW(fd,0); // Verify ID of the packet - if (cmd<0x3800 || cmd>=0x3800+(sizeof(packet_len_table)/sizeof(packet_len_table[0])) || - packet_len_table[cmd-0x3800]==0) { - return 0; - } + if(cmd<0x3800 || cmd>=0x3800+(sizeof(packet_len_table)/sizeof(packet_len_table[0])) || + packet_len_table[cmd-0x3800]==0){ + return 0; + } // Check the length of the packet - packet_len = packet_len_table[cmd-0x3800]; - if (packet_len==-1) { - if (RFIFOREST(fd)<4) - return 2; - packet_len = RFIFOW(fd,2); - } - if ((int)RFIFOREST(fd)<packet_len) { - return 2; - } + packet_len = packet_len_table[cmd-0x3800]; + if(packet_len==-1){ + if(RFIFOREST(fd)<4) + return 2; + packet_len = RFIFOW(fd,2); + } + if((int)RFIFOREST(fd)<packet_len){ + return 2; + } // Processing branch - switch (cmd) { - case 0x3800: - if (RFIFOL(fd,4) == 0xFF000000) //Normal announce. - clif_broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, 0, ALL_CLIENT); - else if (RFIFOL(fd,4) == 0xFE000000) //Main chat message [LuzZza] - clif_MainChatMessage((char *)RFIFOP(fd,16)); - else //Color announce. - clif_broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT); - break; - case 0x3801: - intif_parse_WisMessage(fd); - break; - case 0x3802: - intif_parse_WisEnd(fd); - break; - case 0x3803: - mapif_parse_WisToGM(fd); - break; - case 0x3804: - intif_parse_Registers(fd); - break; - case 0x3806: - intif_parse_ChangeNameOk(fd); - break; - case 0x3807: - intif_parse_MessageToFD(fd); - break; - case 0x3818: - intif_parse_LoadGuildStorage(fd); - break; - case 0x3819: - intif_parse_SaveGuildStorage(fd); - break; - case 0x3820: - intif_parse_PartyCreated(fd); - break; - case 0x3821: - intif_parse_PartyInfo(fd); - break; - case 0x3822: - intif_parse_PartyMemberAdded(fd); - break; - case 0x3823: - intif_parse_PartyOptionChanged(fd); - break; - case 0x3824: - intif_parse_PartyMemberWithdraw(fd); - break; - case 0x3825: - intif_parse_PartyMove(fd); - break; - case 0x3826: - intif_parse_PartyBroken(fd); - break; - case 0x3827: - intif_parse_PartyMessage(fd); - break; - case 0x3830: - intif_parse_GuildCreated(fd); - break; - case 0x3831: - intif_parse_GuildInfo(fd); - break; - case 0x3832: - intif_parse_GuildMemberAdded(fd); - break; - case 0x3834: - intif_parse_GuildMemberWithdraw(fd); - break; - case 0x3835: - intif_parse_GuildMemberInfoShort(fd); - break; - case 0x3836: - intif_parse_GuildBroken(fd); - break; - case 0x3837: - intif_parse_GuildMessage(fd); - break; - case 0x3839: - intif_parse_GuildBasicInfoChanged(fd); - break; - case 0x383a: - intif_parse_GuildMemberInfoChanged(fd); - break; - case 0x383b: - intif_parse_GuildPosition(fd); - break; - case 0x383c: - intif_parse_GuildSkillUp(fd); - break; - case 0x383d: - intif_parse_GuildAlliance(fd); - break; - case 0x383e: - intif_parse_GuildNotice(fd); - break; - case 0x383f: - intif_parse_GuildEmblem(fd); - break; - case 0x3840: - intif_parse_GuildCastleDataLoad(fd); - break; - case 0x3843: - intif_parse_GuildMasterChanged(fd); - break; - - //Quest system - case 0x3860: - intif_parse_questlog(fd); - break; - case 0x3861: - intif_parse_questsave(fd); - break; - - // Mail System - case 0x3848: - intif_parse_Mail_inboxreceived(fd); - break; - case 0x3849: - intif_parse_Mail_new(fd); - break; - case 0x384a: - intif_parse_Mail_getattach(fd); - break; - case 0x384b: - intif_parse_Mail_delete(fd); - break; - case 0x384c: - intif_parse_Mail_return(fd); - break; - case 0x384d: - intif_parse_Mail_send(fd); - break; - // Auction System - case 0x3850: - intif_parse_Auction_results(fd); - break; - case 0x3851: - intif_parse_Auction_register(fd); - break; - case 0x3852: - intif_parse_Auction_cancel(fd); - break; - case 0x3853: - intif_parse_Auction_close(fd); - break; - case 0x3854: - intif_parse_Auction_message(fd); - break; - case 0x3855: - intif_parse_Auction_bid(fd); - break; - - // Mercenary System - case 0x3870: - intif_parse_mercenary_received(fd); - break; - case 0x3871: - intif_parse_mercenary_deleted(fd); - break; - case 0x3872: - intif_parse_mercenary_saved(fd); - break; - // Elemental System - case 0x387c: - intif_parse_elemental_received(fd); - break; - case 0x387d: - intif_parse_elemental_deleted(fd); - break; - case 0x387e: - intif_parse_elemental_saved(fd); - break; - - case 0x3880: - intif_parse_CreatePet(fd); - break; - case 0x3881: - intif_parse_RecvPetData(fd); - break; - case 0x3882: - intif_parse_SavePetOk(fd); - break; - case 0x3883: - intif_parse_DeletePetOk(fd); - break; - case 0x3890: - intif_parse_CreateHomunculus(fd); - break; - case 0x3891: - intif_parse_RecvHomunculusData(fd); - break; - case 0x3892: - intif_parse_SaveHomunculusOk(fd); - break; - case 0x3893: - intif_parse_DeleteHomunculusOk(fd); - break; - default: - ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0)); - return 0; - } + switch(cmd){ + case 0x3800: + if (RFIFOL(fd,4) == 0xFF000000) //Normal announce. + clif_broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, 0, ALL_CLIENT); + else if (RFIFOL(fd,4) == 0xFE000000) //Main chat message [LuzZza] + clif_MainChatMessage((char *)RFIFOP(fd,16)); + else //Color announce. + clif_broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT); + break; + case 0x3801: intif_parse_WisMessage(fd); break; + case 0x3802: intif_parse_WisEnd(fd); break; + case 0x3803: mapif_parse_WisToGM(fd); break; + case 0x3804: intif_parse_Registers(fd); break; + case 0x3806: intif_parse_ChangeNameOk(fd); break; + case 0x3807: intif_parse_MessageToFD(fd); break; + case 0x3818: intif_parse_LoadGuildStorage(fd); break; + case 0x3819: intif_parse_SaveGuildStorage(fd); break; + case 0x3820: intif_parse_PartyCreated(fd); break; + case 0x3821: intif_parse_PartyInfo(fd); break; + case 0x3822: intif_parse_PartyMemberAdded(fd); break; + case 0x3823: intif_parse_PartyOptionChanged(fd); break; + case 0x3824: intif_parse_PartyMemberWithdraw(fd); break; + case 0x3825: intif_parse_PartyMove(fd); break; + case 0x3826: intif_parse_PartyBroken(fd); break; + case 0x3827: intif_parse_PartyMessage(fd); break; + case 0x3830: intif_parse_GuildCreated(fd); break; + case 0x3831: intif_parse_GuildInfo(fd); break; + case 0x3832: intif_parse_GuildMemberAdded(fd); break; + case 0x3834: intif_parse_GuildMemberWithdraw(fd); break; + case 0x3835: intif_parse_GuildMemberInfoShort(fd); break; + case 0x3836: intif_parse_GuildBroken(fd); break; + case 0x3837: intif_parse_GuildMessage(fd); break; + case 0x3839: intif_parse_GuildBasicInfoChanged(fd); break; + case 0x383a: intif_parse_GuildMemberInfoChanged(fd); break; + case 0x383b: intif_parse_GuildPosition(fd); break; + case 0x383c: intif_parse_GuildSkillUp(fd); break; + case 0x383d: intif_parse_GuildAlliance(fd); break; + case 0x383e: intif_parse_GuildNotice(fd); break; + case 0x383f: intif_parse_GuildEmblem(fd); break; + case 0x3840: intif_parse_GuildCastleDataLoad(fd); break; + case 0x3843: intif_parse_GuildMasterChanged(fd); break; + + //Quest system + case 0x3860: intif_parse_questlog(fd); break; + case 0x3861: intif_parse_questsave(fd); break; + +// Mail System + case 0x3848: intif_parse_Mail_inboxreceived(fd); break; + case 0x3849: intif_parse_Mail_new(fd); break; + case 0x384a: intif_parse_Mail_getattach(fd); break; + case 0x384b: intif_parse_Mail_delete(fd); break; + case 0x384c: intif_parse_Mail_return(fd); break; + case 0x384d: intif_parse_Mail_send(fd); break; +// Auction System + case 0x3850: intif_parse_Auction_results(fd); break; + case 0x3851: intif_parse_Auction_register(fd); break; + case 0x3852: intif_parse_Auction_cancel(fd); break; + case 0x3853: intif_parse_Auction_close(fd); break; + case 0x3854: intif_parse_Auction_message(fd); break; + case 0x3855: intif_parse_Auction_bid(fd); break; + +// Mercenary System + case 0x3870: intif_parse_mercenary_received(fd); break; + case 0x3871: intif_parse_mercenary_deleted(fd); break; + case 0x3872: intif_parse_mercenary_saved(fd); break; +// Elemental System + case 0x387c: intif_parse_elemental_received(fd); break; + case 0x387d: intif_parse_elemental_deleted(fd); break; + case 0x387e: intif_parse_elemental_saved(fd); break; + + case 0x3880: intif_parse_CreatePet(fd); break; + case 0x3881: intif_parse_RecvPetData(fd); break; + case 0x3882: intif_parse_SavePetOk(fd); break; + case 0x3883: intif_parse_DeletePetOk(fd); break; + case 0x3890: intif_parse_CreateHomunculus(fd); break; + case 0x3891: intif_parse_RecvHomunculusData(fd); break; + case 0x3892: intif_parse_SaveHomunculusOk(fd); break; + case 0x3893: intif_parse_DeleteHomunculusOk(fd); break; + default: + ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0)); + return 0; + } // Skip packet - RFIFOSKIP(fd,packet_len); - return 1; + RFIFOSKIP(fd,packet_len); + return 1; } diff --git a/src/map/intif.h b/src/map/intif.h index 623f37ba0..081667545 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -17,9 +17,9 @@ struct auction_data; int intif_parse(int fd); -int intif_broadcast(const char *mes, int len, int type); -int intif_broadcast2(const char *mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY); -int intif_main_message(struct map_session_data *sd, const char *message); +int intif_broadcast(const char* mes, int len, int type); +int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY); +int intif_main_message(struct map_session_data* sd, const char* message); 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 permission, char *mes); @@ -50,7 +50,7 @@ int intif_guild_leave(int guild_id, int account_id, int char_id, int flag, const 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, const char *mes, int len); -int intif_guild_change_gm(int guild_id, const char *name, int len); +int intif_guild_change_gm(int guild_id, const char* name, int len); 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); int intif_guild_position(int guild_id, int idx, struct guild_position *p); @@ -72,12 +72,12 @@ int intif_rename(struct map_session_data *sd, int type, char *name); #define intif_rename_hom(sd, name) intif_rename(sd, 2, name) int intif_homunculus_create(int account_id, struct s_homunculus *sh); int intif_homunculus_requestload(int account_id, int homun_id); -int intif_homunculus_requestsave(int account_id, struct s_homunculus *sh); +int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh); int intif_homunculus_requestdelete(int homun_id); /******QUEST SYTEM*******/ -int intif_request_questlog(struct map_session_data *sd); -int intif_quest_save(struct map_session_data *sd); +int intif_request_questlog(struct map_session_data * sd); +int intif_quest_save(struct map_session_data * sd); // MERCENARY SYSTEM int intif_mercenary_create(struct s_mercenary *merc); @@ -93,11 +93,11 @@ int intif_Mail_delete(int char_id, int mail_id); int intif_Mail_return(int char_id, int mail_id); int intif_Mail_send(int account_id, struct mail_message *msg); // AUCTION SYSTEM -int intif_Auction_requestlist(int char_id, short type, int price, const char *searchtext, short page); +int intif_Auction_requestlist(int char_id, short type, int price, const char* searchtext, short page); int intif_Auction_register(struct auction_data *auction); int intif_Auction_cancel(int char_id, unsigned int auction_id); int intif_Auction_close(int char_id, unsigned int auction_id); -int intif_Auction_bid(int char_id, const char *name, unsigned int auction_id, int bid); +int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, int bid); // ELEMENTAL SYSTEM int intif_elemental_create(struct s_elemental *ele); int intif_elemental_request(int ele_id, int char_id); @@ -105,7 +105,7 @@ int intif_elemental_delete(int ele_id); int intif_elemental_save(struct s_elemental *ele); /* @accinfo */ -void intif_request_accinfo(int u_fd, int aid, int group_id, char *query); +void intif_request_accinfo( int u_fd, int aid, int group_id, char* query ); int CheckForCharServer(void); diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 18f8f5c07..e0c964de3 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -17,64 +17,66 @@ #include <stdlib.h> #include <string.h> -static struct item_data *itemdb_array[MAX_ITEMDB]; -static DBMap *itemdb_other;// int nameid -> struct item_data* +static struct item_data* itemdb_array[MAX_ITEMDB]; +static DBMap* itemdb_other;// int nameid -> struct item_data* static struct item_group itemgroup_db[MAX_ITEMGROUP]; struct item_data dummy_item; //This is the default dummy item used for non-existant items. [Skotlex] /** - * Search for item name + * Search for item name * name = item alias, so we should find items aliases first. if not found then look for "jname" (full name) * @see DBApply */ static int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap) { - struct item_data *item = db_data2ptr(data), **dst, **dst2; - char *str; - str=va_arg(ap,char *); - dst=va_arg(ap,struct item_data **); - dst2=va_arg(ap,struct item_data **); - if (item == &dummy_item) return 0; - - //Absolute priority to Aegis code name. - if (*dst != NULL) return 0; - if (strcmpi(item->name,str)==0) - *dst=item; - - //Second priority to Client displayed name. - if (*dst2 != NULL) return 0; - if (strcmpi(item->jname,str)==0) - *dst2=item; - return 0; + struct item_data *item = db_data2ptr(data), **dst, **dst2; + char *str; + str=va_arg(ap,char *); + dst=va_arg(ap,struct item_data **); + dst2=va_arg(ap,struct item_data **); + if(item == &dummy_item) return 0; + + //Absolute priority to Aegis code name. + if (*dst != NULL) return 0; + if( strcmpi(item->name,str)==0 ) + *dst=item; + + //Second priority to Client displayed name. + if (*dst2 != NULL) return 0; + if( strcmpi(item->jname,str)==0 ) + *dst2=item; + return 0; } /*========================================== - * Return item data from item name. (lookup) + * Return item data from item name. (lookup) *------------------------------------------*/ -struct item_data *itemdb_searchname(const char *str) { - struct item_data *item; - struct item_data *item2=NULL; - int i; - - for (i = 0; i < ARRAYLENGTH(itemdb_array); ++i) { - item = itemdb_array[i]; - if (item == NULL) - continue; - - // Absolute priority to Aegis code name. - if (strcasecmp(item->name,str) == 0) - return item; - - //Second priority to Client displayed name. - if (strcasecmp(item->jname,str) == 0) - item2 = item; - } - - item = NULL; - itemdb_other->foreach(itemdb_other,itemdb_searchname_sub,str,&item,&item2); - return item?item:item2; +struct item_data* itemdb_searchname(const char *str) +{ + struct item_data* item; + struct item_data* item2=NULL; + int i; + + for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) + { + item = itemdb_array[i]; + if( item == NULL ) + continue; + + // Absolute priority to Aegis code name. + if( strcasecmp(item->name,str) == 0 ) + return item; + + //Second priority to Client displayed name. + if( strcasecmp(item->jname,str) == 0 ) + item2 = item; + } + + item = NULL; + itemdb_other->foreach(itemdb_other,itemdb_searchname_sub,str,&item,&item2); + return item?item:item2; } /** @@ -82,258 +84,258 @@ struct item_data *itemdb_searchname(const char *str) { */ static int itemdb_searchname_array_sub(DBKey key, DBData data, va_list ap) { - struct item_data *item = db_data2ptr(&data); - char *str; - str=va_arg(ap,char *); - if (item == &dummy_item) - return 1; //Invalid item. - if (stristr(item->jname,str)) - return 0; - if (stristr(item->name,str)) - return 0; - return strcmpi(item->jname,str); + struct item_data *item = db_data2ptr(&data); + char *str; + str=va_arg(ap,char *); + if (item == &dummy_item) + return 1; //Invalid item. + if(stristr(item->jname,str)) + return 0; + if(stristr(item->name,str)) + return 0; + return strcmpi(item->jname,str); } /*========================================== * Founds up to N matches. Returns number of matches [Skotlex] *------------------------------------------*/ -int itemdb_searchname_array(struct item_data **data, int size, const char *str) +int itemdb_searchname_array(struct item_data** data, int size, const char *str) { - struct item_data *item; - int i; - int count=0; - - // Search in the array - for (i = 0; i < ARRAYLENGTH(itemdb_array); ++i) { - item = itemdb_array[i]; - if (item == NULL) - continue; - - if (stristr(item->jname,str) || stristr(item->name,str)) { - if (count < size) - data[count] = item; - ++count; - } - } - - // search in the db - if (count < size) { - DBData *db_data[MAX_SEARCH]; - int db_count = 0; - size -= count; - db_count = itemdb_other->getall(itemdb_other, (DBData **)&db_data, size, itemdb_searchname_array_sub, str); - for (i = 0; i < db_count; i++) - data[count++] = db_data2ptr(db_data[i]); - count += db_count; - } - return count; + struct item_data* item; + int i; + int count=0; + + // Search in the array + for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) + { + item = itemdb_array[i]; + if( item == NULL ) + continue; + + if( stristr(item->jname,str) || stristr(item->name,str) ) + { + if( count < size ) + data[count] = item; + ++count; + } + } + + // search in the db + if( count < size ) + { + DBData *db_data[MAX_SEARCH]; + int db_count = 0; + size -= count; + db_count = itemdb_other->getall(itemdb_other, (DBData**)&db_data, size, itemdb_searchname_array_sub, str); + for (i = 0; i < db_count; i++) + data[count++] = db_data2ptr(db_data[i]); + count += db_count; + } + return count; } /*========================================== - * Return a random item id from group. (takes into account % chance giving/tot group) + * Return a random item id from group. (takes into account % chance giving/tot group) *------------------------------------------*/ int itemdb_searchrandomid(int group) { - if (group<1 || group>=MAX_ITEMGROUP) { - ShowError("itemdb_searchrandomid: Invalid group id %d\n", group); - return UNKNOWN_ITEM_ID; - } - if (itemgroup_db[group].qty) - return itemgroup_db[group].nameid[rnd()%itemgroup_db[group].qty]; - - ShowError("itemdb_searchrandomid: No item entries for group id %d\n", group); - return UNKNOWN_ITEM_ID; + if(group<1 || group>=MAX_ITEMGROUP) { + ShowError("itemdb_searchrandomid: Invalid group id %d\n", group); + return UNKNOWN_ITEM_ID; + } + if (itemgroup_db[group].qty) + return itemgroup_db[group].nameid[rnd()%itemgroup_db[group].qty]; + + ShowError("itemdb_searchrandomid: No item entries for group id %d\n", group); + return UNKNOWN_ITEM_ID; } /*========================================== * Calculates total item-group related bonuses for the given item *------------------------------------------*/ -int itemdb_group_bonus(struct map_session_data *sd, int itemid) +int itemdb_group_bonus(struct map_session_data* sd, int itemid) { - int bonus = 0, i, j; - for (i=0; i < MAX_ITEMGROUP; i++) { - if (!sd->itemgrouphealrate[i]) - continue; - ARR_FIND(0, itemgroup_db[i].qty, j, itemgroup_db[i].nameid[j] == itemid); - if (j < itemgroup_db[i].qty) - bonus += sd->itemgrouphealrate[i]; - } - return bonus; + int bonus = 0, i, j; + for (i=0; i < MAX_ITEMGROUP; i++) { + if (!sd->itemgrouphealrate[i]) + continue; + ARR_FIND( 0, itemgroup_db[i].qty, j, itemgroup_db[i].nameid[j] == itemid ); + if( j < itemgroup_db[i].qty ) + bonus += sd->itemgrouphealrate[i]; + } + return bonus; } /// Searches for the item_data. /// Returns the item_data or NULL if it does not exist. -struct item_data *itemdb_exists(int nameid) { - struct item_data *item; - - if (nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array)) - return itemdb_array[nameid]; - item = (struct item_data *)idb_get(itemdb_other,nameid); - if (item == &dummy_item) - return NULL;// dummy data, doesn't exist - return item; +struct item_data* itemdb_exists(int nameid) +{ + struct item_data* item; + + if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) ) + return itemdb_array[nameid]; + item = (struct item_data*)idb_get(itemdb_other,nameid); + if( item == &dummy_item ) + return NULL;// dummy data, doesn't exist + return item; } /// Returns human readable name for given item type. /// @param type Type id to retrieve name for ( IT_* ). -const char *itemdb_typename(int type) +const char* itemdb_typename(int type) { - switch (type) { - case IT_HEALING: - return "Potion/Food"; - case IT_USABLE: - return "Usable"; - case IT_ETC: - return "Etc."; - case IT_WEAPON: - return "Weapon"; - case IT_ARMOR: - return "Armor"; - case IT_CARD: - return "Card"; - case IT_PETEGG: - return "Pet Egg"; - case IT_PETARMOR: - return "Pet Accessory"; - case IT_AMMO: - return "Arrow/Ammunition"; - case IT_DELAYCONSUME: - return "Delay-Consume Usable"; - case IT_CASH: - return "Cash Usable"; - } - return "Unknown Type"; + switch(type) + { + case IT_HEALING: return "Potion/Food"; + case IT_USABLE: return "Usable"; + case IT_ETC: return "Etc."; + case IT_WEAPON: return "Weapon"; + case IT_ARMOR: return "Armor"; + case IT_CARD: return "Card"; + case IT_PETEGG: return "Pet Egg"; + case IT_PETARMOR: return "Pet Accessory"; + case IT_AMMO: return "Arrow/Ammunition"; + case IT_DELAYCONSUME: return "Delay-Consume Usable"; + case IT_CASH: return "Cash Usable"; + } + return "Unknown Type"; } /*========================================== - * Converts the jobid from the format in itemdb + * Converts the jobid from the format in itemdb * to the format used by the map server. [Skotlex] *------------------------------------------*/ static void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask) { - int i; - bclass[0]= bclass[1]= bclass[2]= 0; - //Base classes - if (jobmask & 1<<JOB_NOVICE) { - //Both Novice/Super-Novice are counted with the same ID - bclass[0] |= 1<<MAPID_NOVICE; - bclass[1] |= 1<<MAPID_NOVICE; - } - for (i = JOB_NOVICE+1; i <= JOB_THIEF; i++) { - if (jobmask & 1<<i) - bclass[0] |= 1<<(MAPID_NOVICE+i); - } - //2-1 classes - if (jobmask & 1<<JOB_KNIGHT) - bclass[1] |= 1<<MAPID_SWORDMAN; - if (jobmask & 1<<JOB_PRIEST) - bclass[1] |= 1<<MAPID_ACOLYTE; - if (jobmask & 1<<JOB_WIZARD) - bclass[1] |= 1<<MAPID_MAGE; - if (jobmask & 1<<JOB_BLACKSMITH) - bclass[1] |= 1<<MAPID_MERCHANT; - if (jobmask & 1<<JOB_HUNTER) - bclass[1] |= 1<<MAPID_ARCHER; - if (jobmask & 1<<JOB_ASSASSIN) - bclass[1] |= 1<<MAPID_THIEF; - //2-2 classes - if (jobmask & 1<<JOB_CRUSADER) - bclass[2] |= 1<<MAPID_SWORDMAN; - if (jobmask & 1<<JOB_MONK) - bclass[2] |= 1<<MAPID_ACOLYTE; - if (jobmask & 1<<JOB_SAGE) - bclass[2] |= 1<<MAPID_MAGE; - if (jobmask & 1<<JOB_ALCHEMIST) - bclass[2] |= 1<<MAPID_MERCHANT; - if (jobmask & 1<<JOB_BARD) - bclass[2] |= 1<<MAPID_ARCHER; - // Bard/Dancer share the same slot now. - // if (jobmask & 1<<JOB_DANCER) - // bclass[2] |= 1<<MAPID_ARCHER; - if (jobmask & 1<<JOB_ROGUE) - bclass[2] |= 1<<MAPID_THIEF; - //Special classes that don't fit above. - if (jobmask & 1<<21) //Taekwon boy - bclass[0] |= 1<<MAPID_TAEKWON; - if (jobmask & 1<<22) //Star Gladiator - bclass[1] |= 1<<MAPID_TAEKWON; - if (jobmask & 1<<23) //Soul Linker - bclass[2] |= 1<<MAPID_TAEKWON; - if (jobmask & 1<<JOB_GUNSLINGER) - bclass[0] |= 1<<MAPID_GUNSLINGER; - if (jobmask & 1<<JOB_NINJA) { - bclass[0] |= 1<<MAPID_NINJA; - bclass[1] |= 1<<MAPID_NINJA; - }//Kagerou/Oboro jobs can equip Ninja equips. [Rytech] - if (jobmask & 1<<26) //Bongun/Munak - bclass[0] |= 1<<MAPID_GANGSI; - if (jobmask & 1<<27) //Death Knight - bclass[1] |= 1<<MAPID_GANGSI; - if (jobmask & 1<<28) //Dark Collector - bclass[2] |= 1<<MAPID_GANGSI; - if (jobmask & 1<<29) //Kagerou / Oboro - bclass[1] |= 1<<MAPID_NINJA; + int i; + bclass[0]= bclass[1]= bclass[2]= 0; + //Base classes + if (jobmask & 1<<JOB_NOVICE) + { //Both Novice/Super-Novice are counted with the same ID + bclass[0] |= 1<<MAPID_NOVICE; + bclass[1] |= 1<<MAPID_NOVICE; + } + for (i = JOB_NOVICE+1; i <= JOB_THIEF; i++) + { + if (jobmask & 1<<i) + bclass[0] |= 1<<(MAPID_NOVICE+i); + } + //2-1 classes + if (jobmask & 1<<JOB_KNIGHT) + bclass[1] |= 1<<MAPID_SWORDMAN; + if (jobmask & 1<<JOB_PRIEST) + bclass[1] |= 1<<MAPID_ACOLYTE; + if (jobmask & 1<<JOB_WIZARD) + bclass[1] |= 1<<MAPID_MAGE; + if (jobmask & 1<<JOB_BLACKSMITH) + bclass[1] |= 1<<MAPID_MERCHANT; + if (jobmask & 1<<JOB_HUNTER) + bclass[1] |= 1<<MAPID_ARCHER; + if (jobmask & 1<<JOB_ASSASSIN) + bclass[1] |= 1<<MAPID_THIEF; + //2-2 classes + if (jobmask & 1<<JOB_CRUSADER) + bclass[2] |= 1<<MAPID_SWORDMAN; + if (jobmask & 1<<JOB_MONK) + bclass[2] |= 1<<MAPID_ACOLYTE; + if (jobmask & 1<<JOB_SAGE) + bclass[2] |= 1<<MAPID_MAGE; + if (jobmask & 1<<JOB_ALCHEMIST) + bclass[2] |= 1<<MAPID_MERCHANT; + if (jobmask & 1<<JOB_BARD) + bclass[2] |= 1<<MAPID_ARCHER; +// Bard/Dancer share the same slot now. +// if (jobmask & 1<<JOB_DANCER) +// bclass[2] |= 1<<MAPID_ARCHER; + if (jobmask & 1<<JOB_ROGUE) + bclass[2] |= 1<<MAPID_THIEF; + //Special classes that don't fit above. + if (jobmask & 1<<21) //Taekwon boy + bclass[0] |= 1<<MAPID_TAEKWON; + if (jobmask & 1<<22) //Star Gladiator + bclass[1] |= 1<<MAPID_TAEKWON; + if (jobmask & 1<<23) //Soul Linker + bclass[2] |= 1<<MAPID_TAEKWON; + if (jobmask & 1<<JOB_GUNSLINGER) + bclass[0] |= 1<<MAPID_GUNSLINGER; + if (jobmask & 1<<JOB_NINJA) + {bclass[0] |= 1<<MAPID_NINJA; + bclass[1] |= 1<<MAPID_NINJA;}//Kagerou/Oboro jobs can equip Ninja equips. [Rytech] + if (jobmask & 1<<26) //Bongun/Munak + bclass[0] |= 1<<MAPID_GANGSI; + if (jobmask & 1<<27) //Death Knight + bclass[1] |= 1<<MAPID_GANGSI; + if (jobmask & 1<<28) //Dark Collector + bclass[2] |= 1<<MAPID_GANGSI; + if (jobmask & 1<<29) //Kagerou / Oboro + bclass[1] |= 1<<MAPID_NINJA; } static void create_dummy_data(void) { - memset(&dummy_item, 0, sizeof(struct item_data)); - dummy_item.nameid=500; - dummy_item.weight=1; - dummy_item.value_sell=1; - dummy_item.type=IT_ETC; //Etc item - safestrncpy(dummy_item.name,"UNKNOWN_ITEM",sizeof(dummy_item.name)); - safestrncpy(dummy_item.jname,"UNKNOWN_ITEM",sizeof(dummy_item.jname)); - dummy_item.view_id=UNKNOWN_ITEM_ID; + memset(&dummy_item, 0, sizeof(struct item_data)); + dummy_item.nameid=500; + dummy_item.weight=1; + dummy_item.value_sell=1; + dummy_item.type=IT_ETC; //Etc item + safestrncpy(dummy_item.name,"UNKNOWN_ITEM",sizeof(dummy_item.name)); + safestrncpy(dummy_item.jname,"UNKNOWN_ITEM",sizeof(dummy_item.jname)); + dummy_item.view_id=UNKNOWN_ITEM_ID; } -static struct item_data *create_item_data(int nameid) { - struct item_data *id; - CREATE(id, struct item_data, 1); - id->nameid = nameid; - id->weight = 1; - id->type = IT_ETC; - return id; +static struct item_data* create_item_data(int nameid) +{ + struct item_data *id; + CREATE(id, struct item_data, 1); + id->nameid = nameid; + id->weight = 1; + id->type = IT_ETC; + return id; } /*========================================== * Loads (and creates if not found) an item from the db. *------------------------------------------*/ -struct item_data *itemdb_load(int nameid) { - struct item_data *id; - - if (nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array)) { - id = itemdb_array[nameid]; - if (id == NULL || id == &dummy_item) - id = itemdb_array[nameid] = create_item_data(nameid); - return id; - } - - id = (struct item_data *)idb_get(itemdb_other, nameid); - if (id == NULL || id == &dummy_item) { - id = create_item_data(nameid); - idb_put(itemdb_other, nameid, id); - } - return id; +struct item_data* itemdb_load(int nameid) +{ + struct item_data *id; + + if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) ) + { + id = itemdb_array[nameid]; + if( id == NULL || id == &dummy_item ) + id = itemdb_array[nameid] = create_item_data(nameid); + return id; + } + + id = (struct item_data*)idb_get(itemdb_other, nameid); + if( id == NULL || id == &dummy_item ) + { + id = create_item_data(nameid); + idb_put(itemdb_other, nameid, id); + } + return id; } /*========================================== * Loads an item from the db. If not found, it will return the dummy item. *------------------------------------------*/ -struct item_data *itemdb_search(int nameid) { - struct item_data *id; - if (nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array)) - id = itemdb_array[nameid]; - else - id = (struct item_data *)idb_get(itemdb_other, nameid); - - if (id == NULL) { - ShowWarning("itemdb_search: Item ID %d does not exists in the item_db. Using dummy data.\n", nameid); - id = &dummy_item; - dummy_item.nameid = nameid; - } - return id; +struct item_data* itemdb_search(int nameid) +{ + struct item_data* id; + if( nameid >= 0 && nameid < ARRAYLENGTH(itemdb_array) ) + id = itemdb_array[nameid]; + else + id = (struct item_data*)idb_get(itemdb_other, nameid); + + if( id == NULL ) + { + ShowWarning("itemdb_search: Item ID %d does not exists in the item_db. Using dummy data.\n", nameid); + id = &dummy_item; + dummy_item.nameid = nameid; + } + return id; } /*========================================== @@ -341,31 +343,31 @@ struct item_data *itemdb_search(int nameid) { *------------------------------------------*/ int itemdb_isequip(int nameid) { - int type=itemdb_type(nameid); - switch (type) { - case IT_WEAPON: - case IT_ARMOR: - case IT_AMMO: - return 1; - default: - return 0; - } + int type=itemdb_type(nameid); + switch (type) { + case IT_WEAPON: + case IT_ARMOR: + case IT_AMMO: + return 1; + default: + return 0; + } } /*========================================== * Alternate version of itemdb_isequip *------------------------------------------*/ int itemdb_isequip2(struct item_data *data) -{ - nullpo_ret(data); - switch (data->type) { - case IT_WEAPON: - case IT_ARMOR: - case IT_AMMO: - return 1; - default: - return 0; - } +{ + nullpo_ret(data); + switch(data->type) { + case IT_WEAPON: + case IT_ARMOR: + case IT_AMMO: + return 1; + default: + return 0; + } } /*========================================== @@ -373,16 +375,16 @@ int itemdb_isequip2(struct item_data *data) *------------------------------------------*/ int itemdb_isstackable(int nameid) { - int type=itemdb_type(nameid); - switch (type) { - case IT_WEAPON: - case IT_ARMOR: - case IT_PETEGG: - case IT_PETARMOR: - return 0; - default: - return 1; - } + int type=itemdb_type(nameid); + switch(type) { + case IT_WEAPON: + case IT_ARMOR: + case IT_PETEGG: + case IT_PETARMOR: + return 0; + default: + return 1; + } } /*========================================== @@ -390,515 +392,513 @@ int itemdb_isstackable(int nameid) *------------------------------------------*/ int itemdb_isstackable2(struct item_data *data) { - nullpo_ret(data); - switch (data->type) { - case IT_WEAPON: - case IT_ARMOR: - case IT_PETEGG: - case IT_PETARMOR: - return 0; - default: - return 1; - } + nullpo_ret(data); + switch(data->type) { + case IT_WEAPON: + case IT_ARMOR: + case IT_PETEGG: + case IT_PETARMOR: + return 0; + default: + return 1; + } } /*========================================== * Trade Restriction functions [Skotlex] *------------------------------------------*/ -int itemdb_isdropable_sub(struct item_data *item, int gmlv, int unused) -{ - return (item && (!(item->flag.trade_restriction&1) || gmlv >= item->gm_lv_trade_override)); +int itemdb_isdropable_sub(struct item_data *item, int gmlv, int unused) { + return (item && (!(item->flag.trade_restriction&1) || gmlv >= item->gm_lv_trade_override)); } -int itemdb_cantrade_sub(struct item_data *item, int gmlv, int gmlv2) -{ - return (item && (!(item->flag.trade_restriction&2) || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override)); +int itemdb_cantrade_sub(struct item_data* item, int gmlv, int gmlv2) { + return (item && (!(item->flag.trade_restriction&2) || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override)); } -int itemdb_canpartnertrade_sub(struct item_data *item, int gmlv, int gmlv2) -{ - return (item && (item->flag.trade_restriction&4 || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override)); +int itemdb_canpartnertrade_sub(struct item_data* item, int gmlv, int gmlv2) { + return (item && (item->flag.trade_restriction&4 || gmlv >= item->gm_lv_trade_override || gmlv2 >= item->gm_lv_trade_override)); } -int itemdb_cansell_sub(struct item_data *item, int gmlv, int unused) -{ - return (item && (!(item->flag.trade_restriction&8) || gmlv >= item->gm_lv_trade_override)); +int itemdb_cansell_sub(struct item_data* item, int gmlv, int unused) { + return (item && (!(item->flag.trade_restriction&8) || gmlv >= item->gm_lv_trade_override)); } -int itemdb_cancartstore_sub(struct item_data *item, int gmlv, int unused) -{ - return (item && (!(item->flag.trade_restriction&16) || gmlv >= item->gm_lv_trade_override)); +int itemdb_cancartstore_sub(struct item_data* item, int gmlv, int unused) { + return (item && (!(item->flag.trade_restriction&16) || gmlv >= item->gm_lv_trade_override)); } -int itemdb_canstore_sub(struct item_data *item, int gmlv, int unused) -{ - return (item && (!(item->flag.trade_restriction&32) || gmlv >= item->gm_lv_trade_override)); +int itemdb_canstore_sub(struct item_data* item, int gmlv, int unused) { + return (item && (!(item->flag.trade_restriction&32) || gmlv >= item->gm_lv_trade_override)); } -int itemdb_canguildstore_sub(struct item_data *item, int gmlv, int unused) -{ - return (item && (!(item->flag.trade_restriction&64) || gmlv >= item->gm_lv_trade_override)); +int itemdb_canguildstore_sub(struct item_data* item, int gmlv, int unused) { + return (item && (!(item->flag.trade_restriction&64) || gmlv >= item->gm_lv_trade_override)); } -int itemdb_canmail_sub(struct item_data *item, int gmlv, int unused) -{ - return (item && (!(item->flag.trade_restriction&128) || gmlv >= item->gm_lv_trade_override)); +int itemdb_canmail_sub(struct item_data* item, int gmlv, int unused) { + return (item && (!(item->flag.trade_restriction&128) || gmlv >= item->gm_lv_trade_override)); } -int itemdb_canauction_sub(struct item_data *item, int gmlv, int unused) -{ - return (item && (!(item->flag.trade_restriction&256) || gmlv >= item->gm_lv_trade_override)); +int itemdb_canauction_sub(struct item_data* item, int gmlv, int unused) { + return (item && (!(item->flag.trade_restriction&256) || gmlv >= item->gm_lv_trade_override)); } -int itemdb_isrestricted(struct item *item, int gmlv, int gmlv2, int (*func)(struct item_data *, int, int)) +int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(struct item_data*, int, int)) { - struct item_data *item_data = itemdb_search(item->nameid); - int i; - - if (!func(item_data, gmlv, gmlv2)) - return 0; - - if (item_data->slot == 0 || itemdb_isspecial(item->card[0])) - return 1; - - for (i = 0; i < item_data->slot; i++) { - if (!item->card[i]) continue; - if (!func(itemdb_search(item->card[i]), gmlv, gmlv2)) - return 0; - } - return 1; + struct item_data* item_data = itemdb_search(item->nameid); + int i; + + if (!func(item_data, gmlv, gmlv2)) + return 0; + + if(item_data->slot == 0 || itemdb_isspecial(item->card[0])) + return 1; + + for(i = 0; i < item_data->slot; i++) { + if (!item->card[i]) continue; + if (!func(itemdb_search(item->card[i]), gmlv, gmlv2)) + return 0; + } + return 1; } /*========================================== - * Specifies if item-type should drop unidentified. + * Specifies if item-type should drop unidentified. *------------------------------------------*/ int itemdb_isidentified(int nameid) { - int type=itemdb_type(nameid); - switch (type) { - case IT_WEAPON: - case IT_ARMOR: - case IT_PETARMOR: - return 0; - default: - return 1; - } + int type=itemdb_type(nameid); + switch (type) { + case IT_WEAPON: + case IT_ARMOR: + case IT_PETARMOR: + return 0; + default: + return 1; + } } /*========================================== * Search by name for the override flags available items * (Give item another sprite) *------------------------------------------*/ -static bool itemdb_read_itemavail(char *str[], int columns, int current) -{ - // <nameid>,<sprite> - int nameid, sprite; - struct item_data *id; - - nameid = atoi(str[0]); - - if ((id = itemdb_exists(nameid)) == NULL) { - ShowWarning("itemdb_read_itemavail: Invalid item id %d.\n", nameid); - return false; - } - - sprite = atoi(str[1]); - - if (sprite > 0) { - id->flag.available = 1; - id->view_id = sprite; - } else { - id->flag.available = 0; - } - - return true; +static bool itemdb_read_itemavail(char* str[], int columns, int current) +{// <nameid>,<sprite> + int nameid, sprite; + struct item_data *id; + + nameid = atoi(str[0]); + + if( ( id = itemdb_exists(nameid) ) == NULL ) + { + ShowWarning("itemdb_read_itemavail: Invalid item id %d.\n", nameid); + return false; + } + + sprite = atoi(str[1]); + + if( sprite > 0 ) + { + id->flag.available = 1; + id->view_id = sprite; + } + else + { + id->flag.available = 0; + } + + return true; } /*========================================== * read item group data *------------------------------------------*/ -static void itemdb_read_itemgroup_sub(const char *filename) +static void itemdb_read_itemgroup_sub(const char* filename) { - FILE *fp; - char line[1024]; - int ln=0; - int groupid,j,k,nameid; - char *str[3],*p; - char w1[1024], w2[1024]; - - if ((fp=fopen(filename,"r"))==NULL) { - ShowError("can't read %s\n", filename); - return; - } - - while (fgets(line, sizeof(line), fp)) { - ln++; - if (line[0]=='/' && line[1]=='/') - continue; - if (strstr(line,"import")) { - if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 && - strcmpi(w1, "import") == 0) { - itemdb_read_itemgroup_sub(w2); - continue; - } - } - memset(str,0,sizeof(str)); - for (j=0,p=line; j<3 && p; j++) { - str[j]=p; - p=strchr(p,','); - if (p) *p++=0; - } - if (str[0]==NULL) - continue; - if (j<3) { - if (j>1) //Or else it barks on blank lines... - ShowWarning("itemdb_read_itemgroup: Insufficient fields for entry at %s:%d\n", filename, ln); - continue; - } - groupid = atoi(str[0]); - if (groupid < 0 || groupid >= MAX_ITEMGROUP) { - ShowWarning("itemdb_read_itemgroup: Invalid group %d in %s:%d\n", groupid, filename, ln); - continue; - } - nameid = atoi(str[1]); - if (!itemdb_exists(nameid)) { - ShowWarning("itemdb_read_itemgroup: Non-existant item %d in %s:%d\n", nameid, filename, ln); - continue; - } - k = atoi(str[2]); - if (itemgroup_db[groupid].qty+k >= MAX_RANDITEM) { - ShowWarning("itemdb_read_itemgroup: Group %d is full (%d entries) in %s:%d\n", groupid, MAX_RANDITEM, filename, ln); - continue; - } - for (j=0; j<k; j++) - itemgroup_db[groupid].nameid[itemgroup_db[groupid].qty++] = nameid; - } - fclose(fp); - return; + FILE *fp; + char line[1024]; + int ln=0; + int groupid,j,k,nameid; + char *str[3],*p; + char w1[1024], w2[1024]; + + if( (fp=fopen(filename,"r"))==NULL ){ + ShowError("can't read %s\n", filename); + return; + } + + while(fgets(line, sizeof(line), fp)) + { + ln++; + if(line[0]=='/' && line[1]=='/') + continue; + if(strstr(line,"import")) { + if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 && + strcmpi(w1, "import") == 0) { + itemdb_read_itemgroup_sub(w2); + continue; + } + } + memset(str,0,sizeof(str)); + for(j=0,p=line;j<3 && p;j++){ + str[j]=p; + p=strchr(p,','); + if(p) *p++=0; + } + if(str[0]==NULL) + continue; + if (j<3) { + if (j>1) //Or else it barks on blank lines... + ShowWarning("itemdb_read_itemgroup: Insufficient fields for entry at %s:%d\n", filename, ln); + continue; + } + groupid = atoi(str[0]); + if (groupid < 0 || groupid >= MAX_ITEMGROUP) { + ShowWarning("itemdb_read_itemgroup: Invalid group %d in %s:%d\n", groupid, filename, ln); + continue; + } + nameid = atoi(str[1]); + if (!itemdb_exists(nameid)) { + ShowWarning("itemdb_read_itemgroup: Non-existant item %d in %s:%d\n", nameid, filename, ln); + continue; + } + k = atoi(str[2]); + if (itemgroup_db[groupid].qty+k >= MAX_RANDITEM) { + ShowWarning("itemdb_read_itemgroup: Group %d is full (%d entries) in %s:%d\n", groupid, MAX_RANDITEM, filename, ln); + continue; + } + for(j=0;j<k;j++) + itemgroup_db[groupid].nameid[itemgroup_db[groupid].qty++] = nameid; + } + fclose(fp); + return; } static void itemdb_read_itemgroup(void) { - char path[256]; - snprintf(path, 255, "%s/"DBPATH"item_group_db.txt", db_path); - memset(&itemgroup_db, 0, sizeof(itemgroup_db)); - itemdb_read_itemgroup_sub(path); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n", "item_group_db.txt"); - return; + char path[256]; + snprintf(path, 255, "%s/"DBPATH"item_group_db.txt", db_path); + memset(&itemgroup_db, 0, sizeof(itemgroup_db)); + itemdb_read_itemgroup_sub(path); + ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n", "item_group_db.txt"); + return; } /*========================================== * Read item forbidden by mapflag (can't equip item) *------------------------------------------*/ -static bool itemdb_read_noequip(char *str[], int columns, int current) -{ - // <nameid>,<mode> - int nameid; - struct item_data *id; +static bool itemdb_read_noequip(char* str[], int columns, int current) +{// <nameid>,<mode> + int nameid; + struct item_data *id; - nameid = atoi(str[0]); + nameid = atoi(str[0]); - if ((id = itemdb_exists(nameid)) == NULL) { - ShowWarning("itemdb_read_noequip: Invalid item id %d.\n", nameid); - return false; - } + if( ( id = itemdb_exists(nameid) ) == NULL ) + { + ShowWarning("itemdb_read_noequip: Invalid item id %d.\n", nameid); + return false; + } - id->flag.no_equip |= atoi(str[1]); + id->flag.no_equip |= atoi(str[1]); - return true; + return true; } /*========================================== * Reads item trade restrictions [Skotlex] *------------------------------------------*/ -static bool itemdb_read_itemtrade(char *str[], int columns, int current) -{ - // <nameid>,<mask>,<gm level> - int nameid, flag, gmlv; - struct item_data *id; - - nameid = atoi(str[0]); - - if ((id = itemdb_exists(nameid)) == NULL) { - //ShowWarning("itemdb_read_itemtrade: Invalid item id %d.\n", nameid); - //return false; - // FIXME: item_trade.txt contains items, which are commented in item database. - return true; - } - - flag = atoi(str[1]); - gmlv = atoi(str[2]); - - if (flag < 0 || flag > 511) { //Check range - ShowWarning("itemdb_read_itemtrade: Invalid trading mask %d for item id %d.\n", flag, nameid); - return false; - } - if (gmlv < 1) { - ShowWarning("itemdb_read_itemtrade: Invalid override GM level %d for item id %d.\n", gmlv, nameid); - return false; - } - - id->flag.trade_restriction = flag; - id->gm_lv_trade_override = gmlv; - - return true; +static bool itemdb_read_itemtrade(char* str[], int columns, int current) +{// <nameid>,<mask>,<gm level> + int nameid, flag, gmlv; + struct item_data *id; + + nameid = atoi(str[0]); + + if( ( id = itemdb_exists(nameid) ) == NULL ) + { + //ShowWarning("itemdb_read_itemtrade: Invalid item id %d.\n", nameid); + //return false; + // FIXME: item_trade.txt contains items, which are commented in item database. + return true; + } + + flag = atoi(str[1]); + gmlv = atoi(str[2]); + + if( flag < 0 || flag > 511 ) {//Check range + ShowWarning("itemdb_read_itemtrade: Invalid trading mask %d for item id %d.\n", flag, nameid); + return false; + } + if( gmlv < 1 ) + { + ShowWarning("itemdb_read_itemtrade: Invalid override GM level %d for item id %d.\n", gmlv, nameid); + return false; + } + + id->flag.trade_restriction = flag; + id->gm_lv_trade_override = gmlv; + + return true; } /*========================================== * Reads item delay amounts [Paradox924X] *------------------------------------------*/ -static bool itemdb_read_itemdelay(char *str[], int columns, int current) -{ - // <nameid>,<delay> - int nameid, delay; - struct item_data *id; +static bool itemdb_read_itemdelay(char* str[], int columns, int current) +{// <nameid>,<delay> + int nameid, delay; + struct item_data *id; - nameid = atoi(str[0]); + nameid = atoi(str[0]); - if ((id = itemdb_exists(nameid)) == NULL) { - ShowWarning("itemdb_read_itemdelay: Invalid item id %d.\n", nameid); - return false; - } + if( ( id = itemdb_exists(nameid) ) == NULL ) + { + ShowWarning("itemdb_read_itemdelay: Invalid item id %d.\n", nameid); + return false; + } - delay = atoi(str[1]); + delay = atoi(str[1]); - if (delay < 0) { - ShowWarning("itemdb_read_itemdelay: Invalid delay %d for item id %d.\n", id->delay, nameid); - return false; - } + if( delay < 0 ) + { + ShowWarning("itemdb_read_itemdelay: Invalid delay %d for item id %d.\n", id->delay, nameid); + return false; + } - id->delay = delay; + id->delay = delay; - return true; + return true; } /*================================================================== * Reads item stacking restrictions *----------------------------------------------------------------*/ -static bool itemdb_read_stack(char *fields[], int columns, int current) -{ - // <item id>,<stack limit amount>,<type> - unsigned short nameid, amount; - unsigned int type; - struct item_data *id; - - nameid = (unsigned short)strtoul(fields[0], NULL, 10); - - if ((id = itemdb_exists(nameid)) == NULL) { - ShowWarning("itemdb_read_stack: Unknown item id '%hu'.\n", nameid); - return false; - } - - if (!itemdb_isstackable2(id)) { - ShowWarning("itemdb_read_stack: Item id '%hu' is not stackable.\n", nameid); - return false; - } - - amount = (unsigned short)strtoul(fields[1], NULL, 10); - type = strtoul(fields[2], NULL, 10); - - if (!amount) { - // ignore - return true; - } - - id->stack.amount = amount; - id->stack.inventory = (type&1)!=0; - id->stack.cart = (type&2)!=0; - id->stack.storage = (type&4)!=0; - id->stack.guildstorage = (type&8)!=0; - - return true; +static bool itemdb_read_stack(char* fields[], int columns, int current) +{// <item id>,<stack limit amount>,<type> + unsigned short nameid, amount; + unsigned int type; + struct item_data* id; + + nameid = (unsigned short)strtoul(fields[0], NULL, 10); + + if( ( id = itemdb_exists(nameid) ) == NULL ) + { + ShowWarning("itemdb_read_stack: Unknown item id '%hu'.\n", nameid); + return false; + } + + if( !itemdb_isstackable2(id) ) + { + ShowWarning("itemdb_read_stack: Item id '%hu' is not stackable.\n", nameid); + return false; + } + + amount = (unsigned short)strtoul(fields[1], NULL, 10); + type = strtoul(fields[2], NULL, 10); + + if( !amount ) + {// ignore + return true; + } + + id->stack.amount = amount; + id->stack.inventory = (type&1)!=0; + id->stack.cart = (type&2)!=0; + id->stack.storage = (type&4)!=0; + id->stack.guildstorage = (type&8)!=0; + + return true; } /// Reads items allowed to be sold in buying stores -static bool itemdb_read_buyingstore(char *fields[], int columns, int current) -{ - // <nameid> - int nameid; - struct item_data *id; +static bool itemdb_read_buyingstore(char* fields[], int columns, int current) +{// <nameid> + int nameid; + struct item_data* id; - nameid = atoi(fields[0]); + nameid = atoi(fields[0]); - if ((id = itemdb_exists(nameid)) == NULL) { - ShowWarning("itemdb_read_buyingstore: Invalid item id %d.\n", nameid); - return false; - } + if( ( id = itemdb_exists(nameid) ) == NULL ) + { + ShowWarning("itemdb_read_buyingstore: Invalid item id %d.\n", nameid); + return false; + } - if (!itemdb_isstackable2(id)) { - ShowWarning("itemdb_read_buyingstore: Non-stackable item id %d cannot be enabled for buying store.\n", nameid); - return false; - } + if( !itemdb_isstackable2(id) ) + { + ShowWarning("itemdb_read_buyingstore: Non-stackable item id %d cannot be enabled for buying store.\n", nameid); + return false; + } - id->flag.buyingstore = true; + id->flag.buyingstore = true; - return true; + return true; } /** * @return: amount of retrieved entries. **/ -int itemdb_combo_split_atoi(char *str, int *val) -{ - int i; - - for (i=0; i<MAX_ITEMS_PER_COMBO; i++) { - if (!str) break; - - val[i] = atoi(str); - - str = strchr(str,':'); - - if (str) - *str++=0; - } - - if (i == 0) //No data found. - return 0; - - return i; +int itemdb_combo_split_atoi (char *str, int *val) { + int i; + + for (i=0; i<MAX_ITEMS_PER_COMBO; i++) { + if (!str) break; + + val[i] = atoi(str); + + str = strchr(str,':'); + + if (str) + *str++=0; + } + + if( i == 0 ) //No data found. + return 0; + + return i; } /** * <combo{:combo{:combo:{..}}}>,<{ script }> **/ -void itemdb_read_combos() -{ - uint32 lines = 0, count = 0; - char line[1024]; - - char path[256]; - FILE *fp; - - sprintf(path, "%s/%s", db_path, DBPATH"item_combo_db.txt"); - - if ((fp = fopen(path, "r")) == NULL) { - ShowError("itemdb_read_combos: File not found \"%s\".\n", path); - return; - } - - // process rows one by one - while (fgets(line, sizeof(line), fp)) { - char *str[2], *p; - - lines++; - - if (line[0] == '/' && line[1] == '/') - continue; - - memset(str, 0, sizeof(str)); - - p = line; - - p = trim(p); - - if (*p == '\0') - continue;// empty line - - if (!strchr(p,',')) { - /* is there even a single column? */ - ShowError("itemdb_read_combos: Insufficient columns in line %d of \"%s\", skipping.\n", lines, path); - continue; - } - - str[0] = p; - p = strchr(p,','); - *p = '\0'; - p++; - - str[1] = p; - p = strchr(p,','); - p++; - - if (str[1][0] != '{') { - ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path); - continue; - } - - /* no ending key anywhere (missing \}\) */ - if (str[1][strlen(str[1])-1] != '}') { - ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path); - continue; - } else { - int items[MAX_ITEMS_PER_COMBO]; - int v = 0, retcount = 0; - struct item_data *id = NULL; - int idx = 0; - - if ((retcount = itemdb_combo_split_atoi(str[0], items)) < 2) { - ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, path); - continue; - } - - /* validate */ - for (v = 0; v < retcount; v++) { - if (!itemdb_exists(items[v])) { - ShowError("itemdb_read_combos: line %d of \"%s\" contains unknown item ID %d, skipping.\n", lines, path,items[v]); - break; - } - } - /* failed at some item */ - if (v < retcount) - continue; - - id = itemdb_exists(items[0]); - - idx = id->combos_count; - - /* first entry, create */ - if (id->combos == NULL) { - CREATE(id->combos, struct item_combo *, 1); - id->combos_count = 1; - } else { - RECREATE(id->combos, struct item_combo *, ++id->combos_count); - } - - CREATE(id->combos[idx],struct item_combo,1); - - id->combos[idx]->nameid = aMalloc(retcount * sizeof(unsigned short)); - id->combos[idx]->count = retcount; - id->combos[idx]->script = parse_script(str[1], path, lines, 0); - id->combos[idx]->id = count; - id->combos[idx]->isRef = false; - /* populate ->nameid field */ - for (v = 0; v < retcount; v++) { - id->combos[idx]->nameid[v] = items[v]; - } - - /* populate the children to refer to this combo */ - for (v = 1; v < retcount; v++) { - struct item_data *it = NULL; - int index; - - it = itemdb_exists(items[v]); - - index = it->combos_count; - - if (it->combos == NULL) { - CREATE(it->combos, struct item_combo *, 1); - it->combos_count = 1; - } else { - RECREATE(it->combos, struct item_combo *, ++it->combos_count); - } - - CREATE(it->combos[index],struct item_combo,1); - - /* we copy previously alloc'd pointers and just set it to reference */ - memcpy(it->combos[index],id->combos[idx],sizeof(struct item_combo)); - /* we flag this way to ensure we don't double-dealloc same data */ - it->combos[index]->isRef = true; - } - - } - - count++; - } - - fclose(fp); - - ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"item_combo_db"CL_RESET"'.\n", count); - - return; +void itemdb_read_combos() { + uint32 lines = 0, count = 0; + char line[1024]; + + char path[256]; + FILE* fp; + + sprintf(path, "%s/%s", db_path, DBPATH"item_combo_db.txt"); + + if ((fp = fopen(path, "r")) == NULL) { + ShowError("itemdb_read_combos: File not found \"%s\".\n", path); + return; + } + + // process rows one by one + while(fgets(line, sizeof(line), fp)) { + char *str[2], *p; + + lines++; + + if (line[0] == '/' && line[1] == '/') + continue; + + memset(str, 0, sizeof(str)); + + p = line; + + p = trim(p); + + if (*p == '\0') + continue;// empty line + + if (!strchr(p,',')) + { + /* is there even a single column? */ + ShowError("itemdb_read_combos: Insufficient columns in line %d of \"%s\", skipping.\n", lines, path); + continue; + } + + str[0] = p; + p = strchr(p,','); + *p = '\0'; + p++; + + str[1] = p; + p = strchr(p,','); + p++; + + if (str[1][0] != '{') { + ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path); + continue; + } + + /* no ending key anywhere (missing \}\) */ + if ( str[1][strlen(str[1])-1] != '}' ) { + ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, path); + continue; + } else { + int items[MAX_ITEMS_PER_COMBO]; + int v = 0, retcount = 0; + struct item_data * id = NULL; + int idx = 0; + + if((retcount = itemdb_combo_split_atoi(str[0], items)) < 2) { + ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, path); + continue; + } + + /* validate */ + for(v = 0; v < retcount; v++) { + if( !itemdb_exists(items[v]) ) { + ShowError("itemdb_read_combos: line %d of \"%s\" contains unknown item ID %d, skipping.\n", lines, path,items[v]); + break; + } + } + /* failed at some item */ + if( v < retcount ) + continue; + + id = itemdb_exists(items[0]); + + idx = id->combos_count; + + /* first entry, create */ + if( id->combos == NULL ) { + CREATE(id->combos, struct item_combo*, 1); + id->combos_count = 1; + } else { + RECREATE(id->combos, struct item_combo*, ++id->combos_count); + } + + CREATE(id->combos[idx],struct item_combo,1); + + id->combos[idx]->nameid = aMalloc( retcount * sizeof(unsigned short) ); + id->combos[idx]->count = retcount; + id->combos[idx]->script = parse_script(str[1], path, lines, 0); + id->combos[idx]->id = count; + id->combos[idx]->isRef = false; + /* populate ->nameid field */ + for( v = 0; v < retcount; v++ ) { + id->combos[idx]->nameid[v] = items[v]; + } + + /* populate the children to refer to this combo */ + for( v = 1; v < retcount; v++ ) { + struct item_data * it = NULL; + int index; + + it = itemdb_exists(items[v]); + + index = it->combos_count; + + if( it->combos == NULL ) { + CREATE(it->combos, struct item_combo*, 1); + it->combos_count = 1; + } else { + RECREATE(it->combos, struct item_combo*, ++it->combos_count); + } + + CREATE(it->combos[index],struct item_combo,1); + + /* we copy previously alloc'd pointers and just set it to reference */ + memcpy(it->combos[index],id->combos[idx],sizeof(struct item_combo)); + /* we flag this way to ensure we don't double-dealloc same data */ + it->combos[index]->isRef = true; + } + + } + + count++; + } + + fclose(fp); + + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"item_combo_db"CL_RESET"'.\n", count); + + return; } @@ -908,170 +908,171 @@ void itemdb_read_combos() *======================================*/ static int itemdb_gendercheck(struct item_data *id) { - if (id->nameid == WEDDING_RING_M) //Grom Ring - return 1; - if (id->nameid == WEDDING_RING_F) //Bride Ring - return 0; - if (id->look == W_MUSICAL && id->type == IT_WEAPON) //Musical instruments are always male-only - return 1; - if (id->look == W_WHIP && id->type == IT_WEAPON) //Whips are always female-only - return 0; - - return (battle_config.ignore_items_gender) ? 2 : id->sex; + if (id->nameid == WEDDING_RING_M) //Grom Ring + return 1; + if (id->nameid == WEDDING_RING_F) //Bride Ring + return 0; + if (id->look == W_MUSICAL && id->type == IT_WEAPON) //Musical instruments are always male-only + return 1; + if (id->look == W_WHIP && id->type == IT_WEAPON) //Whips are always female-only + return 0; + + return (battle_config.ignore_items_gender) ? 2 : id->sex; } /** * [RRInd] * For backwards compatibility, in Renewal mode, MATK from weapons comes from the atk slot * We use a ':' delimiter which, if not found, assumes the weapon does not provide any matk. **/ -void itemdb_re_split_atoi(char *str, int *atk, int *matk) -{ - int i, val[2]; - - for (i=0; i<2; i++) { - if (!str) break; - val[i] = atoi(str); - str = strchr(str,':'); - if (str) - *str++=0; - } - if (i == 0) { - *atk = *matk = 0; - return;//no data found - } - if (i == 1) { //Single Value, we assume it's the ATK - *atk = val[0]; - *matk = 0; - return; - } - //We assume we have 2 values. - *atk = val[0]; - *matk = val[1]; - return; +void itemdb_re_split_atoi(char *str, int *atk, int *matk) { + int i, val[2]; + + for (i=0; i<2; i++) { + if (!str) break; + val[i] = atoi(str); + str = strchr(str,':'); + if (str) + *str++=0; + } + if( i == 0 ) { + *atk = *matk = 0; + return;//no data found + } + if( i == 1 ) {//Single Value, we assume it's the ATK + *atk = val[0]; + *matk = 0; + return; + } + //We assume we have 2 values. + *atk = val[0]; + *matk = val[1]; + return; } /*========================================== * processes one itemdb entry *------------------------------------------*/ -static bool itemdb_parse_dbrow(char **str, const char *source, int line, int scriptopt) -{ - /* - +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ - | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | - +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ - | id | name_english | name_japanese | type | price_buy | price_sell | weight | attack | defence | range | slots | equip_jobs | equip_upper | equip_genders | equip_locations | weapon_level | equip_level | refineable | view | script | equip_script | unequip_script | - +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ - */ - int nameid; - struct item_data *id; - - nameid = atoi(str[0]); - if (nameid <= 0) { - ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", nameid, line, source); - return false; - } - - //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View - id = itemdb_load(nameid); - safestrncpy(id->name, str[1], sizeof(id->name)); - safestrncpy(id->jname, str[2], sizeof(id->jname)); - - id->type = atoi(str[3]); - - if (id->type < 0 || id->type == IT_UNKNOWN || id->type == IT_UNKNOWN2 || (id->type > IT_DELAYCONSUME && id->type < IT_CASH) || id->type >= IT_MAX) { - // catch invalid item types - ShowWarning("itemdb_parse_dbrow: Invalid item type %d for item %d. IT_ETC will be used.\n", id->type, nameid); - id->type = IT_ETC; - } - - if (id->type == IT_DELAYCONSUME) { - //Items that are consumed only after target confirmation - id->type = IT_USABLE; - id->flag.delay_consume = 1; - } else //In case of an itemdb reload and the item type changed. - id->flag.delay_consume = 0; - - //When a particular price is not given, we should base it off the other one - //(it is important to make a distinction between 'no price' and 0z) - if (str[4][0]) - id->value_buy = atoi(str[4]); - else - id->value_buy = atoi(str[5]) * 2; - - if (str[5][0]) - id->value_sell = atoi(str[5]); - else - id->value_sell = id->value_buy / 2; - /* - if ( !str[4][0] && !str[5][0]) - { - ShowWarning("itemdb_parse_dbrow: No buying/selling price defined for item %d (%s), using 20/10z\n", nameid, id->jname); - id->value_buy = 20; - id->value_sell = 10; - } else - */ - if (id->value_buy/124. < id->value_sell/75.) - ShowWarning("itemdb_parse_dbrow: Buying/Selling [%d/%d] price of item %d (%s) allows Zeny making exploit through buying/selling at discounted/overcharged prices!\n", - id->value_buy, id->value_sell, nameid, id->jname); - - id->weight = atoi(str[6]); +static bool itemdb_parse_dbrow(char** str, const char* source, int line, int scriptopt) { + /* + +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | + +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ + | id | name_english | name_japanese | type | price_buy | price_sell | weight | attack | defence | range | slots | equip_jobs | equip_upper | equip_genders | equip_locations | weapon_level | equip_level | refineable | view | script | equip_script | unequip_script | + +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ + */ + int nameid; + struct item_data* id; + + nameid = atoi(str[0]); + if( nameid <= 0 ) + { + ShowWarning("itemdb_parse_dbrow: Invalid id %d in line %d of \"%s\", skipping.\n", nameid, line, source); + return false; + } + + //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View + id = itemdb_load(nameid); + safestrncpy(id->name, str[1], sizeof(id->name)); + safestrncpy(id->jname, str[2], sizeof(id->jname)); + + id->type = atoi(str[3]); + + if( id->type < 0 || id->type == IT_UNKNOWN || id->type == IT_UNKNOWN2 || ( id->type > IT_DELAYCONSUME && id->type < IT_CASH ) || id->type >= IT_MAX ) + {// catch invalid item types + ShowWarning("itemdb_parse_dbrow: Invalid item type %d for item %d. IT_ETC will be used.\n", id->type, nameid); + id->type = IT_ETC; + } + + if (id->type == IT_DELAYCONSUME) + { //Items that are consumed only after target confirmation + id->type = IT_USABLE; + id->flag.delay_consume = 1; + } else //In case of an itemdb reload and the item type changed. + id->flag.delay_consume = 0; + + //When a particular price is not given, we should base it off the other one + //(it is important to make a distinction between 'no price' and 0z) + if ( str[4][0] ) + id->value_buy = atoi(str[4]); + else + id->value_buy = atoi(str[5]) * 2; + + if ( str[5][0] ) + id->value_sell = atoi(str[5]); + else + id->value_sell = id->value_buy / 2; + /* + if ( !str[4][0] && !str[5][0]) + { + ShowWarning("itemdb_parse_dbrow: No buying/selling price defined for item %d (%s), using 20/10z\n", nameid, id->jname); + id->value_buy = 20; + id->value_sell = 10; + } else + */ + if (id->value_buy/124. < id->value_sell/75.) + ShowWarning("itemdb_parse_dbrow: Buying/Selling [%d/%d] price of item %d (%s) allows Zeny making exploit through buying/selling at discounted/overcharged prices!\n", + id->value_buy, id->value_sell, nameid, id->jname); + + id->weight = atoi(str[6]); #ifdef RENEWAL - itemdb_re_split_atoi(str[7],&id->atk,&id->matk); + itemdb_re_split_atoi(str[7],&id->atk,&id->matk); #else - id->atk = atoi(str[7]); + id->atk = atoi(str[7]); #endif - id->def = atoi(str[8]); - id->range = atoi(str[9]); - id->slot = atoi(str[10]); - - if (id->slot > MAX_SLOTS) { - ShowWarning("itemdb_parse_dbrow: Item %d (%s) specifies %d slots, but the server only supports up to %d. Using %d slots.\n", nameid, id->jname, id->slot, MAX_SLOTS, MAX_SLOTS); - id->slot = MAX_SLOTS; - } - - itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11],NULL,0)); - id->class_upper = atoi(str[12]); - id->sex = atoi(str[13]); - id->equip = atoi(str[14]); - - if (!id->equip && itemdb_isequip2(id)) { - ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname); - id->type = IT_ETC; - } - - id->wlv = cap_value(atoi(str[15]), REFINE_TYPE_ARMOR, REFINE_TYPE_MAX); + id->def = atoi(str[8]); + id->range = atoi(str[9]); + id->slot = atoi(str[10]); + + if (id->slot > MAX_SLOTS) + { + ShowWarning("itemdb_parse_dbrow: Item %d (%s) specifies %d slots, but the server only supports up to %d. Using %d slots.\n", nameid, id->jname, id->slot, MAX_SLOTS, MAX_SLOTS); + id->slot = MAX_SLOTS; + } + + itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11],NULL,0)); + id->class_upper = atoi(str[12]); + id->sex = atoi(str[13]); + id->equip = atoi(str[14]); + + if (!id->equip && itemdb_isequip2(id)) + { + ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname); + id->type = IT_ETC; + } + + id->wlv = cap_value(atoi(str[15]), REFINE_TYPE_ARMOR, REFINE_TYPE_MAX); #ifdef RENEWAL - itemdb_re_split_atoi(str[16],&id->elv,&id->elvmax); + itemdb_re_split_atoi(str[16],&id->elv,&id->elvmax); #else - id->elv = atoi(str[16]); + id->elv = atoi(str[16]); #endif - id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this - id->look = atoi(str[18]); - - id->flag.available = 1; - id->view_id = 0; - id->sex = itemdb_gendercheck(id); //Apply gender filtering. - - if (id->script) { - script_free_code(id->script); - id->script = NULL; - } - if (id->equip_script) { - script_free_code(id->equip_script); - id->equip_script = NULL; - } - if (id->unequip_script) { - script_free_code(id->unequip_script); - id->unequip_script = NULL; - } - - if (*str[19]) - id->script = parse_script(str[19], source, line, scriptopt); - if (*str[20]) - id->equip_script = parse_script(str[20], source, line, scriptopt); - if (*str[21]) - id->unequip_script = parse_script(str[21], source, line, scriptopt); - - return true; + id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this + id->look = atoi(str[18]); + + id->flag.available = 1; + id->view_id = 0; + id->sex = itemdb_gendercheck(id); //Apply gender filtering. + + if (id->script) { + script_free_code(id->script); + id->script = NULL; + } + if (id->equip_script) { + script_free_code(id->equip_script); + id->equip_script = NULL; + } + if (id->unequip_script) { + script_free_code(id->unequip_script); + id->unequip_script = NULL; + } + + if (*str[19]) + id->script = parse_script(str[19], source, line, scriptopt); + if (*str[20]) + id->equip_script = parse_script(str[20], source, line, scriptopt); + if (*str[21]) + id->unequip_script = parse_script(str[21], source, line, scriptopt); + + return true; } /*========================================== @@ -1080,191 +1081,195 @@ static bool itemdb_parse_dbrow(char **str, const char *source, int line, int scr *------------------------------------------*/ static int itemdb_readdb(void) { - const char *filename[] = { - DBPATH"item_db.txt", - "item_db2.txt" - }; - - int fi; - - for (fi = 0; fi < ARRAYLENGTH(filename); ++fi) { - uint32 lines = 0, count = 0; - char line[1024]; - - char path[256]; - FILE *fp; - - sprintf(path, "%s/%s", db_path, filename[fi]); - fp = fopen(path, "r"); - if (fp == NULL) { - ShowWarning("itemdb_readdb: File not found \"%s\", skipping.\n", path); - continue; - } - - // process rows one by one - while (fgets(line, sizeof(line), fp)) { - char *str[32], *p; - int i; - lines++; - if (line[0] == '/' && line[1] == '/') - continue; - memset(str, 0, sizeof(str)); - - p = line; - while (ISSPACE(*p)) - ++p; - if (*p == '\0') - continue;// empty line - for (i = 0; i < 19; ++i) { - str[i] = p; - p = strchr(p,','); - if (p == NULL) - break;// comma not found - *p = '\0'; - ++p; - } - - if (p == NULL) { - ShowError("itemdb_readdb: Insufficient columns in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); - continue; - } - - // Script - if (*p != '{') { - ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); - continue; - } - str[19] = p; - p = strstr(p+1,"},"); - if (p == NULL) { - ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); - continue; - } - p[1] = '\0'; - p += 2; - - // OnEquip_Script - if (*p != '{') { - ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); - continue; - } - str[20] = p; - p = strstr(p+1,"},"); - if (p == NULL) { - ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); - continue; - } - p[1] = '\0'; - p += 2; - - // OnUnequip_Script (last column) - if (*p != '{') { - ShowError("itemdb_readdb: Invalid format (OnUnequip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); - continue; - } - str[21] = p; - - if (str[21][strlen(str[21])-2] != '}') { - /* lets count to ensure it's not something silly e.g. a extra space at line ending */ - int v, lcurly = 0, rcurly = 0; - - for (v = 0; v < strlen(str[21]); v++) { - if (str[21][v] == '{') - lcurly++; - else if (str[21][v] == '}') - rcurly++; - } - - if (lcurly != rcurly) { - ShowError("itemdb_readdb: Mismatching curly braces in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); - continue; - } - } - - if (!itemdb_parse_dbrow(str, path, lines, 0)) - continue; - - count++; - } - - fclose(fp); - - ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename[fi]); - } - - return 0; + const char* filename[] = { + DBPATH"item_db.txt", + "item_db2.txt" }; + + int fi; + + for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) { + uint32 lines = 0, count = 0; + char line[1024]; + + char path[256]; + FILE* fp; + + sprintf(path, "%s/%s", db_path, filename[fi]); + fp = fopen(path, "r"); + if( fp == NULL ) { + ShowWarning("itemdb_readdb: File not found \"%s\", skipping.\n", path); + continue; + } + + // process rows one by one + while(fgets(line, sizeof(line), fp)) + { + char *str[32], *p; + int i; + lines++; + if(line[0] == '/' && line[1] == '/') + continue; + memset(str, 0, sizeof(str)); + + p = line; + while( ISSPACE(*p) ) + ++p; + if( *p == '\0' ) + continue;// empty line + for( i = 0; i < 19; ++i ) + { + str[i] = p; + p = strchr(p,','); + if( p == NULL ) + break;// comma not found + *p = '\0'; + ++p; + } + + if( p == NULL ) + { + ShowError("itemdb_readdb: Insufficient columns in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); + continue; + } + + // Script + if( *p != '{' ) + { + ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); + continue; + } + str[19] = p; + p = strstr(p+1,"},"); + if( p == NULL ) + { + ShowError("itemdb_readdb: Invalid format (Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); + continue; + } + p[1] = '\0'; + p += 2; + + // OnEquip_Script + if( *p != '{' ) + { + ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); + continue; + } + str[20] = p; + p = strstr(p+1,"},"); + if( p == NULL ) + { + ShowError("itemdb_readdb: Invalid format (OnEquip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); + continue; + } + p[1] = '\0'; + p += 2; + + // OnUnequip_Script (last column) + if( *p != '{' ) + { + ShowError("itemdb_readdb: Invalid format (OnUnequip_Script column) in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); + continue; + } + str[21] = p; + + if ( str[21][strlen(str[21])-2] != '}' ) { + /* lets count to ensure it's not something silly e.g. a extra space at line ending */ + int v, lcurly = 0, rcurly = 0; + + for( v = 0; v < strlen(str[21]); v++ ) { + if( str[21][v] == '{' ) + lcurly++; + else if ( str[21][v] == '}' ) + rcurly++; + } + + if( lcurly != rcurly ) { + ShowError("itemdb_readdb: Mismatching curly braces in line %d of \"%s\" (item with id %d), skipping.\n", lines, path, atoi(str[0])); + continue; + } + } + + if (!itemdb_parse_dbrow(str, path, lines, 0)) + continue; + + count++; + } + + fclose(fp); + + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename[fi]); + } + + return 0; } /*====================================== * item_db table reading *======================================*/ -static int itemdb_read_sqldb(void) -{ - - const char *item_db_name[] = { -#ifdef RENEWAL - item_db_re_db, -#else - item_db_db, -#endif - item_db2_db - }; - int fi; - - for (fi = 0; fi < ARRAYLENGTH(item_db_name); ++fi) { - uint32 lines = 0, count = 0; - - // retrieve all rows from the item database - if (SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", item_db_name[fi])) { - Sql_ShowDebug(mmysql_handle); - continue; - } - - // process rows one by one - while (SQL_SUCCESS == Sql_NextRow(mmysql_handle)) { // wrap the result into a TXT-compatible format - char *str[22]; - char *dummy = ""; - int i; - ++lines; - for (i = 0; i < 22; ++i) { - Sql_GetData(mmysql_handle, i, &str[i], NULL); - if (str[i] == NULL) - str[i] = dummy; // get rid of NULL columns - } - - if (!itemdb_parse_dbrow(str, item_db_name[fi], lines, SCRIPT_IGNORE_EXTERNAL_BRACKETS)) - continue; - ++count; - } - - // free the query result - Sql_FreeResult(mmysql_handle); - - ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, item_db_name[fi]); - } - - return 0; +static int itemdb_read_sqldb(void) { + + const char* item_db_name[] = { + #ifdef RENEWAL + item_db_re_db, + #else + item_db_db, + #endif + item_db2_db }; + int fi; + + for( fi = 0; fi < ARRAYLENGTH(item_db_name); ++fi ) { + uint32 lines = 0, count = 0; + + // retrieve all rows from the item database + if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", item_db_name[fi]) ) { + Sql_ShowDebug(mmysql_handle); + continue; + } + + // process rows one by one + while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) {// wrap the result into a TXT-compatible format + char* str[22]; + char* dummy = ""; + int i; + ++lines; + for( i = 0; i < 22; ++i ) { + Sql_GetData(mmysql_handle, i, &str[i], NULL); + if( str[i] == NULL ) + str[i] = dummy; // get rid of NULL columns + } + + if (!itemdb_parse_dbrow(str, item_db_name[fi], lines, SCRIPT_IGNORE_EXTERNAL_BRACKETS)) + continue; + ++count; + } + + // free the query result + Sql_FreeResult(mmysql_handle); + + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, item_db_name[fi]); + } + + return 0; } /*==================================== * read all item-related databases *------------------------------------*/ -static void itemdb_read(void) -{ - - if (db_use_sqldbs) - itemdb_read_sqldb(); - else - itemdb_readdb(); - - itemdb_read_combos(); - itemdb_read_itemgroup(); - sv_readdb(db_path, "item_avail.txt", ',', 2, 2, -1, &itemdb_read_itemavail); - sv_readdb(db_path, DBPATH"item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip); - sv_readdb(db_path, DBPATH"item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade); - sv_readdb(db_path, "item_delay.txt", ',', 2, 2, -1, &itemdb_read_itemdelay); - sv_readdb(db_path, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack); - sv_readdb(db_path, DBPATH"item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore); +static void itemdb_read(void) { + + if (db_use_sqldbs) + itemdb_read_sqldb(); + else + itemdb_readdb(); + + itemdb_read_combos(); + itemdb_read_itemgroup(); + sv_readdb(db_path, "item_avail.txt", ',', 2, 2, -1, &itemdb_read_itemavail); + sv_readdb(db_path, DBPATH"item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip); + sv_readdb(db_path, DBPATH"item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade); + sv_readdb(db_path, "item_delay.txt", ',', 2, 2, -1, &itemdb_read_itemdelay); + sv_readdb(db_path, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack); + sv_readdb(db_path, DBPATH"item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore); } /*========================================== @@ -1272,35 +1277,35 @@ static void itemdb_read(void) *------------------------------------------*/ /// Destroys the item_data. -static void destroy_item_data(struct item_data *self, int free_self) +static void destroy_item_data(struct item_data* self, int free_self) { - if (self == NULL) - return; - // free scripts - if (self->script) - script_free_code(self->script); - if (self->equip_script) - script_free_code(self->equip_script); - if (self->unequip_script) - script_free_code(self->unequip_script); - if (self->combos_count) { - int i; - for (i = 0; i < self->combos_count; i++) { - if (!self->combos[i]->isRef) { - aFree(self->combos[i]->nameid); - script_free_code(self->combos[i]->script); - } - aFree(self->combos[i]); - } - aFree(self->combos); - } + if( self == NULL ) + return; + // free scripts + if( self->script ) + script_free_code(self->script); + if( self->equip_script ) + script_free_code(self->equip_script); + if( self->unequip_script ) + script_free_code(self->unequip_script); + if( self->combos_count ) { + int i; + for( i = 0; i < self->combos_count; i++ ) { + if( !self->combos[i]->isRef ) { + aFree(self->combos[i]->nameid); + script_free_code(self->combos[i]->script); + } + aFree(self->combos[i]); + } + aFree(self->combos); + } #if defined(DEBUG) - // trash item - memset(self, 0xDD, sizeof(struct item_data)); + // trash item + memset(self, 0xDD, sizeof(struct item_data)); #endif - // free self - if (free_self) - aFree(self); + // free self + if( free_self ) + aFree(self); } /** @@ -1308,99 +1313,98 @@ static void destroy_item_data(struct item_data *self, int free_self) */ static int itemdb_final_sub(DBKey key, DBData *data, va_list ap) { - struct item_data *id = db_data2ptr(data); + struct item_data *id = db_data2ptr(data); - if (id != &dummy_item) - destroy_item_data(id, 1); + if( id != &dummy_item ) + destroy_item_data(id, 1); - return 0; + return 0; } void itemdb_reload(void) { - struct s_mapiterator *iter; - struct map_session_data *sd; - - int i,d,k; - - // clear the previous itemdb data - for (i = 0; i < ARRAYLENGTH(itemdb_array); ++i) - if (itemdb_array[i]) - destroy_item_data(itemdb_array[i], 1); - - itemdb_other->clear(itemdb_other, itemdb_final_sub); - - memset(itemdb_array, 0, sizeof(itemdb_array)); - - // read new data - itemdb_read(); - - //Epoque's awesome @reloaditemdb fix - thanks! [Ind] - //- Fixes the need of a @reloadmobdb after a @reloaditemdb to re-link monster drop data - for (i = 0; i < MAX_MOB_DB; i++) { - struct mob_db *entry; - if (!((i < 1324 || i > 1363) && (i < 1938 || i > 1946))) - continue; - entry = mob_db(i); - for (d = 0; d < MAX_MOB_DROP; d++) { - struct item_data *id; - if (!entry->dropitem[d].nameid) - continue; - id = itemdb_search(entry->dropitem[d].nameid); - - for (k = 0; k < MAX_SEARCH; k++) { - if (id->mob[k].chance <= entry->dropitem[d].p) - break; - } - - if (k == MAX_SEARCH) - continue; - - if (id->mob[k].id != i) - memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0])); - id->mob[k].chance = entry->dropitem[d].p; - id->mob[k].id = i; - } - } - - // readjust itemdb pointer cache for each player - iter = mapit_geteachpc(); - for (sd = (struct map_session_data *)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data *)mapit_next(iter)) { - memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays - pc_setinventorydata(sd); - /* clear combo bonuses */ - if (sd->combos.count) { - aFree(sd->combos.bonus); - aFree(sd->combos.id); - sd->combos.bonus = NULL; - sd->combos.id = NULL; - sd->combos.count = 0; - if (pc_load_combo(sd) > 0) - status_calc_pc(sd,0); - } - - } - mapit_free(iter); + struct s_mapiterator* iter; + struct map_session_data* sd; + + int i,d,k; + + // clear the previous itemdb data + for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) + if( itemdb_array[i] ) + destroy_item_data(itemdb_array[i], 1); + + itemdb_other->clear(itemdb_other, itemdb_final_sub); + + memset(itemdb_array, 0, sizeof(itemdb_array)); + + // read new data + itemdb_read(); + + //Epoque's awesome @reloaditemdb fix - thanks! [Ind] + //- Fixes the need of a @reloadmobdb after a @reloaditemdb to re-link monster drop data + for( i = 0; i < MAX_MOB_DB; i++ ) { + struct mob_db *entry; + if( !((i < 1324 || i > 1363) && (i < 1938 || i > 1946)) ) + continue; + entry = mob_db(i); + for(d = 0; d < MAX_MOB_DROP; d++) { + struct item_data *id; + if( !entry->dropitem[d].nameid ) + continue; + id = itemdb_search(entry->dropitem[d].nameid); + + for (k = 0; k < MAX_SEARCH; k++) { + if (id->mob[k].chance <= entry->dropitem[d].p) + break; + } + + if (k == MAX_SEARCH) + continue; + + if (id->mob[k].id != i) + memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0])); + id->mob[k].chance = entry->dropitem[d].p; + id->mob[k].id = i; + } + } + + // readjust itemdb pointer cache for each player + iter = mapit_geteachpc(); + for( sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data*)mapit_next(iter) ) { + memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays + pc_setinventorydata(sd); + /* clear combo bonuses */ + if( sd->combos.count ) { + aFree(sd->combos.bonus); + aFree(sd->combos.id); + sd->combos.bonus = NULL; + sd->combos.id = NULL; + sd->combos.count = 0; + if( pc_load_combo(sd) > 0 ) + status_calc_pc(sd,0); + } + + } + mapit_free(iter); } void do_final_itemdb(void) { - int i; + int i; - for (i = 0; i < ARRAYLENGTH(itemdb_array); ++i) - if (itemdb_array[i]) - destroy_item_data(itemdb_array[i], 1); + for( i = 0; i < ARRAYLENGTH(itemdb_array); ++i ) + if( itemdb_array[i] ) + destroy_item_data(itemdb_array[i], 1); - itemdb_other->destroy(itemdb_other, itemdb_final_sub); - destroy_item_data(&dummy_item, 0); + itemdb_other->destroy(itemdb_other, itemdb_final_sub); + destroy_item_data(&dummy_item, 0); } -int do_init_itemdb(void) -{ - memset(itemdb_array, 0, sizeof(itemdb_array)); - itemdb_other = idb_alloc(DB_OPT_BASE); - create_dummy_data(); //Dummy data item. - itemdb_read(); +int do_init_itemdb(void) { + memset(itemdb_array, 0, sizeof(itemdb_array)); + itemdb_other = idb_alloc(DB_OPT_BASE); + create_dummy_data(); //Dummy data item. + itemdb_read(); - return 0; + return 0; } diff --git a/src/map/itemdb.h b/src/map/itemdb.h index d18c35b3a..4d4b62818 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -11,28 +11,28 @@ // 32k array entries in array (the rest goes to the db) #define MAX_ITEMDB 0x8000 -#define MAX_RANDITEM 11000 +#define MAX_RANDITEM 11000 // The maximum number of item delays -#define MAX_ITEMDELAYS 10 +#define MAX_ITEMDELAYS 10 -#define MAX_SEARCH 5 //Designed for search functions, species max number of matches to display. +#define MAX_SEARCH 5 //Designed for search functions, species max number of matches to display. /* maximum amount of items a combo may require */ #define MAX_ITEMS_PER_COMBO 6 enum item_itemid { - ITEMID_EMPERIUM = 714, - ITEMID_YELLOW_GEMSTONE = 715, - ITEMID_RED_GEMSTONE = 716, - ITEMID_BLUE_GEMSTONE = 717, - ITEMID_TRAP = 1065, - ITEMID_STONE = 7049, - ITEMID_SKULL_ = 7420, - ITEMID_TOKEN_OF_SIEGFRIED = 7621, - ITEMID_TRAP_ALLOY = 7940, - ITEMID_ANCILLA = 12333, - ITEMID_REINS_OF_MOUNT = 12622, + ITEMID_EMPERIUM = 714, + ITEMID_YELLOW_GEMSTONE = 715, + ITEMID_RED_GEMSTONE = 716, + ITEMID_BLUE_GEMSTONE = 717, + ITEMID_TRAP = 1065, + ITEMID_STONE = 7049, + ITEMID_SKULL_ = 7420, + ITEMID_TOKEN_OF_SIEGFRIED = 7621, + ITEMID_TRAP_ALLOY = 7940, + ITEMID_ANCILLA = 12333, + ITEMID_REINS_OF_MOUNT = 12622, }; /** @@ -40,33 +40,33 @@ enum item_itemid { **/ enum { - ITEMID_NAUTHIZ = 12725, - ITEMID_RAIDO, - ITEMID_BERKANA, - ITEMID_ISA, - ITEMID_OTHILA, - ITEMID_URUZ, - ITEMID_THURISAZ, - ITEMID_WYRD, - ITEMID_HAGALAZ, + ITEMID_NAUTHIZ = 12725, + ITEMID_RAIDO, + ITEMID_BERKANA, + ITEMID_ISA, + ITEMID_OTHILA, + ITEMID_URUZ, + ITEMID_THURISAZ, + ITEMID_WYRD, + ITEMID_HAGALAZ, } rune_list; /** * Mechanic **/ enum { - ITEMID_ACCELERATOR = 2800, - ITEMID_HOVERING_BOOSTER, - ITEMID_SUICIDAL_DEVICE, - ITEMID_SHAPE_SHIFTER, - ITEMID_COOLING_DEVICE, - ITEMID_MAGNETIC_FIELD_GENERATOR, - ITEMID_BARRIER_BUILDER, - ITEMID_REPAIR_KIT, - ITEMID_CAMOUFLAGE_GENERATOR, - ITEMID_HIGH_QUALITY_COOLER, - ITEMID_SPECIAL_COOLER, -} mecha_item_list; + ITEMID_ACCELERATOR = 2800, + ITEMID_HOVERING_BOOSTER, + ITEMID_SUICIDAL_DEVICE, + ITEMID_SHAPE_SHIFTER, + ITEMID_COOLING_DEVICE, + ITEMID_MAGNETIC_FIELD_GENERATOR, + ITEMID_BARRIER_BUILDER, + ITEMID_REPAIR_KIT, + ITEMID_CAMOUFLAGE_GENERATOR, + ITEMID_HIGH_QUALITY_COOLER, + ITEMID_SPECIAL_COOLER, + } mecha_item_list; //The only item group required by the code to be known. See const.txt for the full list. #define IG_FINDINGORE 6 @@ -85,82 +85,82 @@ enum { #define UNKNOWN_ITEM_ID 512 struct item_data { - int nameid; - char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH]; - - //Do not add stuff between value_buy and view_id (see how getiteminfo works) - int value_buy; - int value_sell; - int type; - int maxchance; //For logs, for external game info, for scripts: Max drop chance of this item (e.g. 0.01% , etc.. if it = 0, then monsters don't drop it, -1 denotes items sold in shops only) [Lupus] - int sex; - int equip; - int weight; - int atk; - int def; - int range; - int slot; - int look; - int elv; - int wlv; - int view_id; + int nameid; + char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH]; + + //Do not add stuff between value_buy and view_id (see how getiteminfo works) + int value_buy; + int value_sell; + int type; + int maxchance; //For logs, for external game info, for scripts: Max drop chance of this item (e.g. 0.01% , etc.. if it = 0, then monsters don't drop it, -1 denotes items sold in shops only) [Lupus] + int sex; + int equip; + int weight; + int atk; + int def; + int range; + int slot; + int look; + int elv; + int wlv; + int view_id; #ifdef RENEWAL - int matk; - int elvmax;/* maximum level for this item */ + int matk; + int elvmax;/* maximum level for this item */ #endif - int delay; - //Lupus: I rearranged order of these fields due to compatibility with ITEMINFO script command - // some script commands should be revised as well... - unsigned int class_base[3]; //Specifies if the base can wear this item (split in 3 indexes per type: 1-1, 2-1, 2-2) - unsigned class_upper : 4; //Specifies if the upper-type can equip it (bitfield, 1: normal, 2: upper, 3: baby,4:third) - struct { - unsigned short chance; - int id; - } mob[MAX_SEARCH]; //Holds the mobs that have the highest drop rate for this item. [Skotlex] - struct script_code *script; //Default script for everything. - struct script_code *equip_script; //Script executed once when equipping. - struct script_code *unequip_script;//Script executed once when unequipping. - struct { - unsigned available : 1; - short no_equip; - unsigned no_refine : 1; // [celest] - unsigned delay_consume : 1; // Signifies items that are not consumed immediately upon double-click [Skotlex] - unsigned trade_restriction : 9; //Item restrictions mask [Skotlex] - unsigned autoequip: 1; - unsigned buyingstore : 1; - } flag; - struct {// item stacking limitation - unsigned short amount; - unsigned int inventory:1; - unsigned int cart:1; - unsigned int storage:1; - unsigned int guildstorage:1; - } stack; - short gm_lv_trade_override; //GM-level to override trade_restriction - /* bugreport:309 */ - struct item_combo **combos; - unsigned char combos_count; + int delay; +//Lupus: I rearranged order of these fields due to compatibility with ITEMINFO script command +// some script commands should be revised as well... + unsigned int class_base[3]; //Specifies if the base can wear this item (split in 3 indexes per type: 1-1, 2-1, 2-2) + unsigned class_upper : 4; //Specifies if the upper-type can equip it (bitfield, 1: normal, 2: upper, 3: baby,4:third) + struct { + unsigned short chance; + int id; + } mob[MAX_SEARCH]; //Holds the mobs that have the highest drop rate for this item. [Skotlex] + struct script_code *script; //Default script for everything. + struct script_code *equip_script; //Script executed once when equipping. + struct script_code *unequip_script;//Script executed once when unequipping. + struct { + unsigned available : 1; + short no_equip; + unsigned no_refine : 1; // [celest] + unsigned delay_consume : 1; // Signifies items that are not consumed immediately upon double-click [Skotlex] + unsigned trade_restriction : 9; //Item restrictions mask [Skotlex] + unsigned autoequip: 1; + unsigned buyingstore : 1; + } flag; + struct {// item stacking limitation + unsigned short amount; + unsigned int inventory:1; + unsigned int cart:1; + unsigned int storage:1; + unsigned int guildstorage:1; + } stack; + short gm_lv_trade_override; //GM-level to override trade_restriction + /* bugreport:309 */ + struct item_combo **combos; + unsigned char combos_count; }; struct item_group { - int nameid[MAX_RANDITEM]; - int qty; //Counts amount of items in the group. + int nameid[MAX_RANDITEM]; + int qty; //Counts amount of items in the group. }; struct item_combo { - struct script_code *script; - unsigned short *nameid;/* nameid array */ - unsigned char count; - unsigned short id;/* id of this combo */ - bool isRef;/* whether this struct is a reference or the master */ + struct script_code *script; + unsigned short *nameid;/* nameid array */ + unsigned char count; + unsigned short id;/* id of this combo */ + bool isRef;/* whether this struct is a reference or the master */ }; -struct item_data *itemdb_searchname(const char *name); -int itemdb_searchname_array(struct item_data **data, int size, const char *str); -struct item_data *itemdb_load(int nameid); -struct item_data *itemdb_search(int nameid); -struct item_data *itemdb_exists(int nameid); +struct item_data* itemdb_searchname(const char *name); +int itemdb_searchname_array(struct item_data** data, int size, const char *str); +struct item_data* itemdb_load(int nameid); +struct item_data* itemdb_search(int nameid); +struct item_data* itemdb_exists(int nameid); #define itemdb_name(n) itemdb_search(n)->name #define itemdb_jname(n) itemdb_search(n)->jname #define itemdb_type(n) itemdb_search(n)->type @@ -185,9 +185,9 @@ struct item_data *itemdb_exists(int nameid); #define itemdb_iscashfood(id) ( (id) >= 12202 && (id) <= 12207 ) #define itemdb_is_GNbomb(n) (n >= 13260 && n <= 13267) #define itemdb_is_GNthrowable(n) (n >= 13268 && n <= 13290) -const char *itemdb_typename(int type); +const char* itemdb_typename(int type); -int itemdb_group_bonus(struct map_session_data *sd, int itemid); +int itemdb_group_bonus(struct map_session_data* sd, int itemid); int itemdb_searchrandomid(int flags); #define itemdb_value_buy(n) itemdb_search(n)->value_buy @@ -195,22 +195,22 @@ int itemdb_searchrandomid(int flags); #define itemdb_canrefine(n) (!itemdb_search(n)->flag.no_refine) //Item trade restrictions [Skotlex] int itemdb_isdropable_sub(struct item_data *, int, int); -int itemdb_cantrade_sub(struct item_data *, int, int); -int itemdb_canpartnertrade_sub(struct item_data *, int, int); -int itemdb_cansell_sub(struct item_data *,int, int); -int itemdb_cancartstore_sub(struct item_data *, int, int); -int itemdb_canstore_sub(struct item_data *, int, int); -int itemdb_canguildstore_sub(struct item_data *, int, int); -int itemdb_canmail_sub(struct item_data *, int, int); -int itemdb_canauction_sub(struct item_data *, int, int); -int itemdb_isrestricted(struct item *item, int gmlv, int gmlv2, int (*func)(struct item_data *, int, int)); +int itemdb_cantrade_sub(struct item_data*, int, int); +int itemdb_canpartnertrade_sub(struct item_data*, int, int); +int itemdb_cansell_sub(struct item_data*,int, int); +int itemdb_cancartstore_sub(struct item_data*, int, int); +int itemdb_canstore_sub(struct item_data*, int, int); +int itemdb_canguildstore_sub(struct item_data*, int, int); +int itemdb_canmail_sub(struct item_data*, int, int); +int itemdb_canauction_sub(struct item_data*, int, int); +int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(struct item_data*, int, int)); #define itemdb_isdropable(item, gmlv) itemdb_isrestricted(item, gmlv, 0, itemdb_isdropable_sub) #define itemdb_cantrade(item, gmlv, gmlv2) itemdb_isrestricted(item, gmlv, gmlv2, itemdb_cantrade_sub) #define itemdb_canpartnertrade(item, gmlv, gmlv2) itemdb_isrestricted(item, gmlv, gmlv2, itemdb_canpartnertrade_sub) #define itemdb_cansell(item, gmlv) itemdb_isrestricted(item, gmlv, 0, itemdb_cansell_sub) #define itemdb_cancartstore(item, gmlv) itemdb_isrestricted(item, gmlv, 0, itemdb_cancartstore_sub) -#define itemdb_canstore(item, gmlv) itemdb_isrestricted(item, gmlv, 0, itemdb_canstore_sub) -#define itemdb_canguildstore(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canguildstore_sub) +#define itemdb_canstore(item, gmlv) itemdb_isrestricted(item, gmlv, 0, itemdb_canstore_sub) +#define itemdb_canguildstore(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canguildstore_sub) #define itemdb_canmail(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canmail_sub) #define itemdb_canauction(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canauction_sub) diff --git a/src/map/log.c b/src/map/log.c index 7663a63bf..749bd5c28 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -19,21 +19,22 @@ /// filters for item logging -typedef enum e_log_filter { - LOG_FILTER_NONE = 0x000, - LOG_FILTER_ALL = 0x001, - // bits - LOG_FILTER_HEALING = 0x002, // Healing items (0) - LOG_FILTER_ETC_AMMO = 0x004, // Etc Items(3) + Arrows (10) - LOG_FILTER_USABLE = 0x008, // Usable Items(2) + Scrolls, Lures(11) + Usable Cash Items(18) - LOG_FILTER_WEAPON = 0x010, // Weapons(4) - LOG_FILTER_ARMOR = 0x020, // Shields, Armors, Headgears, Accessories, Garments and Shoes(5) - LOG_FILTER_CARD = 0x040, // Cards(6) - LOG_FILTER_PETITEM = 0x080, // Pet Accessories(8) + Eggs(7) (well, monsters don't drop 'em but we'll use the same system for ALL logs) - LOG_FILTER_PRICE = 0x100, // Log expensive items ( >= price_log ) - LOG_FILTER_AMOUNT = 0x200, // Log large amount of items ( >= amount_log ) - LOG_FILTER_REFINE = 0x400, // Log refined items ( refine >= refine_log ) [not implemented] - LOG_FILTER_CHANCE = 0x800, // Log rare items and Emperium ( drop chance <= rare_log ) +typedef enum e_log_filter +{ + LOG_FILTER_NONE = 0x000, + LOG_FILTER_ALL = 0x001, + // bits + LOG_FILTER_HEALING = 0x002, // Healing items (0) + LOG_FILTER_ETC_AMMO = 0x004, // Etc Items(3) + Arrows (10) + LOG_FILTER_USABLE = 0x008, // Usable Items(2) + Scrolls, Lures(11) + Usable Cash Items(18) + LOG_FILTER_WEAPON = 0x010, // Weapons(4) + LOG_FILTER_ARMOR = 0x020, // Shields, Armors, Headgears, Accessories, Garments and Shoes(5) + LOG_FILTER_CARD = 0x040, // Cards(6) + LOG_FILTER_PETITEM = 0x080, // Pet Accessories(8) + Eggs(7) (well, monsters don't drop 'em but we'll use the same system for ALL logs) + LOG_FILTER_PRICE = 0x100, // Log expensive items ( >= price_log ) + LOG_FILTER_AMOUNT = 0x200, // Log large amount of items ( >= amount_log ) + LOG_FILTER_REFINE = 0x400, // Log refined items ( refine >= refine_log ) [not implemented] + LOG_FILTER_CHANCE = 0x800, // Log rare items and Emperium ( drop chance <= rare_log ) } e_log_filter; @@ -53,515 +54,530 @@ struct Log_Config log_config; /// obtain log type character for item/zeny logs static char log_picktype2char(e_log_pick_type type) { - switch (type) { - case LOG_TYPE_TRADE: - return 'T'; // (T)rade - case LOG_TYPE_VENDING: - return 'V'; // (V)ending - case LOG_TYPE_PICKDROP_PLAYER: - return 'P'; // (P)player - case LOG_TYPE_PICKDROP_MONSTER: - return 'M'; // (M)onster - case LOG_TYPE_NPC: - return 'S'; // NPC (S)hop - case LOG_TYPE_SCRIPT: - return 'N'; // (N)PC Script - case LOG_TYPE_STEAL: - return 'D'; // Steal/Snatcher - case LOG_TYPE_CONSUME: - return 'C'; // (C)onsumed - case LOG_TYPE_PRODUCE: - return 'O'; // Pr(O)duced/Ingredients - case LOG_TYPE_MVP: - return 'U'; // MVP Rewards - case LOG_TYPE_COMMAND: - return 'A'; // (A)dmin command - case LOG_TYPE_STORAGE: - return 'R'; // Sto(R)age - case LOG_TYPE_GSTORAGE: - return 'G'; // (G)uild storage - case LOG_TYPE_MAIL: - return 'E'; // (E)mail attachment - case LOG_TYPE_AUCTION: - return 'I'; // Auct(I)on - case LOG_TYPE_BUYING_STORE: - return 'B'; // (B)uying Store - case LOG_TYPE_LOOT: - return 'L'; // (L)oot (consumed monster pick/drop) - case LOG_TYPE_OTHER: - return 'X'; // Other - } - - // should not get here, fallback - ShowDebug("log_picktype2char: Unknown pick type %d.\n", type); - return 'X'; + switch( type ) + { + case LOG_TYPE_TRADE: return 'T'; // (T)rade + case LOG_TYPE_VENDING: return 'V'; // (V)ending + case LOG_TYPE_PICKDROP_PLAYER: return 'P'; // (P)player + case LOG_TYPE_PICKDROP_MONSTER: return 'M'; // (M)onster + case LOG_TYPE_NPC: return 'S'; // NPC (S)hop + case LOG_TYPE_SCRIPT: return 'N'; // (N)PC Script + case LOG_TYPE_STEAL: return 'D'; // Steal/Snatcher + case LOG_TYPE_CONSUME: return 'C'; // (C)onsumed + case LOG_TYPE_PRODUCE: return 'O'; // Pr(O)duced/Ingredients + case LOG_TYPE_MVP: return 'U'; // MVP Rewards + case LOG_TYPE_COMMAND: return 'A'; // (A)dmin command + case LOG_TYPE_STORAGE: return 'R'; // Sto(R)age + case LOG_TYPE_GSTORAGE: return 'G'; // (G)uild storage + case LOG_TYPE_MAIL: return 'E'; // (E)mail attachment + case LOG_TYPE_AUCTION: return 'I'; // Auct(I)on + case LOG_TYPE_BUYING_STORE: return 'B'; // (B)uying Store + case LOG_TYPE_LOOT: return 'L'; // (L)oot (consumed monster pick/drop) + case LOG_TYPE_OTHER: return 'X'; // Other + } + + // should not get here, fallback + ShowDebug("log_picktype2char: Unknown pick type %d.\n", type); + return 'X'; } /// obtain log type character for chat logs static char log_chattype2char(e_log_chat_type type) { - switch (type) { - case LOG_CHAT_GLOBAL: - return 'O'; // Gl(O)bal - case LOG_CHAT_WHISPER: - return 'W'; // (W)hisper - case LOG_CHAT_PARTY: - return 'P'; // (P)arty - case LOG_CHAT_GUILD: - return 'G'; // (G)uild - case LOG_CHAT_MAINCHAT: - return 'M'; // (M)ain chat - } - - // should not get here, fallback - ShowDebug("log_chattype2char: Unknown chat type %d.\n", type); - return 'O'; + switch( type ) + { + case LOG_CHAT_GLOBAL: return 'O'; // Gl(O)bal + case LOG_CHAT_WHISPER: return 'W'; // (W)hisper + case LOG_CHAT_PARTY: return 'P'; // (P)arty + case LOG_CHAT_GUILD: return 'G'; // (G)uild + case LOG_CHAT_MAINCHAT: return 'M'; // (M)ain chat + } + + // should not get here, fallback + ShowDebug("log_chattype2char: Unknown chat type %d.\n", type); + return 'O'; } /// check if this item should be logged according the settings static bool should_log_item(int nameid, int amount, int refine) { - int filter = log_config.filter; - struct item_data *id; - - if ((id = itemdb_exists(nameid)) == NULL) - return false; - - if ((filter&LOG_FILTER_ALL) || - (filter&LOG_FILTER_HEALING && id->type == IT_HEALING) || - (filter&LOG_FILTER_ETC_AMMO && (id->type == IT_ETC || id->type == IT_AMMO)) || - (filter&LOG_FILTER_USABLE && (id->type == IT_USABLE || id->type == IT_CASH)) || - (filter&LOG_FILTER_WEAPON && id->type == IT_WEAPON) || - (filter&LOG_FILTER_ARMOR && id->type == IT_ARMOR) || - (filter&LOG_FILTER_CARD && id->type == IT_CARD) || - (filter&LOG_FILTER_PETITEM && (id->type == IT_PETEGG || id->type == IT_PETARMOR)) || - (filter&LOG_FILTER_PRICE && id->value_buy >= log_config.price_items_log) || - (filter&LOG_FILTER_AMOUNT && abs(amount) >= log_config.amount_items_log) || - (filter&LOG_FILTER_REFINE && refine >= log_config.refine_items_log) || - (filter&LOG_FILTER_CHANCE && ((id->maxchance != -1 && id->maxchance <= log_config.rare_items_log) || id->nameid == ITEMID_EMPERIUM)) - ) - return true; - - return false; + int filter = log_config.filter; + struct item_data* id; + + if( ( id = itemdb_exists(nameid) ) == NULL ) + return false; + + if( ( filter&LOG_FILTER_ALL ) || + ( filter&LOG_FILTER_HEALING && id->type == IT_HEALING ) || + ( filter&LOG_FILTER_ETC_AMMO && ( id->type == IT_ETC || id->type == IT_AMMO ) ) || + ( filter&LOG_FILTER_USABLE && ( id->type == IT_USABLE || id->type == IT_CASH ) ) || + ( filter&LOG_FILTER_WEAPON && id->type == IT_WEAPON ) || + ( filter&LOG_FILTER_ARMOR && id->type == IT_ARMOR ) || + ( filter&LOG_FILTER_CARD && id->type == IT_CARD ) || + ( filter&LOG_FILTER_PETITEM && ( id->type == IT_PETEGG || id->type == IT_PETARMOR ) ) || + ( filter&LOG_FILTER_PRICE && id->value_buy >= log_config.price_items_log ) || + ( filter&LOG_FILTER_AMOUNT && abs(amount) >= log_config.amount_items_log ) || + ( filter&LOG_FILTER_REFINE && refine >= log_config.refine_items_log ) || + ( filter&LOG_FILTER_CHANCE && ( ( id->maxchance != -1 && id->maxchance <= log_config.rare_items_log ) || id->nameid == ITEMID_EMPERIUM ) ) + ) + return true; + + return false; } /// logs items, that summon monsters -void log_branch(struct map_session_data *sd) +void log_branch(struct map_session_data* sd) { - nullpo_retv(sd); + nullpo_retv(sd); - if (!log_config.branch) - return; + if( !log_config.branch ) + return; - if (log_config.sql_logs) { + if( log_config.sql_logs ) { #ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%s')", log_config.log_branch, sd->status.account_id, sd->status.char_id, sd->status.name, mapindex_id2name(sd->mapindex)); - queryThread_log(entry,e_length); + char entry[512]; + int e_length = 0; + e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%s')", log_config.log_branch, sd->status.account_id, sd->status.char_id, sd->status.name, mapindex_id2name(sd->mapindex)); + queryThread_log(entry,e_length); #else - SqlStmt *stmt; - stmt = SqlStmt_Malloc(logmysql_handle); - if (SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', ?, '%s')", log_config.log_branch, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) - || SQL_SUCCESS != SqlStmt_Execute(stmt)) { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - return; - } - SqlStmt_Free(stmt); + SqlStmt* stmt; + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', ?, '%s')", log_config.log_branch, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return; + } + SqlStmt_Free(stmt); #endif - } else { - char timestring[255]; - time_t curtime; - FILE *logfp; - - if ((logfp = fopen(log_config.log_branch, "a")) == NULL) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %s[%d:%d]\t%s\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex)); - fclose(logfp); - } + } + else + { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(log_config.log_branch, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - %s[%d:%d]\t%s\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex)); + fclose(logfp); + } } /// logs item transactions (generic) -void log_pick(int id, int m, e_log_pick_type type, int amount, struct item *itm) +void log_pick(int id, int m, e_log_pick_type type, int amount, struct item* itm) { - nullpo_retv(itm); - if ((log_config.enable_logs&type) == 0) { - // disabled - return; - } + nullpo_retv(itm); + if( ( log_config.enable_logs&type ) == 0 ) + {// disabled + return; + } - if (!should_log_item(itm->nameid, amount, itm->refine)) - return; //we skip logging this item set - it doesn't meet our logging conditions [Lupus] + if( !should_log_item(itm->nameid, amount, itm->refine) ) + return; //we skip logging this item set - it doesn't meet our logging conditions [Lupus] - if (log_config.sql_logs) { + if( log_config.sql_logs ) + { #ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", - log_config.log_pick, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:""); - queryThread_log(entry,e_length); + char entry[512]; + int e_length = 0; + e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", + log_config.log_pick, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"" ); + queryThread_log(entry,e_length); #else - if (SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", - log_config.log_pick, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"")) { - Sql_ShowDebug(logmysql_handle); - return; - } + if( SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", + log_config.log_pick, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"") ) + { + Sql_ShowDebug(logmysql_handle); + return; + } #endif - } else { - char timestring[255]; - time_t curtime; - FILE *logfp; - - if ((logfp = fopen(log_config.log_pick, "a")) == NULL) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %d\t%c\t%d,%d,%d,%d,%d,%d,%d,%s\n", timestring, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:""); - fclose(logfp); - } + } + else + { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(log_config.log_pick, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - %d\t%c\t%d,%d,%d,%d,%d,%d,%d,%s\n", timestring, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:""); + fclose(logfp); + } } /// logs item transactions (players) -void log_pick_pc(struct map_session_data *sd, e_log_pick_type type, int amount, struct item *itm) +void log_pick_pc(struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm) { - nullpo_retv(sd); - log_pick(sd->status.char_id, sd->bl.m, type, amount, itm); + nullpo_retv(sd); + log_pick(sd->status.char_id, sd->bl.m, type, amount, itm); } /// logs item transactions (monsters) -void log_pick_mob(struct mob_data *md, e_log_pick_type type, int amount, struct item *itm) +void log_pick_mob(struct mob_data* md, e_log_pick_type type, int amount, struct item* itm) { - nullpo_retv(md); - log_pick(md->class_, md->bl.m, type, amount, itm); + nullpo_retv(md); + log_pick(md->class_, md->bl.m, type, amount, itm); } /// logs zeny transactions -void log_zeny(struct map_session_data *sd, e_log_pick_type type, struct map_session_data *src_sd, int amount) +void log_zeny(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount) { - nullpo_retv(sd); + nullpo_retv(sd); - if (!log_config.zeny || (log_config.zeny != 1 && abs(amount) < log_config.zeny)) - return; + if( !log_config.zeny || ( log_config.zeny != 1 && abs(amount) < log_config.zeny ) ) + return; - if (log_config.sql_logs) { + if( log_config.sql_logs ) + { #ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')", - log_config.log_zeny, sd->status.char_id, src_sd->status.char_id, log_picktype2char(type), amount, mapindex_id2name(sd->mapindex)); - queryThread_log(entry,e_length); + char entry[512]; + int e_length = 0; + e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')", + log_config.log_zeny, sd->status.char_id, src_sd->status.char_id, log_picktype2char(type), amount, mapindex_id2name(sd->mapindex)); + queryThread_log(entry,e_length); #else - if (SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')", - log_config.log_zeny, sd->status.char_id, src_sd->status.char_id, log_picktype2char(type), amount, mapindex_id2name(sd->mapindex))) { - Sql_ShowDebug(logmysql_handle); - return; - } + if( SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')", + log_config.log_zeny, sd->status.char_id, src_sd->status.char_id, log_picktype2char(type), amount, mapindex_id2name(sd->mapindex)) ) + { + Sql_ShowDebug(logmysql_handle); + return; + } #endif - } else { - char timestring[255]; - time_t curtime; - FILE *logfp; - - if ((logfp = fopen(log_config.log_zeny, "a")) == NULL) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp, "%s - %s[%d]\t%s[%d]\t%d\t\n", timestring, src_sd->status.name, src_sd->status.account_id, sd->status.name, sd->status.account_id, amount); - fclose(logfp); - } + } + else + { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(log_config.log_zeny, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %s[%d]\t%s[%d]\t%d\t\n", timestring, src_sd->status.name, src_sd->status.account_id, sd->status.name, sd->status.account_id, amount); + fclose(logfp); + } } /// logs MVP monster rewards -void log_mvpdrop(struct map_session_data *sd, int monster_id, int *log_mvp) +void log_mvpdrop(struct map_session_data* sd, int monster_id, int* log_mvp) { - nullpo_retv(sd); + nullpo_retv(sd); - if (!log_config.mvpdrop) - return; + if( !log_config.mvpdrop ) + return; - if (log_config.sql_logs) { + if( log_config.sql_logs ) + { #ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", - log_config.log_mvpdrop, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)); - queryThread_log(entry,e_length); -#else - if (SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", - log_config.log_mvpdrop, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex))) { - Sql_ShowDebug(logmysql_handle); - return; - } + char entry[512]; + int e_length = 0; + e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", + log_config.log_mvpdrop, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)); + queryThread_log(entry,e_length); +#else + if( SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", + log_config.log_mvpdrop, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)) ) + { + Sql_ShowDebug(logmysql_handle); + return; + } #endif - } else { - char timestring[255]; - time_t curtime; - FILE *logfp; - - if ((logfp = fopen(log_config.log_mvpdrop,"a")) == NULL) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1]); - fclose(logfp); - } + } + else + { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(log_config.log_mvpdrop,"a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1]); + fclose(logfp); + } } /// logs used atcommands -void log_atcommand(struct map_session_data *sd, const char *message) +void log_atcommand(struct map_session_data* sd, const char* message) { - nullpo_retv(sd); + nullpo_retv(sd); - if (!log_config.commands || - !pc_should_log_commands(sd)) - return; + if( !log_config.commands || + !pc_should_log_commands(sd) ) + return; - if (log_config.sql_logs) { + if( log_config.sql_logs ) + { #ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', '%s', '%s', '%s')", log_config.log_gm, sd->status.account_id, sd->status.char_id, sd->status.name ,mapindex_id2name(sd->mapindex), message); - queryThread_log(entry,e_length); -#else - SqlStmt *stmt; - - stmt = SqlStmt_Malloc(logmysql_handle); - if (SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_gm, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char *)message, safestrnlen(message, 255)) - || SQL_SUCCESS != SqlStmt_Execute(stmt)) { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - return; - } - SqlStmt_Free(stmt); + char entry[512]; + int e_length = 0; + e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', '%s', '%s', '%s')", log_config.log_gm, sd->status.account_id, sd->status.char_id, sd->status.name ,mapindex_id2name(sd->mapindex), message); + queryThread_log(entry,e_length); +#else + SqlStmt* stmt; + + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_gm, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return; + } + SqlStmt_Free(stmt); #endif - } else { - char timestring[255]; - time_t curtime; - FILE *logfp; - - if ((logfp = fopen(log_config.log_gm, "a")) == NULL) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); - fclose(logfp); - } + } + else + { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(log_config.log_gm, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); + fclose(logfp); + } } /// logs messages passed to script command 'logmes' -void log_npc(struct map_session_data *sd, const char *message) +void log_npc(struct map_session_data* sd, const char* message) { - nullpo_retv(sd); + nullpo_retv(sd); - if (!log_config.npc) - return; + if( !log_config.npc ) + return; - if (log_config.sql_logs) { + if( log_config.sql_logs ) + { #ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', '%s', '%s', '%s')", log_config.log_npc, sd->status.account_id, sd->status.char_id, sd->status.name, mapindex_id2name(sd->mapindex), message); - queryThread_log(entry,e_length); -#else - SqlStmt *stmt; - stmt = SqlStmt_Malloc(logmysql_handle); - if (SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_npc, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char *)message, safestrnlen(message, 255)) - || SQL_SUCCESS != SqlStmt_Execute(stmt)) { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - return; - } - SqlStmt_Free(stmt); + char entry[512]; + int e_length = 0; + e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', '%s', '%s', '%s')", log_config.log_npc, sd->status.account_id, sd->status.char_id, sd->status.name, mapindex_id2name(sd->mapindex), message ); + queryThread_log(entry,e_length); +#else + SqlStmt* stmt; + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_npc, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return; + } + SqlStmt_Free(stmt); #endif - } else { - char timestring[255]; - time_t curtime; - FILE *logfp; - - if ((logfp = fopen(log_config.log_npc, "a")) == NULL) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); - fclose(logfp); - } + } + else + { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(log_config.log_npc, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); + fclose(logfp); + } } /// logs chat -void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *map, int x, int y, const char *dst_charname, const char *message) +void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message) { - if ((log_config.chat&type) == 0) { - // disabled - return; - } + if( ( log_config.chat&type ) == 0 ) + {// disabled + return; + } - if (log_config.log_chat_woe_disable && (agit_flag || agit2_flag)) { - // no chat logging during woe - return; - } + if( log_config.log_chat_woe_disable && ( agit_flag || agit2_flag ) ) + {// no chat logging during woe + return; + } - if (log_config.sql_logs) { + if( log_config.sql_logs ) { #ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%c', '%d', '%d', '%d', '%s', '%d', '%d', '%s', '%s')", log_config.log_chat, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y, dst_charname, message); - queryThread_log(entry,e_length); -#else - SqlStmt *stmt; - - stmt = SqlStmt_Malloc(logmysql_handle); - if (SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%c', '%d', '%d', '%d', '%s', '%d', '%d', ?, ?)", log_config.log_chat, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (char *)dst_charname, safestrnlen(dst_charname, NAME_LENGTH)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char *)message, safestrnlen(message, CHAT_SIZE_MAX)) - || SQL_SUCCESS != SqlStmt_Execute(stmt)) { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - return; - } - SqlStmt_Free(stmt); + char entry[512]; + int e_length = 0; + e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%c', '%d', '%d', '%d', '%s', '%d', '%d', '%s', '%s')", log_config.log_chat, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y, dst_charname, message ); + queryThread_log(entry,e_length); +#else + SqlStmt* stmt; + + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%c', '%d', '%d', '%d', '%s', '%d', '%d', ?, ?)", log_config.log_chat, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (char*)dst_charname, safestrnlen(dst_charname, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, CHAT_SIZE_MAX)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return; + } + SqlStmt_Free(stmt); #endif - } else { - char timestring[255]; - time_t curtime; - FILE *logfp; - - if ((logfp = fopen(log_config.log_chat, "a")) == NULL) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp, "%s - %c,%d,%d,%d,%s,%d,%d,%s,%s\n", timestring, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y, dst_charname, message); - fclose(logfp); - } + } + else + { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(log_config.log_chat, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %c,%d,%d,%d,%s,%d,%d,%s,%s\n", timestring, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y, dst_charname, message); + fclose(logfp); + } } void log_set_defaults(void) { - memset(&log_config, 0, sizeof(log_config)); + memset(&log_config, 0, sizeof(log_config)); - //LOG FILTER Default values - log_config.refine_items_log = 5; // log refined items, with refine >= +5 - 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; + //LOG FILTER Default values + log_config.refine_items_log = 5; // log refined items, with refine >= +5 + 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; } -int log_config_read(const char *cfgName) +int log_config_read(const char* cfgName) { - static int count = 0; - char line[1024], w1[1024], w2[1024]; - FILE *fp; - - if (count++ == 0) - log_set_defaults(); - - if ((fp = fopen(cfgName, "r")) == NULL) { - ShowError("Log configuration file not found at: %s\n", cfgName); - return 1; - } - - while (fgets(line, sizeof(line), fp)) { - if (line[0] == '/' && line[1] == '/') - continue; - - if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) { - if (strcmpi(w1, "enable_logs") == 0) - log_config.enable_logs = (e_log_pick_type)config_switch(w2); - else if (strcmpi(w1, "sql_logs") == 0) - log_config.sql_logs = (bool)config_switch(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 = config_switch(w2); - else if (strcmpi(w1, "log_filter") == 0) - log_config.filter = config_switch(w2); - else if (strcmpi(w1, "log_zeny") == 0) - log_config.zeny = config_switch(w2); - else if (strcmpi(w1, "log_commands") == 0) - log_config.commands = config_switch(w2); - else if (strcmpi(w1, "log_npc") == 0) - log_config.npc = config_switch(w2); - else if (strcmpi(w1, "log_chat") == 0) - log_config.chat = config_switch(w2); - else if (strcmpi(w1, "log_mvpdrop") == 0) - log_config.mvpdrop = config_switch(w2); - else if (strcmpi(w1, "log_chat_woe_disable") == 0) - log_config.log_chat_woe_disable = (bool)config_switch(w2); - else if (strcmpi(w1, "log_branch_db") == 0) - safestrncpy(log_config.log_branch, w2, sizeof(log_config.log_branch)); - else if (strcmpi(w1, "log_pick_db") == 0) - safestrncpy(log_config.log_pick, w2, sizeof(log_config.log_pick)); - else if (strcmpi(w1, "log_zeny_db") == 0) - safestrncpy(log_config.log_zeny, w2, sizeof(log_config.log_zeny)); - else if (strcmpi(w1, "log_mvpdrop_db") == 0) - safestrncpy(log_config.log_mvpdrop, w2, sizeof(log_config.log_mvpdrop)); - else if (strcmpi(w1, "log_gm_db") == 0) - safestrncpy(log_config.log_gm, w2, sizeof(log_config.log_gm)); - else if (strcmpi(w1, "log_npc_db") == 0) - safestrncpy(log_config.log_npc, w2, sizeof(log_config.log_npc)); - else if (strcmpi(w1, "log_chat_db") == 0) - safestrncpy(log_config.log_chat, w2, sizeof(log_config.log_chat)); - //support the import command, just like any other config - else if (strcmpi(w1,"import") == 0) - log_config_read(w2); - else - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); - } - } - - fclose(fp); - - if (--count == 0) { - // report final logging state - const char *target = log_config.sql_logs ? "table" : "file"; - - if (log_config.enable_logs && log_config.filter) { - ShowInfo("Logging item transactions to %s '%s'.\n", target, log_config.log_pick); - } - if (log_config.branch) { - ShowInfo("Logging monster summon item usage to %s '%s'.\n", target, log_config.log_pick); - } - if (log_config.chat) { - ShowInfo("Logging chat to %s '%s'.\n", target, log_config.log_chat); - } - if (log_config.commands) { - ShowInfo("Logging commands to %s '%s'.\n", target, log_config.log_gm); - } - if (log_config.mvpdrop) { - ShowInfo("Logging MVP monster rewards to %s '%s'.\n", target, log_config.log_mvpdrop); - } - if (log_config.npc) { - ShowInfo("Logging 'logmes' messages to %s '%s'.\n", target, log_config.log_npc); - } - if (log_config.zeny) { - ShowInfo("Logging Zeny transactions to %s '%s'.\n", target, log_config.log_zeny); - } - } - - return 0; + static int count = 0; + char line[1024], w1[1024], w2[1024]; + FILE *fp; + + if( count++ == 0 ) + log_set_defaults(); + + if( ( fp = fopen(cfgName, "r") ) == NULL ) + { + ShowError("Log configuration file not found at: %s\n", cfgName); + return 1; + } + + while( fgets(line, sizeof(line), fp) ) + { + if( line[0] == '/' && line[1] == '/' ) + continue; + + if( sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 ) + { + if( strcmpi(w1, "enable_logs") == 0 ) + log_config.enable_logs = (e_log_pick_type)config_switch(w2); + else if( strcmpi(w1, "sql_logs") == 0 ) + log_config.sql_logs = (bool)config_switch(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 = config_switch(w2); + else if( strcmpi(w1, "log_filter") == 0 ) + log_config.filter = config_switch(w2); + else if( strcmpi(w1, "log_zeny") == 0 ) + log_config.zeny = config_switch(w2); + else if( strcmpi(w1, "log_commands") == 0 ) + log_config.commands = config_switch(w2); + else if( strcmpi(w1, "log_npc") == 0 ) + log_config.npc = config_switch(w2); + else if( strcmpi(w1, "log_chat") == 0 ) + log_config.chat = config_switch(w2); + else if( strcmpi(w1, "log_mvpdrop") == 0 ) + log_config.mvpdrop = config_switch(w2); + else if( strcmpi(w1, "log_chat_woe_disable") == 0 ) + log_config.log_chat_woe_disable = (bool)config_switch(w2); + else if( strcmpi(w1, "log_branch_db") == 0 ) + safestrncpy(log_config.log_branch, w2, sizeof(log_config.log_branch)); + else if( strcmpi(w1, "log_pick_db") == 0 ) + safestrncpy(log_config.log_pick, w2, sizeof(log_config.log_pick)); + else if( strcmpi(w1, "log_zeny_db") == 0 ) + safestrncpy(log_config.log_zeny, w2, sizeof(log_config.log_zeny)); + else if( strcmpi(w1, "log_mvpdrop_db") == 0 ) + safestrncpy(log_config.log_mvpdrop, w2, sizeof(log_config.log_mvpdrop)); + else if( strcmpi(w1, "log_gm_db") == 0 ) + safestrncpy(log_config.log_gm, w2, sizeof(log_config.log_gm)); + else if( strcmpi(w1, "log_npc_db") == 0 ) + safestrncpy(log_config.log_npc, w2, sizeof(log_config.log_npc)); + else if( strcmpi(w1, "log_chat_db") == 0 ) + safestrncpy(log_config.log_chat, w2, sizeof(log_config.log_chat)); + //support the import command, just like any other config + else if( strcmpi(w1,"import") == 0 ) + log_config_read(w2); + else + ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); + } + } + + fclose(fp); + + if( --count == 0 ) + {// report final logging state + const char* target = log_config.sql_logs ? "table" : "file"; + + if( log_config.enable_logs && log_config.filter ) + { + ShowInfo("Logging item transactions to %s '%s'.\n", target, log_config.log_pick); + } + if( log_config.branch ) + { + ShowInfo("Logging monster summon item usage to %s '%s'.\n", target, log_config.log_pick); + } + if( log_config.chat ) + { + ShowInfo("Logging chat to %s '%s'.\n", target, log_config.log_chat); + } + if( log_config.commands ) + { + ShowInfo("Logging commands to %s '%s'.\n", target, log_config.log_gm); + } + if( log_config.mvpdrop ) + { + ShowInfo("Logging MVP monster rewards to %s '%s'.\n", target, log_config.log_mvpdrop); + } + if( log_config.npc ) + { + ShowInfo("Logging 'logmes' messages to %s '%s'.\n", target, log_config.log_npc); + } + if( log_config.zeny ) + { + ShowInfo("Logging Zeny transactions to %s '%s'.\n", target, log_config.log_zeny); + } + } + + return 0; } diff --git a/src/map/log.h b/src/map/log.h index 051e31fc0..a40a3fcf4 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -11,76 +11,79 @@ struct mob_data; struct item; -typedef enum e_log_chat_type { - LOG_CHAT_GLOBAL = 0x01, - LOG_CHAT_WHISPER = 0x02, - LOG_CHAT_PARTY = 0x04, - LOG_CHAT_GUILD = 0x08, - LOG_CHAT_MAINCHAT = 0x10, - // all - LOG_CHAT_ALL = 0xFF, +typedef enum e_log_chat_type +{ + LOG_CHAT_GLOBAL = 0x01, + LOG_CHAT_WHISPER = 0x02, + LOG_CHAT_PARTY = 0x04, + LOG_CHAT_GUILD = 0x08, + LOG_CHAT_MAINCHAT = 0x10, + // all + LOG_CHAT_ALL = 0xFF, } e_log_chat_type; -typedef enum e_log_pick_type { - LOG_TYPE_NONE = 0, - LOG_TYPE_TRADE = 0x00001, - LOG_TYPE_VENDING = 0x00002, - LOG_TYPE_PICKDROP_PLAYER = 0x00004, - LOG_TYPE_PICKDROP_MONSTER = 0x00008, - LOG_TYPE_NPC = 0x00010, - LOG_TYPE_SCRIPT = 0x00020, - LOG_TYPE_STEAL = 0x00040, - LOG_TYPE_CONSUME = 0x00080, - LOG_TYPE_PRODUCE = 0x00100, - LOG_TYPE_MVP = 0x00200, - LOG_TYPE_COMMAND = 0x00400, - LOG_TYPE_STORAGE = 0x00800, - LOG_TYPE_GSTORAGE = 0x01000, - LOG_TYPE_MAIL = 0x02000, - LOG_TYPE_AUCTION = 0x04000, - LOG_TYPE_BUYING_STORE = 0x08000, - LOG_TYPE_OTHER = 0x10000, - // combinations - LOG_TYPE_LOOT = LOG_TYPE_PICKDROP_MONSTER|LOG_TYPE_CONSUME, - // all - LOG_TYPE_ALL = 0xFFFFF, +typedef enum e_log_pick_type +{ + LOG_TYPE_NONE = 0, + LOG_TYPE_TRADE = 0x00001, + LOG_TYPE_VENDING = 0x00002, + LOG_TYPE_PICKDROP_PLAYER = 0x00004, + LOG_TYPE_PICKDROP_MONSTER = 0x00008, + LOG_TYPE_NPC = 0x00010, + LOG_TYPE_SCRIPT = 0x00020, + LOG_TYPE_STEAL = 0x00040, + LOG_TYPE_CONSUME = 0x00080, + LOG_TYPE_PRODUCE = 0x00100, + LOG_TYPE_MVP = 0x00200, + LOG_TYPE_COMMAND = 0x00400, + LOG_TYPE_STORAGE = 0x00800, + LOG_TYPE_GSTORAGE = 0x01000, + LOG_TYPE_MAIL = 0x02000, + LOG_TYPE_AUCTION = 0x04000, + LOG_TYPE_BUYING_STORE = 0x08000, + LOG_TYPE_OTHER = 0x10000, + // combinations + LOG_TYPE_LOOT = LOG_TYPE_PICKDROP_MONSTER|LOG_TYPE_CONSUME, + // all + LOG_TYPE_ALL = 0xFFFFF, } e_log_pick_type; /// new logs -void log_pick_pc(struct map_session_data *sd, e_log_pick_type type, int amount, struct item *itm); -void log_pick_mob(struct mob_data *md, e_log_pick_type type, int amount, struct item *itm); -void log_zeny(struct map_session_data *sd, e_log_pick_type type, struct map_session_data *src_sd, int amount); +void log_pick_pc(struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm); +void log_pick_mob(struct mob_data* md, e_log_pick_type type, int amount, struct item* itm); +void log_zeny(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount); -void log_npc(struct map_session_data *sd, const char *message); -void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *map, int x, int y, const char *dst_charname, const char *message); -void log_atcommand(struct map_session_data *sd, const char *message); +void log_npc(struct map_session_data* sd, const char *message); +void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message); +void log_atcommand(struct map_session_data* sd, const char* message); /// old, but useful logs -void log_branch(struct map_session_data *sd); -void log_mvpdrop(struct map_session_data *sd, int monster_id, int *log_mvp); +void log_branch(struct map_session_data* sd); +void log_mvpdrop(struct map_session_data* sd, int monster_id, int* log_mvp); -int log_config_read(const char *cfgName); +int log_config_read(const char* cfgName); -extern struct Log_Config { - e_log_pick_type enable_logs; - int filter; - bool sql_logs; - bool log_chat_woe_disable; - int rare_items_log,refine_items_log,price_items_log,amount_items_log; //for filter - int branch, mvpdrop, zeny, commands, npc, chat; - char log_branch[64], log_pick[64], log_zeny[64], log_mvpdrop[64], log_gm[64], log_npc[64], log_chat[64]; +extern struct Log_Config +{ + e_log_pick_type enable_logs; + int filter; + bool sql_logs; + bool log_chat_woe_disable; + int rare_items_log,refine_items_log,price_items_log,amount_items_log; //for filter + int branch, mvpdrop, zeny, commands, npc, chat; + char log_branch[64], log_pick[64], log_zeny[64], log_mvpdrop[64], log_gm[64], log_npc[64], log_chat[64]; } log_config; #ifdef BETA_THREAD_TEST -struct { - char **entry; - int count; -} logThreadData; + struct { + char** entry; + int count; + } logThreadData; #endif #endif /* _LOG_H_ */ diff --git a/src/map/mail.c b/src/map/mail.c index ecd79f957..03b8227b5 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -16,164 +16,170 @@ void mail_clear(struct map_session_data *sd) { - sd->mail.nameid = 0; - sd->mail.index = 0; - sd->mail.amount = 0; - sd->mail.zeny = 0; + sd->mail.nameid = 0; + sd->mail.index = 0; + sd->mail.amount = 0; + sd->mail.zeny = 0; - return; + return; } int mail_removeitem(struct map_session_data *sd, short flag) { - nullpo_ret(sd); - - if (sd->mail.amount) { - if (flag) // Item send - pc_delitem(sd, sd->mail.index, sd->mail.amount, 1, 0, LOG_TYPE_MAIL); - else - clif_additem(sd, sd->mail.index, sd->mail.amount, 0); - } - - sd->mail.nameid = 0; - sd->mail.index = 0; - sd->mail.amount = 0; - return 1; + nullpo_ret(sd); + + if( sd->mail.amount ) + { + if (flag) // Item send + pc_delitem(sd, sd->mail.index, sd->mail.amount, 1, 0, LOG_TYPE_MAIL); + else + clif_additem(sd, sd->mail.index, sd->mail.amount, 0); + } + + sd->mail.nameid = 0; + sd->mail.index = 0; + sd->mail.amount = 0; + return 1; } int mail_removezeny(struct map_session_data *sd, short flag) { - nullpo_ret(sd); + nullpo_ret(sd); - if (flag && sd->mail.zeny > 0) { - //Zeny send - pc_payzeny(sd,sd->mail.zeny,LOG_TYPE_MAIL, NULL); - } - sd->mail.zeny = 0; + if (flag && sd->mail.zeny > 0) + { //Zeny send + pc_payzeny(sd,sd->mail.zeny,LOG_TYPE_MAIL, NULL); + } + sd->mail.zeny = 0; - return 1; + return 1; } -unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) -{ +unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) { + + if( pc_istrading(sd) ) + return 1; + + if( idx == 0 ) { // Zeny Transfer + if( amount < 0 || !pc_can_give_items(sd) ) + return 1; + + if( amount > sd->status.zeny ) + amount = sd->status.zeny; + + sd->mail.zeny = amount; + // clif_updatestatus(sd, SP_ZENY); + return 0; + } else { // Item Transfer + idx -= 2; + mail_removeitem(sd, 0); + + if( idx < 0 || idx >= MAX_INVENTORY ) + return 1; + if( amount < 0 || amount > sd->status.inventory[idx].amount ) + return 1; + if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time || + !itemdb_canmail(&sd->status.inventory[idx],pc_get_group_level(sd)) ) + return 1; + + sd->mail.index = idx; + sd->mail.nameid = sd->status.inventory[idx].nameid; + sd->mail.amount = amount; - if (pc_istrading(sd)) - return 1; - - if (idx == 0) { // Zeny Transfer - if (amount < 0 || !pc_can_give_items(sd)) - return 1; - - if (amount > sd->status.zeny) - amount = sd->status.zeny; - - sd->mail.zeny = amount; - // clif_updatestatus(sd, SP_ZENY); - return 0; - } else { // Item Transfer - idx -= 2; - mail_removeitem(sd, 0); - - if (idx < 0 || idx >= MAX_INVENTORY) - return 1; - if (amount < 0 || amount > sd->status.inventory[idx].amount) - return 1; - if (!pc_can_give_items(sd) || sd->status.inventory[idx].expire_time || - !itemdb_canmail(&sd->status.inventory[idx],pc_get_group_level(sd))) - return 1; - - sd->mail.index = idx; - sd->mail.nameid = sd->status.inventory[idx].nameid; - sd->mail.amount = amount; - - return 0; - } + return 0; + } } bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg) { - int n; + int n; - nullpo_retr(false,sd); - nullpo_retr(false,msg); + nullpo_retr(false,sd); + nullpo_retr(false,msg); - if (sd->mail.zeny < 0 || sd->mail.zeny > sd->status.zeny) - return false; + if( sd->mail.zeny < 0 || sd->mail.zeny > sd->status.zeny ) + return false; - n = sd->mail.index; - if (sd->mail.amount) { - if (sd->status.inventory[n].nameid != sd->mail.nameid) - return false; + n = sd->mail.index; + if( sd->mail.amount ) + { + if( sd->status.inventory[n].nameid != sd->mail.nameid ) + return false; - if (sd->status.inventory[n].amount < sd->mail.amount) - return false; + if( sd->status.inventory[n].amount < sd->mail.amount ) + return false; - if (sd->weight > sd->max_weight) - return false; + if( sd->weight > sd->max_weight ) + return false; - memcpy(&msg->item, &sd->status.inventory[n], sizeof(struct item)); - msg->item.amount = sd->mail.amount; - } else - memset(&msg->item, 0x00, sizeof(struct item)); + memcpy(&msg->item, &sd->status.inventory[n], sizeof(struct item)); + msg->item.amount = sd->mail.amount; + } + else + memset(&msg->item, 0x00, sizeof(struct item)); - msg->zeny = sd->mail.zeny; + msg->zeny = sd->mail.zeny; - // Removes the attachment from sender - mail_removeitem(sd,1); - mail_removezeny(sd,1); + // Removes the attachment from sender + mail_removeitem(sd,1); + mail_removezeny(sd,1); - return true; + return true; } -void mail_getattachment(struct map_session_data *sd, int zeny, struct item *item) +void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item) { - if (item->nameid > 0 && item->amount > 0) { - pc_additem(sd, item, item->amount, LOG_TYPE_MAIL); - clif_Mail_getattachment(sd->fd, 0); - } - - if (zeny > 0) { - //Zeny receive - pc_getzeny(sd, zeny,LOG_TYPE_MAIL, NULL); - } + if( item->nameid > 0 && item->amount > 0 ) + { + pc_additem(sd, item, item->amount, LOG_TYPE_MAIL); + clif_Mail_getattachment(sd->fd, 0); + } + + if( zeny > 0 ) + { //Zeny receive + pc_getzeny(sd, zeny,LOG_TYPE_MAIL, NULL); + } } int mail_openmail(struct map_session_data *sd) { - nullpo_ret(sd); + nullpo_ret(sd); - if (sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading) - return 0; + if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading ) + return 0; - clif_Mail_window(sd->fd, 0); + clif_Mail_window(sd->fd, 0); - return 1; + return 1; } void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg) { - nullpo_retv(sd); - nullpo_retv(msg); + nullpo_retv(sd); + nullpo_retv(msg); - if (msg->item.amount > 0) { - // Item receive (due to failure) - pc_additem(sd, &msg->item, msg->item.amount, LOG_TYPE_MAIL); - } + if( msg->item.amount > 0 ) + { + // Item receive (due to failure) + pc_additem(sd, &msg->item, msg->item.amount, LOG_TYPE_MAIL); + } - if (msg->zeny > 0) { - pc_getzeny(sd,msg->zeny,LOG_TYPE_MAIL, NULL); //Zeny receive (due to failure) - } + if( msg->zeny > 0 ) + { + pc_getzeny(sd,msg->zeny,LOG_TYPE_MAIL, NULL); //Zeny receive (due to failure) + } - clif_Mail_send(sd->fd, true); + clif_Mail_send(sd->fd, true); } // This function only check if the mail operations are valid bool mail_invalid_operation(struct map_session_data *sd) { - if (!map[sd->bl.m].flag.town && !pc_can_use_command(sd, "mail", COMMAND_ATCOMMAND)) { - ShowWarning("clif_parse_Mail: char '%s' trying to do invalid mail operations.\n", sd->status.name); - return true; - } + if( !map[sd->bl.m].flag.town && !pc_can_use_command(sd, "mail", COMMAND_ATCOMMAND) ) + { + ShowWarning("clif_parse_Mail: char '%s' trying to do invalid mail operations.\n", sd->status.name); + return true; + } - return false; + return false; } diff --git a/src/map/mail.h b/src/map/mail.h index eb4e76c4d..cab582e55 100644 --- a/src/map/mail.h +++ b/src/map/mail.h @@ -11,7 +11,7 @@ int mail_removeitem(struct map_session_data *sd, short flag); int mail_removezeny(struct map_session_data *sd, short flag); unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount); bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg); -void mail_getattachment(struct map_session_data *sd, int zeny, struct item *item); +void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item); int mail_openmail(struct map_session_data *sd); void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg); bool mail_invalid_operation(struct map_session_data *sd); diff --git a/src/map/map.c b/src/map/map.c index 69e343fb3..9238af9f9 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -61,7 +61,7 @@ char map_server_ip[32] = "127.0.0.1"; char map_server_id[32] = "ragnarok"; char map_server_pw[32] = "ragnarok"; char map_server_db[32] = "ragnarok"; -Sql *mmysql_handle; +Sql* mmysql_handle; int db_use_sqldbs = 0; char item_db_db[32] = "item_db"; @@ -78,7 +78,7 @@ int log_db_port = 3306; char log_db_id[32] = "ragnarok"; char log_db_pw[32] = "ragnarok"; char log_db_db[32] = "log"; -Sql *logmysql_handle; +Sql* logmysql_handle; // This param using for sending mainchat // messages like whispers to this nick. [LuzZza] @@ -94,14 +94,14 @@ char *MSG_CONF_NAME; char *GRF_PATH_FILENAME; // DBMap declaartion -static DBMap *id_db=NULL; // int id -> struct block_list* -static DBMap *pc_db=NULL; // int id -> struct map_session_data* -static DBMap *mobid_db=NULL; // int id -> struct mob_data* -static DBMap *bossid_db=NULL; // int id -> struct mob_data* (MVP db) -static DBMap *map_db=NULL; // unsigned int mapindex -> struct map_data* -static DBMap *nick_db=NULL; // int char_id -> struct charid2nick* (requested names of offline characters) -static DBMap *charid_db=NULL; // int char_id -> struct map_session_data* -static DBMap *regen_db=NULL; // int id -> struct block_list* (status_natural_heal processing) +static DBMap* id_db=NULL; // int id -> struct block_list* +static DBMap* pc_db=NULL; // int id -> struct map_session_data* +static DBMap* mobid_db=NULL; // int id -> struct mob_data* +static DBMap* bossid_db=NULL; // int id -> struct mob_data* (MVP db) +static DBMap* map_db=NULL; // unsigned int mapindex -> struct map_data* +static DBMap* nick_db=NULL; // int char_id -> struct charid2nick* (requested names of offline characters) +static DBMap* charid_db=NULL; // int char_id -> struct map_session_data* +static DBMap* regen_db=NULL; // int id -> struct block_list* (status_natural_heal processing) static int map_users=0; @@ -126,26 +126,26 @@ int agit2_flag = 0; int night_flag = 0; // 0=day, 1=night [Yor] struct charid_request { - struct charid_request *next; - int charid;// who want to be notified of the nick + struct charid_request* next; + int charid;// who want to be notified of the nick }; struct charid2nick { - char nick[NAME_LENGTH]; - struct charid_request *requests;// requests of notification on this nick + char nick[NAME_LENGTH]; + struct charid_request* requests;// requests of notification on this nick }; // This is the main header found at the very beginning of the map cache struct map_cache_main_header { - uint32 file_size; - uint16 map_count; + uint32 file_size; + uint16 map_count; }; // This is the header appended before every compressed map cells info in the map cache struct map_cache_map_info { - char name[MAP_NAME_LENGTH]; - int16 xs; - int16 ys; - int32 len; + char name[MAP_NAME_LENGTH]; + int16 xs; + int16 ys; + int32 len; }; char db_path[256] = "db"; @@ -158,19 +158,19 @@ char wisp_server_name[NAME_LENGTH] = "Server"; // can be modified in char-server int console = 0; int enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex] -int enable_grf = 0; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89] +int enable_grf = 0; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89] /*========================================== * server player count (of all mapservers) *------------------------------------------*/ void map_setusers(int users) { - map_users = users; + map_users = users; } int map_getusers(void) { - return map_users; + return map_users; } /*========================================== @@ -178,65 +178,67 @@ int map_getusers(void) *------------------------------------------*/ int map_usercount(void) { - return pc_db->size(pc_db); + return pc_db->size(pc_db); } /*========================================== * Attempt to free a map blocklist *------------------------------------------*/ -int map_freeblock(struct block_list *bl) +int map_freeblock (struct block_list *bl) { - nullpo_retr(block_free_lock, bl); - if (block_free_lock == 0 || block_free_count >= block_free_max) { - aFree(bl); - bl = NULL; - if (block_free_count >= block_free_max) - ShowWarning("map_freeblock: too many free block! %d %d\n", block_free_count, block_free_lock); - } else - block_free[block_free_count++] = bl; + nullpo_retr(block_free_lock, bl); + if (block_free_lock == 0 || block_free_count >= block_free_max) + { + aFree(bl); + bl = NULL; + if (block_free_count >= block_free_max) + ShowWarning("map_freeblock: too many free block! %d %d\n", block_free_count, block_free_lock); + } else + block_free[block_free_count++] = bl; - return block_free_lock; + return block_free_lock; } /*========================================== * Lock blocklist, (prevent map_freeblock usage) *------------------------------------------*/ -int map_freeblock_lock(void) +int map_freeblock_lock (void) { - return ++block_free_lock; + return ++block_free_lock; } /*========================================== * Remove the lock on map_bl *------------------------------------------*/ -int map_freeblock_unlock(void) +int map_freeblock_unlock (void) { - if ((--block_free_lock) == 0) { - int i; - for (i = 0; i < block_free_count; i++) { - aFree(block_free[i]); - block_free[i] = NULL; - } - block_free_count = 0; - } else if (block_free_lock < 0) { - ShowError("map_freeblock_unlock: lock count < 0 !\n"); - block_free_lock = 0; - } + if ((--block_free_lock) == 0) { + int i; + for (i = 0; i < block_free_count; i++) + { + aFree(block_free[i]); + block_free[i] = NULL; + } + block_free_count = 0; + } else if (block_free_lock < 0) { + ShowError("map_freeblock_unlock: lock count < 0 !\n"); + block_free_lock = 0; + } - return block_free_lock; + return block_free_lock; } // Timer function to check if there some remaining lock and remove them if so. // Called each 1s int map_freeblock_timer(int tid, unsigned int tick, int id, intptr_t data) { - if (block_free_lock > 0) { - ShowError("map_freeblock_timer: block_free_lock(%d) is invalid.\n", block_free_lock); - block_free_lock = 1; - map_freeblock_unlock(); - } + if (block_free_lock > 0) { + ShowError("map_freeblock_timer: block_free_lock(%d) is invalid.\n", block_free_lock); + block_free_lock = 1; + map_freeblock_unlock(); + } - return 0; + return 0; } // @@ -255,17 +257,17 @@ static struct block_list bl_head; *------------------------------------------*/ static void map_addblcell(struct block_list *bl) { - if (bl->m<0 || bl->x<0 || bl->x>=map[bl->m].xs || bl->y<0 || bl->y>=map[bl->m].ys || !(bl->type&BL_CHAR)) - return; - map[bl->m].cell[bl->x+bl->y*map[bl->m].xs].cell_bl++; - return; + if( bl->m<0 || bl->x<0 || bl->x>=map[bl->m].xs || bl->y<0 || bl->y>=map[bl->m].ys || !(bl->type&BL_CHAR) ) + return; + map[bl->m].cell[bl->x+bl->y*map[bl->m].xs].cell_bl++; + return; } static void map_delblcell(struct block_list *bl) { - if (bl->m <0 || bl->x<0 || bl->x>=map[bl->m].xs || bl->y<0 || bl->y>=map[bl->m].ys || !(bl->type&BL_CHAR)) - return; - map[bl->m].cell[bl->x+bl->y*map[bl->m].xs].cell_bl--; + if( bl->m <0 || bl->x<0 || bl->x>=map[bl->m].xs || bl->y<0 || bl->y>=map[bl->m].ys || !(bl->type&BL_CHAR) ) + return; + map[bl->m].cell[bl->x+bl->y*map[bl->m].xs].cell_bl--; } #endif @@ -273,89 +275,91 @@ static void map_delblcell(struct block_list *bl) * Adds a block to the map. * Returns 0 on success, 1 on failure (illegal coordinates). *------------------------------------------*/ -int map_addblock(struct block_list *bl) -{ - int m, x, y, pos; - - nullpo_ret(bl); - - if (bl->prev != NULL) { - ShowError("map_addblock: bl->prev != NULL\n"); - return 1; - } - - m = bl->m; - x = bl->x; - y = bl->y; - if (m < 0 || m >= map_num) { - ShowError("map_addblock: invalid map id (%d), only %d are loaded.\n", m, map_num); - return 1; - } - if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys) { - ShowError("map_addblock: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d\n", map[m].name, x, y, map[m].xs, map[m].ys); - return 1; - } - - pos = x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs; - - if (bl->type == BL_MOB) { - bl->next = map[m].block_mob[pos]; - bl->prev = &bl_head; - if (bl->next) bl->next->prev = bl; - map[m].block_mob[pos] = bl; - } else { - bl->next = map[m].block[pos]; - bl->prev = &bl_head; - if (bl->next) bl->next->prev = bl; - map[m].block[pos] = bl; - } +int map_addblock(struct block_list* bl) +{ + int m, x, y, pos; + + nullpo_ret(bl); + + if (bl->prev != NULL) { + ShowError("map_addblock: bl->prev != NULL\n"); + return 1; + } + + m = bl->m; + x = bl->x; + y = bl->y; + if( m < 0 || m >= map_num ) + { + ShowError("map_addblock: invalid map id (%d), only %d are loaded.\n", m, map_num); + return 1; + } + if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) + { + ShowError("map_addblock: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d\n", map[m].name, x, y, map[m].xs, map[m].ys); + return 1; + } + + pos = x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs; + + if (bl->type == BL_MOB) { + bl->next = map[m].block_mob[pos]; + bl->prev = &bl_head; + if (bl->next) bl->next->prev = bl; + map[m].block_mob[pos] = bl; + } else { + bl->next = map[m].block[pos]; + bl->prev = &bl_head; + if (bl->next) bl->next->prev = bl; + map[m].block[pos] = bl; + } #ifdef CELL_NOSTACK - map_addblcell(bl); + map_addblcell(bl); #endif - return 0; + return 0; } /*========================================== * Removes a block from the map. *------------------------------------------*/ -int map_delblock(struct block_list *bl) +int map_delblock(struct block_list* bl) { - int pos; - nullpo_ret(bl); + int pos; + nullpo_ret(bl); // blocklist (2ways chainlist) - if (bl->prev == NULL) { - if (bl->next != NULL) { - // can't delete block (already at the begining of the chain) - ShowError("map_delblock error : bl->next!=NULL\n"); - } - return 0; - } + if (bl->prev == NULL) { + if (bl->next != NULL) { + // can't delete block (already at the begining of the chain) + ShowError("map_delblock error : bl->next!=NULL\n"); + } + return 0; + } #ifdef CELL_NOSTACK - map_delblcell(bl); + map_delblcell(bl); #endif - pos = bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs; + pos = bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs; - if (bl->next) - bl->next->prev = bl->prev; - if (bl->prev == &bl_head) { - //Since the head of the list, update the block_list map of [] - if (bl->type == BL_MOB) { - map[bl->m].block_mob[pos] = bl->next; - } else { - map[bl->m].block[pos] = bl->next; - } - } else { - bl->prev->next = bl->next; - } - bl->next = NULL; - bl->prev = NULL; + if (bl->next) + bl->next->prev = bl->prev; + if (bl->prev == &bl_head) { + //Since the head of the list, update the block_list map of [] + if (bl->type == BL_MOB) { + map[bl->m].block_mob[pos] = bl->next; + } else { + map[bl->m].block[pos] = bl->next; + } + } else { + bl->prev->next = bl->next; + } + bl->next = NULL; + bl->prev = NULL; - return 0; + return 0; } /*========================================== @@ -365,105 +369,107 @@ int map_delblock(struct block_list *bl) *------------------------------------------*/ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) { - int x0 = bl->x, y0 = bl->y; - struct status_change *sc = NULL; - int moveblock = (x0/BLOCK_SIZE != x1/BLOCK_SIZE || y0/BLOCK_SIZE != y1/BLOCK_SIZE); - - if (!bl->prev) { - //Block not in map, just update coordinates, but do naught else. - bl->x = x1; - bl->y = y1; - return 0; - } - - //TODO: Perhaps some outs of bounds checking should be placed here? - if (bl->type&BL_CHAR) { - sc = status_get_sc(bl); - - skill_unit_move(bl,tick,2); - status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); - status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); - // status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure... - status_change_end(bl, SC_TATAMIGAESHI, INVALID_TIMER); - status_change_end(bl, SC_MAGICROD, INVALID_TIMER); - if (sc->data[SC_PROPERTYWALK] && - sc->data[SC_PROPERTYWALK]->val3 >= skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2)) - status_change_end(bl,SC_PROPERTYWALK,INVALID_TIMER); - } else if (bl->type == BL_NPC) - npc_unsetcells((TBL_NPC *)bl); - - if (moveblock) map_delblock(bl); + int x0 = bl->x, y0 = bl->y; + struct status_change *sc = NULL; + int moveblock = ( x0/BLOCK_SIZE != x1/BLOCK_SIZE || y0/BLOCK_SIZE != y1/BLOCK_SIZE); + + if (!bl->prev) { + //Block not in map, just update coordinates, but do naught else. + bl->x = x1; + bl->y = y1; + return 0; + } + + //TODO: Perhaps some outs of bounds checking should be placed here? + if (bl->type&BL_CHAR) { + sc = status_get_sc(bl); + + skill_unit_move(bl,tick,2); + status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); + status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); +// status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure... + status_change_end(bl, SC_TATAMIGAESHI, INVALID_TIMER); + status_change_end(bl, SC_MAGICROD, INVALID_TIMER); + if (sc->data[SC_PROPERTYWALK] && + sc->data[SC_PROPERTYWALK]->val3 >= skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) + status_change_end(bl,SC_PROPERTYWALK,INVALID_TIMER); + } else + if (bl->type == BL_NPC) + npc_unsetcells((TBL_NPC*)bl); + + if (moveblock) map_delblock(bl); #ifdef CELL_NOSTACK - else map_delblcell(bl); + else map_delblcell(bl); #endif - bl->x = x1; - bl->y = y1; - if (moveblock) map_addblock(bl); + bl->x = x1; + bl->y = y1; + if (moveblock) map_addblock(bl); #ifdef CELL_NOSTACK - else map_addblcell(bl); + else map_addblcell(bl); #endif - if (bl->type&BL_CHAR) { - - skill_unit_move(bl,tick,3); - - if (bl->type == BL_PC && ((TBL_PC *)bl)->shadowform_id) {//Shadow Form Target Moving - struct block_list *d_bl; - if ((d_bl = map_id2bl(((TBL_PC *)bl)->shadowform_id)) == NULL || bl->m != d_bl->m || !check_distance_bl(bl,d_bl,10)) { - if (d_bl) - status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER); - ((TBL_PC *)bl)->shadowform_id = 0; - } - } - - if (sc && sc->count) { - if (sc->data[SC_DANCING]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_DANCING]->val2), bl->m, x1-x0, y1-y0); - else { - if (sc->data[SC_CLOAKING]) - skill_check_cloaking(bl, sc->data[SC_CLOAKING]); - if (sc->data[SC_WARM]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_WARM]->val4), bl->m, x1-x0, y1-y0); - if (sc->data[SC_BANDING]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_BANDING]->val4), bl->m, x1-x0, y1-y0); - - if (sc->data[SC_NEUTRALBARRIER_MASTER]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_NEUTRALBARRIER_MASTER]->val2), bl->m, x1-x0, y1-y0); - else if (sc->data[SC_STEALTHFIELD_MASTER]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_STEALTHFIELD_MASTER]->val2), bl->m, x1-x0, y1-y0); - - if (sc->data[SC__SHADOWFORM]) { //Shadow Form Caster Moving - struct block_list *d_bl; - if ((d_bl = map_id2bl(sc->data[SC__SHADOWFORM]->val2)) == NULL || bl->m != d_bl->m || !check_distance_bl(bl,d_bl,10)) - status_change_end(bl,SC__SHADOWFORM,INVALID_TIMER); - } - - if (sc->data[SC_PROPERTYWALK] - && sc->data[SC_PROPERTYWALK]->val3 < skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) - && map_find_skill_unit_oncell(bl,bl->x,bl->y,SO_ELECTRICWALK,NULL,0) == NULL - && map_find_skill_unit_oncell(bl,bl->x,bl->y,SO_FIREWALK,NULL,0) == NULL - && skill_unitsetting(bl,sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2,x0, y0,0)) { - sc->data[SC_PROPERTYWALK]->val3++; - } - - - } - /* Guild Aura Moving */ - if (bl->type == BL_PC && ((TBL_PC *)bl)->state.gmaster_flag) { - if (sc->data[SC_LEADERSHIP]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_LEADERSHIP]->val4), bl->m, x1-x0, y1-y0); - if (sc->data[SC_GLORYWOUNDS]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_GLORYWOUNDS]->val4), bl->m, x1-x0, y1-y0); - if (sc->data[SC_SOULCOLD]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_SOULCOLD]->val4), bl->m, x1-x0, y1-y0); - if (sc->data[SC_HAWKEYES]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_HAWKEYES]->val4), bl->m, x1-x0, y1-y0); - } - } - } else if (bl->type == BL_NPC) - npc_setcells((TBL_NPC *)bl); - - return 0; + if (bl->type&BL_CHAR) { + + skill_unit_move(bl,tick,3); + + if( bl->type == BL_PC && ((TBL_PC*)bl)->shadowform_id ) {//Shadow Form Target Moving + struct block_list *d_bl; + if( (d_bl = map_id2bl(((TBL_PC*)bl)->shadowform_id)) == NULL || bl->m != d_bl->m || !check_distance_bl(bl,d_bl,10) ) { + if( d_bl ) + status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER); + ((TBL_PC*)bl)->shadowform_id = 0; + } + } + + if (sc && sc->count) { + if (sc->data[SC_DANCING]) + skill_unit_move_unit_group(skill_id2group(sc->data[SC_DANCING]->val2), bl->m, x1-x0, y1-y0); + else { + if (sc->data[SC_CLOAKING]) + skill_check_cloaking(bl, sc->data[SC_CLOAKING]); + if (sc->data[SC_WARM]) + skill_unit_move_unit_group(skill_id2group(sc->data[SC_WARM]->val4), bl->m, x1-x0, y1-y0); + if (sc->data[SC_BANDING]) + skill_unit_move_unit_group(skill_id2group(sc->data[SC_BANDING]->val4), bl->m, x1-x0, y1-y0); + + if (sc->data[SC_NEUTRALBARRIER_MASTER]) + skill_unit_move_unit_group(skill_id2group(sc->data[SC_NEUTRALBARRIER_MASTER]->val2), bl->m, x1-x0, y1-y0); + else if (sc->data[SC_STEALTHFIELD_MASTER]) + skill_unit_move_unit_group(skill_id2group(sc->data[SC_STEALTHFIELD_MASTER]->val2), bl->m, x1-x0, y1-y0); + + if( sc->data[SC__SHADOWFORM] ) {//Shadow Form Caster Moving + struct block_list *d_bl; + if( (d_bl = map_id2bl(sc->data[SC__SHADOWFORM]->val2)) == NULL || bl->m != d_bl->m || !check_distance_bl(bl,d_bl,10) ) + status_change_end(bl,SC__SHADOWFORM,INVALID_TIMER); + } + + if (sc->data[SC_PROPERTYWALK] + && sc->data[SC_PROPERTYWALK]->val3 < skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) + && map_find_skill_unit_oncell(bl,bl->x,bl->y,SO_ELECTRICWALK,NULL,0) == NULL + && map_find_skill_unit_oncell(bl,bl->x,bl->y,SO_FIREWALK,NULL,0) == NULL + && skill_unitsetting(bl,sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2,x0, y0,0)) { + sc->data[SC_PROPERTYWALK]->val3++; + } + + + } + /* Guild Aura Moving */ + if( bl->type == BL_PC && ((TBL_PC*)bl)->state.gmaster_flag ) { + if (sc->data[SC_LEADERSHIP]) + skill_unit_move_unit_group(skill_id2group(sc->data[SC_LEADERSHIP]->val4), bl->m, x1-x0, y1-y0); + if (sc->data[SC_GLORYWOUNDS]) + skill_unit_move_unit_group(skill_id2group(sc->data[SC_GLORYWOUNDS]->val4), bl->m, x1-x0, y1-y0); + if (sc->data[SC_SOULCOLD]) + skill_unit_move_unit_group(skill_id2group(sc->data[SC_SOULCOLD]->val4), bl->m, x1-x0, y1-y0); + if (sc->data[SC_HAWKEYES]) + skill_unit_move_unit_group(skill_id2group(sc->data[SC_HAWKEYES]->val4), bl->m, x1-x0, y1-y0); + } + } + } else + if (bl->type == BL_NPC) + npc_setcells((TBL_NPC*)bl); + + return 0; } /*========================================== @@ -471,189 +477,190 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) *------------------------------------------*/ int map_count_oncell(int m, int x, int y, int type) { - int bx,by; - struct block_list *bl; - int count = 0; + int bx,by; + struct block_list *bl; + int count = 0; - if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) - return 0; + if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) + return 0; - bx = x/BLOCK_SIZE; - by = y/BLOCK_SIZE; + bx = x/BLOCK_SIZE; + by = y/BLOCK_SIZE; - if (type&~BL_MOB) - for (bl = map[m].block[bx+by*map[m].bxs] ; bl != NULL ; bl = bl->next) - if (bl->x == x && bl->y == y && bl->type&type) - count++; + if (type&~BL_MOB) + for( bl = map[m].block[bx+by*map[m].bxs] ; bl != NULL ; bl = bl->next ) + if(bl->x == x && bl->y == y && bl->type&type) + count++; - if (type&BL_MOB) - for (bl = map[m].block_mob[bx+by*map[m].bxs] ; bl != NULL ; bl = bl->next) - if (bl->x == x && bl->y == y) - count++; + if (type&BL_MOB) + for( bl = map[m].block_mob[bx+by*map[m].bxs] ; bl != NULL ; bl = bl->next ) + if(bl->x == x && bl->y == y) + count++; - return count; + return count; } /* * Looks for a skill unit on a given cell * flag&1: runs battle_check_target check based on unit->group->target_flag */ -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 flag) { - int m,bx,by; - struct block_list *bl; - struct skill_unit *unit; - m = target->m; +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 flag) { + int m,bx,by; + struct block_list *bl; + struct skill_unit *unit; + m = target->m; - if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) - return NULL; + if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) + return NULL; - bx = x/BLOCK_SIZE; - by = y/BLOCK_SIZE; + bx = x/BLOCK_SIZE; + by = y/BLOCK_SIZE; - for (bl = map[m].block[bx+by *map[m].bxs] ; bl != NULL ; bl = bl->next) { - if (bl->x != x || bl->y != y || bl->type != BL_SKILL) - continue; + for( bl = map[m].block[bx+by*map[m].bxs] ; bl != NULL ; 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 (!(flag&1) || battle_check_target(&unit->bl,target,unit->group->target_flag) > 0) - return unit; - } - return NULL; + unit = (struct skill_unit *) bl; + if( unit == out_unit || !unit->alive || !unit->group || unit->group->skill_id != skill_id ) + continue; + if( !(flag&1) || battle_check_target(&unit->bl,target,unit->group->target_flag) > 0 ) + return unit; + } + return NULL; } /*========================================== * Adapted from foreachinarea for an easier invocation. [Skotlex] *------------------------------------------*/ -int map_foreachinrange(int (*func)(struct block_list *,va_list), struct block_list *center, int range, int type, ...) -{ - int bx, by, m; - int returnCount = 0; //total sum of returned values of func() [Skotlex] - struct block_list *bl; - int blockcount = bl_list_count, i; - int x0, x1, y0, y1; - va_list ap; - - m = center->m; - x0 = max(center->x - range, 0); - y0 = max(center->y - range, 0); - x1 = min(center->x + range, map[ m ].xs - 1); - y1 = min(center->y + range, map[ m ].ys - 1); - - if (type&~BL_MOB) - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { - for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - for (bl = map[m].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->type&type - && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 +int map_foreachinrange(int (*func)(struct block_list*,va_list), struct block_list* center, int range, int type, ...) +{ + int bx, by, m; + int returnCount = 0; //total sum of returned values of func() [Skotlex] + struct block_list *bl; + int blockcount = bl_list_count, i; + int x0, x1, y0, y1; + va_list ap; + + m = center->m; + x0 = max(center->x - range, 0); + y0 = max(center->y - range, 0); + x1 = min(center->x + range, map[ m ].xs - 1); + y1 = min(center->y + range, map[ m ].ys - 1); + + if ( type&~BL_MOB ) + for ( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { + for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { + for( bl = map[m].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->type&type + && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 #ifdef CIRCULAR_AREA - && check_distance_bl(center, bl, range) + && check_distance_bl(center, bl, range) #endif - && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - } - } - } - - if (type&BL_MOB) - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { - for (bx=x0/BLOCK_SIZE; bx<=x1/BLOCK_SIZE; bx++) { - for (bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 + && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + } + } + } + + if( type&BL_MOB ) + for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { + for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++) { + for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 #ifdef CIRCULAR_AREA - && check_distance_bl(center, bl, range) + && check_distance_bl(center, bl, range) #endif - && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - } - } - } + && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + } + } + } - if (bl_list_count >= BL_LIST_MAX) - ShowWarning("map_foreachinrange: block count too many!\n"); + if( bl_list_count >= BL_LIST_MAX ) + ShowWarning("map_foreachinrange: block count too many!\n"); - map_freeblock_lock(); + map_freeblock_lock(); - for (i = blockcount; i < bl_list_count; i++) - if (bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. - va_start(ap, type); - returnCount += func(bl_list[ i ], ap); - va_end(ap); - } + for( i = blockcount; i < bl_list_count; i++ ) + if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. + va_start(ap, type); + returnCount += func(bl_list[ i ], ap); + va_end(ap); + } - map_freeblock_unlock(); + map_freeblock_unlock(); - bl_list_count = blockcount; - return returnCount; //[Skotlex] + bl_list_count = blockcount; + return returnCount; //[Skotlex] } /*========================================== * Same as foreachinrange, but there must be a shoot-able range between center and target to be counted in. [Skotlex] *------------------------------------------*/ -int map_foreachinshootrange(int (*func)(struct block_list *,va_list),struct block_list *center, int range, int type,...) -{ - int bx, by, m; - int returnCount = 0; //total sum of returned values of func() [Skotlex] - struct block_list *bl; - int blockcount = bl_list_count, i; - int x0, x1, y0, y1; - va_list ap; - - m = center->m; - if (m < 0) - return 0; - - x0 = max(center->x-range, 0); - y0 = max(center->y-range, 0); - x1 = min(center->x+range, map[m].xs-1); - y1 = min(center->y+range, map[m].ys-1); - - if (type&~BL_MOB) - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { - for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - for (bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->type&type - && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 +int map_foreachinshootrange(int (*func)(struct block_list*,va_list),struct block_list* center, int range, int type,...) +{ + int bx, by, m; + int returnCount = 0; //total sum of returned values of func() [Skotlex] + struct block_list *bl; + int blockcount = bl_list_count, i; + int x0, x1, y0, y1; + va_list ap; + + m = center->m; + if ( m < 0 ) + return 0; + + x0 = max(center->x-range, 0); + y0 = max(center->y-range, 0); + x1 = min(center->x+range, map[m].xs-1); + y1 = min(center->y+range, map[m].ys-1); + + if ( type&~BL_MOB ) + for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { + for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { + for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->type&type + && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 #ifdef CIRCULAR_AREA - && check_distance_bl(center, bl, range) + && check_distance_bl(center, bl, range) #endif - && path_search_long(NULL, center->m, center->x, center->y, bl->x, bl->y, CELL_CHKWALL) - && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - } - } - } - if (type&BL_MOB) - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { - for (bx=x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - for (bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 + && path_search_long(NULL, center->m, center->x, center->y, bl->x, bl->y, CELL_CHKWALL) + && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + } + } + } + if( type&BL_MOB ) + for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { + for( bx=x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { + for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 #ifdef CIRCULAR_AREA - && check_distance_bl(center, bl, range) + && check_distance_bl(center, bl, range) #endif - && path_search_long(NULL, center->m, center->x, center->y, bl->x, bl->y, CELL_CHKWALL) - && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - } - } - } + && path_search_long(NULL, center->m, center->x, center->y, bl->x, bl->y, CELL_CHKWALL) + && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + } + } + } - if (bl_list_count >= BL_LIST_MAX) - ShowWarning("map_foreachinrange: block count too many!\n"); + if( bl_list_count >= BL_LIST_MAX ) + ShowWarning("map_foreachinrange: block count too many!\n"); - map_freeblock_lock(); + map_freeblock_lock(); - for (i = blockcount; i < bl_list_count; i++) - if (bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. - va_start(ap, type); - returnCount += func(bl_list[ i ], ap); - va_end(ap); - } + for( i = blockcount; i < bl_list_count; i++ ) + if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. + va_start(ap, type); + returnCount += func(bl_list[ i ], ap); + va_end(ap); + } - map_freeblock_unlock(); + map_freeblock_unlock(); - bl_list_count = blockcount; - return returnCount; //[Skotlex] + bl_list_count = blockcount; + return returnCount; //[Skotlex] } /*========================================== @@ -661,175 +668,175 @@ int map_foreachinshootrange(int (*func)(struct block_list *,va_list),struct bloc * Apply *func with ... arguments for the range. * @type = BL_PC/BL_MOB etc.. *------------------------------------------*/ -int map_foreachinarea(int (*func)(struct block_list *,va_list), int m, int x0, int y0, int x1, int y1, int type, ...) -{ - int bx, by; - int returnCount = 0; //total sum of returned values of func() [Skotlex] - struct block_list *bl; - int blockcount = bl_list_count, i; - va_list ap; - - if (m < 0) - return 0; - - if (x1 < x0) - swap(x0, x1); - if (y1 < y0) - swap(y0, y1); - - x0 = max(x0, 0); - y0 = max(y0, 0); - x1 = min(x1, map[ m ].xs - 1); - y1 = min(y1, map[ m ].ys - 1); - if (type&~BL_MOB) - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) - for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) - for (bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) - if (bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - - if (type&BL_MOB) - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) - for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) - for (bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) - if (bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - - if (bl_list_count >= BL_LIST_MAX) - ShowWarning("map_foreachinarea: block count too many!\n"); - - map_freeblock_lock(); - - for (i = blockcount; i < bl_list_count; i++) - if (bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. - va_start(ap, type); - returnCount += func(bl_list[ i ], ap); - va_end(ap); - } - - map_freeblock_unlock(); - - bl_list_count = blockcount; - return returnCount; //[Skotlex] +int map_foreachinarea(int (*func)(struct block_list*,va_list), int m, int x0, int y0, int x1, int y1, int type, ...) +{ + int bx, by; + int returnCount = 0; //total sum of returned values of func() [Skotlex] + struct block_list *bl; + int blockcount = bl_list_count, i; + va_list ap; + + if ( m < 0 ) + return 0; + + if ( x1 < x0 ) + swap(x0, x1); + if ( y1 < y0 ) + swap(y0, y1); + + x0 = max(x0, 0); + y0 = max(y0, 0); + x1 = min(x1, map[ m ].xs - 1); + y1 = min(y1, map[ m ].ys - 1); + if ( type&~BL_MOB ) + for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) + for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) + for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) + if( bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + + if( type&BL_MOB ) + for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) + for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) + for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) + if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + + if( bl_list_count >= BL_LIST_MAX ) + ShowWarning("map_foreachinarea: block count too many!\n"); + + map_freeblock_lock(); + + for( i = blockcount; i < bl_list_count; i++ ) + if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. + va_start(ap, type); + returnCount += func(bl_list[ i ], ap); + va_end(ap); + } + + map_freeblock_unlock(); + + bl_list_count = blockcount; + return returnCount; //[Skotlex] } /*========================================== * Adapted from forcountinarea for an easier invocation. [pakpil] *------------------------------------------*/ -int map_forcountinrange(int (*func)(struct block_list *,va_list), struct block_list *center, int range, int count, int type, ...) -{ - int bx, by, m; - int returnCount = 0; //total sum of returned values of func() [Skotlex] - struct block_list *bl; - int blockcount = bl_list_count, i; - int x0, x1, y0, y1; - va_list ap; - - m = center->m; - x0 = max(center->x - range, 0); - y0 = max(center->y - range, 0); - x1 = min(center->x + range, map[ m ].xs - 1); - y1 = min(center->y + range, map[ m ].ys - 1); - - if (type&~BL_MOB) - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { - for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - for (bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->type&type - && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 +int map_forcountinrange(int (*func)(struct block_list*,va_list), struct block_list* center, int range, int count, int type, ...) +{ + int bx, by, m; + int returnCount = 0; //total sum of returned values of func() [Skotlex] + struct block_list *bl; + int blockcount = bl_list_count, i; + int x0, x1, y0, y1; + va_list ap; + + m = center->m; + x0 = max(center->x - range, 0); + y0 = max(center->y - range, 0); + x1 = min(center->x + range, map[ m ].xs - 1); + y1 = min(center->y + range, map[ m ].ys - 1); + + if ( type&~BL_MOB ) + for ( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { + for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { + for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->type&type + && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 #ifdef CIRCULAR_AREA - && check_distance_bl(center, bl, range) + && check_distance_bl(center, bl, range) #endif - && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - } - } - } - if (type&BL_MOB) - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { - for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - for (bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 + && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + } + } + } + if( type&BL_MOB ) + for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { + for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ){ + for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 #ifdef CIRCULAR_AREA - && check_distance_bl(center, bl, range) + && check_distance_bl(center, bl, range) #endif - && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - } - } - } - - if (bl_list_count >= BL_LIST_MAX) - ShowWarning("map_forcountinrange: block count too many!\n"); - - map_freeblock_lock(); - - for (i = blockcount; i < bl_list_count; i++) - if (bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. - va_start(ap, type); - returnCount += func(bl_list[ i ], ap); - va_end(ap); - if (count && returnCount >= count) - break; - } - - map_freeblock_unlock(); - - bl_list_count = blockcount; - return returnCount; //[Skotlex] -} -int map_forcountinarea(int (*func)(struct block_list *,va_list), int m, int x0, int y0, int x1, int y1, int count, int type, ...) -{ - int bx, by; - int returnCount = 0; //total sum of returned values of func() [Skotlex] - struct block_list *bl; - int blockcount = bl_list_count, i; - va_list ap; - - if (m < 0) - return 0; - - if (x1 < x0) - swap(x0, x1); - if (y1 < y0) - swap(y0, y1); - - x0 = max(x0, 0); - y0 = max(y0, 0); - x1 = min(x1, map[ m ].xs - 1); - y1 = min(y1, map[ m ].ys - 1); - - if (type&~BL_MOB) - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) - for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) - for (bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) - if (bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - - if (type&BL_MOB) - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) - for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) - for (bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) - if (bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - - if (bl_list_count >= BL_LIST_MAX) - ShowWarning("map_foreachinarea: block count too many!\n"); - - map_freeblock_lock(); - - for (i = blockcount; i < bl_list_count; i++) - if (bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. - va_start(ap, type); - returnCount += func(bl_list[ i ], ap); - va_end(ap); - if (count && returnCount >= count) - break; - } - - map_freeblock_unlock(); - - bl_list_count = blockcount; - return returnCount; //[Skotlex] + && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + } + } + } + + if( bl_list_count >= BL_LIST_MAX ) + ShowWarning("map_forcountinrange: block count too many!\n"); + + map_freeblock_lock(); + + for( i = blockcount; i < bl_list_count; i++ ) + if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. + va_start(ap, type); + returnCount += func(bl_list[ i ], ap); + va_end(ap); + if( count && returnCount >= count ) + break; + } + + map_freeblock_unlock(); + + bl_list_count = blockcount; + return returnCount; //[Skotlex] +} +int map_forcountinarea(int (*func)(struct block_list*,va_list), int m, int x0, int y0, int x1, int y1, int count, int type, ...) +{ + int bx, by; + int returnCount = 0; //total sum of returned values of func() [Skotlex] + struct block_list *bl; + int blockcount = bl_list_count, i; + va_list ap; + + if ( m < 0 ) + return 0; + + if ( x1 < x0 ) + swap(x0, x1); + if ( y1 < y0 ) + swap(y0, y1); + + x0 = max(x0, 0); + y0 = max(y0, 0); + x1 = min(x1, map[ m ].xs - 1); + y1 = min(y1, map[ m ].ys - 1); + + if ( type&~BL_MOB ) + for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) + for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) + for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) + if( bl->type&type && bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + + if( type&BL_MOB ) + for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) + for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) + for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) + if( bl->x >= x0 && bl->x <= x1 && bl->y >= y0 && bl->y <= y1 && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + + if( bl_list_count >= BL_LIST_MAX ) + ShowWarning("map_foreachinarea: block count too many!\n"); + + map_freeblock_lock(); + + for( i = blockcount; i < bl_list_count; i++ ) + if(bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. + va_start(ap, type); + returnCount += func(bl_list[ i ], ap); + va_end(ap); + if( count && returnCount >= count ) + break; + } + + map_freeblock_unlock(); + + bl_list_count = blockcount; + return returnCount; //[Skotlex] } /*========================================== @@ -837,390 +844,390 @@ int map_forcountinarea(int (*func)(struct block_list *,va_list), int m, int x0, * Move bl and do func* with va_list while moving. * Mouvement is set by dx dy wich are distance in x and y *------------------------------------------*/ -int map_foreachinmovearea(int (*func)(struct block_list *,va_list), struct block_list *center, int range, int dx, int dy, int type, ...) -{ - int bx, by, m; - int returnCount = 0; //total sum of returned values of func() [Skotlex] - struct block_list *bl; - int blockcount = bl_list_count, i; - int x0, x1, y0, y1; - va_list ap; - - if (!range) return 0; - if (!dx && !dy) return 0; //No movement. - - m = center->m; - - x0 = center->x - range; - x1 = center->x + range; - y0 = center->y - range; - y1 = center->y + range; - - if (x1 < x0) - swap(x0, x1); - if (y1 < y0) - swap(y0, y1); - - if (dx == 0 || dy == 0) { - //Movement along one axis only. - if (dx == 0) { - if (dy < 0) //Moving south - y0 = y1 + dy + 1; - else //North - y1 = y0 + dy - 1; - } else { //dy == 0 - if (dx < 0) //West - x0 = x1 + dx + 1; - else //East - x1 = x0 + dx - 1; - } - - x0 = max(x0, 0); - y0 = max(y0, 0); - x1 = min(x1, map[ m ].xs - 1); - y1 = min(y1, map[ m ].ys - 1); - - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { - for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - if (type&~BL_MOB) { - for (bl = map[m].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->type&type && - bl->x >= x0 && bl->x <= x1 && - bl->y >= y0 && bl->y <= y1 && - bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - } - } - if (type&BL_MOB) { - for (bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->x >= x0 && bl->x <= x1 && - bl->y >= y0 && bl->y <= y1 && - bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - } - } - } - } - } else { // Diagonal movement - - x0 = max(x0, 0); - y0 = max(y0, 0); - x1 = min(x1, map[ m ].xs - 1); - y1 = min(y1, map[ m ].ys - 1); - - for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) { - for (bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++) { - if (type & ~BL_MOB) { - for (bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->type&type && - bl->x >= x0 && bl->x <= x1 && - bl->y >= y0 && bl->y <= y1 && - bl_list_count < BL_LIST_MAX) - if ((dx > 0 && bl->x < x0 + dx) || - (dx < 0 && bl->x > x1 + dx) || - (dy > 0 && bl->y < y0 + dy) || - (dy < 0 && bl->y > y1 + dy)) - bl_list[ bl_list_count++ ] = bl; - } - } - if (type&BL_MOB) { - for (bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->x >= x0 && bl->x <= x1 && - bl->y >= y0 && bl->y <= y1 && - bl_list_count < BL_LIST_MAX) - if ((dx > 0 && bl->x < x0 + dx) || - (dx < 0 && bl->x > x1 + dx) || - (dy > 0 && bl->y < y0 + dy) || - (dy < 0 && bl->y > y1 + dy)) - bl_list[ bl_list_count++ ] = bl; - } - } - } - } - - } - - if (bl_list_count >= BL_LIST_MAX) - ShowWarning("map_foreachinmovearea: block count too many!\n"); - - map_freeblock_lock(); // Prohibit the release from memory - - for (i = blockcount; i < bl_list_count; i++) - if (bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. - va_start(ap, type); - returnCount += func(bl_list[ i ], ap); - va_end(ap); - } - - map_freeblock_unlock(); // Allow Free - - bl_list_count = blockcount; - return returnCount; -} - -// -- moonsoul (added map_foreachincell which is a rework of map_foreachinarea but -// which only checks the exact single x/y passed to it rather than an -// area radius - may be more useful in some instances) +int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_list* center, int range, int dx, int dy, int type, ...) +{ + int bx, by, m; + int returnCount = 0; //total sum of returned values of func() [Skotlex] + struct block_list *bl; + int blockcount = bl_list_count, i; + int x0, x1, y0, y1; + va_list ap; + + if ( !range ) return 0; + if ( !dx && !dy ) return 0; //No movement. + + m = center->m; + + x0 = center->x - range; + x1 = center->x + range; + y0 = center->y - range; + y1 = center->y + range; + + if ( x1 < x0 ) + swap(x0, x1); + if ( y1 < y0 ) + swap(y0, y1); + + if( dx == 0 || dy == 0 ) { + //Movement along one axis only. + if( dx == 0 ){ + if( dy < 0 ) //Moving south + y0 = y1 + dy + 1; + else //North + y1 = y0 + dy - 1; + } else { //dy == 0 + if( dx < 0 ) //West + x0 = x1 + dx + 1; + else //East + x1 = x0 + dx - 1; + } + + x0 = max(x0, 0); + y0 = max(y0, 0); + x1 = min(x1, map[ m ].xs - 1); + y1 = min(y1, map[ m ].ys - 1); + + for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { + for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { + if ( type&~BL_MOB ) { + for( bl = map[m].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->type&type && + bl->x >= x0 && bl->x <= x1 && + bl->y >= y0 && bl->y <= y1 && + bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + } + } + if ( type&BL_MOB ) { + for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->x >= x0 && bl->x <= x1 && + bl->y >= y0 && bl->y <= y1 && + bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + } + } + } + } + } else { // Diagonal movement + + x0 = max(x0, 0); + y0 = max(y0, 0); + x1 = min(x1, map[ m ].xs - 1); + y1 = min(y1, map[ m ].ys - 1); + + for( by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++ ) { + for( bx = x0 / BLOCK_SIZE; bx <= x1 / BLOCK_SIZE; bx++ ) { + if ( type & ~BL_MOB ) { + for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->type&type && + bl->x >= x0 && bl->x <= x1 && + bl->y >= y0 && bl->y <= y1 && + bl_list_count < BL_LIST_MAX ) + if( ( dx > 0 && bl->x < x0 + dx) || + ( dx < 0 && bl->x > x1 + dx) || + ( dy > 0 && bl->y < y0 + dy) || + ( dy < 0 && bl->y > y1 + dy) ) + bl_list[ bl_list_count++ ] = bl; + } + } + if ( type&BL_MOB ) { + for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->x >= x0 && bl->x <= x1 && + bl->y >= y0 && bl->y <= y1 && + bl_list_count < BL_LIST_MAX) + if( ( dx > 0 && bl->x < x0 + dx) || + ( dx < 0 && bl->x > x1 + dx) || + ( dy > 0 && bl->y < y0 + dy) || + ( dy < 0 && bl->y > y1 + dy) ) + bl_list[ bl_list_count++ ] = bl; + } + } + } + } + + } + + if( bl_list_count >= BL_LIST_MAX ) + ShowWarning("map_foreachinmovearea: block count too many!\n"); + + map_freeblock_lock(); // Prohibit the release from memory + + for( i = blockcount; i < bl_list_count; i++ ) + if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. + va_start(ap, type); + returnCount += func(bl_list[ i ], ap); + va_end(ap); + } + + map_freeblock_unlock(); // Allow Free + + bl_list_count = blockcount; + return returnCount; +} + +// -- moonsoul (added map_foreachincell which is a rework of map_foreachinarea but +// which only checks the exact single x/y passed to it rather than an +// area radius - may be more useful in some instances) // -int map_foreachincell(int (*func)(struct block_list *,va_list), int m, int x, int y, int type, ...) +int map_foreachincell(int (*func)(struct block_list*,va_list), int m, int x, int y, int type, ...) { - int bx, by; - int returnCount = 0; //total sum of returned values of func() [Skotlex] - struct block_list *bl; - int blockcount = bl_list_count, i; - va_list ap; + int bx, by; + int returnCount = 0; //total sum of returned values of func() [Skotlex] + struct block_list *bl; + int blockcount = bl_list_count, i; + va_list ap; - if (x < 0 || y < 0 || x >= map[ m ].xs || y >= map[ m ].ys) return 0; + if ( x < 0 || y < 0 || x >= map[ m ].xs || y >= map[ m ].ys ) return 0; - by = y / BLOCK_SIZE; - bx = x / BLOCK_SIZE; + by = y / BLOCK_SIZE; + bx = x / BLOCK_SIZE; - if (type&~BL_MOB) - for (bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) - if (bl->type&type && bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; - if (type&BL_MOB) - for (bl = map[ m ].block_mob[ bx + by * map[ m ].bxs]; bl != NULL; bl = bl->next) - if (bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; + if( type&~BL_MOB ) + for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) + if( bl->type&type && bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; + if( type&BL_MOB ) + for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs]; bl != NULL; bl = bl->next ) + if( bl->x == x && bl->y == y && bl_list_count < BL_LIST_MAX) + bl_list[ bl_list_count++ ] = bl; - if (bl_list_count >= BL_LIST_MAX) - ShowWarning("map_foreachincell: block count too many!\n"); + if( bl_list_count >= BL_LIST_MAX ) + ShowWarning("map_foreachincell: block count too many!\n"); - map_freeblock_lock(); + map_freeblock_lock(); - for (i = blockcount; i < bl_list_count; i++) - if (bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. - va_start(ap, type); - returnCount += func(bl_list[ i ], ap); - va_end(ap); - } + for( i = blockcount; i < bl_list_count; i++ ) + if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. + va_start(ap, type); + returnCount += func(bl_list[ i ], ap); + va_end(ap); + } - map_freeblock_unlock(); + map_freeblock_unlock(); - bl_list_count = blockcount; - return returnCount; + bl_list_count = blockcount; + return returnCount; } /*============================================================ * For checking a path between two points (x0, y0) and (x1, y1) *------------------------------------------------------------*/ -int map_foreachinpath(int (*func)(struct block_list *,va_list),int m,int x0,int y0,int x1,int y1,int range,int length, int type,...) -{ - int returnCount = 0; //total sum of returned values of func() [Skotlex] - ////////////////////////////////////////////////////////////// - // - // sharp shooting 3 [Skotlex] - // - ////////////////////////////////////////////////////////////// - // problem: - // Same as Sharp Shooting 1. Hits all targets within range of - // the line. - // (t1,t2 t3 and t4 get hit) - // - // target 1 - // x t4 - // t2 - // t3 x - // x - // S - ////////////////////////////////////////////////////////////// - // Methodology: - // My trigonometrics and math are a little rusty... so the approach I am writing - // here is basicly do a double for to check for all targets in the square that - // contains the initial and final positions (area range increased to match the - // radius given), then for each object to test, calculate the distance to the - // path and include it if the range fits and the target is in the line (0<k<1, - // as they call it). - // The implementation I took as reference is found at - // http://astronomy.swin.edu.au/~pbourke/geometry/pointline/ - // (they have a link to a C implementation, too) - // This approach is a lot like #2 commented on this function, which I have no - // idea why it was commented. I won't use doubles/floats, but pure int math for - // speed purposes. The range considered is always the same no matter how - // close/far the target is because that's how SharpShooting works currently in - // kRO. - - //Generic map_foreach* variables. - int i, blockcount = bl_list_count; - struct block_list *bl; - int bx, by; - //method specific variables - int magnitude2, len_limit; //The square of the magnitude - int k, xi, yi, xu, yu; - int mx0 = x0, mx1 = x1, my0 = y0, my1 = y1; - va_list ap; - - //Avoid needless calculations by not getting the sqrt right away. -#define MAGNITUDE2(x0, y0, x1, y1) ( ( ( x1 ) - ( x0 ) ) * ( ( x1 ) - ( x0 ) ) + ( ( y1 ) - ( y0 ) ) * ( ( y1 ) - ( y0 ) ) ) - - if (m < 0) - return 0; - - len_limit = magnitude2 = MAGNITUDE2(x0, y0, x1, y1); - if (magnitude2 < 1) //Same begin and ending point, can't trace path. - return 0; - - if (length) { //Adjust final position to fit in the given area. - //TODO: Find an alternate method which does not requires a square root calculation. - k = (int)sqrt((float)magnitude2); - mx1 = x0 + (x1 - x0) * length / k; - my1 = y0 + (y1 - y0) * length / k; - len_limit = MAGNITUDE2(x0, y0, mx1, my1); - } - //Expand target area to cover range. - if (mx0 > mx1) { - mx0 += range; - mx1 -= range; - } else { - mx0 -= range; - mx1 += range; - } - if (my0 > my1) { - my0 += range; - my1 -= range; - } else { - my0 -= range; - my1 += range; - } - - //The two fors assume mx0 < mx1 && my0 < my1 - if (mx0 > mx1) - swap(mx0, mx1); - if (my0 > my1) - swap(my0, my1); - - mx0 = max(mx0, 0); - my0 = max(my0, 0); - mx1 = min(mx1, map[ m ].xs - 1); - my1 = min(my1, map[ m ].ys - 1); - - range *= range << 8; //Values are shifted later on for higher precision using int math. - - if (type&~BL_MOB) - for (by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++) { - for (bx = mx0 / BLOCK_SIZE; bx <= mx1 / BLOCK_SIZE; bx++) { - for (bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->prev && bl->type&type && bl_list_count < BL_LIST_MAX) { - xi = bl->x; - yi = bl->y; - - k = (xi - x0) * (x1 - x0) + (yi - y0) * (y1 - y0); - - if (k < 0 || k > len_limit) //Since more skills use this, check for ending point as well. - continue; - - if (k > magnitude2 && !path_search_long(NULL, m, x0, y0, xi, yi, CELL_CHKWALL)) - continue; //Targets beyond the initial ending point need the wall check. - - //All these shifts are to increase the precision of the intersection point and distance considering how it's - //int math. - k = (k << 4) / magnitude2; //k will be between 1~16 instead of 0~1 - xi <<= 4; - yi <<= 4; - xu = (x0 << 4) + k * (x1 - x0); - yu = (y0 << 4) + k * (y1 - y0); - k = MAGNITUDE2(xi, yi, xu, yu); - - //If all dot coordinates were <<4 the square of the magnitude is <<8 - if (k > range) - continue; - - bl_list[ bl_list_count++ ] = bl; - } - } - } - } - if (type&BL_MOB) - for (by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++) { - for (bx = mx0 / BLOCK_SIZE; bx <= mx1 / BLOCK_SIZE; bx++) { - for (bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next) { - if (bl->prev && bl_list_count < BL_LIST_MAX) { - xi = bl->x; - yi = bl->y; - k = (xi - x0) * (x1 - x0) + (yi - y0) * (y1 - y0); - - if (k < 0 || k > len_limit) - continue; - - if (k > magnitude2 && !path_search_long(NULL, m, x0, y0, xi, yi, CELL_CHKWALL)) - continue; //Targets beyond the initial ending point need the wall check. - - k = (k << 4) / magnitude2; //k will be between 1~16 instead of 0~1 - xi <<= 4; - yi <<= 4; - xu = (x0 << 4) + k * (x1 - x0); - yu = (y0 << 4) + k * (y1 - y0); - k = MAGNITUDE2(xi, yi, xu, yu); - - //If all dot coordinates were <<4 the square of the magnitude is <<8 - if (k > range) - continue; - - bl_list[ bl_list_count++ ] = bl; - } - } - } - } - - if (bl_list_count >= BL_LIST_MAX) - ShowWarning("map_foreachinpath: block count too many!\n"); - - map_freeblock_lock(); - - for (i = blockcount; i < bl_list_count; i++) - if (bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. - va_start(ap, type); - returnCount += func(bl_list[ i ], ap); - va_end(ap); - } - - map_freeblock_unlock(); - - bl_list_count = blockcount; - return returnCount; //[Skotlex] +int map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int range,int length, int type,...) +{ + int returnCount = 0; //total sum of returned values of func() [Skotlex] +////////////////////////////////////////////////////////////// +// +// sharp shooting 3 [Skotlex] +// +////////////////////////////////////////////////////////////// +// problem: +// Same as Sharp Shooting 1. Hits all targets within range of +// the line. +// (t1,t2 t3 and t4 get hit) +// +// target 1 +// x t4 +// t2 +// t3 x +// x +// S +////////////////////////////////////////////////////////////// +// Methodology: +// My trigonometrics and math are a little rusty... so the approach I am writing +// here is basicly do a double for to check for all targets in the square that +// contains the initial and final positions (area range increased to match the +// radius given), then for each object to test, calculate the distance to the +// path and include it if the range fits and the target is in the line (0<k<1, +// as they call it). +// The implementation I took as reference is found at +// http://astronomy.swin.edu.au/~pbourke/geometry/pointline/ +// (they have a link to a C implementation, too) +// This approach is a lot like #2 commented on this function, which I have no +// idea why it was commented. I won't use doubles/floats, but pure int math for +// speed purposes. The range considered is always the same no matter how +// close/far the target is because that's how SharpShooting works currently in +// kRO. + + //Generic map_foreach* variables. + int i, blockcount = bl_list_count; + struct block_list *bl; + int bx, by; + //method specific variables + int magnitude2, len_limit; //The square of the magnitude + int k, xi, yi, xu, yu; + int mx0 = x0, mx1 = x1, my0 = y0, my1 = y1; + va_list ap; + + //Avoid needless calculations by not getting the sqrt right away. + #define MAGNITUDE2(x0, y0, x1, y1) ( ( ( x1 ) - ( x0 ) ) * ( ( x1 ) - ( x0 ) ) + ( ( y1 ) - ( y0 ) ) * ( ( y1 ) - ( y0 ) ) ) + + if ( m < 0 ) + return 0; + + len_limit = magnitude2 = MAGNITUDE2(x0, y0, x1, y1); + if ( magnitude2 < 1 ) //Same begin and ending point, can't trace path. + return 0; + + if ( length ) { //Adjust final position to fit in the given area. + //TODO: Find an alternate method which does not requires a square root calculation. + k = (int)sqrt((float)magnitude2); + mx1 = x0 + (x1 - x0) * length / k; + my1 = y0 + (y1 - y0) * length / k; + len_limit = MAGNITUDE2(x0, y0, mx1, my1); + } + //Expand target area to cover range. + if ( mx0 > mx1 ) { + mx0 += range; + mx1 -= range; + } else { + mx0 -= range; + mx1 += range; + } + if (my0 > my1) { + my0 += range; + my1 -= range; + } else { + my0 -= range; + my1 += range; + } + + //The two fors assume mx0 < mx1 && my0 < my1 + if ( mx0 > mx1 ) + swap(mx0, mx1); + if ( my0 > my1 ) + swap(my0, my1); + + mx0 = max(mx0, 0); + my0 = max(my0, 0); + mx1 = min(mx1, map[ m ].xs - 1); + my1 = min(my1, map[ m ].ys - 1); + + range *= range << 8; //Values are shifted later on for higher precision using int math. + + if ( type&~BL_MOB ) + for ( by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++ ) { + for( bx = mx0 / BLOCK_SIZE; bx <= mx1 / BLOCK_SIZE; bx++ ) { + for( bl = map[ m ].block[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->prev && bl->type&type && bl_list_count < BL_LIST_MAX ) { + xi = bl->x; + yi = bl->y; + + k = ( xi - x0 ) * ( x1 - x0 ) + ( yi - y0 ) * ( y1 - y0 ); + + if ( k < 0 || k > len_limit ) //Since more skills use this, check for ending point as well. + continue; + + if ( k > magnitude2 && !path_search_long(NULL, m, x0, y0, xi, yi, CELL_CHKWALL) ) + continue; //Targets beyond the initial ending point need the wall check. + + //All these shifts are to increase the precision of the intersection point and distance considering how it's + //int math. + k = ( k << 4 ) / magnitude2; //k will be between 1~16 instead of 0~1 + xi <<= 4; + yi <<= 4; + xu = ( x0 << 4 ) + k * ( x1 - x0 ); + yu = ( y0 << 4 ) + k * ( y1 - y0 ); + k = MAGNITUDE2(xi, yi, xu, yu); + + //If all dot coordinates were <<4 the square of the magnitude is <<8 + if ( k > range ) + continue; + + bl_list[ bl_list_count++ ] = bl; + } + } + } + } + if( type&BL_MOB ) + for( by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++ ) { + for( bx = mx0 / BLOCK_SIZE; bx <= mx1 / BLOCK_SIZE; bx++ ) { + for( bl = map[ m ].block_mob[ bx + by * map[ m ].bxs ]; bl != NULL; bl = bl->next ) { + if( bl->prev && bl_list_count < BL_LIST_MAX ) { + xi = bl->x; + yi = bl->y; + k = ( xi - x0 ) * ( x1 - x0 ) + ( yi - y0 ) * ( y1 - y0 ); + + if ( k < 0 || k > len_limit ) + continue; + + if ( k > magnitude2 && !path_search_long(NULL, m, x0, y0, xi, yi, CELL_CHKWALL) ) + continue; //Targets beyond the initial ending point need the wall check. + + k = ( k << 4 ) / magnitude2; //k will be between 1~16 instead of 0~1 + xi <<= 4; + yi <<= 4; + xu = ( x0 << 4 ) + k * ( x1 - x0 ); + yu = ( y0 << 4 ) + k * ( y1 - y0 ); + k = MAGNITUDE2(xi, yi, xu, yu); + + //If all dot coordinates were <<4 the square of the magnitude is <<8 + if ( k > range ) + continue; + + bl_list[ bl_list_count++ ] = bl; + } + } + } + } + + if( bl_list_count >= BL_LIST_MAX ) + ShowWarning("map_foreachinpath: block count too many!\n"); + + map_freeblock_lock(); + + for( i = blockcount; i < bl_list_count; i++ ) + if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. + va_start(ap, type); + returnCount += func(bl_list[ i ], ap); + va_end(ap); + } + + map_freeblock_unlock(); + + bl_list_count = blockcount; + return returnCount; //[Skotlex] } // Copy of map_foreachincell, but applied to the whole map. [Skotlex] -int map_foreachinmap(int (*func)(struct block_list *,va_list), int m, int type,...) +int map_foreachinmap(int (*func)(struct block_list*,va_list), int m, int type,...) { - int b, bsize; - int returnCount = 0; //total sum of returned values of func() [Skotlex] - struct block_list *bl; - int blockcount = bl_list_count, i; - va_list ap; - - bsize = map[ m ].bxs * map[ m ].bys; + int b, bsize; + int returnCount = 0; //total sum of returned values of func() [Skotlex] + struct block_list *bl; + int blockcount = bl_list_count, i; + va_list ap; + + bsize = map[ m ].bxs * map[ m ].bys; - if (type&~BL_MOB) - for (b = 0; b < bsize; b++) - for (bl = map[ m ].block[ b ]; bl != NULL; bl = bl->next) - if (bl->type&type && bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; + if( type&~BL_MOB ) + for( b = 0; b < bsize; b++ ) + for( bl = map[ m ].block[ b ]; bl != NULL; bl = bl->next ) + if( bl->type&type && bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; - if (type&BL_MOB) - for (b = 0; b < bsize; b++) - for (bl = map[ m ].block_mob[ b ]; bl != NULL; bl = bl->next) - if (bl_list_count < BL_LIST_MAX) - bl_list[ bl_list_count++ ] = bl; + if( type&BL_MOB ) + for( b = 0; b < bsize; b++ ) + for( bl = map[ m ].block_mob[ b ]; bl != NULL; bl = bl->next ) + if( bl_list_count < BL_LIST_MAX ) + bl_list[ bl_list_count++ ] = bl; - if (bl_list_count >= BL_LIST_MAX) - ShowWarning("map_foreachinmap: block count too many!\n"); + if( bl_list_count >= BL_LIST_MAX ) + ShowWarning("map_foreachinmap: block count too many!\n"); - map_freeblock_lock(); + map_freeblock_lock(); - for (i = blockcount; i < bl_list_count ; i++) - if (bl_list[ i ]->prev) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. - va_start(ap, type); - returnCount += func(bl_list[ i ], ap); - va_end(ap); - } + for( i = blockcount; i < bl_list_count ; i++ ) + if( bl_list[ i ]->prev ) { //func() may delete this bl_list[] slot, checking for prev ensures it wasnt queued for deletion. + va_start(ap, type); + returnCount += func(bl_list[ i ], ap); + va_end(ap); + } - map_freeblock_unlock(); + map_freeblock_unlock(); - bl_list_count = blockcount; - return returnCount; + bl_list_count = blockcount; + return returnCount; } @@ -1229,30 +1236,30 @@ int map_foreachinmap(int (*func)(struct block_list *,va_list), int m, int type,. /// @return The new object id int map_get_new_object_id(void) { - static int last_object_id = MIN_FLOORITEM - 1; - int i; + static int last_object_id = MIN_FLOORITEM - 1; + int i; - // find a free id - i = last_object_id + 1; - while (i != last_object_id) { - if (i == MAX_FLOORITEM) - i = MIN_FLOORITEM; + // find a free id + i = last_object_id + 1; + while( i != last_object_id ) { + if( i == MAX_FLOORITEM ) + i = MIN_FLOORITEM; - if (!idb_exists(id_db, i)) - break; + if( !idb_exists(id_db, i) ) + break; - ++i; - } + ++i; + } - if (i == last_object_id) { - ShowError("map_addobject: no free object id!\n"); - return 0; - } + if( i == last_object_id ) { + ShowError("map_addobject: no free object id!\n"); + return 0; + } - // update cursor - last_object_id = i; + // update cursor + last_object_id = i; - return i; + return i; } /*========================================== @@ -1261,38 +1268,37 @@ int map_get_new_object_id(void) *------------------------------------------*/ int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct flooritem_data *fitem = (struct flooritem_data *)idb_get(id_db, id); + struct flooritem_data* fitem = (struct flooritem_data*)idb_get(id_db, id); - if (fitem == NULL || fitem->bl.type != BL_ITEM || (fitem->cleartimer != tid)) { - ShowError("map_clearflooritem_timer : error\n"); - return 1; - } + if (fitem == NULL || fitem->bl.type != BL_ITEM || (fitem->cleartimer != tid)) { + ShowError("map_clearflooritem_timer : error\n"); + return 1; + } - if (search_petDB_index(fitem->item_data.nameid, PET_EGG) >= 0) - intif_delete_petdata(MakeDWord(fitem->item_data.card[1], fitem->item_data.card[2])); + if (search_petDB_index(fitem->item_data.nameid, PET_EGG) >= 0) + intif_delete_petdata(MakeDWord(fitem->item_data.card[1], fitem->item_data.card[2])); - clif_clearflooritem(fitem, 0); - map_deliddb(&fitem->bl); - map_delblock(&fitem->bl); - map_freeblock(&fitem->bl); - return 0; + clif_clearflooritem(fitem, 0); + map_deliddb(&fitem->bl); + map_delblock(&fitem->bl); + map_freeblock(&fitem->bl); + return 0; } -/* +/* * clears a single bl item out of the bazooonga. */ -void map_clearflooritem(struct block_list *bl) -{ - struct flooritem_data *fitem = (struct flooritem_data *)bl; - - if (fitem->cleartimer) - delete_timer(fitem->cleartimer,map_clearflooritem_timer); - - clif_clearflooritem(fitem, 0); - map_deliddb(&fitem->bl); - map_delblock(&fitem->bl); - map_freeblock(&fitem->bl); +void map_clearflooritem(struct block_list *bl) { + struct flooritem_data* fitem = (struct flooritem_data*)bl; + + if( fitem->cleartimer ) + delete_timer(fitem->cleartimer,map_clearflooritem_timer); + + clif_clearflooritem(fitem, 0); + map_deliddb(&fitem->bl); + map_delblock(&fitem->bl); + map_freeblock(&fitem->bl); } /*========================================== @@ -1300,38 +1306,37 @@ void map_clearflooritem(struct block_list *bl) * to place an BL_ITEM object. Scan area is 9x9, returns 1 on success. * x and y are modified with the target cell when successful. *------------------------------------------*/ -int map_searchrandfreecell(int m,int *x,int *y,int stack) -{ - int free_cell,i,j; - int free_cells[9][2]; - - for (free_cell=0,i=-1; i<=1; i++) { - if (i+*y<0 || i+*y>=map[m].ys) - continue; - for (j=-1; j<=1; j++) { - if (j+*x<0 || j+*x>=map[m].xs) - continue; - if (map_getcell(m,j+*x,i+*y,CELL_CHKNOPASS) && !map_getcell(m,j+*x,i+*y,CELL_CHKICEWALL)) - continue; - //Avoid item stacking to prevent against exploits. [Skotlex] - if (stack && map_count_oncell(m,j+*x,i+*y, BL_ITEM) > stack) - continue; - free_cells[free_cell][0] = j+*x; - free_cells[free_cell++][1] = i+*y; - } - } - if (free_cell==0) - return 0; - free_cell = rnd()%free_cell; - *x = free_cells[free_cell][0]; - *y = free_cells[free_cell][1]; - return 1; +int map_searchrandfreecell(int m,int *x,int *y,int stack) { + int free_cell,i,j; + int free_cells[9][2]; + + for(free_cell=0,i=-1;i<=1;i++){ + if(i+*y<0 || i+*y>=map[m].ys) + continue; + for(j=-1;j<=1;j++){ + if(j+*x<0 || j+*x>=map[m].xs) + continue; + if(map_getcell(m,j+*x,i+*y,CELL_CHKNOPASS) && !map_getcell(m,j+*x,i+*y,CELL_CHKICEWALL)) + continue; + //Avoid item stacking to prevent against exploits. [Skotlex] + if(stack && map_count_oncell(m,j+*x,i+*y, BL_ITEM) > stack) + continue; + free_cells[free_cell][0] = j+*x; + free_cells[free_cell++][1] = i+*y; + } + } + if(free_cell==0) + return 0; + free_cell = rnd()%free_cell; + *x = free_cells[free_cell][0]; + *y = free_cells[free_cell][1]; + return 1; } static int map_count_sub(struct block_list *bl,va_list ap) { - return 1; + return 1; } /*========================================== @@ -1348,64 +1353,66 @@ static int map_count_sub(struct block_list *bl,va_list ap) *------------------------------------------*/ int map_search_freecell(struct block_list *src, int m, short *x,short *y, int rx, int ry, int flag) { - int tries, spawn=0; - int bx, by; - int rx2 = 2*rx+1; - int ry2 = 2*ry+1; - - if (!src && (!(flag&1) || flag&2)) { - ShowDebug("map_search_freecell: Incorrect usage! When src is NULL, flag has to be &1 and can't have &2\n"); - return 0; - } - - if (flag&1) { - bx = *x; - by = *y; - } else { - bx = src->x; - by = src->y; - m = src->m; - } - if (!rx && !ry) { - //No range? Return the target cell then.... - *x = bx; - *y = by; - return map_getcell(m,*x,*y,CELL_CHKREACH); - } - - if (rx >= 0 && ry >= 0) { - tries = rx2*ry2; - if (tries > 100) tries = 100; - } else { - tries = map[m].xs*map[m].ys; - if (tries > 500) tries = 500; - } - - while (tries--) { - *x = (rx >= 0)?(rnd()%rx2-rx+bx):(rnd()%(map[m].xs-2)+1); - *y = (ry >= 0)?(rnd()%ry2-ry+by):(rnd()%(map[m].ys-2)+1); - - if (*x == bx && *y == by) - continue; //Avoid picking the same target tile. - - if (map_getcell(m,*x,*y,CELL_CHKREACH)) { - if (flag&2 && !unit_can_reach_pos(src, *x, *y, 1)) - continue; - if (flag&4) { - if (spawn >= 100) return 0; //Limit of retries reached. - if (spawn++ < battle_config.no_spawn_on_player && - map_foreachinarea(map_count_sub, m, - *x-AREA_SIZE, *y-AREA_SIZE, - *x+AREA_SIZE, *y+AREA_SIZE, BL_PC) - ) - continue; - } - return 1; - } - } - *x = bx; - *y = by; - return 0; + int tries, spawn=0; + int bx, by; + int rx2 = 2*rx+1; + int ry2 = 2*ry+1; + + if( !src && (!(flag&1) || flag&2) ) + { + ShowDebug("map_search_freecell: Incorrect usage! When src is NULL, flag has to be &1 and can't have &2\n"); + return 0; + } + + if (flag&1) { + bx = *x; + by = *y; + } else { + bx = src->x; + by = src->y; + m = src->m; + } + if (!rx && !ry) { + //No range? Return the target cell then.... + *x = bx; + *y = by; + return map_getcell(m,*x,*y,CELL_CHKREACH); + } + + if (rx >= 0 && ry >= 0) { + tries = rx2*ry2; + if (tries > 100) tries = 100; + } else { + tries = map[m].xs*map[m].ys; + if (tries > 500) tries = 500; + } + + while(tries--) { + *x = (rx >= 0)?(rnd()%rx2-rx+bx):(rnd()%(map[m].xs-2)+1); + *y = (ry >= 0)?(rnd()%ry2-ry+by):(rnd()%(map[m].ys-2)+1); + + if (*x == bx && *y == by) + continue; //Avoid picking the same target tile. + + if (map_getcell(m,*x,*y,CELL_CHKREACH)) + { + if(flag&2 && !unit_can_reach_pos(src, *x, *y, 1)) + continue; + if(flag&4) { + if (spawn >= 100) return 0; //Limit of retries reached. + if (spawn++ < battle_config.no_spawn_on_player && + map_foreachinarea(map_count_sub, m, + *x-AREA_SIZE, *y-AREA_SIZE, + *x+AREA_SIZE, *y+AREA_SIZE, BL_PC) + ) + continue; + } + return 1; + } + } + *x = bx; + *y = by; + return 0; } /*========================================== @@ -1419,45 +1426,45 @@ int map_search_freecell(struct block_list *src, int m, short *x,short *y, int rx *------------------------------------------*/ int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,int first_charid,int second_charid,int third_charid,int flags) { - int r; - struct flooritem_data *fitem=NULL; + int r; + struct flooritem_data *fitem=NULL; - nullpo_ret(item_data); + nullpo_ret(item_data); - if (!map_searchrandfreecell(m,&x,&y,flags&2?1:0)) - return 0; - r=rnd(); + if(!map_searchrandfreecell(m,&x,&y,flags&2?1:0)) + return 0; + r=rnd(); - CREATE(fitem, struct flooritem_data, 1); - fitem->bl.type=BL_ITEM; - fitem->bl.prev = fitem->bl.next = NULL; - fitem->bl.m=m; - fitem->bl.x=x; - fitem->bl.y=y; - fitem->bl.id = map_get_new_object_id(); - if (fitem->bl.id==0) { - aFree(fitem); - return 0; - } + CREATE(fitem, struct flooritem_data, 1); + fitem->bl.type=BL_ITEM; + fitem->bl.prev = fitem->bl.next = NULL; + fitem->bl.m=m; + fitem->bl.x=x; + fitem->bl.y=y; + fitem->bl.id = map_get_new_object_id(); + if(fitem->bl.id==0){ + aFree(fitem); + return 0; + } - fitem->first_get_charid = first_charid; - fitem->first_get_tick = gettick() + (flags&1 ? battle_config.mvp_item_first_get_time : battle_config.item_first_get_time); - fitem->second_get_charid = second_charid; - fitem->second_get_tick = fitem->first_get_tick + (flags&1 ? battle_config.mvp_item_second_get_time : battle_config.item_second_get_time); - fitem->third_get_charid = third_charid; - fitem->third_get_tick = fitem->second_get_tick + (flags&1 ? battle_config.mvp_item_third_get_time : battle_config.item_third_get_time); + fitem->first_get_charid = first_charid; + fitem->first_get_tick = gettick() + (flags&1 ? battle_config.mvp_item_first_get_time : battle_config.item_first_get_time); + fitem->second_get_charid = second_charid; + fitem->second_get_tick = fitem->first_get_tick + (flags&1 ? battle_config.mvp_item_second_get_time : battle_config.item_second_get_time); + fitem->third_get_charid = third_charid; + fitem->third_get_tick = fitem->second_get_tick + (flags&1 ? battle_config.mvp_item_third_get_time : battle_config.item_third_get_time); - memcpy(&fitem->item_data,item_data,sizeof(*item_data)); - fitem->item_data.amount=amount; - fitem->subx=(r&3)*3+3; - fitem->suby=((r>>2)&3)*3+3; - fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0); + memcpy(&fitem->item_data,item_data,sizeof(*item_data)); + fitem->item_data.amount=amount; + fitem->subx=(r&3)*3+3; + fitem->suby=((r>>2)&3)*3+3; + fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0); - map_addiddb(&fitem->bl); - map_addblock(&fitem->bl); - clif_dropflooritem(fitem); + map_addiddb(&fitem->bl); + map_addblock(&fitem->bl); + clif_dropflooritem(fitem); - return fitem->bl.id; + return fitem->bl.id; } /** @@ -1465,85 +1472,89 @@ int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,int fir */ static DBData create_charid2nick(DBKey key, va_list args) { - struct charid2nick *p; - CREATE(p, struct charid2nick, 1); - return db_ptr2data(p); + struct charid2nick *p; + CREATE(p, struct charid2nick, 1); + return db_ptr2data(p); } /// Adds(or replaces) the nick of charid to nick_db and fullfils pending requests. /// Does nothing if the character is online. -void map_addnickdb(int charid, const char *nick) +void map_addnickdb(int charid, const char* nick) { - struct charid2nick *p; - struct charid_request *req; - struct map_session_data *sd; + struct charid2nick* p; + struct charid_request* req; + struct map_session_data* sd; - if (map_charid2sd(charid)) - return;// already online + if( map_charid2sd(charid) ) + return;// already online - p = idb_ensure(nick_db, charid, create_charid2nick); - safestrncpy(p->nick, nick, sizeof(p->nick)); + p = idb_ensure(nick_db, charid, create_charid2nick); + safestrncpy(p->nick, nick, sizeof(p->nick)); - while (p->requests) { - req = p->requests; - p->requests = req->next; - sd = map_charid2sd(req->charid); - if (sd) - clif_solved_charname(sd->fd, charid, p->nick); - aFree(req); - } + while( p->requests ) + { + req = p->requests; + p->requests = req->next; + sd = map_charid2sd(req->charid); + if( sd ) + clif_solved_charname(sd->fd, charid, p->nick); + aFree(req); + } } /// Removes the nick of charid from nick_db. /// Sends name to all pending requests on charid. -void map_delnickdb(int charid, const char *name) +void map_delnickdb(int charid, const char* name) { - struct charid2nick *p; - struct charid_request *req; - struct map_session_data *sd; - DBData data; + struct charid2nick* p; + struct charid_request* req; + struct map_session_data* sd; + DBData data; - if (!nick_db->remove(nick_db, db_i2key(charid), &data) || (p = db_data2ptr(&data)) == NULL) - return; + if (!nick_db->remove(nick_db, db_i2key(charid), &data) || (p = db_data2ptr(&data)) == NULL) + return; - while (p->requests) { - req = p->requests; - p->requests = req->next; - sd = map_charid2sd(req->charid); - if (sd) - clif_solved_charname(sd->fd, charid, name); - aFree(req); - } - aFree(p); + while( p->requests ) + { + req = p->requests; + p->requests = req->next; + sd = map_charid2sd(req->charid); + if( sd ) + clif_solved_charname(sd->fd, charid, name); + aFree(req); + } + aFree(p); } /// Notifies sd of the nick of charid. /// Uses the name in the character if online. /// Uses the name in nick_db if offline. -void map_reqnickdb(struct map_session_data *sd, int charid) -{ - struct charid2nick *p; - struct charid_request *req; - struct map_session_data *tsd; - - nullpo_retv(sd); - - tsd = map_charid2sd(charid); - if (tsd) { - clif_solved_charname(sd->fd, charid, tsd->status.name); - return; - } - - p = idb_ensure(nick_db, charid, create_charid2nick); - if (*p->nick) { - clif_solved_charname(sd->fd, charid, p->nick); - return; - } - // not in cache, request it - CREATE(req, struct charid_request, 1); - req->next = p->requests; - p->requests = req; - chrif_searchcharid(charid); +void map_reqnickdb(struct map_session_data * sd, int charid) +{ + struct charid2nick* p; + struct charid_request* req; + struct map_session_data* tsd; + + nullpo_retv(sd); + + tsd = map_charid2sd(charid); + if( tsd ) + { + clif_solved_charname(sd->fd, charid, tsd->status.name); + return; + } + + p = idb_ensure(nick_db, charid, create_charid2nick); + if( *p->nick ) + { + clif_solved_charname(sd->fd, charid, p->nick); + return; + } + // not in cache, request it + CREATE(req, struct charid_request, 1); + req->next = p->requests; + p->requests = req; + chrif_searchcharid(charid); } /*========================================== @@ -1551,24 +1562,27 @@ void map_reqnickdb(struct map_session_data *sd, int charid) *------------------------------------------*/ void map_addiddb(struct block_list *bl) { - nullpo_retv(bl); + nullpo_retv(bl); - if (bl->type == BL_PC) { - TBL_PC *sd = (TBL_PC *)bl; - idb_put(pc_db,sd->bl.id,sd); - idb_put(charid_db,sd->status.char_id,sd); - } else if (bl->type == BL_MOB) { - TBL_MOB *md = (TBL_MOB *)bl; - idb_put(mobid_db,bl->id,bl); + if( bl->type == BL_PC ) + { + TBL_PC* sd = (TBL_PC*)bl; + idb_put(pc_db,sd->bl.id,sd); + idb_put(charid_db,sd->status.char_id,sd); + } + else if( bl->type == BL_MOB ) + { + TBL_MOB* md = (TBL_MOB*)bl; + idb_put(mobid_db,bl->id,bl); - if (md->state.boss) - idb_put(bossid_db, bl->id, bl); - } + if( md->state.boss ) + idb_put(bossid_db, bl->id, bl); + } - if (bl->type & BL_REGEN) - idb_put(regen_db, bl->id, bl); + if( bl->type & BL_REGEN ) + idb_put(regen_db, bl->id, bl); - idb_put(id_db,bl->id,bl); + idb_put(id_db,bl->id,bl); } /*========================================== @@ -1576,202 +1590,211 @@ void map_addiddb(struct block_list *bl) *------------------------------------------*/ void map_deliddb(struct block_list *bl) { - nullpo_retv(bl); + nullpo_retv(bl); - if (bl->type == BL_PC) { - TBL_PC *sd = (TBL_PC *)bl; - idb_remove(pc_db,sd->bl.id); - idb_remove(charid_db,sd->status.char_id); - } else if (bl->type == BL_MOB) { - idb_remove(mobid_db,bl->id); - idb_remove(bossid_db,bl->id); - } + if( bl->type == BL_PC ) + { + TBL_PC* sd = (TBL_PC*)bl; + idb_remove(pc_db,sd->bl.id); + idb_remove(charid_db,sd->status.char_id); + } + else if( bl->type == BL_MOB ) + { + idb_remove(mobid_db,bl->id); + idb_remove(bossid_db,bl->id); + } - if (bl->type & BL_REGEN) - idb_remove(regen_db,bl->id); + if( bl->type & BL_REGEN ) + idb_remove(regen_db,bl->id); - idb_remove(id_db,bl->id); + idb_remove(id_db,bl->id); } /*========================================== * Standard call when a player connection is closed. *------------------------------------------*/ -int map_quit(struct map_session_data *sd) -{ - int i; - - if (!sd->state.active) { //Removing a player that is not active. - struct auth_node *node = chrif_search(sd->status.account_id); - if (node && node->char_id == sd->status.char_id && - node->state != ST_LOGOUT) - //Except when logging out, clear the auth-connect data immediately. - chrif_auth_delete(node->account_id, node->char_id, node->state); - //Non-active players should not have loaded any data yet (or it was cleared already) so no additional cleanups are needed. - return 0; - } - - if (sd->npc_timer_id != INVALID_TIMER) //Cancel the event timer. - npc_timerevent_quit(sd); - - if (sd->npc_id) - npc_event_dequeue(sd); - - if (sd->bg_id) - bg_team_leave(sd,1); - - pc_itemcd_do(sd,false); - - npc_script_event(sd, NPCE_LOGOUT); - - //Unit_free handles clearing the player related data, - //map_quit handles extra specific data which is related to quitting normally - //(changing map-servers invokes unit_free but bypasses map_quit) - if (sd->sc.count) { - //Status that are not saved... - status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER); - status_change_end(&sd->bl, SC_AUTOTRADE, INVALID_TIMER); - status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER); - status_change_end(&sd->bl, SC_BERSERK, INVALID_TIMER); - status_change_end(&sd->bl, SC__BLOODYLUST, INVALID_TIMER); - status_change_end(&sd->bl, SC_TRICKDEAD, INVALID_TIMER); - status_change_end(&sd->bl, SC_LEADERSHIP, INVALID_TIMER); - status_change_end(&sd->bl, SC_GLORYWOUNDS, INVALID_TIMER); - status_change_end(&sd->bl, SC_SOULCOLD, INVALID_TIMER); - status_change_end(&sd->bl, SC_HAWKEYES, INVALID_TIMER); - if (sd->sc.data[SC_ENDURE] && sd->sc.data[SC_ENDURE]->val4) - status_change_end(&sd->bl, SC_ENDURE, INVALID_TIMER); //No need to save infinite endure. - status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER); - status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER); +int map_quit(struct map_session_data *sd) { + int i; + + if(!sd->state.active) { //Removing a player that is not active. + struct auth_node *node = chrif_search(sd->status.account_id); + if (node && node->char_id == sd->status.char_id && + node->state != ST_LOGOUT) + //Except when logging out, clear the auth-connect data immediately. + chrif_auth_delete(node->account_id, node->char_id, node->state); + //Non-active players should not have loaded any data yet (or it was cleared already) so no additional cleanups are needed. + return 0; + } + + if (sd->npc_timer_id != INVALID_TIMER) //Cancel the event timer. + npc_timerevent_quit(sd); + + if (sd->npc_id) + npc_event_dequeue(sd); + + if( sd->bg_id ) + bg_team_leave(sd,1); + + pc_itemcd_do(sd,false); + + npc_script_event(sd, NPCE_LOGOUT); + + //Unit_free handles clearing the player related data, + //map_quit handles extra specific data which is related to quitting normally + //(changing map-servers invokes unit_free but bypasses map_quit) + if( sd->sc.count ) { + //Status that are not saved... + status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER); + status_change_end(&sd->bl, SC_AUTOTRADE, INVALID_TIMER); + status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER); + status_change_end(&sd->bl, SC_BERSERK, INVALID_TIMER); + status_change_end(&sd->bl, SC__BLOODYLUST, INVALID_TIMER); + status_change_end(&sd->bl, SC_TRICKDEAD, INVALID_TIMER); + status_change_end(&sd->bl, SC_LEADERSHIP, INVALID_TIMER); + status_change_end(&sd->bl, SC_GLORYWOUNDS, INVALID_TIMER); + status_change_end(&sd->bl, SC_SOULCOLD, INVALID_TIMER); + status_change_end(&sd->bl, SC_HAWKEYES, INVALID_TIMER); + if(sd->sc.data[SC_ENDURE] && sd->sc.data[SC_ENDURE]->val4) + status_change_end(&sd->bl, SC_ENDURE, INVALID_TIMER); //No need to save infinite endure. + status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER); + status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER); status_change_end(&sd->bl, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); - status_change_end(&sd->bl, SC_KYOUGAKU, INVALID_TIMER); - if (battle_config.debuff_on_logout&1) { - status_change_end(&sd->bl, SC_ORCISH, INVALID_TIMER); - status_change_end(&sd->bl, SC_STRIPWEAPON, INVALID_TIMER); - status_change_end(&sd->bl, SC_STRIPARMOR, INVALID_TIMER); - status_change_end(&sd->bl, SC_STRIPSHIELD, INVALID_TIMER); - status_change_end(&sd->bl, SC_STRIPHELM, INVALID_TIMER); - status_change_end(&sd->bl, SC_EXTREMITYFIST, INVALID_TIMER); - status_change_end(&sd->bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER); - if (sd->sc.data[SC_REGENERATION] && sd->sc.data[SC_REGENERATION]->val4) - status_change_end(&sd->bl, SC_REGENERATION, INVALID_TIMER); - //TO-DO Probably there are way more NPC_type negative status that are removed - status_change_end(&sd->bl, SC_CHANGEUNDEAD, INVALID_TIMER); - // Both these statuses are removed on logout. [L0ne_W0lf] - status_change_end(&sd->bl, SC_SLOWCAST, INVALID_TIMER); - status_change_end(&sd->bl, SC_CRITICALWOUND, INVALID_TIMER); - } - if (battle_config.debuff_on_logout&2) { - status_change_end(&sd->bl, SC_MAXIMIZEPOWER, INVALID_TIMER); - status_change_end(&sd->bl, SC_MAXOVERTHRUST, INVALID_TIMER); - status_change_end(&sd->bl, SC_STEELBODY, INVALID_TIMER); - status_change_end(&sd->bl, SC_PRESERVE, INVALID_TIMER); - status_change_end(&sd->bl, SC_KAAHI, INVALID_TIMER); - status_change_end(&sd->bl, SC_SPIRIT, INVALID_TIMER); - } - } - - for (i = 0; i < EQI_MAX; i++) { - if (sd->equip_index[ i ] >= 0) - if (!pc_isequip(sd , sd->equip_index[ i ])) - pc_unequipitem(sd , sd->equip_index[ i ] , 2); - } - - // Return loot to owner - if (sd->pd) pet_lootitem_drop(sd->pd, sd); - - if (sd->state.storage_flag == 1) sd->state.storage_flag = 0; // No need to Double Save Storage on Quit. - - if (sd->ed) { - elemental_clean_effect(sd->ed); - unit_remove_map(&sd->ed->bl,CLR_TELEPORT); - } - - unit_remove_map_pc(sd,CLR_TELEPORT); - - if (map[sd->bl.m].instance_id) { - // Avoid map conflicts and warnings on next login - int m; - struct point *pt; - if (map[sd->bl.m].save.map) - pt = &map[sd->bl.m].save; - else - pt = &sd->status.save_point; - - if ((m=map_mapindex2mapid(pt->map)) >= 0) { - sd->bl.m = m; - sd->bl.x = pt->x; - sd->bl.y = pt->y; - sd->mapindex = pt->map; - } - } - - party_booking_delete(sd); // Party Booking [Spiria] - pc_makesavestatus(sd); - pc_clean_skilltree(sd); - chrif_save(sd,1); - unit_free_pc(sd); - return 0; + status_change_end(&sd->bl, SC_KYOUGAKU, INVALID_TIMER); + if (battle_config.debuff_on_logout&1) { + status_change_end(&sd->bl, SC_ORCISH, INVALID_TIMER); + status_change_end(&sd->bl, SC_STRIPWEAPON, INVALID_TIMER); + status_change_end(&sd->bl, SC_STRIPARMOR, INVALID_TIMER); + status_change_end(&sd->bl, SC_STRIPSHIELD, INVALID_TIMER); + status_change_end(&sd->bl, SC_STRIPHELM, INVALID_TIMER); + status_change_end(&sd->bl, SC_EXTREMITYFIST, INVALID_TIMER); + status_change_end(&sd->bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER); + if(sd->sc.data[SC_REGENERATION] && sd->sc.data[SC_REGENERATION]->val4) + status_change_end(&sd->bl, SC_REGENERATION, INVALID_TIMER); + //TO-DO Probably there are way more NPC_type negative status that are removed + status_change_end(&sd->bl, SC_CHANGEUNDEAD, INVALID_TIMER); + // Both these statuses are removed on logout. [L0ne_W0lf] + status_change_end(&sd->bl, SC_SLOWCAST, INVALID_TIMER); + status_change_end(&sd->bl, SC_CRITICALWOUND, INVALID_TIMER); + } + if (battle_config.debuff_on_logout&2) { + status_change_end(&sd->bl, SC_MAXIMIZEPOWER, INVALID_TIMER); + status_change_end(&sd->bl, SC_MAXOVERTHRUST, INVALID_TIMER); + status_change_end(&sd->bl, SC_STEELBODY, INVALID_TIMER); + status_change_end(&sd->bl, SC_PRESERVE, INVALID_TIMER); + status_change_end(&sd->bl, SC_KAAHI, INVALID_TIMER); + status_change_end(&sd->bl, SC_SPIRIT, INVALID_TIMER); + } + } + + for( i = 0; i < EQI_MAX; i++ ) { + if( sd->equip_index[ i ] >= 0 ) + if( !pc_isequip( sd , sd->equip_index[ i ] ) ) + pc_unequipitem( sd , sd->equip_index[ i ] , 2 ); + } + + // Return loot to owner + if( sd->pd ) pet_lootitem_drop(sd->pd, sd); + + if( sd->state.storage_flag == 1 ) sd->state.storage_flag = 0; // No need to Double Save Storage on Quit. + + if( sd->ed ) { + elemental_clean_effect(sd->ed); + unit_remove_map(&sd->ed->bl,CLR_TELEPORT); + } + + unit_remove_map_pc(sd,CLR_TELEPORT); + + if( map[sd->bl.m].instance_id ) + { // Avoid map conflicts and warnings on next login + int m; + struct point *pt; + if( map[sd->bl.m].save.map ) + pt = &map[sd->bl.m].save; + else + pt = &sd->status.save_point; + + if( (m=map_mapindex2mapid(pt->map)) >= 0 ) + { + sd->bl.m = m; + sd->bl.x = pt->x; + sd->bl.y = pt->y; + sd->mapindex = pt->map; + } + } + + party_booking_delete(sd); // Party Booking [Spiria] + pc_makesavestatus(sd); + pc_clean_skilltree(sd); + chrif_save(sd,1); + unit_free_pc(sd); + return 0; } /*========================================== * Lookup, id to session (player,mob,npc,homon,merc..) *------------------------------------------*/ -struct map_session_data *map_id2sd(int id) { - if (id <= 0) return NULL; - return (struct map_session_data *)idb_get(pc_db,id); +struct map_session_data * map_id2sd(int id) +{ + if (id <= 0) return NULL; + return (struct map_session_data*)idb_get(pc_db,id); } -struct mob_data *map_id2md(int id) { - if (id <= 0) return NULL; - return (struct mob_data *)idb_get(mobid_db,id); +struct mob_data * map_id2md(int id) +{ + if (id <= 0) return NULL; + return (struct mob_data*)idb_get(mobid_db,id); } -struct npc_data *map_id2nd(int id) { - // just a id2bl lookup because there's no npc_db - struct block_list *bl = map_id2bl(id); +struct npc_data * map_id2nd(int id) +{// just a id2bl lookup because there's no npc_db + struct block_list* bl = map_id2bl(id); - return BL_CAST(BL_NPC, bl); + return BL_CAST(BL_NPC, bl); } -struct homun_data *map_id2hd(int id) { - struct block_list *bl = map_id2bl(id); +struct homun_data* map_id2hd(int id) +{ + struct block_list* bl = map_id2bl(id); - return BL_CAST(BL_HOM, bl); + return BL_CAST(BL_HOM, bl); } -struct mercenary_data *map_id2mc(int id) { - struct block_list *bl = map_id2bl(id); +struct mercenary_data* map_id2mc(int id) +{ + struct block_list* bl = map_id2bl(id); - return BL_CAST(BL_MER, bl); + return BL_CAST(BL_MER, bl); } -struct chat_data *map_id2cd(int id) { - struct block_list *bl = map_id2bl(id); +struct chat_data* map_id2cd(int id) +{ + struct block_list* bl = map_id2bl(id); - return BL_CAST(BL_CHAT, bl); + return BL_CAST(BL_CHAT, bl); } /// Returns the nick of the target charid or NULL if unknown (requests the nick to the char server). -const char *map_charid2nick(int charid) +const char* map_charid2nick(int charid) { - struct charid2nick *p; - struct map_session_data *sd; + struct charid2nick *p; + struct map_session_data* sd; - sd = map_charid2sd(charid); - if (sd) - return sd->status.name;// character is online, return it's name + sd = map_charid2sd(charid); + if( sd ) + return sd->status.name;// character is online, return it's name - p = idb_ensure(nick_db, charid, create_charid2nick); - if (*p->nick) - return p->nick;// name in nick_db + p = idb_ensure(nick_db, charid, create_charid2nick); + if( *p->nick ) + return p->nick;// name in nick_db - chrif_searchcharid(charid);// request the name - return NULL; + chrif_searchcharid(charid);// request the name + return NULL; } /// Returns the struct map_session_data of the charid or NULL if the char is not online. -struct map_session_data *map_charid2sd(int charid) { - return (struct map_session_data *)idb_get(charid_db, charid); +struct map_session_data* map_charid2sd(int charid) +{ + return (struct map_session_data*)idb_get(charid_db, charid); } /*========================================== @@ -1779,202 +1802,216 @@ struct map_session_data *map_charid2sd(int charid) { * (without sensitive case if necessary) * return map_session_data pointer or NULL *------------------------------------------*/ -struct map_session_data *map_nick2sd(const char *nick) { - struct map_session_data *sd; - struct map_session_data *found_sd; - struct s_mapiterator *iter; - size_t nicklen; - int qty = 0; - - if (nick == NULL) - return NULL; - - nicklen = strlen(nick); - iter = mapit_getallusers(); - - found_sd = NULL; - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) { - if (battle_config.partial_name_scan) { - // partial name search - if (strnicmp(sd->status.name, nick, nicklen) == 0) { - found_sd = sd; - - if (strcmp(sd->status.name, nick) == 0) { - // Perfect Match - qty = 1; - break; - } - - qty++; - } - } else if (strcasecmp(sd->status.name, nick) == 0) { - // exact search only - found_sd = sd; - break; - } - } - mapit_free(iter); - - if (battle_config.partial_name_scan && qty != 1) - found_sd = NULL; - - return found_sd; +struct map_session_data * map_nick2sd(const char *nick) +{ + struct map_session_data* sd; + struct map_session_data* found_sd; + struct s_mapiterator* iter; + size_t nicklen; + int qty = 0; + + if( nick == NULL ) + return NULL; + + nicklen = strlen(nick); + iter = mapit_getallusers(); + + found_sd = NULL; + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + { + if( battle_config.partial_name_scan ) + {// partial name search + if( strnicmp(sd->status.name, nick, nicklen) == 0 ) + { + found_sd = sd; + + if( strcmp(sd->status.name, nick) == 0 ) + {// Perfect Match + qty = 1; + break; + } + + qty++; + } + } + else if( strcasecmp(sd->status.name, nick) == 0 ) + {// exact search only + found_sd = sd; + break; + } + } + mapit_free(iter); + + if( battle_config.partial_name_scan && qty != 1 ) + found_sd = NULL; + + return found_sd; } /*========================================== * Looksup id_db DBMap and returns BL pointer of 'id' or NULL if not found *------------------------------------------*/ -struct block_list *map_id2bl(int id) { - return (struct block_list *)idb_get(id_db,id); +struct block_list * map_id2bl(int id) { + return (struct block_list*)idb_get(id_db,id); } /** * Same as map_id2bl except it only checks for its existence **/ -bool map_blid_exists(int id) -{ - return (idb_exists(id_db,id)); +bool map_blid_exists( int id ) { + return (idb_exists(id_db,id)); } /*========================================== * Convext Mirror *------------------------------------------*/ -struct mob_data *map_getmob_boss(int m) { - DBIterator *iter; - struct mob_data *md = NULL; - bool found = false; +struct mob_data * map_getmob_boss(int m) +{ + DBIterator* iter; + struct mob_data *md = NULL; + bool found = false; - iter = db_iterator(bossid_db); - for (md = (struct mob_data *)dbi_first(iter); dbi_exists(iter); md = (struct mob_data *)dbi_next(iter)) { - if (md->bl.m == m) { - found = true; - break; - } - } - dbi_destroy(iter); + iter = db_iterator(bossid_db); + for( md = (struct mob_data*)dbi_first(iter); dbi_exists(iter); md = (struct mob_data*)dbi_next(iter) ) + { + if( md->bl.m == m ) + { + found = true; + break; + } + } + dbi_destroy(iter); - return (found)? md : NULL; + return (found)? md : NULL; } -struct mob_data *map_id2boss(int id) { - if (id <= 0) return NULL; - return (struct mob_data *)idb_get(bossid_db,id); +struct mob_data * map_id2boss(int id) +{ + if (id <= 0) return NULL; + return (struct mob_data*)idb_get(bossid_db,id); } /// Applies func to all the players in the db. /// Stops iterating if func returns -1. -void map_foreachpc(int (*func)(struct map_session_data *sd, va_list args), ...) +void map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...) { - DBIterator *iter; - struct map_session_data *sd; + DBIterator* iter; + struct map_session_data* sd; - iter = db_iterator(pc_db); - for (sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter)) { - va_list args; - int ret; + iter = db_iterator(pc_db); + for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) ) + { + va_list args; + int ret; - va_start(args, func); - ret = func(sd, args); - va_end(args); - if (ret == -1) - break;// stop iterating - } - dbi_destroy(iter); + va_start(args, func); + ret = func(sd, args); + va_end(args); + if( ret == -1 ) + break;// stop iterating + } + dbi_destroy(iter); } /// Applies func to all the mobs in the db. /// Stops iterating if func returns -1. -void map_foreachmob(int (*func)(struct mob_data *md, va_list args), ...) +void map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...) { - DBIterator *iter; - struct mob_data *md; + DBIterator* iter; + struct mob_data* md; - iter = db_iterator(mobid_db); - for (md = (struct mob_data *)dbi_first(iter); dbi_exists(iter); md = (struct mob_data *)dbi_next(iter)) { - va_list args; - int ret; + iter = db_iterator(mobid_db); + for( md = (struct mob_data*)dbi_first(iter); dbi_exists(iter); md = (struct mob_data*)dbi_next(iter) ) + { + va_list args; + int ret; - va_start(args, func); - ret = func(md, args); - va_end(args); - if (ret == -1) - break;// stop iterating - } - dbi_destroy(iter); + va_start(args, func); + ret = func(md, args); + va_end(args); + if( ret == -1 ) + break;// stop iterating + } + dbi_destroy(iter); } /// Applies func to all the npcs in the db. /// Stops iterating if func returns -1. -void map_foreachnpc(int (*func)(struct npc_data *nd, va_list args), ...) -{ - DBIterator *iter; - struct block_list *bl; - - iter = db_iterator(id_db); - for (bl = (struct block_list *)dbi_first(iter); dbi_exists(iter); bl = (struct block_list *)dbi_next(iter)) { - if (bl->type == BL_NPC) { - struct npc_data *nd = (struct npc_data *)bl; - va_list args; - int ret; - - va_start(args, func); - ret = func(nd, args); - va_end(args); - if (ret == -1) - break;// stop iterating - } - } - dbi_destroy(iter); +void map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...) +{ + DBIterator* iter; + struct block_list* bl; + + iter = db_iterator(id_db); + for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) ) + { + if( bl->type == BL_NPC ) + { + struct npc_data* nd = (struct npc_data*)bl; + va_list args; + int ret; + + va_start(args, func); + ret = func(nd, args); + va_end(args); + if( ret == -1 ) + break;// stop iterating + } + } + dbi_destroy(iter); } /// Applies func to everything in the db. /// Stops iteratin gif func returns -1. -void map_foreachregen(int (*func)(struct block_list *bl, va_list args), ...) +void map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...) { - DBIterator *iter; - struct block_list *bl; + DBIterator* iter; + struct block_list* bl; - iter = db_iterator(regen_db); - for (bl = (struct block_list *)dbi_first(iter); dbi_exists(iter); bl = (struct block_list *)dbi_next(iter)) { - va_list args; - int ret; + iter = db_iterator(regen_db); + for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) ) + { + va_list args; + int ret; - va_start(args, func); - ret = func(bl, args); - va_end(args); - if (ret == -1) - break;// stop iterating - } - dbi_destroy(iter); + va_start(args, func); + ret = func(bl, args); + va_end(args); + if( ret == -1 ) + break;// stop iterating + } + dbi_destroy(iter); } /// Applies func to everything in the db. /// Stops iterating if func returns -1. -void map_foreachiddb(int (*func)(struct block_list *bl, va_list args), ...) +void map_foreachiddb(int (*func)(struct block_list* bl, va_list args), ...) { - DBIterator *iter; - struct block_list *bl; + DBIterator* iter; + struct block_list* bl; - iter = db_iterator(id_db); - for (bl = (struct block_list *)dbi_first(iter); dbi_exists(iter); bl = (struct block_list *)dbi_next(iter)) { - va_list args; - int ret; + iter = db_iterator(id_db); + for( bl = (struct block_list*)dbi_first(iter); dbi_exists(iter); bl = (struct block_list*)dbi_next(iter) ) + { + va_list args; + int ret; - va_start(args, func); - ret = func(bl, args); - va_end(args); - if (ret == -1) - break;// stop iterating - } - dbi_destroy(iter); + va_start(args, func); + ret = func(bl, args); + va_end(args); + if( ret == -1 ) + break;// stop iterating + } + dbi_destroy(iter); } /// Iterator. /// Can filter by bl type. -struct s_mapiterator { - enum e_mapitflags flags;// flags for special behaviour - enum bl_type types;// what bl types to return - DBIterator *dbi;// database iterator +struct s_mapiterator +{ + enum e_mapitflags flags;// flags for special behaviour + enum bl_type types;// what bl types to return + DBIterator* dbi;// database iterator }; /// Returns true if the block_list matches the description in the iterator. @@ -1983,9 +2020,9 @@ struct s_mapiterator { /// @param _bl_ block_list /// @return true if it matches #define MAPIT_MATCHES(_mapit_,_bl_) \ - ( \ - ( (_bl_)->type & (_mapit_)->types /* type matches */ ) \ - ) + ( \ + ( (_bl_)->type & (_mapit_)->types /* type matches */ ) \ + ) /// Allocates a new iterator. /// Returns the new iterator. @@ -1995,27 +2032,28 @@ struct s_mapiterator { /// @param flags Flags of the iterator /// @param type Target types /// @return Iterator -struct s_mapiterator *mapit_alloc(enum e_mapitflags flags, enum bl_type types) { - struct s_mapiterator *mapit; +struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types) +{ + struct s_mapiterator* mapit; - CREATE(mapit, struct s_mapiterator, 1); - mapit->flags = flags; - mapit->types = types; - if (types == BL_PC) mapit->dbi = db_iterator(pc_db); - else if (types == BL_MOB) mapit->dbi = db_iterator(mobid_db); - else mapit->dbi = db_iterator(id_db); - return mapit; + CREATE(mapit, struct s_mapiterator, 1); + mapit->flags = flags; + mapit->types = types; + if( types == BL_PC ) mapit->dbi = db_iterator(pc_db); + else if( types == BL_MOB ) mapit->dbi = db_iterator(mobid_db); + else mapit->dbi = db_iterator(id_db); + return mapit; } /// Frees the iterator. /// /// @param mapit Iterator -void mapit_free(struct s_mapiterator *mapit) +void mapit_free(struct s_mapiterator* mapit) { - nullpo_retv(mapit); + nullpo_retv(mapit); - dbi_destroy(mapit->dbi); - aFree(mapit); + dbi_destroy(mapit->dbi); + aFree(mapit); } /// Returns the first block_list that matches the description. @@ -2023,16 +2061,18 @@ void mapit_free(struct s_mapiterator *mapit) /// /// @param mapit Iterator /// @return first block_list or NULL -struct block_list *mapit_first(struct s_mapiterator *mapit) { - struct block_list *bl; +struct block_list* mapit_first(struct s_mapiterator* mapit) +{ + struct block_list* bl; - nullpo_retr(NULL,mapit); + nullpo_retr(NULL,mapit); - for (bl = (struct block_list *)dbi_first(mapit->dbi); bl != NULL; bl = (struct block_list *)dbi_next(mapit->dbi)) { - if (MAPIT_MATCHES(mapit,bl)) - break;// found match - } - return bl; + for( bl = (struct block_list*)dbi_first(mapit->dbi); bl != NULL; bl = (struct block_list*)dbi_next(mapit->dbi) ) + { + if( MAPIT_MATCHES(mapit,bl) ) + break;// found match + } + return bl; } /// Returns the last block_list that matches the description. @@ -2040,16 +2080,18 @@ struct block_list *mapit_first(struct s_mapiterator *mapit) { /// /// @param mapit Iterator /// @return last block_list or NULL -struct block_list *mapit_last(struct s_mapiterator *mapit) { - struct block_list *bl; +struct block_list* mapit_last(struct s_mapiterator* mapit) +{ + struct block_list* bl; - nullpo_retr(NULL,mapit); + nullpo_retr(NULL,mapit); - for (bl = (struct block_list *)dbi_last(mapit->dbi); bl != NULL; bl = (struct block_list *)dbi_prev(mapit->dbi)) { - if (MAPIT_MATCHES(mapit,bl)) - break;// found match - } - return bl; + for( bl = (struct block_list*)dbi_last(mapit->dbi); bl != NULL; bl = (struct block_list*)dbi_prev(mapit->dbi) ) + { + if( MAPIT_MATCHES(mapit,bl) ) + break;// found match + } + return bl; } /// Returns the next block_list that matches the description. @@ -2057,20 +2099,22 @@ struct block_list *mapit_last(struct s_mapiterator *mapit) { /// /// @param mapit Iterator /// @return next block_list or NULL -struct block_list *mapit_next(struct s_mapiterator *mapit) { - struct block_list *bl; +struct block_list* mapit_next(struct s_mapiterator* mapit) +{ + struct block_list* bl; - nullpo_retr(NULL,mapit); + nullpo_retr(NULL,mapit); - for (; ;) { - bl = (struct block_list *)dbi_next(mapit->dbi); - if (bl == NULL) - break;// end - if (MAPIT_MATCHES(mapit,bl)) - break;// found a match - // try next - } - return bl; + for( ; ; ) + { + bl = (struct block_list*)dbi_next(mapit->dbi); + if( bl == NULL ) + break;// end + if( MAPIT_MATCHES(mapit,bl) ) + break;// found a match + // try next + } + return bl; } /// Returns the previous block_list that matches the description. @@ -2078,31 +2122,33 @@ struct block_list *mapit_next(struct s_mapiterator *mapit) { /// /// @param mapit Iterator /// @return previous block_list or NULL -struct block_list *mapit_prev(struct s_mapiterator *mapit) { - struct block_list *bl; +struct block_list* mapit_prev(struct s_mapiterator* mapit) +{ + struct block_list* bl; - nullpo_retr(NULL,mapit); + nullpo_retr(NULL,mapit); - for (; ;) { - bl = (struct block_list *)dbi_prev(mapit->dbi); - if (bl == NULL) - break;// end - if (MAPIT_MATCHES(mapit,bl)) - break;// found a match - // try prev - } - return bl; + for( ; ; ) + { + bl = (struct block_list*)dbi_prev(mapit->dbi); + if( bl == NULL ) + break;// end + if( MAPIT_MATCHES(mapit,bl) ) + break;// found a match + // try prev + } + return bl; } /// Returns true if the current block_list exists in the database. /// /// @param mapit Iterator /// @return true if it exists -bool mapit_exists(struct s_mapiterator *mapit) +bool mapit_exists(struct s_mapiterator* mapit) { - nullpo_retr(false,mapit); + nullpo_retr(false,mapit); - return dbi_exists(mapit->dbi); + return dbi_exists(mapit->dbi); } /*========================================== @@ -2110,20 +2156,21 @@ bool mapit_exists(struct s_mapiterator *mapit) *------------------------------------------*/ bool map_addnpc(int m,struct npc_data *nd) { - nullpo_ret(nd); + nullpo_ret(nd); - if (m < 0 || m >= map_num) - return false; + if( m < 0 || m >= map_num ) + return false; - if (map[m].npc_num == MAX_NPC_PER_MAP) { - ShowWarning("too many NPCs in one map %s\n",map[m].name); - return false; - } + if( map[m].npc_num == MAX_NPC_PER_MAP ) + { + ShowWarning("too many NPCs in one map %s\n",map[m].name); + return false; + } - map[m].npc[map[m].npc_num]=nd; - map[m].npc_num++; - idb_put(id_db,nd->bl.id,nd); - return true; + map[m].npc[map[m].npc_num]=nd; + map[m].npc_num++; + idb_put(id_db,nd->bl.id,nd); + return true; } /*========================================= @@ -2133,107 +2180,110 @@ bool map_addnpc(int m,struct npc_data *nd) // Returns the index of successful, or -1 if the list was full. int map_addmobtolist(unsigned short m, struct spawn_data *spawn) { - size_t i; - ARR_FIND(0, MAX_MOB_LIST_PER_MAP, i, map[m].moblist[i] == NULL); - if (i < MAX_MOB_LIST_PER_MAP) { - map[m].moblist[i] = spawn; - return i; - } - return -1; + size_t i; + ARR_FIND( 0, MAX_MOB_LIST_PER_MAP, i, map[m].moblist[i] == NULL ); + if( i < MAX_MOB_LIST_PER_MAP ) + { + map[m].moblist[i] = spawn; + return i; + } + return -1; } void map_spawnmobs(int m) { - int i, k=0; - if (map[m].mob_delete_timer != INVALID_TIMER) { - //Mobs have not been removed yet [Skotlex] - delete_timer(map[m].mob_delete_timer, map_removemobs_timer); - map[m].mob_delete_timer = INVALID_TIMER; - return; - } - for (i=0; i<MAX_MOB_LIST_PER_MAP; i++) - if (map[m].moblist[i]!=NULL) { - k+=map[m].moblist[i]->num; - npc_parse_mob2(map[m].moblist[i]); - } - - if (battle_config.etc_log && k > 0) { - ShowStatus("Map %s: Spawned '"CL_WHITE"%d"CL_RESET"' mobs.\n",map[m].name, k); - } + int i, k=0; + if (map[m].mob_delete_timer != INVALID_TIMER) + { //Mobs have not been removed yet [Skotlex] + delete_timer(map[m].mob_delete_timer, map_removemobs_timer); + map[m].mob_delete_timer = INVALID_TIMER; + return; + } + for(i=0; i<MAX_MOB_LIST_PER_MAP; i++) + if(map[m].moblist[i]!=NULL) + { + k+=map[m].moblist[i]->num; + npc_parse_mob2(map[m].moblist[i]); + } + + if (battle_config.etc_log && k > 0) + { + ShowStatus("Map %s: Spawned '"CL_WHITE"%d"CL_RESET"' mobs.\n",map[m].name, k); + } } int map_removemobs_sub(struct block_list *bl, va_list ap) { - struct mob_data *md = (struct mob_data *)bl; - nullpo_ret(md); + struct mob_data *md = (struct mob_data *)bl; + nullpo_ret(md); - //When not to remove mob: - // doesn't respawn and is not a slave - if (!md->spawn && !md->master_id) - return 0; - // respawn data is not in cache - if (md->spawn && !md->spawn->state.dynamic) - return 0; - // hasn't spawned yet - if (md->spawn_timer != INVALID_TIMER) - return 0; - // is damaged and mob_remove_damaged is off - if (!battle_config.mob_remove_damaged && md->status.hp < md->status.max_hp) - return 0; - // is a mvp - if (md->db->mexp > 0) - return 0; + //When not to remove mob: + // doesn't respawn and is not a slave + if( !md->spawn && !md->master_id ) + return 0; + // respawn data is not in cache + if( md->spawn && !md->spawn->state.dynamic ) + return 0; + // hasn't spawned yet + if( md->spawn_timer != INVALID_TIMER ) + return 0; + // is damaged and mob_remove_damaged is off + if( !battle_config.mob_remove_damaged && md->status.hp < md->status.max_hp ) + return 0; + // is a mvp + if( md->db->mexp > 0 ) + return 0; - unit_free(&md->bl,CLR_OUTSIGHT); + unit_free(&md->bl,CLR_OUTSIGHT); - return 1; + return 1; } int map_removemobs_timer(int tid, unsigned int tick, int id, intptr_t data) { - int count; - const int m = id; + int count; + const int m = id; - if (m < 0 || m >= MAX_MAP_PER_SERVER) { - //Incorrect map id! - ShowError("map_removemobs_timer error: timer %d points to invalid map %d\n",tid, m); - return 0; - } - if (map[m].mob_delete_timer != tid) { - //Incorrect timer call! - ShowError("map_removemobs_timer mismatch: %d != %d (map %s)\n",map[m].mob_delete_timer, tid, map[m].name); - return 0; - } - map[m].mob_delete_timer = INVALID_TIMER; - if (map[m].users > 0) //Map not empty! - return 1; + if (m < 0 || m >= MAX_MAP_PER_SERVER) + { //Incorrect map id! + ShowError("map_removemobs_timer error: timer %d points to invalid map %d\n",tid, m); + return 0; + } + if (map[m].mob_delete_timer != tid) + { //Incorrect timer call! + ShowError("map_removemobs_timer mismatch: %d != %d (map %s)\n",map[m].mob_delete_timer, tid, map[m].name); + return 0; + } + map[m].mob_delete_timer = INVALID_TIMER; + if (map[m].users > 0) //Map not empty! + return 1; - count = map_foreachinmap(map_removemobs_sub, m, BL_MOB); + count = map_foreachinmap(map_removemobs_sub, m, BL_MOB); - if (battle_config.etc_log && count > 0) - ShowStatus("Map %s: Removed '"CL_WHITE"%d"CL_RESET"' mobs.\n",map[m].name, count); + if (battle_config.etc_log && count > 0) + ShowStatus("Map %s: Removed '"CL_WHITE"%d"CL_RESET"' mobs.\n",map[m].name, count); - return 1; + return 1; } void map_removemobs(int m) { - if (map[m].mob_delete_timer != INVALID_TIMER) // should never happen - return; //Mobs are already scheduled for removal + if (map[m].mob_delete_timer != INVALID_TIMER) // should never happen + return; //Mobs are already scheduled for removal - map[m].mob_delete_timer = add_timer(gettick()+battle_config.mob_remove_delay, map_removemobs_timer, m, 0); + map[m].mob_delete_timer = add_timer(gettick()+battle_config.mob_remove_delay, map_removemobs_timer, m, 0); } /*========================================== * Hookup, get map_id from map_name *------------------------------------------*/ -int map_mapname2mapid(const char *name) +int map_mapname2mapid(const char* name) { - unsigned short map_index; - map_index = mapindex_name2id(name); - if (!map_index) - return -1; - return map_mapindex2mapid(map_index); + unsigned short map_index; + map_index = mapindex_name2id(name); + if (!map_index) + return -1; + return map_mapindex2mapid(map_index); } /*========================================== @@ -2241,30 +2291,30 @@ int map_mapname2mapid(const char *name) *------------------------------------------*/ int map_mapindex2mapid(unsigned short mapindex) { - struct map_data *md=NULL; + struct map_data *md=NULL; - if (!mapindex) - return -1; + if (!mapindex) + return -1; - md = (struct map_data *)uidb_get(map_db,(unsigned int)mapindex); - if (md==NULL || md->cell==NULL) - return -1; - return md->m; + md = (struct map_data*)uidb_get(map_db,(unsigned int)mapindex); + if(md==NULL || md->cell==NULL) + return -1; + return md->m; } /*========================================== * Switching Ip, port ? (like changing map_server) get ip/port from map_name *------------------------------------------*/ -int map_mapname2ipport(unsigned short name, uint32 *ip, uint16 *port) +int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port) { - struct map_data_other_server *mdos=NULL; + struct map_data_other_server *mdos=NULL; - mdos = (struct map_data_other_server *)uidb_get(map_db,(unsigned int)name); - if (mdos==NULL || mdos->cell) //If gat isn't null, this is a local map. - return -1; - *ip=mdos->ip; - *port=mdos->port; - return 0; + mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)name); + if(mdos==NULL || mdos->cell) //If gat isn't null, this is a local map. + return -1; + *ip=mdos->ip; + *port=mdos->port; + return 0; } /*========================================== @@ -2272,76 +2322,64 @@ int map_mapname2ipport(unsigned short name, uint32 *ip, uint16 *port) *------------------------------------------*/ int map_check_dir(int s_dir,int t_dir) { - if (s_dir == t_dir) - return 0; - switch (s_dir) { - case 0: - if (t_dir == 7 || t_dir == 1 || t_dir == 0) return 0; - break; - case 1: - if (t_dir == 0 || t_dir == 2 || t_dir == 1) return 0; - break; - case 2: - if (t_dir == 1 || t_dir == 3 || t_dir == 2) return 0; - break; - case 3: - if (t_dir == 2 || t_dir == 4 || t_dir == 3) return 0; - break; - case 4: - if (t_dir == 3 || t_dir == 5 || t_dir == 4) return 0; - break; - case 5: - if (t_dir == 4 || t_dir == 6 || t_dir == 5) return 0; - break; - case 6: - if (t_dir == 5 || t_dir == 7 || t_dir == 6) return 0; - break; - case 7: - if (t_dir == 6 || t_dir == 0 || t_dir == 7) return 0; - break; - } - return 1; + if(s_dir == t_dir) + return 0; + switch(s_dir) { + case 0: if(t_dir == 7 || t_dir == 1 || t_dir == 0) return 0; break; + case 1: if(t_dir == 0 || t_dir == 2 || t_dir == 1) return 0; break; + case 2: if(t_dir == 1 || t_dir == 3 || t_dir == 2) return 0; break; + case 3: if(t_dir == 2 || t_dir == 4 || t_dir == 3) return 0; break; + case 4: if(t_dir == 3 || t_dir == 5 || t_dir == 4) return 0; break; + case 5: if(t_dir == 4 || t_dir == 6 || t_dir == 5) return 0; break; + case 6: if(t_dir == 5 || t_dir == 7 || t_dir == 6) return 0; break; + case 7: if(t_dir == 6 || t_dir == 0 || t_dir == 7) return 0; break; + } + return 1; } /*========================================== * Returns the direction of the given cell, relative to 'src' *------------------------------------------*/ -uint8 map_calc_dir(struct block_list *src, int x, int y) -{ - unsigned char dir = 0; - int dx, dy; - - nullpo_ret(src); - - dx = x-src->x; - dy = y-src->y; - if (dx == 0 && dy == 0) { - // both are standing on the same spot - //dir = 6; // aegis-style, makes knockback default to the left - dir = unit_getdir(src); // athena-style, makes knockback default to behind 'src' - } else if (dx >= 0 && dy >=0) { - // upper-right - if (dx*2 <= dy) dir = 0; // up - else if (dx > dy*2) dir = 6; // right - else dir = 7; // up-right - } else if (dx >= 0 && dy <= 0) { - // lower-right - if (dx*2 <= -dy) dir = 4; // down - else if (dx > -dy*2) dir = 6; // right - else dir = 5; // down-right - } else if (dx <= 0 && dy <= 0) { - // lower-left - if (dx*2 >= dy) dir = 4; // down - else if (dx < dy*2) dir = 2; // left - else dir = 3; // down-left - } else { - // upper-left - if (-dx*2 <= dy) dir = 0; // up - else if (-dx > dy*2) dir = 2; // left - else dir = 1; // up-left - - } - return dir; +uint8 map_calc_dir(struct block_list* src, int x, int y) +{ + unsigned char dir = 0; + int dx, dy; + + nullpo_ret(src); + + dx = x-src->x; + dy = y-src->y; + if( dx == 0 && dy == 0 ) + { // both are standing on the same spot + //dir = 6; // aegis-style, makes knockback default to the left + dir = unit_getdir(src); // athena-style, makes knockback default to behind 'src' + } + else if( dx >= 0 && dy >=0 ) + { // upper-right + if( dx*2 <= dy ) dir = 0; // up + else if( dx > dy*2 ) dir = 6; // right + else dir = 7; // up-right + } + else if( dx >= 0 && dy <= 0 ) + { // lower-right + if( dx*2 <= -dy ) dir = 4; // down + else if( dx > -dy*2 ) dir = 6; // right + else dir = 5; // down-right + } + else if( dx <= 0 && dy <= 0 ) + { // lower-left + if( dx*2 >= dy ) dir = 4; // down + else if( dx < dy*2 ) dir = 2; // left + else dir = 3; // down-left + } + else + { // upper-left + if( -dx*2 <= dy ) dir = 0; // up + else if( -dx > dy*2 ) dir = 2; // left + else dir = 1; // up-left + + } + return dir; } /*========================================== @@ -2350,92 +2388,64 @@ uint8 map_calc_dir(struct block_list *src, int x, int y) *------------------------------------------*/ int map_random_dir(struct block_list *bl, short *x, short *y) { - short xi = *x-bl->x; - short yi = *y-bl->y; - short i=0, j; - int dist2 = xi*xi + yi*yi; - short dist = (short)sqrt((float)dist2); - short segment; - - if (dist < 1) dist =1; - - do { - j = 1 + 2*(rnd()%4); //Pick a random diagonal direction - segment = 1+(rnd()%dist); //Pick a random interval from the whole vector in that direction - xi = bl->x + segment*dirx[j]; - segment = (short)sqrt((float)(dist2 - segment*segment)); //The complement of the previously picked segment - yi = bl->y + segment*diry[j]; - } while ( - (map_getcell(bl->m,xi,yi,CELL_CHKNOPASS) || !path_search(NULL,bl->m,bl->x,bl->y,xi,yi,1,CELL_CHKNOREACH)) - && (++i)<100); - - if (i < 100) { - *x = xi; - *y = yi; - return 1; - } - return 0; + short xi = *x-bl->x; + short yi = *y-bl->y; + short i=0, j; + int dist2 = xi*xi + yi*yi; + short dist = (short)sqrt((float)dist2); + short segment; + + if (dist < 1) dist =1; + + do { + j = 1 + 2*(rnd()%4); //Pick a random diagonal direction + segment = 1+(rnd()%dist); //Pick a random interval from the whole vector in that direction + xi = bl->x + segment*dirx[j]; + segment = (short)sqrt((float)(dist2 - segment*segment)); //The complement of the previously picked segment + yi = bl->y + segment*diry[j]; + } while ( + (map_getcell(bl->m,xi,yi,CELL_CHKNOPASS) || !path_search(NULL,bl->m,bl->x,bl->y,xi,yi,1,CELL_CHKNOREACH)) + && (++i)<100 ); + + if (i < 100) { + *x = xi; + *y = yi; + return 1; + } + return 0; } // gat system inline static struct mapcell map_gat2cell(int gat) { - struct mapcell cell; - - memset(&cell,0,sizeof(struct mapcell)); - - switch (gat) { - case 0: - cell.walkable = 1; - cell.shootable = 1; - cell.water = 0; - break; // walkable ground - case 1: - cell.walkable = 0; - cell.shootable = 0; - cell.water = 0; - break; // non-walkable ground - case 2: - cell.walkable = 1; - cell.shootable = 1; - cell.water = 0; - break; // ??? - case 3: - cell.walkable = 1; - cell.shootable = 1; - cell.water = 1; - break; // walkable water - case 4: - cell.walkable = 1; - cell.shootable = 1; - cell.water = 0; - break; // ??? - case 5: - cell.walkable = 0; - cell.shootable = 1; - cell.water = 0; - break; // gap (snipable) - case 6: - cell.walkable = 1; - cell.shootable = 1; - cell.water = 0; - break; // ??? - default: - ShowWarning("map_gat2cell: unrecognized gat type '%d'\n", gat); - break; - } - - return cell; + struct mapcell cell; + + memset(&cell,0,sizeof(struct mapcell)); + + switch( gat ) { + case 0: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // walkable ground + case 1: cell.walkable = 0; cell.shootable = 0; cell.water = 0; break; // non-walkable ground + case 2: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // ??? + case 3: cell.walkable = 1; cell.shootable = 1; cell.water = 1; break; // walkable water + case 4: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // ??? + case 5: cell.walkable = 0; cell.shootable = 1; cell.water = 0; break; // gap (snipable) + case 6: cell.walkable = 1; cell.shootable = 1; cell.water = 0; break; // ??? + default: + ShowWarning("map_gat2cell: unrecognized gat type '%d'\n", gat); + break; + } + + return cell; } static int map_cell2gat(struct mapcell cell) { - if (cell.walkable == 1 && cell.shootable == 1 && cell.water == 0) return 0; - if (cell.walkable == 0 && cell.shootable == 0 && cell.water == 0) return 1; - if (cell.walkable == 1 && cell.shootable == 1 && cell.water == 1) return 3; - if (cell.walkable == 0 && cell.shootable == 1 && cell.water == 0) return 5; + if( cell.walkable == 1 && cell.shootable == 1 && cell.water == 0 ) return 0; + if( cell.walkable == 0 && cell.shootable == 0 && cell.water == 0 ) return 1; + if( cell.walkable == 1 && cell.shootable == 1 && cell.water == 1 ) return 3; + if( cell.walkable == 0 && cell.shootable == 1 && cell.water == 0 ) return 5; - ShowWarning("map_cell2gat: cell has no matching gat type\n"); - return 1; // default to 'wall' + ShowWarning("map_cell2gat: cell has no matching gat type\n"); + return 1; // default to 'wall' } /*========================================== @@ -2443,78 +2453,79 @@ static int map_cell2gat(struct mapcell cell) *------------------------------------------*/ int map_getcell(int m,int x,int y,cell_chk cellchk) { - return (m < 0 || m >= MAX_MAP_PER_SERVER) ? 0 : map_getcellp(&map[m],x,y,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_chk cellchk) +int map_getcellp(struct map_data* m,int x,int y,cell_chk cellchk) { - struct mapcell cell; + struct mapcell cell; - nullpo_ret(m); + nullpo_ret(m); - //NOTE: this intentionally overrides the last row and column - if (x<0 || x>=m->xs-1 || y<0 || y>=m->ys-1) - return(cellchk == CELL_CHKNOPASS); + //NOTE: this intentionally overrides the last row and column + if(x<0 || x>=m->xs-1 || y<0 || y>=m->ys-1) + return( cellchk == CELL_CHKNOPASS ); - cell = m->cell[x + y*m->xs]; + cell = m->cell[x + y*m->xs]; - switch (cellchk) { - // gat type retrieval - case CELL_GETTYPE: - return map_cell2gat(cell); + switch(cellchk) + { + // gat type retrieval + case CELL_GETTYPE: + return map_cell2gat(cell); - // base gat type checks - case CELL_CHKWALL: - return (!cell.walkable && !cell.shootable); + // base gat type checks + case CELL_CHKWALL: + return (!cell.walkable && !cell.shootable); - case CELL_CHKWATER: - return (cell.water); + case CELL_CHKWATER: + return (cell.water); - case CELL_CHKCLIFF: - return (!cell.walkable && cell.shootable); + case CELL_CHKCLIFF: + return (!cell.walkable && cell.shootable); - // base cell type checks - case CELL_CHKNPC: - return (cell.npc); - case CELL_CHKBASILICA: - return (cell.basilica); - case CELL_CHKLANDPROTECTOR: - return (cell.landprotector); - case CELL_CHKNOVENDING: - return (cell.novending); - case CELL_CHKNOCHAT: - return (cell.nochat); - case CELL_CHKMAELSTROM: - return (cell.maelstrom); - case CELL_CHKICEWALL: - return (cell.icewall); + // base cell type checks + case CELL_CHKNPC: + return (cell.npc); + case CELL_CHKBASILICA: + return (cell.basilica); + case CELL_CHKLANDPROTECTOR: + return (cell.landprotector); + case CELL_CHKNOVENDING: + return (cell.novending); + case CELL_CHKNOCHAT: + return (cell.nochat); + case CELL_CHKMAELSTROM: + return (cell.maelstrom); + case CELL_CHKICEWALL: + return (cell.icewall); - // special checks - case CELL_CHKPASS: + // special checks + case CELL_CHKPASS: #ifdef CELL_NOSTACK - if (cell.cell_bl >= battle_config.cell_stack_limit) return 0; + if (cell.cell_bl >= battle_config.cell_stack_limit) return 0; #endif - case CELL_CHKREACH: - return (cell.walkable); + case CELL_CHKREACH: + return (cell.walkable); - case CELL_CHKNOPASS: + case CELL_CHKNOPASS: #ifdef CELL_NOSTACK - if (cell.cell_bl >= battle_config.cell_stack_limit) return 1; + if (cell.cell_bl >= battle_config.cell_stack_limit) return 1; #endif - case CELL_CHKNOREACH: - return (!cell.walkable); + case CELL_CHKNOREACH: + return (!cell.walkable); - case CELL_CHKSTACK: + case CELL_CHKSTACK: #ifdef CELL_NOSTACK - return (cell.cell_bl >= battle_config.cell_stack_limit); + return (cell.cell_bl >= battle_config.cell_stack_limit); #else - return 0; + return 0; #endif - default: - return 0; - } + default: + return 0; + } } /*========================================== @@ -2524,174 +2535,158 @@ int map_getcellp(struct map_data *m,int x,int y,cell_chk cellchk) *------------------------------------------*/ void map_setcell(int m, int x, int y, cell_t cell, bool flag) { - int j; - - if (m < 0 || m >= map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys) - return; - - j = x + y*map[m].xs; - - switch (cell) { - case CELL_WALKABLE: - map[m].cell[j].walkable = flag; - break; - case CELL_SHOOTABLE: - map[m].cell[j].shootable = flag; - break; - case CELL_WATER: - map[m].cell[j].water = flag; - break; - - case CELL_NPC: - map[m].cell[j].npc = flag; - break; - case CELL_BASILICA: - map[m].cell[j].basilica = flag; - break; - case CELL_LANDPROTECTOR: - map[m].cell[j].landprotector = flag; - break; - case CELL_NOVENDING: - map[m].cell[j].novending = flag; - break; - case CELL_NOCHAT: - map[m].cell[j].nochat = flag; - break; - case CELL_MAELSTROM: - map[m].cell[j].maelstrom = flag; - break; - case CELL_ICEWALL: - map[m].cell[j].icewall = flag; - break; - default: - ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell); - break; - } + int j; + + if( m < 0 || m >= map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) + return; + + j = x + y*map[m].xs; + + switch( cell ) { + case CELL_WALKABLE: map[m].cell[j].walkable = flag; break; + case CELL_SHOOTABLE: map[m].cell[j].shootable = flag; break; + case CELL_WATER: map[m].cell[j].water = flag; break; + + case CELL_NPC: map[m].cell[j].npc = flag; break; + case CELL_BASILICA: map[m].cell[j].basilica = flag; break; + case CELL_LANDPROTECTOR: map[m].cell[j].landprotector = flag; break; + case CELL_NOVENDING: map[m].cell[j].novending = flag; break; + case CELL_NOCHAT: map[m].cell[j].nochat = flag; break; + case CELL_MAELSTROM: map[m].cell[j].maelstrom = flag; break; + case CELL_ICEWALL: map[m].cell[j].icewall = flag; break; + default: + ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell); + break; + } } void map_setgatcell(int m, int x, int y, int gat) { - int j; - struct mapcell cell; + int j; + struct mapcell cell; - if (m < 0 || m >= map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys) - return; + if( m < 0 || m >= map_num || x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) + return; - j = x + y*map[m].xs; + j = x + y*map[m].xs; - cell = map_gat2cell(gat); - map[m].cell[j].walkable = cell.walkable; - map[m].cell[j].shootable = cell.shootable; - map[m].cell[j].water = cell.water; + cell = map_gat2cell(gat); + map[m].cell[j].walkable = cell.walkable; + map[m].cell[j].shootable = cell.shootable; + map[m].cell[j].water = cell.water; } /*========================================== * Invisible Walls *------------------------------------------*/ -static DBMap *iwall_db; +static DBMap* iwall_db; void map_iwall_nextxy(int x, int y, int dir, int pos, int *x1, int *y1) { - if (dir == 0 || dir == 4) - *x1 = x; // Keep X - else if (dir > 0 && dir < 4) - *x1 = x - pos; // Going left - else - *x1 = x + pos; // Going right + if( dir == 0 || dir == 4 ) + *x1 = x; // Keep X + else if( dir > 0 && dir < 4 ) + *x1 = x - pos; // Going left + else + *x1 = x + pos; // Going right - if (dir == 2 || dir == 6) - *y1 = y; - else if (dir > 2 && dir < 6) - *y1 = y - pos; - else - *y1 = y + pos; + if( dir == 2 || dir == 6 ) + *y1 = y; + else if( dir > 2 && dir < 6 ) + *y1 = y - pos; + else + *y1 = y + pos; } -bool map_iwall_set(int m, int x, int y, int size, int dir, bool shootable, const char *wall_name) +bool map_iwall_set(int m, int x, int y, int size, int dir, bool shootable, const char* wall_name) { - struct iwall_data *iwall; - int i, x1 = 0, y1 = 0; + struct iwall_data *iwall; + int i, x1 = 0, y1 = 0; - if (size < 1 || !wall_name) - return false; + if( size < 1 || !wall_name ) + return false; - if ((iwall = (struct iwall_data *)strdb_get(iwall_db, wall_name)) != NULL) - return false; // Already Exists + if( (iwall = (struct iwall_data *)strdb_get(iwall_db, wall_name)) != NULL ) + return false; // Already Exists - if (map_getcell(m, x, y, CELL_CHKNOREACH)) - return false; // Starting cell problem + if( map_getcell(m, x, y, CELL_CHKNOREACH) ) + return false; // Starting cell problem - CREATE(iwall, struct iwall_data, 1); - iwall->m = m; - iwall->x = x; - iwall->y = y; - iwall->size = size; - iwall->dir = dir; - iwall->shootable = shootable; - safestrncpy(iwall->wall_name, wall_name, sizeof(iwall->wall_name)); + CREATE(iwall, struct iwall_data, 1); + iwall->m = m; + iwall->x = x; + iwall->y = y; + iwall->size = size; + iwall->dir = dir; + iwall->shootable = shootable; + safestrncpy(iwall->wall_name, wall_name, sizeof(iwall->wall_name)); - for (i = 0; i < size; i++) { - map_iwall_nextxy(x, y, dir, i, &x1, &y1); + for( i = 0; i < size; i++ ) + { + map_iwall_nextxy(x, y, dir, i, &x1, &y1); - if (map_getcell(m, x1, y1, CELL_CHKNOREACH)) - break; // Collision + if( map_getcell(m, x1, y1, CELL_CHKNOREACH) ) + break; // Collision - map_setcell(m, x1, y1, CELL_WALKABLE, false); - map_setcell(m, x1, y1, CELL_SHOOTABLE, shootable); + map_setcell(m, x1, y1, CELL_WALKABLE, false); + map_setcell(m, x1, y1, CELL_SHOOTABLE, shootable); - clif_changemapcell(0, m, x1, y1, map_getcell(m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); - } + clif_changemapcell(0, m, x1, y1, map_getcell(m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); + } - iwall->size = i; + iwall->size = i; - strdb_put(iwall_db, iwall->wall_name, iwall); - map[m].iwall_num++; + strdb_put(iwall_db, iwall->wall_name, iwall); + map[m].iwall_num++; - return true; + return true; } void map_iwall_get(struct map_session_data *sd) { - struct iwall_data *iwall; - DBIterator *iter; - int x1, y1; - int i; + struct iwall_data *iwall; + DBIterator* iter; + int x1, y1; + int i; - if (map[sd->bl.m].iwall_num < 1) - return; + if( map[sd->bl.m].iwall_num < 1 ) + return; - iter = db_iterator(iwall_db); - for (iwall = dbi_first(iter); dbi_exists(iter); iwall = dbi_next(iter)) { - if (iwall->m != sd->bl.m) - continue; + iter = db_iterator(iwall_db); + for( iwall = dbi_first(iter); dbi_exists(iter); iwall = dbi_next(iter) ) + { + if( iwall->m != sd->bl.m ) + continue; - for (i = 0; i < iwall->size; i++) { - map_iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1); - clif_changemapcell(sd->fd, iwall->m, x1, y1, map_getcell(iwall->m, x1, y1, CELL_GETTYPE), SELF); - } - } - dbi_destroy(iter); + for( i = 0; i < iwall->size; i++ ) + { + map_iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1); + clif_changemapcell(sd->fd, iwall->m, x1, y1, map_getcell(iwall->m, x1, y1, CELL_GETTYPE), SELF); + } + } + dbi_destroy(iter); } void map_iwall_remove(const char *wall_name) { - struct iwall_data *iwall; - int i, x1, y1; + struct iwall_data *iwall; + int i, x1, y1; - if ((iwall = (struct iwall_data *)strdb_get(iwall_db, wall_name)) == NULL) - return; // Nothing to do + if( (iwall = (struct iwall_data *)strdb_get(iwall_db, wall_name)) == NULL ) + return; // Nothing to do - for (i = 0; i < iwall->size; i++) { - map_iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1); + for( i = 0; i < iwall->size; i++ ) + { + map_iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1); - map_setcell(iwall->m, x1, y1, CELL_SHOOTABLE, true); - map_setcell(iwall->m, x1, y1, CELL_WALKABLE, true); + map_setcell(iwall->m, x1, y1, CELL_SHOOTABLE, true); + map_setcell(iwall->m, x1, y1, CELL_WALKABLE, true); - clif_changemapcell(0, iwall->m, x1, y1, map_getcell(iwall->m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); - } + clif_changemapcell(0, iwall->m, x1, y1, map_getcell(iwall->m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); + } - map[iwall->m].iwall_num--; - strdb_remove(iwall_db, iwall->wall_name); + map[iwall->m].iwall_num--; + strdb_remove(iwall_db, iwall->wall_name); } /** @@ -2699,12 +2694,12 @@ void map_iwall_remove(const char *wall_name) */ static DBData create_map_data_other_server(DBKey key, va_list args) { - struct map_data_other_server *mdos; - unsigned short mapindex = (unsigned short)key.ui; - mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server)); - mdos->index = mapindex; - memcpy(mdos->name, mapindex_id2name(mapindex), MAP_NAME_LENGTH); - return db_ptr2data(mdos); + struct map_data_other_server *mdos; + unsigned short mapindex = (unsigned short)key.ui; + mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server)); + mdos->index = mapindex; + memcpy(mdos->name, mapindex_id2name(mapindex), MAP_NAME_LENGTH); + return db_ptr2data(mdos); } /*========================================== @@ -2712,20 +2707,20 @@ static DBData create_map_data_other_server(DBKey key, va_list args) *------------------------------------------*/ int map_setipport(unsigned short mapindex, uint32 ip, uint16 port) { - struct map_data_other_server *mdos=NULL; + struct map_data_other_server *mdos=NULL; - mdos= uidb_ensure(map_db,(unsigned int)mapindex, create_map_data_other_server); + mdos= uidb_ensure(map_db,(unsigned int)mapindex, create_map_data_other_server); - if (mdos->cell) //Local map,Do nothing. Give priority to our own local maps over ones from another server. [Skotlex] - return 0; - if (ip == clif_getip() && port == clif_getport()) { - //That's odd, we received info that we are the ones with this map, but... we don't have it. - ShowFatalError("map_setipport : received info that this map-server SHOULD have map '%s', but it is not loaded.\n",mapindex_id2name(mapindex)); - exit(EXIT_FAILURE); - } - mdos->ip = ip; - mdos->port = port; - return 1; + if(mdos->cell) //Local map,Do nothing. Give priority to our own local maps over ones from another server. [Skotlex] + return 0; + if(ip == clif_getip() && port == clif_getport()) { + //That's odd, we received info that we are the ones with this map, but... we don't have it. + ShowFatalError("map_setipport : received info that this map-server SHOULD have map '%s', but it is not loaded.\n",mapindex_id2name(mapindex)); + exit(EXIT_FAILURE); + } + mdos->ip = ip; + mdos->port = port; + return 1; } /** @@ -2734,18 +2729,18 @@ int map_setipport(unsigned short mapindex, uint32 ip, uint16 port) */ int map_eraseallipport_sub(DBKey key, DBData *data, va_list va) { - struct map_data_other_server *mdos = db_data2ptr(data); - if (mdos->cell == NULL) { - db_remove(map_db,key); - aFree(mdos); - } - return 0; + struct map_data_other_server *mdos = db_data2ptr(data); + if(mdos->cell == NULL) { + db_remove(map_db,key); + aFree(mdos); + } + return 0; } int map_eraseallipport(void) { - map_db->foreach(map_db,map_eraseallipport_sub); - return 1; + map_db->foreach(map_db,map_eraseallipport_sub); + return 1; } /*========================================== @@ -2753,18 +2748,18 @@ int map_eraseallipport(void) *------------------------------------------*/ int map_eraseipport(unsigned short mapindex, uint32 ip, uint16 port) { - struct map_data_other_server *mdos; + struct map_data_other_server *mdos; - mdos = (struct map_data_other_server *)uidb_get(map_db,(unsigned int)mapindex); - if (!mdos || mdos->cell) //Map either does not exists or is a local map. - return 0; + mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)mapindex); + if(!mdos || mdos->cell) //Map either does not exists or is a local map. + return 0; - if (mdos->ip==ip && mdos->port == port) { - uidb_remove(map_db,(unsigned int)mapindex); - aFree(mdos); - return 1; - } - return 0; + if(mdos->ip==ip && mdos->port == port) { + uidb_remove(map_db,(unsigned int)mapindex); + aFree(mdos); + return 1; + } + return 0; } /*========================================== @@ -2772,30 +2767,30 @@ int map_eraseipport(unsigned short mapindex, uint32 ip, uint16 port) *------------------------------------------*/ static char *map_init_mapcache(FILE *fp) { - size_t size = 0; - char *buffer; + size_t size = 0; + char *buffer; - // No file open? Return.. - nullpo_ret(fp); + // No file open? Return.. + nullpo_ret(fp); - // Get file size - fseek(fp, 0, SEEK_END); - size = ftell(fp); - fseek(fp, 0, SEEK_SET); + // Get file size + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); - // Allocate enough space - CREATE(buffer, char, size); + // Allocate enough space + CREATE(buffer, char, size); - // No memory? Return.. - nullpo_ret(buffer); + // No memory? Return.. + nullpo_ret(buffer); - // Read file into buffer.. - if (fread(buffer, sizeof(char), size, fp) != size) { - ShowError("map_init_mapcache: Could not read entire mapcache file\n"); - return NULL; - } + // Read file into buffer.. + if(fread(buffer, sizeof(char), size, fp) != size) { + ShowError("map_init_mapcache: Could not read entire mapcache file\n"); + return NULL; + } - return buffer; + return buffer; } /*========================================== @@ -2804,116 +2799,119 @@ static char *map_init_mapcache(FILE *fp) *==========================================*/ int map_readfromcache(struct map_data *m, char *buffer, char *decode_buffer) { - int i; - struct map_cache_main_header *header = (struct map_cache_main_header *)buffer; - struct map_cache_map_info *info = NULL; - char *p = buffer + sizeof(struct map_cache_main_header); + int i; + struct map_cache_main_header *header = (struct map_cache_main_header *)buffer; + struct map_cache_map_info *info = NULL; + char *p = buffer + sizeof(struct map_cache_main_header); - for (i = 0; i < header->map_count; i++) { - info = (struct map_cache_map_info *)p; + for(i = 0; i < header->map_count; i++) { + info = (struct map_cache_map_info *)p; - if (strcmp(m->name, info->name) == 0) - break; // Map found + if( strcmp(m->name, info->name) == 0 ) + break; // Map found - // Jump to next entry.. - p += sizeof(struct map_cache_map_info) + info->len; - } + // Jump to next entry.. + p += sizeof(struct map_cache_map_info) + info->len; + } - if (info && i < header->map_count) { - unsigned long size, xy; + if( info && i < header->map_count ) { + unsigned long size, xy; - if (info->xs <= 0 || info->ys <= 0) - return 0;// Invalid + if( info->xs <= 0 || info->ys <= 0 ) + return 0;// Invalid - m->xs = info->xs; - m->ys = info->ys; - size = (unsigned long)info->xs*(unsigned long)info->ys; + m->xs = info->xs; + m->ys = info->ys; + size = (unsigned long)info->xs*(unsigned long)info->ys; - if (size > MAX_MAP_SIZE) { - ShowWarning("map_readfromcache: %s exceeded MAX_MAP_SIZE of %d\n", info->name, MAX_MAP_SIZE); - return 0; // Say not found to remove it from list.. [Shinryo] - } + if(size > MAX_MAP_SIZE) { + ShowWarning("map_readfromcache: %s exceeded MAX_MAP_SIZE of %d\n", info->name, MAX_MAP_SIZE); + return 0; // Say not found to remove it from list.. [Shinryo] + } - // TO-DO: Maybe handle the scenario, if the decoded buffer isn't the same size as expected? [Shinryo] - decode_zip(decode_buffer, &size, p+sizeof(struct map_cache_map_info), info->len); + // TO-DO: Maybe handle the scenario, if the decoded buffer isn't the same size as expected? [Shinryo] + decode_zip(decode_buffer, &size, p+sizeof(struct map_cache_map_info), info->len); - CREATE(m->cell, struct mapcell, size); + CREATE(m->cell, struct mapcell, size); - for (xy = 0; xy < size; ++xy) - m->cell[xy] = map_gat2cell(decode_buffer[xy]); + for( xy = 0; xy < size; ++xy ) + m->cell[xy] = map_gat2cell(decode_buffer[xy]); - return 1; - } + return 1; + } - return 0; // Not found + return 0; // Not found } -int map_addmap(char *mapname) +int map_addmap(char* mapname) { - if (strcmpi(mapname,"clear")==0) { - map_num = 0; - instance_start = 0; - return 0; - } + if( strcmpi(mapname,"clear")==0 ) + { + map_num = 0; + instance_start = 0; + return 0; + } - if (map_num >= MAX_MAP_PER_SERVER - 1) { - ShowError("Could not add map '"CL_WHITE"%s"CL_RESET"', the limit of maps has been reached.\n",mapname); - return 1; - } + if( map_num >= MAX_MAP_PER_SERVER - 1 ) + { + ShowError("Could not add map '"CL_WHITE"%s"CL_RESET"', the limit of maps has been reached.\n",mapname); + return 1; + } - mapindex_getmapname(mapname, map[map_num].name); - map_num++; - return 0; + mapindex_getmapname(mapname, map[map_num].name); + map_num++; + return 0; } static void map_delmapid(int id) { - ShowNotice("Removing map [ %s ] from maplist"CL_CLL"\n",map[id].name); - memmove(map+id, map+id+1, sizeof(map[0])*(map_num-id-1)); - map_num--; + ShowNotice("Removing map [ %s ] from maplist"CL_CLL"\n",map[id].name); + memmove(map+id, map+id+1, sizeof(map[0])*(map_num-id-1)); + map_num--; } -int map_delmap(char *mapname) +int map_delmap(char* mapname) { - int i; - char map_name[MAP_NAME_LENGTH]; + int i; + char map_name[MAP_NAME_LENGTH]; - if (strcmpi(mapname, "all") == 0) { - map_num = 0; - return 0; - } + if (strcmpi(mapname, "all") == 0) { + map_num = 0; + return 0; + } - mapindex_getmapname(mapname, map_name); - for (i = 0; i < map_num; i++) { - if (strcmp(map[i].name, map_name) == 0) { - map_delmapid(i); - return 1; - } - } - return 0; + mapindex_getmapname(mapname, map_name); + for(i = 0; i < map_num; i++) { + if (strcmp(map[i].name, map_name) == 0) { + map_delmapid(i); + return 1; + } + } + return 0; } /// Initializes map flags and adjusts them depending on configuration. void map_flags_init(void) { - int i; + int i; - for (i = 0; i < map_num; i++) { - // mapflags - memset(&map[i].flag, 0, sizeof(map[i].flag)); + for( i = 0; i < map_num; i++ ) + { + // mapflags + memset(&map[i].flag, 0, sizeof(map[i].flag)); - // additional mapflag data - map[i].zone = 0; // restricted mapflag zone - map[i].nocommand = 0; // nocommand mapflag level - map[i].bexp = 100; // per map base exp multiplicator - map[i].jexp = 100; // per map job exp multiplicator - memset(map[i].drop_list, 0, sizeof(map[i].drop_list)); // pvp nightmare drop list + // additional mapflag data + map[i].zone = 0; // restricted mapflag zone + map[i].nocommand = 0; // nocommand mapflag level + map[i].bexp = 100; // per map base exp multiplicator + map[i].jexp = 100; // per map job exp multiplicator + memset(map[i].drop_list, 0, sizeof(map[i].drop_list)); // pvp nightmare drop list - // adjustments - if (battle_config.pk_mode) - map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris] - } + // adjustments + if( battle_config.pk_mode ) + map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris] + } } #define NO_WATER 1000000 @@ -2924,69 +2922,70 @@ void map_flags_init(void) * Assumed path for file is data/mapname.rsw * Credits to LittleWolf */ -int map_waterheight(char *mapname) +int map_waterheight(char* mapname) { - char fn[256]; - char *rsw, *found; + char fn[256]; + char *rsw, *found; - //Look up for the rsw - sprintf(fn, "data\\%s.rsw", mapname); + //Look up for the rsw + sprintf(fn, "data\\%s.rsw", mapname); - found = grfio_find_file(fn); - if (found) strcpy(fn, found); // replace with real name + found = grfio_find_file(fn); + if (found) strcpy(fn, found); // replace with real name - // read & convert fn - rsw = (char *) grfio_read(fn); - if (rsw) { - //Load water height from file - int wh = (int) *(float *)(rsw+166); - aFree(rsw); - return wh; - } - ShowWarning("Failed to find water level for (%s)\n", mapname, fn); - return NO_WATER; + // read & convert fn + rsw = (char *) grfio_read (fn); + if (rsw) + { //Load water height from file + int wh = (int) *(float*)(rsw+166); + aFree(rsw); + return wh; + } + ShowWarning("Failed to find water level for (%s)\n", mapname, fn); + return NO_WATER; } /*================================== * .GAT format *----------------------------------*/ -int map_readgat(struct map_data *m) +int map_readgat (struct map_data* m) { - char filename[256]; - uint8 *gat; - int water_height; - size_t xy, off, num_cells; + char filename[256]; + uint8* gat; + int water_height; + size_t xy, off, num_cells; - sprintf(filename, "data\\%s.gat", m->name); + sprintf(filename, "data\\%s.gat", m->name); - gat = (uint8 *) grfio_read(filename); - if (gat == NULL) - return 0; + gat = (uint8 *) grfio_read(filename); + if (gat == NULL) + return 0; - m->xs = *(int32 *)(gat+6); - m->ys = *(int32 *)(gat+10); - num_cells = m->xs * m->ys; - CREATE(m->cell, struct mapcell, num_cells); + m->xs = *(int32*)(gat+6); + m->ys = *(int32*)(gat+10); + num_cells = m->xs * m->ys; + CREATE(m->cell, struct mapcell, num_cells); - water_height = map_waterheight(m->name); + water_height = map_waterheight(m->name); - // Set cell properties - off = 14; - for (xy = 0; xy < num_cells; ++xy) { - // read cell data - float height = *(float *)(gat + off); - uint32 type = *(uint32 *)(gat + off + 16); - off += 20; + // Set cell properties + off = 14; + for( xy = 0; xy < num_cells; ++xy ) + { + // read cell data + float height = *(float*)( gat + off ); + uint32 type = *(uint32*)( gat + off + 16 ); + off += 20; - if (type == 0 && water_height != NO_WATER && height > water_height) - type = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water) + if( type == 0 && water_height != NO_WATER && height > water_height ) + type = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water) - m->cell[xy] = map_gat2cell(type); - } + m->cell[xy] = map_gat2cell(type); + } - aFree(gat); + aFree(gat); - return 1; + return 1; } /*====================================== @@ -2994,109 +2993,110 @@ int map_readgat(struct map_data *m) *--------------------------------------*/ void map_addmap2db(struct map_data *m) { - uidb_put(map_db, (unsigned int)m->index, m); + uidb_put(map_db, (unsigned int)m->index, m); } void map_removemapdb(struct map_data *m) { - uidb_remove(map_db, (unsigned int)m->index); + uidb_remove(map_db, (unsigned int)m->index); } /*====================================== * Initiate maps loading stage *--------------------------------------*/ -int map_readallmaps(void) -{ - int i; - FILE *fp=NULL; - int maps_removed = 0; - char *map_cache_buffer = NULL; // Has the uncompressed gat data of all maps, so just one allocation has to be made - char map_cache_decode_buffer[MAX_MAP_SIZE]; - - if (enable_grf) - ShowStatus("Loading maps (using GRF files)...\n"); - else { - char mapcachefilepath[254]; - sprintf(mapcachefilepath,"%s/%s%s",db_path,DBPATH,"map_cache.dat"); - ShowStatus("Loading maps (using %s as map cache)...\n", mapcachefilepath); - if ((fp = fopen(mapcachefilepath, "rb")) == NULL) { - ShowFatalError("Unable to open map cache file "CL_WHITE"%s"CL_RESET"\n", mapcachefilepath); - exit(EXIT_FAILURE); //No use launching server if maps can't be read. - } - - // Init mapcache data.. [Shinryo] - map_cache_buffer = map_init_mapcache(fp); - if (!map_cache_buffer) { - ShowFatalError("Failed to initialize mapcache data (%s)..\n", mapcachefilepath); - exit(EXIT_FAILURE); - } - } - - for (i = 0; i < map_num; i++) { - size_t size; - - // show progress - if (enable_grf) - ShowStatus("Loading maps [%i/%i]: %s"CL_CLL"\r", i, map_num, map[i].name); - - // try to load the map - if (! - (enable_grf? - map_readgat(&map[i]) - :map_readfromcache(&map[i], map_cache_buffer, map_cache_decode_buffer)) - ) { - map_delmapid(i); - maps_removed++; - i--; - continue; - } - - map[i].index = mapindex_name2id(map[i].name); - - if (uidb_get(map_db,(unsigned int)map[i].index) != NULL) { - ShowWarning("Map %s already loaded!"CL_CLL"\n", map[i].name); - if (map[i].cell) { - aFree(map[i].cell); - map[i].cell = NULL; - } - map_delmapid(i); - maps_removed++; - i--; - continue; - } - - map_addmap2db(&map[i]); - - map[i].m = i; - memset(map[i].moblist, 0, sizeof(map[i].moblist)); //Initialize moblist [Skotlex] - map[i].mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex] - - map[i].bxs = (map[i].xs + BLOCK_SIZE - 1) / BLOCK_SIZE; - map[i].bys = (map[i].ys + BLOCK_SIZE - 1) / BLOCK_SIZE; - - size = map[i].bxs * map[i].bys * sizeof(struct block_list *); - map[i].block = (struct block_list **)aCalloc(size, 1); - map[i].block_mob = (struct block_list **)aCalloc(size, 1); - } - - // intialization and configuration-dependent adjustments of mapflags - map_flags_init(); - - if (!enable_grf) { - fclose(fp); - - // The cache isn't needed anymore, so free it.. [Shinryo] - aFree(map_cache_buffer); - } - - // finished map loading - ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps."CL_CLL"\n",map_num); - instance_start = map_num; // Next Map Index will be instances - - if (maps_removed) - ShowNotice("Maps removed: '"CL_WHITE"%d"CL_RESET"'\n",maps_removed); - - return 0; +int map_readallmaps (void) +{ + int i; + FILE* fp=NULL; + int maps_removed = 0; + char *map_cache_buffer = NULL; // Has the uncompressed gat data of all maps, so just one allocation has to be made + char map_cache_decode_buffer[MAX_MAP_SIZE]; + + if( enable_grf ) + ShowStatus("Loading maps (using GRF files)...\n"); + else { + char mapcachefilepath[254]; + sprintf(mapcachefilepath,"%s/%s%s",db_path,DBPATH,"map_cache.dat"); + ShowStatus("Loading maps (using %s as map cache)...\n", mapcachefilepath); + if( (fp = fopen(mapcachefilepath, "rb")) == NULL ) { + ShowFatalError("Unable to open map cache file "CL_WHITE"%s"CL_RESET"\n", mapcachefilepath); + exit(EXIT_FAILURE); //No use launching server if maps can't be read. + } + + // Init mapcache data.. [Shinryo] + map_cache_buffer = map_init_mapcache(fp); + if(!map_cache_buffer) { + ShowFatalError("Failed to initialize mapcache data (%s)..\n", mapcachefilepath); + exit(EXIT_FAILURE); + } + } + + for(i = 0; i < map_num; i++) { + size_t size; + + // show progress + if(enable_grf) + ShowStatus("Loading maps [%i/%i]: %s"CL_CLL"\r", i, map_num, map[i].name); + + // try to load the map + if( ! + (enable_grf? + map_readgat(&map[i]) + :map_readfromcache(&map[i], map_cache_buffer, map_cache_decode_buffer)) + ) { + map_delmapid(i); + maps_removed++; + i--; + continue; + } + + map[i].index = mapindex_name2id(map[i].name); + + if (uidb_get(map_db,(unsigned int)map[i].index) != NULL) + { + ShowWarning("Map %s already loaded!"CL_CLL"\n", map[i].name); + if (map[i].cell) { + aFree(map[i].cell); + map[i].cell = NULL; + } + map_delmapid(i); + maps_removed++; + i--; + continue; + } + + map_addmap2db(&map[i]); + + map[i].m = i; + memset(map[i].moblist, 0, sizeof(map[i].moblist)); //Initialize moblist [Skotlex] + map[i].mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex] + + map[i].bxs = (map[i].xs + BLOCK_SIZE - 1) / BLOCK_SIZE; + map[i].bys = (map[i].ys + BLOCK_SIZE - 1) / BLOCK_SIZE; + + size = map[i].bxs * map[i].bys * sizeof(struct block_list*); + map[i].block = (struct block_list**)aCalloc(size, 1); + map[i].block_mob = (struct block_list**)aCalloc(size, 1); + } + + // intialization and configuration-dependent adjustments of mapflags + map_flags_init(); + + if( !enable_grf ) { + fclose(fp); + + // The cache isn't needed anymore, so free it.. [Shinryo] + aFree(map_cache_buffer); + } + + // finished map loading + ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps."CL_CLL"\n",map_num); + instance_start = map_num; // Next Map Index will be instances + + if (maps_removed) + ShowNotice("Maps removed: '"CL_WHITE"%d"CL_RESET"'\n",maps_removed); + + return 0; } //////////////////////////////////////////////////////////////////////// @@ -3106,67 +3106,79 @@ static int char_ip_set = 0; /*========================================== * Console Command Parser [Wizputer] *------------------------------------------*/ -int parse_console(const char *buf) -{ - char type[64]; - char command[64]; - char map[64]; - int x = 0; - int y = 0; - int m; - int n; - struct map_session_data sd; - - memset(&sd, 0, sizeof(struct map_session_data)); - strcpy(sd.status.name, "console"); - - if ((n = sscanf(buf, "%63[^:]:%63[^:]:%63s %d %d[^\n]", type, command, map, &x, &y)) < 5) { - if ((n = sscanf(buf, "%63[^:]:%63[^\n]", type, command)) < 2) { - n = sscanf(buf, "%63[^\n]", type); - } - } - - if (n == 5) { - m = map_mapname2mapid(map); - if (m < 0) { - ShowWarning("Console: Unknown map.\n"); - return 0; - } - sd.bl.m = m; - map_search_freecell(&sd.bl, m, &sd.bl.x, &sd.bl.y, -1, -1, 0); - if (x > 0) - sd.bl.x = x; - if (y > 0) - sd.bl.y = y; - } else { - map[0] = '\0'; - if (n < 2) - command[0] = '\0'; - if (n < 1) - type[0] = '\0'; - } - - ShowNotice("Type of command: '%s' || Command: '%s' || Map: '%s' Coords: %d %d\n", type, command, map, x, y); - - if (n == 5 && strcmpi("admin",type) == 0) { - if (!is_atcommand(sd.fd, &sd, command, 0)) - ShowInfo("Console: not atcommand\n"); - } else if (n == 2 && strcmpi("server", type) == 0) { - if (strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0) { - runflag = 0; - } - } else if (strcmpi("help", type) == 0) { - ShowInfo("To use GM commands:\n"); - ShowInfo(" admin:<gm command>:<map of \"gm\"> <x> <y>\n"); - ShowInfo("You can use any GM command that doesn't require the GM.\n"); - ShowInfo("No using @item or @warp however you can use @charwarp\n"); - ShowInfo("The <map of \"gm\"> <x> <y> is for commands that need coords of the GM\n"); - ShowInfo("IE: @spawn\n"); - ShowInfo("To shutdown the server:\n"); - ShowInfo(" server:shutdown\n"); - } - - return 0; +int parse_console(const char* buf) +{ + char type[64]; + char command[64]; + char map[64]; + int x = 0; + int y = 0; + int m; + int n; + struct map_session_data sd; + + memset(&sd, 0, sizeof(struct map_session_data)); + strcpy(sd.status.name, "console"); + + if( ( n = sscanf(buf, "%63[^:]:%63[^:]:%63s %d %d[^\n]", type, command, map, &x, &y) ) < 5 ) + { + if( ( n = sscanf(buf, "%63[^:]:%63[^\n]", type, command) ) < 2 ) + { + n = sscanf(buf, "%63[^\n]", type); + } + } + + if( n == 5 ) + { + m = map_mapname2mapid(map); + if( m < 0 ) + { + ShowWarning("Console: Unknown map.\n"); + return 0; + } + sd.bl.m = m; + map_search_freecell(&sd.bl, m, &sd.bl.x, &sd.bl.y, -1, -1, 0); + if( x > 0 ) + sd.bl.x = x; + if( y > 0 ) + sd.bl.y = y; + } + else + { + map[0] = '\0'; + if( n < 2 ) + command[0] = '\0'; + if( n < 1 ) + type[0] = '\0'; + } + + ShowNotice("Type of command: '%s' || Command: '%s' || Map: '%s' Coords: %d %d\n", type, command, map, x, y); + + if( n == 5 && strcmpi("admin",type) == 0 ) + { + if( !is_atcommand(sd.fd, &sd, command, 0) ) + ShowInfo("Console: not atcommand\n"); + } + else if( n == 2 && strcmpi("server", type) == 0 ) + { + if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ) + { + runflag = 0; + } + } + else if( strcmpi("help", type) == 0 ) + { + ShowInfo("To use GM commands:\n"); + ShowInfo(" admin:<gm command>:<map of \"gm\"> <x> <y>\n"); + ShowInfo("You can use any GM command that doesn't require the GM.\n"); + ShowInfo("No using @item or @warp however you can use @charwarp\n"); + ShowInfo("The <map of \"gm\"> <x> <y> is for commands that need coords of the GM\n"); + ShowInfo("IE: @spawn\n"); + ShowInfo("To shutdown the server:\n"); + ShowInfo(" server:shutdown\n"); + } + + return 0; } /*========================================== @@ -3174,218 +3186,241 @@ int parse_console(const char *buf) *------------------------------------------*/ int map_config_read(char *cfgName) { - char line[1024], w1[1024], w2[1024]; - FILE *fp; - - fp = fopen(cfgName,"r"); - if (fp == NULL) { - ShowError("Map configuration file not found at: %s\n", cfgName); - return 1; - } - - while (fgets(line, sizeof(line), fp)) { - char *ptr; - - if (line[0] == '/' && line[1] == '/') - continue; - if ((ptr = strstr(line, "//")) != NULL) - *ptr = '\n'; //Strip comments - if (sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2) - continue; - - //Strip trailing spaces - ptr = w2 + strlen(w2); - while (--ptr >= w2 && *ptr == ' '); - ptr++; - *ptr = '\0'; - - if (strcmpi(w1,"timestamp_format")==0) - strncpy(timestamp_format, w2, 20); - else if (strcmpi(w1,"stdout_with_ansisequence")==0) - stdout_with_ansisequence = config_switch(w2); - else if (strcmpi(w1,"console_silent")==0) { - msg_silent = atoi(w2); - if (msg_silent) // only bother if its actually enabled - ShowInfo("Console Silent Setting: %d\n", atoi(w2)); - } else if (strcmpi(w1, "userid")==0) - chrif_setuserid(w2); - else if (strcmpi(w1, "passwd") == 0) - chrif_setpasswd(w2); - else if (strcmpi(w1, "char_ip") == 0) - char_ip_set = chrif_setip(w2); - else if (strcmpi(w1, "char_port") == 0) - chrif_setport(atoi(w2)); - else if (strcmpi(w1, "map_ip") == 0) - map_ip_set = clif_setip(w2); - else if (strcmpi(w1, "bind_ip") == 0) - clif_setbindip(w2); - else if (strcmpi(w1, "map_port") == 0) { - clif_setport(atoi(w2)); - map_port = (atoi(w2)); - } else if (strcmpi(w1, "map") == 0) - map_addmap(w2); - else if (strcmpi(w1, "delmap") == 0) - map_delmap(w2); - else if (strcmpi(w1, "npc") == 0) - npc_addsrcfile(w2); - else if (strcmpi(w1, "delnpc") == 0) - npc_delsrcfile(w2); - else if (strcmpi(w1, "autosave_time") == 0) { - autosave_interval = atoi(w2); - if (autosave_interval < 1) //Revert to default saving. - autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; - else - autosave_interval *= 1000; //Pass from sec to ms - } else if (strcmpi(w1, "minsave_time") == 0) { - minsave_interval= atoi(w2); - if (minsave_interval < 1) - minsave_interval = 1; - } else if (strcmpi(w1, "save_settings") == 0) - save_settings = atoi(w2); - else if (strcmpi(w1, "motd_txt") == 0) - strcpy(motd_txt, w2); - else if (strcmpi(w1, "help_txt") == 0) - strcpy(help_txt, w2); - else if (strcmpi(w1, "help2_txt") == 0) - strcpy(help2_txt, w2); - else if (strcmpi(w1, "charhelp_txt") == 0) - strcpy(charhelp_txt, w2); - else if (strcmpi(w1,"db_path") == 0) - strncpy(db_path,w2,255); - else if (strcmpi(w1, "console") == 0) { - console = config_switch(w2); - if (console) - ShowNotice("Console Commands are enabled.\n"); - } else if (strcmpi(w1, "enable_spy") == 0) - enable_spy = config_switch(w2); - else if (strcmpi(w1, "use_grf") == 0) - enable_grf = config_switch(w2); - else if (strcmpi(w1, "console_msg_log") == 0) - console_msg_log = atoi(w2);//[Ind] - else if (strcmpi(w1, "import") == 0) - map_config_read(w2); - else - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); - } - - fclose(fp); - return 0; + char line[1024], w1[1024], w2[1024]; + FILE *fp; + + fp = fopen(cfgName,"r"); + if( fp == NULL ) + { + ShowError("Map configuration file not found at: %s\n", cfgName); + return 1; + } + + while( fgets(line, sizeof(line), fp) ) + { + char* ptr; + + if( line[0] == '/' && line[1] == '/' ) + continue; + if( (ptr = strstr(line, "//")) != NULL ) + *ptr = '\n'; //Strip comments + if( sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2 ) + continue; + + //Strip trailing spaces + ptr = w2 + strlen(w2); + while (--ptr >= w2 && *ptr == ' '); + ptr++; + *ptr = '\0'; + + if(strcmpi(w1,"timestamp_format")==0) + strncpy(timestamp_format, w2, 20); + else if(strcmpi(w1,"stdout_with_ansisequence")==0) + stdout_with_ansisequence = config_switch(w2); + else if(strcmpi(w1,"console_silent")==0) { + msg_silent = atoi(w2); + if( msg_silent ) // only bother if its actually enabled + ShowInfo("Console Silent Setting: %d\n", atoi(w2)); + } else if (strcmpi(w1, "userid")==0) + chrif_setuserid(w2); + else if (strcmpi(w1, "passwd") == 0) + chrif_setpasswd(w2); + else if (strcmpi(w1, "char_ip") == 0) + char_ip_set = chrif_setip(w2); + else if (strcmpi(w1, "char_port") == 0) + chrif_setport(atoi(w2)); + else if (strcmpi(w1, "map_ip") == 0) + map_ip_set = clif_setip(w2); + else if (strcmpi(w1, "bind_ip") == 0) + clif_setbindip(w2); + else if (strcmpi(w1, "map_port") == 0) { + clif_setport(atoi(w2)); + map_port = (atoi(w2)); + } else if (strcmpi(w1, "map") == 0) + map_addmap(w2); + else if (strcmpi(w1, "delmap") == 0) + map_delmap(w2); + else if (strcmpi(w1, "npc") == 0) + npc_addsrcfile(w2); + else if (strcmpi(w1, "delnpc") == 0) + npc_delsrcfile(w2); + else if (strcmpi(w1, "autosave_time") == 0) { + autosave_interval = atoi(w2); + if (autosave_interval < 1) //Revert to default saving. + autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; + else + autosave_interval *= 1000; //Pass from sec to ms + } else if (strcmpi(w1, "minsave_time") == 0) { + minsave_interval= atoi(w2); + if (minsave_interval < 1) + minsave_interval = 1; + } else if (strcmpi(w1, "save_settings") == 0) + save_settings = atoi(w2); + else if (strcmpi(w1, "motd_txt") == 0) + strcpy(motd_txt, w2); + else if (strcmpi(w1, "help_txt") == 0) + strcpy(help_txt, w2); + else if (strcmpi(w1, "help2_txt") == 0) + strcpy(help2_txt, w2); + else if (strcmpi(w1, "charhelp_txt") == 0) + strcpy(charhelp_txt, w2); + else if(strcmpi(w1,"db_path") == 0) + strncpy(db_path,w2,255); + else if (strcmpi(w1, "console") == 0) { + console = config_switch(w2); + if (console) + ShowNotice("Console Commands are enabled.\n"); + } else if (strcmpi(w1, "enable_spy") == 0) + enable_spy = config_switch(w2); + else if (strcmpi(w1, "use_grf") == 0) + enable_grf = config_switch(w2); + else if (strcmpi(w1, "console_msg_log") == 0) + console_msg_log = atoi(w2);//[Ind] + else if (strcmpi(w1, "import") == 0) + map_config_read(w2); + else + ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); + } + + fclose(fp); + return 0; } void map_reloadnpc_sub(char *cfgName) { - char line[1024], w1[1024], w2[1024]; - FILE *fp; + char line[1024], w1[1024], w2[1024]; + FILE *fp; - fp = fopen(cfgName,"r"); - if (fp == NULL) { - ShowError("Map configuration file not found at: %s\n", cfgName); - return; - } + fp = fopen(cfgName,"r"); + if( fp == NULL ) + { + ShowError("Map configuration file not found at: %s\n", cfgName); + return; + } - while (fgets(line, sizeof(line), fp)) { - char *ptr; + while( fgets(line, sizeof(line), fp) ) + { + char* ptr; - if (line[0] == '/' && line[1] == '/') - continue; - if ((ptr = strstr(line, "//")) != NULL) - *ptr = '\n'; //Strip comments - if (sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2) - continue; + if( line[0] == '/' && line[1] == '/' ) + continue; + if( (ptr = strstr(line, "//")) != NULL ) + *ptr = '\n'; //Strip comments + if( sscanf(line, "%[^:]: %[^\t\r\n]", w1, w2) < 2 ) + continue; - //Strip trailing spaces - ptr = w2 + strlen(w2); - while (--ptr >= w2 && *ptr == ' '); - ptr++; - *ptr = '\0'; + //Strip trailing spaces + ptr = w2 + strlen(w2); + while (--ptr >= w2 && *ptr == ' '); + ptr++; + *ptr = '\0'; - if (strcmpi(w1, "npc") == 0) - npc_addsrcfile(w2); - else if (strcmpi(w1, "import") == 0) - map_reloadnpc_sub(w2); - else - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); - } + if (strcmpi(w1, "npc") == 0) + npc_addsrcfile(w2); + else if (strcmpi(w1, "import") == 0) + map_reloadnpc_sub(w2); + else + ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); + } - fclose(fp); + fclose(fp); } void map_reloadnpc(bool clear) { - if (clear) - npc_addsrcfile("clear"); // this will clear the current script list + if (clear) + npc_addsrcfile("clear"); // this will clear the current script list #ifdef RENEWAL - map_reloadnpc_sub("npc/re/scripts_main.conf"); + map_reloadnpc_sub("npc/re/scripts_main.conf"); #else - map_reloadnpc_sub("npc/pre-re/scripts_main.conf"); + map_reloadnpc_sub("npc/pre-re/scripts_main.conf"); #endif } int inter_config_read(char *cfgName) { - char line[1024],w1[1024],w2[1024]; - FILE *fp; - - fp=fopen(cfgName,"r"); - if (fp==NULL) { - ShowError("File not found: %s\n",cfgName); - return 1; - } - while (fgets(line, sizeof(line), fp)) { - if (line[0] == '/' && line[1] == '/') - continue; - if (sscanf(line,"%[^:]: %[^\r\n]",w1,w2) < 2) - continue; - - if (strcmpi(w1, "main_chat_nick")==0) - safestrncpy(main_chat_nick, w2, sizeof(main_chat_nick)); - 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); - else if (strcmpi(w1,"item_db2_db")==0) - strcpy(item_db2_db,w2); - else if (strcmpi(w1,"item_db_re_db")==0) - strcpy(item_db_re_db,w2); - else if (strcmpi(w1,"mob_db2_db")==0) - strcpy(mob_db2_db,w2); - else - //Map Server SQL DB - if (strcmpi(w1,"map_server_ip")==0) - strcpy(map_server_ip, w2); - else if (strcmpi(w1,"map_server_port")==0) - map_server_port=atoi(w2); - else if (strcmpi(w1,"map_server_id")==0) - strcpy(map_server_id, w2); - else if (strcmpi(w1,"map_server_pw")==0) - strcpy(map_server_pw, w2); - else if (strcmpi(w1,"map_server_db")==0) - strcpy(map_server_db, w2); - else if (strcmpi(w1,"default_codepage")==0) - strcpy(default_codepage, w2); - else if (strcmpi(w1,"use_sql_db")==0) { - db_use_sqldbs = config_switch(w2); - ShowStatus("Using SQL dbs: %s\n",w2); - } else if (strcmpi(w1,"log_db_ip")==0) - strcpy(log_db_ip, w2); - else if (strcmpi(w1,"log_db_id")==0) - strcpy(log_db_id, w2); - else if (strcmpi(w1,"log_db_pw")==0) - strcpy(log_db_pw, w2); - else if (strcmpi(w1,"log_db_port")==0) - log_db_port = atoi(w2); - else if (strcmpi(w1,"log_db_db")==0) - strcpy(log_db_db, w2); - else if (mapreg_config_read(w1,w2)) - continue; - //support the import command, just like any other config - else if (strcmpi(w1,"import")==0) - inter_config_read(w2); - } - fclose(fp); - - return 0; + char line[1024],w1[1024],w2[1024]; + FILE *fp; + + fp=fopen(cfgName,"r"); + if(fp==NULL){ + ShowError("File not found: %s\n",cfgName); + return 1; + } + while(fgets(line, sizeof(line), fp)) + { + if(line[0] == '/' && line[1] == '/') + continue; + if( sscanf(line,"%[^:]: %[^\r\n]",w1,w2) < 2 ) + continue; + + if(strcmpi(w1, "main_chat_nick")==0) + safestrncpy(main_chat_nick, w2, sizeof(main_chat_nick)); + 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); + else + if(strcmpi(w1,"item_db2_db")==0) + strcpy(item_db2_db,w2); + else + if(strcmpi(w1,"item_db_re_db")==0) + strcpy(item_db_re_db,w2); + else + if(strcmpi(w1,"mob_db2_db")==0) + strcpy(mob_db2_db,w2); + else + //Map Server SQL DB + if(strcmpi(w1,"map_server_ip")==0) + strcpy(map_server_ip, w2); + else + if(strcmpi(w1,"map_server_port")==0) + map_server_port=atoi(w2); + else + if(strcmpi(w1,"map_server_id")==0) + strcpy(map_server_id, w2); + else + if(strcmpi(w1,"map_server_pw")==0) + strcpy(map_server_pw, w2); + else + if(strcmpi(w1,"map_server_db")==0) + strcpy(map_server_db, w2); + else + if(strcmpi(w1,"default_codepage")==0) + strcpy(default_codepage, w2); + else + if(strcmpi(w1,"use_sql_db")==0) { + db_use_sqldbs = config_switch(w2); + ShowStatus ("Using SQL dbs: %s\n",w2); + } else + if(strcmpi(w1,"log_db_ip")==0) + strcpy(log_db_ip, w2); + else + if(strcmpi(w1,"log_db_id")==0) + strcpy(log_db_id, w2); + else + if(strcmpi(w1,"log_db_pw")==0) + strcpy(log_db_pw, w2); + else + if(strcmpi(w1,"log_db_port")==0) + log_db_port = atoi(w2); + else + if(strcmpi(w1,"log_db_db")==0) + strcpy(log_db_db, w2); + else + if( mapreg_config_read(w1,w2) ) + continue; + //support the import command, just like any other config + else + if(strcmpi(w1,"import")==0) + inter_config_read(w2); + } + fclose(fp); + + return 0; } /*======================================= @@ -3393,52 +3428,53 @@ int inter_config_read(char *cfgName) *---------------------------------------*/ int map_sql_init(void) { - // main db connection - mmysql_handle = Sql_Malloc(); + // main db connection + mmysql_handle = Sql_Malloc(); - ShowInfo("Connecting to the Map DB Server....\n"); - if (SQL_ERROR == Sql_Connect(mmysql_handle, map_server_id, map_server_pw, map_server_ip, map_server_port, map_server_db)) - exit(EXIT_FAILURE); - ShowStatus("connect success! (Map Server Connection)\n"); + ShowInfo("Connecting to the Map DB Server....\n"); + if( SQL_ERROR == Sql_Connect(mmysql_handle, map_server_id, map_server_pw, map_server_ip, map_server_port, map_server_db) ) + exit(EXIT_FAILURE); + ShowStatus("connect success! (Map Server Connection)\n"); - if (strlen(default_codepage) > 0) - if (SQL_ERROR == Sql_SetEncoding(mmysql_handle, default_codepage)) - Sql_ShowDebug(mmysql_handle); + if( strlen(default_codepage) > 0 ) + if ( SQL_ERROR == Sql_SetEncoding(mmysql_handle, default_codepage) ) + Sql_ShowDebug(mmysql_handle); - return 0; + return 0; } int map_sql_close(void) { - ShowStatus("Close Map DB Connection....\n"); - Sql_Free(mmysql_handle); - mmysql_handle = NULL; + ShowStatus("Close Map DB Connection....\n"); + Sql_Free(mmysql_handle); + mmysql_handle = NULL; #ifndef BETA_THREAD_TEST - if (log_config.sql_logs) { - ShowStatus("Close Log DB Connection....\n"); - Sql_Free(logmysql_handle); - logmysql_handle = NULL; - } + if (log_config.sql_logs) + { + ShowStatus("Close Log DB Connection....\n"); + Sql_Free(logmysql_handle); + logmysql_handle = NULL; + } #endif - return 0; + return 0; } int log_sql_init(void) { #ifndef BETA_THREAD_TEST - // log db connection - logmysql_handle = Sql_Malloc(); + // log db connection + logmysql_handle = Sql_Malloc(); - ShowInfo(""CL_WHITE"[SQL]"CL_RESET": Connecting to the Log Database "CL_WHITE"%s"CL_RESET" At "CL_WHITE"%s"CL_RESET"...\n",log_db_db,log_db_ip); - if (SQL_ERROR == Sql_Connect(logmysql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db_db)) - exit(EXIT_FAILURE); - ShowStatus(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", log_db_db); + ShowInfo(""CL_WHITE"[SQL]"CL_RESET": Connecting to the Log Database "CL_WHITE"%s"CL_RESET" At "CL_WHITE"%s"CL_RESET"...\n",log_db_db,log_db_ip); + if ( SQL_ERROR == Sql_Connect(logmysql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db_db) ) + exit(EXIT_FAILURE); + ShowStatus(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", log_db_db); - if (strlen(default_codepage) > 0) - if (SQL_ERROR == Sql_SetEncoding(logmysql_handle, default_codepage)) - Sql_ShowDebug(logmysql_handle); + if( strlen(default_codepage) > 0 ) + if ( SQL_ERROR == Sql_SetEncoding(logmysql_handle, default_codepage) ) + Sql_ShowDebug(logmysql_handle); #endif - return 0; + return 0; } /** @@ -3446,10 +3482,10 @@ int log_sql_init(void) */ int map_db_final(DBKey key, DBData *data, va_list ap) { - struct map_data_other_server *mdos = db_data2ptr(data); - if (mdos && mdos->cell == NULL) - aFree(mdos); - return 0; + struct map_data_other_server *mdos = db_data2ptr(data); + if(mdos && mdos->cell == NULL) + aFree(mdos); + return 0; } /** @@ -3457,46 +3493,47 @@ int map_db_final(DBKey key, DBData *data, va_list ap) */ int nick_db_final(DBKey key, DBData *data, va_list args) { - struct charid2nick *p = db_data2ptr(data); - struct charid_request *req; + struct charid2nick* p = db_data2ptr(data); + struct charid_request* req; - if (p == NULL) - return 0; - while (p->requests) { - req = p->requests; - p->requests = req->next; - aFree(req); - } - aFree(p); - return 0; + if( p == NULL ) + return 0; + while( p->requests ) + { + req = p->requests; + p->requests = req->next; + aFree(req); + } + aFree(p); + return 0; } int cleanup_sub(struct block_list *bl, va_list ap) { - nullpo_ret(bl); - - switch (bl->type) { - case BL_PC: - map_quit((struct map_session_data *) bl); - break; - case BL_NPC: - npc_unload((struct npc_data *)bl,false); - break; - case BL_MOB: - unit_free(bl,CLR_OUTSIGHT); - break; - case BL_PET: - //There is no need for this, the pet is removed together with the player. [Skotlex] - break; - case BL_ITEM: - map_clearflooritem(bl); - break; - case BL_SKILL: - skill_delunit((struct skill_unit *) bl); - break; - } - - return 1; + nullpo_ret(bl); + + switch(bl->type) { + case BL_PC: + map_quit((struct map_session_data *) bl); + break; + case BL_NPC: + npc_unload((struct npc_data *)bl,false); + break; + case BL_MOB: + unit_free(bl,CLR_OUTSIGHT); + break; + case BL_PET: + //There is no need for this, the pet is removed together with the player. [Skotlex] + break; + case BL_ITEM: + map_clearflooritem(bl); + break; + case BL_SKILL: + skill_delunit((struct skill_unit *) bl); + break; + } + + return 1; } /** @@ -3504,7 +3541,7 @@ int cleanup_sub(struct block_list *bl, va_list ap) */ static int cleanup_db_sub(DBKey key, DBData *data, va_list va) { - return cleanup_sub(db_data2ptr(data), va); + return cleanup_sub(db_data2ptr(data), va); } /*========================================== @@ -3512,91 +3549,91 @@ static int cleanup_db_sub(DBKey key, DBData *data, va_list va) *------------------------------------------*/ void do_final(void) { - int i, j; - struct map_session_data *sd; - struct s_mapiterator *iter; - - ShowStatus("Terminating...\n"); - - //Ladies and babies first. - iter = mapit_getallusers(); - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) - map_quit(sd); - mapit_free(iter); - - /* prepares npcs for a faster shutdown process */ - do_clear_npc(); - - // remove all objects on maps - for (i = 0; i < map_num; i++) { - ShowStatus("Cleaning up maps [%d/%d]: %s..."CL_CLL"\r", i+1, map_num, map[i].name); - if (map[i].m >= 0) - map_foreachinmap(cleanup_sub, i, BL_ALL); - } - ShowStatus("Cleaned up %d maps."CL_CLL"\n", map_num); - - id_db->foreach(id_db,cleanup_db_sub); - chrif_char_reset_offline(); - chrif_flush_fifo(); - - do_final_atcommand(); - do_final_battle(); - do_final_chrif(); - do_final_clif(); - do_final_npc(); - do_final_script(); - do_final_instance(); - do_final_itemdb(); - do_final_storage(); - do_final_guild(); - do_final_party(); - do_final_pc(); - do_final_pet(); - do_final_mob(); - do_final_msg(); - do_final_skill(); - do_final_status(); - do_final_unit(); - do_final_battleground(); - do_final_duel(); - do_final_elemental(); - - map_db->destroy(map_db, map_db_final); - - for (i=0; i<map_num; i++) { - if (map[i].cell) aFree(map[i].cell); - if (map[i].block) aFree(map[i].block); - if (map[i].block_mob) aFree(map[i].block_mob); - if (battle_config.dynamic_mobs) { //Dynamic mobs flag by [random] - if (map[i].mob_delete_timer != INVALID_TIMER) - delete_timer(map[i].mob_delete_timer, map_removemobs_timer); - for (j=0; j<MAX_MOB_LIST_PER_MAP; j++) - if (map[i].moblist[j]) aFree(map[i].moblist[j]); - } - } - - mapindex_final(); - if (enable_grf) - grfio_final(); - - id_db->destroy(id_db, NULL); - pc_db->destroy(pc_db, NULL); - mobid_db->destroy(mobid_db, NULL); - bossid_db->destroy(bossid_db, NULL); - nick_db->destroy(nick_db, nick_db_final); - charid_db->destroy(charid_db, NULL); - iwall_db->destroy(iwall_db, NULL); - regen_db->destroy(regen_db, NULL); + int i, j; + struct map_session_data* sd; + struct s_mapiterator* iter; + + ShowStatus("Terminating...\n"); + + //Ladies and babies first. + iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + map_quit(sd); + mapit_free(iter); + + /* prepares npcs for a faster shutdown process */ + do_clear_npc(); + + // remove all objects on maps + for (i = 0; i < map_num; i++) { + ShowStatus("Cleaning up maps [%d/%d]: %s..."CL_CLL"\r", i+1, map_num, map[i].name); + if (map[i].m >= 0) + map_foreachinmap(cleanup_sub, i, BL_ALL); + } + ShowStatus("Cleaned up %d maps."CL_CLL"\n", map_num); + + id_db->foreach(id_db,cleanup_db_sub); + chrif_char_reset_offline(); + chrif_flush_fifo(); + + do_final_atcommand(); + do_final_battle(); + do_final_chrif(); + do_final_clif(); + do_final_npc(); + do_final_script(); + do_final_instance(); + do_final_itemdb(); + do_final_storage(); + do_final_guild(); + do_final_party(); + do_final_pc(); + do_final_pet(); + do_final_mob(); + do_final_msg(); + do_final_skill(); + do_final_status(); + do_final_unit(); + do_final_battleground(); + do_final_duel(); + do_final_elemental(); + + map_db->destroy(map_db, map_db_final); + + for (i=0; i<map_num; i++) { + if(map[i].cell) aFree(map[i].cell); + if(map[i].block) aFree(map[i].block); + if(map[i].block_mob) aFree(map[i].block_mob); + if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random] + if(map[i].mob_delete_timer != INVALID_TIMER) + delete_timer(map[i].mob_delete_timer, map_removemobs_timer); + for (j=0; j<MAX_MOB_LIST_PER_MAP; j++) + if (map[i].moblist[j]) aFree(map[i].moblist[j]); + } + } + + mapindex_final(); + if(enable_grf) + grfio_final(); + + id_db->destroy(id_db, NULL); + pc_db->destroy(pc_db, NULL); + mobid_db->destroy(mobid_db, NULL); + bossid_db->destroy(bossid_db, NULL); + nick_db->destroy(nick_db, nick_db_final); + charid_db->destroy(charid_db, NULL); + iwall_db->destroy(iwall_db, NULL); + regen_db->destroy(regen_db, NULL); map_sql_close(); - ShowStatus("Finished.\n"); + ShowStatus("Finished.\n"); } -static int map_abort_sub(struct map_session_data *sd, va_list ap) +static int map_abort_sub(struct map_session_data* sd, va_list ap) { - chrif_save(sd,1); - return 1; + chrif_save(sd,1); + return 1; } @@ -3606,21 +3643,22 @@ static int map_abort_sub(struct map_session_data *sd, va_list ap) //------------------------------ void do_abort(void) { - static int run = 0; - //Save all characters and then flush the inter-connection. - if (run) { - ShowFatalError("Server has crashed while trying to save characters. Character data can't be saved!\n"); - return; - } - run = 1; - if (!chrif_isconnected()) { - if (pc_db->size(pc_db)) - ShowFatalError("Server has crashed without a connection to the char-server, %u characters can't be saved!\n", pc_db->size(pc_db)); - return; - } - ShowError("Server received crash signal! Attempting to save all online characters!\n"); - map_foreachpc(map_abort_sub); - chrif_flush_fifo(); + static int run = 0; + //Save all characters and then flush the inter-connection. + if (run) { + ShowFatalError("Server has crashed while trying to save characters. Character data can't be saved!\n"); + return; + } + run = 1; + if (!chrif_isconnected()) + { + if (pc_db->size(pc_db)) + ShowFatalError("Server has crashed without a connection to the char-server, %u characters can't be saved!\n", pc_db->size(pc_db)); + return; + } + ShowError("Server received crash signal! Attempting to save all online characters!\n"); + map_foreachpc(map_abort_sub); + chrif_flush_fifo(); } /*====================================================== @@ -3628,22 +3666,22 @@ void do_abort(void) *------------------------------------------------------*/ static void map_helpscreen(bool do_exit) { - ShowInfo("Usage: %s [options]\n", SERVER_NAME); - ShowInfo("\n"); - ShowInfo("Options:\n"); - ShowInfo(" -?, -h [--help]\t\tDisplays this help screen.\n"); - ShowInfo(" -v [--version]\t\tDisplays the server's version.\n"); - ShowInfo(" --run-once\t\t\tCloses server after loading (testing).\n"); - ShowInfo(" --map-config <file>\t\tAlternative map-server configuration.\n"); - ShowInfo(" --battle-config <file>\tAlternative battle configuration.\n"); - ShowInfo(" --atcommand-config <file>\tAlternative atcommand configuration.\n"); - ShowInfo(" --script-config <file>\tAlternative script configuration.\n"); - ShowInfo(" --msg-config <file>\t\tAlternative message configuration.\n"); - ShowInfo(" --grf-path <file>\t\tAlternative GRF path configuration.\n"); - ShowInfo(" --inter-config <file>\t\tAlternative inter-server configuration.\n"); - ShowInfo(" --log-config <file>\t\tAlternative logging configuration.\n"); - if (do_exit) - exit(EXIT_SUCCESS); + ShowInfo("Usage: %s [options]\n", SERVER_NAME); + ShowInfo("\n"); + ShowInfo("Options:\n"); + ShowInfo(" -?, -h [--help]\t\tDisplays this help screen.\n"); + ShowInfo(" -v [--version]\t\tDisplays the server's version.\n"); + ShowInfo(" --run-once\t\t\tCloses server after loading (testing).\n"); + ShowInfo(" --map-config <file>\t\tAlternative map-server configuration.\n"); + ShowInfo(" --battle-config <file>\tAlternative battle configuration.\n"); + ShowInfo(" --atcommand-config <file>\tAlternative atcommand configuration.\n"); + ShowInfo(" --script-config <file>\tAlternative script configuration.\n"); + ShowInfo(" --msg-config <file>\t\tAlternative message configuration.\n"); + ShowInfo(" --grf-path <file>\t\tAlternative GRF path configuration.\n"); + ShowInfo(" --inter-config <file>\t\tAlternative inter-server configuration.\n"); + ShowInfo(" --log-config <file>\t\tAlternative logging configuration.\n"); + if( do_exit ) + exit(EXIT_SUCCESS); } /*====================================================== @@ -3651,12 +3689,12 @@ static void map_helpscreen(bool do_exit) *------------------------------------------------------*/ static void map_versionscreen(bool do_exit) { - ShowInfo(CL_WHITE"rAthena SVN version: %s" CL_RESET"\n", get_svn_revision()); - ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://rathena.org/\n"); - ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rathena.net/#rathena\n"); - ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n"); - if (do_exit) - exit(EXIT_SUCCESS); + ShowInfo(CL_WHITE"rAthena SVN version: %s" CL_RESET"\n", get_svn_revision()); + ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://rathena.org/\n"); + ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rathena.net/#rathena\n"); + ShowInfo("Open "CL_WHITE"readme.html"CL_RESET" for more information.\n"); + if( do_exit ) + exit(EXIT_SUCCESS); } /*====================================================== @@ -3664,219 +3702,249 @@ static void map_versionscreen(bool do_exit) *------------------------------------------------------*/ void set_server_type(void) { - SERVER_TYPE = ATHENA_SERVER_MAP; + SERVER_TYPE = ATHENA_SERVER_MAP; } /// Called when a terminate signal is received. void do_shutdown(void) { - if (runflag != MAPSERVER_ST_SHUTDOWN) { - runflag = MAPSERVER_ST_SHUTDOWN; - ShowStatus("Shutting down...\n"); - { - struct map_session_data *sd; - struct s_mapiterator *iter = mapit_getallusers(); - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) - clif_GM_kick(NULL, sd); - mapit_free(iter); - flush_fifos(); - } - chrif_check_shutdown(); - } + if( runflag != MAPSERVER_ST_SHUTDOWN ) + { + runflag = MAPSERVER_ST_SHUTDOWN; + ShowStatus("Shutting down...\n"); + { + struct map_session_data* sd; + struct s_mapiterator* iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + clif_GM_kick(NULL, sd); + mapit_free(iter); + flush_fifos(); + } + chrif_check_shutdown(); + } } -static bool map_arg_next_value(const char *option, int i, int argc) +static bool map_arg_next_value(const char* option, int i, int argc) { - if (i >= argc-1) { - ShowWarning("Missing value for option '%s'.\n", option); - return false; - } + if( i >= argc-1 ) + { + ShowWarning("Missing value for option '%s'.\n", option); + return false; + } - return true; + return true; } int do_init(int argc, char *argv[]) { - int i; + int i; #ifdef GCOLLECT - GC_enable_incremental(); + GC_enable_incremental(); #endif - 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"; - SCRIPT_CONF_NAME = "conf/script_athena.conf"; - MSG_CONF_NAME = "conf/msg_athena.conf"; - GRF_PATH_FILENAME = "conf/grf-files.txt"; - - rnd_init(); - - for (i = 1; i < argc ; i++) { - const char *arg = argv[i]; - - if (arg[0] != '-' && (arg[0] != '/' || arg[1] == '-')) { - // -, -- and / - ShowError("Unknown option '%s'.\n", argv[i]); - exit(EXIT_FAILURE); - } else if ((++arg)[0] == '-') { - // long option - arg++; - - if (strcmp(arg, "help") == 0) { - map_helpscreen(true); - } else if (strcmp(arg, "version") == 0) { - map_versionscreen(true); - } else if (strcmp(arg, "map-config") == 0) { - if (map_arg_next_value(arg, i, argc)) - MAP_CONF_NAME = argv[++i]; - } else if (strcmp(arg, "battle-config") == 0) { - if (map_arg_next_value(arg, i, argc)) - BATTLE_CONF_FILENAME = argv[++i]; - } else if (strcmp(arg, "atcommand-config") == 0) { - if (map_arg_next_value(arg, i, argc)) - ATCOMMAND_CONF_FILENAME = argv[++i]; - } else if (strcmp(arg, "script-config") == 0) { - if (map_arg_next_value(arg, i, argc)) - SCRIPT_CONF_NAME = argv[++i]; - } else if (strcmp(arg, "msg-config") == 0) { - if (map_arg_next_value(arg, i, argc)) - MSG_CONF_NAME = argv[++i]; - } else if (strcmp(arg, "grf-path-file") == 0) { - if (map_arg_next_value(arg, i, argc)) - GRF_PATH_FILENAME = argv[++i]; - } else if (strcmp(arg, "inter-config") == 0) { - if (map_arg_next_value(arg, i, argc)) - INTER_CONF_NAME = argv[++i]; - } else if (strcmp(arg, "log-config") == 0) { - if (map_arg_next_value(arg, i, argc)) - LOG_CONF_NAME = argv[++i]; - } else if (strcmp(arg, "run-once") == 0) { // close the map-server as soon as its done.. for testing [Celest] - runflag = CORE_ST_STOP; - } else { - ShowError("Unknown option '%s'.\n", argv[i]); - exit(EXIT_FAILURE); - } - } else switch (arg[0]) { - // short option - case '?': - case 'h': - map_helpscreen(true); - break; - case 'v': - map_versionscreen(true); - break; - default: - ShowError("Unknown option '%s'.\n", argv[i]); - exit(EXIT_FAILURE); - } - } - - map_config_read(MAP_CONF_NAME); - /* only temporary until sirius's datapack patch is complete */ - - // loads npcs - map_reloadnpc(false); - - chrif_checkdefaultlogin(); - - if (!map_ip_set || !char_ip_set) { - char ip_str[16]; - ip2str(addr_[0], ip_str); - - ShowWarning("Not all IP addresses in map_athena.conf configured, autodetecting...\n"); - - if (naddr_ == 0) - ShowError("Unable to determine your IP address...\n"); - else if (naddr_ > 1) - ShowNotice("Multiple interfaces detected...\n"); - - ShowInfo("Defaulting to %s as our IP address\n", ip_str); - - if (!map_ip_set) - clif_setip(ip_str); - if (!char_ip_set) - chrif_setip(ip_str); - } - - battle_config_read(BATTLE_CONF_FILENAME); - msg_config_read(MSG_CONF_NAME); - script_config_read(SCRIPT_CONF_NAME); - inter_config_read(INTER_CONF_NAME); - log_config_read(LOG_CONF_NAME); - - id_db = idb_alloc(DB_OPT_BASE); - pc_db = idb_alloc(DB_OPT_BASE); //Added for reliable map_id2sd() use. [Skotlex] - mobid_db = idb_alloc(DB_OPT_BASE); //Added to lower the load of the lazy mob ai. [Skotlex] - bossid_db = idb_alloc(DB_OPT_BASE); // Used for Convex Mirror quick MVP search - map_db = uidb_alloc(DB_OPT_BASE); - nick_db = idb_alloc(DB_OPT_BASE); - charid_db = idb_alloc(DB_OPT_BASE); - regen_db = idb_alloc(DB_OPT_BASE); // efficient status_natural_heal processing - - iwall_db = strdb_alloc(DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1); // [Zephyrus] Invisible Walls - - map_sql_init(); - if (log_config.sql_logs) - log_sql_init(); - - mapindex_init(); - if (enable_grf) - grfio_init(GRF_PATH_FILENAME); - - map_readallmaps(); - - add_timer_func_list(map_freeblock_timer, "map_freeblock_timer"); - add_timer_func_list(map_clearflooritem_timer, "map_clearflooritem_timer"); - add_timer_func_list(map_removemobs_timer, "map_removemobs_timer"); - add_timer_interval(gettick()+1000, map_freeblock_timer, 0, 0, 60*1000); - - do_init_atcommand(); - do_init_battle(); - do_init_instance(); - do_init_chrif(); - do_init_clif(); - do_init_script(); - do_init_itemdb(); - do_init_skill(); - do_init_mob(); - do_init_pc(); - do_init_status(); - do_init_party(); - do_init_guild(); - do_init_storage(); - do_init_pet(); - do_init_merc(); - do_init_mercenary(); - do_init_elemental(); - do_init_quest(); - do_init_npc(); - do_init_unit(); - do_init_battleground(); - do_init_duel(); - - npc_event_do_oninit(); // Init npcs (OnInit) - - if (console) { - //##TODO invoke a CONSOLE_START plugin event - } - - if (battle_config.pk_mode) - ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n"); - - ShowStatus("Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port); - - if (runflag != CORE_ST_STOP) { - shutdown_callback = do_shutdown; - runflag = MAPSERVER_ST_RUNNING; - } + 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"; + SCRIPT_CONF_NAME = "conf/script_athena.conf"; + MSG_CONF_NAME = "conf/msg_athena.conf"; + GRF_PATH_FILENAME = "conf/grf-files.txt"; + + rnd_init(); + + for( i = 1; i < argc ; i++ ) + { + const char* arg = argv[i]; + + if( arg[0] != '-' && ( arg[0] != '/' || arg[1] == '-' ) ) + {// -, -- and / + ShowError("Unknown option '%s'.\n", argv[i]); + exit(EXIT_FAILURE); + } + else if( (++arg)[0] == '-' ) + {// long option + arg++; + + if( strcmp(arg, "help") == 0 ) + { + map_helpscreen(true); + } + else if( strcmp(arg, "version") == 0 ) + { + map_versionscreen(true); + } + else if( strcmp(arg, "map-config") == 0 ) + { + if( map_arg_next_value(arg, i, argc) ) + MAP_CONF_NAME = argv[++i]; + } + else if( strcmp(arg, "battle-config") == 0 ) + { + if( map_arg_next_value(arg, i, argc) ) + BATTLE_CONF_FILENAME = argv[++i]; + } + else if( strcmp(arg, "atcommand-config") == 0 ) + { + if( map_arg_next_value(arg, i, argc) ) + ATCOMMAND_CONF_FILENAME = argv[++i]; + } + else if( strcmp(arg, "script-config") == 0 ) + { + if( map_arg_next_value(arg, i, argc) ) + SCRIPT_CONF_NAME = argv[++i]; + } + else if( strcmp(arg, "msg-config") == 0 ) + { + if( map_arg_next_value(arg, i, argc) ) + MSG_CONF_NAME = argv[++i]; + } + else if( strcmp(arg, "grf-path-file") == 0 ) + { + if( map_arg_next_value(arg, i, argc) ) + GRF_PATH_FILENAME = argv[++i]; + } + else if( strcmp(arg, "inter-config") == 0 ) + { + if( map_arg_next_value(arg, i, argc) ) + INTER_CONF_NAME = argv[++i]; + } + else if( strcmp(arg, "log-config") == 0 ) + { + if( map_arg_next_value(arg, i, argc) ) + LOG_CONF_NAME = argv[++i]; + } + else if( strcmp(arg, "run-once") == 0 ) // close the map-server as soon as its done.. for testing [Celest] + { + runflag = CORE_ST_STOP; + } + else + { + ShowError("Unknown option '%s'.\n", argv[i]); + exit(EXIT_FAILURE); + } + } + else switch( arg[0] ) + {// short option + case '?': + case 'h': + map_helpscreen(true); + break; + case 'v': + map_versionscreen(true); + break; + default: + ShowError("Unknown option '%s'.\n", argv[i]); + exit(EXIT_FAILURE); + } + } + + map_config_read(MAP_CONF_NAME); + /* only temporary until sirius's datapack patch is complete */ + + // loads npcs + map_reloadnpc(false); + + chrif_checkdefaultlogin(); + + if (!map_ip_set || !char_ip_set) { + char ip_str[16]; + ip2str(addr_[0], ip_str); + + ShowWarning("Not all IP addresses in map_athena.conf configured, autodetecting...\n"); + + if (naddr_ == 0) + ShowError("Unable to determine your IP address...\n"); + else if (naddr_ > 1) + ShowNotice("Multiple interfaces detected...\n"); + + ShowInfo("Defaulting to %s as our IP address\n", ip_str); + + if (!map_ip_set) + clif_setip(ip_str); + if (!char_ip_set) + chrif_setip(ip_str); + } + + battle_config_read(BATTLE_CONF_FILENAME); + msg_config_read(MSG_CONF_NAME); + script_config_read(SCRIPT_CONF_NAME); + inter_config_read(INTER_CONF_NAME); + log_config_read(LOG_CONF_NAME); + + id_db = idb_alloc(DB_OPT_BASE); + pc_db = idb_alloc(DB_OPT_BASE); //Added for reliable map_id2sd() use. [Skotlex] + mobid_db = idb_alloc(DB_OPT_BASE); //Added to lower the load of the lazy mob ai. [Skotlex] + bossid_db = idb_alloc(DB_OPT_BASE); // Used for Convex Mirror quick MVP search + map_db = uidb_alloc(DB_OPT_BASE); + nick_db = idb_alloc(DB_OPT_BASE); + charid_db = idb_alloc(DB_OPT_BASE); + regen_db = idb_alloc(DB_OPT_BASE); // efficient status_natural_heal processing + + iwall_db = strdb_alloc(DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1); // [Zephyrus] Invisible Walls + + map_sql_init(); + if (log_config.sql_logs) + log_sql_init(); + + mapindex_init(); + if(enable_grf) + grfio_init(GRF_PATH_FILENAME); + + map_readallmaps(); + + add_timer_func_list(map_freeblock_timer, "map_freeblock_timer"); + add_timer_func_list(map_clearflooritem_timer, "map_clearflooritem_timer"); + add_timer_func_list(map_removemobs_timer, "map_removemobs_timer"); + add_timer_interval(gettick()+1000, map_freeblock_timer, 0, 0, 60*1000); + + do_init_atcommand(); + do_init_battle(); + do_init_instance(); + do_init_chrif(); + do_init_clif(); + do_init_script(); + do_init_itemdb(); + do_init_skill(); + do_init_mob(); + do_init_pc(); + do_init_status(); + do_init_party(); + do_init_guild(); + do_init_storage(); + do_init_pet(); + do_init_merc(); + do_init_mercenary(); + do_init_elemental(); + do_init_quest(); + do_init_npc(); + do_init_unit(); + do_init_battleground(); + do_init_duel(); + + npc_event_do_oninit(); // Init npcs (OnInit) + + if( console ) + { + //##TODO invoke a CONSOLE_START plugin event + } + + if (battle_config.pk_mode) + ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n"); + + ShowStatus("Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port); + + if( runflag != CORE_ST_STOP ) + { + shutdown_callback = do_shutdown; + runflag = MAPSERVER_ST_RUNNING; + } #if defined(BUILDBOT) - if (buildbotflag) - exit(EXIT_FAILURE); + if( buildbotflag ) + exit(EXIT_FAILURE); #endif - return 0; + return 0; } diff --git a/src/map/map.h b/src/map/map.h index e8c95ed35..b011c8193 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -20,10 +20,11 @@ struct npc_data; struct item_data; -enum E_MAPSERVER_ST { - MAPSERVER_ST_RUNNING = CORE_ST_LAST, - MAPSERVER_ST_SHUTDOWN, - MAPSERVER_ST_LAST +enum E_MAPSERVER_ST +{ + MAPSERVER_ST_RUNNING = CORE_ST_LAST, + MAPSERVER_ST_SHUTDOWN, + MAPSERVER_ST_LAST }; @@ -82,130 +83,130 @@ enum MOBID { //Note the oddity of the novice: //Super Novices are considered the 2-1 version of the novice! Novices are considered a first class type, too... enum { - //Novice And 1-1 Jobs - MAPID_NOVICE = 0x0, - MAPID_SWORDMAN, - MAPID_MAGE, - MAPID_ARCHER, - MAPID_ACOLYTE, - MAPID_MERCHANT, - MAPID_THIEF, - MAPID_TAEKWON, - MAPID_WEDDING, - MAPID_GUNSLINGER, - MAPID_NINJA, - MAPID_XMAS, - MAPID_SUMMER, - MAPID_GANGSI, - //2-1 Jobs - MAPID_SUPER_NOVICE = JOBL_2_1|0x0, - MAPID_KNIGHT, - MAPID_WIZARD, - MAPID_HUNTER, - MAPID_PRIEST, - MAPID_BLACKSMITH, - MAPID_ASSASSIN, - MAPID_STAR_GLADIATOR, - MAPID_KAGEROUOBORO = JOBL_2_1|0x0A, - MAPID_DEATH_KNIGHT = JOBL_2_1|0x0D, - //2-2 Jobs - MAPID_CRUSADER = JOBL_2_2|0x1, - MAPID_SAGE, - MAPID_BARDDANCER, - MAPID_MONK, - MAPID_ALCHEMIST, - MAPID_ROGUE, - MAPID_SOUL_LINKER, - MAPID_DARK_COLLECTOR = JOBL_2_2|0x0D, - //Trans Novice And Trans 1-1 Jobs - MAPID_NOVICE_HIGH = JOBL_UPPER|0x0, - MAPID_SWORDMAN_HIGH, - MAPID_MAGE_HIGH, - MAPID_ARCHER_HIGH, - MAPID_ACOLYTE_HIGH, - MAPID_MERCHANT_HIGH, - MAPID_THIEF_HIGH, - //Trans 2-1 Jobs - MAPID_LORD_KNIGHT = JOBL_UPPER|JOBL_2_1|0x1, - MAPID_HIGH_WIZARD, - MAPID_SNIPER, - MAPID_HIGH_PRIEST, - MAPID_WHITESMITH, - MAPID_ASSASSIN_CROSS, - //Trans 2-2 Jobs - MAPID_PALADIN = JOBL_UPPER|JOBL_2_2|0x1, - MAPID_PROFESSOR, - MAPID_CLOWNGYPSY, - MAPID_CHAMPION, - MAPID_CREATOR, - MAPID_STALKER, - //Baby Novice And Baby 1-1 Jobs - MAPID_BABY = JOBL_BABY|0x0, - MAPID_BABY_SWORDMAN, - MAPID_BABY_MAGE, - MAPID_BABY_ARCHER, - MAPID_BABY_ACOLYTE, - MAPID_BABY_MERCHANT, - MAPID_BABY_THIEF, - //Baby 2-1 Jobs - MAPID_SUPER_BABY = JOBL_BABY|JOBL_2_1|0x0, - MAPID_BABY_KNIGHT, - MAPID_BABY_WIZARD, - MAPID_BABY_HUNTER, - MAPID_BABY_PRIEST, - MAPID_BABY_BLACKSMITH, - MAPID_BABY_ASSASSIN, - //Baby 2-2 Jobs - MAPID_BABY_CRUSADER = JOBL_BABY|JOBL_2_2|0x1, - MAPID_BABY_SAGE, - MAPID_BABY_BARDDANCER, - MAPID_BABY_MONK, - MAPID_BABY_ALCHEMIST, - MAPID_BABY_ROGUE, - //3-1 Jobs - MAPID_SUPER_NOVICE_E = JOBL_THIRD|JOBL_2_1|0x0, - MAPID_RUNE_KNIGHT, - MAPID_WARLOCK, - MAPID_RANGER, - MAPID_ARCH_BISHOP, - MAPID_MECHANIC, - MAPID_GUILLOTINE_CROSS, - //3-2 Jobs - MAPID_ROYAL_GUARD = JOBL_THIRD|JOBL_2_2|0x1, - MAPID_SORCERER, - MAPID_MINSTRELWANDERER, - MAPID_SURA, - MAPID_GENETIC, - MAPID_SHADOW_CHASER, - //Trans 3-1 Jobs - MAPID_RUNE_KNIGHT_T = JOBL_THIRD|JOBL_UPPER|JOBL_2_1|0x1, - MAPID_WARLOCK_T, - MAPID_RANGER_T, - MAPID_ARCH_BISHOP_T, - MAPID_MECHANIC_T, - MAPID_GUILLOTINE_CROSS_T, - //Trans 3-2 Jobs - MAPID_ROYAL_GUARD_T = JOBL_THIRD|JOBL_UPPER|JOBL_2_2|0x1, - MAPID_SORCERER_T, - MAPID_MINSTRELWANDERER_T, - MAPID_SURA_T, - MAPID_GENETIC_T, - MAPID_SHADOW_CHASER_T, - //Baby 3-1 Jobs - MAPID_SUPER_BABY_E = JOBL_THIRD|JOBL_BABY|JOBL_2_1|0x0, - MAPID_BABY_RUNE, - MAPID_BABY_WARLOCK, - MAPID_BABY_RANGER, - MAPID_BABY_BISHOP, - MAPID_BABY_MECHANIC, - MAPID_BABY_CROSS, - //Baby 3-2 Jobs - MAPID_BABY_GUARD = JOBL_THIRD|JOBL_BABY|JOBL_2_2|0x1, - MAPID_BABY_SORCERER, - MAPID_BABY_MINSTRELWANDERER, - MAPID_BABY_SURA, - MAPID_BABY_GENETIC, - MAPID_BABY_CHASER, +//Novice And 1-1 Jobs + MAPID_NOVICE = 0x0, + MAPID_SWORDMAN, + MAPID_MAGE, + MAPID_ARCHER, + MAPID_ACOLYTE, + MAPID_MERCHANT, + MAPID_THIEF, + MAPID_TAEKWON, + MAPID_WEDDING, + MAPID_GUNSLINGER, + MAPID_NINJA, + MAPID_XMAS, + MAPID_SUMMER, + MAPID_GANGSI, +//2-1 Jobs + MAPID_SUPER_NOVICE = JOBL_2_1|0x0, + MAPID_KNIGHT, + MAPID_WIZARD, + MAPID_HUNTER, + MAPID_PRIEST, + MAPID_BLACKSMITH, + MAPID_ASSASSIN, + MAPID_STAR_GLADIATOR, + MAPID_KAGEROUOBORO = JOBL_2_1|0x0A, + MAPID_DEATH_KNIGHT = JOBL_2_1|0x0D, +//2-2 Jobs + MAPID_CRUSADER = JOBL_2_2|0x1, + MAPID_SAGE, + MAPID_BARDDANCER, + MAPID_MONK, + MAPID_ALCHEMIST, + MAPID_ROGUE, + MAPID_SOUL_LINKER, + MAPID_DARK_COLLECTOR = JOBL_2_2|0x0D, +//Trans Novice And Trans 1-1 Jobs + MAPID_NOVICE_HIGH = JOBL_UPPER|0x0, + MAPID_SWORDMAN_HIGH, + MAPID_MAGE_HIGH, + MAPID_ARCHER_HIGH, + MAPID_ACOLYTE_HIGH, + MAPID_MERCHANT_HIGH, + MAPID_THIEF_HIGH, +//Trans 2-1 Jobs + MAPID_LORD_KNIGHT = JOBL_UPPER|JOBL_2_1|0x1, + MAPID_HIGH_WIZARD, + MAPID_SNIPER, + MAPID_HIGH_PRIEST, + MAPID_WHITESMITH, + MAPID_ASSASSIN_CROSS, +//Trans 2-2 Jobs + MAPID_PALADIN = JOBL_UPPER|JOBL_2_2|0x1, + MAPID_PROFESSOR, + MAPID_CLOWNGYPSY, + MAPID_CHAMPION, + MAPID_CREATOR, + MAPID_STALKER, +//Baby Novice And Baby 1-1 Jobs + MAPID_BABY = JOBL_BABY|0x0, + MAPID_BABY_SWORDMAN, + MAPID_BABY_MAGE, + MAPID_BABY_ARCHER, + MAPID_BABY_ACOLYTE, + MAPID_BABY_MERCHANT, + MAPID_BABY_THIEF, +//Baby 2-1 Jobs + MAPID_SUPER_BABY = JOBL_BABY|JOBL_2_1|0x0, + MAPID_BABY_KNIGHT, + MAPID_BABY_WIZARD, + MAPID_BABY_HUNTER, + MAPID_BABY_PRIEST, + MAPID_BABY_BLACKSMITH, + MAPID_BABY_ASSASSIN, +//Baby 2-2 Jobs + MAPID_BABY_CRUSADER = JOBL_BABY|JOBL_2_2|0x1, + MAPID_BABY_SAGE, + MAPID_BABY_BARDDANCER, + MAPID_BABY_MONK, + MAPID_BABY_ALCHEMIST, + MAPID_BABY_ROGUE, +//3-1 Jobs + MAPID_SUPER_NOVICE_E = JOBL_THIRD|JOBL_2_1|0x0, + MAPID_RUNE_KNIGHT, + MAPID_WARLOCK, + MAPID_RANGER, + MAPID_ARCH_BISHOP, + MAPID_MECHANIC, + MAPID_GUILLOTINE_CROSS, +//3-2 Jobs + MAPID_ROYAL_GUARD = JOBL_THIRD|JOBL_2_2|0x1, + MAPID_SORCERER, + MAPID_MINSTRELWANDERER, + MAPID_SURA, + MAPID_GENETIC, + MAPID_SHADOW_CHASER, +//Trans 3-1 Jobs + MAPID_RUNE_KNIGHT_T = JOBL_THIRD|JOBL_UPPER|JOBL_2_1|0x1, + MAPID_WARLOCK_T, + MAPID_RANGER_T, + MAPID_ARCH_BISHOP_T, + MAPID_MECHANIC_T, + MAPID_GUILLOTINE_CROSS_T, +//Trans 3-2 Jobs + MAPID_ROYAL_GUARD_T = JOBL_THIRD|JOBL_UPPER|JOBL_2_2|0x1, + MAPID_SORCERER_T, + MAPID_MINSTRELWANDERER_T, + MAPID_SURA_T, + MAPID_GENETIC_T, + MAPID_SHADOW_CHASER_T, +//Baby 3-1 Jobs + MAPID_SUPER_BABY_E = JOBL_THIRD|JOBL_BABY|JOBL_2_1|0x0, + MAPID_BABY_RUNE, + MAPID_BABY_WARLOCK, + MAPID_BABY_RANGER, + MAPID_BABY_BISHOP, + MAPID_BABY_MECHANIC, + MAPID_BABY_CROSS, +//Baby 3-2 Jobs + MAPID_BABY_GUARD = JOBL_THIRD|JOBL_BABY|JOBL_2_2|0x1, + MAPID_BABY_SORCERER, + MAPID_BABY_MINSTRELWANDERER, + MAPID_BABY_SURA, + MAPID_BABY_GENETIC, + MAPID_BABY_CHASER, }; //Max size for inputs to Graffiti, Talkie Box and Vending text prompts @@ -234,19 +235,19 @@ enum { //This stackable implementation does not means a BL can be more than one type at a time, but it's //meant to make it easier to check for multiple types at a time on invocations such as map_foreach* calls [Skotlex] enum bl_type { - BL_NUL = 0x000, - BL_PC = 0x001, - BL_MOB = 0x002, - BL_PET = 0x004, - BL_HOM = 0x008, - BL_MER = 0x010, - BL_ITEM = 0x020, - BL_SKILL = 0x040, - BL_NPC = 0x080, - BL_CHAT = 0x100, - BL_ELEM = 0x200, - - BL_ALL = 0xFFF, + BL_NUL = 0x000, + BL_PC = 0x001, + BL_MOB = 0x002, + BL_PET = 0x004, + BL_HOM = 0x008, + BL_MER = 0x010, + BL_ITEM = 0x020, + BL_SKILL = 0x040, + BL_NPC = 0x080, + BL_CHAT = 0x100, + BL_ELEM = 0x200, + + BL_ALL = 0xFFF, }; //For common mapforeach calls. Since pets cannot be affected, they aren't included here yet. @@ -255,349 +256,350 @@ enum bl_type { enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP, TOMB }; enum { - RC_FORMLESS=0, - RC_UNDEAD, - RC_BRUTE, - RC_PLANT, - RC_INSECT, - RC_FISH, - RC_DEMON, - RC_DEMIHUMAN, - RC_ANGEL, - RC_DRAGON, - RC_BOSS, - RC_NONBOSS, - RC_NONDEMIHUMAN, - RC_MAX + RC_FORMLESS=0, + RC_UNDEAD, + RC_BRUTE, + RC_PLANT, + RC_INSECT, + RC_FISH, + RC_DEMON, + RC_DEMIHUMAN, + RC_ANGEL, + RC_DRAGON, + RC_BOSS, + RC_NONBOSS, + RC_NONDEMIHUMAN, + RC_MAX }; enum { - RC2_NONE = 0, - RC2_GOBLIN, - RC2_KOBOLD, - RC2_ORC, - RC2_GOLEM, - RC2_GUARDIAN, - RC2_NINJA, - RC2_MAX + RC2_NONE = 0, + RC2_GOBLIN, + RC2_KOBOLD, + RC2_ORC, + RC2_GOLEM, + RC2_GUARDIAN, + RC2_NINJA, + RC2_MAX }; enum { - ELE_NEUTRAL=0, - ELE_WATER, - ELE_EARTH, - ELE_FIRE, - ELE_WIND, - ELE_POISON, - ELE_HOLY, - ELE_DARK, - ELE_GHOST, - ELE_UNDEAD, - ELE_MAX + ELE_NEUTRAL=0, + ELE_WATER, + ELE_EARTH, + ELE_FIRE, + ELE_WIND, + ELE_POISON, + ELE_HOLY, + ELE_DARK, + ELE_GHOST, + ELE_UNDEAD, + ELE_MAX }; enum auto_trigger_flag { - ATF_SELF=0x01, - ATF_TARGET=0x02, - ATF_SHORT=0x04, - ATF_LONG=0x08, - ATF_WEAPON=0x10, - ATF_MAGIC=0x20, - ATF_MISC=0x40, + ATF_SELF=0x01, + ATF_TARGET=0x02, + ATF_SHORT=0x04, + ATF_LONG=0x08, + ATF_WEAPON=0x10, + ATF_MAGIC=0x20, + ATF_MISC=0x40, }; struct block_list { - struct block_list *next,*prev; - int id; - short m,x,y; - enum bl_type type; + struct block_list *next,*prev; + int id; + short m,x,y; + enum bl_type type; }; // Mob List Held in memory for Dynamic Mobs [Wizputer] // Expanded to specify all mob-related spawn data by [Skotlex] struct spawn_data { - short class_; //Class, used because a mob can change it's class - unsigned short m, x, y; //Spawn information (map, point, spawn-area around point) - signed short xs, ys; - unsigned short num; //Number of mobs using this structure - unsigned short active;//Number of mobs that are already spawned (for mob_remove_damaged: no) - unsigned int delay1, delay2; //Spawn delay (fixed base + random variance) - unsigned int level; - struct { - unsigned int size : 2; //Holds if mob has to be tiny/large - unsigned int ai : 4; //Special ai for summoned monsters. - //0: Normal mob | 1: Standard summon, attacks mobs - //2: Alchemist Marine Sphere | 3: Alchemist Summon Flora | 4: Summon Zanzou - unsigned int dynamic : 1; //Whether this data is indexed by a map's dynamic mob list - unsigned int boss : 1; //0: Non-boss monster | 1: Boss monster - } state; - char name[NAME_LENGTH], eventname[EVENT_NAME_LENGTH]; //Name/event + short class_; //Class, used because a mob can change it's class + unsigned short m, x, y; //Spawn information (map, point, spawn-area around point) + signed short xs, ys; + unsigned short num; //Number of mobs using this structure + unsigned short active;//Number of mobs that are already spawned (for mob_remove_damaged: no) + unsigned int delay1, delay2; //Spawn delay (fixed base + random variance) + unsigned int level; + struct { + unsigned int size : 2; //Holds if mob has to be tiny/large + unsigned int ai : 4; //Special ai for summoned monsters. + //0: Normal mob | 1: Standard summon, attacks mobs + //2: Alchemist Marine Sphere | 3: Alchemist Summon Flora | 4: Summon Zanzou + unsigned int dynamic : 1; //Whether this data is indexed by a map's dynamic mob list + unsigned int boss : 1; //0: Non-boss monster | 1: Boss monster + } state; + char name[NAME_LENGTH], eventname[EVENT_NAME_LENGTH]; //Name/event }; struct flooritem_data { - struct block_list bl; - unsigned char subx,suby; - int cleartimer; - int first_get_charid,second_get_charid,third_get_charid; - unsigned int first_get_tick,second_get_tick,third_get_tick; - struct item item_data; + struct block_list bl; + unsigned char subx,suby; + int cleartimer; + int first_get_charid,second_get_charid,third_get_charid; + unsigned int first_get_tick,second_get_tick,third_get_tick; + struct item item_data; }; enum _sp { - SP_SPEED,SP_BASEEXP,SP_JOBEXP,SP_KARMA,SP_MANNER,SP_HP,SP_MAXHP,SP_SP, // 0-7 - SP_MAXSP,SP_STATUSPOINT,SP_0a,SP_BASELEVEL,SP_SKILLPOINT,SP_STR,SP_AGI,SP_VIT, // 8-15 - SP_INT,SP_DEX,SP_LUK,SP_CLASS,SP_ZENY,SP_SEX,SP_NEXTBASEEXP,SP_NEXTJOBEXP, // 16-23 - SP_WEIGHT,SP_MAXWEIGHT,SP_1a,SP_1b,SP_1c,SP_1d,SP_1e,SP_1f, // 24-31 - 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-60 - SP_CARTINFO=99, // 99 - - SP_BASEJOB=119, // 100+19 - celest - SP_BASECLASS=120, //Hmm.. why 100+19? I just use the next one... [Skotlex] - SP_KILLERRID=121, - SP_KILLEDRID=122, - - // Mercenaries - SP_MERCFLEE=165, SP_MERCKILLS=189, SP_MERCFAITH=190, - - // original 1000- - SP_ATTACKRANGE=1000, SP_ATKELE,SP_DEFELE, // 1000-1002 - SP_CASTRATE, SP_MAXHPRATE, SP_MAXSPRATE, SP_SPRATE, // 1003-1006 - SP_ADDELE, SP_ADDRACE, SP_ADDSIZE, SP_SUBELE, SP_SUBRACE, // 1007-1011 - SP_ADDEFF, SP_RESEFF, // 1012-1013 - SP_BASE_ATK,SP_ASPD_RATE,SP_HP_RECOV_RATE,SP_SP_RECOV_RATE,SP_SPEED_RATE, // 1014-1018 - SP_CRITICAL_DEF,SP_NEAR_ATK_DEF,SP_LONG_ATK_DEF, // 1019-1021 - SP_DOUBLE_RATE, SP_DOUBLE_ADD_RATE, SP_SKILL_HEAL, SP_MATK_RATE, // 1022-1025 - SP_IGNORE_DEF_ELE,SP_IGNORE_DEF_RACE, // 1026-1027 - SP_ATK_RATE,SP_SPEED_ADDRATE,SP_SP_REGEN_RATE, // 1028-1030 - SP_MAGIC_ATK_DEF,SP_MISC_ATK_DEF, // 1031-1032 - SP_IGNORE_MDEF_ELE,SP_IGNORE_MDEF_RACE, // 1033-1034 - SP_MAGIC_ADDELE,SP_MAGIC_ADDRACE,SP_MAGIC_ADDSIZE, // 1035-1037 - SP_PERFECT_HIT_RATE,SP_PERFECT_HIT_ADD_RATE,SP_CRITICAL_RATE,SP_GET_ZENY_NUM,SP_ADD_GET_ZENY_NUM, // 1038-1042 - SP_ADD_DAMAGE_CLASS,SP_ADD_MAGIC_DAMAGE_CLASS,SP_ADD_DEF_CLASS,SP_ADD_MDEF_CLASS, // 1043-1046 - SP_ADD_MONSTER_DROP_ITEM,SP_DEF_RATIO_ATK_ELE,SP_DEF_RATIO_ATK_RACE,SP_UNBREAKABLE_GARMENT, // 1047-1050 - SP_HIT_RATE,SP_FLEE_RATE,SP_FLEE2_RATE,SP_DEF_RATE,SP_DEF2_RATE,SP_MDEF_RATE,SP_MDEF2_RATE, // 1051-1057 - SP_SPLASH_RANGE,SP_SPLASH_ADD_RANGE,SP_AUTOSPELL,SP_HP_DRAIN_RATE,SP_SP_DRAIN_RATE, // 1058-1062 - SP_SHORT_WEAPON_DAMAGE_RETURN,SP_LONG_WEAPON_DAMAGE_RETURN,SP_WEAPON_COMA_ELE,SP_WEAPON_COMA_RACE, // 1063-1066 - SP_ADDEFF2,SP_BREAK_WEAPON_RATE,SP_BREAK_ARMOR_RATE,SP_ADD_STEAL_RATE, // 1067-1070 - SP_MAGIC_DAMAGE_RETURN,SP_ALL_STATS=1073,SP_AGI_VIT,SP_AGI_DEX_STR,SP_PERFECT_HIDE, // 1071-1076 - SP_NO_KNOCKBACK,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,SP_HP_DRAIN_RATE_RACE,SP_SP_DRAIN_RATE_RACE, // 1083-1085 - SP_IGNORE_MDEF_RATE,SP_IGNORE_DEF_RATE,SP_SKILL_HEAL2,SP_ADDEFF_ONSKILL, //1086-1089 - SP_ADD_HEAL_RATE,SP_ADD_HEAL2_RATE, //1090-1091 - - SP_RESTART_FULL_RECOVER=2000,SP_NO_CASTCANCEL,SP_NO_SIZEFIX,SP_NO_MAGIC_DAMAGE,SP_NO_WEAPON_DAMAGE,SP_NO_GEMSTONE, // 2000-2005 - SP_NO_CASTCANCEL2,SP_NO_MISC_DAMAGE,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_AUTOSPELL_ONSKILL, // 2018-2020 - SP_SP_GAIN_VALUE, SP_HP_REGEN_RATE, SP_HP_LOSS_RATE, SP_ADDRACE2, SP_HP_GAIN_VALUE, // 2021-2025 - SP_SUBSIZE, SP_HP_DRAIN_VALUE_RACE, SP_ADD_ITEM_HEAL_RATE, SP_SP_DRAIN_VALUE_RACE, SP_EXP_ADDRACE, // 2026-2030 - SP_SP_GAIN_RACE, SP_SUBRACE2, SP_UNBREAKABLE_SHOES, // 2031-2033 - SP_UNSTRIPABLE_WEAPON,SP_UNSTRIPABLE_ARMOR,SP_UNSTRIPABLE_HELM,SP_UNSTRIPABLE_SHIELD, // 2034-2037 - SP_INTRAVISION, SP_ADD_MONSTER_DROP_ITEMGROUP, SP_SP_LOSS_RATE, // 2038-2040 - SP_ADD_SKILL_BLOW, SP_SP_VANISH_RATE, SP_MAGIC_SP_GAIN_VALUE, SP_MAGIC_HP_GAIN_VALUE, SP_ADD_CLASS_DROP_ITEM, //2041-2045 - SP_EMATK, SP_SP_GAIN_RACE_ATTACK, SP_HP_GAIN_RACE_ATTACK, SP_SKILL_USE_SP_RATE, //2046-2049 - SP_SKILL_COOLDOWN,SP_SKILL_FIXEDCAST, SP_SKILL_VARIABLECAST, SP_FIXCASTRATE, SP_VARCASTRATE, //2050-2054 - SP_SKILL_USE_SP //2055 + SP_SPEED,SP_BASEEXP,SP_JOBEXP,SP_KARMA,SP_MANNER,SP_HP,SP_MAXHP,SP_SP, // 0-7 + SP_MAXSP,SP_STATUSPOINT,SP_0a,SP_BASELEVEL,SP_SKILLPOINT,SP_STR,SP_AGI,SP_VIT, // 8-15 + SP_INT,SP_DEX,SP_LUK,SP_CLASS,SP_ZENY,SP_SEX,SP_NEXTBASEEXP,SP_NEXTJOBEXP, // 16-23 + SP_WEIGHT,SP_MAXWEIGHT,SP_1a,SP_1b,SP_1c,SP_1d,SP_1e,SP_1f, // 24-31 + 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-60 + SP_CARTINFO=99, // 99 + + SP_BASEJOB=119, // 100+19 - celest + SP_BASECLASS=120, //Hmm.. why 100+19? I just use the next one... [Skotlex] + SP_KILLERRID=121, + SP_KILLEDRID=122, + + // Mercenaries + SP_MERCFLEE=165, SP_MERCKILLS=189, SP_MERCFAITH=190, + + // original 1000- + SP_ATTACKRANGE=1000, SP_ATKELE,SP_DEFELE, // 1000-1002 + SP_CASTRATE, SP_MAXHPRATE, SP_MAXSPRATE, SP_SPRATE, // 1003-1006 + SP_ADDELE, SP_ADDRACE, SP_ADDSIZE, SP_SUBELE, SP_SUBRACE, // 1007-1011 + SP_ADDEFF, SP_RESEFF, // 1012-1013 + SP_BASE_ATK,SP_ASPD_RATE,SP_HP_RECOV_RATE,SP_SP_RECOV_RATE,SP_SPEED_RATE, // 1014-1018 + SP_CRITICAL_DEF,SP_NEAR_ATK_DEF,SP_LONG_ATK_DEF, // 1019-1021 + SP_DOUBLE_RATE, SP_DOUBLE_ADD_RATE, SP_SKILL_HEAL, SP_MATK_RATE, // 1022-1025 + SP_IGNORE_DEF_ELE,SP_IGNORE_DEF_RACE, // 1026-1027 + SP_ATK_RATE,SP_SPEED_ADDRATE,SP_SP_REGEN_RATE, // 1028-1030 + SP_MAGIC_ATK_DEF,SP_MISC_ATK_DEF, // 1031-1032 + SP_IGNORE_MDEF_ELE,SP_IGNORE_MDEF_RACE, // 1033-1034 + SP_MAGIC_ADDELE,SP_MAGIC_ADDRACE,SP_MAGIC_ADDSIZE, // 1035-1037 + SP_PERFECT_HIT_RATE,SP_PERFECT_HIT_ADD_RATE,SP_CRITICAL_RATE,SP_GET_ZENY_NUM,SP_ADD_GET_ZENY_NUM, // 1038-1042 + SP_ADD_DAMAGE_CLASS,SP_ADD_MAGIC_DAMAGE_CLASS,SP_ADD_DEF_CLASS,SP_ADD_MDEF_CLASS, // 1043-1046 + SP_ADD_MONSTER_DROP_ITEM,SP_DEF_RATIO_ATK_ELE,SP_DEF_RATIO_ATK_RACE,SP_UNBREAKABLE_GARMENT, // 1047-1050 + SP_HIT_RATE,SP_FLEE_RATE,SP_FLEE2_RATE,SP_DEF_RATE,SP_DEF2_RATE,SP_MDEF_RATE,SP_MDEF2_RATE, // 1051-1057 + SP_SPLASH_RANGE,SP_SPLASH_ADD_RANGE,SP_AUTOSPELL,SP_HP_DRAIN_RATE,SP_SP_DRAIN_RATE, // 1058-1062 + SP_SHORT_WEAPON_DAMAGE_RETURN,SP_LONG_WEAPON_DAMAGE_RETURN,SP_WEAPON_COMA_ELE,SP_WEAPON_COMA_RACE, // 1063-1066 + SP_ADDEFF2,SP_BREAK_WEAPON_RATE,SP_BREAK_ARMOR_RATE,SP_ADD_STEAL_RATE, // 1067-1070 + SP_MAGIC_DAMAGE_RETURN,SP_ALL_STATS=1073,SP_AGI_VIT,SP_AGI_DEX_STR,SP_PERFECT_HIDE, // 1071-1076 + SP_NO_KNOCKBACK,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,SP_HP_DRAIN_RATE_RACE,SP_SP_DRAIN_RATE_RACE, // 1083-1085 + SP_IGNORE_MDEF_RATE,SP_IGNORE_DEF_RATE,SP_SKILL_HEAL2,SP_ADDEFF_ONSKILL, //1086-1089 + SP_ADD_HEAL_RATE,SP_ADD_HEAL2_RATE, //1090-1091 + + SP_RESTART_FULL_RECOVER=2000,SP_NO_CASTCANCEL,SP_NO_SIZEFIX,SP_NO_MAGIC_DAMAGE,SP_NO_WEAPON_DAMAGE,SP_NO_GEMSTONE, // 2000-2005 + SP_NO_CASTCANCEL2,SP_NO_MISC_DAMAGE,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_AUTOSPELL_ONSKILL, // 2018-2020 + SP_SP_GAIN_VALUE, SP_HP_REGEN_RATE, SP_HP_LOSS_RATE, SP_ADDRACE2, SP_HP_GAIN_VALUE, // 2021-2025 + SP_SUBSIZE, SP_HP_DRAIN_VALUE_RACE, SP_ADD_ITEM_HEAL_RATE, SP_SP_DRAIN_VALUE_RACE, SP_EXP_ADDRACE, // 2026-2030 + SP_SP_GAIN_RACE, SP_SUBRACE2, SP_UNBREAKABLE_SHOES, // 2031-2033 + SP_UNSTRIPABLE_WEAPON,SP_UNSTRIPABLE_ARMOR,SP_UNSTRIPABLE_HELM,SP_UNSTRIPABLE_SHIELD, // 2034-2037 + SP_INTRAVISION, SP_ADD_MONSTER_DROP_ITEMGROUP, SP_SP_LOSS_RATE, // 2038-2040 + SP_ADD_SKILL_BLOW, SP_SP_VANISH_RATE, SP_MAGIC_SP_GAIN_VALUE, SP_MAGIC_HP_GAIN_VALUE, SP_ADD_CLASS_DROP_ITEM, //2041-2045 + SP_WEAPON_MATK, SP_BASE_MATK, SP_SP_GAIN_RACE_ATTACK, SP_HP_GAIN_RACE_ATTACK, SP_SKILL_USE_SP_RATE, //2046-2050 + SP_SKILL_COOLDOWN,SP_SKILL_FIXEDCAST, SP_SKILL_VARIABLECAST, SP_FIXCASTRATE, SP_VARCASTRATE, //2051-2055 + SP_SKILL_USE_SP //2056 }; enum _look { - 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, - LOOK_BODY, - LOOK_FLOOR, - LOOK_ROBE, + 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, + LOOK_BODY, + LOOK_FLOOR, + LOOK_ROBE, }; // used by map_setcell() typedef enum { - CELL_WALKABLE, - CELL_SHOOTABLE, - CELL_WATER, - - CELL_NPC, - CELL_BASILICA, - CELL_LANDPROTECTOR, - CELL_NOVENDING, - CELL_NOCHAT, - CELL_MAELSTROM, - CELL_ICEWALL, + CELL_WALKABLE, + CELL_SHOOTABLE, + CELL_WATER, + + CELL_NPC, + CELL_BASILICA, + CELL_LANDPROTECTOR, + CELL_NOVENDING, + CELL_NOCHAT, + CELL_MAELSTROM, + CELL_ICEWALL, } cell_t; // used by map_getcell() typedef enum { - CELL_GETTYPE, // retrieves a cell's 'gat' type - - CELL_CHKWALL, // wall (gat type 1) - CELL_CHKWATER, // water (gat type 3) - CELL_CHKCLIFF, // cliff/gap (gat type 5) - - CELL_CHKPASS, // passable cell (gat type non-1/5) - CELL_CHKREACH, // Same as PASS, but ignores the cell-stacking mod. - CELL_CHKNOPASS, // non-passable cell (gat types 1 and 5) - CELL_CHKNOREACH, // Same as NOPASS, but ignores the cell-stacking mod. - CELL_CHKSTACK, // whether cell is full (reached cell stacking limit) - - CELL_CHKNPC, - CELL_CHKBASILICA, - CELL_CHKLANDPROTECTOR, - CELL_CHKNOVENDING, - CELL_CHKNOCHAT, - CELL_CHKMAELSTROM, - CELL_CHKICEWALL, + CELL_GETTYPE, // retrieves a cell's 'gat' type + + CELL_CHKWALL, // wall (gat type 1) + CELL_CHKWATER, // water (gat type 3) + CELL_CHKCLIFF, // cliff/gap (gat type 5) + + CELL_CHKPASS, // passable cell (gat type non-1/5) + CELL_CHKREACH, // Same as PASS, but ignores the cell-stacking mod. + CELL_CHKNOPASS, // non-passable cell (gat types 1 and 5) + CELL_CHKNOREACH, // Same as NOPASS, but ignores the cell-stacking mod. + CELL_CHKSTACK, // whether cell is full (reached cell stacking limit) + + CELL_CHKNPC, + CELL_CHKBASILICA, + CELL_CHKLANDPROTECTOR, + CELL_CHKNOVENDING, + CELL_CHKNOCHAT, + CELL_CHKMAELSTROM, + CELL_CHKICEWALL, } cell_chk; -struct mapcell { - // terrain flags - unsigned char - walkable : 1, - shootable : 1, - water : 1; - - // dynamic flags - unsigned char - npc : 1, - basilica : 1, - landprotector : 1, - novending : 1, - nochat : 1, - maelstrom : 1, - icewall : 1; +struct mapcell +{ + // terrain flags + unsigned char + walkable : 1, + shootable : 1, + water : 1; + + // dynamic flags + unsigned char + npc : 1, + basilica : 1, + landprotector : 1, + novending : 1, + nochat : 1, + maelstrom : 1, + icewall : 1; #ifdef CELL_NOSTACK - unsigned char cell_bl; //Holds amount of bls in this cell. + unsigned char cell_bl; //Holds amount of bls in this cell. #endif }; struct iwall_data { - char wall_name[50]; - short m, x, y, size, dir; - bool shootable; + char wall_name[50]; + short m, x, y, size, dir; + bool shootable; }; struct map_data { - char name[MAP_NAME_LENGTH]; - unsigned short index; // The map index used by the mapindex* functions. - struct mapcell *cell; // Holds the information of each map cell (NULL if the map is not on this map-server). - struct block_list **block; - struct block_list **block_mob; - int m; - short xs,ys; // map dimensions (in cells) - short bxs,bys; // map dimensions (in blocks) - short bgscore_lion, bgscore_eagle; // Battleground ScoreBoard - int npc_num; - int users; - int users_pvp; - int iwall_num; // Total of invisible walls in this map - struct map_flag { - unsigned town : 1; // [Suggestion to protect Mail System] - unsigned autotrade : 1; - unsigned allowks : 1; // [Kill Steal Protection] - unsigned nomemo : 1; - unsigned noteleport : 1; - unsigned noreturn : 1; - unsigned monster_noteleport : 1; - unsigned nosave : 1; - unsigned nobranch : 1; - unsigned noexppenalty : 1; - unsigned pvp : 1; - unsigned pvp_noparty : 1; - unsigned pvp_noguild : 1; - unsigned pvp_nightmaredrop :1; - unsigned pvp_nocalcrank : 1; - unsigned gvg_castle : 1; - unsigned gvg : 1; // Now it identifies gvg versus maps that are active 24/7 - unsigned gvg_dungeon : 1; // Celest - unsigned gvg_noparty : 1; - unsigned battleground : 2; // [BattleGround System] - unsigned nozenypenalty : 1; - unsigned notrade : 1; - unsigned noskill : 1; - unsigned nowarp : 1; - unsigned nowarpto : 1; - unsigned noicewall : 1; // [Valaris] - unsigned snow : 1; // [Valaris] - unsigned clouds : 1; - unsigned clouds2 : 1; // [Valaris] - unsigned fog : 1; // [Valaris] - unsigned fireworks : 1; - unsigned sakura : 1; // [Valaris] - unsigned leaves : 1; // [Valaris] - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //unsigned rain : 1; // [Valaris] - unsigned nogo : 1; // [Valaris] - unsigned nobaseexp : 1; // [Lorky] added by Lupus - unsigned nojobexp : 1; // [Lorky] - unsigned nomobloot : 1; // [Lorky] - unsigned nomvploot : 1; // [Lorky] - unsigned nightenabled :1; //For night display. [Skotlex] - unsigned restricted : 1; // [Komurka] - unsigned nodrop : 1; - unsigned novending : 1; - unsigned loadevent : 1; - unsigned nochat :1; - unsigned partylock :1; - unsigned guildlock :1; - unsigned src4instance : 1; // To flag this map when it's used as a src map for instances - unsigned reset :1; // [Daegaladh] - } flag; - struct point save; - struct npc_data *npc[MAX_NPC_PER_MAP]; - struct { - int drop_id; - int drop_type; - int drop_per; - } drop_list[MAX_DROP_PER_MAP]; - - struct spawn_data *moblist[MAX_MOB_LIST_PER_MAP]; // [Wizputer] - int mob_delete_timer; // [Skotlex] - int zone; // zone number (for item/skill restrictions) - int jexp; // map experience multiplicator - int bexp; // map experience multiplicator - int nocommand; //Blocks @/# commands for non-gms. [Skotlex] - /** - * Ice wall reference counter for bugreport:3574 - * - since there are a thounsand mobs out there in a lot of maps checking on, - * - every targetting for icewall on attack path would just be a waste, so, - * - this counter allows icewall checking be only run when there is a actual ice wall on the map - **/ - int icewall_num; - // Instance Variables - int instance_id; - int instance_src_map; + char name[MAP_NAME_LENGTH]; + unsigned short index; // The map index used by the mapindex* functions. + struct mapcell* cell; // Holds the information of each map cell (NULL if the map is not on this map-server). + struct block_list **block; + struct block_list **block_mob; + int m; + short xs,ys; // map dimensions (in cells) + short bxs,bys; // map dimensions (in blocks) + short bgscore_lion, bgscore_eagle; // Battleground ScoreBoard + int npc_num; + int users; + int users_pvp; + int iwall_num; // Total of invisible walls in this map + struct map_flag { + unsigned town : 1; // [Suggestion to protect Mail System] + unsigned autotrade : 1; + unsigned allowks : 1; // [Kill Steal Protection] + unsigned nomemo : 1; + unsigned noteleport : 1; + unsigned noreturn : 1; + unsigned monster_noteleport : 1; + unsigned nosave : 1; + unsigned nobranch : 1; + unsigned noexppenalty : 1; + unsigned pvp : 1; + unsigned pvp_noparty : 1; + unsigned pvp_noguild : 1; + unsigned pvp_nightmaredrop :1; + unsigned pvp_nocalcrank : 1; + unsigned gvg_castle : 1; + unsigned gvg : 1; // Now it identifies gvg versus maps that are active 24/7 + unsigned gvg_dungeon : 1; // Celest + unsigned gvg_noparty : 1; + unsigned battleground : 2; // [BattleGround System] + unsigned nozenypenalty : 1; + unsigned notrade : 1; + unsigned noskill : 1; + unsigned nowarp : 1; + unsigned nowarpto : 1; + unsigned noicewall : 1; // [Valaris] + unsigned snow : 1; // [Valaris] + unsigned clouds : 1; + unsigned clouds2 : 1; // [Valaris] + unsigned fog : 1; // [Valaris] + unsigned fireworks : 1; + unsigned sakura : 1; // [Valaris] + unsigned leaves : 1; // [Valaris] + /** + * No longer available, keeping here just in case it's back someday. [Ind] + **/ + //unsigned rain : 1; // [Valaris] + unsigned nogo : 1; // [Valaris] + unsigned nobaseexp : 1; // [Lorky] added by Lupus + unsigned nojobexp : 1; // [Lorky] + unsigned nomobloot : 1; // [Lorky] + unsigned nomvploot : 1; // [Lorky] + unsigned nightenabled :1; //For night display. [Skotlex] + unsigned restricted : 1; // [Komurka] + unsigned nodrop : 1; + unsigned novending : 1; + unsigned loadevent : 1; + unsigned nochat :1; + unsigned partylock :1; + unsigned guildlock :1; + unsigned src4instance : 1; // To flag this map when it's used as a src map for instances + unsigned reset :1; // [Daegaladh] + } flag; + struct point save; + struct npc_data *npc[MAX_NPC_PER_MAP]; + struct { + int drop_id; + int drop_type; + int drop_per; + } drop_list[MAX_DROP_PER_MAP]; + + struct spawn_data *moblist[MAX_MOB_LIST_PER_MAP]; // [Wizputer] + int mob_delete_timer; // [Skotlex] + int zone; // zone number (for item/skill restrictions) + int jexp; // map experience multiplicator + int bexp; // map experience multiplicator + int nocommand; //Blocks @/# commands for non-gms. [Skotlex] + /** + * Ice wall reference counter for bugreport:3574 + * - since there are a thounsand mobs out there in a lot of maps checking on, + * - every targetting for icewall on attack path would just be a waste, so, + * - this counter allows icewall checking be only run when there is a actual ice wall on the map + **/ + int icewall_num; + // Instance Variables + int instance_id; + int instance_src_map; }; /// Stores information about a remote map (for multi-mapserver setups). /// Beginning of data structure matches 'map_data', to allow typecasting. struct map_data_other_server { - char name[MAP_NAME_LENGTH]; - unsigned short index; //Index is the map index used by the mapindex* functions. - struct mapcell *cell; // If this is NULL, the map is not on this map-server - uint32 ip; - uint16 port; + char name[MAP_NAME_LENGTH]; + unsigned short index; //Index is the map index used by the mapindex* functions. + struct mapcell* cell; // If this is NULL, the map is not on this map-server + uint32 ip; + uint16 port; }; int map_getcell(int,int,int,cell_chk); -int map_getcellp(struct map_data *,int,int,cell_chk); +int map_getcellp(struct map_data*,int,int,cell_chk); void map_setcell(int m, int x, int y, cell_t cell, bool flag); void map_setgatcell(int m, int x, int y, int gat); @@ -630,18 +632,18 @@ int map_freeblock(struct block_list *bl); int map_freeblock_lock(void); int map_freeblock_unlock(void); // blocklist manipulation -int map_addblock(struct block_list *bl); -int map_delblock(struct block_list *bl); +int map_addblock(struct block_list* bl); +int map_delblock(struct block_list* bl); int map_moveblock(struct block_list *, int, int, unsigned int); -int map_foreachinrange(int (*func)(struct block_list *,va_list), struct block_list *center, int range, int type, ...); -int map_foreachinshootrange(int (*func)(struct block_list *,va_list), struct block_list *center, int range, int type, ...); -int map_foreachinarea(int (*func)(struct block_list *,va_list), int m, int x0, int y0, int x1, int y1, int type, ...); -int map_forcountinrange(int (*func)(struct block_list *,va_list), struct block_list *center, int range, int count, int type, ...); -int map_forcountinarea(int (*func)(struct block_list *,va_list), int m, int x0, int y0, int x1, int y1, int count, int type, ...); -int map_foreachinmovearea(int (*func)(struct block_list *,va_list), struct block_list *center, int range, int dx, int dy, int type, ...); -int map_foreachincell(int (*func)(struct block_list *,va_list), int m, int x, int y, int type, ...); -int map_foreachinpath(int (*func)(struct block_list *,va_list), int m, int x0, int y0, int x1, int y1, int range, int length, int type, ...); -int map_foreachinmap(int (*func)(struct block_list *,va_list), int m, int type, ...); +int map_foreachinrange(int (*func)(struct block_list*,va_list), struct block_list* center, int range, int type, ...); +int map_foreachinshootrange(int (*func)(struct block_list*,va_list), struct block_list* center, int range, int type, ...); +int map_foreachinarea(int (*func)(struct block_list*,va_list), int m, int x0, int y0, int x1, int y1, int type, ...); +int map_forcountinrange(int (*func)(struct block_list*,va_list), struct block_list* center, int range, int count, int type, ...); +int map_forcountinarea(int (*func)(struct block_list*,va_list), int m, int x0, int y0, int x1, int y1, int count, int type, ...); +int map_foreachinmovearea(int (*func)(struct block_list*,va_list), struct block_list* center, int range, int dx, int dy, int type, ...); +int map_foreachincell(int (*func)(struct block_list*,va_list), int m, int x, int y, int type, ...); +int map_foreachinpath(int (*func)(struct block_list*,va_list), int m, int x0, int y0, int x1, int y1, int range, int length, int type, ...); +int map_foreachinmap(int (*func)(struct block_list*,va_list), int m, int type, ...); //blocklist nb in one cell int map_count_oncell(int m,int x,int y,int type); struct skill_unit *map_find_skill_unit_oncell(struct block_list *,int x,int y,int skill_id,struct skill_unit *, int flag); @@ -656,59 +658,60 @@ bool map_addnpc(int,struct npc_data *); // map item int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data); int map_removemobs_timer(int tid, unsigned int tick, int id, intptr_t data); -void map_clearflooritem(struct block_list *bl); +void map_clearflooritem(struct block_list* bl); int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,int first_charid,int second_charid,int third_charid,int flags); // player to map session -void map_addnickdb(int charid, const char *nick); -void map_delnickdb(int charid, const char *nick); -void map_reqnickdb(struct map_session_data *sd,int charid); -const char *map_charid2nick(int charid); -struct map_session_data *map_charid2sd(int charid); - -struct map_session_data *map_id2sd(int id); -struct mob_data *map_id2md(int id); -struct npc_data *map_id2nd(int id); -struct homun_data *map_id2hd(int id); -struct mercenary_data *map_id2mc(int id); -struct chat_data *map_id2cd(int id); -struct block_list *map_id2bl(int id); -bool map_blid_exists(int id); +void map_addnickdb(int charid, const char* nick); +void map_delnickdb(int charid, const char* nick); +void map_reqnickdb(struct map_session_data* sd,int charid); +const char* map_charid2nick(int charid); +struct map_session_data* map_charid2sd(int charid); + +struct map_session_data * map_id2sd(int id); +struct mob_data * map_id2md(int id); +struct npc_data * map_id2nd(int id); +struct homun_data* map_id2hd(int id); +struct mercenary_data* map_id2mc(int id); +struct chat_data* map_id2cd(int id); +struct block_list * map_id2bl(int id); +bool map_blid_exists( int id ); #define map_id2index(id) map[(id)].index int map_mapindex2mapid(unsigned short mapindex); -int map_mapname2mapid(const char *name); -int map_mapname2ipport(unsigned short name, uint32 *ip, uint16 *port); +int map_mapname2mapid(const char* name); +int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port); int map_setipport(unsigned short map, uint32 ip, uint16 port); int map_eraseipport(unsigned short map, uint32 ip, uint16 port); int map_eraseallipport(void); void map_addiddb(struct block_list *); void map_deliddb(struct block_list *bl); -void map_foreachpc(int (*func)(struct map_session_data *sd, va_list args), ...); -void map_foreachmob(int (*func)(struct mob_data *md, va_list args), ...); -void map_foreachnpc(int (*func)(struct npc_data *nd, va_list args), ...); -void map_foreachregen(int (*func)(struct block_list *bl, va_list args), ...); -void map_foreachiddb(int (*func)(struct block_list *bl, va_list args), ...); -struct map_session_data *map_nick2sd(const char *); -struct mob_data *map_getmob_boss(int m); -struct mob_data *map_id2boss(int id); +void map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...); +void map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...); +void map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...); +void map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...); +void map_foreachiddb(int (*func)(struct block_list* bl, va_list args), ...); +struct map_session_data * map_nick2sd(const char*); +struct mob_data * map_getmob_boss(int m); +struct mob_data * map_id2boss(int id); // reload config file looking only for npcs void map_reloadnpc(bool clear); /// Bitfield of flags for the iterator. -enum e_mapitflags { - MAPIT_NORMAL = 0, - // MAPIT_PCISPLAYING = 1,// Unneeded as pc_db/id_db will only hold auth'ed, active players. +enum e_mapitflags +{ + MAPIT_NORMAL = 0, +// MAPIT_PCISPLAYING = 1,// Unneeded as pc_db/id_db will only hold auth'ed, active players. }; struct s_mapiterator; -struct s_mapiterator *mapit_alloc(enum e_mapitflags flags, enum bl_type types); -void mapit_free(struct s_mapiterator *mapit); -struct block_list *mapit_first(struct s_mapiterator *mapit); -struct block_list *mapit_last(struct s_mapiterator *mapit); -struct block_list *mapit_next(struct s_mapiterator *mapit); -struct block_list *mapit_prev(struct s_mapiterator *mapit); -bool mapit_exists(struct s_mapiterator *mapit); +struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types); +void mapit_free(struct s_mapiterator* mapit); +struct block_list* mapit_first(struct s_mapiterator* mapit); +struct block_list* mapit_last(struct s_mapiterator* mapit); +struct block_list* mapit_next(struct s_mapiterator* mapit); +struct block_list* mapit_prev(struct s_mapiterator* mapit); +bool mapit_exists(struct s_mapiterator* mapit); #define mapit_getallusers() mapit_alloc(MAPIT_NORMAL,BL_PC) #define mapit_geteachpc() mapit_alloc(MAPIT_NORMAL,BL_PC) #define mapit_geteachmob() mapit_alloc(MAPIT_NORMAL,BL_MOB) @@ -716,19 +719,19 @@ bool mapit_exists(struct s_mapiterator *mapit); #define mapit_geteachiddb() mapit_alloc(MAPIT_NORMAL,BL_ALL) int map_check_dir(int s_dir,int t_dir); -unsigned char map_calc_dir(struct block_list *src,int x,int y); +unsigned char map_calc_dir( struct block_list *src,int x,int y); int map_random_dir(struct block_list *bl, short *x, short *y); // [Skotlex] int cleanup_sub(struct block_list *bl, va_list ap); -int map_delmap(char *mapname); +int map_delmap(char* mapname); void map_flags_init(void); -bool map_iwall_set(int m, int x, int y, int size, int dir, bool shootable, const char *wall_name); +bool map_iwall_set(int m, int x, int y, int size, int dir, bool shootable, const char* wall_name); void map_iwall_get(struct map_session_data *sd); void map_iwall_remove(const char *wall_name); -int map_addmobtolist(unsigned short m, struct spawn_data *spawn); // [Wizputer] +int map_addmobtolist(unsigned short m, struct spawn_data *spawn); // [Wizputer] void map_spawnmobs(int); // [Wizputer] void map_removemobs(int); // [Wizputer] void do_reconnect_map(void); //Invoked on map-char reconnection [Skotlex] @@ -754,10 +757,10 @@ typedef struct skill_unit TBL_SKILL; typedef struct pet_data TBL_PET; typedef struct homun_data TBL_HOM; typedef struct mercenary_data TBL_MER; -typedef struct elemental_data TBL_ELEM; +typedef struct elemental_data TBL_ELEM; #define BL_CAST(type_, bl) \ - ( ((bl) == (struct block_list*)NULL || (bl)->type != (type_)) ? (T ## type_ *)NULL : (T ## type_ *)(bl) ) + ( ((bl) == (struct block_list*)NULL || (bl)->type != (type_)) ? (T ## type_ *)NULL : (T ## type_ *)(bl) ) extern char main_chat_nick[16]; @@ -783,8 +786,8 @@ extern char log_db_db[32]; extern int db_use_sqldbs; -extern Sql *mmysql_handle; -extern Sql *logmysql_handle; +extern Sql* mmysql_handle; +extern Sql* logmysql_handle; extern char item_db_db[32]; extern char item_db2_db[32]; diff --git a/src/map/mapreg.h b/src/map/mapreg.h index 2d761cbbb..d5fadafc5 100644 --- a/src/map/mapreg.h +++ b/src/map/mapreg.h @@ -7,11 +7,11 @@ void mapreg_reload(void); void mapreg_final(void); void mapreg_init(void); -bool mapreg_config_read(const char *w1, const char *w2); +bool mapreg_config_read(const char* w1, const char* w2); int mapreg_readreg(int uid); -char *mapreg_readregstr(int uid); +char* mapreg_readregstr(int uid); bool mapreg_setreg(int uid, int val); -bool mapreg_setregstr(int uid, const char *str); +bool mapreg_setregstr(int uid, const char* str); #endif /* _MAPREG_H_ */ diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index 4fa943b2e..7782f7f02 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -13,8 +13,8 @@ #include <stdlib.h> #include <string.h> -static DBMap *mapreg_db = NULL; // int var_id -> int value -static DBMap *mapregstr_db = NULL; // int var_id -> char* value +static DBMap* mapreg_db = NULL; // int var_id -> int value +static DBMap* mapregstr_db = NULL; // int var_id -> char* value static char mapreg_table[32] = "mapreg"; static bool mapreg_dirty = false; @@ -24,203 +24,212 @@ static bool mapreg_dirty = false; /// Looks up the value of an integer variable using its uid. int mapreg_readreg(int uid) { - return idb_iget(mapreg_db, uid); + return idb_iget(mapreg_db, uid); } /// Looks up the value of a string variable using its uid. -char *mapreg_readregstr(int uid) +char* mapreg_readregstr(int uid) { - return idb_get(mapregstr_db, uid); + return idb_get(mapregstr_db, uid); } /// Modifies the value of an integer variable. bool mapreg_setreg(int uid, int val) { - int num = (uid & 0x00ffffff); - int i = (uid & 0xff000000) >> 24; - const char *name = get_str(num); - - if (val != 0) { - if (idb_iput(mapreg_db,uid,val)) - mapreg_dirty = true; // already exists, delay write - else if (name[1] != '@') { - // write new variable to database - char tmp_str[32*2+1]; - Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); - if (SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%d')", mapreg_table, tmp_str, i, val)) - Sql_ShowDebug(mmysql_handle); - } - } else { // val == 0 - idb_remove(mapreg_db,uid); - - if (name[1] != '@') { - // Remove from database because it is unused. - if (SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i)) - Sql_ShowDebug(mmysql_handle); - } - } - - return true; + int num = (uid & 0x00ffffff); + int i = (uid & 0xff000000) >> 24; + const char* name = get_str(num); + + if( val != 0 ) + { + if( idb_iput(mapreg_db,uid,val) ) + mapreg_dirty = true; // already exists, delay write + else if(name[1] != '@') + {// write new variable to database + char tmp_str[32*2+1]; + Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); + if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%d')", mapreg_table, tmp_str, i, val) ) + Sql_ShowDebug(mmysql_handle); + } + } + else // val == 0 + { + idb_remove(mapreg_db,uid); + + if( name[1] != '@' ) + {// Remove from database because it is unused. + if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) ) + Sql_ShowDebug(mmysql_handle); + } + } + + return true; } /// Modifies the value of a string variable. -bool mapreg_setregstr(int uid, const char *str) +bool mapreg_setregstr(int uid, const char* str) { - int num = (uid & 0x00ffffff); - int i = (uid & 0xff000000) >> 24; - const char *name = get_str(num); - - if (str == NULL || *str == 0) { - if (name[1] != '@') { - if (SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i)) - Sql_ShowDebug(mmysql_handle); - } - idb_remove(mapregstr_db,uid); - } else { - if (idb_put(mapregstr_db,uid, aStrdup(str))) - mapreg_dirty = true; - else if (name[1] != '@') { //put returned null, so we must insert. - // Someone is causing a database size infinite increase here without name[1] != '@' [Lance] - char tmp_str[32*2+1]; - char tmp_str2[255*2+1]; - Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); - Sql_EscapeStringLen(mmysql_handle, tmp_str2, str, strnlen(str, 255)); - if (SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%s')", mapreg_table, tmp_str, i, tmp_str2)) - Sql_ShowDebug(mmysql_handle); - } - } - - return true; + int num = (uid & 0x00ffffff); + int i = (uid & 0xff000000) >> 24; + const char* name = get_str(num); + + if( str == NULL || *str == 0 ) + { + if(name[1] != '@') { + if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) ) + Sql_ShowDebug(mmysql_handle); + } + idb_remove(mapregstr_db,uid); + } + else + { + if (idb_put(mapregstr_db,uid, aStrdup(str))) + mapreg_dirty = true; + else if(name[1] != '@') { //put returned null, so we must insert. + // Someone is causing a database size infinite increase here without name[1] != '@' [Lance] + char tmp_str[32*2+1]; + char tmp_str2[255*2+1]; + Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); + Sql_EscapeStringLen(mmysql_handle, tmp_str2, str, strnlen(str, 255)); + if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%s')", mapreg_table, tmp_str, i, tmp_str2) ) + Sql_ShowDebug(mmysql_handle); + } + } + + return true; } /// Loads permanent variables from database static void script_load_mapreg(void) { - /* - 0 1 2 - +-------------------------+ - | varname | index | value | - +-------------------------+ - */ - SqlStmt *stmt = SqlStmt_Malloc(mmysql_handle); - char varname[32+1]; - int index; - char value[255+1]; - uint32 length; - - if (SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `varname`, `index`, `value` FROM `%s`", mapreg_table) - || SQL_ERROR == SqlStmt_Execute(stmt) - ) { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - return; - } - - SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &varname[0], sizeof(varname), &length, NULL); - SqlStmt_BindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL); - SqlStmt_BindColumn(stmt, 2, SQLDT_STRING, &value[0], sizeof(value), NULL, NULL); - - while (SQL_SUCCESS == SqlStmt_NextRow(stmt)) { - int s = add_str(varname); - int i = index; - - if (varname[length-1] == '$') - idb_put(mapregstr_db, (i<<24)|s, aStrdup(value)); - else - idb_iput(mapreg_db, (i<<24)|s, atoi(value)); - } - - SqlStmt_Free(stmt); - - mapreg_dirty = false; + /* + 0 1 2 + +-------------------------+ + | varname | index | value | + +-------------------------+ + */ + SqlStmt* stmt = SqlStmt_Malloc(mmysql_handle); + char varname[32+1]; + int index; + char value[255+1]; + uint32 length; + + if ( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `varname`, `index`, `value` FROM `%s`", mapreg_table) + || SQL_ERROR == SqlStmt_Execute(stmt) + ) { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return; + } + + SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &varname[0], sizeof(varname), &length, NULL); + SqlStmt_BindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 2, SQLDT_STRING, &value[0], sizeof(value), NULL, NULL); + + while ( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) + { + int s = add_str(varname); + int i = index; + + if( varname[length-1] == '$' ) + idb_put(mapregstr_db, (i<<24)|s, aStrdup(value)); + else + idb_iput(mapreg_db, (i<<24)|s, atoi(value)); + } + + SqlStmt_Free(stmt); + + mapreg_dirty = false; } /// Saves permanent variables to database static void script_save_mapreg(void) { - DBIterator *iter; - DBData *data; - DBKey key; - - iter = db_iterator(mapreg_db); - for (data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key)) { - int num = (key.i & 0x00ffffff); - int i = (key.i & 0xff000000) >> 24; - const char *name = get_str(num); - - if (name[1] == '@') - continue; - - if (SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d'", mapreg_table, db_data2i(data), name, i)) - Sql_ShowDebug(mmysql_handle); - } - dbi_destroy(iter); - - iter = db_iterator(mapregstr_db); - for (data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key)) { - int num = (key.i & 0x00ffffff); - int i = (key.i & 0xff000000) >> 24; - const char *name = get_str(num); - char tmp_str2[2*255+1]; - - if (name[1] == '@') - continue; - - Sql_EscapeStringLen(mmysql_handle, tmp_str2, db_data2ptr(data), safestrnlen(db_data2ptr(data), 255)); - if (SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d'", mapreg_table, tmp_str2, name, i)) - Sql_ShowDebug(mmysql_handle); - } - dbi_destroy(iter); - - mapreg_dirty = false; + DBIterator* iter; + DBData *data; + DBKey key; + + iter = db_iterator(mapreg_db); + for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) + { + int num = (key.i & 0x00ffffff); + int i = (key.i & 0xff000000) >> 24; + const char* name = get_str(num); + + if( name[1] == '@' ) + continue; + + if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d'", mapreg_table, db_data2i(data), name, i) ) + Sql_ShowDebug(mmysql_handle); + } + dbi_destroy(iter); + + iter = db_iterator(mapregstr_db); + for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) + { + int num = (key.i & 0x00ffffff); + int i = (key.i & 0xff000000) >> 24; + const char* name = get_str(num); + char tmp_str2[2*255+1]; + + if( name[1] == '@' ) + continue; + + Sql_EscapeStringLen(mmysql_handle, tmp_str2, db_data2ptr(data), safestrnlen(db_data2ptr(data), 255)); + if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d'", mapreg_table, tmp_str2, name, i) ) + Sql_ShowDebug(mmysql_handle); + } + dbi_destroy(iter); + + mapreg_dirty = false; } static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data) { - if (mapreg_dirty) - script_save_mapreg(); + if( mapreg_dirty ) + script_save_mapreg(); - return 0; + return 0; } void mapreg_reload(void) { - if (mapreg_dirty) - script_save_mapreg(); + if( mapreg_dirty ) + script_save_mapreg(); - db_clear(mapreg_db); - db_clear(mapregstr_db); + db_clear(mapreg_db); + db_clear(mapregstr_db); - script_load_mapreg(); + script_load_mapreg(); } void mapreg_final(void) { - if (mapreg_dirty) - script_save_mapreg(); + if( mapreg_dirty ) + script_save_mapreg(); - db_destroy(mapreg_db); - db_destroy(mapregstr_db); + db_destroy(mapreg_db); + db_destroy(mapregstr_db); } void mapreg_init(void) { - mapreg_db = idb_alloc(DB_OPT_BASE); - mapregstr_db = idb_alloc(DB_OPT_RELEASE_DATA); + mapreg_db = idb_alloc(DB_OPT_BASE); + mapregstr_db = idb_alloc(DB_OPT_RELEASE_DATA); - script_load_mapreg(); + script_load_mapreg(); - add_timer_func_list(script_autosave_mapreg, "script_autosave_mapreg"); - add_timer_interval(gettick() + MAPREG_AUTOSAVE_INTERVAL, script_autosave_mapreg, 0, 0, MAPREG_AUTOSAVE_INTERVAL); + add_timer_func_list(script_autosave_mapreg, "script_autosave_mapreg"); + add_timer_interval(gettick() + MAPREG_AUTOSAVE_INTERVAL, script_autosave_mapreg, 0, 0, MAPREG_AUTOSAVE_INTERVAL); } -bool mapreg_config_read(const char *w1, const char *w2) +bool mapreg_config_read(const char* w1, const char* w2) { - if (!strcmpi(w1, "mapreg_db")) - safestrncpy(mapreg_table, w2, sizeof(mapreg_table)); - else - return false; + if(!strcmpi(w1, "mapreg_db")) + safestrncpy(mapreg_table, w2, sizeof(mapreg_table)); + else + return false; - return true; + return true; } diff --git a/src/map/mercenary.c b/src/map/mercenary.c index d2945886a..832cc835b 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -42,461 +42,469 @@ struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS]; // Mercenary Database int merc_search_index(int class_) { - int i; - ARR_FIND(0, MAX_MERCENARY_CLASS, i, mercenary_db[i].class_ == class_); - return (i == MAX_MERCENARY_CLASS)?-1:i; + int i; + ARR_FIND(0, MAX_MERCENARY_CLASS, i, mercenary_db[i].class_ == class_); + return (i == MAX_MERCENARY_CLASS)?-1:i; } bool merc_class(int class_) { - return (bool)(merc_search_index(class_) > -1); + return (bool)(merc_search_index(class_) > -1); } -struct view_data *merc_get_viewdata(int class_) { - int i = merc_search_index(class_); - if (i < 0) - return 0; +struct view_data * merc_get_viewdata(int class_) +{ + int i = merc_search_index(class_); + if( i < 0 ) + return 0; - return &mercenary_db[i].vd; + return &mercenary_db[i].vd; } int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime) { - struct s_mercenary merc; - struct s_mercenary_db *db; - int i; - nullpo_retr(0,sd); + struct s_mercenary merc; + struct s_mercenary_db *db; + int i; + nullpo_retr(0,sd); - if ((i = merc_search_index(class_)) < 0) - return 0; + if( (i = merc_search_index(class_)) < 0 ) + return 0; - db = &mercenary_db[i]; - memset(&merc,0,sizeof(struct s_mercenary)); + db = &mercenary_db[i]; + memset(&merc,0,sizeof(struct s_mercenary)); - merc.char_id = sd->status.char_id; - merc.class_ = class_; - merc.hp = db->status.max_hp; - merc.sp = db->status.max_sp; - merc.life_time = lifetime; + merc.char_id = sd->status.char_id; + merc.class_ = class_; + merc.hp = db->status.max_hp; + merc.sp = db->status.max_sp; + merc.life_time = lifetime; - // Request Char Server to create this mercenary - intif_mercenary_create(&merc); + // Request Char Server to create this mercenary + intif_mercenary_create(&merc); - return 1; + return 1; } int mercenary_get_lifetime(struct mercenary_data *md) { - const struct TimerData *td; - if (md == NULL || md->contract_timer == INVALID_TIMER) - return 0; + const struct TimerData * td; + if( md == NULL || md->contract_timer == INVALID_TIMER ) + return 0; - td = get_timer(md->contract_timer); - return (td != NULL) ? DIFF_TICK(td->tick, gettick()) : 0; + td = get_timer(md->contract_timer); + return (td != NULL) ? DIFF_TICK(td->tick, gettick()) : 0; } int mercenary_get_guild(struct mercenary_data *md) { - int class_; + int class_; - if (md == NULL || md->db == NULL) - return -1; + if( md == NULL || md->db == NULL ) + return -1; - class_ = md->db->class_; + class_ = md->db->class_; - if (class_ >= 6017 && class_ <= 6026) - return ARCH_MERC_GUILD; - if (class_ >= 6027 && class_ <= 6036) - return SPEAR_MERC_GUILD; - if (class_ >= 6037 && class_ <= 6046) - return SWORD_MERC_GUILD; + if( class_ >= 6017 && class_ <= 6026 ) + return ARCH_MERC_GUILD; + if( class_ >= 6027 && class_ <= 6036 ) + return SPEAR_MERC_GUILD; + if( class_ >= 6037 && class_ <= 6046 ) + return SWORD_MERC_GUILD; - return -1; + return -1; } int mercenary_get_faith(struct mercenary_data *md) { - struct map_session_data *sd; - int class_; + struct map_session_data *sd; + int class_; - if (md == NULL || md->db == NULL || (sd = md->master) == NULL) - return 0; + if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) + return 0; - class_ = md->db->class_; + class_ = md->db->class_; - if (class_ >= 6017 && class_ <= 6026) - return sd->status.arch_faith; - if (class_ >= 6027 && class_ <= 6036) - return sd->status.spear_faith; - if (class_ >= 6037 && class_ <= 6046) - return sd->status.sword_faith; + if( class_ >= 6017 && class_ <= 6026 ) + return sd->status.arch_faith; + if( class_ >= 6027 && class_ <= 6036 ) + return sd->status.spear_faith; + if( class_ >= 6037 && class_ <= 6046 ) + return sd->status.sword_faith; - return 0; + return 0; } int mercenary_set_faith(struct mercenary_data *md, int value) { - struct map_session_data *sd; - int class_, *faith; + struct map_session_data *sd; + int class_, *faith; - if (md == NULL || md->db == NULL || (sd = md->master) == NULL) - return 0; + if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) + return 0; - class_ = md->db->class_; + class_ = md->db->class_; - if (class_ >= 6017 && class_ <= 6026) - faith = &sd->status.arch_faith; - else if (class_ >= 6027 && class_ <= 6036) - faith = &sd->status.spear_faith; - else if (class_ >= 6037 && class_ <= 6046) - faith = &sd->status.sword_faith; - else - return 0; + if( class_ >= 6017 && class_ <= 6026 ) + faith = &sd->status.arch_faith; + else if( class_ >= 6027 && class_ <= 6036 ) + faith = &sd->status.spear_faith; + else if( class_ >= 6037 && class_ <= 6046 ) + faith = &sd->status.sword_faith; + else + return 0; - *faith += value; - *faith = cap_value(*faith, 0, SHRT_MAX); - clif_mercenary_updatestatus(sd, SP_MERCFAITH); + *faith += value; + *faith = cap_value(*faith, 0, SHRT_MAX); + clif_mercenary_updatestatus(sd, SP_MERCFAITH); - return 0; + return 0; } int mercenary_get_calls(struct mercenary_data *md) { - struct map_session_data *sd; - int class_; + struct map_session_data *sd; + int class_; - if (md == NULL || md->db == NULL || (sd = md->master) == NULL) - return 0; + if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) + return 0; - class_ = md->db->class_; + class_ = md->db->class_; - if (class_ >= 6017 && class_ <= 6026) - return sd->status.arch_calls; - if (class_ >= 6027 && class_ <= 6036) - return sd->status.spear_calls; - if (class_ >= 6037 && class_ <= 6046) - return sd->status.sword_calls; + if( class_ >= 6017 && class_ <= 6026 ) + return sd->status.arch_calls; + if( class_ >= 6027 && class_ <= 6036 ) + return sd->status.spear_calls; + if( class_ >= 6037 && class_ <= 6046 ) + return sd->status.sword_calls; - return 0; + return 0; } int mercenary_set_calls(struct mercenary_data *md, int value) { - struct map_session_data *sd; - int class_, *calls; + struct map_session_data *sd; + int class_, *calls; - if (md == NULL || md->db == NULL || (sd = md->master) == NULL) - return 0; + if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) + return 0; - class_ = md->db->class_; + class_ = md->db->class_; - if (class_ >= 6017 && class_ <= 6026) - calls = &sd->status.arch_calls; - else if (class_ >= 6027 && class_ <= 6036) - calls = &sd->status.spear_calls; - else if (class_ >= 6037 && class_ <= 6046) - calls = &sd->status.sword_calls; - else - return 0; + if( class_ >= 6017 && class_ <= 6026 ) + calls = &sd->status.arch_calls; + else if( class_ >= 6027 && class_ <= 6036 ) + calls = &sd->status.spear_calls; + else if( class_ >= 6037 && class_ <= 6046 ) + calls = &sd->status.sword_calls; + else + return 0; - *calls += value; - *calls = cap_value(*calls, 0, INT_MAX); + *calls += value; + *calls = cap_value(*calls, 0, INT_MAX); - return 0; + return 0; } int mercenary_save(struct mercenary_data *md) { - md->mercenary.hp = md->battle_status.hp; - md->mercenary.sp = md->battle_status.sp; - md->mercenary.life_time = mercenary_get_lifetime(md); + md->mercenary.hp = md->battle_status.hp; + md->mercenary.sp = md->battle_status.sp; + md->mercenary.life_time = mercenary_get_lifetime(md); - intif_mercenary_save(&md->mercenary); - return 1; + intif_mercenary_save(&md->mercenary); + return 1; } static int merc_contract_end(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd; - struct mercenary_data *md; + struct map_session_data *sd; + struct mercenary_data *md; - if ((sd = map_id2sd(id)) == NULL) - return 1; - if ((md = sd->md) == NULL) - return 1; + if( (sd = map_id2sd(id)) == NULL ) + return 1; + if( (md = sd->md) == NULL ) + return 1; - if (md->contract_timer != tid) { - ShowError("merc_contract_end %d != %d.\n", md->contract_timer, tid); - return 0; - } + if( md->contract_timer != tid ) + { + ShowError("merc_contract_end %d != %d.\n", md->contract_timer, tid); + return 0; + } - md->contract_timer = INVALID_TIMER; - merc_delete(md, 0); // Mercenary soldier's duty hour is over. + md->contract_timer = INVALID_TIMER; + merc_delete(md, 0); // Mercenary soldier's duty hour is over. - return 0; + return 0; } int merc_delete(struct mercenary_data *md, int reply) { - struct map_session_data *sd = md->master; - md->mercenary.life_time = 0; - - merc_contract_stop(md); - - if (!sd) - return unit_free(&md->bl, CLR_OUTSIGHT); - - if (md->devotion_flag) { - md->devotion_flag = 0; - status_change_end(&sd->bl, SC_DEVOTION, INVALID_TIMER); - } - - switch (reply) { - case 0: - mercenary_set_faith(md, 1); - break; // +1 Loyalty on Contract ends. - case 1: - mercenary_set_faith(md, -1); - break; // -1 Loyalty on Mercenary killed - } - - clif_mercenary_message(sd, reply); - return unit_remove_map(&md->bl, CLR_OUTSIGHT); + struct map_session_data *sd = md->master; + md->mercenary.life_time = 0; + + merc_contract_stop(md); + + if( !sd ) + return unit_free(&md->bl, CLR_OUTSIGHT); + + if( md->devotion_flag ) + { + md->devotion_flag = 0; + status_change_end(&sd->bl, SC_DEVOTION, INVALID_TIMER); + } + + switch( reply ) + { + case 0: mercenary_set_faith(md, 1); break; // +1 Loyalty on Contract ends. + case 1: mercenary_set_faith(md, -1); break; // -1 Loyalty on Mercenary killed + } + + clif_mercenary_message(sd, reply); + return unit_remove_map(&md->bl, CLR_OUTSIGHT); } void merc_contract_stop(struct mercenary_data *md) { - nullpo_retv(md); - if (md->contract_timer != INVALID_TIMER) - delete_timer(md->contract_timer, merc_contract_end); - md->contract_timer = INVALID_TIMER; + nullpo_retv(md); + if( md->contract_timer != INVALID_TIMER ) + delete_timer(md->contract_timer, merc_contract_end); + md->contract_timer = INVALID_TIMER; } void merc_contract_init(struct mercenary_data *md) { - if (md->contract_timer == INVALID_TIMER) - md->contract_timer = add_timer(gettick() + md->mercenary.life_time, merc_contract_end, md->master->bl.id, 0); + if( md->contract_timer == INVALID_TIMER ) + md->contract_timer = add_timer(gettick() + md->mercenary.life_time, merc_contract_end, md->master->bl.id, 0); - md->regen.state.block = 0; + md->regen.state.block = 0; } int merc_data_received(struct s_mercenary *merc, bool flag) { - struct map_session_data *sd; - struct mercenary_data *md; - struct s_mercenary_db *db; - int i = merc_search_index(merc->class_); - - if ((sd = map_charid2sd(merc->char_id)) == NULL) - return 0; - if (!flag || i < 0) { - // Not created - loaded - DB info - sd->status.mer_id = 0; - return 0; - } - - db = &mercenary_db[i]; - if (!sd->md) { - sd->md = md = (struct mercenary_data *)aCalloc(1,sizeof(struct mercenary_data)); - md->bl.type = BL_MER; - md->bl.id = npc_get_new_npc_id(); - md->devotion_flag = 0; - - md->master = sd; - md->db = db; - memcpy(&md->mercenary, merc, sizeof(struct s_mercenary)); - status_set_viewdata(&md->bl, md->mercenary.class_); - status_change_init(&md->bl); - unit_dataset(&md->bl); - md->ud.dir = sd->ud.dir; - - md->bl.m = sd->bl.m; - md->bl.x = sd->bl.x; - md->bl.y = sd->bl.y; - unit_calc_pos(&md->bl, sd->bl.x, sd->bl.y, sd->ud.dir); - md->bl.x = md->ud.to_x; - md->bl.y = md->ud.to_y; - - map_addiddb(&md->bl); - status_calc_mercenary(md,1); - md->contract_timer = INVALID_TIMER; - merc_contract_init(md); - } else { - memcpy(&sd->md->mercenary, merc, sizeof(struct s_mercenary)); - md = sd->md; - } - - if (sd->status.mer_id == 0) - mercenary_set_calls(md, 1); - sd->status.mer_id = merc->mercenary_id; - - if (md && md->bl.prev == NULL && sd->bl.prev != NULL) { - map_addblock(&md->bl); - clif_spawn(&md->bl); - clif_mercenary_info(sd); - clif_mercenary_skillblock(sd); - } - - return 1; + struct map_session_data *sd; + struct mercenary_data *md; + struct s_mercenary_db *db; + int i = merc_search_index(merc->class_); + + if( (sd = map_charid2sd(merc->char_id)) == NULL ) + return 0; + if( !flag || i < 0 ) + { // Not created - loaded - DB info + sd->status.mer_id = 0; + return 0; + } + + db = &mercenary_db[i]; + if( !sd->md ) + { + sd->md = md = (struct mercenary_data*)aCalloc(1,sizeof(struct mercenary_data)); + md->bl.type = BL_MER; + md->bl.id = npc_get_new_npc_id(); + md->devotion_flag = 0; + + md->master = sd; + md->db = db; + memcpy(&md->mercenary, merc, sizeof(struct s_mercenary)); + status_set_viewdata(&md->bl, md->mercenary.class_); + status_change_init(&md->bl); + unit_dataset(&md->bl); + md->ud.dir = sd->ud.dir; + + md->bl.m = sd->bl.m; + md->bl.x = sd->bl.x; + md->bl.y = sd->bl.y; + unit_calc_pos(&md->bl, sd->bl.x, sd->bl.y, sd->ud.dir); + md->bl.x = md->ud.to_x; + md->bl.y = md->ud.to_y; + + map_addiddb(&md->bl); + status_calc_mercenary(md,1); + md->contract_timer = INVALID_TIMER; + merc_contract_init(md); + } + else + { + memcpy(&sd->md->mercenary, merc, sizeof(struct s_mercenary)); + md = sd->md; + } + + if( sd->status.mer_id == 0 ) + mercenary_set_calls(md, 1); + sd->status.mer_id = merc->mercenary_id; + + if( md && md->bl.prev == NULL && sd->bl.prev != NULL ) + { + map_addblock(&md->bl); + clif_spawn(&md->bl); + clif_mercenary_info(sd); + clif_mercenary_skillblock(sd); + } + + return 1; } void mercenary_heal(struct mercenary_data *md, int hp, int sp) { - if (hp) - clif_mercenary_updatestatus(md->master, SP_HP); - if (sp) - clif_mercenary_updatestatus(md->master, SP_SP); + if( hp ) + clif_mercenary_updatestatus(md->master, SP_HP); + if( sp ) + clif_mercenary_updatestatus(md->master, SP_SP); } int mercenary_dead(struct mercenary_data *md) { - merc_delete(md, 1); - return 0; + merc_delete(md, 1); + return 0; } int mercenary_killbonus(struct mercenary_data *md) { - const enum sc_type scs[] = { SC_MERC_FLEEUP, SC_MERC_ATKUP, SC_MERC_HPUP, SC_MERC_SPUP, SC_MERC_HITUP }; - int index = rnd() % ARRAYLENGTH(scs); + const enum sc_type scs[] = { SC_MERC_FLEEUP, SC_MERC_ATKUP, SC_MERC_HPUP, SC_MERC_SPUP, SC_MERC_HITUP }; + int index = rnd() % ARRAYLENGTH(scs); sc_start(&md->bl, scs[index], 100, rnd() % 5, 600000); - return 0; + return 0; } int mercenary_kills(struct mercenary_data *md) { - md->mercenary.kill_count++; - md->mercenary.kill_count = cap_value(md->mercenary.kill_count, 0, INT_MAX); + md->mercenary.kill_count++; + md->mercenary.kill_count = cap_value(md->mercenary.kill_count, 0, INT_MAX); - if ((md->mercenary.kill_count % 50) == 0) { - mercenary_set_faith(md, 1); - mercenary_killbonus(md); - } + if( (md->mercenary.kill_count % 50) == 0 ) + { + mercenary_set_faith(md, 1); + mercenary_killbonus(md); + } - if (md->master) - clif_mercenary_updatestatus(md->master, SP_MERCKILLS); + if( md->master ) + clif_mercenary_updatestatus(md->master, SP_MERCKILLS); - return 0; + return 0; } int mercenary_checkskill(struct mercenary_data *md, int skill_id) { - int i = skill_id - MC_SKILLBASE; + int i = skill_id - MC_SKILLBASE; - if (!md || !md->db) - return 0; - if (md->db->skill[i].id == skill_id) - return md->db->skill[i].lv; + if( !md || !md->db ) + return 0; + if( md->db->skill[i].id == skill_id ) + return md->db->skill[i].lv; - return 0; + return 0; } -static bool read_mercenarydb_sub(char *str[], int columns, int current) +static bool read_mercenarydb_sub(char* str[], int columns, int current) { - int ele; - struct s_mercenary_db *db; - struct status_data *status; - - db = &mercenary_db[current]; - db->class_ = atoi(str[0]); - strncpy(db->sprite, str[1], NAME_LENGTH); - strncpy(db->name, str[2], NAME_LENGTH); - db->lv = atoi(str[3]); - - status = &db->status; - db->vd.class_ = db->class_; - - status->max_hp = atoi(str[4]); - status->max_sp = atoi(str[5]); - status->rhw.range = atoi(str[6]); - status->rhw.atk = atoi(str[7]); - status->rhw.atk2 = status->rhw.atk + atoi(str[8]); - status->def = atoi(str[9]); - status->mdef = atoi(str[10]); - status->str = atoi(str[11]); - status->agi = atoi(str[12]); - status->vit = atoi(str[13]); - status->int_ = atoi(str[14]); - status->dex = atoi(str[15]); - status->luk = atoi(str[16]); - db->range2 = atoi(str[17]); - db->range3 = atoi(str[18]); - status->size = atoi(str[19]); - status->race = atoi(str[20]); - - ele = atoi(str[21]); - status->def_ele = ele%10; - status->ele_lv = ele/20; - if (status->def_ele >= ELE_MAX) { - ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1); - status->def_ele = ELE_NEUTRAL; - } - if (status->ele_lv < 1 || status->ele_lv > 4) { - ShowWarning("Mercenary %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv); - status->ele_lv = 1; - } - - status->aspd_rate = 1000; - status->speed = atoi(str[22]); - status->adelay = atoi(str[23]); - status->amotion = atoi(str[24]); - status->dmotion = atoi(str[25]); - - return true; + int ele; + struct s_mercenary_db *db; + struct status_data *status; + + db = &mercenary_db[current]; + db->class_ = atoi(str[0]); + strncpy(db->sprite, str[1], NAME_LENGTH); + strncpy(db->name, str[2], NAME_LENGTH); + db->lv = atoi(str[3]); + + status = &db->status; + db->vd.class_ = db->class_; + + status->max_hp = atoi(str[4]); + status->max_sp = atoi(str[5]); + status->rhw.range = atoi(str[6]); + status->rhw.atk = atoi(str[7]); + status->rhw.atk2 = status->rhw.atk + atoi(str[8]); + status->def = atoi(str[9]); + status->mdef = atoi(str[10]); + status->str = atoi(str[11]); + status->agi = atoi(str[12]); + status->vit = atoi(str[13]); + status->int_ = atoi(str[14]); + status->dex = atoi(str[15]); + status->luk = atoi(str[16]); + db->range2 = atoi(str[17]); + db->range3 = atoi(str[18]); + status->size = atoi(str[19]); + status->race = atoi(str[20]); + + ele = atoi(str[21]); + status->def_ele = ele%10; + status->ele_lv = ele/20; + if( status->def_ele >= ELE_MAX ) + { + ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1); + status->def_ele = ELE_NEUTRAL; + } + if( status->ele_lv < 1 || status->ele_lv > 4 ) + { + ShowWarning("Mercenary %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv); + status->ele_lv = 1; + } + + status->aspd_rate = 1000; + status->speed = atoi(str[22]); + status->adelay = atoi(str[23]); + status->amotion = atoi(str[24]); + status->dmotion = atoi(str[25]); + + return true; } int read_mercenarydb(void) { - memset(mercenary_db,0,sizeof(mercenary_db)); - sv_readdb(db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub); + memset(mercenary_db,0,sizeof(mercenary_db)); + sv_readdb(db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub); - return 0; + return 0; } -static bool read_mercenary_skilldb_sub(char *str[], int columns, int current) -{ - // <merc id>,<skill id>,<skill level> - struct s_mercenary_db *db; - int i, class_; - int skillid, skilllv; - - class_ = atoi(str[0]); - ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary_db[i].class_); - if (i == MAX_MERCENARY_CLASS) { - ShowError("read_mercenary_skilldb : Class %d not found in mercenary_db for skill entry.\n", class_); - return false; - } - - skillid = atoi(str[1]); - if (skillid < MC_SKILLBASE || skillid >= MC_SKILLBASE + MAX_MERCSKILL) { - ShowError("read_mercenary_skilldb : Skill %d out of range.\n", skillid); - return false; - } - - db = &mercenary_db[i]; - skilllv = atoi(str[2]); - - i = skillid - MC_SKILLBASE; - db->skill[i].id = skillid; - db->skill[i].lv = skilllv; - - return true; +static bool read_mercenary_skilldb_sub(char* str[], int columns, int current) +{// <merc id>,<skill id>,<skill level> + struct s_mercenary_db *db; + int i, class_; + int skillid, skilllv; + + class_ = atoi(str[0]); + ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary_db[i].class_); + if( i == MAX_MERCENARY_CLASS ) + { + ShowError("read_mercenary_skilldb : Class %d not found in mercenary_db for skill entry.\n", class_); + return false; + } + + skillid = atoi(str[1]); + if( skillid < MC_SKILLBASE || skillid >= MC_SKILLBASE + MAX_MERCSKILL ) + { + ShowError("read_mercenary_skilldb : Skill %d out of range.\n", skillid); + return false; + } + + db = &mercenary_db[i]; + skilllv = atoi(str[2]); + + i = skillid - MC_SKILLBASE; + db->skill[i].id = skillid; + db->skill[i].lv = skilllv; + + return true; } int read_mercenary_skilldb(void) { - sv_readdb(db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub); + sv_readdb(db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub); - return 0; + return 0; } int do_init_mercenary(void) { - read_mercenarydb(); - read_mercenary_skilldb(); - - //add_timer_func_list(mercenary_contract, "mercenary_contract"); - return 0; + read_mercenarydb(); + read_mercenary_skilldb(); + + //add_timer_func_list(mercenary_contract, "mercenary_contract"); + return 0; } int do_final_mercenary(void); diff --git a/src/map/mercenary.h b/src/map/mercenary.h index 4de3f304e..014bd8937 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -11,46 +11,46 @@ #define MAX_MER_DISTANCE 15 enum { - ARCH_MERC_GUILD, - SPEAR_MERC_GUILD, - SWORD_MERC_GUILD, + ARCH_MERC_GUILD, + SPEAR_MERC_GUILD, + SWORD_MERC_GUILD, }; struct s_mercenary_db { - int class_; - char sprite[NAME_LENGTH], name[NAME_LENGTH]; - unsigned short lv; - short range2, range3; - struct status_data status; - struct view_data vd; - struct { - unsigned short id, lv; - } skill[MAX_MERCSKILL]; + int class_; + char sprite[NAME_LENGTH], name[NAME_LENGTH]; + unsigned short lv; + short range2, range3; + struct status_data status; + struct view_data vd; + struct { + unsigned short id, lv; + } skill[MAX_MERCSKILL]; }; extern struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS]; struct mercenary_data { - struct block_list bl; - struct unit_data ud; - struct view_data *vd; - struct status_data base_status, battle_status; - struct status_change sc; - struct regen_data regen; - - struct s_mercenary_db *db; - struct s_mercenary mercenary; - char blockskill[MAX_SKILL]; - - struct map_session_data *master; - int contract_timer; - - unsigned devotion_flag : 1; - unsigned int masterteleport_timer; + struct block_list bl; + struct unit_data ud; + struct view_data *vd; + struct status_data base_status, battle_status; + struct status_change sc; + struct regen_data regen; + + struct s_mercenary_db *db; + struct s_mercenary mercenary; + char blockskill[MAX_SKILL]; + + struct map_session_data *master; + int contract_timer; + + unsigned devotion_flag : 1; + unsigned int masterteleport_timer; }; bool merc_class(int class_); -struct view_data *merc_get_viewdata(int class_); +struct view_data * merc_get_viewdata(int class_); int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime); int merc_data_received(struct s_mercenary *merc, bool flag); diff --git a/src/map/mob.c b/src/map/mob.c index acec51df6..b512e0b26 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -42,40 +42,34 @@ #include <string.h> #include <math.h> -#define ACTIVE_AI_RANGE 2 //Distance added on top of 'AREA_SIZE' at which mobs enter active AI mode. +#define ACTIVE_AI_RANGE 2 //Distance added on top of 'AREA_SIZE' at which mobs enter active AI mode. -#define IDLE_SKILL_INTERVAL 10 //Active idle skills should be triggered every 1 second (1000/MIN_MOBTHINKTIME) +#define IDLE_SKILL_INTERVAL 10 //Active idle skills should be triggered every 1 second (1000/MIN_MOBTHINKTIME) -#define MOB_LAZYSKILLPERC 0 // Probability for mobs far from players from doing their IDLE skill. (rate of 1000 minute) +#define MOB_LAZYSKILLPERC 0 // Probability for mobs far from players from doing their IDLE skill. (rate of 1000 minute) // Move probability for mobs away from players (rate of 1000 minute) // in Aegis, this is 100% for mobs that have been activated by players and none otherwise. #define MOB_LAZYMOVEPERC(md) (md->state.spotted?1000:0) #define MOB_MAX_DELAY (24*3600*1000) -#define MAX_MINCHASE 30 //Max minimum chase value to use for mobs. -#define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used? +#define MAX_MINCHASE 30 //Max minimum chase value to use for mobs. +#define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used? #define MAX_MOB_CHAT 250 //Max Skill's messages //Dynamic mob database, allows saving of memory when there's big gaps in the mob_db [Skotlex] struct mob_db *mob_db_data[MAX_MOB_DB+1]; -struct mob_db *mob_dummy = NULL; //Dummy mob to be returned when a non-existant one is requested. +struct mob_db *mob_dummy = NULL; //Dummy mob to be returned when a non-existant one is requested. -struct mob_db *mob_db(int index) { - if (index < 0 || index > MAX_MOB_DB || mob_db_data[index] == NULL) return mob_dummy; - return mob_db_data[index]; -} +struct mob_db *mob_db(int index) { if (index < 0 || index > MAX_MOB_DB || mob_db_data[index] == NULL) return mob_dummy; return mob_db_data[index]; } //Dynamic mob chat database struct mob_chat *mob_chat_db[MAX_MOB_CHAT+1]; -struct mob_chat *mob_chat(short id) { - if (id<=0 || id>MAX_MOB_CHAT || mob_chat_db[id]==NULL) return (struct mob_chat *)NULL; - return mob_chat_db[id]; -} +struct mob_chat *mob_chat(short id) { if(id<=0 || id>MAX_MOB_CHAT || mob_chat_db[id]==NULL) return (struct mob_chat*)NULL; return mob_chat_db[id]; } //Dynamic item drop ratio database for per-item drop ratio modifiers overriding global drop ratios. #define MAX_ITEMRATIO_MOBS 10 struct item_drop_ratio { - int drop_ratio; - int mob_id[MAX_ITEMRATIO_MOBS]; + int drop_ratio; + int mob_id[MAX_ITEMRATIO_MOBS]; }; static struct item_drop_ratio *item_drop_ratio_db[MAX_ITEMDB]; @@ -83,8 +77,8 @@ static struct eri *item_drop_ers; //For loot drops delay structures. static struct eri *item_drop_list_ers; static struct { - int qty; - int class_[350]; + int qty; + int class_[350]; } summon[MAX_RANDOMMONSTER]; //Defines the Manuk/Splendide mob groups for the status reductions [Epoque] @@ -103,29 +97,29 @@ int mob_skillid2skillidx(int class_,int skillid); *------------------------------------------*/ int mobdb_searchname(const char *str) { - int i; - struct mob_db *mob; - for (i=0; i<=MAX_MOB_DB; i++) { - mob = mob_db(i); - if (mob == mob_dummy) //Skip dummy mobs. - continue; - if (strcmpi(mob->name,str)==0 || strcmpi(mob->jname,str)==0 || strcmpi(mob->sprite,str)==0) - return i; - } - - return 0; + int i; + struct mob_db* mob; + for(i=0;i<=MAX_MOB_DB;i++){ + mob = mob_db(i); + if(mob == mob_dummy) //Skip dummy mobs. + continue; + if(strcmpi(mob->name,str)==0 || strcmpi(mob->jname,str)==0 || strcmpi(mob->sprite,str)==0) + return i; + } + + return 0; } -static int mobdb_searchname_array_sub(struct mob_db *mob, const char *str) +static int mobdb_searchname_array_sub(struct mob_db* mob, const char *str) { - if (mob == mob_dummy) - return 1; //Invalid mob. - if (!mob->base_exp && !mob->job_exp) - return 1; //Discount slave-mobs (no exp) as requested by Playtester. [Skotlex] - if (stristr(mob->jname,str)) - return 0; - if (stristr(mob->name,str)) - return 0; - return strcmpi(mob->jname,str); + if (mob == mob_dummy) + return 1; //Invalid mob. + if(!mob->base_exp && !mob->job_exp) + return 1; //Discount slave-mobs (no exp) as requested by Playtester. [Skotlex] + if(stristr(mob->jname,str)) + return 0; + if(stristr(mob->name,str)) + return 0; + return strcmpi(mob->jname,str); } /*========================================== @@ -133,90 +127,89 @@ static int mobdb_searchname_array_sub(struct mob_db *mob, const char *str) *------------------------------------------*/ void mvptomb_create(struct mob_data *md, char *killer, time_t time) { - struct npc_data *nd; + struct npc_data *nd; - if (md->tomb_nid) - mvptomb_destroy(md); + if ( md->tomb_nid ) + mvptomb_destroy(md); - CREATE(nd, struct npc_data, 1); + CREATE(nd, struct npc_data, 1); - nd->bl.id = md->tomb_nid = npc_get_new_npc_id(); + nd->bl.id = md->tomb_nid = npc_get_new_npc_id(); nd->ud.dir = md->ud.dir; - nd->bl.m = md->bl.m; - nd->bl.x = md->bl.x; - nd->bl.y = md->bl.y; - nd->bl.type = BL_NPC; + nd->bl.m = md->bl.m; + nd->bl.x = md->bl.x; + nd->bl.y = md->bl.y; + nd->bl.type = BL_NPC; - safestrncpy(nd->name, msg_txt(656), sizeof(nd->name)); + safestrncpy(nd->name, msg_txt(656), sizeof(nd->name)); - nd->class_ = 565; - nd->speed = 200; - nd->subtype = TOMB; + nd->class_ = 565; + nd->speed = 200; + nd->subtype = TOMB; - nd->u.tomb.md = md; - nd->u.tomb.kill_time = time; + nd->u.tomb.md = md; + nd->u.tomb.kill_time = time; - if (killer) - safestrncpy(nd->u.tomb.killer_name, killer, NAME_LENGTH); - else - nd->u.tomb.killer_name[0] = '\0'; + if (killer) + safestrncpy(nd->u.tomb.killer_name, killer, NAME_LENGTH); + else + nd->u.tomb.killer_name[0] = '\0'; - map_addnpc(nd->bl.m, nd); - map_addblock(&nd->bl); - status_set_viewdata(&nd->bl, nd->class_); + map_addnpc(nd->bl.m, nd); + map_addblock(&nd->bl); + status_set_viewdata(&nd->bl, nd->class_); status_change_init(&nd->bl); unit_dataset(&nd->bl); clif_spawn(&nd->bl); } -void mvptomb_destroy(struct mob_data *md) -{ - struct npc_data *nd; +void mvptomb_destroy(struct mob_data *md) { + struct npc_data *nd; - if ((nd = map_id2nd(md->tomb_nid))) { - int m, i; + if ( (nd = map_id2nd(md->tomb_nid)) ) { + int m, i; - m = nd->bl.m; + m = nd->bl.m; - clif_clearunit_area(&nd->bl,CLR_OUTSIGHT); + clif_clearunit_area(&nd->bl,CLR_OUTSIGHT); - map_delblock(&nd->bl); + map_delblock(&nd->bl); - ARR_FIND(0, map[m].npc_num, i, map[m].npc[i] == nd); - if (!(i == map[m].npc_num)) { - map[m].npc_num--; - map[m].npc[i] = map[m].npc[map[m].npc_num]; - map[m].npc[map[m].npc_num] = NULL; - } + ARR_FIND( 0, map[m].npc_num, i, map[m].npc[i] == nd ); + if( !(i == map[m].npc_num) ) { + map[m].npc_num--; + map[m].npc[i] = map[m].npc[map[m].npc_num]; + map[m].npc[map[m].npc_num] = NULL; + } - map_deliddb(&nd->bl); + map_deliddb(&nd->bl); - aFree(nd); - } + aFree(nd); + } - md->tomb_nid = 0; + md->tomb_nid = 0; } /*========================================== * Founds up to N matches. Returns number of matches [Skotlex] *------------------------------------------*/ -int mobdb_searchname_array(struct mob_db **data, int size, const char *str) +int mobdb_searchname_array(struct mob_db** data, int size, const char *str) { - int count = 0, i; - struct mob_db *mob; - for (i=0; i<=MAX_MOB_DB; i++) { - mob = mob_db(i); - if (mob == mob_dummy || mob_is_clone(i)) //keep clones out (or you leak player stats) - continue; - if (!mobdb_searchname_array_sub(mob, str)) { - if (count < size) - data[count] = mob; - count++; - } - } - return count; + int count = 0, i; + struct mob_db* mob; + for(i=0;i<=MAX_MOB_DB;i++){ + mob = mob_db(i); + if (mob == mob_dummy || mob_is_clone(i) ) //keep clones out (or you leak player stats) + continue; + if (!mobdb_searchname_array_sub(mob, str)) { + if (count < size) + data[count] = mob; + count++; + } + } + return count; } /*========================================== @@ -224,78 +217,81 @@ int mobdb_searchname_array(struct mob_db **data, int size, const char *str) *------------------------------------------*/ int mobdb_checkid(const int id) { - if (mob_db(id) == mob_dummy) - return 0; - if (mob_is_clone(id)) //checkid is used mostly for random ID based code, therefore clone mobs are out of the question. - return 0; - return id; + if (mob_db(id) == mob_dummy) + return 0; + if (mob_is_clone(id)) //checkid is used mostly for random ID based code, therefore clone mobs are out of the question. + return 0; + return id; } /*========================================== * Returns the view data associated to this mob class. *------------------------------------------*/ -struct view_data *mob_get_viewdata(int class_) { - if (mob_db(class_) == mob_dummy) - return 0; - return &mob_db(class_)->vd; +struct view_data * mob_get_viewdata(int class_) +{ + if (mob_db(class_) == mob_dummy) + return 0; + return &mob_db(class_)->vd; } /*========================================== * Cleans up mob-spawn data to make it "valid" *------------------------------------------*/ int mob_parse_dataset(struct spawn_data *data) { - size_t len; + size_t len; - if ((!mobdb_checkid(data->class_) && !mob_is_clone(data->class_)) || !data->num) - return 0; + if ((!mobdb_checkid(data->class_) && !mob_is_clone(data->class_)) || !data->num) + return 0; - if ((len = strlen(data->eventname)) > 0) { - if (data->eventname[len-1] == '"') - data->eventname[len-1] = '\0'; //Remove trailing quote. - if (data->eventname[0] == '"') //Strip leading quotes - memmove(data->eventname, data->eventname+1, len-1); - } + if( ( len = strlen(data->eventname) ) > 0 ) + { + if( data->eventname[len-1] == '"' ) + data->eventname[len-1] = '\0'; //Remove trailing quote. + if( data->eventname[0] == '"' ) //Strip leading quotes + memmove(data->eventname, data->eventname+1, len-1); + } - if (strcmp(data->name,"--en--")==0) - safestrncpy(data->name, mob_db(data->class_)->name, sizeof(data->name)); - else if (strcmp(data->name,"--ja--")==0) - safestrncpy(data->name, mob_db(data->class_)->jname, sizeof(data->name)); + if(strcmp(data->name,"--en--")==0) + safestrncpy(data->name, mob_db(data->class_)->name, sizeof(data->name)); + else if(strcmp(data->name,"--ja--")==0) + safestrncpy(data->name, mob_db(data->class_)->jname, sizeof(data->name)); - return 1; + return 1; } /*========================================== * Generates the basic mob data using the spawn_data provided. *------------------------------------------*/ -struct mob_data *mob_spawn_dataset(struct spawn_data *data) { - struct mob_data *md = (struct mob_data *)aCalloc(1, sizeof(struct mob_data)); - md->bl.id= npc_get_new_npc_id(); - md->bl.type = BL_MOB; - md->bl.m = data->m; - md->bl.x = data->x; - md->bl.y = data->y; - md->class_ = data->class_; - md->state.boss = data->state.boss; - md->db = mob_db(md->class_); - if (data->level > 0 && data->level <= MAX_LEVEL) - md->level = data->level; - memcpy(md->name, data->name, NAME_LENGTH); - if (data->state.ai) - md->special_state.ai = data->state.ai; - if (data->state.size) - md->special_state.size = data->state.size; - if (data->eventname[0] && strlen(data->eventname) >= 4) - memcpy(md->npc_event, data->eventname, 50); - if (md->db->status.mode &MD_LOOTER) - md->lootitem = (struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item)); - md->spawn_timer = INVALID_TIMER; - md->deletetimer = INVALID_TIMER; - md->skillidx = -1; - status_set_viewdata(&md->bl, md->class_); - status_change_init(&md->bl); - unit_dataset(&md->bl); - - map_addiddb(&md->bl); - return md; +struct mob_data* mob_spawn_dataset(struct spawn_data *data) +{ + struct mob_data *md = (struct mob_data*)aCalloc(1, sizeof(struct mob_data)); + md->bl.id= npc_get_new_npc_id(); + md->bl.type = BL_MOB; + md->bl.m = data->m; + md->bl.x = data->x; + md->bl.y = data->y; + md->class_ = data->class_; + md->state.boss = data->state.boss; + md->db = mob_db(md->class_); + if (data->level > 0 && data->level <= MAX_LEVEL) + md->level = data->level; + memcpy(md->name, data->name, NAME_LENGTH); + if (data->state.ai) + md->special_state.ai = data->state.ai; + if (data->state.size) + md->special_state.size = data->state.size; + if (data->eventname[0] && strlen(data->eventname) >= 4) + memcpy(md->npc_event, data->eventname, 50); + if(md->db->status.mode&MD_LOOTER) + md->lootitem = (struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item)); + md->spawn_timer = INVALID_TIMER; + md->deletetimer = INVALID_TIMER; + md->skillidx = -1; + status_set_viewdata(&md->bl, md->class_); + status_change_init(&md->bl); + unit_dataset(&md->bl); + + map_addiddb(&md->bl); + return md; } /*========================================== @@ -313,436 +309,460 @@ struct mob_data *mob_spawn_dataset(struct spawn_data *data) { *------------------------------------------*/ int mob_get_random_id(int type, int flag, int lv) { - struct mob_db *mob; - int i=0, class_; - if (type < 0 || type >= MAX_RANDOMMONSTER) { - ShowError("mob_get_random_id: Invalid type (%d) of random monster.\n", type); - return 0; - } - do { - if (type) - class_ = summon[type].class_[rnd()%summon[type].qty]; - else //Dead branch - class_ = rnd() % MAX_MOB_DB; - mob = mob_db(class_); - } while ((mob == mob_dummy || - mob_is_clone(class_) || - (flag&1 && mob->summonper[type] <= rnd() % 1000000) || - (flag&2 && lv < mob->lv) || - (flag&4 && mob->status.mode&MD_BOSS) || - (flag&8 && mob->spawn[0].qty < 1) - ) && (i++) < MAX_MOB_DB); - - if (i >= MAX_MOB_DB) // no suitable monster found, use fallback for given list - class_ = mob_db_data[0]->summonper[type]; - return class_; + struct mob_db *mob; + int i=0, class_; + if(type < 0 || type >= MAX_RANDOMMONSTER) { + ShowError("mob_get_random_id: Invalid type (%d) of random monster.\n", type); + return 0; + } + do { + if (type) + class_ = summon[type].class_[rnd()%summon[type].qty]; + else //Dead branch + class_ = rnd() % MAX_MOB_DB; + mob = mob_db(class_); + } while ((mob == mob_dummy || + mob_is_clone(class_) || + (flag&1 && mob->summonper[type] <= rnd() % 1000000) || + (flag&2 && lv < mob->lv) || + (flag&4 && mob->status.mode&MD_BOSS) || + (flag&8 && mob->spawn[0].qty < 1) + ) && (i++) < MAX_MOB_DB); + + if(i >= MAX_MOB_DB) // no suitable monster found, use fallback for given list + class_ = mob_db_data[0]->summonper[type]; + return class_; } /*========================================== * Kill Steal Protection [Zephyrus] *------------------------------------------*/ -bool mob_ksprotected(struct block_list *src, struct block_list *target) +bool mob_ksprotected (struct block_list *src, struct block_list *target) { - struct block_list *s_bl, *t_bl; - struct map_session_data - *sd, // Source - *pl_sd, // Owner - *t_sd; // Mob Target - struct status_change_entry *sce; - struct mob_data *md; - unsigned int tick = gettick(); - char output[128]; + struct block_list *s_bl, *t_bl; + struct map_session_data + *sd, // Source + *pl_sd, // Owner + *t_sd; // Mob Target + struct status_change_entry *sce; + struct mob_data *md; + unsigned int tick = gettick(); + char output[128]; - if (!battle_config.ksprotection) - return false; // KS Protection Disabled + if( !battle_config.ksprotection ) + return false; // KS Protection Disabled - if (!(md = BL_CAST(BL_MOB,target))) - return false; // Tarjet is not MOB + if( !(md = BL_CAST(BL_MOB,target)) ) + return false; // Tarjet is not MOB - if ((s_bl = battle_get_master(src)) == NULL) - s_bl = src; + if( (s_bl = battle_get_master(src)) == NULL ) + s_bl = src; - if (!(sd = BL_CAST(BL_PC,s_bl))) - return false; // Master is not PC + if( !(sd = BL_CAST(BL_PC,s_bl)) ) + return false; // Master is not PC - t_bl = map_id2bl(md->target_id); - if (!t_bl || (s_bl = battle_get_master(t_bl)) == NULL) - s_bl = t_bl; + t_bl = map_id2bl(md->target_id); + if( !t_bl || (s_bl = battle_get_master(t_bl)) == NULL ) + s_bl = t_bl; - t_sd = BL_CAST(BL_PC,s_bl); + t_sd = BL_CAST(BL_PC,s_bl); - do { - if (map[md->bl.m].flag.allowks || map_flag_ks(md->bl.m)) - return false; // Ignores GVG, PVP and AllowKS map flags + do { + if( map[md->bl.m].flag.allowks || map_flag_ks(md->bl.m) ) + return false; // Ignores GVG, PVP and AllowKS map flags - if (md->db->mexp || md->master_id) - return false; // MVP, Slaves mobs ignores KS + if( md->db->mexp || md->master_id ) + return false; // MVP, Slaves mobs ignores KS - if ((sce = md->sc.data[SC_KSPROTECTED]) == NULL) - break; // No KS Protected + if( (sce = md->sc.data[SC_KSPROTECTED]) == NULL ) + break; // No KS Protected - if (sd->bl.id == sce->val1 || // Same Owner - (sce->val2 == 2 && sd->status.party_id && sd->status.party_id == sce->val3) || // Party KS allowed - (sce->val2 == 3 && sd->status.guild_id && sd->status.guild_id == sce->val4)) // Guild KS allowed - break; + if( sd->bl.id == sce->val1 || // Same Owner + (sce->val2 == 2 && sd->status.party_id && sd->status.party_id == sce->val3) || // Party KS allowed + (sce->val2 == 3 && sd->status.guild_id && sd->status.guild_id == sce->val4) ) // Guild KS allowed + break; - if (t_sd && ( - (sce->val2 == 1 && sce->val1 != t_sd->bl.id) || - (sce->val2 == 2 && sce->val3 && sce->val3 != t_sd->status.party_id) || - (sce->val2 == 3 && sce->val4 && sce->val4 != t_sd->status.guild_id))) - break; + if( t_sd && ( + (sce->val2 == 1 && sce->val1 != t_sd->bl.id) || + (sce->val2 == 2 && sce->val3 && sce->val3 != t_sd->status.party_id) || + (sce->val2 == 3 && sce->val4 && sce->val4 != t_sd->status.guild_id)) ) + break; - if ((pl_sd = map_id2sd(sce->val1)) == NULL || pl_sd->bl.m != md->bl.m) - break; + if( (pl_sd = map_id2sd(sce->val1)) == NULL || pl_sd->bl.m != md->bl.m ) + break; - if (!pl_sd->state.noks) - return false; // No KS Protected, but normal players should be protected too + if( !pl_sd->state.noks ) + return false; // No KS Protected, but normal players should be protected too - // Message to KS - if (DIFF_TICK(sd->ks_floodprotect_tick, tick) <= 0) { - sprintf(output, "[KS Warning!! - Owner : %s]", pl_sd->status.name); - clif_disp_onlyself(sd, output, strlen(output)); + // Message to KS + if( DIFF_TICK(sd->ks_floodprotect_tick, tick) <= 0 ) + { + sprintf(output, "[KS Warning!! - Owner : %s]", pl_sd->status.name); + clif_disp_onlyself(sd, output, strlen(output)); - sd->ks_floodprotect_tick = tick + 2000; - } + sd->ks_floodprotect_tick = tick + 2000; + } - // Message to Owner - if (DIFF_TICK(pl_sd->ks_floodprotect_tick, tick) <= 0) { - sprintf(output, "[Watch out! %s is trying to KS you!]", sd->status.name); - clif_disp_onlyself(pl_sd, output, strlen(output)); + // Message to Owner + if( DIFF_TICK(pl_sd->ks_floodprotect_tick, tick) <= 0 ) + { + sprintf(output, "[Watch out! %s is trying to KS you!]", sd->status.name); + clif_disp_onlyself(pl_sd, output, strlen(output)); - pl_sd->ks_floodprotect_tick = tick + 2000; - } + pl_sd->ks_floodprotect_tick = tick + 2000; + } - return true; - } while (0); + return true; + } while(0); - status_change_start(target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks, sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, 0); + status_change_start(target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks, sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, 0); - return false; + return false; } -struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m, short x, short y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai) { - struct spawn_data data; +struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m, short x, short y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai) +{ + struct spawn_data data; - memset(&data, 0, sizeof(struct spawn_data)); - data.m = m; - data.num = 1; - data.class_ = class_; - data.state.size = size; - data.state.ai = ai; + memset(&data, 0, sizeof(struct spawn_data)); + data.m = m; + data.num = 1; + data.class_ = class_; + data.state.size = size; + data.state.ai = ai; - if (mobname) - safestrncpy(data.name, mobname, sizeof(data.name)); - else if (battle_config.override_mob_names == 1) - strcpy(data.name, "--en--"); - else - strcpy(data.name, "--ja--"); + if (mobname) + safestrncpy(data.name, mobname, sizeof(data.name)); + else + if (battle_config.override_mob_names == 1) + strcpy(data.name, "--en--"); + else + strcpy(data.name, "--ja--"); - if (event) - safestrncpy(data.eventname, event, sizeof(data.eventname)); + if (event) + safestrncpy(data.eventname, event, sizeof(data.eventname)); - // Locate spot next to player. - if (bl && (x < 0 || y < 0)) - map_search_freecell(bl, m, &x, &y, 1, 1, 0); + // Locate spot next to player. + if (bl && (x < 0 || y < 0)) + map_search_freecell(bl, m, &x, &y, 1, 1, 0); - // if none found, pick random position on map - if (x <= 0 || y <= 0 || map_getcell(m,x,y,CELL_CHKNOREACH)) - map_search_freecell(NULL, m, &x, &y, -1, -1, 1); + // if none found, pick random position on map + if (x <= 0 || y <= 0 || map_getcell(m,x,y,CELL_CHKNOREACH)) + map_search_freecell(NULL, m, &x, &y, -1, -1, 1); - data.x = x; - data.y = y; + data.x = x; + data.y = y; - if (!mob_parse_dataset(&data)) - return NULL; + if (!mob_parse_dataset(&data)) + return NULL; - return mob_spawn_dataset(&data); + return mob_spawn_dataset(&data); } /*========================================== * Spawn a single mob on the specified coordinates. *------------------------------------------*/ -int mob_once_spawn(struct map_session_data *sd, int m, short x, short y, const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai) +int mob_once_spawn(struct map_session_data* sd, int m, short x, short y, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai) { - struct mob_data *md = NULL; - int count, lv; - - if (m < 0 || amount <= 0) - return 0; // invalid input - - lv = (sd) ? sd->status.base_level : 255; - - for (count = 0; count < amount; count++) { - int c = (class_ >= 0) ? class_ : mob_get_random_id(-class_ - 1, (battle_config.random_monster_checklv) ? 3 : 1, lv); - md = mob_once_spawn_sub((sd) ? &sd->bl : NULL, m, x, y, mobname, c, event, size, ai); - - if (!md) - continue; - - if (class_ == MOBID_EMPERIUM) { - struct guild_castle *gc = guild_mapindex2gc(map[m].index); - struct guild *g = (gc) ? guild_search(gc->guild_id) : NULL; - if (gc) { - md->guardian_data = (struct guardian_data *)aCalloc(1, sizeof(struct guardian_data)); - md->guardian_data->castle = gc; - md->guardian_data->number = MAX_GUARDIANS; - md->guardian_data->guild_id = gc->guild_id; - if (g) { - md->guardian_data->emblem_id = g->emblem_id; - memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); - } else if (gc->guild_id) //Guild not yet available, retry in 5. - add_timer(gettick()+5000,mob_spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id); - } - } // end addition [Valaris] - - mob_spawn(md); - - if (class_ < 0 && battle_config.dead_branch_active) - //Behold Aegis's masterful decisions yet again... - //"I understand the "Aggressive" part, but the "Can Move" and "Can Attack" is just stupid" - Poki#3 - sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE|MD_ANGRY, 0, 60000); - } - - return (md) ? md->bl.id : 0; // id of last spawned mob + struct mob_data* md = NULL; + int count, lv; + + if (m < 0 || amount <= 0) + return 0; // invalid input + + lv = (sd) ? sd->status.base_level : 255; + + for (count = 0; count < amount; count++) + { + int c = (class_ >= 0) ? class_ : mob_get_random_id(-class_ - 1, (battle_config.random_monster_checklv) ? 3 : 1, lv); + md = mob_once_spawn_sub((sd) ? &sd->bl : NULL, m, x, y, mobname, c, event, size, ai); + + if (!md) + continue; + + if (class_ == MOBID_EMPERIUM) + { + struct guild_castle* gc = guild_mapindex2gc(map[m].index); + struct guild* g = (gc) ? guild_search(gc->guild_id) : NULL; + if (gc) + { + md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data)); + md->guardian_data->castle = gc; + md->guardian_data->number = MAX_GUARDIANS; + md->guardian_data->guild_id = gc->guild_id; + if (g) + { + md->guardian_data->emblem_id = g->emblem_id; + memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); + } + else if (gc->guild_id) //Guild not yet available, retry in 5. + add_timer(gettick()+5000,mob_spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id); + } + } // end addition [Valaris] + + mob_spawn(md); + + if (class_ < 0 && battle_config.dead_branch_active) + //Behold Aegis's masterful decisions yet again... + //"I understand the "Aggressive" part, but the "Can Move" and "Can Attack" is just stupid" - Poki#3 + sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE|MD_CANATTACK|MD_CANMOVE|MD_ANGRY, 0, 60000); + } + + return (md) ? md->bl.id : 0; // id of last spawned mob } /*========================================== * Spawn mobs in the specified area. *------------------------------------------*/ -int mob_once_spawn_area(struct map_session_data *sd, int m, int x0, int y0, int x1, int y1, const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai) +int mob_once_spawn_area(struct map_session_data* sd, int m, int x0, int y0, int x1, int y1, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai) { - int i, max, id = 0; - int lx = -1, ly = -1; - - if (m < 0 || amount <= 0) - return 0; // invalid input - - // normalize x/y coordinates - if (x0 > x1) - swap(x0, x1); - if (y0 > y1) - swap(y0, y1); - - // choose a suitable max. number of attempts - max = (y1 - y0 + 1)*(x1 - x0 + 1)*3; - if (max > 1000) - max = 1000; - - // spawn mobs, one by one - for (i = 0; i < amount; i++) { - int x, y; - int j = 0; - - // find a suitable map cell - do { - x = rnd()%(x1-x0+1)+x0; - y = rnd()%(y1-y0+1)+y0; - j++; - } while (map_getcell(m,x,y,CELL_CHKNOPASS) && j < max); - - if (j == max) { - // attempt to find an available cell failed - if (lx == -1 && ly == -1) - return 0; // total failure - - // fallback to last good x/y pair - x = lx; - y = ly; - } - - // record last successful coordinates - lx = x; - ly = y; - - id = mob_once_spawn(sd, m, x, y, mobname, class_, 1, event, size, ai); - } - - return id; // id of last spawned mob + int i, max, id = 0; + int lx = -1, ly = -1; + + if (m < 0 || amount <= 0) + return 0; // invalid input + + // normalize x/y coordinates + if (x0 > x1) + swap(x0, x1); + if (y0 > y1) + swap(y0, y1); + + // choose a suitable max. number of attempts + max = (y1 - y0 + 1)*(x1 - x0 + 1)*3; + if (max > 1000) + max = 1000; + + // spawn mobs, one by one + for (i = 0; i < amount; i++) + { + int x, y; + int j = 0; + + // find a suitable map cell + do { + x = rnd()%(x1-x0+1)+x0; + y = rnd()%(y1-y0+1)+y0; + j++; + } while (map_getcell(m,x,y,CELL_CHKNOPASS) && j < max); + + if (j == max) + {// attempt to find an available cell failed + if (lx == -1 && ly == -1) + return 0; // total failure + + // fallback to last good x/y pair + x = lx; + y = ly; + } + + // record last successful coordinates + lx = x; + ly = y; + + id = mob_once_spawn(sd, m, x, y, mobname, class_, 1, event, size, ai); + } + + return id; // id of last spawned mob } /*========================================== * Set a Guardian's guild data [Skotlex] *------------------------------------------*/ static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t data) -{ - //Needed because the guild_data may not be available at guardian spawn time. - struct block_list *bl = map_id2bl(id); - struct mob_data *md; - struct guild *g; - int guardup_lv; - - if (bl == NULL) //It is possible mob was already removed from map when the castle has no owner. [Skotlex] - return 0; - - if (bl->type != BL_MOB) { - ShowError("mob_spawn_guardian_sub: Block error!\n"); - return 0; - } - - md = (struct mob_data *)bl; - nullpo_ret(md->guardian_data); - g = guild_search((int)data); - - if (g == NULL) { - //Liberate castle, if the guild is not found this is an error! [Skotlex] - ShowError("mob_spawn_guardian_sub: Couldn't load guild %d!\n", (int)data); - if (md->class_ == MOBID_EMPERIUM) { - //Not sure this is the best way, but otherwise we'd be invoking this for ALL guardians spawned later on. - md->guardian_data->guild_id = 0; - if (md->guardian_data->castle->guild_id) { //Free castle up. - ShowNotice("Clearing ownership of castle %d (%s)\n", md->guardian_data->castle->castle_id, md->guardian_data->castle->castle_name); - guild_castledatasave(md->guardian_data->castle->castle_id, 1, 0); - } - } else { - if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible) - guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); - unit_free(&md->bl,CLR_OUTSIGHT); //Remove guardian. - } - return 0; - } - guardup_lv = guild_checkskill(g,GD_GUARDUP); - md->guardian_data->emblem_id = g->emblem_id; - memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); - md->guardian_data->guardup_lv = guardup_lv; - if (guardup_lv) - status_calc_mob(md, 0); //Give bonuses. - return 0; +{ //Needed because the guild_data may not be available at guardian spawn time. + struct block_list* bl = map_id2bl(id); + struct mob_data* md; + struct guild* g; + int guardup_lv; + + if (bl == NULL) //It is possible mob was already removed from map when the castle has no owner. [Skotlex] + return 0; + + if (bl->type != BL_MOB) + { + ShowError("mob_spawn_guardian_sub: Block error!\n"); + return 0; + } + + md = (struct mob_data*)bl; + nullpo_ret(md->guardian_data); + g = guild_search((int)data); + + if (g == NULL) + { //Liberate castle, if the guild is not found this is an error! [Skotlex] + ShowError("mob_spawn_guardian_sub: Couldn't load guild %d!\n", (int)data); + if (md->class_ == MOBID_EMPERIUM) + { //Not sure this is the best way, but otherwise we'd be invoking this for ALL guardians spawned later on. + md->guardian_data->guild_id = 0; + if (md->guardian_data->castle->guild_id) //Free castle up. + { + ShowNotice("Clearing ownership of castle %d (%s)\n", md->guardian_data->castle->castle_id, md->guardian_data->castle->castle_name); + guild_castledatasave(md->guardian_data->castle->castle_id, 1, 0); + } + } else { + if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible) + guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); + unit_free(&md->bl,CLR_OUTSIGHT); //Remove guardian. + } + return 0; + } + guardup_lv = guild_checkskill(g,GD_GUARDUP); + md->guardian_data->emblem_id = g->emblem_id; + memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); + md->guardian_data->guardup_lv = guardup_lv; + if( guardup_lv ) + status_calc_mob(md, 0); //Give bonuses. + return 0; } /*========================================== * Summoning Guardians [Valaris] *------------------------------------------*/ -int mob_spawn_guardian(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index) +int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian, bool has_index) { - struct mob_data *md=NULL; - struct spawn_data data; - struct guild *g=NULL; - struct guild_castle *gc; - int m; - memset(&data, 0, sizeof(struct spawn_data)); - data.num = 1; - - m=map_mapname2mapid(mapname); - - if (m<0) { - ShowWarning("mob_spawn_guardian: Map [%s] not found.\n", mapname); - return 0; - } - data.m = m; - data.num = 1; - if (class_<=0) { - class_ = mob_get_random_id(-class_-1, 1, 99); - if (!class_) return 0; - } - - data.class_ = class_; - - if (!has_index) { - guardian = -1; - } else if (guardian < 0 || guardian >= MAX_GUARDIANS) { - ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, class_, map[m].name); - return 0; - } - - if ((x<=0 || y<=0) && !map_search_freecell(NULL, m, &x, &y, -1,-1, 1)) { - ShowWarning("mob_spawn_guardian: Couldn't locate a spawn cell for guardian class %d (index %d) at castle map %s\n",class_, guardian, map[m].name); - return 0; - } - data.x = x; - data.y = y; - safestrncpy(data.name, mobname, sizeof(data.name)); - safestrncpy(data.eventname, event, sizeof(data.eventname)); - if (!mob_parse_dataset(&data)) - return 0; - - gc=guild_mapname2gc(map[m].name); - if (gc == NULL) { - ShowError("mob_spawn_guardian: No castle set at map %s\n", map[m].name); - return 0; - } - if (!gc->guild_id) - ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", class_, map[m].name); - else - g = guild_search(gc->guild_id); - - if (has_index && gc->guardian[guardian].id) { - //Check if guardian already exists, refuse to spawn if so. - struct mob_data *md2 = (TBL_MOB *)map_id2bl(gc->guardian[guardian].id); - if (md2 && md2->bl.type == BL_MOB && - md2->guardian_data && md2->guardian_data->number == guardian) { - ShowError("mob_spawn_guardian: Attempted to spawn guardian in position %d which already has a guardian (castle map %s)\n", guardian, map[m].name); - return 0; - } - } - - md = mob_spawn_dataset(&data); - md->guardian_data = (struct guardian_data *)aCalloc(1, sizeof(struct guardian_data)); - md->guardian_data->number = guardian; - md->guardian_data->guild_id = gc->guild_id; - md->guardian_data->castle = gc; - if (has_index) { - // permanent guardian - gc->guardian[guardian].id = md->bl.id; - } else { - // temporary guardian - int i; - ARR_FIND(0, gc->temp_guardians_max, i, gc->temp_guardians[i] == 0); - if (i == gc->temp_guardians_max) { - ++(gc->temp_guardians_max); - RECREATE(gc->temp_guardians, int, gc->temp_guardians_max); - } - gc->temp_guardians[i] = md->bl.id; - } - if (g) { - md->guardian_data->emblem_id = g->emblem_id; - memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); - md->guardian_data->guardup_lv = guild_checkskill(g,GD_GUARDUP); - } else if (md->guardian_data->guild_id) - add_timer(gettick()+5000,mob_spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id); - mob_spawn(md); - - return md->bl.id; + struct mob_data *md=NULL; + struct spawn_data data; + struct guild *g=NULL; + struct guild_castle *gc; + int m; + memset(&data, 0, sizeof(struct spawn_data)); + data.num = 1; + + m=map_mapname2mapid(mapname); + + if(m<0) + { + ShowWarning("mob_spawn_guardian: Map [%s] not found.\n", mapname); + return 0; + } + data.m = m; + data.num = 1; + if(class_<=0) { + class_ = mob_get_random_id(-class_-1, 1, 99); + if (!class_) return 0; + } + + data.class_ = class_; + + if( !has_index ) + { + guardian = -1; + } + else if( guardian < 0 || guardian >= MAX_GUARDIANS ) + { + ShowError("mob_spawn_guardian: Invalid guardian index %d for guardian %d (castle map %s)\n", guardian, class_, map[m].name); + return 0; + } + + if((x<=0 || y<=0) && !map_search_freecell(NULL, m, &x, &y, -1,-1, 1)) + { + ShowWarning("mob_spawn_guardian: Couldn't locate a spawn cell for guardian class %d (index %d) at castle map %s\n",class_, guardian, map[m].name); + return 0; + } + data.x = x; + data.y = y; + safestrncpy(data.name, mobname, sizeof(data.name)); + safestrncpy(data.eventname, event, sizeof(data.eventname)); + if (!mob_parse_dataset(&data)) + return 0; + + gc=guild_mapname2gc(map[m].name); + if (gc == NULL) + { + ShowError("mob_spawn_guardian: No castle set at map %s\n", map[m].name); + return 0; + } + if (!gc->guild_id) + ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", class_, map[m].name); + else + g = guild_search(gc->guild_id); + + if( has_index && gc->guardian[guardian].id ) + { //Check if guardian already exists, refuse to spawn if so. + struct mob_data *md2 = (TBL_MOB*)map_id2bl(gc->guardian[guardian].id); + if (md2 && md2->bl.type == BL_MOB && + md2->guardian_data && md2->guardian_data->number == guardian) + { + ShowError("mob_spawn_guardian: Attempted to spawn guardian in position %d which already has a guardian (castle map %s)\n", guardian, map[m].name); + return 0; + } + } + + md = mob_spawn_dataset(&data); + md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data)); + md->guardian_data->number = guardian; + md->guardian_data->guild_id = gc->guild_id; + md->guardian_data->castle = gc; + if( has_index ) + {// permanent guardian + gc->guardian[guardian].id = md->bl.id; + } + else + {// temporary guardian + int i; + ARR_FIND(0, gc->temp_guardians_max, i, gc->temp_guardians[i] == 0); + if( i == gc->temp_guardians_max ) + { + ++(gc->temp_guardians_max); + RECREATE(gc->temp_guardians, int, gc->temp_guardians_max); + } + gc->temp_guardians[i] = md->bl.id; + } + if (g) + { + md->guardian_data->emblem_id = g->emblem_id; + memcpy (md->guardian_data->guild_name, g->name, NAME_LENGTH); + md->guardian_data->guardup_lv = guild_checkskill(g,GD_GUARDUP); + } else if (md->guardian_data->guild_id) + add_timer(gettick()+5000,mob_spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id); + mob_spawn(md); + + return md->bl.id; } /*========================================== * Summoning BattleGround [Zephyrus] *------------------------------------------*/ -int mob_spawn_bg(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id) +int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, unsigned int bg_id) { - struct mob_data *md = NULL; - struct spawn_data data; - int m; - - if ((m = map_mapname2mapid(mapname)) < 0) { - ShowWarning("mob_spawn_bg: Map [%s] not found.\n", mapname); - return 0; - } - - memset(&data, 0, sizeof(struct spawn_data)); - data.m = m; - data.num = 1; - if (class_ <= 0) { - class_ = mob_get_random_id(-class_-1,1,99); - if (!class_) return 0; - } - - data.class_ = class_; - if ((x <= 0 || y <= 0) && !map_search_freecell(NULL, m, &x, &y, -1,-1, 1)) { - ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %d) at map %s\n",class_, bg_id, map[m].name); - return 0; - } - - data.x = x; - data.y = y; - safestrncpy(data.name, mobname, sizeof(data.name)); - safestrncpy(data.eventname, event, sizeof(data.eventname)); - if (!mob_parse_dataset(&data)) - return 0; - - md = mob_spawn_dataset(&data); - mob_spawn(md); - md->bg_id = bg_id; // BG Team ID - - return md->bl.id; + struct mob_data *md = NULL; + struct spawn_data data; + int m; + + if( (m = map_mapname2mapid(mapname)) < 0 ) + { + ShowWarning("mob_spawn_bg: Map [%s] not found.\n", mapname); + return 0; + } + + memset(&data, 0, sizeof(struct spawn_data)); + data.m = m; + data.num = 1; + if( class_ <= 0 ) + { + class_ = mob_get_random_id(-class_-1,1,99); + if( !class_ ) return 0; + } + + data.class_ = class_; + if( (x <= 0 || y <= 0) && !map_search_freecell(NULL, m, &x, &y, -1,-1, 1) ) + { + ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %d) at map %s\n",class_, bg_id, map[m].name); + return 0; + } + + data.x = x; + data.y = y; + safestrncpy(data.name, mobname, sizeof(data.name)); + safestrncpy(data.eventname, event, sizeof(data.eventname)); + if( !mob_parse_dataset(&data) ) + return 0; + + md = mob_spawn_dataset(&data); + mob_spawn(md); + md->bg_id = bg_id; // BG Team ID + + return md->bl.id; } /*========================================== @@ -754,21 +774,21 @@ int mob_spawn_bg(const char *mapname, short x, short y, const char *mobname, int *------------------------------------------*/ int mob_can_reach(struct mob_data *md,struct block_list *bl,int range, int state) { - int easy = 0; - - nullpo_ret(md); - nullpo_ret(bl); - switch (state) { - case MSS_RUSH: - case MSS_FOLLOW: - easy = 0; //(battle_config.mob_ai&0x1?0:1); - break; - case MSS_LOOT: - default: - easy = 1; - break; - } - return unit_can_reach_bl(&md->bl, bl, range, easy, NULL, NULL); + int easy = 0; + + nullpo_ret(md); + nullpo_ret(bl); + switch (state) { + case MSS_RUSH: + case MSS_FOLLOW: + easy = 0; //(battle_config.mob_ai&0x1?0:1); + break; + case MSS_LOOT: + default: + easy = 1; + break; + } + return unit_can_reach_bl(&md->bl, bl, range, easy, NULL, NULL); } /*========================================== @@ -776,28 +796,29 @@ int mob_can_reach(struct mob_data *md,struct block_list *bl,int range, int state *------------------------------------------*/ int mob_linksearch(struct block_list *bl,va_list ap) { - struct mob_data *md; - int class_; - struct block_list *target; - unsigned int tick; - - nullpo_ret(bl); - md=(struct mob_data *)bl; - class_ = va_arg(ap, int); - target = va_arg(ap, struct block_list *); - tick=va_arg(ap, unsigned int); - - if (md->class_ == class_ && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME - && !md->target_id) { - md->last_linktime = tick; - if (mob_can_reach(md,target,md->db->range2, MSS_FOLLOW)) { // Reachability judging - md->target_id = target->id; - md->min_chase=md->db->range3; - return 1; - } - } - - return 0; + struct mob_data *md; + int class_; + struct block_list *target; + unsigned int tick; + + nullpo_ret(bl); + md=(struct mob_data *)bl; + class_ = va_arg(ap, int); + target = va_arg(ap, struct block_list *); + tick=va_arg(ap, unsigned int); + + if (md->class_ == class_ && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME + && !md->target_id) + { + md->last_linktime = tick; + if( mob_can_reach(md,target,md->db->range2, MSS_FOLLOW) ){ // Reachability judging + md->target_id = target->id; + md->min_chase=md->db->range3; + return 1; + } + } + + return 0; } /*========================================== @@ -805,18 +826,20 @@ int mob_linksearch(struct block_list *bl,va_list ap) *------------------------------------------*/ int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *bl = map_id2bl(id); - struct mob_data *md = BL_CAST(BL_MOB, bl); - - if (md) { - if (md->spawn_timer != tid) { - ShowError("mob_delayspawn: Timer mismatch: %d != %d\n", tid, md->spawn_timer); - return 0; - } - md->spawn_timer = INVALID_TIMER; - mob_spawn(md); - } - return 0; + struct block_list* bl = map_id2bl(id); + struct mob_data* md = BL_CAST(BL_MOB, bl); + + if( md ) + { + if( md->spawn_timer != tid ) + { + ShowError("mob_delayspawn: Timer mismatch: %d != %d\n", tid, md->spawn_timer); + return 0; + } + md->spawn_timer = INVALID_TIMER; + mob_spawn(md); + } + return 0; } /*========================================== @@ -824,44 +847,43 @@ int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ int mob_setdelayspawn(struct mob_data *md) { - unsigned int spawntime, mode; - struct mob_db *db; - - if (!md->spawn) //Doesn't has respawn data! - return unit_free(&md->bl,CLR_DEAD); - - spawntime = md->spawn->delay1; //Base respawn time - if (md->spawn->delay2) //random variance - spawntime+= rnd()%md->spawn->delay2; - - //Apply the spawn delay fix [Skotlex] - db = mob_db(md->spawn->class_); - mode = db->status.mode; - if (mode & MD_BOSS) { //Bosses - if (battle_config.boss_spawn_delay != 100) { - // Divide by 100 first to prevent overflows - //(precision loss is minimal as duration is in ms already) - spawntime = spawntime/100*battle_config.boss_spawn_delay; - } - } else if (mode&MD_PLANT) { //Plants - if (battle_config.plant_spawn_delay != 100) { - spawntime = spawntime/100*battle_config.plant_spawn_delay; - } - } else if (battle_config.mob_spawn_delay != 100) { //Normal mobs - spawntime = spawntime/100*battle_config.mob_spawn_delay; - } - - if (spawntime < 500) //Min respawn time (is it needed?) - spawntime = 500; - - if (md->spawn_timer != INVALID_TIMER) - delete_timer(md->spawn_timer, mob_delayspawn); - md->spawn_timer = add_timer(gettick()+spawntime, mob_delayspawn, md->bl.id, 0); - return 0; + unsigned int spawntime, mode; + struct mob_db *db; + + if (!md->spawn) //Doesn't has respawn data! + return unit_free(&md->bl,CLR_DEAD); + + spawntime = md->spawn->delay1; //Base respawn time + if (md->spawn->delay2) //random variance + spawntime+= rnd()%md->spawn->delay2; + + //Apply the spawn delay fix [Skotlex] + db = mob_db(md->spawn->class_); + mode = db->status.mode; + if (mode & MD_BOSS) { //Bosses + if (battle_config.boss_spawn_delay != 100) { + // Divide by 100 first to prevent overflows + //(precision loss is minimal as duration is in ms already) + spawntime = spawntime/100*battle_config.boss_spawn_delay; + } + } else if (mode&MD_PLANT) { //Plants + if (battle_config.plant_spawn_delay != 100) { + spawntime = spawntime/100*battle_config.plant_spawn_delay; + } + } else if (battle_config.mob_spawn_delay != 100) { //Normal mobs + spawntime = spawntime/100*battle_config.mob_spawn_delay; + } + + if (spawntime < 500) //Min respawn time (is it needed?) + spawntime = 500; + + if( md->spawn_timer != INVALID_TIMER ) + delete_timer(md->spawn_timer, mob_delayspawn); + md->spawn_timer = add_timer(gettick()+spawntime, mob_delayspawn, md->bl.id, 0); + return 0; } -int mob_count_sub(struct block_list *bl, va_list ap) -{ +int mob_count_sub(struct block_list *bl, va_list ap) { int mobid[10], i; ARR_FIND(0, 10, i, (mobid[i] = va_arg(ap, int)) == 0); //fetch till 0 if (mobid[0]) { //if there one let's check it otherwise go backward @@ -875,123 +897,128 @@ int mob_count_sub(struct block_list *bl, va_list ap) /*========================================== * Mob spawning. Initialization is also variously here. *------------------------------------------*/ -int mob_spawn(struct mob_data *md) +int mob_spawn (struct mob_data *md) { - int i=0; - unsigned int tick = gettick(); - int c =0; - - md->last_thinktime = tick; - if (md->bl.prev != NULL) - unit_remove_map(&md->bl,CLR_RESPAWN); - else if (md->spawn && md->class_ != md->spawn->class_) { - md->class_ = md->spawn->class_; - status_set_viewdata(&md->bl, md->class_); - md->db = mob_db(md->class_); - memcpy(md->name,md->spawn->name,NAME_LENGTH); - } - - if (md->spawn) { //Respawn data - md->bl.m = md->spawn->m; - md->bl.x = md->spawn->x; - md->bl.y = md->spawn->y; - - if ((md->bl.x == 0 && md->bl.y == 0) || md->spawn->xs || md->spawn->ys) { - //Monster can be spawned on an area. - if (!map_search_freecell(&md->bl, -1, &md->bl.x, &md->bl.y, md->spawn->xs, md->spawn->ys, battle_config.no_spawn_on_player?4:0)) { - // retry again later - if (md->spawn_timer != INVALID_TIMER) - delete_timer(md->spawn_timer, mob_delayspawn); - md->spawn_timer = add_timer(tick+5000,mob_delayspawn,md->bl.id,0); - return 1; - } - } else if (battle_config.no_spawn_on_player > 99 && map_foreachinrange(mob_count_sub, &md->bl, AREA_SIZE, BL_PC)) { - // retry again later (players on sight) - if (md->spawn_timer != INVALID_TIMER) - delete_timer(md->spawn_timer, mob_delayspawn); - md->spawn_timer = add_timer(tick+5000,mob_delayspawn,md->bl.id,0); - return 1; - } - } - - memset(&md->state, 0, sizeof(md->state)); - status_calc_mob(md, 1); - md->attacked_id = 0; - md->target_id = 0; - md->move_fail_count = 0; - md->ud.state.attack_continue = 0; - md->ud.target_to = 0; - if (md->spawn_timer != INVALID_TIMER) { - delete_timer(md->spawn_timer, mob_delayspawn); - md->spawn_timer = INVALID_TIMER; - } - - // md->master_id = 0; - md->master_dist = 0; - - md->state.aggressive = md->status.mode&MD_ANGRY?1:0; - md->state.skillstate = MSS_IDLE; - md->next_walktime = tick+rnd()%5000+1000; - md->last_linktime = tick; - md->dmgtick = tick - 5000; - md->last_pcneartime = 0; - - for (i = 0, c = tick-MOB_MAX_DELAY; i < MAX_MOBSKILL; i++) - md->skilldelay[i] = c; - - memset(md->dmglog, 0, sizeof(md->dmglog)); - md->tdmg = 0; - - if (md->lootitem) - memset(md->lootitem, 0, sizeof(*md->lootitem)); - - md->lootitem_count = 0; - - if (md->db->option) - // Added for carts, falcons and pecos for cloned monsters. [Valaris] - md->sc.option = md->db->option; - - // MvP tomb [GreenBox] - if (md->tomb_nid) - mvptomb_destroy(md); - - map_addblock(&md->bl); - if (map[md->bl.m].users) - clif_spawn(&md->bl); - skill_unit_move(&md->bl,tick,1); - mobskill_use(md, tick, MSC_SPAWN); - return 0; + int i=0; + unsigned int tick = gettick(); + int c =0; + + md->last_thinktime = tick; + if (md->bl.prev != NULL) + unit_remove_map(&md->bl,CLR_RESPAWN); + else + if (md->spawn && md->class_ != md->spawn->class_) + { + md->class_ = md->spawn->class_; + status_set_viewdata(&md->bl, md->class_); + md->db = mob_db(md->class_); + memcpy(md->name,md->spawn->name,NAME_LENGTH); + } + + if (md->spawn) { //Respawn data + md->bl.m = md->spawn->m; + md->bl.x = md->spawn->x; + md->bl.y = md->spawn->y; + + if( (md->bl.x == 0 && md->bl.y == 0) || md->spawn->xs || md->spawn->ys ) + { //Monster can be spawned on an area. + if( !map_search_freecell(&md->bl, -1, &md->bl.x, &md->bl.y, md->spawn->xs, md->spawn->ys, battle_config.no_spawn_on_player?4:0) ) + { // retry again later + if( md->spawn_timer != INVALID_TIMER ) + delete_timer(md->spawn_timer, mob_delayspawn); + md->spawn_timer = add_timer(tick+5000,mob_delayspawn,md->bl.id,0); + return 1; + } + } + else if( battle_config.no_spawn_on_player > 99 && map_foreachinrange(mob_count_sub, &md->bl, AREA_SIZE, BL_PC) ) + { // retry again later (players on sight) + if( md->spawn_timer != INVALID_TIMER ) + delete_timer(md->spawn_timer, mob_delayspawn); + md->spawn_timer = add_timer(tick+5000,mob_delayspawn,md->bl.id,0); + return 1; + } + } + + memset(&md->state, 0, sizeof(md->state)); + status_calc_mob(md, 1); + md->attacked_id = 0; + md->target_id = 0; + md->move_fail_count = 0; + md->ud.state.attack_continue = 0; + md->ud.target_to = 0; + if( md->spawn_timer != INVALID_TIMER ) + { + delete_timer(md->spawn_timer, mob_delayspawn); + md->spawn_timer = INVALID_TIMER; + } + +// md->master_id = 0; + md->master_dist = 0; + + md->state.aggressive = md->status.mode&MD_ANGRY?1:0; + md->state.skillstate = MSS_IDLE; + md->next_walktime = tick+rnd()%5000+1000; + md->last_linktime = tick; + md->dmgtick = tick - 5000; + md->last_pcneartime = 0; + + for (i = 0, c = tick-MOB_MAX_DELAY; i < MAX_MOBSKILL; i++) + md->skilldelay[i] = c; + + memset(md->dmglog, 0, sizeof(md->dmglog)); + md->tdmg = 0; + + if (md->lootitem) + memset(md->lootitem, 0, sizeof(*md->lootitem)); + + md->lootitem_count = 0; + + if(md->db->option) + // Added for carts, falcons and pecos for cloned monsters. [Valaris] + md->sc.option = md->db->option; + + // MvP tomb [GreenBox] + if ( md->tomb_nid ) + mvptomb_destroy(md); + + map_addblock(&md->bl); + if( map[md->bl.m].users ) + clif_spawn(&md->bl); + skill_unit_move(&md->bl,tick,1); + mobskill_use(md, tick, MSC_SPAWN); + return 0; } /*========================================== * Determines if the mob can change target. [Skotlex] *------------------------------------------*/ -static int mob_can_changetarget(struct mob_data *md, struct block_list *target, int mode) +static int mob_can_changetarget(struct mob_data* md, struct block_list* target, int mode) { - // if the monster was provoked ignore the above rule [celest] - if (md->state.provoke_flag) { - if (md->state.provoke_flag == target->id) - return 1; - else if (!(battle_config.mob_ai&0x4)) - return 0; - } - - switch (md->state.skillstate) { - case MSS_BERSERK: - if (!(mode&MD_CHANGETARGET_MELEE)) - return 0; - return (battle_config.mob_ai&0x4 || check_distance_bl(&md->bl, target, 3)); - case MSS_RUSH: - return (mode&MD_CHANGETARGET_CHASE); - case MSS_FOLLOW: - case MSS_ANGRY: - case MSS_IDLE: - case MSS_WALK: - case MSS_LOOT: - return 1; - default: - return 0; - } + // if the monster was provoked ignore the above rule [celest] + if(md->state.provoke_flag) + { + if (md->state.provoke_flag == target->id) + return 1; + else if (!(battle_config.mob_ai&0x4)) + return 0; + } + + switch (md->state.skillstate) { + case MSS_BERSERK: + if (!(mode&MD_CHANGETARGET_MELEE)) + return 0; + return (battle_config.mob_ai&0x4 || check_distance_bl(&md->bl, target, 3)); + case MSS_RUSH: + return (mode&MD_CHANGETARGET_CHASE); + case MSS_FOLLOW: + case MSS_ANGRY: + case MSS_IDLE: + case MSS_WALK: + case MSS_LOOT: + return 1; + default: + return 0; + } } /*========================================== @@ -999,23 +1026,23 @@ static int mob_can_changetarget(struct mob_data *md, struct block_list *target, *------------------------------------------*/ int mob_target(struct mob_data *md,struct block_list *bl,int dist) { - nullpo_ret(md); - nullpo_ret(bl); - - // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending. - if (md->target_id && !mob_can_changetarget(md, bl, status_get_mode(&md->bl))) - return 0; - - if (!status_check_skilluse(&md->bl, bl, 0, 0)) - return 0; - - md->target_id = bl->id; // Since there was no disturbance, it locks on to target. - if (md->state.provoke_flag && bl->id != md->state.provoke_flag) - md->state.provoke_flag = 0; - md->min_chase=dist+md->db->range3; - if (md->min_chase>MAX_MINCHASE) - md->min_chase=MAX_MINCHASE; - return 0; + nullpo_ret(md); + nullpo_ret(bl); + + // Nothing will be carried out if there is no mind of changing TAGE by TAGE ending. + if(md->target_id && !mob_can_changetarget(md, bl, status_get_mode(&md->bl))) + return 0; + + if(!status_check_skilluse(&md->bl, bl, 0, 0)) + return 0; + + md->target_id = bl->id; // Since there was no disturbance, it locks on to target. + if (md->state.provoke_flag && bl->id != md->state.provoke_flag) + md->state.provoke_flag = 0; + md->min_chase=dist+md->db->range3; + if(md->min_chase>MAX_MINCHASE) + md->min_chase=MAX_MINCHASE; + return 0; } /*========================================== @@ -1023,60 +1050,61 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist) *------------------------------------------*/ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) { - struct mob_data *md; - struct block_list **target; - int mode; - int dist; - - nullpo_ret(bl); - md=va_arg(ap,struct mob_data *); - target= va_arg(ap,struct block_list **); - mode= va_arg(ap,int); - - //If can't seek yet, not an enemy, or you can't attack it, skip. - if ((*target) == bl || !status_check_skilluse(&md->bl, bl, 0, 0)) - return 0; - - if ((mode&MD_TARGETWEAK) && status_get_lv(bl) >= md->level-5) - return 0; - - if (battle_check_target(&md->bl,bl,BCT_ENEMY)<=0) - return 0; - - switch (bl->type) { - case BL_PC: - if (((TBL_PC *)bl)->state.gangsterparadise && - !(status_get_mode(&md->bl)&MD_BOSS)) - return 0; //Gangster paradise protection. - default: - if (battle_config.hom_setting&0x4 && - (*target) && (*target)->type == BL_HOM && bl->type != BL_HOM) - return 0; //For some reason Homun targets are never overriden. - - dist = distance_bl(&md->bl, bl); - if ( - ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) && - battle_check_range(&md->bl,bl,md->db->range2) - ) { //Pick closest target? - - if (map[bl->m].icewall_num && - !path_search_long(NULL,bl->m,md->bl.x,md->bl.y,bl->x,bl->y,CELL_CHKICEWALL)) { - - if (!check_distance_bl(&md->bl, bl, status_get_range(&md->bl))) - return 0; - - } - - (*target) = bl; - md->target_id=bl->id; - md->min_chase= dist + md->db->range3; - if (md->min_chase>MAX_MINCHASE) - md->min_chase=MAX_MINCHASE; - return 1; - } - break; - } - return 0; + struct mob_data *md; + struct block_list **target; + int mode; + int dist; + + nullpo_ret(bl); + md=va_arg(ap,struct mob_data *); + target= va_arg(ap,struct block_list**); + mode= va_arg(ap,int); + + //If can't seek yet, not an enemy, or you can't attack it, skip. + if ((*target) == bl || !status_check_skilluse(&md->bl, bl, 0, 0)) + return 0; + + if ((mode&MD_TARGETWEAK) && status_get_lv(bl) >= md->level-5) + return 0; + + if(battle_check_target(&md->bl,bl,BCT_ENEMY)<=0) + return 0; + + switch (bl->type) + { + case BL_PC: + if (((TBL_PC*)bl)->state.gangsterparadise && + !(status_get_mode(&md->bl)&MD_BOSS)) + return 0; //Gangster paradise protection. + default: + if (battle_config.hom_setting&0x4 && + (*target) && (*target)->type == BL_HOM && bl->type != BL_HOM) + return 0; //For some reason Homun targets are never overriden. + + dist = distance_bl(&md->bl, bl); + if( + ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) && + battle_check_range(&md->bl,bl,md->db->range2) + ) { //Pick closest target? + + if( map[bl->m].icewall_num && + !path_search_long(NULL,bl->m,md->bl.x,md->bl.y,bl->x,bl->y,CELL_CHKICEWALL) ) { + + if( !check_distance_bl(&md->bl, bl, status_get_range(&md->bl) ) ) + return 0; + + } + + (*target) = bl; + md->target_id=bl->id; + md->min_chase= dist + md->db->range3; + if(md->min_chase>MAX_MINCHASE) + md->min_chase=MAX_MINCHASE; + return 1; + } + break; + } + return 0; } /*========================================== @@ -1084,43 +1112,43 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) *------------------------------------------*/ static int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) { - struct mob_data *md; - struct block_list **target; - - nullpo_ret(bl); - md=va_arg(ap,struct mob_data *); - target= va_arg(ap,struct block_list **); - - //If can't seek yet, not an enemy, or you can't attack it, skip. - if ((*target) == bl || - battle_check_target(&md->bl,bl,BCT_ENEMY)<=0 || - !status_check_skilluse(&md->bl, bl, 0, 0)) - return 0; - - if (battle_check_range(&md->bl, bl, md->status.rhw.range)) { - (*target) = bl; - md->target_id=bl->id; - md->min_chase= md->db->range3; - } - return 1; + struct mob_data *md; + struct block_list **target; + + nullpo_ret(bl); + md=va_arg(ap,struct mob_data *); + target= va_arg(ap,struct block_list**); + + //If can't seek yet, not an enemy, or you can't attack it, skip. + if ((*target) == bl || + battle_check_target(&md->bl,bl,BCT_ENEMY)<=0 || + !status_check_skilluse(&md->bl, bl, 0, 0)) + return 0; + + if(battle_check_range (&md->bl, bl, md->status.rhw.range)) + { + (*target) = bl; + md->target_id=bl->id; + md->min_chase= md->db->range3; + } + return 1; } /*========================================== * finds nearby bg ally for guardians looking for users to follow. *------------------------------------------*/ -static int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) -{ - struct mob_data *md; - struct block_list **target; - - nullpo_ret(bl); - md=va_arg(ap,struct mob_data *); - target= va_arg(ap,struct block_list **); - - if (status_check_skilluse(&md->bl, bl, 0, 0) && battle_check_target(&md->bl,bl,BCT_ENEMY)<=0) { - (*target) = bl; - } - return 1; +static int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) { + struct mob_data *md; + struct block_list **target; + + nullpo_ret(bl); + md=va_arg(ap,struct mob_data *); + target= va_arg(ap,struct block_list**); + + if( status_check_skilluse(&md->bl, bl, 0, 0) && battle_check_target(&md->bl,bl,BCT_ENEMY)<=0 ) { + (*target) = bl; + } + return 1; } /*========================================== @@ -1128,130 +1156,131 @@ static int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) *------------------------------------------*/ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap) { - struct mob_data *md; - struct block_list **target; - int dist; - - md=va_arg(ap,struct mob_data *); - target= va_arg(ap,struct block_list **); - - dist=distance_bl(&md->bl, bl); - if (mob_can_reach(md,bl,dist+1, MSS_LOOT) && - ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) //New target closer than previous one. - ) { - (*target) = bl; - md->target_id=bl->id; - md->min_chase=md->db->range3; - } - return 0; + struct mob_data* md; + struct block_list **target; + int dist; + + md=va_arg(ap,struct mob_data *); + target= va_arg(ap,struct block_list**); + + dist=distance_bl(&md->bl, bl); + if(mob_can_reach(md,bl,dist+1, MSS_LOOT) && + ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) //New target closer than previous one. + ) { + (*target) = bl; + md->target_id=bl->id; + md->min_chase=md->db->range3; + } + return 0; } -static int mob_warpchase_sub(struct block_list *bl,va_list ap) -{ - struct block_list *target; - struct npc_data **target_nd; - struct npc_data *nd; - int *min_distance; - int cur_distance; - - target= va_arg(ap, struct block_list *); - target_nd= va_arg(ap, struct npc_data **); - min_distance= va_arg(ap, int *); - - nd = (TBL_NPC *) bl; - - if (nd->subtype != WARP) - return 0; //Not a warp - - if (nd->u.warp.mapindex != map[target->m].index) - return 0; //Does not lead to the same map. - - cur_distance = distance_blxy(target, nd->u.warp.x, nd->u.warp.y); - if (cur_distance < *min_distance) { - //Pick warp that leads closest to target. - *target_nd = nd; - *min_distance = cur_distance; - return 1; - } - return 0; +static int mob_warpchase_sub(struct block_list *bl,va_list ap) { + struct block_list *target; + struct npc_data **target_nd; + struct npc_data *nd; + int *min_distance; + int cur_distance; + + target= va_arg(ap, struct block_list*); + target_nd= va_arg(ap, struct npc_data**); + min_distance= va_arg(ap, int*); + + nd = (TBL_NPC*) bl; + + if(nd->subtype != WARP) + return 0; //Not a warp + + if(nd->u.warp.mapindex != map[target->m].index) + return 0; //Does not lead to the same map. + + cur_distance = distance_blxy(target, nd->u.warp.x, nd->u.warp.y); + if (cur_distance < *min_distance) + { //Pick warp that leads closest to target. + *target_nd = nd; + *min_distance = cur_distance; + return 1; + } + return 0; } /*========================================== * Processing of slave monsters *------------------------------------------*/ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) { - struct block_list *bl; - - bl=map_id2bl(md->master_id); - - if (!bl || status_isdead(bl)) { - status_kill(&md->bl); - return 1; - } - if (bl->prev == NULL) - return 0; //Master not on a map? Could be warping, do not process. - - if (status_get_mode(&md->bl)&MD_CANMOVE) { - //If the mob can move, follow around. [Check by Skotlex] - int old_dist; - - // Distance with between slave and master is measured. - old_dist=md->master_dist; - md->master_dist=distance_bl(&md->bl, bl); - - // Since the master was in near immediately before, teleport is carried out and it pursues. - if (bl->m != md->bl.m || - (old_dist<10 && md->master_dist>18) || - md->master_dist > MAX_MINCHASE - ) { - md->master_dist = 0; - unit_warp(&md->bl,bl->m,bl->x,bl->y,CLR_TELEPORT); - return 1; - } - - if (md->target_id) //Slave is busy with a target. - return 0; - - // Approach master if within view range, chase back to Master's area also if standing on top of the master. - if ((md->master_dist>MOB_SLAVEDISTANCE || md->master_dist == 0) && - unit_can_move(&md->bl)) { - short x = bl->x, y = bl->y; - mob_stop_attack(md); - if (map_search_freecell(&md->bl, bl->m, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 1) - && unit_walktoxy(&md->bl, x, y, 0)) - return 1; - } - } else if (bl->m != md->bl.m && map_flag_gvg(md->bl.m)) { - //Delete the summoned mob if it's in a gvg ground and the master is elsewhere. [Skotlex] - status_kill(&md->bl); - return 1; - } - - //Avoid attempting to lock the master's target too often to avoid unnecessary overload. [Skotlex] - if (DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && !md->target_id) { - struct unit_data *ud = unit_bl2ud(bl); - md->last_linktime = tick; - - if (ud) { - struct block_list *tbl=NULL; - if (ud->target && ud->state.attack_continue) - tbl=map_id2bl(ud->target); - else if (ud->skilltarget) { - tbl = map_id2bl(ud->skilltarget); - //Required check as skilltarget is not always an enemy. [Skotlex] - if (tbl && battle_check_target(&md->bl, tbl, BCT_ENEMY) <= 0) - tbl = NULL; - } - if (tbl && status_check_skilluse(&md->bl, tbl, 0, 0)) { - md->target_id=tbl->id; - md->min_chase=md->db->range3+distance_bl(&md->bl, tbl); - if (md->min_chase>MAX_MINCHASE) - md->min_chase=MAX_MINCHASE; - return 1; - } - } - } - return 0; + struct block_list *bl; + + bl=map_id2bl(md->master_id); + + if (!bl || status_isdead(bl)) { + status_kill(&md->bl); + return 1; + } + if (bl->prev == NULL) + return 0; //Master not on a map? Could be warping, do not process. + + if(status_get_mode(&md->bl)&MD_CANMOVE) + { //If the mob can move, follow around. [Check by Skotlex] + int old_dist; + + // Distance with between slave and master is measured. + old_dist=md->master_dist; + md->master_dist=distance_bl(&md->bl, bl); + + // Since the master was in near immediately before, teleport is carried out and it pursues. + if(bl->m != md->bl.m || + (old_dist<10 && md->master_dist>18) || + md->master_dist > MAX_MINCHASE + ){ + md->master_dist = 0; + unit_warp(&md->bl,bl->m,bl->x,bl->y,CLR_TELEPORT); + return 1; + } + + if(md->target_id) //Slave is busy with a target. + return 0; + + // Approach master if within view range, chase back to Master's area also if standing on top of the master. + if((md->master_dist>MOB_SLAVEDISTANCE || md->master_dist == 0) && + unit_can_move(&md->bl)) + { + short x = bl->x, y = bl->y; + mob_stop_attack(md); + if(map_search_freecell(&md->bl, bl->m, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 1) + && unit_walktoxy(&md->bl, x, y, 0)) + return 1; + } + } else if (bl->m != md->bl.m && map_flag_gvg(md->bl.m)) { + //Delete the summoned mob if it's in a gvg ground and the master is elsewhere. [Skotlex] + status_kill(&md->bl); + return 1; + } + + //Avoid attempting to lock the master's target too often to avoid unnecessary overload. [Skotlex] + if (DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && !md->target_id) + { + struct unit_data *ud = unit_bl2ud(bl); + md->last_linktime = tick; + + if (ud) { + struct block_list *tbl=NULL; + if (ud->target && ud->state.attack_continue) + tbl=map_id2bl(ud->target); + else if (ud->skilltarget) { + tbl = map_id2bl(ud->skilltarget); + //Required check as skilltarget is not always an enemy. [Skotlex] + if (tbl && battle_check_target(&md->bl, tbl, BCT_ENEMY) <= 0) + tbl = NULL; + } + if (tbl && status_check_skilluse(&md->bl, tbl, 0, 0)) { + md->target_id=tbl->id; + md->min_chase=md->db->range3+distance_bl(&md->bl, tbl); + if(md->min_chase>MAX_MINCHASE) + md->min_chase=MAX_MINCHASE; + return 1; + } + } + } + return 0; } /*========================================== @@ -1262,112 +1291,112 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) *------------------------------------------*/ int mob_unlocktarget(struct mob_data *md, unsigned int tick) { - nullpo_ret(md); - - switch (md->state.skillstate) { - case MSS_WALK: - if (md->ud.walktimer != INVALID_TIMER) - break; - //Because it is not unset when the mob finishes walking. - md->state.skillstate = MSS_IDLE; - case MSS_IDLE: - // Idle skill. - if ((md->target_id || !(++md->ud.walk_count%IDLE_SKILL_INTERVAL)) && - mobskill_use(md, tick, -1)) - break; - //Random walk. - if (!md->master_id && - DIFF_TICK(md->next_walktime, tick) <= 0 && - !mob_randomwalk(md,tick)) - //Delay next random walk when this one failed. - md->next_walktime=tick+rnd()%3000; - break; - default: - mob_stop_attack(md); - if (battle_config.mob_ai&0x8) - mob_stop_walking(md,1); //Immediately stop chasing. - md->state.skillstate = MSS_IDLE; - md->next_walktime=tick+rnd()%3000+3000; - break; - } - if (md->target_id) { - md->target_id=0; - unit_set_target(&md->ud, 0); - } - return 0; + nullpo_ret(md); + + switch (md->state.skillstate) { + case MSS_WALK: + if (md->ud.walktimer != INVALID_TIMER) + break; + //Because it is not unset when the mob finishes walking. + md->state.skillstate = MSS_IDLE; + case MSS_IDLE: + // Idle skill. + if ((md->target_id || !(++md->ud.walk_count%IDLE_SKILL_INTERVAL)) && + mobskill_use(md, tick, -1)) + break; + //Random walk. + if (!md->master_id && + DIFF_TICK(md->next_walktime, tick) <= 0 && + !mob_randomwalk(md,tick)) + //Delay next random walk when this one failed. + md->next_walktime=tick+rnd()%3000; + break; + default: + mob_stop_attack(md); + if (battle_config.mob_ai&0x8) + mob_stop_walking(md,1); //Immediately stop chasing. + md->state.skillstate = MSS_IDLE; + md->next_walktime=tick+rnd()%3000+3000; + break; + } + if (md->target_id) { + md->target_id=0; + unit_set_target(&md->ud, 0); + } + return 0; } /*========================================== * Random walk *------------------------------------------*/ int mob_randomwalk(struct mob_data *md,unsigned int tick) { - const int retrycount=20; - int i,x,y,c,d; - int speed; - - nullpo_ret(md); - - if (DIFF_TICK(md->next_walktime,tick)>0 || - !unit_can_move(&md->bl) || - !(status_get_mode(&md->bl)&MD_CANMOVE)) - return 0; - - d =12-md->move_fail_count; - if (d<5) d=5; - for (i=0; i<retrycount; i++) { // Search of a movable place - int r=rnd(); - x=r%(d*2+1)-d; - y=r/(d*2+1)%(d*2+1)-d; - x+=md->bl.x; - y+=md->bl.y; - - if ((map_getcell(md->bl.m,x,y,CELL_CHKPASS)) && unit_walktoxy(&md->bl,x,y,1)) { - break; - } - } - if (i==retrycount) { - md->move_fail_count++; - if (md->move_fail_count>1000) { - ShowWarning("MOB can't move. random spawn %d, class = %d, at %s (%d,%d)\n",md->bl.id,md->class_,map[md->bl.m].name, md->bl.x, md->bl.y); - md->move_fail_count=0; - mob_spawn(md); - } - return 0; - } - speed=status_get_speed(&md->bl); - for (i=c=0; i<md->ud.walkpath.path_len; i++) { // The next walk start time is calculated. - if (md->ud.walkpath.path[i]&1) - c+=speed*14/10; - else - c+=speed; - } - md->state.skillstate=MSS_WALK; - md->move_fail_count=0; - md->next_walktime = tick+rnd()%3000+3000+c; - return 1; + const int retrycount=20; + int i,x,y,c,d; + int speed; + + nullpo_ret(md); + + if(DIFF_TICK(md->next_walktime,tick)>0 || + !unit_can_move(&md->bl) || + !(status_get_mode(&md->bl)&MD_CANMOVE)) + return 0; + + d =12-md->move_fail_count; + if(d<5) d=5; + for(i=0;i<retrycount;i++){ // Search of a movable place + int r=rnd(); + x=r%(d*2+1)-d; + y=r/(d*2+1)%(d*2+1)-d; + x+=md->bl.x; + y+=md->bl.y; + + if((map_getcell(md->bl.m,x,y,CELL_CHKPASS)) && unit_walktoxy(&md->bl,x,y,1)){ + break; + } + } + if(i==retrycount){ + md->move_fail_count++; + if(md->move_fail_count>1000){ + ShowWarning("MOB can't move. random spawn %d, class = %d, at %s (%d,%d)\n",md->bl.id,md->class_,map[md->bl.m].name, md->bl.x, md->bl.y); + md->move_fail_count=0; + mob_spawn(md); + } + return 0; + } + speed=status_get_speed(&md->bl); + for(i=c=0;i<md->ud.walkpath.path_len;i++){ // The next walk start time is calculated. + if(md->ud.walkpath.path[i]&1) + c+=speed*14/10; + else + c+=speed; + } + md->state.skillstate=MSS_WALK; + md->move_fail_count=0; + md->next_walktime = tick+rnd()%3000+3000+c; + return 1; } int mob_warpchase(struct mob_data *md, struct block_list *target) { - struct npc_data *warp = NULL; - int distance = AREA_SIZE; - if (!(target && battle_config.mob_ai&0x40 && battle_config.mob_warp&1)) - return 0; //Can't warp chase. + struct npc_data *warp = NULL; + int distance = AREA_SIZE; + if (!(target && battle_config.mob_ai&0x40 && battle_config.mob_warp&1)) + return 0; //Can't warp chase. - if (target->m == md->bl.m && check_distance_bl(&md->bl, target, AREA_SIZE)) - return 0; //No need to do a warp chase. + if (target->m == md->bl.m && check_distance_bl(&md->bl, target, AREA_SIZE)) + return 0; //No need to do a warp chase. - if (md->ud.walktimer != INVALID_TIMER && - map_getcell(md->bl.m,md->ud.to_x,md->ud.to_y,CELL_CHKNPC)) - return 1; //Already walking to a warp. + if (md->ud.walktimer != INVALID_TIMER && + map_getcell(md->bl.m,md->ud.to_x,md->ud.to_y,CELL_CHKNPC)) + return 1; //Already walking to a warp. - //Search for warps within mob's viewing range. - map_foreachinrange(mob_warpchase_sub, &md->bl, - md->db->range2, BL_NPC, target, &warp, &distance); + //Search for warps within mob's viewing range. + map_foreachinrange (mob_warpchase_sub, &md->bl, + md->db->range2, BL_NPC, target, &warp, &distance); - if (warp && unit_walktobl(&md->bl, &warp->bl, 1, 1)) - return 1; - return 0; + if (warp && unit_walktobl(&md->bl, &warp->bl, 1, 1)) + return 1; + return 0; } /*========================================== @@ -1375,269 +1404,281 @@ int mob_warpchase(struct mob_data *md, struct block_list *target) *------------------------------------------*/ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) { - struct block_list *tbl = NULL, *abl = NULL; - int dist; - int mode; - int search_size; - int view_range, can_move; - - if (md->bl.prev == NULL || md->status.hp <= 0) - return false; - - if (DIFF_TICK(tick, md->last_thinktime) < MIN_MOBTHINKTIME) - return false; - - md->last_thinktime = tick; - - if (md->ud.skilltimer != INVALID_TIMER) - return false; - - if (md->ud.walktimer != INVALID_TIMER && md->ud.walkpath.path_pos <= 3) - return false; - - // Abnormalities - if ((md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE) - || md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {//Should reset targets. - md->target_id = md->attacked_id = 0; - return false; - } - - if (md->sc.count && md->sc.data[SC_BLIND]) - view_range = 3; - else - view_range = md->db->range2; - mode = status_get_mode(&md->bl); - - can_move = (mode&MD_CANMOVE)&&unit_can_move(&md->bl); - - if (md->target_id) { - //Check validity of current target. [Skotlex] - tbl = map_id2bl(md->target_id); - if (!tbl || tbl->m != md->bl.m || - (md->ud.attacktimer == INVALID_TIMER && !status_check_skilluse(&md->bl, tbl, 0, 0)) || - (md->ud.walktimer != INVALID_TIMER && !(battle_config.mob_ai&0x1) && !check_distance_bl(&md->bl, tbl, md->min_chase)) || - ( - tbl->type == BL_PC && - ((((TBL_PC *)tbl)->state.gangsterparadise && !(mode&MD_BOSS)) || - ((TBL_PC *)tbl)->invincible_timer != INVALID_TIMER) - )) { //Unlock current target. - if (mob_warpchase(md, tbl)) - return true; //Chasing this target. - mob_unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Imediately do random walk. - tbl = NULL; - } - } - - // Check for target change. - if (md->attacked_id && mode&MD_CANATTACK) { - if (md->attacked_id == md->target_id) { - //Rude attacked check. - if (!battle_check_range(&md->bl, tbl, md->status.rhw.range) - && ( //Can't attack back and can't reach back. - (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) - || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNSTRAP] - || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target. - || !mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) - ) - && md->state.attacked_count++ >= RUDE_ATTACKED_COUNT - && !mobskill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack - && can_move && unit_escape(&md->bl, tbl, rnd()%10 +1)) { // Attempt escape - //Escaped - md->attacked_id = 0; - return true; - } - } else if ((abl = map_id2bl(md->attacked_id)) && (!tbl || mob_can_changetarget(md, abl, mode))) { - if (md->bl.m != abl->m || abl->prev == NULL - || (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE // Attacker longer than visual area - || battle_check_target(&md->bl, abl, BCT_ENEMY) <= 0 // Attacker is not enemy of mob - || (battle_config.mob_ai&0x2 && !status_check_skilluse(&md->bl, abl, 0, 0)) // Cannot normal attack back to Attacker - || (!battle_check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ... - && ( // Reach check - (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) - || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNSTRAP] - || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target. - || !mob_can_reach(md, abl, dist+md->db->range3, MSS_RUSH) - ) - )) { - // Rude attacked - if (md->state.attacked_count++ >= RUDE_ATTACKED_COUNT - && !mobskill_use(md, tick, MSC_RUDEATTACKED) && can_move - && !tbl && unit_escape(&md->bl, abl, rnd()%10 +1)) { - //Escaped. - //TODO: Maybe it shouldn't attempt to run if it has another, valid target? - md->attacked_id = 0; - return true; - } - } else if (!(battle_config.mob_ai&0x2) && !status_check_skilluse(&md->bl, abl, 0, 0)) { - //Can't attack back, but didn't invoke a rude attacked skill... - } else { - //Attackable - if (!tbl || dist < md->status.rhw.range || !check_distance_bl(&md->bl, tbl, dist) - || battle_gettarget(tbl) != md->bl.id) { - //Change if the new target is closer than the actual one - //or if the previous target is not attacking the mob. [Skotlex] - md->target_id = md->attacked_id; // set target - if (md->state.attacked_count) - md->state.attacked_count--; //Should we reset rude attack count? - md->min_chase = dist+md->db->range3; - if (md->min_chase>MAX_MINCHASE) - md->min_chase=MAX_MINCHASE; - tbl = abl; //Set the new target - } - } - } - - //Clear it since it's been checked for already. - md->attacked_id = 0; - } - - // Processing of slave monster - if (md->master_id > 0 && mob_ai_sub_hard_slavemob(md, tick)) - return true; - - // Scan area for targets - if (!tbl && mode&MD_LOOTER && md->lootitem && DIFF_TICK(tick, md->ud.canact_tick) > 0 && - (md->lootitem_count < LOOTITEM_SIZE || battle_config.monster_loot_type != 1)) { - // Scan area for items to loot, avoid trying to loot of the mob is full and can't consume the items. - map_foreachinrange(mob_ai_sub_hard_lootsearch, &md->bl, view_range, BL_ITEM, md, &tbl); - } - - if ((!tbl && mode&MD_AGGRESSIVE) || md->state.skillstate == MSS_FOLLOW) { - map_foreachinrange(mob_ai_sub_hard_activesearch, &md->bl, view_range, DEFAULT_ENEMY_TYPE(md), md, &tbl, mode); - } else if (mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) { - search_size = view_range<md->status.rhw.range ? view_range:md->status.rhw.range; - map_foreachinrange(mob_ai_sub_hard_changechase, &md->bl, search_size, DEFAULT_ENEMY_TYPE(md), md, &tbl); - } - - if (!tbl) { //No targets available. - if (mode&MD_ANGRY && !md->state.aggressive) - md->state.aggressive = 1; //Restore angry state when no targets are available. - - /* bg guardians follow allies when no targets nearby */ - if (md->bg_id && mode&MD_CANATTACK) { - if (md->ud.walktimer != INVALID_TIMER) - return true;/* we are already moving */ - map_foreachinrange(mob_ai_sub_hard_bg_ally, &md->bl, view_range, BL_PC, md, &tbl, mode); - if (tbl) { - if (distance_blxy(&md->bl, tbl->x, tbl->y) <= 3 || unit_walktobl(&md->bl, tbl, 1, 1)) - return true;/* we're moving or close enough don't unlock the target. */ - } - } - - //This handles triggering idle walk/skill. - mob_unlocktarget(md, tick); - return true; - } - - //Target exists, attack or loot as applicable. - if (tbl->type == BL_ITEM) { - //Loot time. - struct flooritem_data *fitem; - if (md->ud.target == tbl->id && md->ud.walktimer != INVALID_TIMER) - return true; //Already locked. - if (md->lootitem == NULL) { - //Can't loot... - mob_unlocktarget(md, tick); - return true; - } - if (!check_distance_bl(&md->bl, tbl, 1)) { - //Still not within loot range. - if (!(mode&MD_CANMOVE)) { - //A looter that can't move? Real smart. - mob_unlocktarget(md,tick); - return true; - } - if (!can_move) //Stuck. Wait before walking. - return true; - md->state.skillstate = MSS_LOOT; - if (!unit_walktobl(&md->bl, tbl, 1, 1)) - mob_unlocktarget(md, tick); //Can't loot... - return true; - } - //Within looting range. - if (md->ud.attacktimer != INVALID_TIMER) - return true; //Busy attacking? - - fitem = (struct flooritem_data *)tbl; - //Logs items, taken by (L)ooter Mobs [Lupus] - log_pick_mob(md, LOG_TYPE_LOOT, fitem->item_data.amount, &fitem->item_data); - - if (md->lootitem_count < LOOTITEM_SIZE) { - memcpy(&md->lootitem[md->lootitem_count++], &fitem->item_data, sizeof(md->lootitem[0])); - } else { //Destroy first looted item... - if (md->lootitem[0].card[0] == CARD0_PET) - intif_delete_petdata(MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2])); - memmove(&md->lootitem[0], &md->lootitem[1], (LOOTITEM_SIZE-1)*sizeof(md->lootitem[0])); - memcpy(&md->lootitem[LOOTITEM_SIZE-1], &fitem->item_data, sizeof(md->lootitem[0])); - } - if (pcdb_checkid(md->vd->class_)) { - //Give them walk act/delay to properly mimic players. [Skotlex] - clif_takeitem(&md->bl,tbl); - md->ud.canact_tick = tick + md->status.amotion; - unit_set_walkdelay(&md->bl, tick, md->status.amotion, 1); - } - //Clear item. - map_clearflooritem(tbl); - mob_unlocktarget(md,tick); - return true; - } - //Attempt to attack. - //At this point we know the target is attackable, we just gotta check if the range matches. - if (md->ud.target == tbl->id && md->ud.attacktimer != INVALID_TIMER) //Already locked. - return true; - - if (battle_check_range(&md->bl, tbl, md->status.rhw.range)) { - //Target within range, engage - - if (tbl->type == BL_PC) - mob_log_damage(md, tbl, 0); //Log interaction (counts as 'attacker' for the exp bonus) - unit_attack(&md->bl,tbl->id,1); - return true; - } - - //Out of range... - if (!(mode&MD_CANMOVE)) { - //Can't chase. Attempt an idle skill before unlocking. - md->state.skillstate = MSS_IDLE; - if (!mobskill_use(md, tick, -1)) - mob_unlocktarget(md,tick); - return true; - } - - if (!can_move) { - //Stuck. Attempt an idle skill - md->state.skillstate = MSS_IDLE; - if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL)) - mobskill_use(md, tick, -1); - return true; - } - - if (md->ud.walktimer != INVALID_TIMER && md->ud.target == tbl->id && - ( - !(battle_config.mob_ai&0x1) || - check_distance_blxy(tbl, md->ud.to_x, md->ud.to_y, md->status.rhw.range) - )) //Current target tile is still within attack range. - return true; - - //Follow up if possible. - if (!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) || - !unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2)) - mob_unlocktarget(md,tick); - - return true; + struct block_list *tbl = NULL, *abl = NULL; + int dist; + int mode; + int search_size; + int view_range, can_move; + + if(md->bl.prev == NULL || md->status.hp <= 0) + return false; + + if (DIFF_TICK(tick, md->last_thinktime) < MIN_MOBTHINKTIME) + return false; + + md->last_thinktime = tick; + + if (md->ud.skilltimer != INVALID_TIMER) + return false; + + if(md->ud.walktimer != INVALID_TIMER && md->ud.walkpath.path_pos <= 3) + return false; + + // Abnormalities + if(( md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE ) + || md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {//Should reset targets. + md->target_id = md->attacked_id = 0; + return false; + } + + if (md->sc.count && md->sc.data[SC_BLIND]) + view_range = 3; + else + view_range = md->db->range2; + mode = status_get_mode(&md->bl); + + can_move = (mode&MD_CANMOVE)&&unit_can_move(&md->bl); + + if (md->target_id) + { //Check validity of current target. [Skotlex] + tbl = map_id2bl(md->target_id); + if (!tbl || tbl->m != md->bl.m || + (md->ud.attacktimer == INVALID_TIMER && !status_check_skilluse(&md->bl, tbl, 0, 0)) || + (md->ud.walktimer != INVALID_TIMER && !(battle_config.mob_ai&0x1) && !check_distance_bl(&md->bl, tbl, md->min_chase)) || + ( + tbl->type == BL_PC && + ((((TBL_PC*)tbl)->state.gangsterparadise && !(mode&MD_BOSS)) || + ((TBL_PC*)tbl)->invincible_timer != INVALID_TIMER) + )) { //Unlock current target. + if (mob_warpchase(md, tbl)) + return true; //Chasing this target. + mob_unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Imediately do random walk. + tbl = NULL; + } + } + + // Check for target change. + if( md->attacked_id && mode&MD_CANATTACK ) + { + if( md->attacked_id == md->target_id ) + { //Rude attacked check. + if( !battle_check_range(&md->bl, tbl, md->status.rhw.range) + && ( //Can't attack back and can't reach back. + (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) + || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNSTRAP] + || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target. + || !mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) + ) + && md->state.attacked_count++ >= RUDE_ATTACKED_COUNT + && !mobskill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack + && can_move && unit_escape(&md->bl, tbl, rnd()%10 +1)) // Attempt escape + { //Escaped + md->attacked_id = 0; + return true; + } + } + else + if( (abl = map_id2bl(md->attacked_id)) && (!tbl || mob_can_changetarget(md, abl, mode)) ) + { + if( md->bl.m != abl->m || abl->prev == NULL + || (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE // Attacker longer than visual area + || battle_check_target(&md->bl, abl, BCT_ENEMY) <= 0 // Attacker is not enemy of mob + || (battle_config.mob_ai&0x2 && !status_check_skilluse(&md->bl, abl, 0, 0)) // Cannot normal attack back to Attacker + || (!battle_check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ... + && ( // Reach check + (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) + || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNSTRAP] + || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target. + || !mob_can_reach(md, abl, dist+md->db->range3, MSS_RUSH) + ) + ) ) + { // Rude attacked + if (md->state.attacked_count++ >= RUDE_ATTACKED_COUNT + && !mobskill_use(md, tick, MSC_RUDEATTACKED) && can_move + && !tbl && unit_escape(&md->bl, abl, rnd()%10 +1)) + { //Escaped. + //TODO: Maybe it shouldn't attempt to run if it has another, valid target? + md->attacked_id = 0; + return true; + } + } + else + if (!(battle_config.mob_ai&0x2) && !status_check_skilluse(&md->bl, abl, 0, 0)) + { + //Can't attack back, but didn't invoke a rude attacked skill... + } + else + { //Attackable + if (!tbl || dist < md->status.rhw.range || !check_distance_bl(&md->bl, tbl, dist) + || battle_gettarget(tbl) != md->bl.id) + { //Change if the new target is closer than the actual one + //or if the previous target is not attacking the mob. [Skotlex] + md->target_id = md->attacked_id; // set target + if (md->state.attacked_count) + md->state.attacked_count--; //Should we reset rude attack count? + md->min_chase = dist+md->db->range3; + if(md->min_chase>MAX_MINCHASE) + md->min_chase=MAX_MINCHASE; + tbl = abl; //Set the new target + } + } + } + + //Clear it since it's been checked for already. + md->attacked_id = 0; + } + + // Processing of slave monster + if (md->master_id > 0 && mob_ai_sub_hard_slavemob(md, tick)) + return true; + + // Scan area for targets + if (!tbl && mode&MD_LOOTER && md->lootitem && DIFF_TICK(tick, md->ud.canact_tick) > 0 && + (md->lootitem_count < LOOTITEM_SIZE || battle_config.monster_loot_type != 1)) + { // Scan area for items to loot, avoid trying to loot of the mob is full and can't consume the items. + map_foreachinrange (mob_ai_sub_hard_lootsearch, &md->bl, view_range, BL_ITEM, md, &tbl); + } + + if ((!tbl && mode&MD_AGGRESSIVE) || md->state.skillstate == MSS_FOLLOW) + { + map_foreachinrange (mob_ai_sub_hard_activesearch, &md->bl, view_range, DEFAULT_ENEMY_TYPE(md), md, &tbl, mode); + } + else + if (mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) + { + search_size = view_range<md->status.rhw.range ? view_range:md->status.rhw.range; + map_foreachinrange (mob_ai_sub_hard_changechase, &md->bl, search_size, DEFAULT_ENEMY_TYPE(md), md, &tbl); + } + + if (!tbl) { //No targets available. + if (mode&MD_ANGRY && !md->state.aggressive) + md->state.aggressive = 1; //Restore angry state when no targets are available. + + /* bg guardians follow allies when no targets nearby */ + if( md->bg_id && mode&MD_CANATTACK ) { + if( md->ud.walktimer != INVALID_TIMER ) + return true;/* we are already moving */ + map_foreachinrange (mob_ai_sub_hard_bg_ally, &md->bl, view_range, BL_PC, md, &tbl, mode); + if( tbl ) { + if( distance_blxy(&md->bl, tbl->x, tbl->y) <= 3 || unit_walktobl(&md->bl, tbl, 1, 1) ) + return true;/* we're moving or close enough don't unlock the target. */ + } + } + + //This handles triggering idle walk/skill. + mob_unlocktarget(md, tick); + return true; + } + + //Target exists, attack or loot as applicable. + if (tbl->type == BL_ITEM) + { //Loot time. + struct flooritem_data *fitem; + if (md->ud.target == tbl->id && md->ud.walktimer != INVALID_TIMER) + return true; //Already locked. + if (md->lootitem == NULL) + { //Can't loot... + mob_unlocktarget (md, tick); + return true; + } + if (!check_distance_bl(&md->bl, tbl, 1)) + { //Still not within loot range. + if (!(mode&MD_CANMOVE)) + { //A looter that can't move? Real smart. + mob_unlocktarget(md,tick); + return true; + } + if (!can_move) //Stuck. Wait before walking. + return true; + md->state.skillstate = MSS_LOOT; + if (!unit_walktobl(&md->bl, tbl, 1, 1)) + mob_unlocktarget(md, tick); //Can't loot... + return true; + } + //Within looting range. + if (md->ud.attacktimer != INVALID_TIMER) + return true; //Busy attacking? + + fitem = (struct flooritem_data *)tbl; + //Logs items, taken by (L)ooter Mobs [Lupus] + log_pick_mob(md, LOG_TYPE_LOOT, fitem->item_data.amount, &fitem->item_data); + + if (md->lootitem_count < LOOTITEM_SIZE) { + memcpy (&md->lootitem[md->lootitem_count++], &fitem->item_data, sizeof(md->lootitem[0])); + } else { //Destroy first looted item... + if (md->lootitem[0].card[0] == CARD0_PET) + intif_delete_petdata( MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2]) ); + memmove(&md->lootitem[0], &md->lootitem[1], (LOOTITEM_SIZE-1)*sizeof(md->lootitem[0])); + memcpy (&md->lootitem[LOOTITEM_SIZE-1], &fitem->item_data, sizeof(md->lootitem[0])); + } + if (pcdb_checkid(md->vd->class_)) + { //Give them walk act/delay to properly mimic players. [Skotlex] + clif_takeitem(&md->bl,tbl); + md->ud.canact_tick = tick + md->status.amotion; + unit_set_walkdelay(&md->bl, tick, md->status.amotion, 1); + } + //Clear item. + map_clearflooritem (tbl); + mob_unlocktarget (md,tick); + return true; + } + //Attempt to attack. + //At this point we know the target is attackable, we just gotta check if the range matches. + if (md->ud.target == tbl->id && md->ud.attacktimer != INVALID_TIMER) //Already locked. + return true; + + if (battle_check_range (&md->bl, tbl, md->status.rhw.range)) + { //Target within range, engage + + if(tbl->type == BL_PC) + mob_log_damage(md, tbl, 0); //Log interaction (counts as 'attacker' for the exp bonus) + unit_attack(&md->bl,tbl->id,1); + return true; + } + + //Out of range... + if (!(mode&MD_CANMOVE)) + { //Can't chase. Attempt an idle skill before unlocking. + md->state.skillstate = MSS_IDLE; + if (!mobskill_use(md, tick, -1)) + mob_unlocktarget(md,tick); + return true; + } + + if (!can_move) + { //Stuck. Attempt an idle skill + md->state.skillstate = MSS_IDLE; + if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL)) + mobskill_use(md, tick, -1); + return true; + } + + if (md->ud.walktimer != INVALID_TIMER && md->ud.target == tbl->id && + ( + !(battle_config.mob_ai&0x1) || + check_distance_blxy(tbl, md->ud.to_x, md->ud.to_y, md->status.rhw.range) + )) //Current target tile is still within attack range. + return true; + + //Follow up if possible. + if(!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) || + !unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2)) + mob_unlocktarget(md,tick); + + return true; } static int mob_ai_sub_hard_timer(struct block_list *bl,va_list ap) { - struct mob_data *md = (struct mob_data *)bl; - unsigned int tick = va_arg(ap, unsigned int); - if (mob_ai_sub_hard(md, tick)) { - //Hard AI triggered. - if (!md->state.spotted) - md->state.spotted = 1; - md->last_pcneartime = tick; - } - return 0; + struct mob_data *md = (struct mob_data*)bl; + unsigned int tick = va_arg(ap, unsigned int); + if (mob_ai_sub_hard(md, tick)) + { //Hard AI triggered. + if(!md->state.spotted) + md->state.spotted = 1; + md->last_pcneartime = tick; + } + return 0; } /*========================================== @@ -1645,11 +1686,11 @@ static int mob_ai_sub_hard_timer(struct block_list *bl,va_list ap) *------------------------------------------*/ static int mob_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) { - unsigned int tick; - tick=va_arg(ap,unsigned int); - map_foreachinrange(mob_ai_sub_hard_timer,&sd->bl, AREA_SIZE+ACTIVE_AI_RANGE, BL_MOB,tick); + unsigned int tick; + tick=va_arg(ap,unsigned int); + map_foreachinrange(mob_ai_sub_hard_timer,&sd->bl, AREA_SIZE+ACTIVE_AI_RANGE, BL_MOB,tick); - return 0; + return 0; } /*========================================== @@ -1657,61 +1698,68 @@ static int mob_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) *------------------------------------------*/ static int mob_ai_sub_lazy(struct mob_data *md, va_list args) { - unsigned int tick; - - nullpo_ret(md); - - if (md->bl.prev == NULL) - return 0; - - tick = va_arg(args,unsigned int); - - if (battle_config.mob_ai&0x20 && map[md->bl.m].users>0) - return (int)mob_ai_sub_hard(md, tick); - - if (md->bl.prev==NULL || md->status.hp == 0) - return 1; - - if (battle_config.mob_active_time && - md->last_pcneartime && - !(md->status.mode&MD_BOSS) && - DIFF_TICK(tick,md->last_thinktime) > MIN_MOBTHINKTIME) { - if (DIFF_TICK(tick,md->last_pcneartime) < battle_config.mob_active_time) - return (int)mob_ai_sub_hard(md, tick); - md->last_pcneartime = 0; - } - - if (battle_config.boss_active_time && - md->last_pcneartime && - (md->status.mode&MD_BOSS) && - DIFF_TICK(tick,md->last_thinktime) > MIN_MOBTHINKTIME) { - if (DIFF_TICK(tick,md->last_pcneartime) < battle_config.boss_active_time) - return (int)mob_ai_sub_hard(md, tick); - md->last_pcneartime = 0; - } - - if (DIFF_TICK(tick,md->last_thinktime)< 10*MIN_MOBTHINKTIME) - return 0; - - md->last_thinktime=tick; - - if (md->master_id) { - mob_ai_sub_hard_slavemob(md,tick); - return 0; - } - - if (DIFF_TICK(md->next_walktime,tick) < 0 && (status_get_mode(&md->bl)&MD_CANMOVE) && unit_can_move(&md->bl)) { - if (map[md->bl.m].users > 0) { - if (rnd()%1000 < MOB_LAZYMOVEPERC(md)) - mob_randomwalk(md, tick); - else if (rnd()%1000 < MOB_LAZYSKILLPERC) //Chance to do a mob's idle skill. - mobskill_use(md, tick, -1); - } else { - if (rnd()%1000 < MOB_LAZYMOVEPERC(md)) - mob_randomwalk(md, tick); - } - } - return 0; + unsigned int tick; + + nullpo_ret(md); + + if(md->bl.prev == NULL) + return 0; + + tick = va_arg(args,unsigned int); + + if (battle_config.mob_ai&0x20 && map[md->bl.m].users>0) + return (int)mob_ai_sub_hard(md, tick); + + if (md->bl.prev==NULL || md->status.hp == 0) + return 1; + + if(battle_config.mob_active_time && + md->last_pcneartime && + !(md->status.mode&MD_BOSS) && + DIFF_TICK(tick,md->last_thinktime) > MIN_MOBTHINKTIME) + { + if (DIFF_TICK(tick,md->last_pcneartime) < battle_config.mob_active_time) + return (int)mob_ai_sub_hard(md, tick); + md->last_pcneartime = 0; + } + + if(battle_config.boss_active_time && + md->last_pcneartime && + (md->status.mode&MD_BOSS) && + DIFF_TICK(tick,md->last_thinktime) > MIN_MOBTHINKTIME) + { + if (DIFF_TICK(tick,md->last_pcneartime) < battle_config.boss_active_time) + return (int)mob_ai_sub_hard(md, tick); + md->last_pcneartime = 0; + } + + if(DIFF_TICK(tick,md->last_thinktime)< 10*MIN_MOBTHINKTIME) + return 0; + + md->last_thinktime=tick; + + if (md->master_id) { + mob_ai_sub_hard_slavemob (md,tick); + return 0; + } + + if( DIFF_TICK(md->next_walktime,tick) < 0 && (status_get_mode(&md->bl)&MD_CANMOVE) && unit_can_move(&md->bl) ) + { + if( map[md->bl.m].users > 0 ) + { + if( rnd()%1000 < MOB_LAZYMOVEPERC(md) ) + mob_randomwalk(md, tick); + else + if( rnd()%1000 < MOB_LAZYSKILLPERC ) //Chance to do a mob's idle skill. + mobskill_use(md, tick, -1); + } + else + { + if( rnd()%1000 < MOB_LAZYMOVEPERC(md) ) + mob_randomwalk(md, tick); + } + } + return 0; } /*========================================== @@ -1719,8 +1767,8 @@ static int mob_ai_sub_lazy(struct mob_data *md, va_list args) *------------------------------------------*/ static int mob_ai_lazy(int tid, unsigned int tick, int id, intptr_t data) { - map_foreachmob(mob_ai_sub_lazy,tick); - return 0; + map_foreachmob(mob_ai_sub_lazy,tick); + return 0; } /*========================================== @@ -1729,35 +1777,37 @@ static int mob_ai_lazy(int tid, unsigned int tick, int id, intptr_t data) static int mob_ai_hard(int tid, unsigned int tick, int id, intptr_t data) { - if (battle_config.mob_ai&0x20) - map_foreachmob(mob_ai_sub_lazy,tick); - else - map_foreachpc(mob_ai_sub_foreachclient,tick); + if (battle_config.mob_ai&0x20) + map_foreachmob(mob_ai_sub_lazy,tick); + else + map_foreachpc(mob_ai_sub_foreachclient,tick); - return 0; + return 0; } /*========================================== * Initializes the delay drop structure for mob-dropped items. *------------------------------------------*/ -static struct item_drop *mob_setdropitem(int nameid, int qty) { - struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop); - memset(&drop->item_data, 0, sizeof(struct item)); - drop->item_data.nameid = nameid; - drop->item_data.amount = qty; - drop->item_data.identify = itemdb_isidentified(nameid); - drop->next = NULL; - return drop; +static struct item_drop* mob_setdropitem(int nameid, int qty) +{ + struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop); + memset(&drop->item_data, 0, sizeof(struct item)); + drop->item_data.nameid = nameid; + drop->item_data.amount = qty; + drop->item_data.identify = itemdb_isidentified(nameid); + drop->next = NULL; + return drop; } /*========================================== * Initializes the delay drop structure for mob-looted items. *------------------------------------------*/ -static struct item_drop *mob_setlootitem(struct item *item) { - struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop); - memcpy(&drop->item_data, item, sizeof(struct item)); - drop->next = NULL; - return drop; +static struct item_drop* mob_setlootitem(struct item* item) +{ + struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop); + memcpy(&drop->item_data, item, sizeof(struct item)); + drop->next = NULL; + return drop; } /*========================================== @@ -1765,20 +1815,20 @@ static struct item_drop *mob_setlootitem(struct item *item) { *------------------------------------------*/ static int mob_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data) { - struct item_drop_list *list; - struct item_drop *ditem, *ditem_prev; - list=(struct item_drop_list *)data; - ditem = list->item; - while (ditem) { - map_addflooritem(&ditem->item_data,ditem->item_data.amount, - list->m,list->x,list->y, - list->first_charid,list->second_charid,list->third_charid,0); - ditem_prev = ditem; - ditem = ditem->next; - ers_free(item_drop_ers, ditem_prev); - } - ers_free(item_drop_list_ers, list); - return 0; + struct item_drop_list *list; + struct item_drop *ditem, *ditem_prev; + list=(struct item_drop_list *)data; + ditem = list->item; + while (ditem) { + map_addflooritem(&ditem->item_data,ditem->item_data.amount, + list->m,list->x,list->y, + list->first_charid,list->second_charid,list->third_charid,0); + ditem_prev = ditem; + ditem = ditem->next; + ers_free(item_drop_ers, ditem_prev); + } + ers_free(item_drop_list_ers, list); + return 0; } /*========================================== @@ -1789,50 +1839,52 @@ static int mob_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data *------------------------------------------*/ static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct item_drop *ditem, int loot, int drop_rate, unsigned short flag) { - TBL_PC *sd; + TBL_PC* sd; - //Logs items, dropped by mobs [Lupus] - log_pick_mob(md, loot?LOG_TYPE_LOOT:LOG_TYPE_PICKDROP_MONSTER, -ditem->item_data.amount, &ditem->item_data); + //Logs items, dropped by mobs [Lupus] + log_pick_mob(md, loot?LOG_TYPE_LOOT:LOG_TYPE_PICKDROP_MONSTER, -ditem->item_data.amount, &ditem->item_data); - sd = map_charid2sd(dlist->first_charid); - if (sd == NULL) sd = map_charid2sd(dlist->second_charid); - if (sd == NULL) sd = map_charid2sd(dlist->third_charid); + sd = map_charid2sd(dlist->first_charid); + if( sd == NULL ) sd = map_charid2sd(dlist->second_charid); + if( sd == NULL ) sd = map_charid2sd(dlist->third_charid); - if (sd - && (drop_rate <= sd->state.autoloot || pc_isautolooting(sd, ditem->item_data.nameid)) - && (battle_config.idle_no_autoloot == 0 || DIFF_TICK(last_tick, sd->idletime) < battle_config.idle_no_autoloot) - && (battle_config.homunculus_autoloot?1:!flag) + if( sd + && (drop_rate <= sd->state.autoloot || pc_isautolooting(sd, ditem->item_data.nameid)) + && (battle_config.idle_no_autoloot == 0 || DIFF_TICK(last_tick, sd->idletime) < battle_config.idle_no_autoloot) + && (battle_config.homunculus_autoloot?1:!flag) #ifdef AUTOLOOT_DISTANCE - && sd->bl.m == md->bl.m - && check_distance_blxy(&sd->bl, dlist->x, dlist->y, AUTOLOOT_DISTANCE) + && sd->bl.m == md->bl.m + && check_distance_blxy(&sd->bl, dlist->x, dlist->y, AUTOLOOT_DISTANCE) #endif - ) { //Autoloot. - if (party_share_loot(party_search(sd->status.party_id), - sd, &ditem->item_data, sd->status.char_id) == 0 - ) { - ers_free(item_drop_ers, ditem); - return; - } - } - ditem->next = dlist->item; - dlist->item = ditem; + ) { //Autoloot. + if (party_share_loot(party_search(sd->status.party_id), + sd, &ditem->item_data, sd->status.char_id) == 0 + ) { + ers_free(item_drop_ers, ditem); + return; + } + } + ditem->next = dlist->item; + dlist->item = ditem; } int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *bl = map_id2bl(id); - struct mob_data *md = BL_CAST(BL_MOB, bl); - - if (md) { - if (md->deletetimer != tid) { - ShowError("mob_timer_delete: Timer mismatch: %d != %d\n", tid, md->deletetimer); - return 0; - } - //for Alchemist CANNIBALIZE [Lupus] - md->deletetimer = INVALID_TIMER; - unit_free(bl, CLR_TELEPORT); - } - return 0; + struct block_list* bl = map_id2bl(id); + struct mob_data* md = BL_CAST(BL_MOB, bl); + + if( md ) + { + if( md->deletetimer != tid ) + { + ShowError("mob_timer_delete: Timer mismatch: %d != %d\n", tid, md->deletetimer); + return 0; + } + //for Alchemist CANNIBALIZE [Lupus] + md->deletetimer = INVALID_TIMER; + unit_free(bl, CLR_TELEPORT); + } + return 0; } /*========================================== @@ -1840,16 +1892,16 @@ int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ int mob_deleteslave_sub(struct block_list *bl,va_list ap) { - struct mob_data *md; - int id; + struct mob_data *md; + int id; - nullpo_ret(bl); - nullpo_ret(md = (struct mob_data *)bl); + nullpo_ret(bl); + nullpo_ret(md = (struct mob_data *)bl); - id=va_arg(ap,int); - if (md->master_id > 0 && md->master_id == id) - status_kill(bl); - return 0; + id=va_arg(ap,int); + if(md->master_id > 0 && md->master_id == id ) + status_kill(bl); + return 0; } /*========================================== @@ -1857,170 +1909,179 @@ int mob_deleteslave_sub(struct block_list *bl,va_list ap) *------------------------------------------*/ int mob_deleteslave(struct mob_data *md) { - nullpo_ret(md); + nullpo_ret(md); - map_foreachinmap(mob_deleteslave_sub, md->bl.m, BL_MOB,md->bl.id); - return 0; + map_foreachinmap(mob_deleteslave_sub, md->bl.m, BL_MOB,md->bl.id); + return 0; } // Mob respawning through KAIZEL or NPC_REBIRTH [Skotlex] int mob_respawn(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *bl = map_id2bl(id); + struct block_list *bl = map_id2bl(id); - if (!bl) return 0; - status_revive(bl, (uint8)data, 0); - return 1; + if(!bl) return 0; + status_revive(bl, (uint8)data, 0); + return 1; } void mob_log_damage(struct mob_data *md, struct block_list *src, int damage) { - int char_id = 0, flag = MDLF_NORMAL; - - if (damage < 0) - return; //Do nothing for absorbed damage. - if (!damage && !(src->type&DEFAULT_ENEMY_TYPE(md))) - return; //Do not log non-damaging effects from non-enemies. - if (src->id == md->bl.id) - return; //Do not log self-damage. - - switch (src->type) { - case BL_PC: { - struct map_session_data *sd = (TBL_PC *)src; - char_id = sd->status.char_id; - if (damage) - md->attacked_id = src->id; - break; - } - case BL_HOM: { - struct homun_data *hd = (TBL_HOM *)src; - flag = MDLF_HOMUN; - if (hd->master) - char_id = hd->master->status.char_id; - if (damage) - md->attacked_id = src->id; - break; - } - case BL_MER: { - struct mercenary_data *mer = (TBL_MER *)src; - if (mer->master) - char_id = mer->master->status.char_id; - if (damage) - md->attacked_id = src->id; - break; - } - case BL_PET: { - struct pet_data *pd = (TBL_PET *)src; - flag = MDLF_PET; - if (pd->msd) { - char_id = pd->msd->status.char_id; - if (damage) //Let mobs retaliate against the pet's master [Skotlex] - md->attacked_id = pd->msd->bl.id; - } - break; - } - case BL_MOB: { - struct mob_data *md2 = (TBL_MOB *)src; - if (md2->special_state.ai && md2->master_id) { - struct map_session_data *msd = map_id2sd(md2->master_id); - if (msd) - char_id = msd->status.char_id; - } - if (!damage) - break; - //Let players decide whether to retaliate versus the master or the mob. [Skotlex] - if (md2->master_id && battle_config.retaliate_to_master) - md->attacked_id = md2->master_id; - else - md->attacked_id = src->id; - break; - } - case BL_ELEM: { - struct elemental_data *ele = (TBL_ELEM *)src; - if (ele->master) - char_id = ele->master->status.char_id; - if (damage) - md->attacked_id = src->id; - break; - } - default: //For all unhandled types. - md->attacked_id = src->id; - } - - if (char_id) { - //Log damage... - int i,minpos; - unsigned int mindmg; - for (i=0,minpos=DAMAGELOG_SIZE-1,mindmg=UINT_MAX; i<DAMAGELOG_SIZE; i++) { - if (md->dmglog[i].id==char_id && - md->dmglog[i].flag==flag) - break; - if (md->dmglog[i].id==0) { //Store data in first empty slot. - md->dmglog[i].id = char_id; - md->dmglog[i].flag= flag; - break; - } - if (md->dmglog[i].dmg<mindmg && i) { - //Never overwrite first hit slot (he gets double exp bonus) - minpos=i; - mindmg=md->dmglog[i].dmg; - } - } - if (i<DAMAGELOG_SIZE) - md->dmglog[i].dmg+=damage; - else { - md->dmglog[minpos].id = char_id; - md->dmglog[minpos].flag= flag; - md->dmglog[minpos].dmg = damage; - } - } - return; + int char_id = 0, flag = MDLF_NORMAL; + + if( damage < 0 ) + return; //Do nothing for absorbed damage. + if( !damage && !(src->type&DEFAULT_ENEMY_TYPE(md)) ) + return; //Do not log non-damaging effects from non-enemies. + if( src->id == md->bl.id ) + return; //Do not log self-damage. + + switch( src->type ) + { + case BL_PC: + { + struct map_session_data *sd = (TBL_PC*)src; + char_id = sd->status.char_id; + if( damage ) + md->attacked_id = src->id; + break; + } + case BL_HOM: + { + struct homun_data *hd = (TBL_HOM*)src; + flag = MDLF_HOMUN; + if( hd->master ) + char_id = hd->master->status.char_id; + if( damage ) + md->attacked_id = src->id; + break; + } + case BL_MER: + { + struct mercenary_data *mer = (TBL_MER*)src; + if( mer->master ) + char_id = mer->master->status.char_id; + if( damage ) + md->attacked_id = src->id; + break; + } + case BL_PET: + { + struct pet_data *pd = (TBL_PET*)src; + flag = MDLF_PET; + if( pd->msd ) + { + char_id = pd->msd->status.char_id; + if( damage ) //Let mobs retaliate against the pet's master [Skotlex] + md->attacked_id = pd->msd->bl.id; + } + break; + } + case BL_MOB: + { + struct mob_data* md2 = (TBL_MOB*)src; + if( md2->special_state.ai && md2->master_id ) + { + struct map_session_data* msd = map_id2sd(md2->master_id); + if( msd ) + char_id = msd->status.char_id; + } + if( !damage ) + break; + //Let players decide whether to retaliate versus the master or the mob. [Skotlex] + if( md2->master_id && battle_config.retaliate_to_master ) + md->attacked_id = md2->master_id; + else + md->attacked_id = src->id; + break; + } + case BL_ELEM: + { + struct elemental_data *ele = (TBL_ELEM*)src; + if( ele->master ) + char_id = ele->master->status.char_id; + if( damage ) + md->attacked_id = src->id; + break; + } + default: //For all unhandled types. + md->attacked_id = src->id; + } + + if( char_id ) + { //Log damage... + int i,minpos; + unsigned int mindmg; + for(i=0,minpos=DAMAGELOG_SIZE-1,mindmg=UINT_MAX;i<DAMAGELOG_SIZE;i++){ + if(md->dmglog[i].id==char_id && + md->dmglog[i].flag==flag) + break; + if(md->dmglog[i].id==0) { //Store data in first empty slot. + md->dmglog[i].id = char_id; + md->dmglog[i].flag= flag; + break; + } + if(md->dmglog[i].dmg<mindmg && i) + { //Never overwrite first hit slot (he gets double exp bonus) + minpos=i; + mindmg=md->dmglog[i].dmg; + } + } + if(i<DAMAGELOG_SIZE) + md->dmglog[i].dmg+=damage; + else { + md->dmglog[minpos].id = char_id; + md->dmglog[minpos].flag= flag; + md->dmglog[minpos].dmg = damage; + } + } + return; } //Call when a mob has received damage. void mob_damage(struct mob_data *md, struct block_list *src, int damage) { - if (damage > 0) { //Store total damage... - if (UINT_MAX - (unsigned int)damage > md->tdmg) - md->tdmg+=damage; - else if (md->tdmg == UINT_MAX) - damage = 0; //Stop recording damage once the cap has been reached. - else { //Cap damage log... - damage = (int)(UINT_MAX - md->tdmg); - md->tdmg = UINT_MAX; - } - if (md->state.aggressive) { //No longer aggressive, change to retaliate AI. - md->state.aggressive = 0; - if (md->state.skillstate== MSS_ANGRY) - md->state.skillstate = MSS_BERSERK; - if (md->state.skillstate== MSS_FOLLOW) - md->state.skillstate = MSS_RUSH; - } - //Log damage - if (src) - mob_log_damage(md, src, damage); - md->dmgtick = gettick(); - } - - if (battle_config.show_mob_info&3) - clif_charnameack(0, &md->bl); - - if (!src) - return; + if (damage > 0) { //Store total damage... + if (UINT_MAX - (unsigned int)damage > md->tdmg) + md->tdmg+=damage; + else if (md->tdmg == UINT_MAX) + damage = 0; //Stop recording damage once the cap has been reached. + else { //Cap damage log... + damage = (int)(UINT_MAX - md->tdmg); + md->tdmg = UINT_MAX; + } + if (md->state.aggressive) { //No longer aggressive, change to retaliate AI. + md->state.aggressive = 0; + if(md->state.skillstate== MSS_ANGRY) + md->state.skillstate = MSS_BERSERK; + if(md->state.skillstate== MSS_FOLLOW) + md->state.skillstate = MSS_RUSH; + } + //Log damage + if (src) + mob_log_damage(md, src, damage); + md->dmgtick = gettick(); + } + + if (battle_config.show_mob_info&3) + clif_charnameack (0, &md->bl); + + if (!src) + return; #if PACKETVER >= 20120404 - if (!(md->status.mode&MD_BOSS)) { - int i; - for (i = 0; i < DAMAGELOG_SIZE; i++) { // must show hp bar to all char who already hit the mob. - struct map_session_data *sd = map_charid2sd(md->dmglog[i].id); - if (sd && check_distance_bl(&md->bl, &sd->bl, AREA_SIZE)) // check if in range - clif_monster_hp_bar(md, sd->fd); - } - } + if( !(md->status.mode&MD_BOSS) ){ + int i; + for(i = 0; i < DAMAGELOG_SIZE; i++){ // must show hp bar to all char who already hit the mob. + struct map_session_data *sd = map_charid2sd(md->dmglog[i].id); + if( sd && check_distance_bl(&md->bl, &sd->bl, AREA_SIZE) ) // check if in range + clif_monster_hp_bar(md, sd->fd); + } + } #endif - if (md->special_state.ai == 2) { //LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex] - md->state.alchemist = 1; - mobskill_use(md, gettick(), MSC_ALCHEMIST); - } + if( md->special_state.ai == 2 ) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex] + md->state.alchemist = 1; + mobskill_use(md, gettick(), MSC_ALCHEMIST); + } } /*========================================== @@ -2029,704 +2090,704 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) *------------------------------------------*/ int mob_dead(struct mob_data *md, struct block_list *src, int type) { - struct status_data *status; - struct map_session_data *sd = NULL, *tmpsd[DAMAGELOG_SIZE]; - struct map_session_data *mvp_sd = NULL, *second_sd = NULL, *third_sd = NULL; - - struct { - struct party_data *p; - int id,zeny; - unsigned int base_exp,job_exp; - } pt[DAMAGELOG_SIZE]; - int i,temp,count,pnum=0,m=md->bl.m; - int dmgbltypes = 0; // bitfield of all bl types, that caused damage to the mob and are elligible for exp distribution - unsigned int mvp_damage, tick = gettick(); - bool rebirth, homkillonly; - - status = &md->status; - - if (src && src->type == BL_PC) { - sd = (struct map_session_data *)src; - mvp_sd = sd; - } - - if (md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS) - guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); - - if (src) { - // Use Dead skill only if not killed by Script or Command - md->state.skillstate = MSS_DEAD; - mobskill_use(md,tick,-1); - } - - map_freeblock_lock(); - - memset(pt,0,sizeof(pt)); - - if (src && src->type == BL_MOB) - mob_unlocktarget((struct mob_data *)src,tick); - - // filter out entries not eligible for exp distribution - memset(tmpsd,0,sizeof(tmpsd)); - for (i = 0, count = 0, mvp_damage = 0; i < DAMAGELOG_SIZE && md->dmglog[i].id; i++) { - struct map_session_data *tsd = map_charid2sd(md->dmglog[i].id); - - if (tsd == NULL) - continue; // skip empty entries - if (tsd->bl.m != m) - continue; // skip players not on this map - count++; //Only logged into same map chars are counted for the total. - if (pc_isdead(tsd)) - continue; // skip dead players - if (md->dmglog[i].flag == MDLF_HOMUN && !merc_is_hom_active(tsd->hd)) - continue; // skip homunc's share if inactive - if (md->dmglog[i].flag == MDLF_PET && (!tsd->status.pet_id || !tsd->pd)) - continue; // skip pet's share if inactive - - if (md->dmglog[i].dmg > mvp_damage) { - third_sd = second_sd; - second_sd = mvp_sd; - mvp_sd = tsd; - mvp_damage = md->dmglog[i].dmg; - } - - tmpsd[i] = tsd; // record as valid damage-log entry - - switch (md->dmglog[i].flag) { - case MDLF_NORMAL: - dmgbltypes|= BL_PC; - break; - case MDLF_HOMUN: - dmgbltypes|= BL_HOM; - break; - case MDLF_PET: - dmgbltypes|= BL_PET; - break; - } - } - - // determines, if the monster was killed by homunculus' damage only - homkillonly = (bool)((dmgbltypes&BL_HOM) && !(dmgbltypes&~BL_HOM)); - - if (!battle_config.exp_calc_type && count > 1) { - //Apply first-attacker 200% exp share bonus - //TODO: Determine if this should go before calculating the MVP player instead of after. - if (UINT_MAX - md->dmglog[0].dmg > md->tdmg) { - md->tdmg += md->dmglog[0].dmg; - md->dmglog[0].dmg<<=1; - } else { - md->dmglog[0].dmg+= UINT_MAX - md->tdmg; - md->tdmg = UINT_MAX; - } - } - - if (!(type&2) && //No exp - (!map[m].flag.pvp || battle_config.pvp_exp) && //Pvp no exp rule [MouseJstr] - (!md->master_id || !md->special_state.ai) && //Only player-summoned mobs do not give exp. [Skotlex] - (!map[m].flag.nobaseexp || !map[m].flag.nojobexp) //Gives Exp - ) { //Experience calculation. - int bonus = 100; //Bonus on top of your share (common to all attackers). - if (md->sc.data[SC_RICHMANKIM]) - bonus += md->sc.data[SC_RICHMANKIM]->val2; - if (sd) { - temp = status_get_class(&md->bl); - if (sd->sc.data[SC_MIRACLE]) i = 2; //All mobs are Star Targets - else - ARR_FIND(0, MAX_PC_FEELHATE, i, temp == sd->hate_mob[i] && - (battle_config.allow_skill_without_day || sg_info[i].day_func())); - if (i<MAX_PC_FEELHATE && (temp=pc_checkskill(sd,sg_info[i].bless_id))) - bonus += (i==2?20:10)*temp; - } - if (battle_config.mobs_level_up && md->level > md->db->lv) // [Valaris] - bonus += (md->level-md->db->lv)*battle_config.mobs_level_up_exp_rate; - - for (i = 0; i < DAMAGELOG_SIZE && md->dmglog[i].id; i++) { - int flag=1,zeny=0; - unsigned int base_exp, job_exp; - double per; //Your share of the mob's exp - - if (!tmpsd[i]) continue; - - if (!battle_config.exp_calc_type && md->tdmg) - //jAthena's exp formula based on total damage. - per = (double)md->dmglog[i].dmg/(double)md->tdmg; - else { - //eAthena's exp formula based on max hp. - per = (double)md->dmglog[i].dmg/(double)status->max_hp; - if (per > 2) per = 2; // prevents unlimited exp gain - } - - if (count>1 && battle_config.exp_bonus_attacker) { - //Exp bonus per additional attacker. - if (count > battle_config.exp_bonus_max_attacker) - count = battle_config.exp_bonus_max_attacker; - per += per*((count-1)*battle_config.exp_bonus_attacker)/100.; - } - - // change experience for different sized monsters [Valaris] - if (battle_config.mob_size_influence) { - if (md->special_state.size == SZ_MEDIUM) - per /= 2.; - else if (md->special_state.size == SZ_BIG) - per *= 2.; - } - - if (md->dmglog[i].flag == MDLF_PET) - per *= battle_config.pet_attack_exp_rate/100.; - - if (battle_config.zeny_from_mobs && md->level) { - // zeny calculation moblv + random moblv [Valaris] - zeny=(int)((md->level+rnd()%md->level)*per*bonus/100.); - if (md->db->mexp > 0) - zeny*=rnd()%250; - } - - if (map[m].flag.nobaseexp || !md->db->base_exp) - base_exp = 0; - else - base_exp = (unsigned int)cap_value(md->db->base_exp * per * bonus/100. * map[m].bexp/100., 1, UINT_MAX); - - if (map[m].flag.nojobexp || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost. - job_exp = 0; - else - job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].jexp/100., 1, UINT_MAX); - - if ((temp = tmpsd[i]->status.party_id)>0 /*&& !md->dmglog[i].flag == MDLF_HOMUN*/) { //Homun-done damage (flag 1) is given to party - int j; - for (j=0; j<pnum && pt[j].id!=temp; j++); //Locate party. - - if (j==pnum) { //Possibly add party. - pt[pnum].p = party_search(temp); - if (pt[pnum].p && pt[pnum].p->party.exp) { - pt[pnum].id=temp; - pt[pnum].base_exp=base_exp; - pt[pnum].job_exp=job_exp; - pt[pnum].zeny=zeny; // zeny share [Valaris] - pnum++; - flag=0; - } - } else { //Add to total - if (pt[j].base_exp > UINT_MAX - base_exp) - pt[j].base_exp=UINT_MAX; - else - pt[j].base_exp+=base_exp; - - if (pt[j].job_exp > UINT_MAX - job_exp) - pt[j].job_exp=UINT_MAX; - else - pt[j].job_exp+=job_exp; - - pt[j].zeny+=zeny; // zeny share [Valaris] - flag=0; - } - } - if (flag) { - if (base_exp && md->dmglog[i].flag == MDLF_HOMUN) //tmpsd[i] is null if it has no homunc. - merc_hom_gainexp(tmpsd[i]->hd, base_exp); - if (base_exp || job_exp) { - if (md->dmglog[i].flag != MDLF_PET || battle_config.pet_attack_exp_to_master) { + struct status_data *status; + struct map_session_data *sd = NULL, *tmpsd[DAMAGELOG_SIZE]; + struct map_session_data *mvp_sd = NULL, *second_sd = NULL, *third_sd = NULL; + + struct { + struct party_data *p; + int id,zeny; + unsigned int base_exp,job_exp; + } pt[DAMAGELOG_SIZE]; + int i,temp,count,pnum=0,m=md->bl.m; + int dmgbltypes = 0; // bitfield of all bl types, that caused damage to the mob and are elligible for exp distribution + unsigned int mvp_damage, tick = gettick(); + bool rebirth, homkillonly; + + status = &md->status; + + if( src && src->type == BL_PC ) + { + sd = (struct map_session_data *)src; + mvp_sd = sd; + } + + if( md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS ) + guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); + + if( src ) + { // Use Dead skill only if not killed by Script or Command + md->state.skillstate = MSS_DEAD; + mobskill_use(md,tick,-1); + } + + map_freeblock_lock(); + + memset(pt,0,sizeof(pt)); + + if(src && src->type == BL_MOB) + mob_unlocktarget((struct mob_data *)src,tick); + + // filter out entries not eligible for exp distribution + memset(tmpsd,0,sizeof(tmpsd)); + for(i = 0, count = 0, mvp_damage = 0; i < DAMAGELOG_SIZE && md->dmglog[i].id; i++) + { + struct map_session_data* tsd = map_charid2sd(md->dmglog[i].id); + + if(tsd == NULL) + continue; // skip empty entries + if(tsd->bl.m != m) + continue; // skip players not on this map + count++; //Only logged into same map chars are counted for the total. + if (pc_isdead(tsd)) + continue; // skip dead players + if(md->dmglog[i].flag == MDLF_HOMUN && !merc_is_hom_active(tsd->hd)) + continue; // skip homunc's share if inactive + if( md->dmglog[i].flag == MDLF_PET && (!tsd->status.pet_id || !tsd->pd) ) + continue; // skip pet's share if inactive + + if(md->dmglog[i].dmg > mvp_damage) + { + third_sd = second_sd; + second_sd = mvp_sd; + mvp_sd = tsd; + mvp_damage = md->dmglog[i].dmg; + } + + tmpsd[i] = tsd; // record as valid damage-log entry + + switch( md->dmglog[i].flag ) + { + case MDLF_NORMAL: dmgbltypes|= BL_PC; break; + case MDLF_HOMUN: dmgbltypes|= BL_HOM; break; + case MDLF_PET: dmgbltypes|= BL_PET; break; + } + } + + // determines, if the monster was killed by homunculus' damage only + homkillonly = (bool)( ( dmgbltypes&BL_HOM ) && !( dmgbltypes&~BL_HOM ) ); + + if(!battle_config.exp_calc_type && count > 1) + { //Apply first-attacker 200% exp share bonus + //TODO: Determine if this should go before calculating the MVP player instead of after. + if (UINT_MAX - md->dmglog[0].dmg > md->tdmg) { + md->tdmg += md->dmglog[0].dmg; + md->dmglog[0].dmg<<=1; + } else { + md->dmglog[0].dmg+= UINT_MAX - md->tdmg; + md->tdmg = UINT_MAX; + } + } + + if(!(type&2) && //No exp + (!map[m].flag.pvp || battle_config.pvp_exp) && //Pvp no exp rule [MouseJstr] + (!md->master_id || !md->special_state.ai) && //Only player-summoned mobs do not give exp. [Skotlex] + (!map[m].flag.nobaseexp || !map[m].flag.nojobexp) //Gives Exp + ) { //Experience calculation. + int bonus = 100; //Bonus on top of your share (common to all attackers). + if (md->sc.data[SC_RICHMANKIM]) + bonus += md->sc.data[SC_RICHMANKIM]->val2; + if(sd) { + temp = status_get_class(&md->bl); + if(sd->sc.data[SC_MIRACLE]) i = 2; //All mobs are Star Targets + else + ARR_FIND(0, MAX_PC_FEELHATE, i, temp == sd->hate_mob[i] && + (battle_config.allow_skill_without_day || sg_info[i].day_func())); + if(i<MAX_PC_FEELHATE && (temp=pc_checkskill(sd,sg_info[i].bless_id))) + bonus += (i==2?20:10)*temp; + } + if(battle_config.mobs_level_up && md->level > md->db->lv) // [Valaris] + bonus += (md->level-md->db->lv)*battle_config.mobs_level_up_exp_rate; + + for(i = 0; i < DAMAGELOG_SIZE && md->dmglog[i].id; i++) + { + int flag=1,zeny=0; + unsigned int base_exp, job_exp; + double per; //Your share of the mob's exp + + if (!tmpsd[i]) continue; + + if (!battle_config.exp_calc_type && md->tdmg) + //jAthena's exp formula based on total damage. + per = (double)md->dmglog[i].dmg/(double)md->tdmg; + else { + //eAthena's exp formula based on max hp. + per = (double)md->dmglog[i].dmg/(double)status->max_hp; + if (per > 2) per = 2; // prevents unlimited exp gain + } + + if (count>1 && battle_config.exp_bonus_attacker) { + //Exp bonus per additional attacker. + if (count > battle_config.exp_bonus_max_attacker) + count = battle_config.exp_bonus_max_attacker; + per += per*((count-1)*battle_config.exp_bonus_attacker)/100.; + } + + // change experience for different sized monsters [Valaris] + if (battle_config.mob_size_influence) + { + if (md->special_state.size == SZ_MEDIUM) + per /= 2.; + else if (md->special_state.size == SZ_BIG) + per *= 2.; + } + + if( md->dmglog[i].flag == MDLF_PET ) + per *= battle_config.pet_attack_exp_rate/100.; + + if(battle_config.zeny_from_mobs && md->level) { + // zeny calculation moblv + random moblv [Valaris] + zeny=(int) ((md->level+rnd()%md->level)*per*bonus/100.); + if(md->db->mexp > 0) + zeny*=rnd()%250; + } + + if (map[m].flag.nobaseexp || !md->db->base_exp) + base_exp = 0; + else + base_exp = (unsigned int)cap_value(md->db->base_exp * per * bonus/100. * map[m].bexp/100., 1, UINT_MAX); + + if (map[m].flag.nojobexp || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost. + job_exp = 0; + else + job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].jexp/100., 1, UINT_MAX); + + if((temp = tmpsd[i]->status.party_id )>0 && !md->dmglog[i].flag == MDLF_HOMUN) //Homun-done damage (flag 1) is not given to party + { + int j; + for(j=0;j<pnum && pt[j].id!=temp;j++); //Locate party. + + if(j==pnum){ //Possibly add party. + pt[pnum].p = party_search(temp); + if(pt[pnum].p && pt[pnum].p->party.exp) + { + pt[pnum].id=temp; + pt[pnum].base_exp=base_exp; + pt[pnum].job_exp=job_exp; + pt[pnum].zeny=zeny; // zeny share [Valaris] + pnum++; + flag=0; + } + }else{ //Add to total + if (pt[j].base_exp > UINT_MAX - base_exp) + pt[j].base_exp=UINT_MAX; + else + pt[j].base_exp+=base_exp; + + if (pt[j].job_exp > UINT_MAX - job_exp) + pt[j].job_exp=UINT_MAX; + else + pt[j].job_exp+=job_exp; + + pt[j].zeny+=zeny; // zeny share [Valaris] + flag=0; + } + } + if(flag) { + if(base_exp && md->dmglog[i].flag == MDLF_HOMUN) //tmpsd[i] is null if it has no homunc. + merc_hom_gainexp(tmpsd[i]->hd, base_exp); + if(base_exp || job_exp) + { + if( md->dmglog[i].flag != MDLF_PET || battle_config.pet_attack_exp_to_master ) { #ifdef RENEWAL_EXP - int rate = pc_level_penalty_mod(tmpsd[i], md, 1); - base_exp = (unsigned int)cap_value(base_exp * rate / 100, 1, UINT_MAX); - job_exp = (unsigned int)cap_value(job_exp * rate / 100, 1, UINT_MAX); + int rate = pc_level_penalty_mod(tmpsd[i], md, 1); + base_exp = (unsigned int)cap_value(base_exp * rate / 100, 1, UINT_MAX); + job_exp = (unsigned int)cap_value(job_exp * rate / 100, 1, UINT_MAX); #endif - pc_gainexp(tmpsd[i], &md->bl, base_exp, job_exp, false); - } - } - if (zeny) // zeny from mobs [Valaris] - pc_getzeny(tmpsd[i], zeny, LOG_TYPE_PICKDROP_MONSTER, NULL); - } - } - - for (i=0; i<pnum; i++) //Party share. - party_exp_share(pt[i].p, &md->bl, pt[i].base_exp,pt[i].job_exp,pt[i].zeny); - - } //End EXP giving. - - if (!(type&1) && !map[m].flag.nomobloot && !md->state.rebirth && ( - !md->special_state.ai || //Non special mob - battle_config.alchemist_summon_reward == 2 || //All summoned give drops - (md->special_state.ai==2 && battle_config.alchemist_summon_reward == 1) //Marine Sphere Drops items. - )) { - // Item Drop - struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list); - struct item_drop *ditem; - struct item_data *it = NULL; - int drop_rate; + pc_gainexp(tmpsd[i], &md->bl, base_exp, job_exp, false); + } + } + if(zeny) // zeny from mobs [Valaris] + pc_getzeny(tmpsd[i], zeny, LOG_TYPE_PICKDROP_MONSTER, NULL); + } + } + + for(i=0;i<pnum;i++) //Party share. + party_exp_share(pt[i].p, &md->bl, pt[i].base_exp,pt[i].job_exp,pt[i].zeny); + + } //End EXP giving. + + if( !(type&1) && !map[m].flag.nomobloot && !md->state.rebirth && ( + !md->special_state.ai || //Non special mob + battle_config.alchemist_summon_reward == 2 || //All summoned give drops + (md->special_state.ai==2 && battle_config.alchemist_summon_reward == 1) //Marine Sphere Drops items. + ) ) + { // Item Drop + struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list); + struct item_drop *ditem; + struct item_data* it = NULL; + int drop_rate; #ifdef RENEWAL_DROP - int drop_modifier = mvp_sd ? pc_level_penalty_mod(mvp_sd, md, 2) : - second_sd ? pc_level_penalty_mod(second_sd, md, 2): - third_sd ? pc_level_penalty_mod(third_sd, md, 2) : - 100;/* no player was attached, we dont use any modifier (100 = rates are not touched) */ + int drop_modifier = mvp_sd ? pc_level_penalty_mod(mvp_sd, md, 2) : + second_sd ? pc_level_penalty_mod(second_sd, md, 2): + third_sd ? pc_level_penalty_mod(third_sd, md, 2) : + 100;/* no player was attached, we dont use any modifier (100 = rates are not touched) */ #endif - dlist->m = md->bl.m; - dlist->x = md->bl.x; - dlist->y = md->bl.y; - dlist->first_charid = (mvp_sd ? mvp_sd->status.char_id : 0); - dlist->second_charid = (second_sd ? second_sd->status.char_id : 0); - dlist->third_charid = (third_sd ? third_sd->status.char_id : 0); - dlist->item = NULL; - - for (i = 0; i < MAX_MOB_DROP; i++) { - if (md->db->dropitem[i].nameid <= 0) - continue; - if (!(it = itemdb_exists(md->db->dropitem[i].nameid))) - continue; - drop_rate = md->db->dropitem[i].p; - if (drop_rate <= 0) { - if (battle_config.drop_rate0item) - continue; - drop_rate = 1; - } - - // change drops depending on monsters size [Valaris] - if (battle_config.mob_size_influence) { - if (md->special_state.size == SZ_MEDIUM && drop_rate >= 2) - drop_rate /= 2; - else if (md->special_state.size == SZ_BIG) - drop_rate *= 2; - } - - if (src) { - //Drops affected by luk as a fixed increase [Valaris] - if (battle_config.drops_by_luk) - drop_rate += status_get_luk(src)*battle_config.drops_by_luk/100; - //Drops affected by luk as a % increase [Skotlex] - if (battle_config.drops_by_luk2) - drop_rate += (int)(0.5+drop_rate*status_get_luk(src)*battle_config.drops_by_luk2/10000.); - } - if (sd && battle_config.pk_mode && - (int)(md->level - sd->status.base_level) >= 20) - drop_rate = (int)(drop_rate*1.25); // pk_mode increase drops if 20 level difference [Valaris] - - // Increase drop rate if user has SC_ITEMBOOST - if (sd && sd->sc.data[SC_ITEMBOOST]) // now rig the drop rate to never be over 90% unless it is originally >90%. - drop_rate = max(drop_rate,cap_value((int)(0.5+drop_rate*(sd->sc.data[SC_ITEMBOOST]->val1)/100.),0,9000)); + dlist->m = md->bl.m; + dlist->x = md->bl.x; + dlist->y = md->bl.y; + dlist->first_charid = (mvp_sd ? mvp_sd->status.char_id : 0); + dlist->second_charid = (second_sd ? second_sd->status.char_id : 0); + dlist->third_charid = (third_sd ? third_sd->status.char_id : 0); + dlist->item = NULL; + + for (i = 0; i < MAX_MOB_DROP; i++) + { + if (md->db->dropitem[i].nameid <= 0) + continue; + if ( !(it = itemdb_exists(md->db->dropitem[i].nameid)) ) + continue; + drop_rate = md->db->dropitem[i].p; + if (drop_rate <= 0) { + if (battle_config.drop_rate0item) + continue; + drop_rate = 1; + } + + // change drops depending on monsters size [Valaris] + if (battle_config.mob_size_influence) + { + if (md->special_state.size == SZ_MEDIUM && drop_rate >= 2) + drop_rate /= 2; + else if( md->special_state.size == SZ_BIG) + drop_rate *= 2; + } + + if (src) { + //Drops affected by luk as a fixed increase [Valaris] + if (battle_config.drops_by_luk) + drop_rate += status_get_luk(src)*battle_config.drops_by_luk/100; + //Drops affected by luk as a % increase [Skotlex] + if (battle_config.drops_by_luk2) + drop_rate += (int)(0.5+drop_rate*status_get_luk(src)*battle_config.drops_by_luk2/10000.); + } + if (sd && battle_config.pk_mode && + (int)(md->level - sd->status.base_level) >= 20) + drop_rate = (int)(drop_rate*1.25); // pk_mode increase drops if 20 level difference [Valaris] + + // Increase drop rate if user has SC_ITEMBOOST + if (sd && sd->sc.data[SC_ITEMBOOST]) // now rig the drop rate to never be over 90% unless it is originally >90%. + drop_rate = max(drop_rate,cap_value((int)(0.5+drop_rate*(sd->sc.data[SC_ITEMBOOST]->val1)/100.),0,9000)); #ifdef RENEWAL_DROP - if (drop_modifier != 100) { - drop_rate = drop_rate * drop_modifier / 100; - if (drop_rate < 1) - drop_rate = 1; - } + if( drop_modifier != 100 ) { + drop_rate = drop_rate * drop_modifier / 100; + if( drop_rate < 1 ) + drop_rate = 1; + } #endif - // attempt to drop the item - if (rnd() % 10000 >= drop_rate) - continue; - - if (mvp_sd && it->type == IT_PETEGG) { - pet_create_egg(mvp_sd, md->db->dropitem[i].nameid); - continue; - } - - ditem = mob_setdropitem(md->db->dropitem[i].nameid, 1); - - //A Rare Drop Global Announce by Lupus - if (mvp_sd && drop_rate <= battle_config.rare_drop_announce) { - char message[128]; - sprintf(message, msg_txt(541), mvp_sd->status.name, md->name, it->jname, (float)drop_rate/100); - //MSG: "'%s' won %s's %s (chance: %0.02f%%)" - intif_broadcast(message,strlen(message)+1,0); - } - // Announce first, or else ditem will be freed. [Lance] - // By popular demand, use base drop rate for autoloot code. [Skotlex] - mob_item_drop(md, dlist, ditem, 0, md->db->dropitem[i].p, homkillonly); - } - - // Ore Discovery [Celest] - if (sd == mvp_sd && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rnd()%10000) { - ditem = mob_setdropitem(itemdb_searchrandomid(IG_FINDINGORE), 1); - mob_item_drop(md, dlist, ditem, 0, battle_config.finding_ore_rate/10, homkillonly); - } - - if (sd) { - // process script-granted extra drop bonuses - int itemid = 0; - for (i = 0; i < ARRAYLENGTH(sd->add_drop) && (sd->add_drop[i].id || sd->add_drop[i].group); i++) { - if (sd->add_drop[i].race == -md->class_ || - (sd->add_drop[i].race > 0 && ( - sd->add_drop[i].race & (1<<status->race) || - sd->add_drop[i].race & (1<<(status->mode&MD_BOSS?RC_BOSS:RC_NONBOSS)) - ))) { - //check if the bonus item drop rate should be multiplied with mob level/10 [Lupus] - if (sd->add_drop[i].rate < 0) { - //it's negative, then it should be multiplied. e.g. for Mimic,Myst Case Cards, etc - // rate = base_rate * (mob_level/10) + 1 - drop_rate = -sd->add_drop[i].rate*(md->level/10)+1; - drop_rate = cap_value(drop_rate, battle_config.item_drop_adddrop_min, battle_config.item_drop_adddrop_max); - if (drop_rate > 10000) drop_rate = 10000; - } else - //it's positive, then it goes as it is - drop_rate = sd->add_drop[i].rate; - - if (rnd()%10000 >= drop_rate) - continue; - itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb_searchrandomid(sd->add_drop[i].group); - mob_item_drop(md, dlist, mob_setdropitem(itemid,1), 0, drop_rate, homkillonly); - } - } - - // process script-granted zeny bonus (get_zeny_num) [Skotlex] - if (sd->bonus.get_zeny_num && rnd()%100 < sd->bonus.get_zeny_rate) { - i = sd->bonus.get_zeny_num > 0 ? sd->bonus.get_zeny_num : -md->level * sd->bonus.get_zeny_num; - if (!i) i = 1; - pc_getzeny(sd, 1+rnd()%i, LOG_TYPE_PICKDROP_MONSTER, NULL); - } - } - - // process items looted by the mob - if (md->lootitem) { - for (i = 0; i < md->lootitem_count; i++) - mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, homkillonly); - } - if (dlist->item) //There are drop items. - add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr_t)dlist); - else //No drops - ers_free(item_drop_list_ers, dlist); - } else if (md->lootitem && md->lootitem_count) { //Loot MUST drop! - struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list); - dlist->m = md->bl.m; - dlist->x = md->bl.x; - dlist->y = md->bl.y; - dlist->first_charid = (mvp_sd ? mvp_sd->status.char_id : 0); - dlist->second_charid = (second_sd ? second_sd->status.char_id : 0); - dlist->third_charid = (third_sd ? third_sd->status.char_id : 0); - dlist->item = NULL; - for (i = 0; i < md->lootitem_count; i++) - mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, homkillonly); - add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr_t)dlist); - } - - if (mvp_sd && md->db->mexp > 0 && !md->special_state.ai) { - int log_mvp[2] = {0}; - unsigned int mexp; - struct item item; - double exp; - - //mapflag: noexp check [Lorky] - if (map[m].flag.nobaseexp || type&2) - exp =1; - else { - exp = md->db->mexp; - if (count > 1) - exp += exp*(battle_config.exp_bonus_attacker*(count-1))/100.; //[Gengar] - } - - mexp = (unsigned int)cap_value(exp, 1, UINT_MAX); - - clif_mvp_effect(mvp_sd); - clif_mvp_exp(mvp_sd,mexp); - pc_gainexp(mvp_sd, &md->bl, mexp,0, false); - log_mvp[1] = mexp; - - if (!(map[m].flag.nomvploot || type&1)) { - /* pose them randomly in the list -- so on 100% drop servers it wont always drop the same item */ - int mdrop_id[MAX_MVP_DROP]; - int mdrop_p[MAX_MVP_DROP]; - - memset(&mdrop_id,0,MAX_MVP_DROP*sizeof(int)); - - for (i = 0; i < MAX_MVP_DROP; i++) { - while (1) { - int va = rand()%MAX_MVP_DROP; - if (!mdrop_id[va] || !md->db->mvpitem[i].nameid) { - mdrop_id[va] = md->db->mvpitem[i].nameid; - mdrop_p[va] = md->db->mvpitem[i].p; - break; - } - } - } - - for (i = 0; i < MAX_MVP_DROP; i++) { - if (mdrop_id[i] <= 0) - continue; - if (!itemdb_exists(mdrop_id[i])) - continue; - - temp = mdrop_p[i]; - if (temp <= 0 && !battle_config.drop_rate0item) - temp = 1; - if (temp <= rnd()%10000+1) //if ==0, then it doesn't drop - continue; - - memset(&item,0,sizeof(item)); - item.nameid=mdrop_id[i]; - item.identify= itemdb_isidentified(item.nameid); - clif_mvp_item(mvp_sd,item.nameid); - log_mvp[0] = item.nameid; - - //A Rare MVP Drop Global Announce by Lupus - if (temp<=battle_config.rare_drop_announce) { - struct item_data *i_data; - char message[128]; - i_data = itemdb_exists(item.nameid); - sprintf(message, msg_txt(541), mvp_sd->status.name, md->name, i_data->jname, temp/100.); - //MSG: "'%s' won %s's %s (chance: %0.02f%%)" - intif_broadcast(message,strlen(message)+1,0); - } - - if ((temp = pc_additem(mvp_sd,&item,1,LOG_TYPE_PICKDROP_PLAYER)) != 0) { - clif_additem(mvp_sd,0,0,temp); - map_addflooritem(&item,1,mvp_sd->bl.m,mvp_sd->bl.x,mvp_sd->bl.y,mvp_sd->status.char_id,(second_sd?second_sd->status.char_id:0),(third_sd?third_sd->status.char_id:0),1); - } - - //Logs items, MVP prizes [Lupus] - log_pick_mob(md, LOG_TYPE_MVP, -1, &item); - break; - } - } - - log_mvpdrop(mvp_sd, md->class_, log_mvp); - } - - if (type&2 && !sd && md->class_ == MOBID_EMPERIUM) - //Emperium destroyed by script. Discard mvp character. [Skotlex] - mvp_sd = NULL; - - rebirth = (md->sc.data[SC_KAIZEL] || (md->sc.data[SC_REBIRTH] && !md->state.rebirth)); - if (!rebirth) { // Only trigger event on final kill - md->status.hp = 0; //So that npc_event invoked functions KNOW that mob is dead - if (src) { - switch (src->type) { - case BL_PET: - sd = ((TBL_PET *)src)->msd; - break; - case BL_HOM: - sd = ((TBL_HOM *)src)->master; - break; - case BL_MER: - sd = ((TBL_MER *)src)->master; - break; - case BL_ELEM: - sd = ((TBL_ELEM *)src)->master; - break; - } - } - - if (sd) { - if (sd->mission_mobid == md->class_) { //TK_MISSION [Skotlex] - if (++sd->mission_count >= 100 && (temp = mob_get_random_id(0, 0xE, sd->status.base_level))) { - pc_addfame(sd, 1); - sd->mission_mobid = temp; - pc_setglobalreg(sd,"TK_MISSION_ID", temp); - sd->mission_count = 0; - clif_mission_info(sd, temp, 0); - } - pc_setglobalreg(sd,"TK_MISSION_COUNT", sd->mission_count); - } - - if (sd->status.party_id) - map_foreachinrange(quest_update_objective_sub,&md->bl,AREA_SIZE,BL_PC,sd->status.party_id,md->class_); - else if (sd->avail_quests) - quest_update_objective(sd, md->class_); - - if (sd->md && src && src->type != BL_HOM && mob_db(md->class_)->lv > sd->status.base_level/2) - mercenary_kills(sd->md); - } - - if (md->npc_event[0] && !md->state.npc_killmonster) { - if (sd && battle_config.mob_npc_event_type) { - pc_setparam(sd, SP_KILLERRID, sd->bl.id); - npc_event(sd,md->npc_event,0); - } else if (mvp_sd) { - pc_setparam(mvp_sd, SP_KILLERRID, sd?sd->bl.id:0); - npc_event(mvp_sd,md->npc_event,0); - } else - npc_event_do(md->npc_event); - } else if (mvp_sd && !md->state.npc_killmonster) { - pc_setparam(mvp_sd, SP_KILLEDRID, md->class_); - npc_script_event(mvp_sd, NPCE_KILLNPC); // PCKillNPC [Lance] - } - - md->status.hp = 1; - } - - if (md->deletetimer != INVALID_TIMER) { - delete_timer(md->deletetimer,mob_timer_delete); - md->deletetimer = INVALID_TIMER; - } - /** - * Only loops if necessary (e.g. a poring would never need to loop) - **/ - if (md->can_summon) - mob_deleteslave(md); - - map_freeblock_unlock(); - - if (!rebirth) { - - if (pcdb_checkid(md->vd->class_)) { //Player mobs are not removed automatically by the client. - /* first we set them dead, then we delay the outsight effect */ - clif_clearunit_area(&md->bl,CLR_DEAD); - clif_clearunit_delayed(&md->bl, CLR_OUTSIGHT,tick+3000); - } else - /** - * We give the client some time to breath and this allows it to display anything it'd like with the dead corpose - * For example, this delay allows it to display soul drain effect - **/ - clif_clearunit_delayed(&md->bl, CLR_DEAD, tick+250); - - } - - if (!md->spawn) //Tell status_damage to remove it from memory. - return 5; // Note: Actually, it's 4. Oh well... - - // MvP tomb [GreenBox] - if (battle_config.mvp_tomb_enabled && md->spawn->state.boss) - mvptomb_create(md, mvp_sd ? mvp_sd->status.name : NULL, time(NULL)); - - if (!rebirth) - mob_setdelayspawn(md); //Set respawning. - return 3; //Remove from map. + // attempt to drop the item + if (rnd() % 10000 >= drop_rate) + continue; + + if( mvp_sd && it->type == IT_PETEGG ) { + pet_create_egg(mvp_sd, md->db->dropitem[i].nameid); + continue; + } + + ditem = mob_setdropitem(md->db->dropitem[i].nameid, 1); + + //A Rare Drop Global Announce by Lupus + if( mvp_sd && drop_rate <= battle_config.rare_drop_announce ) { + char message[128]; + sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, it->jname, (float)drop_rate/100); + //MSG: "'%s' won %s's %s (chance: %0.02f%%)" + intif_broadcast(message,strlen(message)+1,0); + } + // Announce first, or else ditem will be freed. [Lance] + // By popular demand, use base drop rate for autoloot code. [Skotlex] + mob_item_drop(md, dlist, ditem, 0, md->db->dropitem[i].p, homkillonly); + } + + // Ore Discovery [Celest] + if (sd == mvp_sd && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rnd()%10000) { + ditem = mob_setdropitem(itemdb_searchrandomid(IG_FINDINGORE), 1); + mob_item_drop(md, dlist, ditem, 0, battle_config.finding_ore_rate/10, homkillonly); + } + + if(sd) { + // process script-granted extra drop bonuses + int itemid = 0; + for (i = 0; i < ARRAYLENGTH(sd->add_drop) && (sd->add_drop[i].id || sd->add_drop[i].group); i++) + { + if ( sd->add_drop[i].race == -md->class_ || + ( sd->add_drop[i].race > 0 && ( + sd->add_drop[i].race & (1<<status->race) || + sd->add_drop[i].race & (1<<(status->mode&MD_BOSS?RC_BOSS:RC_NONBOSS)) + ))) + { + //check if the bonus item drop rate should be multiplied with mob level/10 [Lupus] + if(sd->add_drop[i].rate < 0) { + //it's negative, then it should be multiplied. e.g. for Mimic,Myst Case Cards, etc + // rate = base_rate * (mob_level/10) + 1 + drop_rate = -sd->add_drop[i].rate*(md->level/10)+1; + drop_rate = cap_value(drop_rate, battle_config.item_drop_adddrop_min, battle_config.item_drop_adddrop_max); + if (drop_rate > 10000) drop_rate = 10000; + } + else + //it's positive, then it goes as it is + drop_rate = sd->add_drop[i].rate; + + if (rnd()%10000 >= drop_rate) + continue; + itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb_searchrandomid(sd->add_drop[i].group); + mob_item_drop(md, dlist, mob_setdropitem(itemid,1), 0, drop_rate, homkillonly); + } + } + + // process script-granted zeny bonus (get_zeny_num) [Skotlex] + if( sd->bonus.get_zeny_num && rnd()%100 < sd->bonus.get_zeny_rate ) { + i = sd->bonus.get_zeny_num > 0 ? sd->bonus.get_zeny_num : -md->level * sd->bonus.get_zeny_num; + if (!i) i = 1; + pc_getzeny(sd, 1+rnd()%i, LOG_TYPE_PICKDROP_MONSTER, NULL); + } + } + + // process items looted by the mob + if(md->lootitem) { + for(i = 0; i < md->lootitem_count; i++) + mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, homkillonly); + } + if (dlist->item) //There are drop items. + add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr_t)dlist); + else //No drops + ers_free(item_drop_list_ers, dlist); + } else if (md->lootitem && md->lootitem_count) { //Loot MUST drop! + struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list); + dlist->m = md->bl.m; + dlist->x = md->bl.x; + dlist->y = md->bl.y; + dlist->first_charid = (mvp_sd ? mvp_sd->status.char_id : 0); + dlist->second_charid = (second_sd ? second_sd->status.char_id : 0); + dlist->third_charid = (third_sd ? third_sd->status.char_id : 0); + dlist->item = NULL; + for(i = 0; i < md->lootitem_count; i++) + mob_item_drop(md, dlist, mob_setlootitem(&md->lootitem[i]), 1, 10000, homkillonly); + add_timer(tick + (!battle_config.delay_battle_damage?500:0), mob_delay_item_drop, 0, (intptr_t)dlist); + } + + if(mvp_sd && md->db->mexp > 0 && !md->special_state.ai) { + int log_mvp[2] = {0}; + unsigned int mexp; + struct item item; + double exp; + + //mapflag: noexp check [Lorky] + if (map[m].flag.nobaseexp || type&2) + exp =1; + else { + exp = md->db->mexp; + if (count > 1) + exp += exp*(battle_config.exp_bonus_attacker*(count-1))/100.; //[Gengar] + } + + mexp = (unsigned int)cap_value(exp, 1, UINT_MAX); + + clif_mvp_effect(mvp_sd); + clif_mvp_exp(mvp_sd,mexp); + pc_gainexp(mvp_sd, &md->bl, mexp,0, false); + log_mvp[1] = mexp; + + if( !(map[m].flag.nomvploot || type&1) ) { + /* pose them randomly in the list -- so on 100% drop servers it wont always drop the same item */ + int mdrop_id[MAX_MVP_DROP]; + int mdrop_p[MAX_MVP_DROP]; + + memset(&mdrop_id,0,MAX_MVP_DROP*sizeof(int)); + + for(i = 0; i < MAX_MVP_DROP; i++) { + while( 1 ) { + int va = rand()%MAX_MVP_DROP; + if( !mdrop_id[va] || !md->db->mvpitem[i].nameid ) { + mdrop_id[va] = md->db->mvpitem[i].nameid; + mdrop_p[va] = md->db->mvpitem[i].p; + break; + } + } + } + + for(i = 0; i < MAX_MVP_DROP; i++) { + if(mdrop_id[i] <= 0) + continue; + if(!itemdb_exists(mdrop_id[i])) + continue; + + temp = mdrop_p[i]; + if(temp <= 0 && !battle_config.drop_rate0item) + temp = 1; + if(temp <= rnd()%10000+1) //if ==0, then it doesn't drop + continue; + + memset(&item,0,sizeof(item)); + item.nameid=mdrop_id[i]; + item.identify= itemdb_isidentified(item.nameid); + clif_mvp_item(mvp_sd,item.nameid); + log_mvp[0] = item.nameid; + + //A Rare MVP Drop Global Announce by Lupus + if(temp<=battle_config.rare_drop_announce) { + struct item_data *i_data; + char message[128]; + i_data = itemdb_exists(item.nameid); + sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, i_data->jname, temp/100.); + //MSG: "'%s' won %s's %s (chance: %0.02f%%)" + intif_broadcast(message,strlen(message)+1,0); + } + + if((temp = pc_additem(mvp_sd,&item,1,LOG_TYPE_PICKDROP_PLAYER)) != 0) { + clif_additem(mvp_sd,0,0,temp); + map_addflooritem(&item,1,mvp_sd->bl.m,mvp_sd->bl.x,mvp_sd->bl.y,mvp_sd->status.char_id,(second_sd?second_sd->status.char_id:0),(third_sd?third_sd->status.char_id:0),1); + } + + //Logs items, MVP prizes [Lupus] + log_pick_mob(md, LOG_TYPE_MVP, -1, &item); + break; + } + } + + log_mvpdrop(mvp_sd, md->class_, log_mvp); + } + + if (type&2 && !sd && md->class_ == MOBID_EMPERIUM) + //Emperium destroyed by script. Discard mvp character. [Skotlex] + mvp_sd = NULL; + + rebirth = ( md->sc.data[SC_KAIZEL] || (md->sc.data[SC_REBIRTH] && !md->state.rebirth) ); + if( !rebirth ) { // Only trigger event on final kill + md->status.hp = 0; //So that npc_event invoked functions KNOW that mob is dead + if( src ) { + switch( src->type ) { + case BL_PET: sd = ((TBL_PET*)src)->msd; break; + case BL_HOM: sd = ((TBL_HOM*)src)->master; break; + case BL_MER: sd = ((TBL_MER*)src)->master; break; + case BL_ELEM: sd = ((TBL_ELEM*)src)->master; break; + } + } + + if( sd ) { + if( sd->mission_mobid == md->class_) { //TK_MISSION [Skotlex] + if( ++sd->mission_count >= 100 && (temp = mob_get_random_id(0, 0xE, sd->status.base_level)) ) { + pc_addfame(sd, 1); + sd->mission_mobid = temp; + pc_setglobalreg(sd,"TK_MISSION_ID", temp); + sd->mission_count = 0; + clif_mission_info(sd, temp, 0); + } + pc_setglobalreg(sd,"TK_MISSION_COUNT", sd->mission_count); + } + + if( sd->status.party_id ) + map_foreachinrange(quest_update_objective_sub,&md->bl,AREA_SIZE,BL_PC,sd->status.party_id,md->class_); + else if( sd->avail_quests ) + quest_update_objective(sd, md->class_); + + if( sd->md && src && src->type != BL_HOM && mob_db(md->class_)->lv > sd->status.base_level/2 ) + mercenary_kills(sd->md); + } + + if( md->npc_event[0] && !md->state.npc_killmonster ) { + if( sd && battle_config.mob_npc_event_type ) { + pc_setparam(sd, SP_KILLERRID, sd->bl.id); + npc_event(sd,md->npc_event,0); + } else if( mvp_sd ) { + pc_setparam(mvp_sd, SP_KILLERRID, sd?sd->bl.id:0); + npc_event(mvp_sd,md->npc_event,0); + } else + npc_event_do(md->npc_event); + } else if( mvp_sd && !md->state.npc_killmonster ) { + pc_setparam(mvp_sd, SP_KILLEDRID, md->class_); + npc_script_event(mvp_sd, NPCE_KILLNPC); // PCKillNPC [Lance] + } + + md->status.hp = 1; + } + + if(md->deletetimer != INVALID_TIMER) { + delete_timer(md->deletetimer,mob_timer_delete); + md->deletetimer = INVALID_TIMER; + } + /** + * Only loops if necessary (e.g. a poring would never need to loop) + **/ + if( md->can_summon ) + mob_deleteslave(md); + + map_freeblock_unlock(); + + if( !rebirth ) { + + if( pcdb_checkid(md->vd->class_) ) {//Player mobs are not removed automatically by the client. + /* first we set them dead, then we delay the outsight effect */ + clif_clearunit_area(&md->bl,CLR_DEAD); + clif_clearunit_delayed(&md->bl, CLR_OUTSIGHT,tick+3000); + } else + /** + * We give the client some time to breath and this allows it to display anything it'd like with the dead corpose + * For example, this delay allows it to display soul drain effect + **/ + clif_clearunit_delayed(&md->bl, CLR_DEAD, tick+250); + + } + + if(!md->spawn) //Tell status_damage to remove it from memory. + return 5; // Note: Actually, it's 4. Oh well... + + // MvP tomb [GreenBox] + if (battle_config.mvp_tomb_enabled && md->spawn->state.boss) + mvptomb_create(md, mvp_sd ? mvp_sd->status.name : NULL, time(NULL)); + + if( !rebirth ) + mob_setdelayspawn(md); //Set respawning. + return 3; //Remove from map. } void mob_revive(struct mob_data *md, unsigned int hp) { - unsigned int tick = gettick(); - md->state.skillstate = MSS_IDLE; - md->last_thinktime = tick; - md->next_walktime = tick+rnd()%50+5000; - md->last_linktime = tick; - md->last_pcneartime = 0; - memset(md->dmglog, 0, sizeof(md->dmglog)); // Reset the damage done on the rebirthed monster, otherwise will grant full exp + damage done. [Valaris] - md->tdmg = 0; - if (!md->bl.prev) - map_addblock(&md->bl); - clif_spawn(&md->bl); - skill_unit_move(&md->bl,tick,1); - mobskill_use(md, tick, MSC_SPAWN); - if (battle_config.show_mob_info&3) - clif_charnameack(0, &md->bl); + unsigned int tick = gettick(); + md->state.skillstate = MSS_IDLE; + md->last_thinktime = tick; + md->next_walktime = tick+rnd()%50+5000; + md->last_linktime = tick; + md->last_pcneartime = 0; + memset(md->dmglog, 0, sizeof(md->dmglog)); // Reset the damage done on the rebirthed monster, otherwise will grant full exp + damage done. [Valaris] + md->tdmg = 0; + if (!md->bl.prev) + map_addblock(&md->bl); + clif_spawn(&md->bl); + skill_unit_move(&md->bl,tick,1); + mobskill_use(md, tick, MSC_SPAWN); + if (battle_config.show_mob_info&3) + clif_charnameack (0, &md->bl); } int mob_guardian_guildchange(struct mob_data *md) { - struct guild *g; - nullpo_ret(md); - - if (!md->guardian_data) - return 0; - - if (md->guardian_data->castle->guild_id == 0) { - //Castle with no owner? Delete the guardians. - if (md->class_ == MOBID_EMPERIUM) { - //But don't delete the emperium, just clear it's guild-data - md->guardian_data->guild_id = 0; - md->guardian_data->emblem_id = 0; - md->guardian_data->guild_name[0] = '\0'; - } else { - if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible) - guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0); - unit_free(&md->bl,CLR_OUTSIGHT); //Remove guardian. - } - return 0; - } - - g = guild_search(md->guardian_data->castle->guild_id); - if (g == NULL) { - //Properly remove guardian info from Castle data. - ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->guild_id); - if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS) - guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0); - unit_free(&md->bl,CLR_OUTSIGHT); - return 0; - } - - md->guardian_data->guild_id = g->guild_id; - md->guardian_data->emblem_id = g->emblem_id; - md->guardian_data->guardup_lv = guild_checkskill(g,GD_GUARDUP); - memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); - - return 1; + struct guild *g; + nullpo_ret(md); + + if (!md->guardian_data) + return 0; + + if (md->guardian_data->castle->guild_id == 0) + { //Castle with no owner? Delete the guardians. + if (md->class_ == MOBID_EMPERIUM) + { //But don't delete the emperium, just clear it's guild-data + md->guardian_data->guild_id = 0; + md->guardian_data->emblem_id = 0; + md->guardian_data->guild_name[0] = '\0'; + } else { + if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible) + guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0); + unit_free(&md->bl,CLR_OUTSIGHT); //Remove guardian. + } + return 0; + } + + g = guild_search(md->guardian_data->castle->guild_id); + if (g == NULL) + { //Properly remove guardian info from Castle data. + ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->guild_id); + if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS) + guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0); + unit_free(&md->bl,CLR_OUTSIGHT); + return 0; + } + + md->guardian_data->guild_id = g->guild_id; + md->guardian_data->emblem_id = g->emblem_id; + md->guardian_data->guardup_lv = guild_checkskill(g,GD_GUARDUP); + memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); + + return 1; } /*========================================== * Pick a random class for the mob *------------------------------------------*/ -int mob_random_class(int *value, size_t count) +int mob_random_class (int *value, size_t count) { - nullpo_ret(value); - - // no count specified, look into the array manually, but take only max 5 elements - if (count < 1) { - count = 0; - while (count < 5 && mobdb_checkid(value[count])) count++; - if (count < 1) // nothing found - return 0; - } else { - // check if at least the first value is valid - if (mobdb_checkid(value[0]) == 0) - return 0; - } - //Pick a random value, hoping it exists. [Skotlex] - return mobdb_checkid(value[rnd()%count]); + nullpo_ret(value); + + // no count specified, look into the array manually, but take only max 5 elements + if (count < 1) { + count = 0; + while(count < 5 && mobdb_checkid(value[count])) count++; + if(count < 1) // nothing found + return 0; + } else { + // check if at least the first value is valid + if(mobdb_checkid(value[0]) == 0) + return 0; + } + //Pick a random value, hoping it exists. [Skotlex] + return mobdb_checkid(value[rnd()%count]); } /*========================================== * Change mob base class *------------------------------------------*/ -int mob_class_change(struct mob_data *md, int class_) +int mob_class_change (struct mob_data *md, int class_) { - unsigned int tick = gettick(); - int i, c, hp_rate; - - nullpo_ret(md); - - if (md->bl.prev == NULL) - return 0; - - //Disable class changing for some targets... - if (md->guardian_data) - return 0; //Guardians/Emperium - - if (mob_is_treasure(md)) - return 0; //Treasure Boxes - - if (md->special_state.ai > 1) - return 0; //Marine Spheres and Floras. - - if (mob_is_clone(md->class_)) - return 0; //Clones - - if (md->class_ == class_) - return 0; //Nothing to change. - - hp_rate = get_percentage(md->status.hp, md->status.max_hp); - md->class_ = class_; - md->db = mob_db(class_); - if (battle_config.override_mob_names==1) - memcpy(md->name,md->db->name,NAME_LENGTH); - else - memcpy(md->name,md->db->jname,NAME_LENGTH); - - mob_stop_attack(md); - mob_stop_walking(md, 0); - unit_skillcastcancel(&md->bl, 0); - status_set_viewdata(&md->bl, class_); - clif_mob_class_change(md,md->vd->class_); - status_calc_mob(md, 1); - md->ud.state.speed_changed = 1; //Speed change update. - - if (battle_config.monster_class_change_recover) { - memset(md->dmglog, 0, sizeof(md->dmglog)); - md->tdmg = 0; - } else { - md->status.hp = md->status.max_hp*hp_rate/100; - if (md->status.hp < 1) md->status.hp = 1; - } - - for (i=0,c=tick-MOB_MAX_DELAY; i<MAX_MOBSKILL; i++) - md->skilldelay[i] = c; - - if (md->lootitem == NULL && md->db->status.mode&MD_LOOTER) - md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item)); - - //Targets should be cleared no morph - md->target_id = md->attacked_id = 0; - - //Need to update name display. - clif_charnameack(0, &md->bl); - status_change_end(&md->bl,SC_KEEPING,INVALID_TIMER); - return 0; + unsigned int tick = gettick(); + int i, c, hp_rate; + + nullpo_ret(md); + + if( md->bl.prev == NULL ) + return 0; + + //Disable class changing for some targets... + if (md->guardian_data) + return 0; //Guardians/Emperium + + if( mob_is_treasure(md) ) + return 0; //Treasure Boxes + + if( md->special_state.ai > 1 ) + return 0; //Marine Spheres and Floras. + + if( mob_is_clone(md->class_) ) + return 0; //Clones + + if( md->class_ == class_ ) + return 0; //Nothing to change. + + hp_rate = get_percentage(md->status.hp, md->status.max_hp); + md->class_ = class_; + md->db = mob_db(class_); + if (battle_config.override_mob_names==1) + memcpy(md->name,md->db->name,NAME_LENGTH); + else + memcpy(md->name,md->db->jname,NAME_LENGTH); + + mob_stop_attack(md); + mob_stop_walking(md, 0); + unit_skillcastcancel(&md->bl, 0); + status_set_viewdata(&md->bl, class_); + clif_mob_class_change(md,md->vd->class_); + status_calc_mob(md, 1); + md->ud.state.speed_changed = 1; //Speed change update. + + if (battle_config.monster_class_change_recover) { + memset(md->dmglog, 0, sizeof(md->dmglog)); + md->tdmg = 0; + } else { + md->status.hp = md->status.max_hp*hp_rate/100; + if(md->status.hp < 1) md->status.hp = 1; + } + + for(i=0,c=tick-MOB_MAX_DELAY;i<MAX_MOBSKILL;i++) + md->skilldelay[i] = c; + + if(md->lootitem == NULL && md->db->status.mode&MD_LOOTER) + md->lootitem=(struct item *)aCalloc(LOOTITEM_SIZE,sizeof(struct item)); + + //Targets should be cleared no morph + md->target_id = md->attacked_id = 0; + + //Need to update name display. + clif_charnameack(0, &md->bl); + status_change_end(&md->bl,SC_KEEPING,INVALID_TIMER); + return 0; } /*========================================== @@ -2734,8 +2795,8 @@ int mob_class_change(struct mob_data *md, int class_) *------------------------------------------*/ void mob_heal(struct mob_data *md,unsigned int heal) { - if (battle_config.show_mob_info&3) - clif_charnameack(0, &md->bl); + if (battle_config.show_mob_info&3) + clif_charnameack (0, &md->bl); } /*========================================== @@ -2743,18 +2804,18 @@ void mob_heal(struct mob_data *md,unsigned int heal) *------------------------------------------*/ int mob_warpslave_sub(struct block_list *bl,va_list ap) { - struct mob_data *md=(struct mob_data *)bl; - struct block_list *master; - short x,y,range=0; - master = va_arg(ap, struct block_list *); - range = va_arg(ap, int); - - if (md->master_id!=master->id) - return 0; - - map_search_freecell(master, 0, &x, &y, range, range, 0); - unit_warp(&md->bl, master->m, x, y,CLR_RESPAWN); - return 1; + struct mob_data *md=(struct mob_data *)bl; + struct block_list *master; + short x,y,range=0; + master = va_arg(ap, struct block_list*); + range = va_arg(ap, int); + + if(md->master_id!=master->id) + return 0; + + map_search_freecell(master, 0, &x, &y, range, range, 0); + unit_warp(&md->bl, master->m, x, y,CLR_RESPAWN); + return 1; } /*========================================== @@ -2764,10 +2825,10 @@ int mob_warpslave_sub(struct block_list *bl,va_list ap) *------------------------------------------*/ int mob_warpslave(struct block_list *bl, int range) { - if (range < 1) - range = 1; //Min range needed to avoid crashes and stuff. [Skotlex] + if (range < 1) + range = 1; //Min range needed to avoid crashes and stuff. [Skotlex] - return map_foreachinmap(mob_warpslave_sub, bl->m, BL_MOB, bl, range); + return map_foreachinmap(mob_warpslave_sub, bl->m, BL_MOB, bl, range); } /*========================================== @@ -2775,14 +2836,14 @@ int mob_warpslave(struct block_list *bl, int range) *------------------------------------------*/ int mob_countslave_sub(struct block_list *bl,va_list ap) { - int id; - struct mob_data *md; - id=va_arg(ap,int); - - md = (struct mob_data *)bl; - if (md->master_id==id) - return 1; - return 0; + int id; + struct mob_data *md; + id=va_arg(ap,int); + + md = (struct mob_data *)bl; + if( md->master_id==id ) + return 1; + return 0; } /*========================================== @@ -2790,7 +2851,7 @@ int mob_countslave_sub(struct block_list *bl,va_list ap) *------------------------------------------*/ int mob_countslave(struct block_list *bl) { - return map_foreachinmap(mob_countslave_sub, bl->m, BL_MOB,bl->id); + return map_foreachinmap(mob_countslave_sub, bl->m, BL_MOB,bl->id); } /*========================================== @@ -2798,96 +2859,97 @@ int mob_countslave(struct block_list *bl) *------------------------------------------*/ int mob_summonslave(struct mob_data *md2,int *value,int amount,int skill_id) { - struct mob_data *md; - struct spawn_data data; - int count = 0,k=0,hp_rate=0; - - nullpo_ret(md2); - nullpo_ret(value); - - memset(&data, 0, sizeof(struct spawn_data)); - data.m = md2->bl.m; - data.x = md2->bl.x; - data.y = md2->bl.y; - data.num = 1; - data.state.size = md2->special_state.size; - data.state.ai = md2->special_state.ai; - - if (mobdb_checkid(value[0]) == 0) - return 0; - /** - * Flags this monster is able to summon; saves a worth amount of memory upon deletion - **/ - md2->can_summon = 1; - - while (count < 5 && mobdb_checkid(value[count])) count++; - if (count < 1) return 0; - if (amount > 0 && amount < count) { //Do not start on 0, pick some random sub subset [Skotlex] - k = rnd()%count; - amount+=k; //Increase final value by same amount to preserve total number to summon. - } - - if (!battle_config.monster_class_change_recover && - (skill_id == NPC_TRANSFORMATION || skill_id == NPC_METAMORPHOSIS)) - hp_rate = get_percentage(md2->status.hp, md2->status.max_hp); - - for (; k<amount; k++) { - short x,y; - data.class_ = value[k%count]; //Summon slaves in round-robin fashion. [Skotlex] - if (mobdb_checkid(data.class_) == 0) - continue; - - if (map_search_freecell(&md2->bl, 0, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 0)) { - data.x = x; - data.y = y; - } else { - data.x = md2->bl.x; - data.y = md2->bl.y; - } - - //These two need to be loaded from the db for each slave. - if (battle_config.override_mob_names==1) - strcpy(data.name,"--en--"); - else - strcpy(data.name,"--ja--"); - - if (!mob_parse_dataset(&data)) - continue; - - md= mob_spawn_dataset(&data); - if (skill_id == NPC_SUMMONSLAVE) { - md->master_id=md2->bl.id; - md->special_state.ai = md2->special_state.ai; - } - mob_spawn(md); - - if (hp_rate) //Scale HP - md->status.hp = md->status.max_hp*hp_rate/100; - - //Inherit the aggressive mode of the master. - if (battle_config.slaves_inherit_mode && md->master_id) { - switch (battle_config.slaves_inherit_mode) { - case 1: //Always aggressive - if (!(md->status.mode&MD_AGGRESSIVE)) - sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0); - break; - case 2: //Always passive - if (md->status.mode&MD_AGGRESSIVE) - sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0); - break; - default: //Copy master. - if (md2->status.mode&MD_AGGRESSIVE) - sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0); - else - sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0); - break; - } - } - - clif_skill_nodamage(&md->bl,&md->bl,skill_id,amount,1); - } - - return 0; + struct mob_data *md; + struct spawn_data data; + int count = 0,k=0,hp_rate=0; + + nullpo_ret(md2); + nullpo_ret(value); + + memset(&data, 0, sizeof(struct spawn_data)); + data.m = md2->bl.m; + data.x = md2->bl.x; + data.y = md2->bl.y; + data.num = 1; + data.state.size = md2->special_state.size; + data.state.ai = md2->special_state.ai; + + if(mobdb_checkid(value[0]) == 0) + return 0; + /** + * Flags this monster is able to summon; saves a worth amount of memory upon deletion + **/ + md2->can_summon = 1; + + while(count < 5 && mobdb_checkid(value[count])) count++; + if(count < 1) return 0; + if (amount > 0 && amount < count) { //Do not start on 0, pick some random sub subset [Skotlex] + k = rnd()%count; + amount+=k; //Increase final value by same amount to preserve total number to summon. + } + + if (!battle_config.monster_class_change_recover && + (skill_id == NPC_TRANSFORMATION || skill_id == NPC_METAMORPHOSIS)) + hp_rate = get_percentage(md2->status.hp, md2->status.max_hp); + + for(;k<amount;k++) { + short x,y; + data.class_ = value[k%count]; //Summon slaves in round-robin fashion. [Skotlex] + if (mobdb_checkid(data.class_) == 0) + continue; + + if (map_search_freecell(&md2->bl, 0, &x, &y, MOB_SLAVEDISTANCE, MOB_SLAVEDISTANCE, 0)) { + data.x = x; + data.y = y; + } else { + data.x = md2->bl.x; + data.y = md2->bl.y; + } + + //These two need to be loaded from the db for each slave. + if(battle_config.override_mob_names==1) + strcpy(data.name,"--en--"); + else + strcpy(data.name,"--ja--"); + + if (!mob_parse_dataset(&data)) + continue; + + md= mob_spawn_dataset(&data); + if(skill_id == NPC_SUMMONSLAVE){ + md->master_id=md2->bl.id; + md->special_state.ai = md2->special_state.ai; + } + mob_spawn(md); + + if (hp_rate) //Scale HP + md->status.hp = md->status.max_hp*hp_rate/100; + + //Inherit the aggressive mode of the master. + if (battle_config.slaves_inherit_mode && md->master_id) + { + switch (battle_config.slaves_inherit_mode) { + case 1: //Always aggressive + if (!(md->status.mode&MD_AGGRESSIVE)) + sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0); + break; + case 2: //Always passive + if (md->status.mode&MD_AGGRESSIVE) + sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0); + break; + default: //Copy master. + if (md2->status.mode&MD_AGGRESSIVE) + sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, MD_AGGRESSIVE, 0, 0); + else + sc_start4(&md->bl, SC_MODECHANGE, 100,1,0, 0, MD_AGGRESSIVE, 0); + break; + } + } + + clif_skill_nodamage(&md->bl,&md->bl,skill_id,amount,1); + } + + return 0; } /*========================================== @@ -2896,14 +2958,14 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int skill_id) *------------------------------------------*/ int mob_skillid2skillidx(int class_,int skillid) { - int i, max = mob_db(class_)->maxskill; - struct mob_skill *ms=mob_db(class_)->skill; + int i, max = mob_db(class_)->maxskill; + struct mob_skill *ms=mob_db(class_)->skill; - if (ms==NULL) - return -1; + if(ms==NULL) + return -1; - ARR_FIND(0, max, i, ms[i].skill_id == skillid); - return (i < max) ? i : -1; + ARR_FIND( 0, max, i, ms[i].skill_id == skillid ); + return ( i < max ) ? i : -1; } /*========================================== @@ -2911,95 +2973,99 @@ int mob_skillid2skillidx(int class_,int skillid) *------------------------------------------*/ int mob_getfriendhprate_sub(struct block_list *bl,va_list ap) { - int min_rate, max_rate,rate; - struct block_list **fr; - struct mob_data *md; + int min_rate, max_rate,rate; + struct block_list **fr; + struct mob_data *md; - md = va_arg(ap,struct mob_data *); - min_rate=va_arg(ap,int); - max_rate=va_arg(ap,int); - fr=va_arg(ap,struct block_list **); + md = va_arg(ap,struct mob_data *); + min_rate=va_arg(ap,int); + max_rate=va_arg(ap,int); + fr=va_arg(ap,struct block_list **); - if (md->bl.id == bl->id && !(battle_config.mob_ai&0x10)) - return 0; + if( md->bl.id == bl->id && !(battle_config.mob_ai&0x10)) + return 0; - if ((*fr) != NULL) //A friend was already found. - return 0; + if ((*fr) != NULL) //A friend was already found. + return 0; - if (battle_check_target(&md->bl,bl,BCT_ENEMY)>0) - return 0; + if (battle_check_target(&md->bl,bl,BCT_ENEMY)>0) + return 0; - rate = get_percentage(status_get_hp(bl), status_get_max_hp(bl)); + rate = get_percentage(status_get_hp(bl), status_get_max_hp(bl)); - if (rate >= min_rate && rate <= max_rate) - (*fr) = bl; - return 1; + if (rate >= min_rate && rate <= max_rate) + (*fr) = bl; + return 1; } -static struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,int max_rate) { - struct block_list *fr=NULL; - int type = BL_MOB; +static struct block_list *mob_getfriendhprate(struct mob_data *md,int min_rate,int max_rate) +{ + struct block_list *fr=NULL; + int type = BL_MOB; - nullpo_retr(NULL, md); + nullpo_retr(NULL, md); - if (md->special_state.ai) //Summoned creatures. [Skotlex] - type = BL_PC; + if (md->special_state.ai) //Summoned creatures. [Skotlex] + type = BL_PC; - map_foreachinrange(mob_getfriendhprate_sub, &md->bl, 8, type,md,min_rate,max_rate,&fr); - return fr; + map_foreachinrange(mob_getfriendhprate_sub, &md->bl, 8, type,md,min_rate,max_rate,&fr); + return fr; } /*========================================== * Check hp rate of its master *------------------------------------------*/ -struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md,int rate) { - if (md && md->master_id > 0) { - struct block_list *bl = map_id2bl(md->master_id); - if (bl && get_percentage(status_get_hp(bl), status_get_max_hp(bl)) < rate) - return bl; - } - - return NULL; +struct block_list *mob_getmasterhpltmaxrate(struct mob_data *md,int rate) +{ + if( md && md->master_id > 0 ) + { + struct block_list *bl = map_id2bl(md->master_id); + if( bl && get_percentage(status_get_hp(bl), status_get_max_hp(bl)) < rate ) + return bl; + } + + return NULL; } /*========================================== * What a status state suits by nearby MOB is looked for. *------------------------------------------*/ int mob_getfriendstatus_sub(struct block_list *bl,va_list ap) { - int cond1,cond2; - struct mob_data **fr, *md, *mmd; - int flag=0; - - nullpo_ret(bl); - nullpo_ret(md=(struct mob_data *)bl); - nullpo_ret(mmd=va_arg(ap,struct mob_data *)); - - if (mmd->bl.id == bl->id && !(battle_config.mob_ai&0x10)) - return 0; - - if (battle_check_target(&mmd->bl,bl,BCT_ENEMY)>0) - return 0; - cond1=va_arg(ap,int); - cond2=va_arg(ap,int); - fr=va_arg(ap,struct mob_data **); - if (cond2==-1) { - int j; - for (j=SC_COMMON_MIN; j<=SC_COMMON_MAX && !flag; j++) { - if ((flag=(md->sc.data[j] != NULL))) //Once an effect was found, break out. [Skotlex] - break; - } - } else - flag=(md->sc.data[cond2] != NULL); - if (flag^(cond1==MSC_FRIENDSTATUSOFF)) - (*fr)=md; - - return 0; + int cond1,cond2; + struct mob_data **fr, *md, *mmd; + int flag=0; + + nullpo_ret(bl); + nullpo_ret(md=(struct mob_data *)bl); + nullpo_ret(mmd=va_arg(ap,struct mob_data *)); + + if( mmd->bl.id == bl->id && !(battle_config.mob_ai&0x10) ) + return 0; + + if (battle_check_target(&mmd->bl,bl,BCT_ENEMY)>0) + return 0; + cond1=va_arg(ap,int); + cond2=va_arg(ap,int); + fr=va_arg(ap,struct mob_data **); + if( cond2==-1 ){ + int j; + for(j=SC_COMMON_MIN;j<=SC_COMMON_MAX && !flag;j++){ + if ((flag=(md->sc.data[j] != NULL))) //Once an effect was found, break out. [Skotlex] + break; + } + }else + flag=( md->sc.data[cond2] != NULL ); + if( flag^( cond1==MSC_FRIENDSTATUSOFF ) ) + (*fr)=md; + + return 0; } -struct mob_data *mob_getfriendstatus(struct mob_data *md,int cond1,int cond2) { - struct mob_data *fr = NULL; - nullpo_ret(md); +struct mob_data *mob_getfriendstatus(struct mob_data *md,int cond1,int cond2) +{ + struct mob_data* fr = NULL; + nullpo_ret(md); - map_foreachinrange(mob_getfriendstatus_sub, &md->bl, 8,BL_MOB, md,cond1,cond2,&fr); - return fr; + map_foreachinrange(mob_getfriendstatus_sub, &md->bl, 8,BL_MOB, md,cond1,cond2,&fr); + return fr; } /*========================================== @@ -3007,269 +3073,260 @@ struct mob_data *mob_getfriendstatus(struct mob_data *md,int cond1,int cond2) { *------------------------------------------*/ int mobskill_use(struct mob_data *md, unsigned int tick, int event) { - struct mob_skill *ms; - struct block_list *fbl = NULL; //Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex] - struct block_list *bl; - struct mob_data *fmd = NULL; - int i,j,n; - - nullpo_ret(md); - nullpo_ret(ms = md->db->skill); - - if (!battle_config.mob_skill_rate || md->ud.skilltimer != INVALID_TIMER || !md->db->maxskill) - return 0; - - if (event == -1 && DIFF_TICK(md->ud.canact_tick, tick) > 0) - return 0; //Skill act delay only affects non-event skills. - - //Pick a starting position and loop from that. - i = battle_config.mob_ai&0x100?rnd()%md->db->maxskill:0; - for (n = 0; n < md->db->maxskill; i++, n++) { - int c2, flag = 0; - - if (i == md->db->maxskill) - i = 0; - - if (DIFF_TICK(tick, md->skilldelay[i]) < ms[i].delay) - continue; - - c2 = ms[i].cond2; - - if (ms[i].state != md->state.skillstate) { - if (md->state.skillstate != MSS_DEAD && (ms[i].state == MSS_ANY || - (ms[i].state == MSS_ANYTARGET && md->target_id && md->state.skillstate != MSS_LOOT) - )) //ANYTARGET works with any state as long as there's a target. [Skotlex] - ; - else - continue; - } - if (rnd() % 10000 > ms[i].permillage) //Lupus (max value = 10000) - continue; - - if (ms[i].cond1 == event) - flag = 1; //Trigger skill. - else if (ms[i].cond1 == MSC_SKILLUSED) - flag = ((event & 0xffff) == MSC_SKILLUSED && ((event >> 16) == c2 || c2 == 0)); - else if (event == -1) { - //Avoid entering on defined events to avoid "hyper-active skill use" due to the overflow of calls to this function in battle. - switch (ms[i].cond1) { - case MSC_ALWAYS: - flag = 1; - break; - case MSC_MYHPLTMAXRATE: // HP< maxhp% - flag = get_percentage(md->status.hp, md->status.max_hp); - flag = (flag <= c2); - break; - case MSC_MYHPINRATE: - flag = get_percentage(md->status.hp, md->status.max_hp); - flag = (flag >= c2 && flag <= ms[i].val[0]); - break; - case MSC_MYSTATUSON: // status[num] on - case MSC_MYSTATUSOFF: // status[num] off - if (!md->sc.count) { - flag = 0; - } else if (ms[i].cond2 == -1) { - for (j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++) - if ((flag = (md->sc.data[j]!=NULL)) != 0) - break; - } else { - flag = (md->sc.data[ms[i].cond2]!=NULL); - } - flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); - break; - case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp% - flag = ((fbl = mob_getfriendhprate(md, 0, ms[i].cond2)) != NULL); - break; - case MSC_FRIENDHPINRATE : - flag = ((fbl = mob_getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); - break; - case MSC_FRIENDSTATUSON: // friend status[num] on - case MSC_FRIENDSTATUSOFF: // friend status[num] off - flag = ((fmd = mob_getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); - break; - case MSC_SLAVELT: // slave < num - flag = (mob_countslave(&md->bl) < c2); - break; - case MSC_ATTACKPCGT: // attack pc > num - flag = (unit_counttargeted(&md->bl) > c2); - break; - case MSC_SLAVELE: // slave <= num - flag = (mob_countslave(&md->bl) <= c2); - break; - case MSC_ATTACKPCGE: // attack pc >= num - flag = (unit_counttargeted(&md->bl) >= c2); - break; - case MSC_AFTERSKILL: - flag = (md->ud.skillid == c2); - break; - case MSC_RUDEATTACKED: - flag = (md->state.attacked_count >= RUDE_ATTACKED_COUNT); - if (flag) md->state.attacked_count = 0; //Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex] - break; - case MSC_MASTERHPLTMAXRATE: - flag = ((fbl = mob_getmasterhpltmaxrate(md, ms[i].cond2)) != NULL); - break; - case MSC_MASTERATTACKED: - flag = (md->master_id > 0 && (fbl=map_id2bl(md->master_id)) && unit_counttargeted(fbl) > 0); - break; - case MSC_ALCHEMIST: - flag = (md->state.alchemist); - break; - } - } - - if (!flag) - continue; //Skill requisite failed to be fulfilled. - - //Execute skill - if (skill_get_casttype(ms[i].skill_id) == CAST_GROUND) { - //Ground skill. - short x, y; - switch (ms[i].target) { - case MST_RANDOM: //Pick a random enemy within skill range. - bl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md), - skill_get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); - break; - case MST_TARGET: - case MST_AROUND5: - case MST_AROUND6: - case MST_AROUND7: - case MST_AROUND8: - bl = map_id2bl(md->target_id); - break; - case MST_MASTER: - bl = &md->bl; - if (md->master_id) - bl = map_id2bl(md->master_id); - if (bl) //Otherwise, fall through. - break; - case MST_FRIEND: - bl = fbl?fbl:(fmd?&fmd->bl:&md->bl); - break; - default: - bl = &md->bl; - break; - } - if (!bl) continue; - - x = bl->x; - y = bl->y; - // Look for an area to cast the spell around... - if (ms[i].target >= MST_AROUND1 || ms[i].target >= MST_AROUND5) { - j = ms[i].target >= MST_AROUND1? - (ms[i].target-MST_AROUND1) +1: - (ms[i].target-MST_AROUND5) +1; - map_search_freecell(&md->bl, md->bl.m, &x, &y, j, j, 3); - } - md->skillidx = i; - map_freeblock_lock(); - if (!battle_check_range(&md->bl,bl,skill_get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) || - !unit_skilluse_pos2(&md->bl, x, y,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel)) { - map_freeblock_unlock(); - continue; - } - } else { - //Targetted skill - switch (ms[i].target) { - case MST_RANDOM: //Pick a random enemy within skill range. - bl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md), - skill_get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); - break; - case MST_TARGET: - bl = map_id2bl(md->target_id); - break; - case MST_MASTER: - bl = &md->bl; - if (md->master_id) - bl = map_id2bl(md->master_id); - if (bl) //Otherwise, fall through. - break; - case MST_FRIEND: - if (fbl) { - bl = fbl; - break; - } else if (fmd) { - bl = &fmd->bl; - break; - } // else fall through - default: - bl = &md->bl; - break; - } - if (!bl) continue; - - md->skillidx = i; - map_freeblock_lock(); - if (!battle_check_range(&md->bl,bl,skill_get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) || - !unit_skilluse_id2(&md->bl, bl->id,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel)) { - map_freeblock_unlock(); - continue; - } - } - //Skill used. Post-setups... - if (ms[ i ].msg_id) { //Display color message [SnakeDrak] - struct mob_chat *mc = mob_chat(ms[i].msg_id); - char temp[CHAT_SIZE_MAX]; - char name[NAME_LENGTH]; - snprintf(name, sizeof name,"%s", md->name); - strtok(name, "#"); // discard extra name identifier if present [Daegaladh] - snprintf(temp, sizeof temp,"%s : %s", name, mc->msg); - clif_messagecolor(&md->bl, mc->color, temp); - } - if (!(battle_config.mob_ai&0x200)) { //pass on delay to same skill. - for (j = 0; j < md->db->maxskill; j++) - if (md->db->skill[j].skill_id == ms[i].skill_id) - md->skilldelay[j]=tick; - } else - md->skilldelay[i]=tick; - map_freeblock_unlock(); - return 1; - } - //No skill was used. - md->skillidx = -1; - return 0; + struct mob_skill *ms; + struct block_list *fbl = NULL; //Friend bl, which can either be a BL_PC or BL_MOB depending on the situation. [Skotlex] + struct block_list *bl; + struct mob_data *fmd = NULL; + int i,j,n; + + nullpo_ret(md); + nullpo_ret(ms = md->db->skill); + + if (!battle_config.mob_skill_rate || md->ud.skilltimer != INVALID_TIMER || !md->db->maxskill) + return 0; + + if (event == -1 && DIFF_TICK(md->ud.canact_tick, tick) > 0) + return 0; //Skill act delay only affects non-event skills. + + //Pick a starting position and loop from that. + i = battle_config.mob_ai&0x100?rnd()%md->db->maxskill:0; + for (n = 0; n < md->db->maxskill; i++, n++) { + int c2, flag = 0; + + if (i == md->db->maxskill) + i = 0; + + if (DIFF_TICK(tick, md->skilldelay[i]) < ms[i].delay) + continue; + + c2 = ms[i].cond2; + + if (ms[i].state != md->state.skillstate) { + if (md->state.skillstate != MSS_DEAD && (ms[i].state == MSS_ANY || + (ms[i].state == MSS_ANYTARGET && md->target_id && md->state.skillstate != MSS_LOOT) + )) //ANYTARGET works with any state as long as there's a target. [Skotlex] + ; + else + continue; + } + if (rnd() % 10000 > ms[i].permillage) //Lupus (max value = 10000) + continue; + + if (ms[i].cond1 == event) + flag = 1; //Trigger skill. + else if (ms[i].cond1 == MSC_SKILLUSED) + flag = ((event & 0xffff) == MSC_SKILLUSED && ((event >> 16) == c2 || c2 == 0)); + else if(event == -1){ + //Avoid entering on defined events to avoid "hyper-active skill use" due to the overflow of calls to this function in battle. + switch (ms[i].cond1) + { + case MSC_ALWAYS: + flag = 1; break; + case MSC_MYHPLTMAXRATE: // HP< maxhp% + flag = get_percentage(md->status.hp, md->status.max_hp); + flag = (flag <= c2); + break; + case MSC_MYHPINRATE: + flag = get_percentage(md->status.hp, md->status.max_hp); + flag = (flag >= c2 && flag <= ms[i].val[0]); + break; + case MSC_MYSTATUSON: // status[num] on + case MSC_MYSTATUSOFF: // status[num] off + if (!md->sc.count) { + flag = 0; + } else if (ms[i].cond2 == -1) { + for (j = SC_COMMON_MIN; j <= SC_COMMON_MAX; j++) + if ((flag = (md->sc.data[j]!=NULL)) != 0) + break; + } else { + flag = (md->sc.data[ms[i].cond2]!=NULL); + } + flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); break; + case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp% + flag = ((fbl = mob_getfriendhprate(md, 0, ms[i].cond2)) != NULL); break; + case MSC_FRIENDHPINRATE : + flag = ((fbl = mob_getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); break; + case MSC_FRIENDSTATUSON: // friend status[num] on + case MSC_FRIENDSTATUSOFF: // friend status[num] off + flag = ((fmd = mob_getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); break; + case MSC_SLAVELT: // slave < num + flag = (mob_countslave(&md->bl) < c2 ); break; + case MSC_ATTACKPCGT: // attack pc > num + flag = (unit_counttargeted(&md->bl) > c2); break; + case MSC_SLAVELE: // slave <= num + flag = (mob_countslave(&md->bl) <= c2 ); break; + case MSC_ATTACKPCGE: // attack pc >= num + flag = (unit_counttargeted(&md->bl) >= c2); break; + case MSC_AFTERSKILL: + flag = (md->ud.skillid == c2); break; + case MSC_RUDEATTACKED: + flag = (md->state.attacked_count >= RUDE_ATTACKED_COUNT); + if (flag) md->state.attacked_count = 0; //Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex] + break; + case MSC_MASTERHPLTMAXRATE: + flag = ((fbl = mob_getmasterhpltmaxrate(md, ms[i].cond2)) != NULL); break; + case MSC_MASTERATTACKED: + flag = (md->master_id > 0 && (fbl=map_id2bl(md->master_id)) && unit_counttargeted(fbl) > 0); break; + case MSC_ALCHEMIST: + flag = (md->state.alchemist); + break; + } + } + + if (!flag) + continue; //Skill requisite failed to be fulfilled. + + //Execute skill + if (skill_get_casttype(ms[i].skill_id) == CAST_GROUND) + { //Ground skill. + short x, y; + switch (ms[i].target) { + case MST_RANDOM: //Pick a random enemy within skill range. + bl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md), + skill_get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); + break; + case MST_TARGET: + case MST_AROUND5: + case MST_AROUND6: + case MST_AROUND7: + case MST_AROUND8: + bl = map_id2bl(md->target_id); + break; + case MST_MASTER: + bl = &md->bl; + if (md->master_id) + bl = map_id2bl(md->master_id); + if (bl) //Otherwise, fall through. + break; + case MST_FRIEND: + bl = fbl?fbl:(fmd?&fmd->bl:&md->bl); + break; + default: + bl = &md->bl; + break; + } + if (!bl) continue; + + x = bl->x; + y = bl->y; + // Look for an area to cast the spell around... + if (ms[i].target >= MST_AROUND1 || ms[i].target >= MST_AROUND5) { + j = ms[i].target >= MST_AROUND1? + (ms[i].target-MST_AROUND1) +1: + (ms[i].target-MST_AROUND5) +1; + map_search_freecell(&md->bl, md->bl.m, &x, &y, j, j, 3); + } + md->skillidx = i; + map_freeblock_lock(); + if( !battle_check_range(&md->bl,bl,skill_get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) || + !unit_skilluse_pos2(&md->bl, x, y,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel) ) + { + map_freeblock_unlock(); + continue; + } + } else { + //Targetted skill + switch (ms[i].target) { + case MST_RANDOM: //Pick a random enemy within skill range. + bl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md), + skill_get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); + break; + case MST_TARGET: + bl = map_id2bl(md->target_id); + break; + case MST_MASTER: + bl = &md->bl; + if (md->master_id) + bl = map_id2bl(md->master_id); + if (bl) //Otherwise, fall through. + break; + case MST_FRIEND: + if (fbl) { + bl = fbl; + break; + } else if (fmd) { + bl = &fmd->bl; + break; + } // else fall through + default: + bl = &md->bl; + break; + } + if (!bl) continue; + + md->skillidx = i; + map_freeblock_lock(); + if( !battle_check_range(&md->bl,bl,skill_get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) || + !unit_skilluse_id2(&md->bl, bl->id,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel) ) + { + map_freeblock_unlock(); + continue; + } + } + //Skill used. Post-setups... + if ( ms[ i ].msg_id ){ //Display color message [SnakeDrak] + struct mob_chat *mc = mob_chat(ms[i].msg_id); + char temp[CHAT_SIZE_MAX]; + char name[NAME_LENGTH]; + snprintf(name, sizeof name,"%s", md->name); + strtok(name, "#"); // discard extra name identifier if present [Daegaladh] + snprintf(temp, sizeof temp,"%s : %s", name, mc->msg); + clif_messagecolor(&md->bl, mc->color, temp); + } + if(!(battle_config.mob_ai&0x200)) { //pass on delay to same skill. + for (j = 0; j < md->db->maxskill; j++) + if (md->db->skill[j].skill_id == ms[i].skill_id) + md->skilldelay[j]=tick; + } else + md->skilldelay[i]=tick; + map_freeblock_unlock(); + return 1; + } + //No skill was used. + md->skillidx = -1; + return 0; } /*========================================== * Skill use event processing *------------------------------------------*/ int mobskill_event(struct mob_data *md, struct block_list *src, unsigned int tick, int flag) { - int target_id, res = 0; - - if (md->bl.prev == NULL || md->status.hp <= 0) - return 0; - - target_id = md->target_id; - if (!target_id || battle_config.mob_changetarget_byskill) - md->target_id = src->id; - - if (flag == -1) - res = mobskill_use(md, tick, MSC_CASTTARGETED); - else if ((flag&0xffff) == MSC_SKILLUSED) - res = mobskill_use(md, tick, flag); - else if (flag&BF_SHORT) - res = mobskill_use(md, tick, MSC_CLOSEDATTACKED); - else if (flag&BF_LONG && !(flag&BF_MAGIC)) //Long-attacked should not include magic. - res = mobskill_use(md, tick, MSC_LONGRANGEATTACKED); - - if (!res) - //Restore previous target only if skill condition failed to trigger. [Skotlex] - md->target_id = target_id; - //Otherwise check if the target is an enemy, and unlock if needed. - else if (battle_check_target(&md->bl, src, BCT_ENEMY) <= 0) - md->target_id = target_id; - - return res; + int target_id, res = 0; + + if(md->bl.prev == NULL || md->status.hp <= 0) + return 0; + + target_id = md->target_id; + if (!target_id || battle_config.mob_changetarget_byskill) + md->target_id = src->id; + + if (flag == -1) + res = mobskill_use(md, tick, MSC_CASTTARGETED); + else if ((flag&0xffff) == MSC_SKILLUSED) + res = mobskill_use(md, tick, flag); + else if (flag&BF_SHORT) + res = mobskill_use(md, tick, MSC_CLOSEDATTACKED); + else if (flag&BF_LONG && !(flag&BF_MAGIC)) //Long-attacked should not include magic. + res = mobskill_use(md, tick, MSC_LONGRANGEATTACKED); + + if (!res) + //Restore previous target only if skill condition failed to trigger. [Skotlex] + md->target_id = target_id; + //Otherwise check if the target is an enemy, and unlock if needed. + else if (battle_check_target(&md->bl, src, BCT_ENEMY) <= 0) + md->target_id = target_id; + + return res; } // Player cloned mobs. [Valaris] int mob_is_clone(int class_) { - if (class_ < MOB_CLONE_START || class_ > MOB_CLONE_END) - return 0; - if (mob_db(class_) == mob_dummy) - return 0; - return class_; + if(class_ < MOB_CLONE_START || class_ > MOB_CLONE_END) + return 0; + if (mob_db(class_) == mob_dummy) + return 0; + return class_; } //Flag values: @@ -3279,212 +3336,213 @@ int mob_is_clone(int class_) //Returns: ID of newly crafted copy. int mob_clone_spawn(struct map_session_data *sd, int m, int x, int y, const char *event, int master_id, int mode, int flag, unsigned int duration) { - int class_; - int i,j,inf,skill_id, fd; - struct mob_data *md; - struct mob_skill *ms; - struct mob_db *db; - struct status_data *status; - - nullpo_ret(sd); - - if (pc_isdead(sd) && master_id && flag&1) - return 0; - - ARR_FIND(MOB_CLONE_START, MOB_CLONE_END, class_, mob_db_data[class_] == NULL); - if (class_ >= MOB_CLONE_END) - return 0; - - db = mob_db_data[class_]=(struct mob_db *)aCalloc(1, sizeof(struct mob_db)); - status = &db->status; - strcpy(db->sprite,sd->status.name); - strcpy(db->name,sd->status.name); - strcpy(db->jname,sd->status.name); - db->lv=status_get_lv(&sd->bl); - memcpy(status, &sd->base_status, sizeof(struct status_data)); - status->rhw.atk2= status->dex + status->rhw.atk + status->rhw.atk2; //Max ATK - status->rhw.atk = status->dex; //Min ATK - if (status->lhw.atk) { - status->lhw.atk2= status->dex + status->lhw.atk + status->lhw.atk2; //Max ATK - status->lhw.atk = status->dex; //Min ATK - } - if (mode) //User provided mode. - status->mode = mode; - else if (flag&1) //Friendly Character, remove looting. - status->mode &= ~MD_LOOTER; - status->hp = status->max_hp; - status->sp = status->max_sp; - memcpy(&db->vd, &sd->vd, sizeof(struct view_data)); - db->base_exp=1; - db->job_exp=1; - db->range2=AREA_SIZE; //Let them have the same view-range as players. - db->range3=AREA_SIZE; //Min chase of a screen. - db->option=sd->sc.option; - - //Skill copy [Skotlex] - ms = &db->skill[0]; - - /** - * We temporarily disable sd's fd so it doesn't receive the messages from skill_check_condition_castbegin - **/ - fd = sd->fd; - sd->fd = 0; - - //Go Backwards to give better priority to advanced skills. - for (i=0,j = MAX_SKILL_TREE-1; j>=0 && i< MAX_MOBSKILL ; j--) { - skill_id = skill_tree[pc_class2idx(sd->status.class_)][j].id; - if (!skill_id || sd->status.skill[skill_id].lv < 1 || - (skill_get_inf2(skill_id)&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)) || - skill_get_nocast(skill_id)&16 - ) - continue; - //Normal aggressive mob, disable skills that cannot help them fight - //against players (those with flags UF_NOMOB and UF_NOPC are specific - //to always aid players!) [Skotlex] - if (!(flag&1) && - skill_get_unit_id(skill_id, 0) && - skill_get_unit_flag(skill_id)&(UF_NOMOB|UF_NOPC)) - continue; - /** - * The clone should be able to cast the skill (e.g. have the required weapon) bugreport:5299) - **/ - if (!skill_check_condition_castbegin(sd,skill_id,sd->status.skill[skill_id].lv)) - continue; - - memset(&ms[i], 0, sizeof(struct mob_skill)); - ms[i].skill_id = skill_id; - ms[i].skill_lv = sd->status.skill[skill_id].lv; - ms[i].state = MSS_ANY; - ms[i].permillage = 500*battle_config.mob_skill_rate/100; //Default chance of all skills: 5% - ms[i].emotion = -1; - ms[i].cancel = 0; - ms[i].casttime = skill_castfix(&sd->bl,skill_id, ms[i].skill_lv); - ms[i].delay = 5000+skill_delayfix(&sd->bl,skill_id, ms[i].skill_lv); - - inf = skill_get_inf(skill_id); - if (inf&INF_ATTACK_SKILL) { - ms[i].target = MST_TARGET; - ms[i].cond1 = MSC_ALWAYS; - if (skill_get_range(skill_id, ms[i].skill_lv) > 3) - ms[i].state = MSS_ANYTARGET; - else - ms[i].state = MSS_BERSERK; - } else if (inf&INF_GROUND_SKILL) { - if (skill_get_inf2(skill_id)&INF2_TRAP) { //Traps! - ms[i].state = MSS_IDLE; - ms[i].target = MST_AROUND2; - ms[i].delay = 60000; - } else if (skill_get_unit_target(skill_id) == BCT_ENEMY) { //Target Enemy - ms[i].state = MSS_ANYTARGET; - ms[i].target = MST_TARGET; - ms[i].cond1 = MSC_ALWAYS; - } else { //Target allies - ms[i].target = MST_FRIEND; - ms[i].cond1 = MSC_FRIENDHPLTMAXRATE; - ms[i].cond2 = 95; - } - } else if (inf&INF_SELF_SKILL) { - if (skill_get_inf2(skill_id)&INF2_NO_TARGET_SELF) { //auto-select target skill. - ms[i].target = MST_TARGET; - ms[i].cond1 = MSC_ALWAYS; - if (skill_get_range(skill_id, ms[i].skill_lv) > 3) { - ms[i].state = MSS_ANYTARGET; - } else { - ms[i].state = MSS_BERSERK; - } - } else { //Self skill - ms[i].target = MST_SELF; - ms[i].cond1 = MSC_MYHPLTMAXRATE; - ms[i].cond2 = 90; - ms[i].permillage = 2000; - //Delay: Remove the stock 5 secs and add half of the support time. - ms[i].delay += -5000 +(skill_get_time(skill_id, ms[i].skill_lv) + skill_get_time2(skill_id, ms[i].skill_lv))/2; - if (ms[i].delay < 5000) - ms[i].delay = 5000; //With a minimum of 5 secs. - } - } else if (inf&INF_SUPPORT_SKILL) { - ms[i].target = MST_FRIEND; - ms[i].cond1 = MSC_FRIENDHPLTMAXRATE; - ms[i].cond2 = 90; - if (skill_id == AL_HEAL) - ms[i].permillage = 5000; //Higher skill rate usage for heal. - else if (skill_id == ALL_RESURRECTION) - ms[i].cond2 = 1; - //Delay: Remove the stock 5 secs and add half of the support time. - ms[i].delay += -5000 +(skill_get_time(skill_id, ms[i].skill_lv) + skill_get_time2(skill_id, ms[i].skill_lv))/2; - if (ms[i].delay < 2000) - ms[i].delay = 2000; //With a minimum of 2 secs. - - if (i+1 < MAX_MOBSKILL) { //duplicate this so it also triggers on self. - memcpy(&ms[i+1], &ms[i], sizeof(struct mob_skill)); - db->maxskill = ++i; - ms[i].target = MST_SELF; - ms[i].cond1 = MSC_MYHPLTMAXRATE; - } - } else { - switch (skill_id) { //Certain Special skills that are passive, and thus, never triggered. - case MO_TRIPLEATTACK: - case TF_DOUBLE: - case GS_CHAINACTION: - ms[i].state = MSS_BERSERK; - ms[i].target = MST_TARGET; - ms[i].cond1 = MSC_ALWAYS; - ms[i].permillage = skill_id==MO_TRIPLEATTACK?(3000-ms[i].skill_lv*100):(ms[i].skill_lv*500); - ms[i].delay -= 5000; //Remove the added delay as these could trigger on "all hits". - break; - default: //Untreated Skill - continue; - } - } - if (battle_config.mob_skill_rate!= 100) - ms[i].permillage = ms[i].permillage*battle_config.mob_skill_rate/100; - if (battle_config.mob_skill_delay != 100) - ms[i].delay = ms[i].delay*battle_config.mob_skill_delay/100; - - db->maxskill = ++i; - } - - /** - * We grant the session it's fd value back. - **/ - sd->fd = fd; - - //Finally, spawn it. - md = mob_once_spawn_sub(&sd->bl, m, x, y, "--en--", class_, event, SZ_SMALL, AI_NONE); - if (!md) return 0; //Failed? - - md->special_state.clone = 1; - - if (master_id || flag || duration) { //Further manipulate crafted char. - if (flag&1) //Friendly Character - md->special_state.ai = AI_ATTACK; - if (master_id) //Attach to Master - md->master_id = master_id; - if (duration) { //Auto Delete after a while. - if (md->deletetimer != INVALID_TIMER) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer(gettick() + duration, mob_timer_delete, md->bl.id, 0); - } - } - - mob_spawn(md); - - return md->bl.id; + int class_; + int i,j,inf,skill_id, fd; + struct mob_data *md; + struct mob_skill *ms; + struct mob_db* db; + struct status_data *status; + + nullpo_ret(sd); + + if(pc_isdead(sd) && master_id && flag&1) + return 0; + + ARR_FIND( MOB_CLONE_START, MOB_CLONE_END, class_, mob_db_data[class_] == NULL ); + if(class_ >= MOB_CLONE_END) + return 0; + + db = mob_db_data[class_]=(struct mob_db*)aCalloc(1, sizeof(struct mob_db)); + status = &db->status; + strcpy(db->sprite,sd->status.name); + strcpy(db->name,sd->status.name); + strcpy(db->jname,sd->status.name); + db->lv=status_get_lv(&sd->bl); + memcpy(status, &sd->base_status, sizeof(struct status_data)); + status->rhw.atk2= status->dex + status->rhw.atk + status->rhw.atk2; //Max ATK + status->rhw.atk = status->dex; //Min ATK + if (status->lhw.atk) { + status->lhw.atk2= status->dex + status->lhw.atk + status->lhw.atk2; //Max ATK + status->lhw.atk = status->dex; //Min ATK + } + if (mode) //User provided mode. + status->mode = mode; + else if (flag&1) //Friendly Character, remove looting. + status->mode &= ~MD_LOOTER; + status->hp = status->max_hp; + status->sp = status->max_sp; + memcpy(&db->vd, &sd->vd, sizeof(struct view_data)); + db->base_exp=1; + db->job_exp=1; + db->range2=AREA_SIZE; //Let them have the same view-range as players. + db->range3=AREA_SIZE; //Min chase of a screen. + db->option=sd->sc.option; + + //Skill copy [Skotlex] + ms = &db->skill[0]; + + /** + * We temporarily disable sd's fd so it doesn't receive the messages from skill_check_condition_castbegin + **/ + fd = sd->fd; + sd->fd = 0; + + //Go Backwards to give better priority to advanced skills. + for (i=0,j = MAX_SKILL_TREE-1;j>=0 && i< MAX_MOBSKILL ;j--) { + skill_id = skill_tree[pc_class2idx(sd->status.class_)][j].id; + if (!skill_id || sd->status.skill[skill_id].lv < 1 || + (skill_get_inf2(skill_id)&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)) || + skill_get_nocast(skill_id)&16 + ) + continue; + //Normal aggressive mob, disable skills that cannot help them fight + //against players (those with flags UF_NOMOB and UF_NOPC are specific + //to always aid players!) [Skotlex] + if (!(flag&1) && + skill_get_unit_id(skill_id, 0) && + skill_get_unit_flag(skill_id)&(UF_NOMOB|UF_NOPC)) + continue; + /** + * The clone should be able to cast the skill (e.g. have the required weapon) bugreport:5299) + **/ + if( !skill_check_condition_castbegin(sd,skill_id,sd->status.skill[skill_id].lv) ) + continue; + + memset (&ms[i], 0, sizeof(struct mob_skill)); + ms[i].skill_id = skill_id; + ms[i].skill_lv = sd->status.skill[skill_id].lv; + ms[i].state = MSS_ANY; + ms[i].permillage = 500*battle_config.mob_skill_rate/100; //Default chance of all skills: 5% + ms[i].emotion = -1; + ms[i].cancel = 0; + ms[i].casttime = skill_castfix(&sd->bl,skill_id, ms[i].skill_lv); + ms[i].delay = 5000+skill_delayfix(&sd->bl,skill_id, ms[i].skill_lv); + + inf = skill_get_inf(skill_id); + if (inf&INF_ATTACK_SKILL) { + ms[i].target = MST_TARGET; + ms[i].cond1 = MSC_ALWAYS; + if (skill_get_range(skill_id, ms[i].skill_lv) > 3) + ms[i].state = MSS_ANYTARGET; + else + ms[i].state = MSS_BERSERK; + } else if(inf&INF_GROUND_SKILL) { + if (skill_get_inf2(skill_id)&INF2_TRAP) { //Traps! + ms[i].state = MSS_IDLE; + ms[i].target = MST_AROUND2; + ms[i].delay = 60000; + } else if (skill_get_unit_target(skill_id) == BCT_ENEMY) { //Target Enemy + ms[i].state = MSS_ANYTARGET; + ms[i].target = MST_TARGET; + ms[i].cond1 = MSC_ALWAYS; + } else { //Target allies + ms[i].target = MST_FRIEND; + ms[i].cond1 = MSC_FRIENDHPLTMAXRATE; + ms[i].cond2 = 95; + } + } else if (inf&INF_SELF_SKILL) { + if (skill_get_inf2(skill_id)&INF2_NO_TARGET_SELF) { //auto-select target skill. + ms[i].target = MST_TARGET; + ms[i].cond1 = MSC_ALWAYS; + if (skill_get_range(skill_id, ms[i].skill_lv) > 3) { + ms[i].state = MSS_ANYTARGET; + } else { + ms[i].state = MSS_BERSERK; + } + } else { //Self skill + ms[i].target = MST_SELF; + ms[i].cond1 = MSC_MYHPLTMAXRATE; + ms[i].cond2 = 90; + ms[i].permillage = 2000; + //Delay: Remove the stock 5 secs and add half of the support time. + ms[i].delay += -5000 +(skill_get_time(skill_id, ms[i].skill_lv) + skill_get_time2(skill_id, ms[i].skill_lv))/2; + if (ms[i].delay < 5000) + ms[i].delay = 5000; //With a minimum of 5 secs. + } + } else if (inf&INF_SUPPORT_SKILL) { + ms[i].target = MST_FRIEND; + ms[i].cond1 = MSC_FRIENDHPLTMAXRATE; + ms[i].cond2 = 90; + if (skill_id == AL_HEAL) + ms[i].permillage = 5000; //Higher skill rate usage for heal. + else if (skill_id == ALL_RESURRECTION) + ms[i].cond2 = 1; + //Delay: Remove the stock 5 secs and add half of the support time. + ms[i].delay += -5000 +(skill_get_time(skill_id, ms[i].skill_lv) + skill_get_time2(skill_id, ms[i].skill_lv))/2; + if (ms[i].delay < 2000) + ms[i].delay = 2000; //With a minimum of 2 secs. + + if (i+1 < MAX_MOBSKILL) { //duplicate this so it also triggers on self. + memcpy(&ms[i+1], &ms[i], sizeof(struct mob_skill)); + db->maxskill = ++i; + ms[i].target = MST_SELF; + ms[i].cond1 = MSC_MYHPLTMAXRATE; + } + } else { + switch (skill_id) { //Certain Special skills that are passive, and thus, never triggered. + case MO_TRIPLEATTACK: + case TF_DOUBLE: + case GS_CHAINACTION: + ms[i].state = MSS_BERSERK; + ms[i].target = MST_TARGET; + ms[i].cond1 = MSC_ALWAYS; + ms[i].permillage = skill_id==MO_TRIPLEATTACK?(3000-ms[i].skill_lv*100):(ms[i].skill_lv*500); + ms[i].delay -= 5000; //Remove the added delay as these could trigger on "all hits". + break; + default: //Untreated Skill + continue; + } + } + if (battle_config.mob_skill_rate!= 100) + ms[i].permillage = ms[i].permillage*battle_config.mob_skill_rate/100; + if (battle_config.mob_skill_delay != 100) + ms[i].delay = ms[i].delay*battle_config.mob_skill_delay/100; + + db->maxskill = ++i; + } + + /** + * We grant the session it's fd value back. + **/ + sd->fd = fd; + + //Finally, spawn it. + md = mob_once_spawn_sub(&sd->bl, m, x, y, "--en--", class_, event, SZ_SMALL, AI_NONE); + if (!md) return 0; //Failed? + + md->special_state.clone = 1; + + if (master_id || flag || duration) { //Further manipulate crafted char. + if (flag&1) //Friendly Character + md->special_state.ai = AI_ATTACK; + if (master_id) //Attach to Master + md->master_id = master_id; + if (duration) //Auto Delete after a while. + { + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer (gettick() + duration, mob_timer_delete, md->bl.id, 0); + } + } + + mob_spawn(md); + + return md->bl.id; } int mob_clone_delete(struct mob_data *md) { - const int class_ = md->class_; - if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END - && mob_db_data[class_]!=NULL) { - aFree(mob_db_data[class_]); - mob_db_data[class_]=NULL; - //Clear references to the db - md->db = mob_dummy; - md->vd = NULL; - return 1; - } - return 0; + const int class_ = md->class_; + if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END + && mob_db_data[class_]!=NULL) { + aFree(mob_db_data[class_]); + mob_db_data[class_]=NULL; + //Clear references to the db + md->db = mob_dummy; + md->vd = NULL; + return 1; + } + return 0; } // @@ -3495,59 +3553,60 @@ int mob_clone_delete(struct mob_data *md) *------------------------------------------*/ static int mob_makedummymobdb(int class_) { - if (mob_dummy != NULL) { - if (mob_db(class_) == mob_dummy) - return 1; //Using the mob_dummy data already. [Skotlex] - if (class_ > 0 && class_ <= MAX_MOB_DB) { - //Remove the mob data so that it uses the dummy data instead. - aFree(mob_db_data[class_]); - mob_db_data[class_] = NULL; - } - return 0; - } - //Initialize dummy data. - mob_dummy = (struct mob_db *)aCalloc(1, sizeof(struct mob_db)); //Initializing the dummy mob. - sprintf(mob_dummy->sprite,"DUMMY"); - sprintf(mob_dummy->name,"Dummy"); - sprintf(mob_dummy->jname,"Dummy"); - mob_dummy->lv=1; - mob_dummy->status.max_hp=1000; - mob_dummy->status.max_sp=1; - mob_dummy->status.rhw.range=1; - mob_dummy->status.rhw.atk=7; - mob_dummy->status.rhw.atk2=10; - mob_dummy->status.str=1; - mob_dummy->status.agi=1; - mob_dummy->status.vit=1; - mob_dummy->status.int_=1; - mob_dummy->status.dex=6; - mob_dummy->status.luk=2; - mob_dummy->status.speed=300; - mob_dummy->status.adelay=1000; - mob_dummy->status.amotion=500; - mob_dummy->status.dmotion=500; - mob_dummy->base_exp=2; - mob_dummy->job_exp=1; - mob_dummy->range2=10; - mob_dummy->range3=10; - - return 0; + if (mob_dummy != NULL) + { + if (mob_db(class_) == mob_dummy) + return 1; //Using the mob_dummy data already. [Skotlex] + if (class_ > 0 && class_ <= MAX_MOB_DB) + { //Remove the mob data so that it uses the dummy data instead. + aFree(mob_db_data[class_]); + mob_db_data[class_] = NULL; + } + return 0; + } + //Initialize dummy data. + mob_dummy = (struct mob_db*)aCalloc(1, sizeof(struct mob_db)); //Initializing the dummy mob. + sprintf(mob_dummy->sprite,"DUMMY"); + sprintf(mob_dummy->name,"Dummy"); + sprintf(mob_dummy->jname,"Dummy"); + mob_dummy->lv=1; + mob_dummy->status.max_hp=1000; + mob_dummy->status.max_sp=1; + mob_dummy->status.rhw.range=1; + mob_dummy->status.rhw.atk=7; + mob_dummy->status.rhw.atk2=10; + mob_dummy->status.str=1; + mob_dummy->status.agi=1; + mob_dummy->status.vit=1; + mob_dummy->status.int_=1; + mob_dummy->status.dex=6; + mob_dummy->status.luk=2; + mob_dummy->status.speed=300; + mob_dummy->status.adelay=1000; + mob_dummy->status.amotion=500; + mob_dummy->status.dmotion=500; + mob_dummy->base_exp=2; + mob_dummy->job_exp=1; + mob_dummy->range2=10; + mob_dummy->range3=10; + + return 0; } //Adjusts the drop rate of item according to the criteria given. [Skotlex] static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_min, unsigned short rate_max) { - double rate = baserate; + double rate = baserate; - if (battle_config.logarithmic_drops && rate_adjust > 0 && baserate > 0) //Logarithmic drops equation by Ishizu-Chan - //Equation: Droprate(x,y) = x * (5 - log(x)) ^ (ln(y) / ln(5)) - //x is the normal Droprate, y is the Modificator. - rate = rate * pow((5.0 - log10(rate)), (log(rate_adjust/100.) / log(5.0))) + 0.5; - else - //Classical linear rate adjustment. - rate = rate * rate_adjust/100; + if (battle_config.logarithmic_drops && rate_adjust > 0 && baserate > 0) //Logarithmic drops equation by Ishizu-Chan + //Equation: Droprate(x,y) = x * (5 - log(x)) ^ (ln(y) / ln(5)) + //x is the normal Droprate, y is the Modificator. + rate = rate * pow((5.0 - log10(rate)), (log(rate_adjust/100.) / log(5.0))) + 0.5; + else + //Classical linear rate adjustment. + rate = rate * rate_adjust/100; - return (unsigned int)cap_value(rate,rate_min,rate_max); + return (unsigned int)cap_value(rate,rate_min,rate_max); } /** @@ -3559,289 +3618,293 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor */ static void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust) { - int i; - if (item_drop_ratio_db[nameid]) { - if (item_drop_ratio_db[nameid]->mob_id[0]) { // only for listed mobs - ARR_FIND(0, MAX_ITEMRATIO_MOBS, i, item_drop_ratio_db[nameid]->mob_id[i] == mob_id); - if (i < MAX_ITEMRATIO_MOBS) // found - *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio; - } else // for all mobs - *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio; - } + int i; + if( item_drop_ratio_db[nameid] ) { + if( item_drop_ratio_db[nameid]->mob_id[0] ) { // only for listed mobs + ARR_FIND(0, MAX_ITEMRATIO_MOBS, i, item_drop_ratio_db[nameid]->mob_id[i] == mob_id); + if(i < MAX_ITEMRATIO_MOBS) // found + *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio; + } + else // for all mobs + *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio; + } } /*========================================== * processes one mobdb entry *------------------------------------------*/ -static bool mob_parse_dbrow(char **str) +static bool mob_parse_dbrow(char** str) { - struct mob_db *db, entry; - struct status_data *status; - int class_, i, k; - double exp, maxhp; - struct mob_data data; - - class_ = atoi(str[0]); - - if (class_ <= 1000 || class_ > MAX_MOB_DB) { - ShowError("mob_parse_dbrow: Invalid monster ID %d, must be in range %d-%d.\n", class_, 1000, MAX_MOB_DB); - return false; - } - if (pcdb_checkid(class_)) { - ShowError("mob_parse_dbrow: Invalid monster ID %d, reserved for player classes.\n", class_); - return false; - } - - if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END) { - ShowError("mob_parse_dbrow: Invalid monster ID %d. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d).\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB); - return false; - } - - memset(&entry, 0, sizeof(entry)); - - db = &entry; - status = &db->status; - - db->vd.class_ = class_; - safestrncpy(db->sprite, str[1], sizeof(db->sprite)); - safestrncpy(db->jname, str[2], sizeof(db->jname)); - safestrncpy(db->name, str[3], sizeof(db->name)); - db->lv = atoi(str[4]); - db->lv = cap_value(db->lv, 1, USHRT_MAX); - status->max_hp = atoi(str[5]); - status->max_sp = atoi(str[6]); - - exp = (double)atoi(str[7]) * (double)battle_config.base_exp_rate / 100.; - db->base_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); - - exp = (double)atoi(str[8]) * (double)battle_config.job_exp_rate / 100.; - db->job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); - - status->rhw.range = atoi(str[9]); - status->rhw.atk = atoi(str[10]); - status->rhw.atk2 = atoi(str[11]); - status->def = atoi(str[12]); - status->mdef = atoi(str[13]); - status->str = atoi(str[14]); - status->agi = atoi(str[15]); - status->vit = atoi(str[16]); - status->int_ = atoi(str[17]); - status->dex = atoi(str[18]); - status->luk = atoi(str[19]); - //All status should be min 1 to prevent divisions by zero from some skills. [Skotlex] - if (status->str < 1) status->str = 1; - if (status->agi < 1) status->agi = 1; - if (status->vit < 1) status->vit = 1; - if (status->int_< 1) status->int_= 1; - if (status->dex < 1) status->dex = 1; - if (status->luk < 1) status->luk = 1; - - db->range2 = atoi(str[20]); - db->range3 = atoi(str[21]); - if (battle_config.view_range_rate != 100) { - db->range2 = db->range2 * battle_config.view_range_rate / 100; - if (db->range2 < 1) - db->range2 = 1; - } - if (battle_config.chase_range_rate != 100) { - db->range3 = db->range3 * battle_config.chase_range_rate / 100; - if (db->range3 < db->range2) - db->range3 = db->range2; - } - - status->size = atoi(str[22]); - status->race = atoi(str[23]); - - i = atoi(str[24]); //Element - status->def_ele = i%10; - status->ele_lv = i/20; - if (status->def_ele >= ELE_MAX) { - ShowError("mob_parse_dbrow: Invalid element type %d for monster ID %d (max=%d).\n", status->def_ele, class_, ELE_MAX-1); - return false; - } - if (status->ele_lv < 1 || status->ele_lv > 4) { - ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-4.\n", status->ele_lv, class_); - return false; - } - - status->mode = (int)strtol(str[25], NULL, 0); - if (!battle_config.monster_active_enable) - status->mode &= ~MD_AGGRESSIVE; - - status->speed = atoi(str[26]); - status->aspd_rate = 1000; - i = atoi(str[27]); - status->adelay = cap_value(i, battle_config.monster_max_aspd*2, 4000); - i = atoi(str[28]); - status->amotion = cap_value(i, battle_config.monster_max_aspd, 2000); - //If the attack animation is longer than the delay, the client crops the attack animation! - //On aegis there is no real visible effect of having a recharge-time less than amotion anyway. - if (status->adelay < status->amotion) - status->adelay = status->amotion; - status->dmotion = atoi(str[29]); - if (battle_config.monster_damage_delay_rate != 100) - status->dmotion = status->dmotion * battle_config.monster_damage_delay_rate / 100; - - // Fill in remaining status data by using a dummy monster. - data.bl.type = BL_MOB; - data.level = db->lv; - memcpy(&data.status, status, sizeof(struct status_data)); - status_calc_misc(&data.bl, status, db->lv); - - // MVP EXP Bonus: MEXP - // Some new MVP's MEXP multipled by high exp-rate cause overflow. [LuzZza] - exp = (double)atoi(str[30]) * (double)battle_config.mvp_exp_rate / 100.; - db->mexp = (unsigned int)cap_value(exp, 0, UINT_MAX); - - //Now that we know if it is an mvp or not, apply battle_config modifiers [Skotlex] - maxhp = (double)status->max_hp; - if (db->mexp > 0) { //Mvp - if (battle_config.mvp_hp_rate != 100) - maxhp = maxhp * (double)battle_config.mvp_hp_rate / 100.; - } else //Normal mob - if (battle_config.monster_hp_rate != 100) - maxhp = maxhp * (double)battle_config.monster_hp_rate / 100.; - - status->max_hp = (unsigned int)cap_value(maxhp, 1, UINT_MAX); - if (status->max_sp < 1) status->max_sp = 1; - - //Since mobs always respawn with full life... - status->hp = status->max_hp; - status->sp = status->max_sp; - - // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per - for (i = 0; i < MAX_MVP_DROP; i++) { - struct item_data *id; - int rate_adjust = battle_config.item_rate_mvp;; - db->mvpitem[i].nameid = atoi(str[31+i*2]); - if (!db->mvpitem[i].nameid) { - db->mvpitem[i].p = 0; //No item.... - continue; - } - item_dropratio_adjust(db->mvpitem[i].nameid, class_, &rate_adjust); - db->mvpitem[i].p = mob_drop_adjust(atoi(str[32+i*2]), rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max); - - //calculate and store Max available drop chance of the MVP item - if (db->mvpitem[i].p) { - id = itemdb_search(db->mvpitem[i].nameid); - if (id->maxchance == -1 || (id->maxchance < db->mvpitem[i].p/10 + 1)) { - //item has bigger drop chance or sold in shops - id->maxchance = db->mvpitem[i].p/10 + 1; //reduce MVP drop info to not spoil common drop rate - } - } - } - - for (i = 0; i < MAX_MOB_DROP; i++) { - int rate = 0, rate_adjust, type; - unsigned short ratemin, ratemax; - struct item_data *id; - k = 31 + MAX_MVP_DROP*2 + i*2; - db->dropitem[i].nameid = atoi(str[k]); - if (!db->dropitem[i].nameid) { - db->dropitem[i].p = 0; //No drop. - continue; - } - id = itemdb_search(db->dropitem[i].nameid); - type = id->type; - rate = atoi(str[k+1]); - if ((class_ >= 1324 && class_ <= 1363) || (class_ >= 1938 && class_ <= 1946)) { - //Treasure box drop rates [Skotlex] - rate_adjust = battle_config.item_rate_treasure; - ratemin = battle_config.item_drop_treasure_min; - ratemax = battle_config.item_drop_treasure_max; - } else switch (type) { - // Added suport to restrict normal drops of MVP's [Reddozen] - case IT_HEALING: - rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_heal_boss : battle_config.item_rate_heal; - ratemin = battle_config.item_drop_heal_min; - ratemax = battle_config.item_drop_heal_max; - break; - case IT_USABLE: - case IT_CASH: - rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_use_boss : battle_config.item_rate_use; - ratemin = battle_config.item_drop_use_min; - ratemax = battle_config.item_drop_use_max; - break; - case IT_WEAPON: - case IT_ARMOR: - case IT_PETARMOR: - rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_equip_boss : battle_config.item_rate_equip; - ratemin = battle_config.item_drop_equip_min; - ratemax = battle_config.item_drop_equip_max; - break; - case IT_CARD: - rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_card_boss : battle_config.item_rate_card; - ratemin = battle_config.item_drop_card_min; - ratemax = battle_config.item_drop_card_max; - break; - default: - rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_common_boss : battle_config.item_rate_common; - ratemin = battle_config.item_drop_common_min; - ratemax = battle_config.item_drop_common_max; - break; - } - item_dropratio_adjust(id->nameid, class_, &rate_adjust); - db->dropitem[i].p = mob_drop_adjust(rate, rate_adjust, ratemin, ratemax); - - //calculate and store Max available drop chance of the item - if (db->dropitem[i].p && (class_ < 1324 || class_ > 1363) && (class_ < 1938 || class_ > 1946)) { - //Skip treasure chests. - if (id->maxchance == -1 || (id->maxchance < db->dropitem[i].p)) { - id->maxchance = db->dropitem[i].p; //item has bigger drop chance or sold in shops - } - for (k = 0; k< MAX_SEARCH; k++) { - if (id->mob[k].chance <= db->dropitem[i].p) - break; - } - if (k == MAX_SEARCH) - continue; - - if (id->mob[k].id != class_) - memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0])); - id->mob[k].chance = db->dropitem[i].p; - id->mob[k].id = class_; - } - } - - // Finally insert monster's data into the database. - if (mob_db_data[class_] == NULL) - mob_db_data[class_] = (struct mob_db *)aCalloc(1, sizeof(struct mob_db)); - else - //Copy over spawn data - memcpy(&db->spawn, mob_db_data[class_]->spawn, sizeof(db->spawn)); - - memcpy(mob_db_data[class_], db, sizeof(struct mob_db)); - return true; + struct mob_db *db, entry; + struct status_data *status; + int class_, i, k; + double exp, maxhp; + struct mob_data data; + + class_ = atoi(str[0]); + + if (class_ <= 1000 || class_ > MAX_MOB_DB) { + ShowError("mob_parse_dbrow: Invalid monster ID %d, must be in range %d-%d.\n", class_, 1000, MAX_MOB_DB); + return false; + } + if (pcdb_checkid(class_)) { + ShowError("mob_parse_dbrow: Invalid monster ID %d, reserved for player classes.\n", class_); + return false; + } + + if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END) { + ShowError("mob_parse_dbrow: Invalid monster ID %d. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d).\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB); + return false; + } + + memset(&entry, 0, sizeof(entry)); + + db = &entry; + status = &db->status; + + db->vd.class_ = class_; + safestrncpy(db->sprite, str[1], sizeof(db->sprite)); + safestrncpy(db->jname, str[2], sizeof(db->jname)); + safestrncpy(db->name, str[3], sizeof(db->name)); + db->lv = atoi(str[4]); + db->lv = cap_value(db->lv, 1, USHRT_MAX); + status->max_hp = atoi(str[5]); + status->max_sp = atoi(str[6]); + + exp = (double)atoi(str[7]) * (double)battle_config.base_exp_rate / 100.; + db->base_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); + + exp = (double)atoi(str[8]) * (double)battle_config.job_exp_rate / 100.; + db->job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); + + status->rhw.range = atoi(str[9]); + status->rhw.atk = atoi(str[10]); + status->rhw.atk2 = atoi(str[11]); + status->def = atoi(str[12]); + status->mdef = atoi(str[13]); + status->str = atoi(str[14]); + status->agi = atoi(str[15]); + status->vit = atoi(str[16]); + status->int_ = atoi(str[17]); + status->dex = atoi(str[18]); + status->luk = atoi(str[19]); + //All status should be min 1 to prevent divisions by zero from some skills. [Skotlex] + if (status->str < 1) status->str = 1; + if (status->agi < 1) status->agi = 1; + if (status->vit < 1) status->vit = 1; + if (status->int_< 1) status->int_= 1; + if (status->dex < 1) status->dex = 1; + if (status->luk < 1) status->luk = 1; + + db->range2 = atoi(str[20]); + db->range3 = atoi(str[21]); + if (battle_config.view_range_rate != 100) { + db->range2 = db->range2 * battle_config.view_range_rate / 100; + if (db->range2 < 1) + db->range2 = 1; + } + if (battle_config.chase_range_rate != 100) { + db->range3 = db->range3 * battle_config.chase_range_rate / 100; + if (db->range3 < db->range2) + db->range3 = db->range2; + } + + status->size = atoi(str[22]); + status->race = atoi(str[23]); + + i = atoi(str[24]); //Element + status->def_ele = i%10; + status->ele_lv = i/20; + if (status->def_ele >= ELE_MAX) { + ShowError("mob_parse_dbrow: Invalid element type %d for monster ID %d (max=%d).\n", status->def_ele, class_, ELE_MAX-1); + return false; + } + if (status->ele_lv < 1 || status->ele_lv > 4) { + ShowError("mob_parse_dbrow: Invalid element level %d for monster ID %d, must be in range 1-4.\n", status->ele_lv, class_); + return false; + } + + status->mode = (int)strtol(str[25], NULL, 0); + if (!battle_config.monster_active_enable) + status->mode &= ~MD_AGGRESSIVE; + + status->speed = atoi(str[26]); + status->aspd_rate = 1000; + i = atoi(str[27]); + status->adelay = cap_value(i, battle_config.monster_max_aspd*2, 4000); + i = atoi(str[28]); + status->amotion = cap_value(i, battle_config.monster_max_aspd, 2000); + //If the attack animation is longer than the delay, the client crops the attack animation! + //On aegis there is no real visible effect of having a recharge-time less than amotion anyway. + if (status->adelay < status->amotion) + status->adelay = status->amotion; + status->dmotion = atoi(str[29]); + if(battle_config.monster_damage_delay_rate != 100) + status->dmotion = status->dmotion * battle_config.monster_damage_delay_rate / 100; + + // Fill in remaining status data by using a dummy monster. + data.bl.type = BL_MOB; + data.level = db->lv; + memcpy(&data.status, status, sizeof(struct status_data)); + status_calc_misc(&data.bl, status, db->lv); + + // MVP EXP Bonus: MEXP + // Some new MVP's MEXP multipled by high exp-rate cause overflow. [LuzZza] + exp = (double)atoi(str[30]) * (double)battle_config.mvp_exp_rate / 100.; + db->mexp = (unsigned int)cap_value(exp, 0, UINT_MAX); + + //Now that we know if it is an mvp or not, apply battle_config modifiers [Skotlex] + maxhp = (double)status->max_hp; + if (db->mexp > 0) { //Mvp + if (battle_config.mvp_hp_rate != 100) + maxhp = maxhp * (double)battle_config.mvp_hp_rate / 100.; + } else //Normal mob + if (battle_config.monster_hp_rate != 100) + maxhp = maxhp * (double)battle_config.monster_hp_rate / 100.; + + status->max_hp = (unsigned int)cap_value(maxhp, 1, UINT_MAX); + if(status->max_sp < 1) status->max_sp = 1; + + //Since mobs always respawn with full life... + status->hp = status->max_hp; + status->sp = status->max_sp; + + // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per + for(i = 0; i < MAX_MVP_DROP; i++) { + struct item_data *id; + int rate_adjust = battle_config.item_rate_mvp;; + db->mvpitem[i].nameid = atoi(str[31+i*2]); + if (!db->mvpitem[i].nameid) { + db->mvpitem[i].p = 0; //No item.... + continue; + } + item_dropratio_adjust(db->mvpitem[i].nameid, class_, &rate_adjust); + db->mvpitem[i].p = mob_drop_adjust(atoi(str[32+i*2]), rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max); + + //calculate and store Max available drop chance of the MVP item + if (db->mvpitem[i].p) { + id = itemdb_search(db->mvpitem[i].nameid); + if (id->maxchance == -1 || (id->maxchance < db->mvpitem[i].p/10 + 1) ) { + //item has bigger drop chance or sold in shops + id->maxchance = db->mvpitem[i].p/10 + 1; //reduce MVP drop info to not spoil common drop rate + } + } + } + + for(i = 0; i < MAX_MOB_DROP; i++) { + int rate = 0, rate_adjust, type; + unsigned short ratemin, ratemax; + struct item_data *id; + k = 31 + MAX_MVP_DROP*2 + i*2; + db->dropitem[i].nameid = atoi(str[k]); + if (!db->dropitem[i].nameid) { + db->dropitem[i].p = 0; //No drop. + continue; + } + id = itemdb_search(db->dropitem[i].nameid); + type = id->type; + rate = atoi(str[k+1]); + if( (class_ >= 1324 && class_ <= 1363) || (class_ >= 1938 && class_ <= 1946) ) + { //Treasure box drop rates [Skotlex] + rate_adjust = battle_config.item_rate_treasure; + ratemin = battle_config.item_drop_treasure_min; + ratemax = battle_config.item_drop_treasure_max; + } + else switch (type) + { // Added suport to restrict normal drops of MVP's [Reddozen] + case IT_HEALING: + rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_heal_boss : battle_config.item_rate_heal; + ratemin = battle_config.item_drop_heal_min; + ratemax = battle_config.item_drop_heal_max; + break; + case IT_USABLE: + case IT_CASH: + rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_use_boss : battle_config.item_rate_use; + ratemin = battle_config.item_drop_use_min; + ratemax = battle_config.item_drop_use_max; + break; + case IT_WEAPON: + case IT_ARMOR: + case IT_PETARMOR: + rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_equip_boss : battle_config.item_rate_equip; + ratemin = battle_config.item_drop_equip_min; + ratemax = battle_config.item_drop_equip_max; + break; + case IT_CARD: + rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_card_boss : battle_config.item_rate_card; + ratemin = battle_config.item_drop_card_min; + ratemax = battle_config.item_drop_card_max; + break; + default: + rate_adjust = (status->mode&MD_BOSS) ? battle_config.item_rate_common_boss : battle_config.item_rate_common; + ratemin = battle_config.item_drop_common_min; + ratemax = battle_config.item_drop_common_max; + break; + } + item_dropratio_adjust(id->nameid, class_, &rate_adjust); + db->dropitem[i].p = mob_drop_adjust(rate, rate_adjust, ratemin, ratemax); + + //calculate and store Max available drop chance of the item + if( db->dropitem[i].p && (class_ < 1324 || class_ > 1363) && (class_ < 1938 || class_ > 1946) ) + { //Skip treasure chests. + if (id->maxchance == -1 || (id->maxchance < db->dropitem[i].p) ) { + id->maxchance = db->dropitem[i].p; //item has bigger drop chance or sold in shops + } + for (k = 0; k< MAX_SEARCH; k++) { + if (id->mob[k].chance <= db->dropitem[i].p) + break; + } + if (k == MAX_SEARCH) + continue; + + if (id->mob[k].id != class_) + memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0])); + id->mob[k].chance = db->dropitem[i].p; + id->mob[k].id = class_; + } + } + + // Finally insert monster's data into the database. + if (mob_db_data[class_] == NULL) + mob_db_data[class_] = (struct mob_db*)aCalloc(1, sizeof(struct mob_db)); + else + //Copy over spawn data + memcpy(&db->spawn, mob_db_data[class_]->spawn, sizeof(db->spawn)); + + memcpy(mob_db_data[class_], db, sizeof(struct mob_db)); + return true; } /*========================================== * mob_db.txt reading *------------------------------------------*/ -static bool mob_readdb_sub(char *fields[], int columns, int current) +static bool mob_readdb_sub(char* fields[], int columns, int current) { - return mob_parse_dbrow(fields); + return mob_parse_dbrow(fields); } static void mob_readdb(void) { - const char *filename[] = { - DBPATH"mob_db.txt", - "mob_db2.txt" - }; - int fi; - - for (fi = 0; fi < ARRAYLENGTH(filename); ++fi) { - char path[256]; - - if (fi > 0) { - sprintf(path, "%s/%s", db_path, filename[fi]); - if (!exists(path)) { - continue; - } - } - - sv_readdb(db_path, filename[fi], ',', 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, &mob_readdb_sub); - } + const char* filename[] = { + DBPATH"mob_db.txt", + "mob_db2.txt" }; + int fi; + + for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) + { + char path[256]; + + if(fi > 0) + { + sprintf(path, "%s/%s", db_path, filename[fi]); + if(!exists(path)) + { + continue; + } + } + + sv_readdb(db_path, filename[fi], ',', 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, &mob_readdb_sub); + } } /*========================================== @@ -3849,88 +3912,91 @@ static void mob_readdb(void) *------------------------------------------*/ static int mob_read_sqldb(void) { - const char *mob_db_name[] = { mob_db_db, mob_db2_db }; - int fi; - - for (fi = 0; fi < ARRAYLENGTH(mob_db_name); ++fi) { - uint32 lines = 0, count = 0; - - // retrieve all rows from the mob database - if (SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", mob_db_name[fi])) { - Sql_ShowDebug(mmysql_handle); - continue; - } - - // process rows one by one - while (SQL_SUCCESS == Sql_NextRow(mmysql_handle)) { - // wrap the result into a TXT-compatible format - char line[1024]; - char *str[31+2*MAX_MVP_DROP+2*MAX_MOB_DROP]; - char *p; - int i; - - lines++; - for (i = 0, p = line; i < 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP; i++) { - char *data; - size_t len; - Sql_GetData(mmysql_handle, i, &data, &len); - - strcpy(p, data); - str[i] = p; - p+= len + 1; - } - - if (!mob_parse_dbrow(str)) - continue; - - count++; - } - - // free the query result - Sql_FreeResult(mmysql_handle); - - ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_db_name[fi]); - } - return 0; + const char* mob_db_name[] = { mob_db_db, mob_db2_db }; + int fi; + + for( fi = 0; fi < ARRAYLENGTH(mob_db_name); ++fi ) { + uint32 lines = 0, count = 0; + + // retrieve all rows from the mob database + if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", mob_db_name[fi]) ) { + Sql_ShowDebug(mmysql_handle); + continue; + } + + // process rows one by one + while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) { + // wrap the result into a TXT-compatible format + char line[1024]; + char* str[31+2*MAX_MVP_DROP+2*MAX_MOB_DROP]; + char* p; + int i; + + lines++; + for(i = 0, p = line; i < 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP; i++) + { + char* data; + size_t len; + Sql_GetData(mmysql_handle, i, &data, &len); + + strcpy(p, data); + str[i] = p; + p+= len + 1; + } + + if (!mob_parse_dbrow(str)) + continue; + + count++; + } + + // free the query result + Sql_FreeResult(mmysql_handle); + + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_db_name[fi]); + } + return 0; } /*========================================== * MOB display graphic change data reading *------------------------------------------*/ -static bool mob_readdb_mobavail(char *str[], int columns, int current) +static bool mob_readdb_mobavail(char* str[], int columns, int current) { - int class_, k; - - class_=atoi(str[0]); - - if (mob_db(class_) == mob_dummy) { // invalid class (probably undefined in db) - ShowWarning("mob_readdb_mobavail: Unknown mob id %d.\n", class_); - return false; - } - - k=atoi(str[1]); - - memset(&mob_db_data[class_]->vd, 0, sizeof(struct view_data)); - mob_db_data[class_]->vd.class_=k; - - //Player sprites - if (pcdb_checkid(k) && columns==12) { - mob_db_data[class_]->vd.sex=atoi(str[2]); - mob_db_data[class_]->vd.hair_style=atoi(str[3]); - mob_db_data[class_]->vd.hair_color=atoi(str[4]); - mob_db_data[class_]->vd.weapon=atoi(str[5]); - mob_db_data[class_]->vd.shield=atoi(str[6]); - mob_db_data[class_]->vd.head_top=atoi(str[7]); - mob_db_data[class_]->vd.head_mid=atoi(str[8]); - mob_db_data[class_]->vd.head_bottom=atoi(str[9]); - mob_db_data[class_]->option=atoi(str[10])&~(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE); - mob_db_data[class_]->vd.cloth_color=atoi(str[11]); // Monster player dye option - Valaris - } else if (columns==3) - mob_db_data[class_]->vd.head_bottom=atoi(str[2]); // mob equipment [Valaris] - else if (columns != 2) - return false; - - return true; + int class_, k; + + class_=atoi(str[0]); + + if(mob_db(class_) == mob_dummy) // invalid class (probably undefined in db) + { + ShowWarning("mob_readdb_mobavail: Unknown mob id %d.\n", class_); + return false; + } + + k=atoi(str[1]); + + memset(&mob_db_data[class_]->vd, 0, sizeof(struct view_data)); + mob_db_data[class_]->vd.class_=k; + + //Player sprites + if(pcdb_checkid(k) && columns==12) { + mob_db_data[class_]->vd.sex=atoi(str[2]); + mob_db_data[class_]->vd.hair_style=atoi(str[3]); + mob_db_data[class_]->vd.hair_color=atoi(str[4]); + mob_db_data[class_]->vd.weapon=atoi(str[5]); + mob_db_data[class_]->vd.shield=atoi(str[6]); + mob_db_data[class_]->vd.head_top=atoi(str[7]); + mob_db_data[class_]->vd.head_mid=atoi(str[8]); + mob_db_data[class_]->vd.head_bottom=atoi(str[9]); + mob_db_data[class_]->option=atoi(str[10])&~(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE); + mob_db_data[class_]->vd.cloth_color=atoi(str[11]); // Monster player dye option - Valaris + } + else if(columns==3) + mob_db_data[class_]->vd.head_bottom=atoi(str[2]); // mob equipment [Valaris] + else if( columns != 2 ) + return false; + + return true; } /*========================================== @@ -3938,119 +4004,124 @@ static bool mob_readdb_mobavail(char *str[], int columns, int current) *------------------------------------------*/ static int mob_read_randommonster(void) { - FILE *fp; - char line[1024]; - char *str[10],*p; - int i,j; - const char *mobfile[] = { - DBPATH"mob_branch.txt", - DBPATH"mob_poring.txt", - DBPATH"mob_boss.txt", - "mob_pouch.txt", - "mob_classchange.txt" - }; - - memset(&summon, 0, sizeof(summon)); - - for (i = 0; i < ARRAYLENGTH(mobfile) && i < MAX_RANDOMMONSTER; i++) { - mob_db_data[0]->summonper[i] = 1002; // Default fallback value, in case the database does not provide one - sprintf(line, "%s/%s", db_path, mobfile[i]); - fp=fopen(line,"r"); - if (fp==NULL) { - ShowError("can't read %s\n",line); - return -1; - } - while (fgets(line, sizeof(line), fp)) { - int class_; - if (line[0] == '/' && line[1] == '/') - continue; - memset(str,0,sizeof(str)); - for (j=0,p=line; j<3 && p; j++) { - str[j]=p; - p=strchr(p,','); - if (p) *p++=0; - } - - if (str[0]==NULL || str[2]==NULL) - continue; - - class_ = atoi(str[0]); - if (mob_db(class_) == mob_dummy) - continue; - mob_db_data[class_]->summonper[i]=atoi(str[2]); - if (i) { - if (summon[i].qty < ARRAYLENGTH(summon[i].class_)) //MvPs - summon[i].class_[summon[i].qty++] = class_; - else { - ShowDebug("Can't store more random mobs from %s, increase size of mob.c:summon variable!\n", mobfile[i]); - break; - } - } - } - if (i && !summon[i].qty) { - //At least have the default here. - summon[i].class_[0] = mob_db_data[0]->summonper[i]; - summon[i].qty = 1; - } - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",mobfile[i]); - } - return 0; + FILE *fp; + char line[1024]; + char *str[10],*p; + int i,j; + const char* mobfile[] = { + DBPATH"mob_branch.txt", + DBPATH"mob_poring.txt", + DBPATH"mob_boss.txt", + "mob_pouch.txt", + "mob_classchange.txt"}; + + memset(&summon, 0, sizeof(summon)); + + for( i = 0; i < ARRAYLENGTH(mobfile) && i < MAX_RANDOMMONSTER; i++ ) + { + mob_db_data[0]->summonper[i] = 1002; // Default fallback value, in case the database does not provide one + sprintf(line, "%s/%s", db_path, mobfile[i]); + fp=fopen(line,"r"); + if(fp==NULL){ + ShowError("can't read %s\n",line); + return -1; + } + while(fgets(line, sizeof(line), fp)) + { + int class_; + if(line[0] == '/' && line[1] == '/') + continue; + memset(str,0,sizeof(str)); + for(j=0,p=line;j<3 && p;j++){ + str[j]=p; + p=strchr(p,','); + if(p) *p++=0; + } + + if(str[0]==NULL || str[2]==NULL) + continue; + + class_ = atoi(str[0]); + if(mob_db(class_) == mob_dummy) + continue; + mob_db_data[class_]->summonper[i]=atoi(str[2]); + if (i) { + if( summon[i].qty < ARRAYLENGTH(summon[i].class_) ) //MvPs + summon[i].class_[summon[i].qty++] = class_; + else { + ShowDebug("Can't store more random mobs from %s, increase size of mob.c:summon variable!\n", mobfile[i]); + break; + } + } + } + if (i && !summon[i].qty) + { //At least have the default here. + summon[i].class_[0] = mob_db_data[0]->summonper[i]; + summon[i].qty = 1; + } + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",mobfile[i]); + } + return 0; } /*========================================== * processes one mob_chat_db entry [SnakeDrak] * @param last_msg_id ensures that only one error message per mob id is printed *------------------------------------------*/ -static bool mob_parse_row_chatdb(char **str, const char *source, int line, int *last_msg_id) +static bool mob_parse_row_chatdb(char** str, const char* source, int line, int* last_msg_id) { - char *msg; - struct mob_chat *ms; - int msg_id; - size_t len; - - msg_id = atoi(str[0]); - - if (msg_id <= 0 || msg_id > MAX_MOB_CHAT) { - if (msg_id != *last_msg_id) { - ShowError("mob_chat: Invalid chat ID: %d at %s, line %d\n", msg_id, source, line); - *last_msg_id = msg_id; - } - return false; - } - - if (mob_chat_db[msg_id] == NULL) - mob_chat_db[msg_id] = (struct mob_chat *)aCalloc(1, sizeof(struct mob_chat)); - - ms = mob_chat_db[msg_id]; - //MSG ID - ms->msg_id=msg_id; - //Color - ms->color=strtoul(str[1],NULL,0); - //Message - msg = str[2]; - len = strlen(msg); - - while (len && (msg[len-1]=='\r' || msg[len-1]=='\n')) { - // find EOL to strip - len--; - } - - if (len>(CHAT_SIZE_MAX-1)) { - if (msg_id != *last_msg_id) { - ShowError("mob_chat: readdb: Message too long! Line %d, id: %d\n", line, msg_id); - *last_msg_id = msg_id; - } - return false; - } else if (!len) { - ShowWarning("mob_parse_row_chatdb: Empty message for id %d.\n", msg_id); - return false; - } - - msg[len] = 0; // strip previously found EOL - strncpy(ms->msg, str[2], CHAT_SIZE_MAX); - - return true; + char* msg; + struct mob_chat *ms; + int msg_id; + size_t len; + + msg_id = atoi(str[0]); + + if (msg_id <= 0 || msg_id > MAX_MOB_CHAT) + { + if (msg_id != *last_msg_id) { + ShowError("mob_chat: Invalid chat ID: %d at %s, line %d\n", msg_id, source, line); + *last_msg_id = msg_id; + } + return false; + } + + if (mob_chat_db[msg_id] == NULL) + mob_chat_db[msg_id] = (struct mob_chat*)aCalloc(1, sizeof (struct mob_chat)); + + ms = mob_chat_db[msg_id]; + //MSG ID + ms->msg_id=msg_id; + //Color + ms->color=strtoul(str[1],NULL,0); + //Message + msg = str[2]; + len = strlen(msg); + + while( len && ( msg[len-1]=='\r' || msg[len-1]=='\n' ) ) + {// find EOL to strip + len--; + } + + if(len>(CHAT_SIZE_MAX-1)) + { + if (msg_id != *last_msg_id) { + ShowError("mob_chat: readdb: Message too long! Line %d, id: %d\n", line, msg_id); + *last_msg_id = msg_id; + } + return false; + } + else if( !len ) + { + ShowWarning("mob_parse_row_chatdb: Empty message for id %d.\n", msg_id); + return false; + } + + msg[len] = 0; // strip previously found EOL + strncpy(ms->msg, str[2], CHAT_SIZE_MAX); + + return true; } /*========================================== @@ -4058,337 +4129,349 @@ static bool mob_parse_row_chatdb(char **str, const char *source, int line, int * *-------------------------------------------------------------------------*/ static void mob_readchatdb(void) { - char arc[]="mob_chat_db.txt"; - uint32 lines=0, count=0; - char line[1024], path[256]; - int i, tmp=0; - FILE *fp; - sprintf(path, "%s/%s", db_path, arc); - fp=fopen(path, "r"); - if (fp == NULL) { - ShowWarning("mob_readchatdb: File not found \"%s\", skipping.\n", path); - return; - } - - while (fgets(line, sizeof(line), fp)) { - char *str[3], *p, *np; - int j=0; - - lines++; - if (line[0] == '/' && line[1] == '/') - continue; - memset(str, 0, sizeof(str)); - - p=line; - while (ISSPACE(*p)) - ++p; - if (*p == '\0') - continue;// empty line - for (i = 0; i <= 2; i++) { - str[i] = p; - if (i<2 && (np = strchr(p, ',')) != NULL) { - *np = '\0'; - p = np + 1; - j++; - } - } - - if (j < 2 || str[2]==NULL) { - ShowError("mob_readchatdb: Insufficient number of fields for skill at %s, line %d\n", arc, lines); - continue; - } - - if (!mob_parse_row_chatdb(str, path, lines, &tmp)) - continue; - - count++; - } - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n", arc); + char arc[]="mob_chat_db.txt"; + uint32 lines=0, count=0; + char line[1024], path[256]; + int i, tmp=0; + FILE *fp; + sprintf(path, "%s/%s", db_path, arc); + fp=fopen(path, "r"); + if(fp == NULL) + { + ShowWarning("mob_readchatdb: File not found \"%s\", skipping.\n", path); + return; + } + + while(fgets(line, sizeof(line), fp)) + { + char *str[3], *p, *np; + int j=0; + + lines++; + if(line[0] == '/' && line[1] == '/') + continue; + memset(str, 0, sizeof(str)); + + p=line; + while(ISSPACE(*p)) + ++p; + if(*p == '\0') + continue;// empty line + for(i = 0; i <= 2; i++) + { + str[i] = p; + if(i<2 && (np = strchr(p, ',')) != NULL) { + *np = '\0'; p = np + 1; j++; + } + } + + if( j < 2 || str[2]==NULL) + { + ShowError("mob_readchatdb: Insufficient number of fields for skill at %s, line %d\n", arc, lines); + continue; + } + + if( !mob_parse_row_chatdb(str, path, lines, &tmp) ) + continue; + + count++; + } + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n", arc); } /*========================================== * processes one mob_skill_db entry *------------------------------------------*/ -static bool mob_parse_row_mobskilldb(char **str, int columns, int current) +static bool mob_parse_row_mobskilldb(char** str, int columns, int current) { - static const struct { - char str[32]; - enum MobSkillState id; - } state[] = { - { "any", MSS_ANY }, //All states except Dead - { "idle", MSS_IDLE }, - { "walk", MSS_WALK }, - { "loot", MSS_LOOT }, - { "dead", MSS_DEAD }, - { "attack", MSS_BERSERK }, //Retaliating attack - { "angry", MSS_ANGRY }, //Preemptive attack (aggressive mobs) - { "chase", MSS_RUSH }, //Chase escaping target - { "follow", MSS_FOLLOW }, //Preemptive chase (aggressive mobs) - { "anytarget",MSS_ANYTARGET }, //Berserk+Angry+Rush+Follow - }; - static const struct { - char str[32]; - int id; - } cond1[] = { - { "always", MSC_ALWAYS }, - { "myhpltmaxrate", MSC_MYHPLTMAXRATE }, - { "myhpinrate", MSC_MYHPINRATE }, - { "friendhpltmaxrate", MSC_FRIENDHPLTMAXRATE }, - { "friendhpinrate", MSC_FRIENDHPINRATE }, - { "mystatuson", MSC_MYSTATUSON }, - { "mystatusoff", MSC_MYSTATUSOFF }, - { "friendstatuson", MSC_FRIENDSTATUSON }, - { "friendstatusoff", MSC_FRIENDSTATUSOFF }, - { "attackpcgt", MSC_ATTACKPCGT }, - { "attackpcge", MSC_ATTACKPCGE }, - { "slavelt", MSC_SLAVELT }, - { "slavele", MSC_SLAVELE }, - { "closedattacked", MSC_CLOSEDATTACKED }, - { "longrangeattacked", MSC_LONGRANGEATTACKED }, - { "skillused", MSC_SKILLUSED }, - { "afterskill", MSC_AFTERSKILL }, - { "casttargeted", MSC_CASTTARGETED }, - { "rudeattacked", MSC_RUDEATTACKED }, - { "masterhpltmaxrate", MSC_MASTERHPLTMAXRATE }, - { "masterattacked", MSC_MASTERATTACKED }, - { "alchemist", MSC_ALCHEMIST }, - { "onspawn", MSC_SPAWN }, - }, cond2[] = { - { "anybad", -1 }, - { "stone", SC_STONE }, - { "freeze", SC_FREEZE }, - { "stun", SC_STUN }, - { "sleep", SC_SLEEP }, - { "poison", SC_POISON }, - { "curse", SC_CURSE }, - { "silence", SC_SILENCE }, - { "confusion", SC_CONFUSION }, - { "blind", SC_BLIND }, - { "hiding", SC_HIDING }, - { "sight", SC_SIGHT }, - }, target[] = { - { "target", MST_TARGET }, - { "randomtarget", MST_RANDOM }, - { "self", MST_SELF }, - { "friend", MST_FRIEND }, - { "master", MST_MASTER }, - { "around5", MST_AROUND5 }, - { "around6", MST_AROUND6 }, - { "around7", MST_AROUND7 }, - { "around8", MST_AROUND8 }, - { "around1", MST_AROUND1 }, - { "around2", MST_AROUND2 }, - { "around3", MST_AROUND3 }, - { "around4", MST_AROUND4 }, - { "around", MST_AROUND }, - }; - static int last_mob_id = 0; // ensures that only one error message per mob id is printed - - struct mob_skill *ms, gms; - int mob_id; - int i =0, j, tmp; - - mob_id = atoi(str[0]); - - if (mob_id > 0 && mob_db(mob_id) == mob_dummy) { - if (mob_id != last_mob_id) { - ShowError("mob_parse_row_mobskilldb: Non existant Mob id %d\n", mob_id); - last_mob_id = mob_id; - } - return false; - } - if (strcmp(str[1],"clear")==0) { - if (mob_id < 0) - return false; - memset(mob_db_data[mob_id]->skill,0,sizeof(struct mob_skill)); - mob_db_data[mob_id]->maxskill=0; - return true; - } - - if (mob_id < 0) { - //Prepare global skill. [Skotlex] - memset(&gms, 0, sizeof(struct mob_skill)); - ms = &gms; - } else { - ARR_FIND(0, MAX_MOBSKILL, i, (ms = &mob_db_data[mob_id]->skill[i])->skill_id == 0); - if (i == MAX_MOBSKILL) { - if (mob_id != last_mob_id) { - ShowError("mob_parse_row_mobskilldb: Too many skills for monster %d[%s]\n", mob_id, mob_db_data[mob_id]->sprite); - last_mob_id = mob_id; - } - return false; - } - } - - //State - ARR_FIND(0, ARRAYLENGTH(state), j, strcmp(str[2],state[j].str) == 0); - if (j < ARRAYLENGTH(state)) - ms->state = state[j].id; - else { - ShowWarning("mob_parse_row_mobskilldb: Unrecognized state %s\n", str[2]); - ms->state = MSS_ANY; - } - - //Skill ID - j=atoi(str[3]); - if (j<=0 || j>MAX_SKILL_DB) { //fixed Lupus - if (mob_id < 0) - ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for all mobs\n", j); - else - ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for mob %d (%s)\n", j, mob_id, mob_db_data[mob_id]->sprite); - return false; - } - ms->skill_id=j; - - //Skill lvl - j= atoi(str[4])<=0 ? 1 : atoi(str[4]); - ms->skill_lv= j>battle_config.mob_max_skilllvl ? battle_config.mob_max_skilllvl : j; //we strip max skill level - - //Apply battle_config modifiers to rate (permillage) and delay [Skotlex] - tmp = atoi(str[5]); - if (battle_config.mob_skill_rate != 100) - tmp = tmp*battle_config.mob_skill_rate/100; - if (tmp > 10000) - ms->permillage= 10000; - else if (!tmp && battle_config.mob_skill_rate) - ms->permillage= 1; - else - ms->permillage= tmp; - ms->casttime=atoi(str[6]); - ms->delay=atoi(str[7]); - if (battle_config.mob_skill_delay != 100) - ms->delay = ms->delay*battle_config.mob_skill_delay/100; - if (ms->delay < 0 || ms->delay > MOB_MAX_DELAY) //time overflow? - ms->delay = MOB_MAX_DELAY; - ms->cancel=atoi(str[8]); - if (strcmp(str[8],"yes")==0) ms->cancel=1; - - //Target - ARR_FIND(0, ARRAYLENGTH(target), j, strcmp(str[9],target[j].str) == 0); - if (j < ARRAYLENGTH(target)) - ms->target = target[j].id; - else { - ShowWarning("mob_parse_row_mobskilldb: Unrecognized target %s for %d\n", str[9], mob_id); - ms->target = MST_TARGET; - } - - //Check that the target condition is right for the skill type. [Skotlex] - if (skill_get_casttype(ms->skill_id) == CAST_GROUND) { - //Ground skill. - if (ms->target > MST_AROUND) { - ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target for ground skill %d (%s) for %s.\n", - ms->skill_id, skill_get_name(ms->skill_id), - mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite); - ms->target = MST_TARGET; - } - } else if (ms->target > MST_MASTER) { - ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n", - ms->skill_id, skill_get_name(ms->skill_id), - mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite); - ms->target = MST_TARGET; - } - - //Cond1 - ARR_FIND(0, ARRAYLENGTH(cond1), j, strcmp(str[10],cond1[j].str) == 0); - if (j < ARRAYLENGTH(cond1)) - ms->cond1 = cond1[j].id; - else { - ShowWarning("mob_parse_row_mobskilldb: Unrecognized condition 1 %s for %d\n", str[10], mob_id); - ms->cond1 = -1; - } - - //Cond2 - // numeric value - ms->cond2 = atoi(str[11]); - // or special constant - ARR_FIND(0, ARRAYLENGTH(cond2), j, strcmp(str[11],cond2[j].str) == 0); - if (j < ARRAYLENGTH(cond2)) - ms->cond2 = cond2[j].id; - - ms->val[0]=(int)strtol(str[12],NULL,0); - ms->val[1]=(int)strtol(str[13],NULL,0); - ms->val[2]=(int)strtol(str[14],NULL,0); - ms->val[3]=(int)strtol(str[15],NULL,0); - ms->val[4]=(int)strtol(str[16],NULL,0); - - if (ms->skill_id == NPC_EMOTION && mob_id>0 && - ms->val[1] == mob_db(mob_id)->status.mode) { - ms->val[1] = 0; - ms->val[4] = 1; //request to return mode to normal. - } - if (ms->skill_id == NPC_EMOTION_ON && mob_id>0 && ms->val[1]) { - //Adds a mode to the mob. - //Remove aggressive mode when the new mob type is passive. - if (!(ms->val[1]&MD_AGGRESSIVE)) - ms->val[3]|=MD_AGGRESSIVE; - ms->val[2]|= ms->val[1]; //Add the new mode. - ms->val[1] = 0; //Do not "set" it. - } - - if (*str[17]) - ms->emotion=atoi(str[17]); - else - ms->emotion=-1; - - if (str[18]!=NULL && mob_chat_db[atoi(str[18])]!=NULL) - ms->msg_id=atoi(str[18]); - else - ms->msg_id=0; - - if (mob_id < 0) { - //Set this skill to ALL mobs. [Skotlex] - mob_id *= -1; - for (i = 1; i < MAX_MOB_DB; i++) { - if (mob_db_data[i] == NULL) - continue; - if (mob_db_data[i]->status.mode&MD_BOSS) { - if (!(mob_id&2)) //Skill not for bosses - continue; - } else if (!(mob_id&1)) //Skill not for normal enemies. - continue; - - ARR_FIND(0, MAX_MOBSKILL, j, mob_db_data[i]->skill[j].skill_id == 0); - if (j==MAX_MOBSKILL) - continue; - - memcpy(&mob_db_data[i]->skill[j], ms, sizeof(struct mob_skill)); - mob_db_data[i]->maxskill=j+1; - } - } else //Skill set on a single mob. - mob_db_data[mob_id]->maxskill=i+1; - - return true; + static const struct { + char str[32]; + enum MobSkillState id; + } state[] = { + { "any", MSS_ANY }, //All states except Dead + { "idle", MSS_IDLE }, + { "walk", MSS_WALK }, + { "loot", MSS_LOOT }, + { "dead", MSS_DEAD }, + { "attack", MSS_BERSERK }, //Retaliating attack + { "angry", MSS_ANGRY }, //Preemptive attack (aggressive mobs) + { "chase", MSS_RUSH }, //Chase escaping target + { "follow", MSS_FOLLOW }, //Preemptive chase (aggressive mobs) + { "anytarget",MSS_ANYTARGET }, //Berserk+Angry+Rush+Follow + }; + static const struct { + char str[32]; + int id; + } cond1[] = { + { "always", MSC_ALWAYS }, + { "myhpltmaxrate", MSC_MYHPLTMAXRATE }, + { "myhpinrate", MSC_MYHPINRATE }, + { "friendhpltmaxrate", MSC_FRIENDHPLTMAXRATE }, + { "friendhpinrate", MSC_FRIENDHPINRATE }, + { "mystatuson", MSC_MYSTATUSON }, + { "mystatusoff", MSC_MYSTATUSOFF }, + { "friendstatuson", MSC_FRIENDSTATUSON }, + { "friendstatusoff", MSC_FRIENDSTATUSOFF }, + { "attackpcgt", MSC_ATTACKPCGT }, + { "attackpcge", MSC_ATTACKPCGE }, + { "slavelt", MSC_SLAVELT }, + { "slavele", MSC_SLAVELE }, + { "closedattacked", MSC_CLOSEDATTACKED }, + { "longrangeattacked", MSC_LONGRANGEATTACKED }, + { "skillused", MSC_SKILLUSED }, + { "afterskill", MSC_AFTERSKILL }, + { "casttargeted", MSC_CASTTARGETED }, + { "rudeattacked", MSC_RUDEATTACKED }, + { "masterhpltmaxrate", MSC_MASTERHPLTMAXRATE }, + { "masterattacked", MSC_MASTERATTACKED }, + { "alchemist", MSC_ALCHEMIST }, + { "onspawn", MSC_SPAWN }, + }, cond2[] ={ + { "anybad", -1 }, + { "stone", SC_STONE }, + { "freeze", SC_FREEZE }, + { "stun", SC_STUN }, + { "sleep", SC_SLEEP }, + { "poison", SC_POISON }, + { "curse", SC_CURSE }, + { "silence", SC_SILENCE }, + { "confusion", SC_CONFUSION }, + { "blind", SC_BLIND }, + { "hiding", SC_HIDING }, + { "sight", SC_SIGHT }, + }, target[] = { + { "target", MST_TARGET }, + { "randomtarget", MST_RANDOM }, + { "self", MST_SELF }, + { "friend", MST_FRIEND }, + { "master", MST_MASTER }, + { "around5", MST_AROUND5 }, + { "around6", MST_AROUND6 }, + { "around7", MST_AROUND7 }, + { "around8", MST_AROUND8 }, + { "around1", MST_AROUND1 }, + { "around2", MST_AROUND2 }, + { "around3", MST_AROUND3 }, + { "around4", MST_AROUND4 }, + { "around", MST_AROUND }, + }; + static int last_mob_id = 0; // ensures that only one error message per mob id is printed + + struct mob_skill *ms, gms; + int mob_id; + int i =0, j, tmp; + + mob_id = atoi(str[0]); + + if (mob_id > 0 && mob_db(mob_id) == mob_dummy) + { + if (mob_id != last_mob_id) { + ShowError("mob_parse_row_mobskilldb: Non existant Mob id %d\n", mob_id); + last_mob_id = mob_id; + } + return false; + } + if( strcmp(str[1],"clear")==0 ){ + if (mob_id < 0) + return false; + memset(mob_db_data[mob_id]->skill,0,sizeof(struct mob_skill)); + mob_db_data[mob_id]->maxskill=0; + return true; + } + + if (mob_id < 0) + { //Prepare global skill. [Skotlex] + memset(&gms, 0, sizeof (struct mob_skill)); + ms = &gms; + } else { + ARR_FIND( 0, MAX_MOBSKILL, i, (ms = &mob_db_data[mob_id]->skill[i])->skill_id == 0 ); + if( i == MAX_MOBSKILL ) + { + if (mob_id != last_mob_id) { + ShowError("mob_parse_row_mobskilldb: Too many skills for monster %d[%s]\n", mob_id, mob_db_data[mob_id]->sprite); + last_mob_id = mob_id; + } + return false; + } + } + + //State + ARR_FIND( 0, ARRAYLENGTH(state), j, strcmp(str[2],state[j].str) == 0 ); + if( j < ARRAYLENGTH(state) ) + ms->state = state[j].id; + else { + ShowWarning("mob_parse_row_mobskilldb: Unrecognized state %s\n", str[2]); + ms->state = MSS_ANY; + } + + //Skill ID + j=atoi(str[3]); + if (j<=0 || j>MAX_SKILL_DB) //fixed Lupus + { + if (mob_id < 0) + ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for all mobs\n", j); + else + ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for mob %d (%s)\n", j, mob_id, mob_db_data[mob_id]->sprite); + return false; + } + ms->skill_id=j; + + //Skill lvl + j= atoi(str[4])<=0 ? 1 : atoi(str[4]); + ms->skill_lv= j>battle_config.mob_max_skilllvl ? battle_config.mob_max_skilllvl : j; //we strip max skill level + + //Apply battle_config modifiers to rate (permillage) and delay [Skotlex] + tmp = atoi(str[5]); + if (battle_config.mob_skill_rate != 100) + tmp = tmp*battle_config.mob_skill_rate/100; + if (tmp > 10000) + ms->permillage= 10000; + else if (!tmp && battle_config.mob_skill_rate) + ms->permillage= 1; + else + ms->permillage= tmp; + ms->casttime=atoi(str[6]); + ms->delay=atoi(str[7]); + if (battle_config.mob_skill_delay != 100) + ms->delay = ms->delay*battle_config.mob_skill_delay/100; + if (ms->delay < 0 || ms->delay > MOB_MAX_DELAY) //time overflow? + ms->delay = MOB_MAX_DELAY; + ms->cancel=atoi(str[8]); + if( strcmp(str[8],"yes")==0 ) ms->cancel=1; + + //Target + ARR_FIND( 0, ARRAYLENGTH(target), j, strcmp(str[9],target[j].str) == 0 ); + if( j < ARRAYLENGTH(target) ) + ms->target = target[j].id; + else { + ShowWarning("mob_parse_row_mobskilldb: Unrecognized target %s for %d\n", str[9], mob_id); + ms->target = MST_TARGET; + } + + //Check that the target condition is right for the skill type. [Skotlex] + if (skill_get_casttype(ms->skill_id) == CAST_GROUND) + { //Ground skill. + if (ms->target > MST_AROUND) + { + ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target for ground skill %d (%s) for %s.\n", + ms->skill_id, skill_get_name(ms->skill_id), + mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite); + ms->target = MST_TARGET; + } + } else if (ms->target > MST_MASTER) { + ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n", + ms->skill_id, skill_get_name(ms->skill_id), + mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite); + ms->target = MST_TARGET; + } + + //Cond1 + ARR_FIND( 0, ARRAYLENGTH(cond1), j, strcmp(str[10],cond1[j].str) == 0 ); + if( j < ARRAYLENGTH(cond1) ) + ms->cond1 = cond1[j].id; + else { + ShowWarning("mob_parse_row_mobskilldb: Unrecognized condition 1 %s for %d\n", str[10], mob_id); + ms->cond1 = -1; + } + + //Cond2 + // numeric value + ms->cond2 = atoi(str[11]); + // or special constant + ARR_FIND( 0, ARRAYLENGTH(cond2), j, strcmp(str[11],cond2[j].str) == 0 ); + if( j < ARRAYLENGTH(cond2) ) + ms->cond2 = cond2[j].id; + + ms->val[0]=(int)strtol(str[12],NULL,0); + ms->val[1]=(int)strtol(str[13],NULL,0); + ms->val[2]=(int)strtol(str[14],NULL,0); + ms->val[3]=(int)strtol(str[15],NULL,0); + ms->val[4]=(int)strtol(str[16],NULL,0); + + if(ms->skill_id == NPC_EMOTION && mob_id>0 && + ms->val[1] == mob_db(mob_id)->status.mode) + { + ms->val[1] = 0; + ms->val[4] = 1; //request to return mode to normal. + } + if(ms->skill_id == NPC_EMOTION_ON && mob_id>0 && ms->val[1]) + { //Adds a mode to the mob. + //Remove aggressive mode when the new mob type is passive. + if (!(ms->val[1]&MD_AGGRESSIVE)) + ms->val[3]|=MD_AGGRESSIVE; + ms->val[2]|= ms->val[1]; //Add the new mode. + ms->val[1] = 0; //Do not "set" it. + } + + if(*str[17]) + ms->emotion=atoi(str[17]); + else + ms->emotion=-1; + + if(str[18]!=NULL && mob_chat_db[atoi(str[18])]!=NULL) + ms->msg_id=atoi(str[18]); + else + ms->msg_id=0; + + if (mob_id < 0) + { //Set this skill to ALL mobs. [Skotlex] + mob_id *= -1; + for (i = 1; i < MAX_MOB_DB; i++) + { + if (mob_db_data[i] == NULL) + continue; + if (mob_db_data[i]->status.mode&MD_BOSS) + { + if (!(mob_id&2)) //Skill not for bosses + continue; + } else + if (!(mob_id&1)) //Skill not for normal enemies. + continue; + + ARR_FIND( 0, MAX_MOBSKILL, j, mob_db_data[i]->skill[j].skill_id == 0 ); + if(j==MAX_MOBSKILL) + continue; + + memcpy (&mob_db_data[i]->skill[j], ms, sizeof(struct mob_skill)); + mob_db_data[i]->maxskill=j+1; + } + } else //Skill set on a single mob. + mob_db_data[mob_id]->maxskill=i+1; + + return true; } /*========================================== * mob_skill_db.txt reading *------------------------------------------*/ -static void mob_readskilldb(void) -{ - const char *filename[] = { - DBPATH"mob_skill_db.txt", - "mob_skill_db2.txt" - }; - int fi; - - if (battle_config.mob_skill_rate == 0) { - ShowStatus("Mob skill use disabled. Not reading mob skills.\n"); - return; - } - - for (fi = 0; fi < ARRAYLENGTH(filename); ++fi) { - char path[256]; - - if (fi > 0) { - sprintf(path, "%s/%s", db_path, filename[fi]); - if (!exists(path)) { - continue; - } - } - - sv_readdb(db_path, filename[fi], ',', 19, 19, -1, &mob_parse_row_mobskilldb); - } +static void mob_readskilldb(void) { + const char* filename[] = { + DBPATH"mob_skill_db.txt", + "mob_skill_db2.txt" }; + int fi; + + if( battle_config.mob_skill_rate == 0 ) + { + ShowStatus("Mob skill use disabled. Not reading mob skills.\n"); + return; + } + + for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) + { + char path[256]; + + if(fi > 0) + { + sprintf(path, "%s/%s", db_path, filename[fi]); + if(!exists(path)) + { + continue; + } + } + + sv_readdb(db_path, filename[fi], ',', 19, 19, -1, &mob_parse_row_mobskilldb); + } } /** @@ -4398,100 +4481,105 @@ static void mob_readskilldb(void) */ static int mob_read_sqlskilldb(void) { - const char *mob_skill_db_name[] = { mob_skill_db_db, mob_skill_db2_db }; - int fi; - - if (battle_config.mob_skill_rate == 0) { - ShowStatus("Mob skill use disabled. Not reading mob skills.\n"); - return 0; - } - - - for (fi = 0; fi < ARRAYLENGTH(mob_skill_db_name); ++fi) { - uint32 lines = 0, count = 0; - - // retrieve all rows from the mob skill database - if (SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", mob_skill_db_name[fi])) { - Sql_ShowDebug(mmysql_handle); - continue; - } - - // process rows one by one - while (SQL_SUCCESS == Sql_NextRow(mmysql_handle)) { - // wrap the result into a TXT-compatible format - char *str[19]; - char *dummy = ""; - int i; - ++lines; - for (i = 0; i < 19; ++i) { - Sql_GetData(mmysql_handle, i, &str[i], NULL); - if (str[i] == NULL) str[i] = dummy; // get rid of NULL columns - } - - if (!mob_parse_row_mobskilldb(str, 19, count)) - continue; - - count++; - } - - // free the query result - Sql_FreeResult(mmysql_handle); - - ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_skill_db_name[fi]); - } - return 0; + const char* mob_skill_db_name[] = { mob_skill_db_db, mob_skill_db2_db }; + int fi; + + if( battle_config.mob_skill_rate == 0 ) { + ShowStatus("Mob skill use disabled. Not reading mob skills.\n"); + return 0; + } + + + for( fi = 0; fi < ARRAYLENGTH(mob_skill_db_name); ++fi ) { + uint32 lines = 0, count = 0; + + // retrieve all rows from the mob skill database + if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", mob_skill_db_name[fi]) ) { + Sql_ShowDebug(mmysql_handle); + continue; + } + + // process rows one by one + while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) { + // wrap the result into a TXT-compatible format + char* str[19]; + char* dummy = ""; + int i; + ++lines; + for( i = 0; i < 19; ++i ) + { + Sql_GetData(mmysql_handle, i, &str[i], NULL); + if( str[i] == NULL ) str[i] = dummy; // get rid of NULL columns + } + + if (!mob_parse_row_mobskilldb(str, 19, count)) + continue; + + count++; + } + + // free the query result + Sql_FreeResult(mmysql_handle); + + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_skill_db_name[fi]); + } + return 0; } /*========================================== * mob_race2_db.txt reading *------------------------------------------*/ -static bool mob_readdb_race2(char *fields[], int columns, int current) +static bool mob_readdb_race2(char* fields[], int columns, int current) { - int race, mobid, i; - - race = atoi(fields[0]); - - if (race < RC2_NONE || race >= RC2_MAX) { - ShowWarning("mob_readdb_race2: Unknown race2 %d.\n", race); - return false; - } - - for (i = 1; i<columns; i++) { - mobid = atoi(fields[i]); - if (mob_db(mobid) == mob_dummy) { - ShowWarning("mob_readdb_race2: Unknown mob id %d for race2 %d.\n", mobid, race); - continue; - } - mob_db_data[mobid]->race2 = race; - } - return true; + int race, mobid, i; + + race = atoi(fields[0]); + + if (race < RC2_NONE || race >= RC2_MAX) + { + ShowWarning("mob_readdb_race2: Unknown race2 %d.\n", race); + return false; + } + + for(i = 1; i<columns; i++) + { + mobid = atoi(fields[i]); + if (mob_db(mobid) == mob_dummy) + { + ShowWarning("mob_readdb_race2: Unknown mob id %d for race2 %d.\n", mobid, race); + continue; + } + mob_db_data[mobid]->race2 = race; + } + return true; } /** * Read mob_item_ratio.txt */ -static bool mob_readdb_itemratio(char *str[], int columns, int current) +static bool mob_readdb_itemratio(char* str[], int columns, int current) { - int nameid, ratio, i; - struct item_data *id; + int nameid, ratio, i; + struct item_data *id; - nameid = atoi(str[0]); + nameid = atoi(str[0]); - if ((id = itemdb_exists(nameid)) == NULL) { - ShowWarning("itemdb_read_itemratio: Invalid item id %d.\n", nameid); - return false; - } + if( ( id = itemdb_exists(nameid) ) == NULL ) + { + ShowWarning("itemdb_read_itemratio: Invalid item id %d.\n", nameid); + return false; + } - ratio = atoi(str[1]); + ratio = atoi(str[1]); - if (item_drop_ratio_db[nameid] == NULL) - item_drop_ratio_db[nameid] = (struct item_drop_ratio *)aCalloc(1, sizeof(struct item_drop_ratio)); + if(item_drop_ratio_db[nameid] == NULL) + item_drop_ratio_db[nameid] = (struct item_drop_ratio*)aCalloc(1, sizeof(struct item_drop_ratio)); - item_drop_ratio_db[nameid]->drop_ratio = ratio; - for (i = 0; i < columns-2; i++) - item_drop_ratio_db[nameid]->mob_id[i] = atoi(str[i+2]); + item_drop_ratio_db[nameid]->drop_ratio = ratio; + for(i = 0; i < columns-2; i++) + item_drop_ratio_db[nameid]->mob_id[i] = atoi(str[i+2]); - return true; + return true; } /** @@ -4499,76 +4587,76 @@ static bool mob_readdb_itemratio(char *str[], int columns, int current) */ static void mob_load(void) { - sv_readdb(db_path, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, &mob_readdb_itemratio); // must be read before mobdb - mob_readchatdb(); - if (db_use_sqldbs) { - mob_read_sqldb(); - mob_read_sqlskilldb(); - } else { - mob_readdb(); - mob_readskilldb(); - } - sv_readdb(db_path, "mob_avail.txt", ',', 2, 12, -1, &mob_readdb_mobavail); - mob_read_randommonster(); - sv_readdb(db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, &mob_readdb_race2); + sv_readdb(db_path, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, &mob_readdb_itemratio); // must be read before mobdb + mob_readchatdb(); + if (db_use_sqldbs) + { + mob_read_sqldb(); + mob_read_sqlskilldb(); + } + else + { + mob_readdb(); + mob_readskilldb(); + } + sv_readdb(db_path, "mob_avail.txt", ',', 2, 12, -1, &mob_readdb_mobavail); + mob_read_randommonster(); + sv_readdb(db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, &mob_readdb_race2); } -void mob_reload(void) -{ - int i; - - //Mob skills need to be cleared before re-reading them. [Skotlex] - for (i = 0; i < MAX_MOB_DB; i++) - if (mob_db_data[i]) { - memset(&mob_db_data[i]->skill,0,sizeof(mob_db_data[i]->skill)); - mob_db_data[i]->maxskill=0; - } - - // Clear item_drop_ratio_db - for (i = 0; i < MAX_ITEMDB; i++) { - if (item_drop_ratio_db[i]) { - aFree(item_drop_ratio_db[i]); - item_drop_ratio_db[i] = NULL; - } - } - - mob_load(); +void mob_reload(void) { + int i; + + //Mob skills need to be cleared before re-reading them. [Skotlex] + for (i = 0; i < MAX_MOB_DB; i++) + if (mob_db_data[i]) { + memset(&mob_db_data[i]->skill,0,sizeof(mob_db_data[i]->skill)); + mob_db_data[i]->maxskill=0; + } + + // Clear item_drop_ratio_db + for (i = 0; i < MAX_ITEMDB; i++) { + if (item_drop_ratio_db[i]) { + aFree(item_drop_ratio_db[i]); + item_drop_ratio_db[i] = NULL; + } + } + + mob_load(); } void mob_clear_spawninfo() -{ - //Clears spawn related information for a script reload. - int i; - for (i = 0; i < MAX_MOB_DB; i++) - if (mob_db_data[i]) - memset(&mob_db_data[i]->spawn,0,sizeof(mob_db_data[i]->spawn)); +{ //Clears spawn related information for a script reload. + int i; + for (i = 0; i < MAX_MOB_DB; i++) + if (mob_db_data[i]) + memset(&mob_db_data[i]->spawn,0,sizeof(mob_db_data[i]->spawn)); } /*========================================== * Circumference initialization of mob *------------------------------------------*/ int do_init_mob(void) -{ - //Initialize the mob database - memset(mob_db_data,0,sizeof(mob_db_data)); //Clear the array - mob_db_data[0] = (struct mob_db *)aCalloc(1, sizeof(struct mob_db)); //This mob is used for random spawns - mob_makedummymobdb(0); //The first time this is invoked, it creates the dummy mob - item_drop_ers = ers_new(sizeof(struct item_drop),"mob.c::item_drop_ers",ERS_OPT_NONE); - item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"mob.c::item_drop_list_ers",ERS_OPT_NONE); - - mob_load(); - - add_timer_func_list(mob_delayspawn,"mob_delayspawn"); - add_timer_func_list(mob_delay_item_drop,"mob_delay_item_drop"); - add_timer_func_list(mob_ai_hard,"mob_ai_hard"); - add_timer_func_list(mob_ai_lazy,"mob_ai_lazy"); - add_timer_func_list(mob_timer_delete,"mob_timer_delete"); - add_timer_func_list(mob_spawn_guardian_sub,"mob_spawn_guardian_sub"); - add_timer_func_list(mob_respawn,"mob_respawn"); - add_timer_interval(gettick()+MIN_MOBTHINKTIME,mob_ai_hard,0,0,MIN_MOBTHINKTIME); - add_timer_interval(gettick()+MIN_MOBTHINKTIME*10,mob_ai_lazy,0,0,MIN_MOBTHINKTIME*10); - - return 0; +{ //Initialize the mob database + memset(mob_db_data,0,sizeof(mob_db_data)); //Clear the array + mob_db_data[0] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db)); //This mob is used for random spawns + mob_makedummymobdb(0); //The first time this is invoked, it creates the dummy mob + item_drop_ers = ers_new(sizeof(struct item_drop),"mob.c::item_drop_ers",ERS_OPT_NONE); + item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"mob.c::item_drop_list_ers",ERS_OPT_NONE); + + mob_load(); + + add_timer_func_list(mob_delayspawn,"mob_delayspawn"); + add_timer_func_list(mob_delay_item_drop,"mob_delay_item_drop"); + add_timer_func_list(mob_ai_hard,"mob_ai_hard"); + add_timer_func_list(mob_ai_lazy,"mob_ai_lazy"); + add_timer_func_list(mob_timer_delete,"mob_timer_delete"); + add_timer_func_list(mob_spawn_guardian_sub,"mob_spawn_guardian_sub"); + add_timer_func_list(mob_respawn,"mob_respawn"); + add_timer_interval(gettick()+MIN_MOBTHINKTIME,mob_ai_hard,0,0,MIN_MOBTHINKTIME); + add_timer_interval(gettick()+MIN_MOBTHINKTIME*10,mob_ai_lazy,0,0,MIN_MOBTHINKTIME*10); + + return 0; } /*========================================== @@ -4576,30 +4664,37 @@ int do_init_mob(void) *------------------------------------------*/ int do_final_mob(void) { - int i; - if (mob_dummy) { - aFree(mob_dummy); - mob_dummy = NULL; - } - for (i = 0; i <= MAX_MOB_DB; i++) { - if (mob_db_data[i] != NULL) { - aFree(mob_db_data[i]); - mob_db_data[i] = NULL; - } - } - for (i = 0; i <= MAX_MOB_CHAT; i++) { - if (mob_chat_db[i] != NULL) { - aFree(mob_chat_db[i]); - mob_chat_db[i] = NULL; - } - } - for (i = 0; i < MAX_ITEMDB; i++) { - if (item_drop_ratio_db[i] != NULL) { - aFree(item_drop_ratio_db[i]); - item_drop_ratio_db[i] = NULL; - } - } - ers_destroy(item_drop_ers); - ers_destroy(item_drop_list_ers); - return 0; + int i; + if (mob_dummy) + { + aFree(mob_dummy); + mob_dummy = NULL; + } + for (i = 0; i <= MAX_MOB_DB; i++) + { + if (mob_db_data[i] != NULL) + { + aFree(mob_db_data[i]); + mob_db_data[i] = NULL; + } + } + for (i = 0; i <= MAX_MOB_CHAT; i++) + { + if (mob_chat_db[i] != NULL) + { + aFree(mob_chat_db[i]); + mob_chat_db[i] = NULL; + } + } + for (i = 0; i < MAX_ITEMDB; i++) + { + if (item_drop_ratio_db[i] != NULL) + { + aFree(item_drop_ratio_db[i]); + item_drop_ratio_db[i] = NULL; + } + } + ers_destroy(item_drop_ers); + ers_destroy(item_drop_list_ers); + return 0; } diff --git a/src/map/mob.h b/src/map/mob.h index 0923fe796..b052c3b16 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -44,234 +44,231 @@ extern const int mob_splendide[5]; //Mob skill states. enum MobSkillState { - MSS_ANY = -1, - MSS_IDLE, - MSS_WALK, - MSS_LOOT, - MSS_DEAD, - MSS_BERSERK, //Aggressive mob attacking - MSS_ANGRY, //Mob retaliating from being attacked. - MSS_RUSH, //Mob following a player after being attacked. - MSS_FOLLOW, //Mob following a player without being attacked. - MSS_ANYTARGET, + MSS_ANY = -1, + MSS_IDLE, + MSS_WALK, + MSS_LOOT, + MSS_DEAD, + MSS_BERSERK, //Aggressive mob attacking + MSS_ANGRY, //Mob retaliating from being attacked. + MSS_RUSH, //Mob following a player after being attacked. + MSS_FOLLOW, //Mob following a player without being attacked. + MSS_ANYTARGET, }; -enum MobDamageLogFlag { - MDLF_NORMAL = 0, - MDLF_HOMUN, - MDLF_PET, +enum MobDamageLogFlag +{ + MDLF_NORMAL = 0, + MDLF_HOMUN, + MDLF_PET, }; enum size { - SZ_SMALL = 0, - SZ_MEDIUM, - SZ_BIG, + SZ_SMALL = 0, + SZ_MEDIUM, + SZ_BIG, }; enum ai { - AI_NONE = 0, - AI_ATTACK, - AI_SPHERE, - AI_FLORA, - AI_ZANZOU, + AI_NONE = 0, + AI_ATTACK, + AI_SPHERE, + AI_FLORA, + AI_ZANZOU, }; struct mob_skill { - enum MobSkillState state; - short skill_id,skill_lv; - short permillage; - int casttime,delay; - short cancel; - short cond1,cond2; - short target; - int val[5]; - short emotion; - unsigned short msg_id; + enum MobSkillState state; + short skill_id,skill_lv; + short permillage; + int casttime,delay; + short cancel; + short cond1,cond2; + short target; + int val[5]; + short emotion; + unsigned short msg_id; }; struct mob_chat { - unsigned short msg_id; - unsigned long color; - char msg[CHAT_SIZE_MAX]; + unsigned short msg_id; + unsigned long color; + char msg[CHAT_SIZE_MAX]; }; struct spawn_info { - unsigned short mapindex; - unsigned short qty; + unsigned short mapindex; + unsigned short qty; }; struct mob_db { - char sprite[NAME_LENGTH],name[NAME_LENGTH],jname[NAME_LENGTH]; - unsigned int base_exp,job_exp; - unsigned int mexp; - short range2,range3; - short race2; // celest - unsigned short lv; - struct { - int nameid,p; - } dropitem[MAX_MOB_DROP]; - struct { - int nameid,p; - } mvpitem[MAX_MVP_DROP]; - struct status_data status; - struct view_data vd; - unsigned int option; - int summonper[MAX_RANDOMMONSTER]; - int maxskill; - struct mob_skill skill[MAX_MOBSKILL]; - struct spawn_info spawn[10]; + char sprite[NAME_LENGTH],name[NAME_LENGTH],jname[NAME_LENGTH]; + unsigned int base_exp,job_exp; + unsigned int mexp; + short range2,range3; + short race2; // celest + unsigned short lv; + struct { int nameid,p; } dropitem[MAX_MOB_DROP]; + struct { int nameid,p; } mvpitem[MAX_MVP_DROP]; + struct status_data status; + struct view_data vd; + unsigned int option; + int summonper[MAX_RANDOMMONSTER]; + int maxskill; + struct mob_skill skill[MAX_MOBSKILL]; + struct spawn_info spawn[10]; }; struct mob_data { - struct block_list bl; - struct unit_data ud; - struct view_data *vd; - struct status_data status, *base_status; //Second one is in case of leveling up mobs, or tiny/large mobs. - struct status_change sc; - struct mob_db *db; //For quick data access (saves doing mob_db(md->class_) all the time) [Skotlex] - char name[NAME_LENGTH]; - struct { - unsigned int size : 2; //Small/Big monsters. - unsigned int ai : 4; //Special ai for summoned monsters. - //0: Normal mob. - //1: Standard summon, attacks mobs. - //2: Alchemist Marine Sphere - //3: Alchemist Summon Flora - //4: Summon Zanzou - unsigned int clone : 1;/* is clone? 1:0 */ - } special_state; //Special mob information that does not needs to be zero'ed on mob respawn. - struct { - unsigned int aggressive : 1; //Signals whether the mob AI is in aggressive mode or reactive mode. [Skotlex] - unsigned int steal_coin_flag : 1; - unsigned int soul_change_flag : 1; // Celest - unsigned int alchemist: 1; - unsigned int spotted: 1; - unsigned int npc_killmonster: 1; //for new killmonster behavior - unsigned int rebirth: 1; // NPC_Rebirth used - unsigned int boss : 1; - enum MobSkillState skillstate; - unsigned char steal_flag; //number of steal tries (to prevent steal exploit on mobs with few items) [Lupus] - unsigned char attacked_count; //For rude attacked. - int provoke_flag; // Celest - } state; - struct guardian_data *guardian_data; - struct { - int id; - unsigned int dmg; - unsigned int flag : 2; //0: Normal. 1: Homunc exp. 2: Pet exp - } dmglog[DAMAGELOG_SIZE]; - struct spawn_data *spawn; //Spawn data. - int spawn_timer; //Required for Convex Mirror - struct item *lootitem; - short class_; - unsigned int tdmg; //Stores total damage given to the mob, for exp calculations. [Skotlex] - int level; - int target_id,attacked_id; - int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs) - unsigned int bg_id; // BattleGround System - - unsigned int next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick; - short move_fail_count; - short lootitem_count; - short min_chase; - - int deletetimer; - int master_id,master_dist; - - short skillidx; - unsigned int skilldelay[MAX_MOBSKILL]; - char npc_event[EVENT_NAME_LENGTH]; - /** - * Did this monster summon something? - * Used to flag summon deletions, saves a worth amount of memory - **/ - bool can_summon; - /** - * MvP Tombstone NPC ID - **/ - int tomb_nid; + struct block_list bl; + struct unit_data ud; + struct view_data *vd; + struct status_data status, *base_status; //Second one is in case of leveling up mobs, or tiny/large mobs. + struct status_change sc; + struct mob_db *db; //For quick data access (saves doing mob_db(md->class_) all the time) [Skotlex] + char name[NAME_LENGTH]; + struct { + unsigned int size : 2; //Small/Big monsters. + unsigned int ai : 4; //Special ai for summoned monsters. + //0: Normal mob. + //1: Standard summon, attacks mobs. + //2: Alchemist Marine Sphere + //3: Alchemist Summon Flora + //4: Summon Zanzou + unsigned int clone : 1;/* is clone? 1:0 */ + } special_state; //Special mob information that does not needs to be zero'ed on mob respawn. + struct { + unsigned int aggressive : 1; //Signals whether the mob AI is in aggressive mode or reactive mode. [Skotlex] + unsigned int steal_coin_flag : 1; + unsigned int soul_change_flag : 1; // Celest + unsigned int alchemist: 1; + unsigned int spotted: 1; + unsigned int npc_killmonster: 1; //for new killmonster behavior + unsigned int rebirth: 1; // NPC_Rebirth used + unsigned int boss : 1; + enum MobSkillState skillstate; + unsigned char steal_flag; //number of steal tries (to prevent steal exploit on mobs with few items) [Lupus] + unsigned char attacked_count; //For rude attacked. + int provoke_flag; // Celest + } state; + struct guardian_data* guardian_data; + struct { + int id; + unsigned int dmg; + unsigned int flag : 2; //0: Normal. 1: Homunc exp. 2: Pet exp + } dmglog[DAMAGELOG_SIZE]; + struct spawn_data *spawn; //Spawn data. + int spawn_timer; //Required for Convex Mirror + struct item *lootitem; + short class_; + unsigned int tdmg; //Stores total damage given to the mob, for exp calculations. [Skotlex] + int level; + int target_id,attacked_id; + int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs) + unsigned int bg_id; // BattleGround System + + unsigned int next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick; + short move_fail_count; + short lootitem_count; + short min_chase; + + int deletetimer; + int master_id,master_dist; + + short skillidx; + unsigned int skilldelay[MAX_MOBSKILL]; + char npc_event[EVENT_NAME_LENGTH]; + /** + * Did this monster summon something? + * Used to flag summon deletions, saves a worth amount of memory + **/ + bool can_summon; + /** + * MvP Tombstone NPC ID + **/ + int tomb_nid; }; enum { - MST_TARGET = 0, - MST_RANDOM, //Random Target! - MST_SELF, - MST_FRIEND, - MST_MASTER, - MST_AROUND5, - MST_AROUND6, - MST_AROUND7, - MST_AROUND8, - MST_AROUND1, - MST_AROUND2, - MST_AROUND3, - MST_AROUND4, - MST_AROUND = MST_AROUND4, - - MSC_ALWAYS = 0x0000, - MSC_MYHPLTMAXRATE, - MSC_MYHPINRATE, - MSC_FRIENDHPLTMAXRATE, - MSC_FRIENDHPINRATE, - MSC_MYSTATUSON, - MSC_MYSTATUSOFF, - MSC_FRIENDSTATUSON, - MSC_FRIENDSTATUSOFF, - MSC_ATTACKPCGT, - MSC_ATTACKPCGE, - MSC_SLAVELT, - MSC_SLAVELE, - MSC_CLOSEDATTACKED, - MSC_LONGRANGEATTACKED, - MSC_AFTERSKILL, - MSC_SKILLUSED, - MSC_CASTTARGETED, - MSC_RUDEATTACKED, - MSC_MASTERHPLTMAXRATE, - MSC_MASTERATTACKED, - MSC_ALCHEMIST, - MSC_SPAWN, + MST_TARGET = 0, + MST_RANDOM, //Random Target! + MST_SELF, + MST_FRIEND, + MST_MASTER, + MST_AROUND5, + MST_AROUND6, + MST_AROUND7, + MST_AROUND8, + MST_AROUND1, + MST_AROUND2, + MST_AROUND3, + MST_AROUND4, + MST_AROUND = MST_AROUND4, + + MSC_ALWAYS = 0x0000, + MSC_MYHPLTMAXRATE, + MSC_MYHPINRATE, + MSC_FRIENDHPLTMAXRATE, + MSC_FRIENDHPINRATE, + MSC_MYSTATUSON, + MSC_MYSTATUSOFF, + MSC_FRIENDSTATUSON, + MSC_FRIENDSTATUSOFF, + MSC_ATTACKPCGT, + MSC_ATTACKPCGE, + MSC_SLAVELT, + MSC_SLAVELE, + MSC_CLOSEDATTACKED, + MSC_LONGRANGEATTACKED, + MSC_AFTERSKILL, + MSC_SKILLUSED, + MSC_CASTTARGETED, + MSC_RUDEATTACKED, + MSC_MASTERHPLTMAXRATE, + MSC_MASTERATTACKED, + MSC_ALCHEMIST, + MSC_SPAWN, }; // The data structures for storing delayed item drops struct item_drop { - struct item item_data; - struct item_drop *next; + struct item item_data; + struct item_drop* next; }; struct item_drop_list { - int m, x, y; // coordinates - int first_charid, second_charid, third_charid; // charid's of players with higher pickup priority - struct item_drop *item; // linked list of drops + int m, x, y; // coordinates + int first_charid, second_charid, third_charid; // charid's of players with higher pickup priority + struct item_drop* item; // linked list of drops }; -struct mob_db *mob_db(int class_); +struct mob_db* mob_db(int class_); int mobdb_searchname(const char *str); -int mobdb_searchname_array(struct mob_db **data, int size, const char *str); +int mobdb_searchname_array(struct mob_db** data, int size, const char *str); int mobdb_checkid(const int id); -struct view_data *mob_get_viewdata(int class_); +struct view_data* mob_get_viewdata(int class_); struct mob_data *mob_once_spawn_sub(struct block_list *bl, int m, - short x, short y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai); + short x, short y, const char *mobname, int class_, const char *event, unsigned int size, unsigned int ai); -int mob_once_spawn(struct map_session_data *sd, int m, short x, short y, - const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai); +int mob_once_spawn(struct map_session_data* sd, int m, short x, short y, + const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai); -int mob_once_spawn_area(struct map_session_data *sd, int m, - int x0, int y0, int x1, int y1, const char *mobname, int class_, int amount, const char *event, unsigned int size, unsigned int ai); +int mob_once_spawn_area(struct map_session_data* sd, int m, + int x0, int y0, int x1, int y1, const char* mobname, int class_, int amount, const char* event, unsigned int size, unsigned int ai); -bool mob_ksprotected(struct block_list *src, struct block_list *target); +bool mob_ksprotected (struct block_list *src, struct block_list *target); -int mob_spawn_guardian(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, int guardian, bool has_index); // Spawning Guardians [Valaris] -int mob_spawn_bg(const char *mapname, short x, short y, const char *mobname, int class_, const char *event, unsigned int bg_id); +int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, int guardian, bool has_index); // Spawning Guardians [Valaris] +int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int class_, const char* event, unsigned int bg_id); int mob_guardian_guildchange(struct mob_data *md); //Change Guardian's ownership. [Skotlex] int mob_randomwalk(struct mob_data *md,unsigned int tick); int mob_warpchase(struct mob_data *md, struct block_list *target); int mob_target(struct mob_data *md,struct block_list *bl,int dist); int mob_unlocktarget(struct mob_data *md, unsigned int tick); -struct mob_data *mob_spawn_dataset(struct spawn_data *data); +struct mob_data* mob_spawn_dataset(struct spawn_data *data); int mob_spawn(struct mob_data *md); int mob_delayspawn(int tid, unsigned int tick, int id, intptr_t data); int mob_setdelayspawn(struct mob_data *md); @@ -295,7 +292,7 @@ int do_final_mob(void); int mob_timer_delete(int tid, unsigned int tick, int id, intptr_t data); int mob_deleteslave(struct mob_data *md); -int mob_random_class(int *value, size_t count); +int mob_random_class (int *value, size_t count); int mob_get_random_id(int type, int flag, int lv); int mob_class_change(struct mob_data *md,int class_); int mob_warpslave(struct block_list *bl, int range); @@ -303,8 +300,8 @@ int mob_linksearch(struct block_list *bl,va_list ap); int mobskill_use(struct mob_data *md,unsigned int tick,int event); int mobskill_event(struct mob_data *md,struct block_list *src,unsigned int tick, 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 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 skill_id); int mob_countslave(struct block_list *bl); int mob_count_sub(struct block_list *bl, va_list ap); diff --git a/src/map/npc.c b/src/map/npc.c index 7cc8b27c9..cf267b73c 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -36,14 +36,14 @@ #include <errno.h> -struct npc_data *fake_nd; +struct npc_data* fake_nd; // linked list of npc source files struct npc_src_list { - struct npc_src_list *next; - char name[4]; // dynamic array, the structure is allocated with extra bytes (string length) + struct npc_src_list* next; + char name[4]; // dynamic array, the structure is allocated with extra bytes (string length) }; -static struct npc_src_list *npc_src_files = NULL; +static struct npc_src_list* npc_src_files = NULL; static int npc_id=START_NPC_NUM; static int npc_warp=0; @@ -55,30 +55,29 @@ static int npc_cache_mob=0; /// Returns a new npc id that isn't being used in id_db. /// Fatal error if nothing is available. -int npc_get_new_npc_id(void) -{ - if (npc_id >= START_NPC_NUM && !map_blid_exists(npc_id)) - return npc_id++;// available - else {// find next id - int base_id = npc_id; - while (base_id != ++npc_id) { - if (npc_id < START_NPC_NUM) - npc_id = START_NPC_NUM; - if (!map_blid_exists(npc_id)) - return npc_id++;// available - } - // full loop, nothing available - ShowFatalError("npc_get_new_npc_id: All ids are taken. Exiting..."); - exit(1); - } -} - -static DBMap *ev_db; // const char* event_name -> struct event_data* -static DBMap *npcname_db; // const char* npc_name -> struct npc_data* +int npc_get_new_npc_id(void) { + if( npc_id >= START_NPC_NUM && !map_blid_exists(npc_id) ) + return npc_id++;// available + else {// find next id + int base_id = npc_id; + while( base_id != ++npc_id ) { + if( npc_id < START_NPC_NUM ) + npc_id = START_NPC_NUM; + if( !map_blid_exists(npc_id) ) + return npc_id++;// available + } + // full loop, nothing available + ShowFatalError("npc_get_new_npc_id: All ids are taken. Exiting..."); + exit(1); + } +} + +static DBMap* ev_db; // const char* event_name -> struct event_data* +static DBMap* npcname_db; // const char* npc_name -> struct npc_data* struct event_data { - struct npc_data *nd; - int pos; + struct npc_data *nd; + int pos; }; static struct eri *timer_event_ers; //For the npc timer data. [Skotlex] @@ -88,8 +87,8 @@ static char *npc_last_path; static char *npc_last_ref; struct npc_path_data { - char *path; - unsigned short references; + char* path; + unsigned short references; }; struct npc_path_data *npc_last_npd; static DBMap *npc_path_db; @@ -97,45 +96,45 @@ static DBMap *npc_path_db; //For holding the view data of npc classes. [Skotlex] static struct view_data npc_viewdb[MAX_NPC_CLASS]; -static struct script_event_s { - //Holds pointers to the commonly executed scripts for speedup. [Skotlex] - struct event_data *event[UCHAR_MAX]; - const char *event_name[UCHAR_MAX]; - uint8 event_count; +static struct script_event_s +{ //Holds pointers to the commonly executed scripts for speedup. [Skotlex] + struct event_data *event[UCHAR_MAX]; + const char *event_name[UCHAR_MAX]; + uint8 event_count; } script_event[NPCE_MAX]; -struct view_data *npc_get_viewdata(int class_) { - //Returns the viewdata for normal npc classes. - if (class_ == INVISIBLE_CLASS) - return &npc_viewdb[0]; - if (npcdb_checkid(class_) || class_ == WARP_CLASS) - return &npc_viewdb[class_]; - return NULL; +struct view_data* npc_get_viewdata(int class_) +{ //Returns the viewdata for normal npc classes. + if( class_ == INVISIBLE_CLASS ) + return &npc_viewdb[0]; + if (npcdb_checkid(class_) || class_ == WARP_CLASS) + return &npc_viewdb[class_]; + return NULL; } int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd) { - char name[EVENT_NAME_LENGTH]; + char name[EVENT_NAME_LENGTH]; - if (nd->touching_id) - return 0; // Attached a player already. Can't trigger on anyone else. + if( nd->touching_id ) + return 0; // Attached a player already. Can't trigger on anyone else. - if (pc_ishiding(sd)) - return 1; // Can't trigger 'OnTouch_'. try 'OnTouch' later. + if( pc_ishiding(sd) ) + return 1; // Can't trigger 'OnTouch_'. try 'OnTouch' later. - snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_name); - return npc_event(sd,name,1); + snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_name); + return npc_event(sd,name,1); } int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd) { - char name[EVENT_NAME_LENGTH]; + char name[EVENT_NAME_LENGTH]; - if (sd->areanpc_id == nd->bl.id) - return 0; + if( sd->areanpc_id == nd->bl.id ) + return 0; - snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch2_name); - return npc_event(sd,name,2); + snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch2_name); + return npc_event(sd,name,2); } /*========================================== @@ -143,72 +142,75 @@ int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd) *------------------------------------------*/ int npc_enable_sub(struct block_list *bl, va_list ap) { - struct npc_data *nd; + struct npc_data *nd; - nullpo_ret(bl); - nullpo_ret(nd=va_arg(ap,struct npc_data *)); - if (bl->type == BL_PC) { - TBL_PC *sd = (TBL_PC *)bl; + nullpo_ret(bl); + nullpo_ret(nd=va_arg(ap,struct npc_data *)); + if(bl->type == BL_PC) + { + TBL_PC *sd = (TBL_PC*)bl; - if (nd->sc.option&OPTION_INVISIBLE) - return 1; + if (nd->sc.option&OPTION_INVISIBLE) + return 1; - if (npc_ontouch_event(sd,nd) > 0 && npc_ontouch2_event(sd,nd) > 0) { - // failed to run OnTouch event, so just click the npc - if (sd->npc_id != 0) - return 0; + if( npc_ontouch_event(sd,nd) > 0 && npc_ontouch2_event(sd,nd) > 0 ) + { // failed to run OnTouch event, so just click the npc + if (sd->npc_id != 0) + return 0; - pc_stop_walking(sd,1); - npc_click(sd,nd); - } - } - return 0; + pc_stop_walking(sd,1); + npc_click(sd,nd); + } + } + return 0; } /*========================================== * Disable / Enable NPC *------------------------------------------*/ -int npc_enable(const char *name, int flag) -{ - struct npc_data *nd = npc_name2id(name); - - if (nd==NULL) { - ShowError("npc_enable: Attempted to %s a non-existing NPC '%s' (flag=%d).\n", (flag&3) ? "show" : "hide", name, flag); - return 0; - } - - if (flag&1) { - nd->sc.option&=~OPTION_INVISIBLE; - clif_spawn(&nd->bl); - } else if (flag&2) - nd->sc.option&=~OPTION_HIDE; - else if (flag&4) - nd->sc.option|= OPTION_HIDE; - else { //Can't change the view_data to invisible class because the view_data for all npcs is shared! [Skotlex] - nd->sc.option|= OPTION_INVISIBLE; - clif_clearunit_area(&nd->bl,CLR_OUTSIGHT); // Hack to trick maya purple card [Xazax] - } - - if (nd->class_ == WARP_CLASS || nd->class_ == FLAG_CLASS) { - //Client won't display option changes for these classes [Toms] - if (nd->sc.option&(OPTION_HIDE|OPTION_INVISIBLE)) - clif_clearunit_area(&nd->bl, CLR_OUTSIGHT); - else - clif_spawn(&nd->bl); - } else - clif_changeoption(&nd->bl); - - if (flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0)) //check if player standing on a OnTouchArea - map_foreachinarea(npc_enable_sub, nd->bl.m, nd->bl.x-nd->u.scr.xs, nd->bl.y-nd->u.scr.ys, nd->bl.x+nd->u.scr.xs, nd->bl.y+nd->u.scr.ys, BL_PC, nd); - - return 0; +int npc_enable(const char* name, int flag) +{ + struct npc_data* nd = npc_name2id(name); + + if (nd==NULL) + { + ShowError("npc_enable: Attempted to %s a non-existing NPC '%s' (flag=%d).\n", (flag&3) ? "show" : "hide", name, flag); + return 0; + } + + if (flag&1) { + nd->sc.option&=~OPTION_INVISIBLE; + clif_spawn(&nd->bl); + } else if (flag&2) + nd->sc.option&=~OPTION_HIDE; + else if (flag&4) + nd->sc.option|= OPTION_HIDE; + else { //Can't change the view_data to invisible class because the view_data for all npcs is shared! [Skotlex] + nd->sc.option|= OPTION_INVISIBLE; + clif_clearunit_area(&nd->bl,CLR_OUTSIGHT); // Hack to trick maya purple card [Xazax] + } + + if (nd->class_ == WARP_CLASS || nd->class_ == FLAG_CLASS) + { //Client won't display option changes for these classes [Toms] + if (nd->sc.option&(OPTION_HIDE|OPTION_INVISIBLE)) + clif_clearunit_area(&nd->bl, CLR_OUTSIGHT); + else + clif_spawn(&nd->bl); + } else + clif_changeoption(&nd->bl); + + if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) ) //check if player standing on a OnTouchArea + map_foreachinarea( npc_enable_sub, nd->bl.m, nd->bl.x-nd->u.scr.xs, nd->bl.y-nd->u.scr.ys, nd->bl.x+nd->u.scr.xs, nd->bl.y+nd->u.scr.ys, BL_PC, nd ); + + return 0; } /*========================================== * NPC lookup (get npc_data through npcname) *------------------------------------------*/ -struct npc_data *npc_name2id(const char *name) { - return (struct npc_data *) strdb_get(npcname_db, name); +struct npc_data* npc_name2id(const char* name) +{ + return (struct npc_data *) strdb_get(npcname_db, name); } /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] @@ -217,62 +219,61 @@ struct npc_data *npc_name2id(const char *name) { /** * Timer to check for idle time and timeout the dialog if necessary **/ -int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data) -{ - struct map_session_data *sd = NULL; - if ((sd = map_id2sd(id)) == NULL || !sd->npc_id) { - if (sd) sd->npc_idle_timer = INVALID_TIMER; - return 0;//Not logged in anymore OR no longer attached to a npc - } - if (DIFF_TICK(tick,sd->npc_idle_tick) > (SECURE_NPCTIMEOUT*1000)) { - /** - * If we still have the NPC script attached, tell it to stop. - **/ - if (sd->st) - sd->st->state = END; - /** - * This guy's been idle for longer than allowed, close him. - **/ - clif_scriptclose(sd,sd->npc_id); - sd->npc_idle_timer = INVALID_TIMER; - } else //Create a new instance of ourselves to continue - sd->npc_idle_timer = add_timer(gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc_rr_secure_timeout_timer,sd->bl.id,0); - return 0; +int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data) { + struct map_session_data* sd = NULL; + if( (sd = map_id2sd(id)) == NULL || !sd->npc_id ) { + if( sd ) sd->npc_idle_timer = INVALID_TIMER; + return 0;//Not logged in anymore OR no longer attached to a npc + } + if( DIFF_TICK(tick,sd->npc_idle_tick) > (SECURE_NPCTIMEOUT*1000) ) { + /** + * If we still have the NPC script attached, tell it to stop. + **/ + if( sd->st ) + sd->st->state = END; + /** + * This guy's been idle for longer than allowed, close him. + **/ + clif_scriptclose(sd,sd->npc_id); + sd->npc_idle_timer = INVALID_TIMER; + } else //Create a new instance of ourselves to continue + sd->npc_idle_timer = add_timer(gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc_rr_secure_timeout_timer,sd->bl.id,0); + return 0; } #endif /*========================================== * Dequeue event and add timer for execution (100ms) *------------------------------------------*/ -int npc_event_dequeue(struct map_session_data *sd) -{ - nullpo_ret(sd); - - if (sd->npc_id) { - //Current script is aborted. - if (sd->state.using_fake_npc) { - clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); - sd->state.using_fake_npc = 0; - } - if (sd->st) { - script_free_state(sd->st); - sd->st = NULL; - } - sd->npc_id = 0; - } - - if (!sd->eventqueue[0][0]) - return 0; //Nothing to dequeue - - if (!pc_addeventtimer(sd,100,sd->eventqueue[0])) { - //Failed to dequeue, couldn't set a timer. - ShowWarning("npc_event_dequeue: event timer is full !\n"); - return 0; - } - //Event dequeued successfully, shift other elements. - memmove(sd->eventqueue[0], sd->eventqueue[1], (MAX_EVENTQUEUE-1)*sizeof(sd->eventqueue[0])); - sd->eventqueue[MAX_EVENTQUEUE-1][0]=0; - return 1; +int npc_event_dequeue(struct map_session_data* sd) +{ + nullpo_ret(sd); + + if(sd->npc_id) + { //Current script is aborted. + if(sd->state.using_fake_npc){ + clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); + sd->state.using_fake_npc = 0; + } + if (sd->st) { + script_free_state(sd->st); + sd->st = NULL; + } + sd->npc_id = 0; + } + + if (!sd->eventqueue[0][0]) + return 0; //Nothing to dequeue + + if (!pc_addeventtimer(sd,100,sd->eventqueue[0])) + { //Failed to dequeue, couldn't set a timer. + ShowWarning("npc_event_dequeue: event timer is full !\n"); + return 0; + } + //Event dequeued successfully, shift other elements. + memmove(sd->eventqueue[0], sd->eventqueue[1], (MAX_EVENTQUEUE-1)*sizeof(sd->eventqueue[0])); + sd->eventqueue[MAX_EVENTQUEUE-1][0]=0; + return 1; } /*========================================== @@ -281,23 +282,23 @@ int npc_event_dequeue(struct map_session_data *sd) *------------------------------------------*/ static int npc_event_export(struct npc_data *nd, int 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')) { - struct event_data *ev; - char buf[EVENT_NAME_LENGTH]; - snprintf(buf, ARRAYLENGTH(buf), "%s::%s", nd->exname, lname); - // generate the data and insert it - CREATE(ev, struct event_data, 1); - ev->nd = nd; - ev->pos = pos; - if (strdb_put(ev_db, buf, ev)) // There was already another event of the same name? - return 1; - } - return 0; + 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')) { + struct event_data *ev; + char buf[EVENT_NAME_LENGTH]; + snprintf(buf, ARRAYLENGTH(buf), "%s::%s", nd->exname, lname); + // generate the data and insert it + CREATE(ev, struct event_data, 1); + ev->nd = nd; + ev->pos = pos; + if (strdb_put(ev_db, buf, ev)) // There was already another event of the same name? + return 1; + } + return 0; } -int npc_event_sub(struct map_session_data *sd, struct event_data *ev, const char *eventname); //[Lance] +int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char* eventname); //[Lance] /** * Exec name (NPC events) on player or global @@ -306,27 +307,28 @@ int npc_event_sub(struct map_session_data *sd, struct event_data *ev, const char */ int npc_event_doall_sub(DBKey key, DBData *data, va_list ap) { - const char *p = key.str; - struct event_data *ev; - int *c; - const char *name; - int rid; - - nullpo_ret(ev = db_data2ptr(data)); - nullpo_ret(c = va_arg(ap, int *)); - nullpo_ret(name = va_arg(ap, const char *)); - rid = va_arg(ap, int); - - p = strchr(p, ':'); // match only the event name - if (p && strcmpi(name, p) == 0 /* && !ev->nd->src_id */) { // Do not run on duplicates. [Paradox924X] - if (rid) // a player may only have 1 script running at the same time - npc_event_sub(map_id2sd(rid),ev,key.str); - else - run_script(ev->nd->u.scr.script,ev->pos,rid,ev->nd->bl.id); - (*c)++; - } + const char* p = key.str; + struct event_data* ev; + int* c; + const char* name; + int rid; - return 0; + nullpo_ret(ev = db_data2ptr(data)); + nullpo_ret(c = va_arg(ap, int *)); + nullpo_ret(name = va_arg(ap, const char *)); + rid = va_arg(ap, int); + + p = strchr(p, ':'); // match only the event name + if( p && strcmpi(name, p) == 0 /* && !ev->nd->src_id */ ) // Do not run on duplicates. [Paradox924X] + { + if(rid) // a player may only have 1 script running at the same time + npc_event_sub(map_id2sd(rid),ev,key.str); + else + run_script(ev->nd->u.scr.script,ev->pos,rid,ev->nd->bl.id); + (*c)++; + } + + return 0; } /** @@ -334,50 +336,51 @@ int npc_event_doall_sub(DBKey key, DBData *data, va_list ap) */ static int npc_event_do_sub(DBKey key, DBData *data, va_list ap) { - const char *p = key.str; - struct event_data *ev; - int *c; - const char *name; + const char* p = key.str; + struct event_data* ev; + int* c; + const char* name; - nullpo_ret(ev = db_data2ptr(data)); - nullpo_ret(c = va_arg(ap, int *)); - nullpo_ret(name = va_arg(ap, const char *)); + nullpo_ret(ev = db_data2ptr(data)); + nullpo_ret(c = va_arg(ap, int *)); + nullpo_ret(name = va_arg(ap, const char *)); - if (p && strcmpi(name, p) == 0) { - run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id); - (*c)++; - } + if( p && strcmpi(name, p) == 0 ) + { + run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id); + (*c)++; + } - return 0; + return 0; } // runs the specified event (supports both single-npc and global events) -int npc_event_do(const char *name) +int npc_event_do(const char* name) { - int c = 0; + int c = 0; - if (name[0] == ':' && name[1] == ':') - ev_db->foreach(ev_db,npc_event_doall_sub,&c,name,0); - else - ev_db->foreach(ev_db,npc_event_do_sub,&c,name); + if( name[0] == ':' && name[1] == ':' ) + ev_db->foreach(ev_db,npc_event_doall_sub,&c,name,0); + else + ev_db->foreach(ev_db,npc_event_do_sub,&c,name); - return c; + return c; } // runs the specified event (global only) -int npc_event_doall(const char *name) +int npc_event_doall(const char* name) { - return npc_event_doall_id(name, 0); + return npc_event_doall_id(name, 0); } // runs the specified event, with a RID attached (global only) -int npc_event_doall_id(const char *name, int rid) +int npc_event_doall_id(const char* name, int rid) { - int c = 0; - char buf[64]; - safesnprintf(buf, sizeof(buf), "::%s", name); - ev_db->foreach(ev_db,npc_event_doall_sub,&c,buf,rid); - return c; + int c = 0; + char buf[64]; + safesnprintf(buf, sizeof(buf), "::%s", name); + ev_db->foreach(ev_db,npc_event_doall_sub,&c,buf,rid); + return c; } /*========================================== @@ -386,67 +389,51 @@ int npc_event_doall_id(const char *name, int rid) *------------------------------------------*/ int npc_event_do_clock(int tid, unsigned int tick, int id, intptr_t data) { - static struct tm ev_tm_b; // tracks previous execution time - time_t timer; - struct tm *t; - char buf[64]; - int c = 0; + static struct tm ev_tm_b; // tracks previous execution time + time_t timer; + struct tm* t; + char buf[64]; + int c = 0; - timer = time(NULL); - t = localtime(&timer); + timer = time(NULL); + t = localtime(&timer); - if (t->tm_min != ev_tm_b.tm_min) { - char *day; + if (t->tm_min != ev_tm_b.tm_min ) { + char* day; - switch (t->tm_wday) { - case 0: - day = "Sun"; - break; - case 1: - day = "Mon"; - break; - case 2: - day = "Tue"; - break; - case 3: - day = "Wed"; - break; - case 4: - day = "Thu"; - break; - case 5: - day = "Fri"; - break; - case 6: - day = "Sat"; - break; - default: - day = ""; - break; - } + switch (t->tm_wday) { + case 0: day = "Sun"; break; + case 1: day = "Mon"; break; + case 2: day = "Tue"; break; + case 3: day = "Wed"; break; + case 4: day = "Thu"; break; + case 5: day = "Fri"; break; + case 6: day = "Sat"; break; + default:day = ""; break; + } - sprintf(buf,"OnMinute%02d",t->tm_min); - c += npc_event_doall(buf); + sprintf(buf,"OnMinute%02d",t->tm_min); + c += npc_event_doall(buf); - sprintf(buf,"OnClock%02d%02d",t->tm_hour,t->tm_min); - c += npc_event_doall(buf); + sprintf(buf,"OnClock%02d%02d",t->tm_hour,t->tm_min); + c += npc_event_doall(buf); - sprintf(buf,"On%s%02d%02d",day,t->tm_hour,t->tm_min); - c += npc_event_doall(buf); - } + sprintf(buf,"On%s%02d%02d",day,t->tm_hour,t->tm_min); + c += npc_event_doall(buf); + } - if (t->tm_hour != ev_tm_b.tm_hour) { - sprintf(buf,"OnHour%02d",t->tm_hour); - c += npc_event_doall(buf); - } + if (t->tm_hour != ev_tm_b.tm_hour) { + sprintf(buf,"OnHour%02d",t->tm_hour); + c += npc_event_doall(buf); + } - if (t->tm_mday != ev_tm_b.tm_mday) { - sprintf(buf,"OnDay%02d%02d",t->tm_mon+1,t->tm_mday); - c += npc_event_doall(buf); - } + if (t->tm_mday != ev_tm_b.tm_mday) { + sprintf(buf,"OnDay%02d%02d",t->tm_mon+1,t->tm_mday); + c += npc_event_doall(buf); + } - memcpy(&ev_tm_b,t,sizeof(ev_tm_b)); - return c; + memcpy(&ev_tm_b,t,sizeof(ev_tm_b)); + return c; } /*========================================== @@ -454,9 +441,9 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ void npc_event_do_oninit(void) { - ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", npc_event_doall("OnInit")); + ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs."CL_CLL"\n", npc_event_doall("OnInit")); - add_timer_interval(gettick()+100,npc_event_do_clock,0,0,1000); + add_timer_interval(gettick()+100,npc_event_do_clock,0,0,1000); } /*========================================== @@ -465,35 +452,35 @@ void npc_event_do_oninit(void) *------------------------------------------*/ int npc_timerevent_export(struct npc_data *nd, int i) { - int t = 0, k = 0; - char *lname = nd->u.scr.label_list[i].name; - int pos = nd->u.scr.label_list[i].pos; - if (sscanf(lname, "OnTimer%d%n", &t, &k) == 1 && lname[k] == '\0') { - // Timer event - 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 *)aMalloc(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++) { - if (te[j].timer > t) { - memmove(te+j+1, te+j, sizeof(struct npc_timerevent_list)*(k-j)); - break; - } - } - te[j].timer = t; - te[j].pos = pos; - nd->u.scr.timer_event = te; - nd->u.scr.timeramount++; - } - return 0; + int t = 0, k = 0; + char *lname = nd->u.scr.label_list[i].name; + int pos = nd->u.scr.label_list[i].pos; + if (sscanf(lname, "OnTimer%d%n", &t, &k) == 1 && lname[k] == '\0') { + // Timer event + 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 *)aMalloc(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++) { + if (te[j].timer > t) { + memmove(te+j+1, te+j, sizeof(struct npc_timerevent_list)*(k-j)); + break; + } + } + te[j].timer = t; + te[j].pos = pos; + nd->u.scr.timer_event = te; + nd->u.scr.timeramount++; + } + return 0; } struct timer_event_data { - int rid; //Attached player for this timer. - int next; //timer index (starts with 0, then goes up to nd->u.scr.timeramount) - int time; //holds total time elapsed for the script from when timer was started to when last time the event triggered. + int rid; //Attached player for this timer. + int next; //timer index (starts with 0, then goes up to nd->u.scr.timeramount) + int time; //holds total time elapsed for the script from when timer was started to when last time the event triggered. }; /*========================================== @@ -501,306 +488,331 @@ struct timer_event_data { *------------------------------------------*/ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) { - int next; - int old_rid, old_timer; - unsigned int old_tick; - struct npc_data *nd=(struct npc_data *)map_id2bl(id); - struct npc_timerevent_list *te; - struct timer_event_data *ted = (struct timer_event_data *)data; - struct map_session_data *sd=NULL; - - if (nd == NULL) { - ShowError("npc_timerevent: NPC not found??\n"); - return 0; - } - - if (ted->rid && !(sd = map_id2sd(ted->rid))) { - ShowError("npc_timerevent: Attached player not found.\n"); - ers_free(timer_event_ers, ted); - return 0; - } - - // These stuffs might need to be restored. - old_rid = nd->u.scr.rid; - old_tick = nd->u.scr.timertick; - old_timer = nd->u.scr.timer; - - // Set the values of the timer - nd->u.scr.rid = sd?sd->bl.id:0; //attached rid - nd->u.scr.timertick = tick; //current time tick - nd->u.scr.timer = ted->time; //total time from beginning to now - - // Locate the event - te = nd->u.scr.timer_event + ted->next; - - // Arrange for the next event - ted->next++; - if (nd->u.scr.timeramount > ted->next) { - next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer; - ted->time += next; - if (sd) - sd->npc_timer_id = add_timer(tick+next,npc_timerevent,id,(intptr_t)ted); - else - nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,id,(intptr_t)ted); - } else { - if (sd) - sd->npc_timer_id = INVALID_TIMER; - else - nd->u.scr.timerid = INVALID_TIMER; - - ers_free(timer_event_ers, ted); - } - - // Run the script - run_script(nd->u.scr.script,te->pos,nd->u.scr.rid,nd->bl.id); - - nd->u.scr.rid = old_rid; // Attached-rid should be restored anyway. - if (sd) { - // Restore previous data, only if this timer is a player-attached one. - nd->u.scr.timer = old_timer; - nd->u.scr.timertick = old_tick; - } - - return 0; + int next; + int old_rid, old_timer; + unsigned int old_tick; + struct npc_data* nd=(struct npc_data *)map_id2bl(id); + struct npc_timerevent_list *te; + struct timer_event_data *ted = (struct timer_event_data*)data; + struct map_session_data *sd=NULL; + + if( nd == NULL ) + { + ShowError("npc_timerevent: NPC not found??\n"); + return 0; + } + + if( ted->rid && !(sd = map_id2sd(ted->rid)) ) + { + ShowError("npc_timerevent: Attached player not found.\n"); + ers_free(timer_event_ers, ted); + return 0; + } + + // These stuffs might need to be restored. + old_rid = nd->u.scr.rid; + old_tick = nd->u.scr.timertick; + old_timer = nd->u.scr.timer; + + // Set the values of the timer + nd->u.scr.rid = sd?sd->bl.id:0; //attached rid + nd->u.scr.timertick = tick; //current time tick + nd->u.scr.timer = ted->time; //total time from beginning to now + + // Locate the event + te = nd->u.scr.timer_event + ted->next; + + // Arrange for the next event + ted->next++; + if( nd->u.scr.timeramount > ted->next ) + { + next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer; + ted->time += next; + if( sd ) + sd->npc_timer_id = add_timer(tick+next,npc_timerevent,id,(intptr_t)ted); + else + nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,id,(intptr_t)ted); + } + else + { + if( sd ) + sd->npc_timer_id = INVALID_TIMER; + else + nd->u.scr.timerid = INVALID_TIMER; + + ers_free(timer_event_ers, ted); + } + + // Run the script + run_script(nd->u.scr.script,te->pos,nd->u.scr.rid,nd->bl.id); + + nd->u.scr.rid = old_rid; // Attached-rid should be restored anyway. + if( sd ) + { // Restore previous data, only if this timer is a player-attached one. + nd->u.scr.timer = old_timer; + nd->u.scr.timertick = old_tick; + } + + return 0; } /*========================================== * Start/Resume NPC timer *------------------------------------------*/ -int npc_timerevent_start(struct npc_data *nd, int rid) -{ - int j, next; - unsigned int tick = gettick(); - struct map_session_data *sd = NULL; //Player to whom script is attached. - struct timer_event_data *ted; - - nullpo_ret(nd); - - // Check if there is an OnTimer Event - ARR_FIND(0, nd->u.scr.timeramount, j, nd->u.scr.timer_event[j].timer > nd->u.scr.timer); - - if (nd->u.scr.rid > 0 && !(sd = map_id2sd(nd->u.scr.rid))) { - // Failed to attach timer to this player. - ShowError("npc_timerevent_start: Attached player not found!\n"); - return 1; - } - - // Check if timer is already started. - if (sd) { - if (sd->npc_timer_id != INVALID_TIMER) - return 0; - } else if (nd->u.scr.timerid != INVALID_TIMER || nd->u.scr.timertick) - return 0; - - if (j < nd->u.scr.timeramount) { - // Arrange for the next event - ted = ers_alloc(timer_event_ers, struct timer_event_data); - ted->next = j; // Set event index - ted->time = nd->u.scr.timer_event[j].timer; - next = nd->u.scr.timer_event[j].timer - nd->u.scr.timer; - if (sd) { - ted->rid = sd->bl.id; // Attach only the player if attachplayerrid was used. - sd->npc_timer_id = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr_t)ted); - } else { - ted->rid = 0; - nd->u.scr.timertick = tick; // Set when timer is started - nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr_t)ted); - } - } else if (!sd) { - nd->u.scr.timertick = tick; - } - - return 0; +int npc_timerevent_start(struct npc_data* nd, int rid) +{ + int j, next; + unsigned int tick = gettick(); + struct map_session_data *sd = NULL; //Player to whom script is attached. + struct timer_event_data *ted; + + nullpo_ret(nd); + + // Check if there is an OnTimer Event + ARR_FIND( 0, nd->u.scr.timeramount, j, nd->u.scr.timer_event[j].timer > nd->u.scr.timer ); + + if( nd->u.scr.rid > 0 && !(sd = map_id2sd(nd->u.scr.rid)) ) + { // Failed to attach timer to this player. + ShowError("npc_timerevent_start: Attached player not found!\n"); + return 1; + } + + // Check if timer is already started. + if( sd ) + { + if( sd->npc_timer_id != INVALID_TIMER ) + return 0; + } + else if( nd->u.scr.timerid != INVALID_TIMER || nd->u.scr.timertick ) + return 0; + + if (j < nd->u.scr.timeramount) + { + // Arrange for the next event + ted = ers_alloc(timer_event_ers, struct timer_event_data); + ted->next = j; // Set event index + ted->time = nd->u.scr.timer_event[j].timer; + next = nd->u.scr.timer_event[j].timer - nd->u.scr.timer; + if( sd ) + { + ted->rid = sd->bl.id; // Attach only the player if attachplayerrid was used. + sd->npc_timer_id = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr_t)ted); + } + else + { + ted->rid = 0; + nd->u.scr.timertick = tick; // Set when timer is started + nd->u.scr.timerid = add_timer(tick+next,npc_timerevent,nd->bl.id,(intptr_t)ted); + } + } + else if (!sd) + { + nd->u.scr.timertick = tick; + } + + return 0; } /*========================================== * Stop NPC timer *------------------------------------------*/ -int npc_timerevent_stop(struct npc_data *nd) -{ - struct map_session_data *sd = NULL; - const struct TimerData *td = NULL; - int *tid; - - nullpo_ret(nd); - - if (nd->u.scr.rid && !(sd = map_id2sd(nd->u.scr.rid))) { - ShowError("npc_timerevent_stop: Attached player not found!\n"); - return 1; - } - - tid = sd?&sd->npc_timer_id:&nd->u.scr.timerid; - if (*tid == INVALID_TIMER && (sd || !nd->u.scr.timertick)) // Nothing to stop - return 0; - - // Delete timer - if (*tid != INVALID_TIMER) { - td = get_timer(*tid); - if (td && td->data) - ers_free(timer_event_ers, (void *)td->data); - delete_timer(*tid,npc_timerevent); - *tid = INVALID_TIMER; - } - - if (!sd && nd->u.scr.timertick) { - nd->u.scr.timer += DIFF_TICK(gettick(),nd->u.scr.timertick); // Set 'timer' to the time that has passed since the beginning of the timers - nd->u.scr.timertick = 0; // Set 'tick' to zero so that we know it's off. - } - - return 0; +int npc_timerevent_stop(struct npc_data* nd) +{ + struct map_session_data *sd = NULL; + const struct TimerData *td = NULL; + int *tid; + + nullpo_ret(nd); + + if( nd->u.scr.rid && !(sd = map_id2sd(nd->u.scr.rid)) ) + { + ShowError("npc_timerevent_stop: Attached player not found!\n"); + return 1; + } + + tid = sd?&sd->npc_timer_id:&nd->u.scr.timerid; + if( *tid == INVALID_TIMER && (sd || !nd->u.scr.timertick) ) // Nothing to stop + return 0; + + // Delete timer + if ( *tid != INVALID_TIMER ) + { + td = get_timer(*tid); + if( td && td->data ) + ers_free(timer_event_ers, (void*)td->data); + delete_timer(*tid,npc_timerevent); + *tid = INVALID_TIMER; + } + + if( !sd && nd->u.scr.timertick ) + { + nd->u.scr.timer += DIFF_TICK(gettick(),nd->u.scr.timertick); // Set 'timer' to the time that has passed since the beginning of the timers + nd->u.scr.timertick = 0; // Set 'tick' to zero so that we know it's off. + } + + return 0; } /*========================================== * Aborts a running NPC timer that is attached to a player. *------------------------------------------*/ -void npc_timerevent_quit(struct map_session_data *sd) -{ - const struct TimerData *td; - struct npc_data *nd; - struct timer_event_data *ted; - - // Check timer existance - if (sd->npc_timer_id == INVALID_TIMER) - return; - if (!(td = get_timer(sd->npc_timer_id))) { - sd->npc_timer_id = INVALID_TIMER; - return; - } - - // Delete timer - nd = (struct npc_data *)map_id2bl(td->id); - ted = (struct timer_event_data *)td->data; - delete_timer(sd->npc_timer_id, npc_timerevent); - sd->npc_timer_id = INVALID_TIMER; - - // Execute OnTimerQuit - if (nd && nd->bl.type == BL_NPC) { - char buf[EVENT_NAME_LENGTH]; - struct event_data *ev; - - snprintf(buf, ARRAYLENGTH(buf), "%s::OnTimerQuit", nd->exname); - ev = (struct event_data *)strdb_get(ev_db, buf); - if (ev && ev->nd != nd) { - ShowWarning("npc_timerevent_quit: Unable to execute \"OnTimerQuit\", two NPCs have the same event name [%s]!\n",buf); - ev = NULL; - } - if (ev) { - int old_rid,old_timer; - unsigned int old_tick; - - //Set timer related info. - old_rid = (nd->u.scr.rid == sd->bl.id ? 0 : nd->u.scr.rid); // Detach rid if the last attached player logged off. - old_tick = nd->u.scr.timertick; - old_timer = nd->u.scr.timer; - - nd->u.scr.rid = sd->bl.id; - nd->u.scr.timertick = gettick(); - nd->u.scr.timer = ted->time; - - //Execute label - run_script(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id); - - //Restore previous data. - nd->u.scr.rid = old_rid; - nd->u.scr.timer = old_timer; - nd->u.scr.timertick = old_tick; - } - } - ers_free(timer_event_ers, ted); +void npc_timerevent_quit(struct map_session_data* sd) +{ + const struct TimerData *td; + struct npc_data* nd; + struct timer_event_data *ted; + + // Check timer existance + if( sd->npc_timer_id == INVALID_TIMER ) + return; + if( !(td = get_timer(sd->npc_timer_id)) ) + { + sd->npc_timer_id = INVALID_TIMER; + return; + } + + // Delete timer + nd = (struct npc_data *)map_id2bl(td->id); + ted = (struct timer_event_data*)td->data; + delete_timer(sd->npc_timer_id, npc_timerevent); + sd->npc_timer_id = INVALID_TIMER; + + // Execute OnTimerQuit + if( nd && nd->bl.type == BL_NPC ) + { + char buf[EVENT_NAME_LENGTH]; + struct event_data *ev; + + snprintf(buf, ARRAYLENGTH(buf), "%s::OnTimerQuit", nd->exname); + ev = (struct event_data*)strdb_get(ev_db, buf); + if( ev && ev->nd != nd ) + { + ShowWarning("npc_timerevent_quit: Unable to execute \"OnTimerQuit\", two NPCs have the same event name [%s]!\n",buf); + ev = NULL; + } + if( ev ) + { + int old_rid,old_timer; + unsigned int old_tick; + + //Set timer related info. + old_rid = (nd->u.scr.rid == sd->bl.id ? 0 : nd->u.scr.rid); // Detach rid if the last attached player logged off. + old_tick = nd->u.scr.timertick; + old_timer = nd->u.scr.timer; + + nd->u.scr.rid = sd->bl.id; + nd->u.scr.timertick = gettick(); + nd->u.scr.timer = ted->time; + + //Execute label + run_script(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id); + + //Restore previous data. + nd->u.scr.rid = old_rid; + nd->u.scr.timer = old_timer; + nd->u.scr.timertick = old_tick; + } + } + ers_free(timer_event_ers, ted); } /*========================================== * Get the tick value of an NPC timer * If it's stopped, return stopped time *------------------------------------------*/ -int npc_gettimerevent_tick(struct npc_data *nd) +int npc_gettimerevent_tick(struct npc_data* nd) { - int tick; - nullpo_ret(nd); + int tick; + nullpo_ret(nd); - // TODO: Get player attached timer's tick. Now we can just get it by using 'getnpctimer' inside OnTimer event. + // TODO: Get player attached timer's tick. Now we can just get it by using 'getnpctimer' inside OnTimer event. - tick = nd->u.scr.timer; // The last time it's active(start, stop or event trigger) - if (nd->u.scr.timertick) // It's a running timer - tick += DIFF_TICK(gettick(), nd->u.scr.timertick); + tick = nd->u.scr.timer; // The last time it's active(start, stop or event trigger) + if( nd->u.scr.timertick ) // It's a running timer + tick += DIFF_TICK(gettick(), nd->u.scr.timertick); - return tick; + return tick; } /*========================================== * Set tick for running and stopped timer *------------------------------------------*/ -int npc_settimerevent_tick(struct npc_data *nd, int newtimer) +int npc_settimerevent_tick(struct npc_data* nd, int newtimer) { - bool flag; - int old_rid; - //struct map_session_data *sd = NULL; + bool flag; + int old_rid; + //struct map_session_data *sd = NULL; - nullpo_ret(nd); + nullpo_ret(nd); - // TODO: Set player attached timer's tick. + // TODO: Set player attached timer's tick. - old_rid = nd->u.scr.rid; - nd->u.scr.rid = 0; + old_rid = nd->u.scr.rid; + nd->u.scr.rid = 0; - // Check if timer is started - flag = (nd->u.scr.timerid != INVALID_TIMER); + // Check if timer is started + flag = (nd->u.scr.timerid != INVALID_TIMER); - if (flag) npc_timerevent_stop(nd); - nd->u.scr.timer = newtimer; - if (flag) npc_timerevent_start(nd, -1); + if( flag ) npc_timerevent_stop(nd); + nd->u.scr.timer = newtimer; + if( flag ) npc_timerevent_start(nd, -1); - nd->u.scr.rid = old_rid; - return 0; + nd->u.scr.rid = old_rid; + return 0; } -int npc_event_sub(struct map_session_data *sd, struct event_data *ev, const char *eventname) +int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char* eventname) { - if (sd->npc_id != 0) { - //Enqueue the event trigger. - int i; - ARR_FIND(0, MAX_EVENTQUEUE, i, sd->eventqueue[i][0] == '\0'); - if (i < MAX_EVENTQUEUE) { - safestrncpy(sd->eventqueue[i],eventname,50); //Event enqueued. - return 0; - } + if ( sd->npc_id != 0 ) + { + //Enqueue the event trigger. + int i; + ARR_FIND( 0, MAX_EVENTQUEUE, i, sd->eventqueue[i][0] == '\0' ); + if( i < MAX_EVENTQUEUE ) + { + safestrncpy(sd->eventqueue[i],eventname,50); //Event enqueued. + return 0; + } - ShowWarning("npc_event: player's event queue is full, can't add event '%s' !\n", eventname); - return 1; - } - if (ev->nd->sc.option&OPTION_INVISIBLE) { - //Disabled npc, shouldn't trigger event. - npc_event_dequeue(sd); - return 2; - } - run_script(ev->nd->u.scr.script,ev->pos,sd->bl.id,ev->nd->bl.id); - return 0; + ShowWarning("npc_event: player's event queue is full, can't add event '%s' !\n", eventname); + return 1; + } + if( ev->nd->sc.option&OPTION_INVISIBLE ) + { + //Disabled npc, shouldn't trigger event. + npc_event_dequeue(sd); + return 2; + } + run_script(ev->nd->u.scr.script,ev->pos,sd->bl.id,ev->nd->bl.id); + return 0; } /*========================================== * NPC processing event type *------------------------------------------*/ -int npc_event(struct map_session_data *sd, const char *eventname, int ontouch) +int npc_event(struct map_session_data* sd, const char* eventname, int ontouch) { - struct event_data *ev = (struct event_data *)strdb_get(ev_db, eventname); - struct npc_data *nd; + struct event_data* ev = (struct event_data*)strdb_get(ev_db, eventname); + struct npc_data *nd; - nullpo_ret(sd); + nullpo_ret(sd); - if (ev == NULL || (nd = ev->nd) == NULL) { - if (!ontouch) - ShowError("npc_event: event not found [%s]\n", eventname); - return ontouch; - } + if( ev == NULL || (nd = ev->nd) == NULL ) + { + if( !ontouch ) + ShowError("npc_event: event not found [%s]\n", eventname); + return ontouch; + } - switch (ontouch) { - case 1: - nd->touching_id = sd->bl.id; - sd->touching_id = nd->bl.id; - break; - case 2: - sd->areanpc_id = nd->bl.id; - break; - } + switch(ontouch) + { + case 1: + nd->touching_id = sd->bl.id; + sd->touching_id = nd->bl.id; + break; + case 2: + sd->areanpc_id = nd->bl.id; + break; + } - return npc_event_sub(sd,ev,eventname); + return npc_event_sub(sd,ev,eventname); } /*========================================== @@ -808,175 +820,181 @@ int npc_event(struct map_session_data *sd, const char *eventname, int ontouch) *------------------------------------------*/ int npc_touch_areanpc_sub(struct block_list *bl, va_list ap) { - struct map_session_data *sd; - int pc_id; - char *name; + struct map_session_data *sd; + int pc_id; + char *name; - nullpo_ret(bl); - nullpo_ret((sd = map_id2sd(bl->id))); + nullpo_ret(bl); + nullpo_ret((sd = map_id2sd(bl->id))); - pc_id = va_arg(ap,int); - name = va_arg(ap,char *); + pc_id = va_arg(ap,int); + name = va_arg(ap,char*); - if (pc_ishiding(sd)) - return 0; - if (pc_id == sd->bl.id) - return 0; + if( pc_ishiding(sd) ) + return 0; + if( pc_id == sd->bl.id ) + return 0; - npc_event(sd,name,1); + npc_event(sd,name,1); - return 1; + return 1; } /*========================================== * Chk if sd is still touching his assigned npc. * If not, it unsets it and searches for another player in range. *------------------------------------------*/ -int npc_touchnext_areanpc(struct map_session_data *sd, bool leavemap) +int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap) { - struct npc_data *nd = map_id2nd(sd->touching_id); - short xs, ys; + struct npc_data *nd = map_id2nd(sd->touching_id); + short xs, ys; - if (!nd || nd->touching_id != sd->bl.id) - return 1; + if( !nd || nd->touching_id != sd->bl.id ) + return 1; - xs = nd->u.scr.xs; - ys = nd->u.scr.ys; + xs = nd->u.scr.xs; + ys = nd->u.scr.ys; - if (sd->bl.m != nd->bl.m || - sd->bl.x < nd->bl.x - xs || sd->bl.x > nd->bl.x + xs || - sd->bl.y < nd->bl.y - ys || sd->bl.y > nd->bl.y + ys || - pc_ishiding(sd) || leavemap) { - char name[EVENT_NAME_LENGTH]; + if( sd->bl.m != nd->bl.m || + sd->bl.x < nd->bl.x - xs || sd->bl.x > nd->bl.x + xs || + sd->bl.y < nd->bl.y - ys || sd->bl.y > nd->bl.y + ys || + pc_ishiding(sd) || leavemap ) + { + char name[EVENT_NAME_LENGTH]; - nd->touching_id = sd->touching_id = 0; - snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_name); - map_forcountinarea(npc_touch_areanpc_sub,nd->bl.m,nd->bl.x - xs,nd->bl.y - ys,nd->bl.x + xs,nd->bl.y + ys,1,BL_PC,sd->bl.id,name); - } - return 0; + nd->touching_id = sd->touching_id = 0; + snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_name); + map_forcountinarea(npc_touch_areanpc_sub,nd->bl.m,nd->bl.x - xs,nd->bl.y - ys,nd->bl.x + xs,nd->bl.y + ys,1,BL_PC,sd->bl.id,name); + } + return 0; } /*========================================== * Exec OnTouch for player if in range of area event *------------------------------------------*/ -int npc_touch_areanpc(struct map_session_data *sd, int m, int x, int y) -{ - int xs,ys; - int f = 1; - int i; - - nullpo_retr(1, sd); - - // Why not enqueue it? [Inkfish] - //if(sd->npc_id) - // return 1; - - for (i=0; i<map[m].npc_num; i++) { - if (map[m].npc[i]->sc.option&OPTION_INVISIBLE) { - f=0; // a npc was found, but it is disabled; don't print warning - continue; - } - - switch (map[m].npc[i]->subtype) { - case WARP: - xs=map[m].npc[i]->u.warp.xs; - ys=map[m].npc[i]->u.warp.ys; - break; - case SCRIPT: - xs=map[m].npc[i]->u.scr.xs; - ys=map[m].npc[i]->u.scr.ys; - break; - default: - continue; - } - if (x >= map[m].npc[i]->bl.x-xs && x <= map[m].npc[i]->bl.x+xs - && y >= map[m].npc[i]->bl.y-ys && y <= map[m].npc[i]->bl.y+ys) - break; - } - if (i == map[m].npc_num) { - if (f == 1) // no npc found - ShowError("npc_touch_areanpc : stray NPC cell/NPC not found in the block on coordinates '%s',%d,%d\n", map[m].name, x, y); - return 1; - } - switch (map[m].npc[i]->subtype) { - case WARP: - if (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE])) - break; // hidden chars cannot use warps - pc_setpos(sd,map[m].npc[i]->u.warp.mapindex,map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,CLR_OUTSIGHT); - break; - case SCRIPT: - if (npc_ontouch_event(sd,map[m].npc[i]) > 0 && npc_ontouch2_event(sd,map[m].npc[i]) > 0) { - // failed to run OnTouch event, so just click the npc - struct unit_data *ud = unit_bl2ud(&sd->bl); - if (ud && ud->walkpath.path_pos < ud->walkpath.path_len) { - // Since walktimer always == INVALID_TIMER at this time, we stop walking manually. [Inkfish] - clif_fixpos(&sd->bl); - ud->walkpath.path_pos = ud->walkpath.path_len; - } - sd->areanpc_id = map[m].npc[i]->bl.id; - npc_click(sd,map[m].npc[i]); - } - break; - } - return 0; +int npc_touch_areanpc(struct map_session_data* sd, int m, int x, int y) +{ + int xs,ys; + int f = 1; + int i; + + nullpo_retr(1, sd); + + // Why not enqueue it? [Inkfish] + //if(sd->npc_id) + // return 1; + + for(i=0;i<map[m].npc_num;i++) + { + if (map[m].npc[i]->sc.option&OPTION_INVISIBLE) { + f=0; // a npc was found, but it is disabled; don't print warning + continue; + } + + switch(map[m].npc[i]->subtype) { + case WARP: + xs=map[m].npc[i]->u.warp.xs; + ys=map[m].npc[i]->u.warp.ys; + break; + case SCRIPT: + xs=map[m].npc[i]->u.scr.xs; + ys=map[m].npc[i]->u.scr.ys; + break; + default: + continue; + } + if( x >= map[m].npc[i]->bl.x-xs && x <= map[m].npc[i]->bl.x+xs + && y >= map[m].npc[i]->bl.y-ys && y <= map[m].npc[i]->bl.y+ys ) + break; + } + if( i == map[m].npc_num ) + { + if( f == 1 ) // no npc found + ShowError("npc_touch_areanpc : stray NPC cell/NPC not found in the block on coordinates '%s',%d,%d\n", map[m].name, x, y); + return 1; + } + switch(map[m].npc[i]->subtype) { + case WARP: + if( pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]) ) + break; // hidden chars cannot use warps + pc_setpos(sd,map[m].npc[i]->u.warp.mapindex,map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,CLR_OUTSIGHT); + break; + case SCRIPT: + if( npc_ontouch_event(sd,map[m].npc[i]) > 0 && npc_ontouch2_event(sd,map[m].npc[i]) > 0 ) + { // failed to run OnTouch event, so just click the npc + struct unit_data *ud = unit_bl2ud(&sd->bl); + if( ud && ud->walkpath.path_pos < ud->walkpath.path_len ) + { // Since walktimer always == INVALID_TIMER at this time, we stop walking manually. [Inkfish] + clif_fixpos(&sd->bl); + ud->walkpath.path_pos = ud->walkpath.path_len; + } + sd->areanpc_id = map[m].npc[i]->bl.id; + npc_click(sd,map[m].npc[i]); + } + break; + } + return 0; } // OnTouch NPC or Warp for Mobs // Return 1 if Warped int npc_touch_areanpc2(struct mob_data *md) { - int i, m = md->bl.m, x = md->bl.x, y = md->bl.y, id; - char eventname[EVENT_NAME_LENGTH]; - struct event_data *ev; - int xs, ys; - - for (i = 0; i < map[m].npc_num; i++) { - if (map[m].npc[i]->sc.option&OPTION_INVISIBLE) - continue; - - switch (map[m].npc[i]->subtype) { - case WARP: - if (!(battle_config.mob_warp&1)) - continue; - xs = map[m].npc[i]->u.warp.xs; - ys = map[m].npc[i]->u.warp.ys; - break; - case SCRIPT: - xs = map[m].npc[i]->u.scr.xs; - ys = map[m].npc[i]->u.scr.ys; - break; - default: - continue; // Keep Searching - } - - if (x >= map[m].npc[i]->bl.x-xs && x <= map[m].npc[i]->bl.x+xs && y >= map[m].npc[i]->bl.y-ys && y <= map[m].npc[i]->bl.y+ys) { - // In the npc touch area - switch (map[m].npc[i]->subtype) { - case WARP: - xs = map_mapindex2mapid(map[m].npc[i]->u.warp.mapindex); - if (m < 0) - break; // Cannot Warp between map servers - if (unit_warp(&md->bl, xs, map[m].npc[i]->u.warp.x, map[m].npc[i]->u.warp.y, CLR_OUTSIGHT) == 0) - return 1; // Warped - break; - case SCRIPT: - if (map[m].npc[i]->bl.id == md->areanpc_id) - break; // Already touch this NPC - snprintf(eventname, ARRAYLENGTH(eventname), "%s::OnTouchNPC", map[m].npc[i]->exname); - if ((ev = (struct event_data *)strdb_get(ev_db, eventname)) == NULL || ev->nd == NULL) - break; // No OnTouchNPC Event - md->areanpc_id = map[m].npc[i]->bl.id; - id = md->bl.id; // Stores Unique ID - run_script(ev->nd->u.scr.script, ev->pos, md->bl.id, ev->nd->bl.id); - if (map_id2md(id) == NULL) return 1; // Not Warped, but killed - break; - } - - return 0; - } - } - - return 0; + int i, m = md->bl.m, x = md->bl.x, y = md->bl.y, id; + char eventname[EVENT_NAME_LENGTH]; + struct event_data* ev; + int xs, ys; + + for( i = 0; i < map[m].npc_num; i++ ) + { + if( map[m].npc[i]->sc.option&OPTION_INVISIBLE ) + continue; + + switch( map[m].npc[i]->subtype ) + { + case WARP: + if( !( battle_config.mob_warp&1 ) ) + continue; + xs = map[m].npc[i]->u.warp.xs; + ys = map[m].npc[i]->u.warp.ys; + break; + case SCRIPT: + xs = map[m].npc[i]->u.scr.xs; + ys = map[m].npc[i]->u.scr.ys; + break; + default: + continue; // Keep Searching + } + + if( x >= map[m].npc[i]->bl.x-xs && x <= map[m].npc[i]->bl.x+xs && y >= map[m].npc[i]->bl.y-ys && y <= map[m].npc[i]->bl.y+ys ) + { // In the npc touch area + switch( map[m].npc[i]->subtype ) + { + case WARP: + xs = map_mapindex2mapid(map[m].npc[i]->u.warp.mapindex); + if( m < 0 ) + break; // Cannot Warp between map servers + if( unit_warp(&md->bl, xs, map[m].npc[i]->u.warp.x, map[m].npc[i]->u.warp.y, CLR_OUTSIGHT) == 0 ) + return 1; // Warped + break; + case SCRIPT: + if( map[m].npc[i]->bl.id == md->areanpc_id ) + break; // Already touch this NPC + snprintf(eventname, ARRAYLENGTH(eventname), "%s::OnTouchNPC", map[m].npc[i]->exname); + if( (ev = (struct event_data*)strdb_get(ev_db, eventname)) == NULL || ev->nd == NULL ) + break; // No OnTouchNPC Event + md->areanpc_id = map[m].npc[i]->bl.id; + id = md->bl.id; // Stores Unique ID + run_script(ev->nd->u.scr.script, ev->pos, md->bl.id, ev->nd->bl.id); + if( map_id2md(id) == NULL ) return 1; // Not Warped, but killed + break; + } + + return 0; + } + } + + return 0; } //Checks if there are any NPC on-touch objects on the given range. @@ -985,111 +1003,114 @@ int npc_touch_areanpc2(struct mob_data *md) //&2: NPCs with on-touch events. int npc_check_areanpc(int flag, int m, int x, int y, int range) { - int i; - int x0,y0,x1,y1; - int xs,ys; - - if (range < 0) return 0; - x0 = max(x-range, 0); - y0 = max(y-range, 0); - x1 = min(x+range, map[m].xs-1); - y1 = min(y+range, map[m].ys-1); - - //First check for npc_cells on the range given - i = 0; - for (ys = y0; ys <= y1 && !i; ys++) { - for (xs = x0; xs <= x1 && !i; xs++) { - if (map_getcell(m,xs,ys,CELL_CHKNPC)) - i = 1; - } - } - if (!i) return 0; //No NPC_CELLs. - - //Now check for the actual NPC on said range. - for (i=0; i<map[m].npc_num; i++) { - if (map[m].npc[i]->sc.option&OPTION_INVISIBLE) - continue; - - switch (map[m].npc[i]->subtype) { - case WARP: - if (!(flag&1)) - continue; - xs=map[m].npc[i]->u.warp.xs; - ys=map[m].npc[i]->u.warp.ys; - break; - case SCRIPT: - if (!(flag&2)) - continue; - xs=map[m].npc[i]->u.scr.xs; - ys=map[m].npc[i]->u.scr.ys; - break; - default: - continue; - } - - if (x1 >= map[m].npc[i]->bl.x-xs && x0 <= map[m].npc[i]->bl.x+xs - && y1 >= map[m].npc[i]->bl.y-ys && y0 <= map[m].npc[i]->bl.y+ys) - break; // found a npc - } - if (i==map[m].npc_num) - return 0; - - return (map[m].npc[i]->bl.id); + int i; + int x0,y0,x1,y1; + int xs,ys; + + if (range < 0) return 0; + x0 = max(x-range, 0); + y0 = max(y-range, 0); + x1 = min(x+range, map[m].xs-1); + y1 = min(y+range, map[m].ys-1); + + //First check for npc_cells on the range given + i = 0; + for (ys = y0; ys <= y1 && !i; ys++) { + for(xs = x0; xs <= x1 && !i; xs++){ + if (map_getcell(m,xs,ys,CELL_CHKNPC)) + i = 1; + } + } + if (!i) return 0; //No NPC_CELLs. + + //Now check for the actual NPC on said range. + for(i=0;i<map[m].npc_num;i++) + { + if (map[m].npc[i]->sc.option&OPTION_INVISIBLE) + continue; + + switch(map[m].npc[i]->subtype) + { + case WARP: + if (!(flag&1)) + continue; + xs=map[m].npc[i]->u.warp.xs; + ys=map[m].npc[i]->u.warp.ys; + break; + case SCRIPT: + if (!(flag&2)) + continue; + xs=map[m].npc[i]->u.scr.xs; + ys=map[m].npc[i]->u.scr.ys; + break; + default: + continue; + } + + if( x1 >= map[m].npc[i]->bl.x-xs && x0 <= map[m].npc[i]->bl.x+xs + && y1 >= map[m].npc[i]->bl.y-ys && y0 <= map[m].npc[i]->bl.y+ys ) + break; // found a npc + } + if (i==map[m].npc_num) + return 0; + + return (map[m].npc[i]->bl.id); } /*========================================== * Chk if player not too far to access the npc. * Returns npc_data (success) or NULL (fail). *------------------------------------------*/ -struct npc_data *npc_checknear(struct map_session_data *sd, struct block_list *bl) { - struct npc_data *nd; +struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* bl) +{ + struct npc_data *nd; - nullpo_retr(NULL, sd); - if (bl == NULL) return NULL; - if (bl->type != BL_NPC) return NULL; - nd = (TBL_NPC *)bl; + nullpo_retr(NULL, sd); + if(bl == NULL) return NULL; + if(bl->type != BL_NPC) return NULL; + nd = (TBL_NPC*)bl; - if (sd->state.using_fake_npc && sd->npc_id == bl->id) - return nd; + if(sd->state.using_fake_npc && sd->npc_id == bl->id) + return nd; - if (nd->class_<0) //Class-less npc, enable click from anywhere. - return nd; + if (nd->class_<0) //Class-less npc, enable click from anywhere. + return nd; - if (bl->m!=sd->bl.m || - bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || - bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1) - return NULL; + if (bl->m!=sd->bl.m || + bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || + bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1) + return NULL; - return nd; + return nd; } /*========================================== * Make NPC talk in global chat (like npctalk) *------------------------------------------*/ -int npc_globalmessage(const char *name, const char *mes) +int npc_globalmessage(const char* name, const char* mes) { - struct npc_data *nd = npc_name2id(name); - char temp[100]; + struct npc_data* nd = npc_name2id(name); + char temp[100]; - if (!nd) - return 0; + if (!nd) + return 0; - snprintf(temp, sizeof(temp), "%s : %s", name, mes); - clif_GlobalMessage(&nd->bl,temp); + snprintf(temp, sizeof(temp), "%s : %s", name, mes); + clif_GlobalMessage(&nd->bl,temp); - return 0; + return 0; } // MvP tomb [GreenBox] -void run_tomb(struct map_session_data *sd, struct npc_data *nd) +void run_tomb(struct map_session_data* sd, struct npc_data* nd) { - char buffer[200]; + char buffer[200]; char time[10]; strftime(time, sizeof(time), "%H:%M", localtime(&nd->u.tomb.kill_time)); - // TODO: Find exact color? - snprintf(buffer, sizeof(buffer), msg_txt(657), nd->u.tomb.md->db->name); + // TODO: Find exact color? + snprintf(buffer, sizeof(buffer), msg_txt(657), nd->u.tomb.md->db->name); clif_scriptmes(sd, nd->bl.id, buffer); clif_scriptmes(sd, nd->bl.id, msg_txt(658)); @@ -1099,7 +1120,7 @@ void run_tomb(struct map_session_data *sd, struct npc_data *nd) clif_scriptmes(sd, nd->bl.id, msg_txt(660)); - snprintf(buffer, sizeof(buffer), msg_txt(661), nd->u.tomb.killer_name[0] ? nd->u.tomb.killer_name : "Unknown"); + snprintf(buffer, sizeof(buffer), msg_txt(661), nd->u.tomb.killer_name[0] ? nd->u.tomb.killer_name : "Unknown"); clif_scriptmes(sd, nd->bl.id, buffer); clif_scriptclose(sd, nd->bl.id); @@ -1109,131 +1130,131 @@ void run_tomb(struct map_session_data *sd, struct npc_data *nd) * NPC 1st call when clicking on npc * Do specific action for NPC type (openshop, run scripts...) *------------------------------------------*/ -int npc_click(struct map_session_data *sd, struct npc_data *nd) -{ - nullpo_retr(1, sd); - - if (sd->npc_id != 0) { - ShowError("npc_click: npc_id != 0\n"); - return 1; - } - - if (!nd) return 1; - if ((nd = npc_checknear(sd,&nd->bl)) == NULL) - return 1; - //Hidden/Disabled npc. - if (nd->class_ < 0 || nd->sc.option&(OPTION_INVISIBLE|OPTION_HIDE)) - return 1; - - switch (nd->subtype) { - case SHOP: - clif_npcbuysell(sd,nd->bl.id); - break; - case CASHSHOP: - clif_cashshop_show(sd,nd); - break; - case SCRIPT: - run_script(nd->u.scr.script,0,sd->bl.id,nd->bl.id); - break; - case TOMB: - run_tomb(sd,nd); - break; - } - - return 0; +int npc_click(struct map_session_data* sd, struct npc_data* nd) +{ + nullpo_retr(1, sd); + + if (sd->npc_id != 0) { + ShowError("npc_click: npc_id != 0\n"); + return 1; + } + + if(!nd) return 1; + if ((nd = npc_checknear(sd,&nd->bl)) == NULL) + return 1; + //Hidden/Disabled npc. + if (nd->class_ < 0 || nd->sc.option&(OPTION_INVISIBLE|OPTION_HIDE)) + return 1; + + switch(nd->subtype) { + case SHOP: + clif_npcbuysell(sd,nd->bl.id); + break; + case CASHSHOP: + clif_cashshop_show(sd,nd); + break; + case SCRIPT: + run_script(nd->u.scr.script,0,sd->bl.id,nd->bl.id); + break; + case TOMB: + run_tomb(sd,nd); + break; + } + + return 0; } /*========================================== * *------------------------------------------*/ -int npc_scriptcont(struct map_session_data *sd, int id) -{ - nullpo_retr(1, sd); - - if (id != sd->npc_id) { - TBL_NPC *nd_sd=(TBL_NPC *)map_id2bl(sd->npc_id); - TBL_NPC *nd=(TBL_NPC *)map_id2bl(id); - ShowDebug("npc_scriptcont: %s (sd->npc_id=%d) is not %s (id=%d).\n", - nd_sd?(char *)nd_sd->name:"'Unknown NPC'", (int)sd->npc_id, - nd?(char *)nd->name:"'Unknown NPC'", (int)id); - return 1; - } - - if (id != fake_nd->bl.id) { // Not item script - if ((npc_checknear(sd,map_id2bl(id))) == NULL) { - ShowWarning("npc_scriptcont: failed npc_checknear test.\n"); - return 1; - } - } - /** - * For the Secure NPC Timeout option (check config/Secure.h) [RR] - **/ +int npc_scriptcont(struct map_session_data* sd, int id) +{ + nullpo_retr(1, sd); + + if( id != sd->npc_id ){ + TBL_NPC* nd_sd=(TBL_NPC*)map_id2bl(sd->npc_id); + TBL_NPC* nd=(TBL_NPC*)map_id2bl(id); + ShowDebug("npc_scriptcont: %s (sd->npc_id=%d) is not %s (id=%d).\n", + nd_sd?(char*)nd_sd->name:"'Unknown NPC'", (int)sd->npc_id, + nd?(char*)nd->name:"'Unknown NPC'", (int)id); + return 1; + } + + if(id != fake_nd->bl.id) { // Not item script + if ((npc_checknear(sd,map_id2bl(id))) == NULL){ + ShowWarning("npc_scriptcont: failed npc_checknear test.\n"); + return 1; + } + } + /** + * For the Secure NPC Timeout option (check config/Secure.h) [RR] + **/ #if SECURE_NPCTIMEOUT - /** - * Update the last NPC iteration - **/ - sd->npc_idle_tick = gettick(); + /** + * Update the last NPC iteration + **/ + sd->npc_idle_tick = gettick(); #endif - /** - * WPE can get to this point with a progressbar; we deny it. - **/ - if (sd->progressbar.npc_id && DIFF_TICK(sd->progressbar.timeout,gettick()) > 0) - return 1; + /** + * WPE can get to this point with a progressbar; we deny it. + **/ + if( sd->progressbar.npc_id && DIFF_TICK(sd->progressbar.timeout,gettick()) > 0 ) + return 1; - run_script_main(sd->st); + run_script_main(sd->st); - return 0; + return 0; } /*========================================== * Chk if valid call then open buy or selling list *------------------------------------------*/ -int npc_buysellsel(struct map_session_data *sd, int id, int type) +int npc_buysellsel(struct map_session_data* sd, int id, int type) { - struct npc_data *nd; + struct npc_data *nd; - nullpo_retr(1, sd); + nullpo_retr(1, sd); - if ((nd = npc_checknear(sd,map_id2bl(id))) == NULL) - return 1; + if ((nd = npc_checknear(sd,map_id2bl(id))) == NULL) + return 1; - if (nd->subtype!=SHOP) { - ShowError("no such shop npc : %d\n",id); - if (sd->npc_id == id) - sd->npc_id=0; - return 1; - } + if (nd->subtype!=SHOP) { + ShowError("no such shop npc : %d\n",id); + if (sd->npc_id == id) + sd->npc_id=0; + return 1; + } if (nd->sc.option & OPTION_INVISIBLE) // can't buy if npc is not visible (hack?) - return 1; - if (nd->class_ < 0 && !sd->state.callshop) { - // not called through a script and is not a visible NPC so an invalid call - return 1; - } - - // reset the callshop state for future calls - sd->state.callshop = 0; - sd->npc_shopid = id; - - if (type==0) { - clif_buylist(sd,nd); - } else { - clif_selllist(sd); - } - return 0; + return 1; + if( nd->class_ < 0 && !sd->state.callshop ) + {// not called through a script and is not a visible NPC so an invalid call + return 1; + } + + // reset the callshop state for future calls + sd->state.callshop = 0; + sd->npc_shopid = id; + + if (type==0) { + clif_buylist(sd,nd); + } else { + clif_selllist(sd); + } + return 0; } /*========================================== * Cash Shop Buy List *------------------------------------------*/ -int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short *item_list) +int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list) { int i, j, nameid, amount, new_, w, vt; struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid); - if (!nd || nd->subtype != CASHSHOP) + if( !nd || nd->subtype != CASHSHOP ) return 1; - if (sd->state.trading) + if( sd->state.trading ) return 4; new_ = 0; @@ -1241,23 +1262,26 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns vt = 0; // Global Value // Validating Process ---------------------------------------------------- - for (i = 0; i < count; i++) { + for( i = 0; i < count; i++ ) + { nameid = item_list[i*2+1]; amount = item_list[i*2+0]; - if (!itemdb_exists(nameid) || amount <= 0) + if( !itemdb_exists(nameid) || amount <= 0 ) return 5; ARR_FIND(0,nd->u.shop.count,j,nd->u.shop.shop_item[j].nameid == nameid); - if (j == nd->u.shop.count || nd->u.shop.shop_item[j].value <= 0) + if( j == nd->u.shop.count || nd->u.shop.shop_item[j].value <= 0 ) return 5; - if (!itemdb_isstackable(nameid) && amount > 1) { + if( !itemdb_isstackable(nameid) && amount > 1 ) + { ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); amount = item_list[i*2+0] = 1; } - switch (pc_checkadditem(sd,nameid,amount)) { + switch( pc_checkadditem(sd,nameid,amount) ) + { case ADDITEM_NEW: new_++; break; @@ -1269,19 +1293,20 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns w += itemdb_weight(nameid) * amount; } - if (w + sd->weight > sd->max_weight) + if( w + sd->weight > sd->max_weight ) return 3; - if (pc_inventoryblank(sd) < new_) + if( pc_inventoryblank(sd) < new_ ) return 3; - if (points > vt) points = vt; + if( points > vt ) points = vt; // Payment Process ---------------------------------------------------- - if (sd->kafraPoints < points || sd->cashPoints < (vt - points)) + if( sd->kafraPoints < points || sd->cashPoints < (vt - points) ) return 6; pc_paycash(sd,vt,points); // Delivery Process ---------------------------------------------------- - for (i = 0; i < count; i++) { + for( i = 0; i < count; i++ ) + { struct item item_tmp; nameid = item_list[i*2+1]; @@ -1289,7 +1314,8 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns memset(&item_tmp,0,sizeof(item_tmp)); - if (!pet_create_egg(sd,nameid)) { + if( !pet_create_egg(sd,nameid) ) + { item_tmp.nameid = nameid; item_tmp.identify = 1; pc_additem(sd,&item_tmp,amount,LOG_TYPE_NPC); @@ -1300,28 +1326,29 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns } //npc_buylist for script-controlled shops. -static int npc_buylist_sub(struct map_session_data *sd, int n, unsigned short *item_list, struct npc_data *nd) +static int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd) { - char npc_ev[EVENT_NAME_LENGTH]; - int i; - int key_nameid = 0; - int key_amount = 0; + char npc_ev[EVENT_NAME_LENGTH]; + int i; + int key_nameid = 0; + int key_amount = 0; - // discard old contents - script_cleararray_pc(sd, "@bought_nameid", (void *)0); - script_cleararray_pc(sd, "@bought_quantity", (void *)0); + // discard old contents + script_cleararray_pc(sd, "@bought_nameid", (void*)0); + script_cleararray_pc(sd, "@bought_quantity", (void*)0); - // save list of bought items - for (i = 0; i < n; i++) { - script_setarray_pc(sd, "@bought_nameid", i, (void *)(intptr_t)item_list[i*2+1], &key_nameid); - script_setarray_pc(sd, "@bought_quantity", i, (void *)(intptr_t)item_list[i*2], &key_amount); - } + // save list of bought items + for( i = 0; i < n; i++ ) + { + script_setarray_pc(sd, "@bought_nameid", i, (void*)(intptr_t)item_list[i*2+1], &key_nameid); + script_setarray_pc(sd, "@bought_quantity", i, (void*)(intptr_t)item_list[i*2], &key_amount); + } - // invoke event - snprintf(npc_ev, ARRAYLENGTH(npc_ev), "%s::OnBuyItem", nd->exname); - npc_event(sd, npc_ev, 0); + // invoke event + snprintf(npc_ev, ARRAYLENGTH(npc_ev), "%s::OnBuyItem", nd->exname); + npc_event(sd, npc_ev, 0); - return 0; + return 0; } /*========================================== @@ -1329,246 +1356,257 @@ static int npc_buylist_sub(struct map_session_data *sd, int n, unsigned short *i *------------------------------------------*/ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points) { - struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid); - struct item_data *item; - int i, price, w; + struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid); + struct item_data *item; + int i, price, w; - if (amount <= 0) - return 5; + if( amount <= 0 ) + return 5; - if (points < 0) - return 6; + if( points < 0 ) + return 6; - if (!nd || nd->subtype != CASHSHOP) - return 1; + if( !nd || nd->subtype != CASHSHOP ) + return 1; - if (sd->state.trading) - return 4; + if( sd->state.trading ) + return 4; - if ((item = itemdb_exists(nameid)) == NULL) - return 5; // Invalid Item + if( (item = itemdb_exists(nameid)) == NULL ) + return 5; // Invalid Item - ARR_FIND(0, nd->u.shop.count, i, nd->u.shop.shop_item[i].nameid == nameid); - if (i == nd->u.shop.count) - return 5; - if (nd->u.shop.shop_item[i].value <= 0) - return 5; + ARR_FIND(0, nd->u.shop.count, i, nd->u.shop.shop_item[i].nameid == nameid); + if( i == nd->u.shop.count ) + return 5; + if( nd->u.shop.shop_item[i].value <= 0 ) + return 5; - if (!itemdb_isstackable(nameid) && amount > 1) { - ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", - sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); - amount = 1; - } + if(!itemdb_isstackable(nameid) && amount > 1) + { + ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", + sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); + amount = 1; + } - switch (pc_checkadditem(sd, nameid, amount)) { - case ADDITEM_NEW: - if (pc_inventoryblank(sd) == 0) - return 3; - break; - case ADDITEM_OVERAMOUNT: - return 3; - } + switch( pc_checkadditem(sd, nameid, amount) ) + { + case ADDITEM_NEW: + if( pc_inventoryblank(sd) == 0 ) + return 3; + break; + case ADDITEM_OVERAMOUNT: + return 3; + } - w = item->weight * amount; - if (w + sd->weight > sd->max_weight) - return 3; + w = item->weight * amount; + if( w + sd->weight > sd->max_weight ) + return 3; - if ((double)nd->u.shop.shop_item[i].value * amount > INT_MAX) { - ShowWarning("npc_cashshop_buy: Item '%s' (%d) price overflow attempt!\n", item->name, nameid); - ShowDebug("(NPC:'%s' (%s,%d,%d), player:'%s' (%d/%d), value:%d, amount:%d)\n", nd->exname, map[nd->bl.m].name, nd->bl.x, nd->bl.y, sd->status.name, sd->status.account_id, sd->status.char_id, nd->u.shop.shop_item[i].value, amount); - return 5; - } + if( (double)nd->u.shop.shop_item[i].value * amount > INT_MAX ) + { + ShowWarning("npc_cashshop_buy: Item '%s' (%d) price overflow attempt!\n", item->name, nameid); + ShowDebug("(NPC:'%s' (%s,%d,%d), player:'%s' (%d/%d), value:%d, amount:%d)\n", nd->exname, map[nd->bl.m].name, nd->bl.x, nd->bl.y, sd->status.name, sd->status.account_id, sd->status.char_id, nd->u.shop.shop_item[i].value, amount); + return 5; + } - price = nd->u.shop.shop_item[i].value * amount; - if (points > price) - points = price; + price = nd->u.shop.shop_item[i].value * amount; + if( points > price ) + points = price; - if ((sd->kafraPoints < points) || (sd->cashPoints < price - points)) - return 6; + if( (sd->kafraPoints < points) || (sd->cashPoints < price - points) ) + return 6; - pc_paycash(sd, price, points); + pc_paycash(sd, price, points); - if (!pet_create_egg(sd, nameid)) { - struct item item_tmp; - memset(&item_tmp, 0, sizeof(struct item)); - item_tmp.nameid = nameid; - item_tmp.identify = 1; + if( !pet_create_egg(sd, nameid) ) + { + struct item item_tmp; + memset(&item_tmp, 0, sizeof(struct item)); + item_tmp.nameid = nameid; + item_tmp.identify = 1; - pc_additem(sd,&item_tmp, amount, LOG_TYPE_NPC); - } + pc_additem(sd,&item_tmp, amount, LOG_TYPE_NPC); + } - return 0; + return 0; } /// Player item purchase from npc shop. /// /// @param item_list 'n' pairs <amount,itemid> /// @return result code for clif_parse_NpcBuyListSend -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,new_; - - nullpo_retr(3, sd); - nullpo_retr(3, item_list); - - nd = npc_checknear(sd,map_id2bl(sd->npc_shopid)); - if (nd == NULL) - return 3; - if (nd->subtype != SHOP) - return 3; - - z = 0; - w = 0; - new_ = 0; - // process entries in buy list, one by one - for (i = 0; i < n; ++i) { - int nameid, amount, value; - - // find this entry in the shop's sell list - ARR_FIND(0, nd->u.shop.count, j, - item_list[i*2+1] == nd->u.shop.shop_item[j].nameid || //Normal items - item_list[i*2+1] == itemdb_viewid(nd->u.shop.shop_item[j].nameid) //item_avail replacement - ); - - if (j == nd->u.shop.count) - return 3; // no such item in shop - - amount = item_list[i*2+0]; - nameid = item_list[i*2+1] = nd->u.shop.shop_item[j].nameid; //item_avail replacement - value = nd->u.shop.shop_item[j].value; - - if (!itemdb_exists(nameid)) - return 3; // item no longer in itemdb - - if (!itemdb_isstackable(nameid) && amount > 1) { - //Exploit? You can't buy more than 1 of equipment types o.O - ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", - sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); - amount = item_list[i*2+0] = 1; - } - - if (nd->master_nd) { - // Script-controlled shops decide by themselves, what can be bought and for what price. - continue; - } - - switch (pc_checkadditem(sd,nameid,amount)) { - case ADDITEM_EXIST: - break; - - case ADDITEM_NEW: - new_++; - break; - - case ADDITEM_OVERAMOUNT: - return 2; - } - - value = pc_modifybuyvalue(sd,value); - - z += (double)value * amount; - w += itemdb_weight(nameid) * amount; - } - - if (nd->master_nd != NULL) //Script-based shops. - return npc_buylist_sub(sd,n,item_list,nd->master_nd); - - if (z > (double)sd->status.zeny) - return 1; // Not enough Zeny - if (w + sd->weight > sd->max_weight) - return 2; // Too heavy - if (pc_inventoryblank(sd) < new_) - return 3; // Not enough space to store items - - pc_payzeny(sd,(int)z,LOG_TYPE_NPC, NULL); - - for (i = 0; i < n; ++i) { - int nameid = item_list[i*2+1]; - int amount = item_list[i*2+0]; - struct item item_tmp; - - if (itemdb_type(nameid) == IT_PETEGG) - pet_create_egg(sd, nameid); - else { - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = nameid; - item_tmp.identify = 1; - - pc_additem(sd,&item_tmp,amount,LOG_TYPE_NPC); - } - } - - // custom merchant shop exp bonus - if (battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_DISCOUNT)) > 0) { - if (sd->status.skill[MC_DISCOUNT].flag >= SKILL_FLAG_REPLACED_LV_0) - skill = sd->status.skill[MC_DISCOUNT].flag - SKILL_FLAG_REPLACED_LV_0; - - if (skill > 0) { - z = z * (double)skill * (double)battle_config.shop_exp/10000.; - if (z < 1) - z = 1; - pc_gainexp(sd,NULL,0,(int)z, false); - } - } - - return 0; +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,new_; + + nullpo_retr(3, sd); + nullpo_retr(3, item_list); + + nd = npc_checknear(sd,map_id2bl(sd->npc_shopid)); + if( nd == NULL ) + return 3; + if( nd->subtype != SHOP ) + return 3; + + z = 0; + w = 0; + new_ = 0; + // process entries in buy list, one by one + for( i = 0; i < n; ++i ) + { + int nameid, amount, value; + + // find this entry in the shop's sell list + ARR_FIND( 0, nd->u.shop.count, j, + item_list[i*2+1] == nd->u.shop.shop_item[j].nameid || //Normal items + item_list[i*2+1] == itemdb_viewid(nd->u.shop.shop_item[j].nameid) //item_avail replacement + ); + + if( j == nd->u.shop.count ) + return 3; // no such item in shop + + amount = item_list[i*2+0]; + nameid = item_list[i*2+1] = nd->u.shop.shop_item[j].nameid; //item_avail replacement + value = nd->u.shop.shop_item[j].value; + + if( !itemdb_exists(nameid) ) + return 3; // item no longer in itemdb + + if( !itemdb_isstackable(nameid) && amount > 1 ) + { //Exploit? You can't buy more than 1 of equipment types o.O + ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", + sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); + amount = item_list[i*2+0] = 1; + } + + if( nd->master_nd ) + {// Script-controlled shops decide by themselves, what can be bought and for what price. + continue; + } + + switch( pc_checkadditem(sd,nameid,amount) ) + { + case ADDITEM_EXIST: + break; + + case ADDITEM_NEW: + new_++; + break; + + case ADDITEM_OVERAMOUNT: + return 2; + } + + value = pc_modifybuyvalue(sd,value); + + z += (double)value * amount; + w += itemdb_weight(nameid) * amount; + } + + if( nd->master_nd != NULL ) //Script-based shops. + return npc_buylist_sub(sd,n,item_list,nd->master_nd); + + if( z > (double)sd->status.zeny ) + return 1; // Not enough Zeny + if( w + sd->weight > sd->max_weight ) + return 2; // Too heavy + if( pc_inventoryblank(sd) < new_ ) + return 3; // Not enough space to store items + + pc_payzeny(sd,(int)z,LOG_TYPE_NPC, NULL); + + for( i = 0; i < n; ++i ) + { + int nameid = item_list[i*2+1]; + int amount = item_list[i*2+0]; + struct item item_tmp; + + if (itemdb_type(nameid) == IT_PETEGG) + pet_create_egg(sd, nameid); + else + { + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = nameid; + item_tmp.identify = 1; + + pc_additem(sd,&item_tmp,amount,LOG_TYPE_NPC); + } + } + + // custom merchant shop exp bonus + if( battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_DISCOUNT)) > 0 ) + { + if( sd->status.skill[MC_DISCOUNT].flag >= SKILL_FLAG_REPLACED_LV_0 ) + skill = sd->status.skill[MC_DISCOUNT].flag - SKILL_FLAG_REPLACED_LV_0; + + if( skill > 0 ) + { + z = z * (double)skill * (double)battle_config.shop_exp/10000.; + if( z < 1 ) + z = 1; + pc_gainexp(sd,NULL,0,(int)z, false); + } + } + + return 0; } /// npc_selllist for script-controlled shops -static int npc_selllist_sub(struct map_session_data *sd, int n, unsigned short *item_list, struct npc_data *nd) -{ - char npc_ev[EVENT_NAME_LENGTH]; - char card_slot[NAME_LENGTH]; - int i, j, idx; - int key_nameid = 0; - int key_amount = 0; - int key_refine = 0; - int key_attribute = 0; - int key_identify = 0; - int key_card[MAX_SLOTS]; - - // discard old contents - script_cleararray_pc(sd, "@sold_nameid", (void *)0); - script_cleararray_pc(sd, "@sold_quantity", (void *)0); - script_cleararray_pc(sd, "@sold_refine", (void *)0); - script_cleararray_pc(sd, "@sold_attribute", (void *)0); - script_cleararray_pc(sd, "@sold_identify", (void *)0); - - for (j = 0; j < MAX_SLOTS; j++) { - // clear each of the card slot entries - key_card[j] = 0; - snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1); - script_cleararray_pc(sd, card_slot, (void *)0); - } - - // save list of to be sold items - for (i = 0; i < n; i++) { - idx = item_list[i*2]-2; - - script_setarray_pc(sd, "@sold_nameid", i, (void *)(intptr_t)sd->status.inventory[idx].nameid, &key_nameid); - script_setarray_pc(sd, "@sold_quantity", i, (void *)(intptr_t)item_list[i*2+1], &key_amount); - - if (itemdb_isequip(sd->status.inventory[idx].nameid)) { - // process equipment based information into the arrays - script_setarray_pc(sd, "@sold_refine", i, (void *)(intptr_t)sd->status.inventory[idx].refine, &key_refine); - script_setarray_pc(sd, "@sold_attribute", i, (void *)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute); - script_setarray_pc(sd, "@sold_identify", i, (void *)(intptr_t)sd->status.inventory[idx].identify, &key_identify); - - for (j = 0; j < MAX_SLOTS; j++) { - // store each of the cards from the equipment in the array - snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1); - script_setarray_pc(sd, card_slot, i, (void *)(intptr_t)sd->status.inventory[idx].card[j], &key_card[j]); - } - } - } - - // invoke event - snprintf(npc_ev, ARRAYLENGTH(npc_ev), "%s::OnSellItem", nd->exname); - npc_event(sd, npc_ev, 0); - return 0; +static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd) +{ + char npc_ev[EVENT_NAME_LENGTH]; + char card_slot[NAME_LENGTH]; + int i, j, idx; + int key_nameid = 0; + int key_amount = 0; + int key_refine = 0; + int key_attribute = 0; + int key_identify = 0; + int key_card[MAX_SLOTS]; + + // discard old contents + script_cleararray_pc(sd, "@sold_nameid", (void*)0); + script_cleararray_pc(sd, "@sold_quantity", (void*)0); + script_cleararray_pc(sd, "@sold_refine", (void*)0); + script_cleararray_pc(sd, "@sold_attribute", (void*)0); + script_cleararray_pc(sd, "@sold_identify", (void*)0); + + for( j = 0; j < MAX_SLOTS; j++ ) + {// clear each of the card slot entries + key_card[j] = 0; + snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1); + script_cleararray_pc(sd, card_slot, (void*)0); + } + + // save list of to be sold items + for( i = 0; i < n; i++ ) + { + idx = item_list[i*2]-2; + + script_setarray_pc(sd, "@sold_nameid", i, (void*)(intptr_t)sd->status.inventory[idx].nameid, &key_nameid); + script_setarray_pc(sd, "@sold_quantity", i, (void*)(intptr_t)item_list[i*2+1], &key_amount); + + if( itemdb_isequip(sd->status.inventory[idx].nameid) ) + {// process equipment based information into the arrays + script_setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine); + script_setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute); + script_setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify); + + for( j = 0; j < MAX_SLOTS; j++ ) + {// store each of the cards from the equipment in the array + snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1); + script_setarray_pc(sd, card_slot, i, (void*)(intptr_t)sd->status.inventory[idx].card[j], &key_card[j]); + } + } + } + + // invoke event + snprintf(npc_ev, ARRAYLENGTH(npc_ev), "%s::OnSellItem", nd->exname); + npc_event(sd, npc_ev, 0); + return 0; } @@ -1576,111 +1614,120 @@ static int npc_selllist_sub(struct map_session_data *sd, int n, unsigned short * /// /// @param item_list 'n' pairs <index,amount> /// @return result code for clif_parse_NpcSellListSend -int npc_selllist(struct map_session_data *sd, int n, unsigned short *item_list) +int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) { - double z; - int i,skill; - struct npc_data *nd; + double z; + int i,skill; + struct npc_data *nd; - nullpo_retr(1, sd); - nullpo_retr(1, item_list); + nullpo_retr(1, sd); + nullpo_retr(1, item_list); - if ((nd = npc_checknear(sd, map_id2bl(sd->npc_shopid))) == NULL || nd->subtype != SHOP) { - return 1; - } + if( ( nd = npc_checknear(sd, map_id2bl(sd->npc_shopid)) ) == NULL || nd->subtype != SHOP ) + { + return 1; + } - z = 0; + z = 0; - // verify the sell list - for (i = 0; i < n; i++) { - int nameid, amount, idx, value; + // verify the sell list + for( i = 0; i < n; i++ ) + { + int nameid, amount, idx, value; - idx = item_list[i*2]-2; - amount = item_list[i*2+1]; + idx = item_list[i*2]-2; + amount = item_list[i*2+1]; - if (idx >= MAX_INVENTORY || idx < 0 || amount < 0) { - return 1; - } + if( idx >= MAX_INVENTORY || idx < 0 || amount < 0 ) + { + return 1; + } - nameid = sd->status.inventory[idx].nameid; + nameid = sd->status.inventory[idx].nameid; - if (!nameid || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < amount) { - return 1; - } + if( !nameid || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < amount ) + { + return 1; + } - if (nd->master_nd) { - // Script-controlled shops decide by themselves, what can be sold and at what price. - continue; - } + if( nd->master_nd ) + {// Script-controlled shops decide by themselves, what can be sold and at what price. + continue; + } - value = pc_modifysellvalue(sd, sd->inventory_data[idx]->value_sell); + value = pc_modifysellvalue(sd, sd->inventory_data[idx]->value_sell); - z+= (double)value*amount; - } + z+= (double)value*amount; + } - if (nd->master_nd) { - // Script-controlled shops - return npc_selllist_sub(sd, n, item_list, nd->master_nd); - } + if( nd->master_nd ) + {// Script-controlled shops + return npc_selllist_sub(sd, n, item_list, nd->master_nd); + } - // delete items - for (i = 0; i < n; i++) { - int amount, idx; + // delete items + for( i = 0; i < n; i++ ) + { + int amount, idx; - idx = item_list[i*2]-2; - amount = item_list[i*2+1]; + idx = item_list[i*2]-2; + amount = item_list[i*2+1]; - if (sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET) { - if (search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0) { - intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); - } - } + if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) + { + if( search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0 ) + { + intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); + } + } - pc_delitem(sd, idx, amount, 0, 6, LOG_TYPE_NPC); - } + pc_delitem(sd, idx, amount, 0, 6, LOG_TYPE_NPC); + } - if (z > MAX_ZENY) - z = MAX_ZENY; + if( z > MAX_ZENY ) + z = MAX_ZENY; - pc_getzeny(sd, (int)z, LOG_TYPE_NPC, NULL); + pc_getzeny(sd, (int)z, LOG_TYPE_NPC, NULL); - // custom merchant shop exp bonus - if (battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_OVERCHARGE)) > 0) { - if (sd->status.skill[MC_OVERCHARGE].flag >= SKILL_FLAG_REPLACED_LV_0) - skill = sd->status.skill[MC_OVERCHARGE].flag - SKILL_FLAG_REPLACED_LV_0; + // custom merchant shop exp bonus + if( battle_config.shop_exp > 0 && z > 0 && ( skill = pc_checkskill(sd,MC_OVERCHARGE) ) > 0) + { + if( sd->status.skill[MC_OVERCHARGE].flag >= SKILL_FLAG_REPLACED_LV_0 ) + skill = sd->status.skill[MC_OVERCHARGE].flag - SKILL_FLAG_REPLACED_LV_0; - if (skill > 0) { - z = z * (double)skill * (double)battle_config.shop_exp/10000.; - if (z < 1) - z = 1; - pc_gainexp(sd, NULL, 0, (int)z, false); - } - } + if( skill > 0 ) + { + z = z * (double)skill * (double)battle_config.shop_exp/10000.; + if( z < 1 ) + z = 1; + pc_gainexp(sd, NULL, 0, (int)z, false); + } + } - return 0; + return 0; } //Atempt to remove an npc from a map //This doesn't remove it from map_db -int npc_remove_map(struct npc_data *nd) -{ - int m,i; - nullpo_retr(1, nd); - - if (nd->bl.prev == NULL || nd->bl.m < 0) - return 1; //Not assigned to a map. - m = nd->bl.m; - clif_clearunit_area(&nd->bl,CLR_RESPAWN); - npc_unsetcells(nd); - map_delblock(&nd->bl); - //Remove npc from map[].npc list. [Skotlex] - ARR_FIND(0, map[m].npc_num, i, map[m].npc[i] == nd); - if (i == map[m].npc_num) return 2; //failed to find it? - - map[m].npc_num--; - map[m].npc[i] = map[m].npc[map[m].npc_num]; - map[m].npc[map[m].npc_num] = NULL; - return 0; +int npc_remove_map(struct npc_data* nd) +{ + int m,i; + nullpo_retr(1, nd); + + if(nd->bl.prev == NULL || nd->bl.m < 0) + return 1; //Not assigned to a map. + m = nd->bl.m; + clif_clearunit_area(&nd->bl,CLR_RESPAWN); + npc_unsetcells(nd); + map_delblock(&nd->bl); + //Remove npc from map[].npc list. [Skotlex] + ARR_FIND( 0, map[m].npc_num, i, map[m].npc[i] == nd ); + if( i == map[m].npc_num ) return 2; //failed to find it? + + map[m].npc_num--; + map[m].npc[i] = map[m].npc[map[m].npc_num]; + map[m].npc[map[m].npc_num] = NULL; + return 0; } /** @@ -1688,119 +1735,118 @@ int npc_remove_map(struct npc_data *nd) */ static int npc_unload_ev(DBKey key, DBData *data, va_list ap) { - struct event_data *ev = db_data2ptr(data); - char *npcname = va_arg(ap, char *); + struct event_data* ev = db_data2ptr(data); + char* npcname = va_arg(ap, char *); - if (strcmp(ev->nd->exname,npcname)==0) { - db_remove(ev_db, key); - return 1; - } - return 0; + if(strcmp(ev->nd->exname,npcname)==0){ + db_remove(ev_db, key); + return 1; + } + return 0; } //Chk if npc matches src_id, then unload. //Sub-function used to find duplicates. -static int npc_unload_dup_sub(struct npc_data *nd, va_list args) +static int npc_unload_dup_sub(struct npc_data* nd, va_list args) { - int src_id; + int src_id; - src_id = va_arg(args, int); - if (nd->src_id == src_id) - npc_unload(nd, true); - return 0; + src_id = va_arg(args, int); + if (nd->src_id == src_id) + npc_unload(nd, true); + return 0; } //Removes all npcs that are duplicates of the passed one. [Skotlex] -void npc_unload_duplicates(struct npc_data *nd) +void npc_unload_duplicates(struct npc_data* nd) { - map_foreachnpc(npc_unload_dup_sub,nd->bl.id); + map_foreachnpc(npc_unload_dup_sub,nd->bl.id); } //Removes an npc from map and db. //Single is to free name (for duplicates). -int npc_unload(struct npc_data *nd, bool single) -{ - nullpo_ret(nd); +int npc_unload(struct npc_data* nd, bool single) { + nullpo_ret(nd); - npc_remove_map(nd); - map_deliddb(&nd->bl); - if (single) - strdb_remove(npcname_db, nd->exname); + npc_remove_map(nd); + map_deliddb(&nd->bl); + if( single ) + strdb_remove(npcname_db, nd->exname); - if (nd->chat_id) // remove npc chatroom object and kick users - chat_deletenpcchat(nd); + if (nd->chat_id) // remove npc chatroom object and kick users + chat_deletenpcchat(nd); #ifdef PCRE_SUPPORT - npc_chat_finalize(nd); // deallocate npc PCRE data structures + npc_chat_finalize(nd); // deallocate npc PCRE data structures #endif - if (single && nd->path) { - struct npc_path_data *npd = NULL; - if (nd->path && nd->path != npc_last_ref) { - npd = strdb_get(npc_path_db, nd->path); - } - - if (npd && --npd->references == 0) { - strdb_remove(npc_path_db, nd->path);/* remove from db */ - aFree(nd->path);/* remove now that no other instances exist */ - } - } - - if ((nd->subtype == SHOP || nd->subtype == CASHSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao] - aFree(nd->u.shop.shop_item); - else if (nd->subtype == SCRIPT) { - struct s_mapiterator *iter; - struct block_list *bl; - - if (single) - ev_db->foreach(ev_db,npc_unload_ev,nd->exname); //Clean up all events related - - iter = mapit_geteachpc(); - for (bl = (struct block_list *)mapit_first(iter); mapit_exists(iter); bl = (struct block_list *)mapit_next(iter)) { - struct map_session_data *sd = ((TBL_PC *)bl); - if (sd && sd->npc_timer_id != INVALID_TIMER) { - const struct TimerData *td = get_timer(sd->npc_timer_id); - - if (td && td->id != nd->bl.id) - continue; - - if (td && td->data) - ers_free(timer_event_ers, (void *)td->data); - delete_timer(sd->npc_timer_id, npc_timerevent); - sd->npc_timer_id = INVALID_TIMER; - } - } - mapit_free(iter); - - if (nd->u.scr.timerid != INVALID_TIMER) { - const struct TimerData *td = NULL; - td = get_timer(nd->u.scr.timerid); - if (td && td->data) - ers_free(timer_event_ers, (void *)td->data); - delete_timer(nd->u.scr.timerid, npc_timerevent); - } - if (nd->u.scr.timer_event) - aFree(nd->u.scr.timer_event); - if (nd->src_id == 0) { - if (nd->u.scr.script) { - script_free_code(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; - nd->u.scr.label_list_num = 0; - } - } - if (nd->u.scr.guild_id) - guild_flag_remove(nd); - } - - script_stop_sleeptimers(nd->bl.id); - - aFree(nd); - - return 0; + if( single && nd->path ) { + struct npc_path_data* npd = NULL; + if( nd->path && nd->path != npc_last_ref ) { + npd = strdb_get(npc_path_db, nd->path); + } + + if( npd && --npd->references == 0 ) { + strdb_remove(npc_path_db, nd->path);/* remove from db */ + aFree(nd->path);/* remove now that no other instances exist */ + } + } + + if( (nd->subtype == SHOP || nd->subtype == CASHSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao] + aFree(nd->u.shop.shop_item); + else if( nd->subtype == SCRIPT ) { + struct s_mapiterator* iter; + struct block_list* bl; + + if( single ) + ev_db->foreach(ev_db,npc_unload_ev,nd->exname); //Clean up all events related + + iter = mapit_geteachpc(); + for( bl = (struct block_list*)mapit_first(iter); mapit_exists(iter); bl = (struct block_list*)mapit_next(iter) ) { + struct map_session_data *sd = ((TBL_PC*)bl); + if( sd && sd->npc_timer_id != INVALID_TIMER ) { + const struct TimerData *td = get_timer(sd->npc_timer_id); + + if( td && td->id != nd->bl.id ) + continue; + + if( td && td->data ) + ers_free(timer_event_ers, (void*)td->data); + delete_timer(sd->npc_timer_id, npc_timerevent); + sd->npc_timer_id = INVALID_TIMER; + } + } + mapit_free(iter); + + if (nd->u.scr.timerid != INVALID_TIMER) { + const struct TimerData *td = NULL; + td = get_timer(nd->u.scr.timerid); + if (td && td->data) + ers_free(timer_event_ers, (void*)td->data); + delete_timer(nd->u.scr.timerid, npc_timerevent); + } + if (nd->u.scr.timer_event) + aFree(nd->u.scr.timer_event); + if (nd->src_id == 0) { + if(nd->u.scr.script) { + script_free_code(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; + nd->u.scr.label_list_num = 0; + } + } + if( nd->u.scr.guild_id ) + guild_flag_remove(nd); + } + + script_stop_sleeptimers(nd->bl.id); + + aFree(nd); + + return 0; } // @@ -1810,369 +1856,385 @@ int npc_unload(struct npc_data *nd, bool single) /// Clears the npc source file list static void npc_clearsrcfile(void) { - struct npc_src_list *file = npc_src_files; - struct npc_src_list *file_tofree; + struct npc_src_list* file = npc_src_files; + struct npc_src_list* file_tofree; - while (file != NULL) { - file_tofree = file; - file = file->next; - aFree(file_tofree); - } - npc_src_files = NULL; + while( file != NULL ) + { + file_tofree = file; + file = file->next; + aFree(file_tofree); + } + npc_src_files = NULL; } /// Adds a npc source file (or removes all) -void npc_addsrcfile(const char *name) -{ - struct npc_src_list *file; - struct npc_src_list *file_prev = NULL; - - if (strcmpi(name, "clear") == 0) { - npc_clearsrcfile(); - return; - } - - // prevent multiple insert of source files - file = npc_src_files; - while (file != NULL) { - if (strcmp(name, file->name) == 0) - return;// found the file, no need to insert it again - file_prev = file; - file = file->next; - } - - file = (struct npc_src_list *)aMalloc(sizeof(struct npc_src_list) + strlen(name)); - file->next = NULL; - strncpy(file->name, name, strlen(name) + 1); - if (file_prev == NULL) - npc_src_files = file; - else - file_prev->next = file; +void npc_addsrcfile(const char* name) +{ + struct npc_src_list* file; + struct npc_src_list* file_prev = NULL; + + if( strcmpi(name, "clear") == 0 ) + { + npc_clearsrcfile(); + return; + } + + // prevent multiple insert of source files + file = npc_src_files; + while( file != NULL ) + { + if( strcmp(name, file->name) == 0 ) + return;// found the file, no need to insert it again + file_prev = file; + file = file->next; + } + + file = (struct npc_src_list*)aMalloc(sizeof(struct npc_src_list) + strlen(name)); + file->next = NULL; + strncpy(file->name, name, strlen(name) + 1); + if( file_prev == NULL ) + npc_src_files = file; + else + file_prev->next = file; } /// Removes a npc source file (or all) -void npc_delsrcfile(const char *name) -{ - struct npc_src_list *file = npc_src_files; - struct npc_src_list *file_prev = NULL; - - if (strcmpi(name, "all") == 0) { - npc_clearsrcfile(); - return; - } - - while (file != NULL) { - if (strcmp(file->name, name) == 0) { - if (npc_src_files == file) - npc_src_files = file->next; - else - file_prev->next = file->next; - aFree(file); - break; - } - file_prev = file; - file = file->next; - } +void npc_delsrcfile(const char* name) +{ + struct npc_src_list* file = npc_src_files; + struct npc_src_list* file_prev = NULL; + + if( strcmpi(name, "all") == 0 ) + { + npc_clearsrcfile(); + return; + } + + while( file != NULL ) + { + if( strcmp(file->name, name) == 0 ) + { + if( npc_src_files == file ) + npc_src_files = file->next; + else + file_prev->next = file->next; + aFree(file); + break; + } + file_prev = file; + file = file->next; + } } /// Parses and sets the name and exname of a npc. /// Assumes that m, x and y are already set in nd. -static void npc_parsename(struct npc_data *nd, const char *name, const char *start, const char *buffer, const char *filepath) -{ - const char *p; - struct npc_data *dnd;// duplicate npc - char newname[NAME_LENGTH]; - - // parse name - p = strstr(name,"::"); - if (p) { // <Display name>::<Unique name> - size_t len = p-name; - if (len > NAME_LENGTH) { - ShowWarning("npc_parsename: Display name of '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); - safestrncpy(nd->name, name, sizeof(nd->name)); - } else { - memcpy(nd->name, name, len); - memset(nd->name+len, 0, sizeof(nd->name)-len); - } - len = strlen(p+2); - if (len > NAME_LENGTH) - ShowWarning("npc_parsename: Unique name of '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); - safestrncpy(nd->exname, p+2, sizeof(nd->exname)); - } else {// <Display name> - size_t len = strlen(name); - if (len > NAME_LENGTH) - ShowWarning("npc_parsename: Name '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); - safestrncpy(nd->name, name, sizeof(nd->name)); - safestrncpy(nd->exname, name, sizeof(nd->exname)); - } - - if (*nd->exname == '\0' || strstr(nd->exname,"::") != NULL) { // invalid - snprintf(newname, ARRAYLENGTH(newname), "0_%d_%d_%d", nd->bl.m, nd->bl.x, nd->bl.y); - ShowWarning("npc_parsename: Invalid unique name in file '%s', line'%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname); - safestrncpy(nd->exname, newname, sizeof(nd->exname)); - } - - if ((dnd=npc_name2id(nd->exname)) != NULL) { // duplicate unique name, generate new one - char this_mapname[32]; - char other_mapname[32]; - int i = 0; - - do { - ++i; - snprintf(newname, ARRAYLENGTH(newname), "%d_%d_%d_%d", i, nd->bl.m, nd->bl.x, nd->bl.y); - } while (npc_name2id(newname) != NULL); - - strcpy(this_mapname, (nd->bl.m==-1?"(not on a map)":mapindex_id2name(map[nd->bl.m].index))); - strcpy(other_mapname, (dnd->bl.m==-1?"(not on a map)":mapindex_id2name(map[dnd->bl.m].index))); - - ShowWarning("npc_parsename: Duplicate unique name in file '%s', line'%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname); - ShowDebug("this npc:\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n", nd->name, nd->exname, this_mapname, nd->bl.x, nd->bl.y); - ShowDebug("other npc in '%s' :\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n",dnd->path, dnd->name, dnd->exname, other_mapname, dnd->bl.x, dnd->bl.y); - safestrncpy(nd->exname, newname, sizeof(nd->exname)); - } - - if (npc_last_path != filepath) { - struct npc_path_data *npd = NULL; - - if (!(npd = strdb_get(npc_path_db,filepath))) { - CREATE(npd, struct npc_path_data, 1); - strdb_put(npc_path_db, filepath, npd); - - CREATE(npd->path, char, strlen(filepath)+1); - safestrncpy(npd->path, filepath, strlen(filepath)+1); - - npd->references = 0; - } - - nd->path = npd->path; - npd->references++; - - npc_last_npd = npd; - npc_last_ref = npd->path; - npc_last_path = (char *) filepath; - } else { - nd->path = npc_last_ref; - if (npc_last_npd) - npc_last_npd->references++; - } +static void npc_parsename(struct npc_data* nd, const char* name, const char* start, const char* buffer, const char* filepath) +{ + const char* p; + struct npc_data* dnd;// duplicate npc + char newname[NAME_LENGTH]; + + // parse name + p = strstr(name,"::"); + if( p ) { // <Display name>::<Unique name> + size_t len = p-name; + if( len > NAME_LENGTH ) { + ShowWarning("npc_parsename: Display name of '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); + safestrncpy(nd->name, name, sizeof(nd->name)); + } else { + memcpy(nd->name, name, len); + memset(nd->name+len, 0, sizeof(nd->name)-len); + } + len = strlen(p+2); + if( len > NAME_LENGTH ) + ShowWarning("npc_parsename: Unique name of '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); + safestrncpy(nd->exname, p+2, sizeof(nd->exname)); + } else {// <Display name> + size_t len = strlen(name); + if( len > NAME_LENGTH ) + ShowWarning("npc_parsename: Name '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); + safestrncpy(nd->name, name, sizeof(nd->name)); + safestrncpy(nd->exname, name, sizeof(nd->exname)); + } + + if( *nd->exname == '\0' || strstr(nd->exname,"::") != NULL ) {// invalid + snprintf(newname, ARRAYLENGTH(newname), "0_%d_%d_%d", nd->bl.m, nd->bl.x, nd->bl.y); + ShowWarning("npc_parsename: Invalid unique name in file '%s', line'%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname); + safestrncpy(nd->exname, newname, sizeof(nd->exname)); + } + + if( (dnd=npc_name2id(nd->exname)) != NULL ) {// duplicate unique name, generate new one + char this_mapname[32]; + char other_mapname[32]; + int i = 0; + + do { + ++i; + snprintf(newname, ARRAYLENGTH(newname), "%d_%d_%d_%d", i, nd->bl.m, nd->bl.x, nd->bl.y); + } while( npc_name2id(newname) != NULL ); + + strcpy(this_mapname, (nd->bl.m==-1?"(not on a map)":mapindex_id2name(map[nd->bl.m].index))); + strcpy(other_mapname, (dnd->bl.m==-1?"(not on a map)":mapindex_id2name(map[dnd->bl.m].index))); + + ShowWarning("npc_parsename: Duplicate unique name in file '%s', line'%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname); + ShowDebug("this npc:\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n", nd->name, nd->exname, this_mapname, nd->bl.x, nd->bl.y); + ShowDebug("other npc in '%s' :\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n",dnd->path, dnd->name, dnd->exname, other_mapname, dnd->bl.x, dnd->bl.y); + safestrncpy(nd->exname, newname, sizeof(nd->exname)); + } + + if( npc_last_path != filepath ) { + struct npc_path_data * npd = NULL; + + if( !(npd = strdb_get(npc_path_db,filepath) ) ) { + CREATE(npd, struct npc_path_data, 1); + strdb_put(npc_path_db, filepath, npd); + + CREATE(npd->path, char, strlen(filepath)+1); + safestrncpy(npd->path, filepath, strlen(filepath)+1); + + npd->references = 0; + } + + nd->path = npd->path; + npd->references++; + + npc_last_npd = npd; + npc_last_ref = npd->path; + npc_last_path = (char*) filepath; + } else { + nd->path = npc_last_ref; + if( npc_last_npd ) + npc_last_npd->references++; + } } //Add then display an npc warp on map -struct npc_data *npc_add_warp(char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y) { - int i, flag = 0; - struct npc_data *nd; - - CREATE(nd, struct npc_data, 1); - nd->bl.id = npc_get_new_npc_id(); - map_addnpc(from_mapid, nd); - nd->bl.prev = nd->bl.next = NULL; - nd->bl.m = from_mapid; - nd->bl.x = from_x; - nd->bl.y = from_y; - - safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname)); - if (npc_name2id(nd->exname) != NULL) - flag = 1; - - if (flag == 1) - snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp_%d_%d_%d", from_mapid, from_x, from_y); - - for (i = 0; npc_name2id(nd->exname) != NULL; ++i) - snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp%d_%d_%d_%d", i, from_mapid, from_x, from_y); - safestrncpy(nd->name, nd->exname, ARRAYLENGTH(nd->name)); - - if (battle_config.warp_point_debug) - nd->class_ = WARP_DEBUG_CLASS; - else - nd->class_ = WARP_CLASS; - nd->speed = 200; - - nd->u.warp.mapindex = to_mapindex; - nd->u.warp.x = to_x; - nd->u.warp.y = to_y; - nd->u.warp.xs = xs; - nd->u.warp.ys = xs; - nd->bl.type = BL_NPC; - nd->subtype = WARP; - npc_setcells(nd); - map_addblock(&nd->bl); - status_set_viewdata(&nd->bl, nd->class_); - status_change_init(&nd->bl); - unit_dataset(&nd->bl); - if (map[nd->bl.m].users) - clif_spawn(&nd->bl); - strdb_put(npcname_db, nd->exname, nd); - - return nd; +struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y) +{ + int i, flag = 0; + struct npc_data *nd; + + CREATE(nd, struct npc_data, 1); + nd->bl.id = npc_get_new_npc_id(); + map_addnpc(from_mapid, nd); + nd->bl.prev = nd->bl.next = NULL; + nd->bl.m = from_mapid; + nd->bl.x = from_x; + nd->bl.y = from_y; + + safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname)); + if (npc_name2id(nd->exname) != NULL) + flag = 1; + + if (flag == 1) + snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp_%d_%d_%d", from_mapid, from_x, from_y); + + for( i = 0; npc_name2id(nd->exname) != NULL; ++i ) + snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp%d_%d_%d_%d", i, from_mapid, from_x, from_y); + safestrncpy(nd->name, nd->exname, ARRAYLENGTH(nd->name)); + + if( battle_config.warp_point_debug ) + nd->class_ = WARP_DEBUG_CLASS; + else + nd->class_ = WARP_CLASS; + nd->speed = 200; + + nd->u.warp.mapindex = to_mapindex; + nd->u.warp.x = to_x; + nd->u.warp.y = to_y; + nd->u.warp.xs = xs; + nd->u.warp.ys = xs; + nd->bl.type = BL_NPC; + nd->subtype = WARP; + npc_setcells(nd); + map_addblock(&nd->bl); + status_set_viewdata(&nd->bl, nd->class_); + status_change_init(&nd->bl); + unit_dataset(&nd->bl); + if( map[nd->bl.m].users ) + clif_spawn(&nd->bl); + strdb_put(npcname_db, nd->exname, nd); + + return nd; } /// Parses a warp npc. -static const char *npc_parse_warp(char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath) -{ - int x, y, xs, ys, to_x, to_y, m; - unsigned short i; - char mapname[32], to_mapname[32]; - struct npc_data *nd; - - // w1=<from map name>,<fromX>,<fromY>,<facing> - // w4=<spanx>,<spany>,<to map name>,<toX>,<toY> - if (sscanf(w1, "%31[^,],%d,%d", mapname, &x, &y) != 3 - || sscanf(w4, "%d,%d,%31[^,],%d,%d", &xs, &ys, to_mapname, &to_x, &to_y) != 5) { - ShowError("npc_parse_warp: Invalid warp definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - return strchr(start,'\n');// skip and continue - } - - m = map_mapname2mapid(mapname); - i = mapindex_name2id(to_mapname); - if (i == 0) { - ShowError("npc_parse_warp: Unknown destination map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), to_mapname, w1, w2, w3, w4); - return strchr(start,'\n');// skip and continue - } - - CREATE(nd, struct npc_data, 1); - - nd->bl.id = npc_get_new_npc_id(); - map_addnpc(m, nd); - nd->bl.prev = nd->bl.next = NULL; - nd->bl.m = m; - nd->bl.x = x; - nd->bl.y = y; - npc_parsename(nd, w3, start, buffer, filepath); - - if (!battle_config.warp_point_debug) - nd->class_ = WARP_CLASS; - else - nd->class_ = WARP_DEBUG_CLASS; - nd->speed = 200; - - nd->u.warp.mapindex = i; - nd->u.warp.x = to_x; - nd->u.warp.y = to_y; - nd->u.warp.xs = xs; - nd->u.warp.ys = ys; - npc_warp++; - nd->bl.type = BL_NPC; - nd->subtype = WARP; - npc_setcells(nd); - map_addblock(&nd->bl); - status_set_viewdata(&nd->bl, nd->class_); - status_change_init(&nd->bl); - unit_dataset(&nd->bl); - if (map[nd->bl.m].users) - clif_spawn(&nd->bl); - strdb_put(npcname_db, nd->exname, nd); - - return strchr(start,'\n');// continue +static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) +{ + int x, y, xs, ys, to_x, to_y, m; + unsigned short i; + char mapname[32], to_mapname[32]; + struct npc_data *nd; + + // w1=<from map name>,<fromX>,<fromY>,<facing> + // w4=<spanx>,<spany>,<to map name>,<toX>,<toY> + if( sscanf(w1, "%31[^,],%d,%d", mapname, &x, &y) != 3 + || sscanf(w4, "%d,%d,%31[^,],%d,%d", &xs, &ys, to_mapname, &to_x, &to_y) != 5 ) + { + ShowError("npc_parse_warp: Invalid warp definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + return strchr(start,'\n');// skip and continue + } + + m = map_mapname2mapid(mapname); + i = mapindex_name2id(to_mapname); + if( i == 0 ) + { + ShowError("npc_parse_warp: Unknown destination map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), to_mapname, w1, w2, w3, w4); + return strchr(start,'\n');// skip and continue + } + + CREATE(nd, struct npc_data, 1); + + nd->bl.id = npc_get_new_npc_id(); + map_addnpc(m, nd); + nd->bl.prev = nd->bl.next = NULL; + nd->bl.m = m; + nd->bl.x = x; + nd->bl.y = y; + npc_parsename(nd, w3, start, buffer, filepath); + + if (!battle_config.warp_point_debug) + nd->class_ = WARP_CLASS; + else + nd->class_ = WARP_DEBUG_CLASS; + nd->speed = 200; + + nd->u.warp.mapindex = i; + nd->u.warp.x = to_x; + nd->u.warp.y = to_y; + nd->u.warp.xs = xs; + nd->u.warp.ys = ys; + npc_warp++; + nd->bl.type = BL_NPC; + nd->subtype = WARP; + npc_setcells(nd); + map_addblock(&nd->bl); + status_set_viewdata(&nd->bl, nd->class_); + status_change_init(&nd->bl); + unit_dataset(&nd->bl); + if( map[nd->bl.m].users ) + clif_spawn(&nd->bl); + strdb_put(npcname_db, nd->exname, nd); + + return strchr(start,'\n');// continue } /// Parses a shop/cashshop npc. -static const char *npc_parse_shop(char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath) -{ - //TODO: could be rewritten to NOT need this temp array [ultramage] -#define MAX_SHOPITEM 100 - struct npc_item_list items[MAX_SHOPITEM]; - char *p; - int x, y, dir, m, i; - struct npc_data *nd; - enum npc_subtype type; - - if (strcmp(w1,"-") == 0) { - // 'floating' shop? - x = y = dir = 0; - m = -1; - } else { - // w1=<map name>,<x>,<y>,<facing> - char mapname[32]; - if (sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 - || strchr(w4, ',') == NULL) { - ShowError("npc_parse_shop: Invalid shop definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - return strchr(start,'\n');// skip and continue - } - - m = map_mapname2mapid(mapname); - } - - if (!strcasecmp(w2,"cashshop")) - type = CASHSHOP; - else - type = SHOP; - - p = strchr(w4,','); - for (i = 0; i < ARRAYLENGTH(items) && p; ++i) { - int nameid, value; - struct item_data *id; - if (sscanf(p, ",%d:%d", &nameid, &value) != 2) { - ShowError("npc_parse_shop: Invalid item definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - break; - } - - if ((id = itemdb_exists(nameid)) == NULL) { - ShowWarning("npc_parse_shop: Invalid sell item in file '%s', line '%d' (id '%d').\n", filepath, strline(buffer,start-buffer), nameid); - p = strchr(p+1,','); - continue; - } - - if (value < 0) { - if (type == SHOP) value = id->value_buy; - else value = 0; // Cashshop doesn't have a "buy price" in the item_db - } - - if (type == SHOP && value == 0) { - // NPC selling items for free! - ShowWarning("npc_parse_shop: Item %s [%d] is being sold for FREE in file '%s', line '%d'.\n", - id->name, nameid, filepath, strline(buffer,start-buffer)); - } - if (type == SHOP && value*0.75 < id->value_sell*1.24) { - // Exploit possible: you can buy and sell back with profit - ShowWarning("npc_parse_shop: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) at file '%s', line '%d'.\n", - id->name, nameid, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer)); - } - //for logs filters, atcommands and iteminfo script command - if (id->maxchance == 0) - id->maxchance = -1; // -1 would show that the item's sold in NPC Shop - - items[i].nameid = nameid; - items[i].value = value; - p = strchr(p+1,','); - } - if (i == 0) { - ShowWarning("npc_parse_shop: Ignoring empty shop in file '%s', line '%d'.\n", filepath, strline(buffer,start-buffer)); - return strchr(start,'\n');// continue - } - - CREATE(nd, struct npc_data, 1); - CREATE(nd->u.shop.shop_item, struct npc_item_list, i); - memcpy(nd->u.shop.shop_item, items, sizeof(struct npc_item_list)*i); - nd->u.shop.count = i; - nd->bl.prev = nd->bl.next = NULL; - nd->bl.m = m; - nd->bl.x = x; - nd->bl.y = y; - nd->bl.id = npc_get_new_npc_id(); - npc_parsename(nd, w3, start, buffer, filepath); - nd->class_ = m==-1?-1:atoi(w4); - nd->speed = 200; - - ++npc_shop; - nd->bl.type = BL_NPC; - nd->subtype = type; - if (m >= 0) { - // normal shop npc - map_addnpc(m,nd); - map_addblock(&nd->bl); - status_set_viewdata(&nd->bl, nd->class_); - status_change_init(&nd->bl); - unit_dataset(&nd->bl); - nd->ud.dir = dir; - if (map[nd->bl.m].users) - clif_spawn(&nd->bl); - } else { - // 'floating' shop? - map_addiddb(&nd->bl); - } - strdb_put(npcname_db, nd->exname, nd); - - return strchr(start,'\n');// continue +static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) +{ + //TODO: could be rewritten to NOT need this temp array [ultramage] + #define MAX_SHOPITEM 100 + struct npc_item_list items[MAX_SHOPITEM]; + char *p; + int x, y, dir, m, i; + struct npc_data *nd; + enum npc_subtype type; + + if( strcmp(w1,"-") == 0 ) + {// 'floating' shop? + x = y = dir = 0; + m = -1; + } + else + {// w1=<map name>,<x>,<y>,<facing> + char mapname[32]; + if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 + || strchr(w4, ',') == NULL ) + { + ShowError("npc_parse_shop: Invalid shop definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + return strchr(start,'\n');// skip and continue + } + + m = map_mapname2mapid(mapname); + } + + if( !strcasecmp(w2,"cashshop") ) + type = CASHSHOP; + else + type = SHOP; + + p = strchr(w4,','); + for( i = 0; i < ARRAYLENGTH(items) && p; ++i ) + { + int nameid, value; + struct item_data* id; + if( sscanf(p, ",%d:%d", &nameid, &value) != 2 ) + { + ShowError("npc_parse_shop: Invalid item definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + break; + } + + if( (id = itemdb_exists(nameid)) == NULL ) + { + ShowWarning("npc_parse_shop: Invalid sell item in file '%s', line '%d' (id '%d').\n", filepath, strline(buffer,start-buffer), nameid); + p = strchr(p+1,','); + continue; + } + + if( value < 0 ) + { + if( type == SHOP ) value = id->value_buy; + else value = 0; // Cashshop doesn't have a "buy price" in the item_db + } + + if( type == SHOP && value == 0 ) + { // NPC selling items for free! + ShowWarning("npc_parse_shop: Item %s [%d] is being sold for FREE in file '%s', line '%d'.\n", + id->name, nameid, filepath, strline(buffer,start-buffer)); + } + if( type == SHOP && value*0.75 < id->value_sell*1.24 ) + {// Exploit possible: you can buy and sell back with profit + ShowWarning("npc_parse_shop: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) at file '%s', line '%d'.\n", + id->name, nameid, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer)); + } + //for logs filters, atcommands and iteminfo script command + if( id->maxchance == 0 ) + id->maxchance = -1; // -1 would show that the item's sold in NPC Shop + + items[i].nameid = nameid; + items[i].value = value; + p = strchr(p+1,','); + } + if( i == 0 ) + { + ShowWarning("npc_parse_shop: Ignoring empty shop in file '%s', line '%d'.\n", filepath, strline(buffer,start-buffer)); + return strchr(start,'\n');// continue + } + + CREATE(nd, struct npc_data, 1); + CREATE(nd->u.shop.shop_item, struct npc_item_list, i); + memcpy(nd->u.shop.shop_item, items, sizeof(struct npc_item_list)*i); + nd->u.shop.count = i; + nd->bl.prev = nd->bl.next = NULL; + nd->bl.m = m; + nd->bl.x = x; + nd->bl.y = y; + nd->bl.id = npc_get_new_npc_id(); + npc_parsename(nd, w3, start, buffer, filepath); + nd->class_ = m==-1?-1:atoi(w4); + nd->speed = 200; + + ++npc_shop; + nd->bl.type = BL_NPC; + nd->subtype = type; + if( m >= 0 ) + {// normal shop npc + map_addnpc(m,nd); + map_addblock(&nd->bl); + status_set_viewdata(&nd->bl, nd->class_); + status_change_init(&nd->bl); + unit_dataset(&nd->bl); + nd->ud.dir = dir; + if( map[nd->bl.m].users ) + clif_spawn(&nd->bl); + } else + {// 'floating' shop? + map_addiddb(&nd->bl); + } + strdb_put(npcname_db, nd->exname, nd); + + return strchr(start,'\n');// continue } /** @@ -2182,91 +2244,102 @@ static const char *npc_parse_shop(char *w1, char *w2, char *w3, char *w4, const */ int npc_convertlabel_db(DBKey key, DBData *data, va_list ap) { - const char *lname = (const char *)key.str; - int lpos = db_data2i(data); - struct npc_label_list **label_list; - int *label_list_num; - const char *filepath; - struct npc_label_list *label; - const char *p; - int len; - - nullpo_ret(label_list = va_arg(ap,struct npc_label_list **)); - nullpo_ret(label_list_num = va_arg(ap,int *)); - nullpo_ret(filepath = va_arg(ap,const char *)); - - // In case of labels not terminated with ':', for user defined function support - p = lname; - while (ISALNUM(*p) || *p == '_') - ++p; - len = p-lname; - - // here we check if the label fit into the buffer - if (len > 23) { - ShowError("npc_parse_script: label name longer than 23 chars! '%s'\n (%s)", lname, filepath); - return 0; - } - - if (*label_list == NULL) { - *label_list = (struct npc_label_list *) aCalloc(1, sizeof(struct npc_label_list)); - *label_list_num = 0; - } else - *label_list = (struct npc_label_list *) aRealloc(*label_list, sizeof(struct npc_label_list)*(*label_list_num+1)); - label = *label_list+*label_list_num; - - safestrncpy(label->name, lname, sizeof(label->name)); - label->pos = lpos; - ++(*label_list_num); - - return 0; + const char* lname = (const char*)key.str; + int lpos = db_data2i(data); + struct npc_label_list** label_list; + int* label_list_num; + const char* filepath; + struct npc_label_list* label; + const char *p; + int len; + + nullpo_ret(label_list = va_arg(ap,struct npc_label_list**)); + nullpo_ret(label_list_num = va_arg(ap,int*)); + nullpo_ret(filepath = va_arg(ap,const char*)); + + // In case of labels not terminated with ':', for user defined function support + p = lname; + while( ISALNUM(*p) || *p == '_' ) + ++p; + len = p-lname; + + // here we check if the label fit into the buffer + if( len > 23 ) + { + ShowError("npc_parse_script: label name longer than 23 chars! '%s'\n (%s)", lname, filepath); + return 0; + } + + if( *label_list == NULL ) + { + *label_list = (struct npc_label_list *) aCalloc (1, sizeof(struct npc_label_list)); + *label_list_num = 0; + } else + *label_list = (struct npc_label_list *) aRealloc (*label_list, sizeof(struct npc_label_list)*(*label_list_num+1)); + label = *label_list+*label_list_num; + + safestrncpy(label->name, lname, sizeof(label->name)); + label->pos = lpos; + ++(*label_list_num); + + return 0; } // Skip the contents of a script. -static const char *npc_skip_script(const char *start, const char *buffer, const char *filepath) -{ - const char *p; - int curly_count; - - if (start == NULL) - return NULL;// nothing to skip - - // initial bracket (assumes the previous part is ok) - p = strchr(start,'{'); - if (p == NULL) { - ShowError("npc_skip_script: Missing left curly in file '%s', line'%d'.", filepath, strline(buffer,start-buffer)); - return NULL;// can't continue - } - - // skip everything - for (curly_count = 1; curly_count > 0 ;) { - p = skip_space(p+1) ; - if (*p == '}') { - // right curly - --curly_count; - } else if (*p == '{') { - // left curly - ++curly_count; - } else if (*p == '"') { - // string - for (++p; *p != '"' ; ++p) { - if (*p == '\\' && (unsigned char)p[-1] <= 0x7e) - ++p;// escape sequence (not part of a multibyte character) - else if (*p == '\0') { - script_error(buffer, filepath, 0, "Unexpected end of string.", p); - return NULL;// can't continue - } else if (*p == '\n') { - script_error(buffer, filepath, 0, "Unexpected newline at string.", p); - return NULL;// can't continue - } - } - } else if (*p == '\0') { - // end of buffer - ShowError("Missing %d right curlys at file '%s', line '%d'.\n", curly_count, filepath, strline(buffer,p-buffer)); - return NULL;// can't continue - } - } - - return p+1;// return after the last '}' +static const char* npc_skip_script(const char* start, const char* buffer, const char* filepath) +{ + const char* p; + int curly_count; + + if( start == NULL ) + return NULL;// nothing to skip + + // initial bracket (assumes the previous part is ok) + p = strchr(start,'{'); + if( p == NULL ) + { + ShowError("npc_skip_script: Missing left curly in file '%s', line'%d'.", filepath, strline(buffer,start-buffer)); + return NULL;// can't continue + } + + // skip everything + for( curly_count = 1; curly_count > 0 ; ) + { + p = skip_space(p+1) ; + if( *p == '}' ) + {// right curly + --curly_count; + } + else if( *p == '{' ) + {// left curly + ++curly_count; + } + else if( *p == '"' ) + {// string + for( ++p; *p != '"' ; ++p ) + { + if( *p == '\\' && (unsigned char)p[-1] <= 0x7e ) + ++p;// escape sequence (not part of a multibyte character) + else if( *p == '\0' ) + { + script_error(buffer, filepath, 0, "Unexpected end of string.", p); + return NULL;// can't continue + } + else if( *p == '\n' ) + { + script_error(buffer, filepath, 0, "Unexpected newline at string.", p); + return NULL;// can't continue + } + } + } + else if( *p == '\0' ) + {// end of buffer + ShowError("Missing %d right curlys at file '%s', line '%d'.\n", curly_count, filepath, strline(buffer,p-buffer)); + return NULL;// can't continue + } + } + + return p+1;// return after the last '}' } /// Parses a npc script. @@ -2274,128 +2347,136 @@ static const char *npc_skip_script(const char *start, const char *buffer, const /// -%TAB%script%TAB%<NPC Name>%TAB%-1,{<code>} /// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>} /// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>} -static const char *npc_parse_script(char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, bool runOnInit) -{ - int x, y, dir = 0, m, xs = 0, ys = 0, class_ = 0; // [Valaris] thanks to fov - char mapname[32]; - struct script_code *script; - int i; - const char *end; - const char *script_start; - - struct npc_label_list *label_list; - int label_list_num; - struct npc_data *nd; - - if (strcmp(w1, "-") == 0) { - // floating npc - x = 0; - y = 0; - m = -1; - } else { - // npc in a map - if (sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4) { - ShowError("npc_parse_script: Invalid placement format for a script in file '%s', line '%d'. Skipping the rest of file...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - return NULL;// unknown format, don't continue - } - m = map_mapname2mapid(mapname); - } - - script_start = strstr(start,",{"); - end = strchr(start,'\n'); - if (strstr(w4,",{") == NULL || script_start == NULL || (end != NULL && script_start > end)) { - ShowError("npc_parse_script: Missing left curly ',{' in file '%s', line '%d'. Skipping the rest of the file.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - return NULL;// can't continue - } - ++script_start; - - end = npc_skip_script(script_start, buffer, filepath); - if (end == NULL) - return NULL;// (simple) parse error, don't continue - - script = parse_script(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB); - label_list = NULL; - label_list_num = 0; - if (script) { - DBMap *label_db = script_get_label_db(); - label_db->foreach(label_db, npc_convertlabel_db, &label_list, &label_list_num, filepath); - db_clear(label_db); // not needed anymore, so clear the db - } - - CREATE(nd, struct npc_data, 1); - - if (sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3) { - // OnTouch area defined - nd->u.scr.xs = xs; - nd->u.scr.ys = ys; - } else { - // no OnTouch area - class_ = atoi(w4); - nd->u.scr.xs = -1; - nd->u.scr.ys = -1; - } - - nd->bl.prev = nd->bl.next = NULL; - nd->bl.m = m; - nd->bl.x = x; - nd->bl.y = y; - npc_parsename(nd, w3, start, buffer, filepath); - nd->bl.id = npc_get_new_npc_id(); - nd->class_ = class_; - nd->speed = 200; - nd->u.scr.script = script; - nd->u.scr.label_list = label_list; - nd->u.scr.label_list_num = label_list_num; - - ++npc_script; - nd->bl.type = BL_NPC; - nd->subtype = SCRIPT; - - if (m >= 0) { - map_addnpc(m, nd); - status_change_init(&nd->bl); - unit_dataset(&nd->bl); - nd->ud.dir = dir; - npc_setcells(nd); - map_addblock(&nd->bl); - if (class_ >= 0) { - status_set_viewdata(&nd->bl, nd->class_); - if (map[nd->bl.m].users) - clif_spawn(&nd->bl); - } - } else { - // we skip map_addnpc, but still add it to the list of ID's - map_addiddb(&nd->bl); - } - strdb_put(npcname_db, nd->exname, nd); - - //----------------------------------------- - // Loop through labels to export them as necessary - for (i = 0; i < nd->u.scr.label_list_num; i++) { - if (npc_event_export(nd, i)) { - ShowWarning("npc_parse_script : duplicate event %s::%s (%s)\n", - nd->exname, nd->u.scr.label_list[i].name, filepath); - } - npc_timerevent_export(nd, i); - } - - nd->u.scr.timerid = INVALID_TIMER; - - if (runOnInit) { - char evname[EVENT_NAME_LENGTH]; - struct event_data *ev; - - snprintf(evname, ARRAYLENGTH(evname), "%s::OnInit", nd->exname); - - if ((ev = (struct event_data *)strdb_get(ev_db, evname))) { - - //Execute OnInit - run_script(nd->u.scr.script,ev->pos,0,nd->bl.id); - - } - } - - return end; +static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, bool runOnInit) { + int x, y, dir = 0, m, xs = 0, ys = 0, class_ = 0; // [Valaris] thanks to fov + char mapname[32]; + struct script_code *script; + int i; + const char* end; + const char* script_start; + + struct npc_label_list* label_list; + int label_list_num; + struct npc_data* nd; + + if( strcmp(w1, "-") == 0 ) + {// floating npc + x = 0; + y = 0; + m = -1; + } + else + {// npc in a map + if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 ) + { + ShowError("npc_parse_script: Invalid placement format for a script in file '%s', line '%d'. Skipping the rest of file...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + return NULL;// unknown format, don't continue + } + m = map_mapname2mapid(mapname); + } + + script_start = strstr(start,",{"); + end = strchr(start,'\n'); + if( strstr(w4,",{") == NULL || script_start == NULL || (end != NULL && script_start > end) ) + { + ShowError("npc_parse_script: Missing left curly ',{' in file '%s', line '%d'. Skipping the rest of the file.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + return NULL;// can't continue + } + ++script_start; + + end = npc_skip_script(script_start, buffer, filepath); + if( end == NULL ) + return NULL;// (simple) parse error, don't continue + + script = parse_script(script_start, filepath, strline(buffer,script_start-buffer), SCRIPT_USE_LABEL_DB); + label_list = NULL; + label_list_num = 0; + if( script ) + { + DBMap* label_db = script_get_label_db(); + label_db->foreach(label_db, npc_convertlabel_db, &label_list, &label_list_num, filepath); + db_clear(label_db); // not needed anymore, so clear the db + } + + CREATE(nd, struct npc_data, 1); + + if( sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3 ) + {// OnTouch area defined + nd->u.scr.xs = xs; + nd->u.scr.ys = ys; + } + else + {// no OnTouch area + class_ = atoi(w4); + nd->u.scr.xs = -1; + nd->u.scr.ys = -1; + } + + nd->bl.prev = nd->bl.next = NULL; + nd->bl.m = m; + nd->bl.x = x; + nd->bl.y = y; + npc_parsename(nd, w3, start, buffer, filepath); + nd->bl.id = npc_get_new_npc_id(); + nd->class_ = class_; + nd->speed = 200; + nd->u.scr.script = script; + nd->u.scr.label_list = label_list; + nd->u.scr.label_list_num = label_list_num; + + ++npc_script; + nd->bl.type = BL_NPC; + nd->subtype = SCRIPT; + + if( m >= 0 ) + { + map_addnpc(m, nd); + status_change_init(&nd->bl); + unit_dataset(&nd->bl); + nd->ud.dir = dir; + npc_setcells(nd); + map_addblock(&nd->bl); + if( class_ >= 0 ) + { + status_set_viewdata(&nd->bl, nd->class_); + if( map[nd->bl.m].users ) + clif_spawn(&nd->bl); + } + } + else + { + // we skip map_addnpc, but still add it to the list of ID's + map_addiddb(&nd->bl); + } + strdb_put(npcname_db, nd->exname, nd); + + //----------------------------------------- + // Loop through labels to export them as necessary + for (i = 0; i < nd->u.scr.label_list_num; i++) { + if (npc_event_export(nd, i)) { + ShowWarning("npc_parse_script : duplicate event %s::%s (%s)\n", + nd->exname, nd->u.scr.label_list[i].name, filepath); + } + npc_timerevent_export(nd, i); + } + + nd->u.scr.timerid = INVALID_TIMER; + + if( runOnInit ) { + char evname[EVENT_NAME_LENGTH]; + struct event_data *ev; + + snprintf(evname, ARRAYLENGTH(evname), "%s::OnInit", nd->exname); + + if( ( ev = (struct event_data*)strdb_get(ev_db, evname) ) ) { + + //Execute OnInit + run_script(nd->u.scr.script,ev->pos,0,nd->bl.id); + + } + } + + return end; } /// Duplicate a warp, shop, cashshop or script. [Orcao] @@ -2404,426 +2485,440 @@ static const char *npc_parse_script(char *w1, char *w2, char *w3, char *w4, cons /// shop/cashshop/npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id> /// npc: -%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY> /// npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY> -const char *npc_parse_duplicate(char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath) -{ - int x, y, dir, m, xs = -1, ys = -1, class_ = 0; - char mapname[32]; - char srcname[128]; - int i; - const char *end; - size_t length; - - int src_id; - int type; - struct npc_data *nd; - struct npc_data *dnd; - - end = strchr(start,'\n'); - length = strlen(w2); - - // get the npc being duplicated - if (w2[length-1] != ')' || length <= 11 || length-11 >= sizeof(srcname)) { - // does not match 'duplicate(%127s)', name is empty or too long - ShowError("npc_parse_script: bad duplicate name in file '%s', line '%d' : %s\n", filepath, strline(buffer,start-buffer), w2); - return end;// next line, try to continue - } - safestrncpy(srcname, w2+10, length-10); - - dnd = npc_name2id(srcname); - if (dnd == NULL) { - ShowError("npc_parse_script: original npc not found for duplicate in file '%s', line '%d' : %s\n", filepath, strline(buffer,start-buffer), srcname); - return end;// next line, try to continue - } - src_id = dnd->bl.id; - type = dnd->subtype; - - // get placement - if ((type==SHOP || type==CASHSHOP || type==SCRIPT) && strcmp(w1, "-") == 0) { - // floating shop/chashshop/script - x = y = dir = 0; - m = -1; - } else { - if (sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4) { // <map name>,<x>,<y>,<facing> - ShowError("npc_parse_duplicate: Invalid placement format for duplicate in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - return end;// next line, try to continue - } - m = map_mapname2mapid(mapname); - } - - if (type == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2); // <spanx>,<spany> - else if (type == SCRIPT && sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3);// <sprite id>,<triggerX>,<triggerY> - else if (type != WARP) class_ = atoi(w4); // <sprite id> - else { - ShowError("npc_parse_duplicate: Invalid span format for duplicate warp in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - return end;// next line, try to continue - } - - CREATE(nd, struct npc_data, 1); - - nd->bl.prev = nd->bl.next = NULL; - nd->bl.m = m; - nd->bl.x = x; - nd->bl.y = y; - npc_parsename(nd, w3, start, buffer, filepath); - nd->bl.id = npc_get_new_npc_id(); - nd->class_ = class_; - nd->speed = 200; - nd->src_id = src_id; - nd->bl.type = BL_NPC; - nd->subtype = (enum npc_subtype)type; - switch (type) { - case SCRIPT: - ++npc_script; - nd->u.scr.xs = xs; - nd->u.scr.ys = ys; - nd->u.scr.script = dnd->u.scr.script; - nd->u.scr.label_list = dnd->u.scr.label_list; - nd->u.scr.label_list_num = dnd->u.scr.label_list_num; - break; - - case SHOP: - case CASHSHOP: - ++npc_shop; - nd->u.shop.shop_item = dnd->u.shop.shop_item; - nd->u.shop.count = dnd->u.shop.count; - break; - - case WARP: - ++npc_warp; - if (!battle_config.warp_point_debug) - nd->class_ = WARP_CLASS; - else - nd->class_ = WARP_DEBUG_CLASS; - nd->u.warp.xs = xs; - nd->u.warp.ys = ys; - nd->u.warp.mapindex = dnd->u.warp.mapindex; - nd->u.warp.x = dnd->u.warp.x; - nd->u.warp.y = dnd->u.warp.y; - break; - } - - //Add the npc to its location - if (m >= 0) { - map_addnpc(m, nd); - status_change_init(&nd->bl); - unit_dataset(&nd->bl); - nd->ud.dir = dir; - npc_setcells(nd); - map_addblock(&nd->bl); - if (class_ >= 0) { - status_set_viewdata(&nd->bl, nd->class_); - if (map[nd->bl.m].users) - clif_spawn(&nd->bl); - } - } else { - // we skip map_addnpc, but still add it to the list of ID's - map_addiddb(&nd->bl); - } - strdb_put(npcname_db, nd->exname, nd); - - if (type != SCRIPT) - return end; - - //----------------------------------------- - // Loop through labels to export them as necessary - for (i = 0; i < nd->u.scr.label_list_num; i++) { - if (npc_event_export(nd, i)) { - ShowWarning("npc_parse_duplicate : duplicate event %s::%s (%s)\n", - nd->exname, nd->u.scr.label_list[i].name, filepath); - } - npc_timerevent_export(nd, i); - } - - nd->u.scr.timerid = INVALID_TIMER; - - return end; +const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) +{ + int x, y, dir, m, xs = -1, ys = -1, class_ = 0; + char mapname[32]; + char srcname[128]; + int i; + const char* end; + size_t length; + + int src_id; + int type; + struct npc_data* nd; + struct npc_data* dnd; + + end = strchr(start,'\n'); + length = strlen(w2); + + // get the npc being duplicated + if( w2[length-1] != ')' || length <= 11 || length-11 >= sizeof(srcname) ) + {// does not match 'duplicate(%127s)', name is empty or too long + ShowError("npc_parse_script: bad duplicate name in file '%s', line '%d' : %s\n", filepath, strline(buffer,start-buffer), w2); + return end;// next line, try to continue + } + safestrncpy(srcname, w2+10, length-10); + + dnd = npc_name2id(srcname); + if( dnd == NULL) { + ShowError("npc_parse_script: original npc not found for duplicate in file '%s', line '%d' : %s\n", filepath, strline(buffer,start-buffer), srcname); + return end;// next line, try to continue + } + src_id = dnd->bl.id; + type = dnd->subtype; + + // get placement + if( (type==SHOP || type==CASHSHOP || type==SCRIPT) && strcmp(w1, "-") == 0 ) + {// floating shop/chashshop/script + x = y = dir = 0; + m = -1; + } + else + { + if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 )// <map name>,<x>,<y>,<facing> + { + ShowError("npc_parse_duplicate: Invalid placement format for duplicate in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + return end;// next line, try to continue + } + m = map_mapname2mapid(mapname); + } + + if( type == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2 );// <spanx>,<spany> + else if( type == SCRIPT && sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3);// <sprite id>,<triggerX>,<triggerY> + else if( type != WARP ) class_ = atoi(w4);// <sprite id> + else + { + ShowError("npc_parse_duplicate: Invalid span format for duplicate warp in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + return end;// next line, try to continue + } + + CREATE(nd, struct npc_data, 1); + + nd->bl.prev = nd->bl.next = NULL; + nd->bl.m = m; + nd->bl.x = x; + nd->bl.y = y; + npc_parsename(nd, w3, start, buffer, filepath); + nd->bl.id = npc_get_new_npc_id(); + nd->class_ = class_; + nd->speed = 200; + nd->src_id = src_id; + nd->bl.type = BL_NPC; + nd->subtype = (enum npc_subtype)type; + switch( type ) + { + case SCRIPT: + ++npc_script; + nd->u.scr.xs = xs; + nd->u.scr.ys = ys; + nd->u.scr.script = dnd->u.scr.script; + nd->u.scr.label_list = dnd->u.scr.label_list; + nd->u.scr.label_list_num = dnd->u.scr.label_list_num; + break; + + case SHOP: + case CASHSHOP: + ++npc_shop; + nd->u.shop.shop_item = dnd->u.shop.shop_item; + nd->u.shop.count = dnd->u.shop.count; + break; + + case WARP: + ++npc_warp; + if( !battle_config.warp_point_debug ) + nd->class_ = WARP_CLASS; + else + nd->class_ = WARP_DEBUG_CLASS; + nd->u.warp.xs = xs; + nd->u.warp.ys = ys; + nd->u.warp.mapindex = dnd->u.warp.mapindex; + nd->u.warp.x = dnd->u.warp.x; + nd->u.warp.y = dnd->u.warp.y; + break; + } + + //Add the npc to its location + if( m >= 0 ) + { + map_addnpc(m, nd); + status_change_init(&nd->bl); + unit_dataset(&nd->bl); + nd->ud.dir = dir; + npc_setcells(nd); + map_addblock(&nd->bl); + if( class_ >= 0 ) + { + status_set_viewdata(&nd->bl, nd->class_); + if( map[nd->bl.m].users ) + clif_spawn(&nd->bl); + } + } + else + { + // we skip map_addnpc, but still add it to the list of ID's + map_addiddb(&nd->bl); + } + strdb_put(npcname_db, nd->exname, nd); + + if( type != SCRIPT ) + return end; + + //----------------------------------------- + // Loop through labels to export them as necessary + for (i = 0; i < nd->u.scr.label_list_num; i++) { + if (npc_event_export(nd, i)) { + ShowWarning("npc_parse_duplicate : duplicate event %s::%s (%s)\n", + nd->exname, nd->u.scr.label_list[i].name, filepath); + } + npc_timerevent_export(nd, i); + } + + nd->u.scr.timerid = INVALID_TIMER; + + return end; +} + +int npc_duplicate4instance(struct npc_data *snd, int m) { + char newname[NAME_LENGTH]; + + if( map[m].instance_id == 0 ) + return 1; + + snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", map[m].instance_id, snd->bl.id); + if( npc_name2id(newname) != NULL ) + { // Name already in use + ShowError("npc_duplicate4instance: the npcname (%s) is already in use while trying to duplicate npc %s in instance %d.\n", newname, snd->exname, map[m].instance_id); + return 1; + } + + if( snd->subtype == WARP ) + { // Adjust destination, if instanced + struct npc_data *wnd = NULL; // New NPC + int dm = map_mapindex2mapid(snd->u.warp.mapindex), im; + if( dm < 0 ) return 1; + + im = instance_mapid2imapid(dm, map[m].instance_id); + if( im == -1 ) + { + ShowError("npc_duplicate4instance: warp (%s) leading to instanced map (%s), but instance map is not attached to current instance.\n", map[dm].name, snd->exname); + return 1; + } + + CREATE(wnd, struct npc_data, 1); + wnd->bl.id = npc_get_new_npc_id(); + map_addnpc(m, wnd); + wnd->bl.prev = wnd->bl.next = NULL; + wnd->bl.m = m; + wnd->bl.x = snd->bl.x; + wnd->bl.y = snd->bl.y; + safestrncpy(wnd->name, "", ARRAYLENGTH(wnd->name)); + safestrncpy(wnd->exname, newname, ARRAYLENGTH(wnd->exname)); + wnd->class_ = WARP_CLASS; + wnd->speed = 200; + wnd->u.warp.mapindex = map_id2index(im); + wnd->u.warp.x = snd->u.warp.x; + wnd->u.warp.y = snd->u.warp.y; + wnd->u.warp.xs = snd->u.warp.xs; + wnd->u.warp.ys = snd->u.warp.ys; + wnd->bl.type = BL_NPC; + wnd->subtype = WARP; + npc_setcells(wnd); + map_addblock(&wnd->bl); + status_set_viewdata(&wnd->bl, wnd->class_); + status_change_init(&wnd->bl); + unit_dataset(&wnd->bl); + if( map[wnd->bl.m].users ) + clif_spawn(&wnd->bl); + strdb_put(npcname_db, wnd->exname, wnd); + } + else + { + static char w1[50], w2[50], w3[50], w4[50]; + const char* stat_buf = "- call from instancing subsystem -\n"; + + snprintf(w1, sizeof(w1), "%s,%d,%d,%d", map[m].name, snd->bl.x, snd->bl.y, snd->ud.dir); + snprintf(w2, sizeof(w2), "duplicate(%s)", snd->exname); + snprintf(w3, sizeof(w3), "%s::%s", snd->name, newname); + + if( snd->u.scr.xs >= 0 && snd->u.scr.ys >= 0 ) + snprintf(w4, sizeof(w4), "%d,%d,%d", snd->class_, snd->u.scr.xs, snd->u.scr.ys); // Touch Area + else + snprintf(w4, sizeof(w4), "%d", snd->class_); + + npc_parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING"); + } + + return 0; } -int npc_duplicate4instance(struct npc_data *snd, int m) +//Set mapcell CELL_NPC to trigger event later +void npc_setcells(struct npc_data* nd) { - char newname[NAME_LENGTH]; + int m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; + int i,j; - if (map[m].instance_id == 0) - return 1; + switch(nd->subtype) + { + case WARP: + xs = nd->u.warp.xs; + ys = nd->u.warp.ys; + break; + case SCRIPT: + xs = nd->u.scr.xs; + ys = nd->u.scr.ys; + break; + default: + return; // Other types doesn't have touch area + } - snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", map[m].instance_id, snd->bl.id); - if (npc_name2id(newname) != NULL) { - // Name already in use - ShowError("npc_duplicate4instance: the npcname (%s) is already in use while trying to duplicate npc %s in instance %d.\n", newname, snd->exname, map[m].instance_id); - return 1; - } + if (m < 0 || xs < 0 || ys < 0) //invalid range or map + return; - if (snd->subtype == WARP) { - // Adjust destination, if instanced - struct npc_data *wnd = NULL; // New NPC - int dm = map_mapindex2mapid(snd->u.warp.mapindex), im; - if (dm < 0) return 1; - - im = instance_mapid2imapid(dm, map[m].instance_id); - if (im == -1) { - ShowError("npc_duplicate4instance: warp (%s) leading to instanced map (%s), but instance map is not attached to current instance.\n", map[dm].name, snd->exname); - return 1; - } - - CREATE(wnd, struct npc_data, 1); - wnd->bl.id = npc_get_new_npc_id(); - map_addnpc(m, wnd); - wnd->bl.prev = wnd->bl.next = NULL; - wnd->bl.m = m; - wnd->bl.x = snd->bl.x; - wnd->bl.y = snd->bl.y; - safestrncpy(wnd->name, "", ARRAYLENGTH(wnd->name)); - safestrncpy(wnd->exname, newname, ARRAYLENGTH(wnd->exname)); - wnd->class_ = WARP_CLASS; - wnd->speed = 200; - wnd->u.warp.mapindex = map_id2index(im); - wnd->u.warp.x = snd->u.warp.x; - wnd->u.warp.y = snd->u.warp.y; - wnd->u.warp.xs = snd->u.warp.xs; - wnd->u.warp.ys = snd->u.warp.ys; - wnd->bl.type = BL_NPC; - wnd->subtype = WARP; - npc_setcells(wnd); - map_addblock(&wnd->bl); - status_set_viewdata(&wnd->bl, wnd->class_); - status_change_init(&wnd->bl); - unit_dataset(&wnd->bl); - if (map[wnd->bl.m].users) - clif_spawn(&wnd->bl); - strdb_put(npcname_db, wnd->exname, wnd); - } else { - static char w1[50], w2[50], w3[50], w4[50]; - const char *stat_buf = "- call from instancing subsystem -\n"; - - snprintf(w1, sizeof(w1), "%s,%d,%d,%d", map[m].name, snd->bl.x, snd->bl.y, snd->ud.dir); - snprintf(w2, sizeof(w2), "duplicate(%s)", snd->exname); - snprintf(w3, sizeof(w3), "%s::%s", snd->name, newname); - - if (snd->u.scr.xs >= 0 && snd->u.scr.ys >= 0) - snprintf(w4, sizeof(w4), "%d,%d,%d", snd->class_, snd->u.scr.xs, snd->u.scr.ys); // Touch Area - else - snprintf(w4, sizeof(w4), "%d", snd->class_); - - npc_parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING"); - } - - return 0; + for (i = y-ys; i <= y+ys; i++) { + for (j = x-xs; j <= x+xs; j++) { + if (map_getcell(m, j, i, CELL_CHKNOPASS)) + continue; + map_setcell(m, j, i, CELL_NPC, true); + } + } } -//Set mapcell CELL_NPC to trigger event later -void npc_setcells(struct npc_data *nd) -{ - int m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; - int i,j; - - switch (nd->subtype) { - case WARP: - xs = nd->u.warp.xs; - ys = nd->u.warp.ys; - break; - case SCRIPT: - xs = nd->u.scr.xs; - ys = nd->u.scr.ys; - break; - default: - return; // Other types doesn't have touch area - } - - if (m < 0 || xs < 0 || ys < 0) //invalid range or map - return; - - for (i = y-ys; i <= y+ys; i++) { - for (j = x-xs; j <= x+xs; j++) { - if (map_getcell(m, j, i, CELL_CHKNOPASS)) - continue; - map_setcell(m, j, i, CELL_NPC, true); - } - } -} - -int npc_unsetcells_sub(struct block_list *bl, va_list ap) +int npc_unsetcells_sub(struct block_list* bl, va_list ap) { - struct npc_data *nd = (struct npc_data *)bl; - int id = va_arg(ap,int); - if (nd->bl.id == id) return 0; - npc_setcells(nd); - return 1; + struct npc_data *nd = (struct npc_data*)bl; + int id = va_arg(ap,int); + if (nd->bl.id == id) return 0; + npc_setcells(nd); + return 1; } -void npc_unsetcells(struct npc_data *nd) +void npc_unsetcells(struct npc_data* nd) { - int m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; - int i,j, x0, x1, y0, y1; + int m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; + int i,j, x0, x1, y0, y1; - if (nd->subtype == WARP) { - xs = nd->u.warp.xs; - ys = nd->u.warp.ys; - } else { - xs = nd->u.scr.xs; - ys = nd->u.scr.ys; - } + if (nd->subtype == WARP) { + xs = nd->u.warp.xs; + ys = nd->u.warp.ys; + } else { + xs = nd->u.scr.xs; + ys = nd->u.scr.ys; + } - if (m < 0 || xs < 0 || ys < 0) - return; + if (m < 0 || xs < 0 || ys < 0) + return; - //Locate max range on which we can locate npc cells - //FIXME: does this really do what it's supposed to do? [ultramage] - for (x0 = x-xs; x0 > 0 && map_getcell(m, x0, y, CELL_CHKNPC); x0--); - for (x1 = x+xs; x1 < map[m].xs-1 && map_getcell(m, x1, y, CELL_CHKNPC); x1++); - for (y0 = y-ys; y0 > 0 && map_getcell(m, x, y0, CELL_CHKNPC); y0--); - for (y1 = y+ys; y1 < map[m].ys-1 && map_getcell(m, x, y1, CELL_CHKNPC); y1++); + //Locate max range on which we can locate npc cells + //FIXME: does this really do what it's supposed to do? [ultramage] + for(x0 = x-xs; x0 > 0 && map_getcell(m, x0, y, CELL_CHKNPC); x0--); + for(x1 = x+xs; x1 < map[m].xs-1 && map_getcell(m, x1, y, CELL_CHKNPC); x1++); + for(y0 = y-ys; y0 > 0 && map_getcell(m, x, y0, CELL_CHKNPC); y0--); + for(y1 = y+ys; y1 < map[m].ys-1 && map_getcell(m, x, y1, CELL_CHKNPC); y1++); - //Erase this npc's cells - for (i = y-ys; i <= y+ys; i++) - for (j = x-xs; j <= x+xs; j++) - map_setcell(m, j, i, CELL_NPC, false); + //Erase this npc's cells + for (i = y-ys; i <= y+ys; i++) + for (j = x-xs; j <= x+xs; j++) + map_setcell(m, j, i, CELL_NPC, false); - //Re-deploy NPC cells for other nearby npcs. - map_foreachinarea(npc_unsetcells_sub, m, x0, y0, x1, y1, BL_NPC, nd->bl.id); + //Re-deploy NPC cells for other nearby npcs. + map_foreachinarea( npc_unsetcells_sub, m, x0, y0, x1, y1, BL_NPC, nd->bl.id ); } -void npc_movenpc(struct npc_data *nd, int x, int y) +void npc_movenpc(struct npc_data* nd, int x, int y) { - const int m = nd->bl.m; - if (m < 0 || nd->bl.prev == NULL) return; //Not on a map. + const int m = nd->bl.m; + if (m < 0 || nd->bl.prev == NULL) return; //Not on a map. - x = cap_value(x, 0, map[m].xs-1); - y = cap_value(y, 0, map[m].ys-1); + x = cap_value(x, 0, map[m].xs-1); + y = cap_value(y, 0, map[m].ys-1); - map_foreachinrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); - map_moveblock(&nd->bl, x, y, gettick()); - map_foreachinrange(clif_insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); + map_foreachinrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); + map_moveblock(&nd->bl, x, y, gettick()); + map_foreachinrange(clif_insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); } /// Changes the display name of the npc. /// /// @param nd Target npc /// @param newname New display name -void npc_setdisplayname(struct npc_data *nd, const char *newname) +void npc_setdisplayname(struct npc_data* nd, const char* newname) { - nullpo_retv(nd); + nullpo_retv(nd); - safestrncpy(nd->name, newname, sizeof(nd->name)); - if (map[nd->bl.m].users) - clif_charnameack(0, &nd->bl); + safestrncpy(nd->name, newname, sizeof(nd->name)); + if( map[nd->bl.m].users ) + clif_charnameack(0, &nd->bl); } /// Changes the display class of the npc. /// /// @param nd Target npc /// @param class_ New display class -void npc_setclass(struct npc_data *nd, short class_) +void npc_setclass(struct npc_data* nd, short class_) { - nullpo_retv(nd); + nullpo_retv(nd); - if (nd->class_ == class_) - return; + if( nd->class_ == class_ ) + return; - if (map[nd->bl.m].users) - clif_clearunit_area(&nd->bl, CLR_OUTSIGHT);// fade out - nd->class_ = class_; - status_set_viewdata(&nd->bl, class_); - if (map[nd->bl.m].users) - clif_spawn(&nd->bl);// fade in + if( map[nd->bl.m].users ) + clif_clearunit_area(&nd->bl, CLR_OUTSIGHT);// fade out + nd->class_ = class_; + status_set_viewdata(&nd->bl, class_); + if( map[nd->bl.m].users ) + clif_spawn(&nd->bl);// fade in } // @commands (script based) -int npc_do_atcmd_event(struct map_session_data *sd, const char *command, const char *message, const char *eventname) -{ - struct event_data *ev = (struct event_data *)strdb_get(ev_db, eventname); - struct npc_data *nd; - struct script_state *st; - int i = 0, j = 0, k = 0; - char *temp; - - nullpo_ret(sd); - - if (ev == NULL || (nd = ev->nd) == NULL) { - ShowError("npc_event: event not found [%s]\n", eventname); - return 0; - } - - if (sd->npc_id != 0) { // Enqueue the event trigger. - int i; - ARR_FIND(0, MAX_EVENTQUEUE, i, sd->eventqueue[i][0] == '\0'); - if (i < MAX_EVENTQUEUE) { - safestrncpy(sd->eventqueue[i],eventname,50); //Event enqueued. - return 0; - } - - ShowWarning("npc_event: player's event queue is full, can't add event '%s' !\n", eventname); - return 1; - } - - if (ev->nd->sc.option&OPTION_INVISIBLE) { // Disabled npc, shouldn't trigger event. - npc_event_dequeue(sd); - return 2; - } +int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const char* message, const char* eventname) +{ + struct event_data* ev = (struct event_data*)strdb_get(ev_db, eventname); + struct npc_data *nd; + struct script_state *st; + int i = 0, j = 0, k = 0; + char *temp; + + nullpo_ret(sd); + + if( ev == NULL || (nd = ev->nd) == NULL ) { + ShowError("npc_event: event not found [%s]\n", eventname); + return 0; + } + + if( sd->npc_id != 0 ) { // Enqueue the event trigger. + int i; + ARR_FIND( 0, MAX_EVENTQUEUE, i, sd->eventqueue[i][0] == '\0' ); + if( i < MAX_EVENTQUEUE ) { + safestrncpy(sd->eventqueue[i],eventname,50); //Event enqueued. + return 0; + } + + ShowWarning("npc_event: player's event queue is full, can't add event '%s' !\n", eventname); + return 1; + } + + if( ev->nd->sc.option&OPTION_INVISIBLE ) { // Disabled npc, shouldn't trigger event. + npc_event_dequeue(sd); + return 2; + } + + st = script_alloc_state(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id); + setd_sub(st, NULL, ".@atcmd_command$", 0, (void *)command, NULL); + + // split atcmd parameters based on spaces + i = 0; + j = 0; + + temp = (char*)aMalloc(strlen(message) + 1); + + while( message[i] != '\0' ) { + if( message[i] == ' ' && k < 127 ) { + temp[j] = '\0'; + setd_sub(st, NULL, ".@atcmd_parameters$", k++, (void *)temp, NULL); + j = 0; + ++i; + } else + temp[j++] = message[i++]; + } + + temp[j] = '\0'; + setd_sub(st, NULL, ".@atcmd_parameters$", k++, (void *)temp, NULL); + setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)&k, NULL); + aFree(temp); + + run_script_main(st); + return 0; +} - st = script_alloc_state(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id); - setd_sub(st, NULL, ".@atcmd_command$", 0, (void *)command, NULL); +/// Parses a function. +/// function%TAB%script%TAB%<function name>%TAB%{<code>} +static const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) +{ + DBMap* func_db; + DBData old_data; + struct script_code *script; + const char* end; + const char* script_start; - // split atcmd parameters based on spaces - i = 0; - j = 0; + script_start = strstr(start,"\t{"); + end = strchr(start,'\n'); + if( *w4 != '{' || script_start == NULL || (end != NULL && script_start > end) ) + { + ShowError("npc_parse_function: Missing left curly '%%TAB%%{' in file '%s', line '%d'. Skipping the rest of the file.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + return NULL;// can't continue + } + ++script_start; - temp = (char *)aMalloc(strlen(message) + 1); + end = npc_skip_script(script_start,buffer,filepath); + if( end == NULL ) + return NULL;// (simple) parse error, don't continue - while (message[i] != '\0') { - if (message[i] == ' ' && k < 127) { - temp[j] = '\0'; - setd_sub(st, NULL, ".@atcmd_parameters$", k++, (void *)temp, NULL); - j = 0; - ++i; - } else - temp[j++] = message[i++]; - } + script = parse_script(script_start, filepath, strline(buffer,start-buffer), SCRIPT_RETURN_EMPTY_SCRIPT); + if( script == NULL )// parse error, continue + return end; - temp[j] = '\0'; - setd_sub(st, NULL, ".@atcmd_parameters$", k++, (void *)temp, NULL); - setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)&k, NULL); - aFree(temp); + func_db = script_get_userfunc_db(); + if (func_db->put(func_db, db_str2key(w3), db_ptr2data(script), &old_data)) + { + struct script_code *oldscript = (struct script_code*)db_data2ptr(&old_data); + ShowInfo("npc_parse_function: Overwriting user function [%s] (%s:%d)\n", w3, filepath, strline(buffer,start-buffer)); + script_free_vars(oldscript->script_vars); + aFree(oldscript->script_buf); + aFree(oldscript); + } - run_script_main(st); - return 0; -} - -/// Parses a function. -/// function%TAB%script%TAB%<function name>%TAB%{<code>} -static const char *npc_parse_function(char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath) -{ - DBMap *func_db; - DBData old_data; - struct script_code *script; - const char *end; - const char *script_start; - - script_start = strstr(start,"\t{"); - end = strchr(start,'\n'); - if (*w4 != '{' || script_start == NULL || (end != NULL && script_start > end)) { - ShowError("npc_parse_function: Missing left curly '%%TAB%%{' in file '%s', line '%d'. Skipping the rest of the file.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - return NULL;// can't continue - } - ++script_start; - - end = npc_skip_script(script_start,buffer,filepath); - if (end == NULL) - return NULL;// (simple) parse error, don't continue - - script = parse_script(script_start, filepath, strline(buffer,start-buffer), SCRIPT_RETURN_EMPTY_SCRIPT); - if (script == NULL) // parse error, continue - return end; - - func_db = script_get_userfunc_db(); - if (func_db->put(func_db, db_str2key(w3), db_ptr2data(script), &old_data)) { - struct script_code *oldscript = (struct script_code *)db_data2ptr(&old_data); - ShowInfo("npc_parse_function: Overwriting user function [%s] (%s:%d)\n", w3, filepath, strline(buffer,start-buffer)); - script_free_vars(oldscript->script_vars); - aFree(oldscript->script_buf); - aFree(oldscript); - } - - return end; + return end; } @@ -2832,806 +2927,867 @@ static const char *npc_parse_function(char *w1, char *w2, char *w3, char *w4, co * Parse Mob 2 - Actually Spawns Mob * [Wizputer] *------------------------------------------*/ -void npc_parse_mob2(struct spawn_data *mob) -{ - int i; - - for (i = mob->active; i < mob->num; ++i) { - struct mob_data *md = mob_spawn_dataset(mob); - md->spawn = mob; - md->spawn->active++; - mob_spawn(md); - } -} - -static const char *npc_parse_mob(char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath) -{ - int num, class_, m,x,y,xs,ys, i,j; - int mob_lv = -1, ai = -1, size = -1; - char mapname[32], mobname[NAME_LENGTH]; - struct spawn_data mob, *data; - struct mob_db *db; - - memset(&mob, 0, sizeof(struct spawn_data)); - - mob.state.boss = !strcmpi(w2,"boss_monster"); - - // w1=<map name>,<x>,<y>,<xs>,<ys> - // w3=<mob name>{,<mob level>} - // w4=<mob id>,<amount>,<delay1>,<delay2>,<event>{,<mob size>,<mob ai>} - if (sscanf(w1, "%31[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 3 - || sscanf(w3, "%23[^,],%d", mobname, &mob_lv) < 1 - || sscanf(w4, "%d,%d,%u,%u,%127[^,],%d,%d[^\t\r\n]", &class_, &num, &mob.delay1, &mob.delay2, mob.eventname, &size, &ai) < 2) { - ShowError("npc_parse_mob: Invalid mob definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - return strchr(start,'\n');// skip and continue - } - if (mapindex_name2id(mapname) == 0) { - ShowError("npc_parse_mob: Unknown map '%s' in file '%s', line '%d'.\n", mapname, filepath, strline(buffer,start-buffer)); - return strchr(start,'\n');// skip and continue - } - m = map_mapname2mapid(mapname); - if (m < 0) //Not loaded on this map-server instance. - return strchr(start,'\n');// skip and continue - mob.m = (unsigned short)m; - - if (x < 0 || x >= map[mob.m].xs || y < 0 || y >= map[mob.m].ys) { - ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s (file '%s', line '%d').\n", map[mob.m].name, x, y, (map[mob.m].xs-1), (map[mob.m].ys-1), w1, w3, filepath, strline(buffer,start-buffer)); - return strchr(start,'\n');// skip and continue - } - - // check monster ID if exists! - if (mobdb_checkid(class_) == 0) { - ShowError("npc_parse_mob: Unknown mob ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer)); - return strchr(start,'\n');// skip and continue - } - - if (num < 1 || num > 1000) { - ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] (file '%s', line '%d').\n", num, filepath, strline(buffer,start-buffer)); - return strchr(start,'\n');// skip and continue - } - - if ((mob.state.size < 0 || mob.state.size > 2) && size != -1) { - ShowError("npc_parse_mob: Invalid size number %d for mob ID %d (file '%s', line '%d').\n", mob.state.size, class_, filepath, strline(buffer, start - buffer)); - return strchr(start, '\n'); - } - - if ((mob.state.ai < 0 || mob.state.ai > 4) && ai != -1) { - ShowError("npc_parse_mob: Invalid ai %d for mob ID %d (file '%s', line '%d').\n", mob.state.ai, class_, filepath, strline(buffer, start - buffer)); - return strchr(start, '\n'); - } - - if ((mob_lv == 0 || mob_lv > MAX_LEVEL) && mob_lv != -1) { - ShowError("npc_parse_mob: Invalid level %d for mob ID %d (file '%s', line '%d').\n", mob_lv, class_, filepath, strline(buffer, start - buffer)); - return strchr(start, '\n'); - } - - mob.num = (unsigned short)num; - mob.active = 0; - mob.class_ = (short) class_; - mob.x = (unsigned short)x; - mob.y = (unsigned short)y; - mob.xs = (signed short)xs; - mob.ys = (signed short)ys; - if (mob_lv > 0 && mob_lv <= MAX_LEVEL) - mob.level = mob_lv; - if (size > 0 && size <= 2) - mob.state.size = size; - if (ai > 0 && ai <= 4) - mob.state.ai = ai; - - if (mob.num > 1 && battle_config.mob_count_rate != 100) { - if ((mob.num = mob.num * battle_config.mob_count_rate / 100) < 1) - mob.num = 1; - } - - if (battle_config.force_random_spawn || (mob.x == 0 && mob.y == 0)) { - //Force a random spawn anywhere on the map. - mob.x = mob.y = 0; - mob.xs = mob.ys = -1; - } - - if (mob.delay1>0xfffffff || mob.delay2>0xfffffff) { - ShowError("npc_parse_mob: Invalid spawn delays %u %u (file '%s', line '%d').\n", mob.delay1, mob.delay2, filepath, strline(buffer,start-buffer)); - return strchr(start,'\n');// skip and continue - } - - //Use db names instead of the spawn file ones. - if (battle_config.override_mob_names==1) - strcpy(mob.name,"--en--"); - else if (battle_config.override_mob_names==2) - strcpy(mob.name,"--ja--"); - else - safestrncpy(mob.name, mobname, sizeof(mob.name)); - - //Verify dataset. - if (!mob_parse_dataset(&mob)) { - ShowError("npc_parse_mob: Invalid dataset for monster ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer)); - return strchr(start,'\n');// skip and continue - } - - //Update mob spawn lookup database - db = mob_db(class_); - for (i = 0; i < ARRAYLENGTH(db->spawn); ++i) { - if (map[mob.m].index == db->spawn[i].mapindex) { - //Update total - db->spawn[i].qty += mob.num; - //Re-sort list - for (j = i; j > 0 && db->spawn[j-1].qty < db->spawn[i].qty; --j); - if (j != i) { - xs = db->spawn[i].mapindex; - ys = db->spawn[i].qty; - memmove(&db->spawn[j+1], &db->spawn[j], (i-j)*sizeof(db->spawn[0])); - db->spawn[j].mapindex = xs; - db->spawn[j].qty = ys; - } - break; - } - if (mob.num > db->spawn[i].qty) { - //Insert into list - memmove(&db->spawn[i+1], &db->spawn[i], sizeof(db->spawn) -(i+1)*sizeof(db->spawn[0])); - db->spawn[i].mapindex = map[mob.m].index; - db->spawn[i].qty = mob.num; - break; - } - } - - //Now that all has been validated. We allocate the actual memory that the re-spawn data will use. - data = (struct spawn_data *)aMalloc(sizeof(struct spawn_data)); - memcpy(data, &mob, sizeof(struct spawn_data)); - - // spawn / cache the new mobs - if (battle_config.dynamic_mobs && map_addmobtolist(data->m, data) >= 0) { - data->state.dynamic = true; - npc_cache_mob += data->num; - - // check if target map has players - // (usually shouldn't occur when map server is just starting, - // but not the case when we do @reloadscript - if (map[data->m].users > 0) - npc_parse_mob2(data); - } else { - data->state.dynamic = false; - npc_parse_mob2(data); - npc_delay_mob += data->num; - } - - npc_mob++; - - return strchr(start,'\n');// continue +void npc_parse_mob2(struct spawn_data* mob) +{ + int i; + + for( i = mob->active; i < mob->num; ++i ) + { + struct mob_data* md = mob_spawn_dataset(mob); + md->spawn = mob; + md->spawn->active++; + mob_spawn(md); + } +} + +static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) +{ + int num, class_, m,x,y,xs,ys, i,j; + int mob_lv = -1, ai = -1, size = -1; + char mapname[32], mobname[NAME_LENGTH]; + struct spawn_data mob, *data; + struct mob_db* db; + + memset(&mob, 0, sizeof(struct spawn_data)); + + mob.state.boss = !strcmpi(w2,"boss_monster"); + + // w1=<map name>,<x>,<y>,<xs>,<ys> + // w3=<mob name>{,<mob level>} + // w4=<mob id>,<amount>,<delay1>,<delay2>,<event>{,<mob size>,<mob ai>} + if( sscanf(w1, "%31[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 3 + || sscanf(w3, "%23[^,],%d", mobname, &mob_lv) < 1 + || sscanf(w4, "%d,%d,%u,%u,%127[^,],%d,%d[^\t\r\n]", &class_, &num, &mob.delay1, &mob.delay2, mob.eventname, &size, &ai) < 2 ) + { + ShowError("npc_parse_mob: Invalid mob definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + return strchr(start,'\n');// skip and continue + } + if( mapindex_name2id(mapname) == 0 ) + { + ShowError("npc_parse_mob: Unknown map '%s' in file '%s', line '%d'.\n", mapname, filepath, strline(buffer,start-buffer)); + return strchr(start,'\n');// skip and continue + } + m = map_mapname2mapid(mapname); + if( m < 0 )//Not loaded on this map-server instance. + return strchr(start,'\n');// skip and continue + mob.m = (unsigned short)m; + + if( x < 0 || x >= map[mob.m].xs || y < 0 || y >= map[mob.m].ys ) + { + ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s (file '%s', line '%d').\n", map[mob.m].name, x, y, (map[mob.m].xs-1), (map[mob.m].ys-1), w1, w3, filepath, strline(buffer,start-buffer)); + return strchr(start,'\n');// skip and continue + } + + // check monster ID if exists! + if( mobdb_checkid(class_) == 0 ) + { + ShowError("npc_parse_mob: Unknown mob ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer)); + return strchr(start,'\n');// skip and continue + } + + if( num < 1 || num > 1000 ) + { + ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] (file '%s', line '%d').\n", num, filepath, strline(buffer,start-buffer)); + return strchr(start,'\n');// skip and continue + } + + if( (mob.state.size < 0 || mob.state.size > 2) && size != -1 ) + { + ShowError("npc_parse_mob: Invalid size number %d for mob ID %d (file '%s', line '%d').\n", mob.state.size, class_, filepath, strline(buffer, start - buffer)); + return strchr(start, '\n'); + } + + if( (mob.state.ai < 0 || mob.state.ai > 4) && ai != -1 ) + { + ShowError("npc_parse_mob: Invalid ai %d for mob ID %d (file '%s', line '%d').\n", mob.state.ai, class_, filepath, strline(buffer, start - buffer)); + return strchr(start, '\n'); + } + + if( (mob_lv == 0 || mob_lv > MAX_LEVEL) && mob_lv != -1 ) + { + ShowError("npc_parse_mob: Invalid level %d for mob ID %d (file '%s', line '%d').\n", mob_lv, class_, filepath, strline(buffer, start - buffer)); + return strchr(start, '\n'); + } + + mob.num = (unsigned short)num; + mob.active = 0; + mob.class_ = (short) class_; + mob.x = (unsigned short)x; + mob.y = (unsigned short)y; + mob.xs = (signed short)xs; + mob.ys = (signed short)ys; + if (mob_lv > 0 && mob_lv <= MAX_LEVEL) + mob.level = mob_lv; + if (size > 0 && size <= 2) + mob.state.size = size; + if (ai > 0 && ai <= 4) + mob.state.ai = ai; + + if (mob.num > 1 && battle_config.mob_count_rate != 100) { + if ((mob.num = mob.num * battle_config.mob_count_rate / 100) < 1) + mob.num = 1; + } + + if (battle_config.force_random_spawn || (mob.x == 0 && mob.y == 0)) + { //Force a random spawn anywhere on the map. + mob.x = mob.y = 0; + mob.xs = mob.ys = -1; + } + + if(mob.delay1>0xfffffff || mob.delay2>0xfffffff) { + ShowError("npc_parse_mob: Invalid spawn delays %u %u (file '%s', line '%d').\n", mob.delay1, mob.delay2, filepath, strline(buffer,start-buffer)); + return strchr(start,'\n');// skip and continue + } + + //Use db names instead of the spawn file ones. + if(battle_config.override_mob_names==1) + strcpy(mob.name,"--en--"); + else if (battle_config.override_mob_names==2) + strcpy(mob.name,"--ja--"); + else + safestrncpy(mob.name, mobname, sizeof(mob.name)); + + //Verify dataset. + if( !mob_parse_dataset(&mob) ) + { + ShowError("npc_parse_mob: Invalid dataset for monster ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer)); + return strchr(start,'\n');// skip and continue + } + + //Update mob spawn lookup database + db = mob_db(class_); + for( i = 0; i < ARRAYLENGTH(db->spawn); ++i ) + { + if (map[mob.m].index == db->spawn[i].mapindex) + { //Update total + db->spawn[i].qty += mob.num; + //Re-sort list + for( j = i; j > 0 && db->spawn[j-1].qty < db->spawn[i].qty; --j ); + if( j != i ) + { + xs = db->spawn[i].mapindex; + ys = db->spawn[i].qty; + memmove(&db->spawn[j+1], &db->spawn[j], (i-j)*sizeof(db->spawn[0])); + db->spawn[j].mapindex = xs; + db->spawn[j].qty = ys; + } + break; + } + if (mob.num > db->spawn[i].qty) + { //Insert into list + memmove(&db->spawn[i+1], &db->spawn[i], sizeof(db->spawn) -(i+1)*sizeof(db->spawn[0])); + db->spawn[i].mapindex = map[mob.m].index; + db->spawn[i].qty = mob.num; + break; + } + } + + //Now that all has been validated. We allocate the actual memory that the re-spawn data will use. + data = (struct spawn_data*)aMalloc(sizeof(struct spawn_data)); + memcpy(data, &mob, sizeof(struct spawn_data)); + + // spawn / cache the new mobs + if( battle_config.dynamic_mobs && map_addmobtolist(data->m, data) >= 0 ) + { + data->state.dynamic = true; + npc_cache_mob += data->num; + + // check if target map has players + // (usually shouldn't occur when map server is just starting, + // but not the case when we do @reloadscript + if( map[data->m].users > 0 ) + npc_parse_mob2(data); + } + else + { + data->state.dynamic = false; + npc_parse_mob2(data); + npc_delay_mob += data->num; + } + + npc_mob++; + + return strchr(start,'\n');// continue } /*========================================== * Set or disable mapflag on map - * eg : bat_c01 mapflag battleground 2 + * eg : bat_c01 mapflag battleground 2 * also chking if mapflag conflict with another *------------------------------------------*/ -static const char *npc_parse_mapflag(char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath) -{ - int m; - char mapname[32]; - int state = 1; - - // w1=<mapname> - if (sscanf(w1, "%31[^,]", mapname) != 1) { - ShowError("npc_parse_mapflag: Invalid mapflag definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - return strchr(start,'\n');// skip and continue - } - m = map_mapname2mapid(mapname); - if (m < 0) { - ShowWarning("npc_parse_mapflag: Unknown map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", mapname, filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - return strchr(start,'\n');// skip and continue - } - - if (w4 && !strcmpi(w4, "off")) - state = 0; //Disable mapflag rather than enable it. [Skotlex] - - if (!strcmpi(w3, "nosave")) { - char savemap[32]; - int savex, savey; - if (state == 0) - ; //Map flag disabled. - else if (!strcmpi(w4, "SavePoint")) { - map[m].save.map = 0; - map[m].save.x = -1; - map[m].save.y = -1; - } else if (sscanf(w4, "%31[^,],%d,%d", savemap, &savex, &savey) == 3) { - map[m].save.map = mapindex_name2id(savemap); - map[m].save.x = savex; - map[m].save.y = savey; - if (!map[m].save.map) { - ShowWarning("npc_parse_mapflag: Specified save point map '%s' for mapflag 'nosave' not found (file '%s', line '%d'), using 'SavePoint'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", savemap, filepath, strline(buffer,start-buffer), w1, w2, w3, w4); - map[m].save.x = -1; - map[m].save.y = -1; - } - } - map[m].flag.nosave = state; - } else if (!strcmpi(w3,"autotrade")) - map[m].flag.autotrade=state; - else if (!strcmpi(w3,"allowks")) - map[m].flag.allowks=state; // [Kill Steal Protection] - else if (!strcmpi(w3,"town")) - map[m].flag.town=state; - else if (!strcmpi(w3,"nomemo")) - map[m].flag.nomemo=state; - else if (!strcmpi(w3,"noteleport")) - map[m].flag.noteleport=state; - else if (!strcmpi(w3,"nowarp")) - map[m].flag.nowarp=state; - else if (!strcmpi(w3,"nowarpto")) - map[m].flag.nowarpto=state; - else if (!strcmpi(w3,"noreturn")) - map[m].flag.noreturn=state; - else if (!strcmpi(w3,"monster_noteleport")) - map[m].flag.monster_noteleport=state; - else if (!strcmpi(w3,"nobranch")) - map[m].flag.nobranch=state; - else if (!strcmpi(w3,"nopenalty")) { - map[m].flag.noexppenalty=state; - map[m].flag.nozenypenalty=state; - } else if (!strcmpi(w3,"pvp")) { - map[m].flag.pvp = state; - if (state && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle)) { - map[m].flag.gvg = 0; - map[m].flag.gvg_dungeon = 0; - map[m].flag.gvg_castle = 0; - ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); - } - if (state && map[m].flag.battleground) { - map[m].flag.battleground = 0; - ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); - } - } else if (!strcmpi(w3,"pvp_noparty")) - map[m].flag.pvp_noparty=state; - else if (!strcmpi(w3,"pvp_noguild")) - map[m].flag.pvp_noguild=state; - else if (!strcmpi(w3, "pvp_nightmaredrop")) { - char drop_arg1[16], drop_arg2[16]; - int drop_id = 0, drop_type = 0, drop_per = 0; - if (sscanf(w4, "%[^,],%[^,],%d", drop_arg1, drop_arg2, &drop_per) == 3) { - int i; - if (!strcmpi(drop_arg1, "random")) - drop_id = -1; - else if (itemdb_exists((drop_id = atoi(drop_arg1))) == NULL) - drop_id = 0; - if (!strcmpi(drop_arg2, "inventory")) - drop_type = 1; - else if (!strcmpi(drop_arg2,"equip")) - drop_type = 2; - else if (!strcmpi(drop_arg2,"all")) - drop_type = 3; - - if (drop_id != 0) { - for (i = 0; i < MAX_DROP_PER_MAP; i++) { - if (map[m].drop_list[i].drop_id == 0) { - map[m].drop_list[i].drop_id = drop_id; - map[m].drop_list[i].drop_type = drop_type; - map[m].drop_list[i].drop_per = drop_per; - break; - } - } - map[m].flag.pvp_nightmaredrop = 1; - } - } else if (!state) //Disable - map[m].flag.pvp_nightmaredrop = 0; - } else if (!strcmpi(w3,"pvp_nocalcrank")) - map[m].flag.pvp_nocalcrank=state; - else if (!strcmpi(w3,"gvg")) { - map[m].flag.gvg = state; - if (state && map[m].flag.pvp) { - map[m].flag.pvp = 0; - ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); - } - if (state && map[m].flag.battleground) { - map[m].flag.battleground = 0; - ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); - } - } else if (!strcmpi(w3,"gvg_noparty")) - map[m].flag.gvg_noparty=state; - else if (!strcmpi(w3,"gvg_dungeon")) { - map[m].flag.gvg_dungeon=state; - if (state) map[m].flag.pvp=0; - } else if (!strcmpi(w3,"gvg_castle")) { - map[m].flag.gvg_castle=state; - if (state) map[m].flag.pvp=0; - } else if (!strcmpi(w3,"battleground")) { - if (state) { - if (sscanf(w4, "%d", &state) == 1) - map[m].flag.battleground = state; - else - map[m].flag.battleground = 1; // Default value - } else - map[m].flag.battleground = 0; - - if (map[m].flag.battleground && map[m].flag.pvp) { - map[m].flag.pvp = 0; - ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); - } - if (map[m].flag.battleground && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle)) { - map[m].flag.gvg = 0; - map[m].flag.gvg_dungeon = 0; - map[m].flag.gvg_castle = 0; - ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); - } - } else if (!strcmpi(w3,"noexppenalty")) - map[m].flag.noexppenalty=state; - else if (!strcmpi(w3,"nozenypenalty")) - map[m].flag.nozenypenalty=state; - else if (!strcmpi(w3,"notrade")) - map[m].flag.notrade=state; - else if (!strcmpi(w3,"novending")) - map[m].flag.novending=state; - else if (!strcmpi(w3,"nodrop")) - map[m].flag.nodrop=state; - else if (!strcmpi(w3,"noskill")) - map[m].flag.noskill=state; - else if (!strcmpi(w3,"noicewall")) - map[m].flag.noicewall=state; - else if (!strcmpi(w3,"snow")) - map[m].flag.snow=state; - else if (!strcmpi(w3,"clouds")) - map[m].flag.clouds=state; - else if (!strcmpi(w3,"clouds2")) - map[m].flag.clouds2=state; - else if (!strcmpi(w3,"fog")) - map[m].flag.fog=state; - else if (!strcmpi(w3,"fireworks")) - map[m].flag.fireworks=state; - else if (!strcmpi(w3,"sakura")) - map[m].flag.sakura=state; - else if (!strcmpi(w3,"leaves")) - map[m].flag.leaves=state; - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //else if (!strcmpi(w3,"rain")) - // map[m].flag.rain=state; - else if (!strcmpi(w3,"nightenabled")) - map[m].flag.nightenabled=state; - else if (!strcmpi(w3,"nogo")) - map[m].flag.nogo=state; - else if (!strcmpi(w3,"noexp")) { - map[m].flag.nobaseexp=state; - map[m].flag.nojobexp=state; - } else if (!strcmpi(w3,"nobaseexp")) - map[m].flag.nobaseexp=state; - else if (!strcmpi(w3,"nojobexp")) - map[m].flag.nojobexp=state; - else if (!strcmpi(w3,"noloot")) { - map[m].flag.nomobloot=state; - map[m].flag.nomvploot=state; - } else if (!strcmpi(w3,"nomobloot")) - map[m].flag.nomobloot=state; - else if (!strcmpi(w3,"nomvploot")) - map[m].flag.nomvploot=state; - else if (!strcmpi(w3,"nocommand")) { - if (state) { - if (sscanf(w4, "%d", &state) == 1) - map[m].nocommand =state; - else //No level specified, block everyone. - map[m].nocommand =100; - } else - map[m].nocommand=0; - } else if (!strcmpi(w3,"restricted")) { - if (state) { - map[m].flag.restricted=1; - sscanf(w4, "%d", &state); - map[m].zone |= 1<<(state+1); - } else { - map[m].flag.restricted=0; - map[m].zone = 0; - } - } else if (!strcmpi(w3,"jexp")) { - map[m].jexp = (state) ? atoi(w4) : 100; - if (map[m].jexp < 0) map[m].jexp = 100; - map[m].flag.nojobexp = (map[m].jexp==0)?1:0; - } else if (!strcmpi(w3,"bexp")) { - map[m].bexp = (state) ? atoi(w4) : 100; - if (map[m].bexp < 0) map[m].bexp = 100; - map[m].flag.nobaseexp = (map[m].bexp==0)?1:0; - } else if (!strcmpi(w3,"loadevent")) - map[m].flag.loadevent=state; - else if (!strcmpi(w3,"nochat")) - map[m].flag.nochat=state; - else if (!strcmpi(w3,"partylock")) - map[m].flag.partylock=state; - else if (!strcmpi(w3,"guildlock")) - map[m].flag.guildlock=state; - else if (!strcmpi(w3,"reset")) - map[m].flag.reset=state; - else - ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer)); - - return strchr(start,'\n');// continue +static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) +{ + int m; + char mapname[32]; + int state = 1; + + // w1=<mapname> + if( sscanf(w1, "%31[^,]", mapname) != 1 ) + { + ShowError("npc_parse_mapflag: Invalid mapflag definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + return strchr(start,'\n');// skip and continue + } + m = map_mapname2mapid(mapname); + if( m < 0 ) + { + ShowWarning("npc_parse_mapflag: Unknown map in file '%s', line '%d' : %s\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", mapname, filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + return strchr(start,'\n');// skip and continue + } + + if (w4 && !strcmpi(w4, "off")) + state = 0; //Disable mapflag rather than enable it. [Skotlex] + + if (!strcmpi(w3, "nosave")) { + char savemap[32]; + int savex, savey; + if (state == 0) + ; //Map flag disabled. + else if (!strcmpi(w4, "SavePoint")) { + map[m].save.map = 0; + map[m].save.x = -1; + map[m].save.y = -1; + } else if (sscanf(w4, "%31[^,],%d,%d", savemap, &savex, &savey) == 3) { + map[m].save.map = mapindex_name2id(savemap); + map[m].save.x = savex; + map[m].save.y = savey; + if (!map[m].save.map) { + ShowWarning("npc_parse_mapflag: Specified save point map '%s' for mapflag 'nosave' not found (file '%s', line '%d'), using 'SavePoint'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", savemap, filepath, strline(buffer,start-buffer), w1, w2, w3, w4); + map[m].save.x = -1; + map[m].save.y = -1; + } + } + map[m].flag.nosave = state; + } + else if (!strcmpi(w3,"autotrade")) + map[m].flag.autotrade=state; + else if (!strcmpi(w3,"allowks")) + map[m].flag.allowks=state; // [Kill Steal Protection] + else if (!strcmpi(w3,"town")) + map[m].flag.town=state; + else if (!strcmpi(w3,"nomemo")) + map[m].flag.nomemo=state; + else if (!strcmpi(w3,"noteleport")) + map[m].flag.noteleport=state; + else if (!strcmpi(w3,"nowarp")) + map[m].flag.nowarp=state; + else if (!strcmpi(w3,"nowarpto")) + map[m].flag.nowarpto=state; + else if (!strcmpi(w3,"noreturn")) + map[m].flag.noreturn=state; + else if (!strcmpi(w3,"monster_noteleport")) + map[m].flag.monster_noteleport=state; + else if (!strcmpi(w3,"nobranch")) + map[m].flag.nobranch=state; + else if (!strcmpi(w3,"nopenalty")) { + map[m].flag.noexppenalty=state; + map[m].flag.nozenypenalty=state; + } + else if (!strcmpi(w3,"pvp")) { + map[m].flag.pvp = state; + if( state && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) ) + { + map[m].flag.gvg = 0; + map[m].flag.gvg_dungeon = 0; + map[m].flag.gvg_castle = 0; + ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); + } + if( state && map[m].flag.battleground ) + { + map[m].flag.battleground = 0; + ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); + } + } + else if (!strcmpi(w3,"pvp_noparty")) + map[m].flag.pvp_noparty=state; + else if (!strcmpi(w3,"pvp_noguild")) + map[m].flag.pvp_noguild=state; + else if (!strcmpi(w3, "pvp_nightmaredrop")) { + char drop_arg1[16], drop_arg2[16]; + int drop_id = 0, drop_type = 0, drop_per = 0; + if (sscanf(w4, "%[^,],%[^,],%d", drop_arg1, drop_arg2, &drop_per) == 3) { + int i; + if (!strcmpi(drop_arg1, "random")) + drop_id = -1; + else if (itemdb_exists((drop_id = atoi(drop_arg1))) == NULL) + drop_id = 0; + if (!strcmpi(drop_arg2, "inventory")) + drop_type = 1; + else if (!strcmpi(drop_arg2,"equip")) + drop_type = 2; + else if (!strcmpi(drop_arg2,"all")) + drop_type = 3; + + if (drop_id != 0){ + for (i = 0; i < MAX_DROP_PER_MAP; i++) { + if (map[m].drop_list[i].drop_id == 0){ + map[m].drop_list[i].drop_id = drop_id; + map[m].drop_list[i].drop_type = drop_type; + map[m].drop_list[i].drop_per = drop_per; + break; + } + } + map[m].flag.pvp_nightmaredrop = 1; + } + } else if (!state) //Disable + map[m].flag.pvp_nightmaredrop = 0; + } + else if (!strcmpi(w3,"pvp_nocalcrank")) + map[m].flag.pvp_nocalcrank=state; + else if (!strcmpi(w3,"gvg")) { + map[m].flag.gvg = state; + if( state && map[m].flag.pvp ) + { + map[m].flag.pvp = 0; + ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); + } + if( state && map[m].flag.battleground ) + { + map[m].flag.battleground = 0; + ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); + } + } + else if (!strcmpi(w3,"gvg_noparty")) + map[m].flag.gvg_noparty=state; + else if (!strcmpi(w3,"gvg_dungeon")) { + map[m].flag.gvg_dungeon=state; + if (state) map[m].flag.pvp=0; + } + else if (!strcmpi(w3,"gvg_castle")) { + map[m].flag.gvg_castle=state; + if (state) map[m].flag.pvp=0; + } + else if (!strcmpi(w3,"battleground")) { + if( state ) + { + if( sscanf(w4, "%d", &state) == 1 ) + map[m].flag.battleground = state; + else + map[m].flag.battleground = 1; // Default value + } + else + map[m].flag.battleground = 0; + + if( map[m].flag.battleground && map[m].flag.pvp ) + { + map[m].flag.pvp = 0; + ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); + } + if( map[m].flag.battleground && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) ) + { + map[m].flag.gvg = 0; + map[m].flag.gvg_dungeon = 0; + map[m].flag.gvg_castle = 0; + ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); + } + } + else if (!strcmpi(w3,"noexppenalty")) + map[m].flag.noexppenalty=state; + else if (!strcmpi(w3,"nozenypenalty")) + map[m].flag.nozenypenalty=state; + else if (!strcmpi(w3,"notrade")) + map[m].flag.notrade=state; + else if (!strcmpi(w3,"novending")) + map[m].flag.novending=state; + else if (!strcmpi(w3,"nodrop")) + map[m].flag.nodrop=state; + else if (!strcmpi(w3,"noskill")) + map[m].flag.noskill=state; + else if (!strcmpi(w3,"noicewall")) + map[m].flag.noicewall=state; + else if (!strcmpi(w3,"snow")) + map[m].flag.snow=state; + else if (!strcmpi(w3,"clouds")) + map[m].flag.clouds=state; + else if (!strcmpi(w3,"clouds2")) + map[m].flag.clouds2=state; + else if (!strcmpi(w3,"fog")) + map[m].flag.fog=state; + else if (!strcmpi(w3,"fireworks")) + map[m].flag.fireworks=state; + else if (!strcmpi(w3,"sakura")) + map[m].flag.sakura=state; + else if (!strcmpi(w3,"leaves")) + map[m].flag.leaves=state; + /** + * No longer available, keeping here just in case it's back someday. [Ind] + **/ + //else if (!strcmpi(w3,"rain")) + // map[m].flag.rain=state; + else if (!strcmpi(w3,"nightenabled")) + map[m].flag.nightenabled=state; + else if (!strcmpi(w3,"nogo")) + map[m].flag.nogo=state; + else if (!strcmpi(w3,"noexp")) { + map[m].flag.nobaseexp=state; + map[m].flag.nojobexp=state; + } + else if (!strcmpi(w3,"nobaseexp")) + map[m].flag.nobaseexp=state; + else if (!strcmpi(w3,"nojobexp")) + map[m].flag.nojobexp=state; + else if (!strcmpi(w3,"noloot")) { + map[m].flag.nomobloot=state; + map[m].flag.nomvploot=state; + } + else if (!strcmpi(w3,"nomobloot")) + map[m].flag.nomobloot=state; + else if (!strcmpi(w3,"nomvploot")) + map[m].flag.nomvploot=state; + else if (!strcmpi(w3,"nocommand")) { + if (state) { + if (sscanf(w4, "%d", &state) == 1) + map[m].nocommand =state; + else //No level specified, block everyone. + map[m].nocommand =100; + } else + map[m].nocommand=0; + } + else if (!strcmpi(w3,"restricted")) { + if (state) { + map[m].flag.restricted=1; + sscanf(w4, "%d", &state); + map[m].zone |= 1<<(state+1); + } else { + map[m].flag.restricted=0; + map[m].zone = 0; + } + } + else if (!strcmpi(w3,"jexp")) { + map[m].jexp = (state) ? atoi(w4) : 100; + if( map[m].jexp < 0 ) map[m].jexp = 100; + map[m].flag.nojobexp = (map[m].jexp==0)?1:0; + } + else if (!strcmpi(w3,"bexp")) { + map[m].bexp = (state) ? atoi(w4) : 100; + if( map[m].bexp < 0 ) map[m].bexp = 100; + map[m].flag.nobaseexp = (map[m].bexp==0)?1:0; + } + else if (!strcmpi(w3,"loadevent")) + map[m].flag.loadevent=state; + else if (!strcmpi(w3,"nochat")) + map[m].flag.nochat=state; + else if (!strcmpi(w3,"partylock")) + map[m].flag.partylock=state; + else if (!strcmpi(w3,"guildlock")) + map[m].flag.guildlock=state; + else if (!strcmpi(w3,"reset")) + map[m].flag.reset=state; + else + ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer)); + + return strchr(start,'\n');// continue } //Read file and create npc/func/mapflag/monster... accordingly. //@runOnInit should we exec OnInit when it's done ? -void npc_parsesrcfile(const char *filepath, bool runOnInit) -{ - int m, lines = 0; - FILE *fp; - size_t len; - char *buffer; - const char *p; - - // read whole file to buffer - fp = fopen(filepath, "rb"); - if (fp == NULL) { - ShowError("npc_parsesrcfile: File not found '%s'.\n", filepath); - return; - } - fseek(fp, 0, SEEK_END); - len = ftell(fp); - buffer = (char *)aMalloc(len+1); - fseek(fp, 0, SEEK_SET); - len = fread(buffer, sizeof(char), len, fp); - buffer[len] = '\0'; - if (ferror(fp)) { - ShowError("npc_parsesrcfile: Failed to read file '%s' - %s\n", filepath, strerror(errno)); - aFree(buffer); - fclose(fp); - return; - } - fclose(fp); - - // parse buffer - for (p = skip_space(buffer); p && *p ; p = skip_space(p)) { - int pos[9]; - char w1[2048], w2[2048], w3[2048], w4[2048]; - int i, count; - lines++; - - // w1<TAB>w2<TAB>w3<TAB>w4 - count = sv_parse(p, len+buffer-p, 0, '\t', pos, ARRAYLENGTH(pos), (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF)); - if (count < 0) { - ShowError("npc_parsesrcfile: Parse error in file '%s', line '%d'. Stopping...\n", filepath, strline(buffer,p-buffer)); - break; - } - // fill w1 - if (pos[3]-pos[2] > ARRAYLENGTH(w1)-1) - ShowWarning("npc_parsesrcfile: w1 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[3]-pos[2], filepath, strline(buffer,p-buffer)); - i = min(pos[3]-pos[2], ARRAYLENGTH(w1)-1); - memcpy(w1, p+pos[2], i*sizeof(char)); - w1[i] = '\0'; - // fill w2 - if (pos[5]-pos[4] > ARRAYLENGTH(w2)-1) - ShowWarning("npc_parsesrcfile: w2 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[5]-pos[4], filepath, strline(buffer,p-buffer)); - i = min(pos[5]-pos[4], ARRAYLENGTH(w2)-1); - memcpy(w2, p+pos[4], i*sizeof(char)); - w2[i] = '\0'; - // fill w3 - if (pos[7]-pos[6] > ARRAYLENGTH(w3)-1) - ShowWarning("npc_parsesrcfile: w3 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[7]-pos[6], filepath, strline(buffer,p-buffer)); - i = min(pos[7]-pos[6], ARRAYLENGTH(w3)-1); - memcpy(w3, p+pos[6], i*sizeof(char)); - w3[i] = '\0'; - // fill w4 (to end of line) - if (pos[1]-pos[8] > ARRAYLENGTH(w4)-1) - ShowWarning("npc_parsesrcfile: w4 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[1]-pos[8], filepath, strline(buffer,p-buffer)); - if (pos[8] != -1) { - i = min(pos[1]-pos[8], ARRAYLENGTH(w4)-1); - memcpy(w4, p+pos[8], i*sizeof(char)); - w4[i] = '\0'; - } else - w4[0] = '\0'; - - if (count < 3) { - // Unknown syntax - ShowError("npc_parsesrcfile: Unknown syntax in file '%s', line '%d'. Stopping...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4); - break; - } - - if (strcmp(w1,"-") !=0 && strcasecmp(w1,"function") != 0) { - // w1 = <map name>,<x>,<y>,<facing> - char mapname[2048]; - sscanf(w1,"%[^,]",mapname); - if (!mapindex_name2id(mapname)) { - // Incorrect map, we must skip the script info... - ShowError("npc_parsesrcfile: Unknown map '%s' in file '%s', line '%d'. Skipping line...\n", mapname, filepath, strline(buffer,p-buffer)); - if (strcasecmp(w2,"script") == 0 && count > 3) { - if ((p = npc_skip_script(p,buffer,filepath)) == NULL) { - break; - } - } - p = strchr(p,'\n');// next line - continue; - } - m = map_mapname2mapid(mapname); - if (m < 0) { - // "mapname" is not assigned to this server, we must skip the script info... - if (strcasecmp(w2,"script") == 0 && count > 3) { - if ((p = npc_skip_script(p,buffer,filepath)) == NULL) { - break; - } - } - p = strchr(p,'\n');// next line - continue; - } - } - - if (strcasecmp(w2,"warp") == 0 && count > 3) { - p = npc_parse_warp(w1,w2,w3,w4, p, buffer, filepath); - } else if ((!strcasecmp(w2,"shop") || !strcasecmp(w2,"cashshop")) && count > 3) { - p = npc_parse_shop(w1,w2,w3,w4, p, buffer, filepath); - } else if (strcasecmp(w2,"script") == 0 && count > 3) { - if (strcasecmp(w1,"function") == 0) - p = npc_parse_function(w1, w2, w3, w4, p, buffer, filepath); - else - p = npc_parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit); - } else if ((i=0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) && count > 3) { - p = npc_parse_duplicate(w1,w2,w3,w4, p, buffer, filepath); - } else if ((strcmpi(w2,"monster") == 0 || strcmpi(w2,"boss_monster") == 0) && count > 3) { - p = npc_parse_mob(w1, w2, w3, w4, p, buffer, filepath); - } else if (strcmpi(w2,"mapflag") == 0 && count >= 3) { - p = npc_parse_mapflag(w1, w2, trim(w3), trim(w4), p, buffer, filepath); - } else { - ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4); - p = strchr(p,'\n');// skip and continue - } - } - aFree(buffer); - - return; -} - -int npc_script_event(struct map_session_data *sd, enum npce_event type) -{ - int i; - if (type == NPCE_MAX) - return 0; - if (!sd) { - ShowError("npc_script_event: NULL sd. Event Type %d\n", type); - return 0; - } - for (i = 0; i<script_event[type].event_count; i++) - npc_event_sub(sd,script_event[type].event[i],script_event[type].event_name[i]); - return i; +void npc_parsesrcfile(const char* filepath, bool runOnInit) +{ + int m, lines = 0; + FILE* fp; + size_t len; + char* buffer; + const char* p; + + // read whole file to buffer + fp = fopen(filepath, "rb"); + if( fp == NULL ) + { + ShowError("npc_parsesrcfile: File not found '%s'.\n", filepath); + return; + } + fseek(fp, 0, SEEK_END); + len = ftell(fp); + buffer = (char*)aMalloc(len+1); + fseek(fp, 0, SEEK_SET); + len = fread(buffer, sizeof(char), len, fp); + buffer[len] = '\0'; + if( ferror(fp) ) + { + ShowError("npc_parsesrcfile: Failed to read file '%s' - %s\n", filepath, strerror(errno)); + aFree(buffer); + fclose(fp); + return; + } + fclose(fp); + + // parse buffer + for( p = skip_space(buffer); p && *p ; p = skip_space(p) ) + { + int pos[9]; + char w1[2048], w2[2048], w3[2048], w4[2048]; + int i, count; + lines++; + + // w1<TAB>w2<TAB>w3<TAB>w4 + count = sv_parse(p, len+buffer-p, 0, '\t', pos, ARRAYLENGTH(pos), (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF)); + if( count < 0 ) + { + ShowError("npc_parsesrcfile: Parse error in file '%s', line '%d'. Stopping...\n", filepath, strline(buffer,p-buffer)); + break; + } + // fill w1 + if( pos[3]-pos[2] > ARRAYLENGTH(w1)-1 ) + ShowWarning("npc_parsesrcfile: w1 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[3]-pos[2], filepath, strline(buffer,p-buffer)); + i = min(pos[3]-pos[2], ARRAYLENGTH(w1)-1); + memcpy(w1, p+pos[2], i*sizeof(char)); + w1[i] = '\0'; + // fill w2 + if( pos[5]-pos[4] > ARRAYLENGTH(w2)-1 ) + ShowWarning("npc_parsesrcfile: w2 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[5]-pos[4], filepath, strline(buffer,p-buffer)); + i = min(pos[5]-pos[4], ARRAYLENGTH(w2)-1); + memcpy(w2, p+pos[4], i*sizeof(char)); + w2[i] = '\0'; + // fill w3 + if( pos[7]-pos[6] > ARRAYLENGTH(w3)-1 ) + ShowWarning("npc_parsesrcfile: w3 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[7]-pos[6], filepath, strline(buffer,p-buffer)); + i = min(pos[7]-pos[6], ARRAYLENGTH(w3)-1); + memcpy(w3, p+pos[6], i*sizeof(char)); + w3[i] = '\0'; + // fill w4 (to end of line) + if( pos[1]-pos[8] > ARRAYLENGTH(w4)-1 ) + ShowWarning("npc_parsesrcfile: w4 truncated, too much data (%d) in file '%s', line '%d'.\n", pos[1]-pos[8], filepath, strline(buffer,p-buffer)); + if( pos[8] != -1 ) + { + i = min(pos[1]-pos[8], ARRAYLENGTH(w4)-1); + memcpy(w4, p+pos[8], i*sizeof(char)); + w4[i] = '\0'; + } + else + w4[0] = '\0'; + + if( count < 3 ) + {// Unknown syntax + ShowError("npc_parsesrcfile: Unknown syntax in file '%s', line '%d'. Stopping...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4); + break; + } + + if( strcmp(w1,"-") !=0 && strcasecmp(w1,"function") != 0 ) + {// w1 = <map name>,<x>,<y>,<facing> + char mapname[2048]; + sscanf(w1,"%[^,]",mapname); + if( !mapindex_name2id(mapname) ) + {// Incorrect map, we must skip the script info... + ShowError("npc_parsesrcfile: Unknown map '%s' in file '%s', line '%d'. Skipping line...\n", mapname, filepath, strline(buffer,p-buffer)); + if( strcasecmp(w2,"script") == 0 && count > 3 ) + { + if((p = npc_skip_script(p,buffer,filepath)) == NULL) + { + break; + } + } + p = strchr(p,'\n');// next line + continue; + } + m = map_mapname2mapid(mapname); + if( m < 0 ) + {// "mapname" is not assigned to this server, we must skip the script info... + if( strcasecmp(w2,"script") == 0 && count > 3 ) + { + if((p = npc_skip_script(p,buffer,filepath)) == NULL) + { + break; + } + } + p = strchr(p,'\n');// next line + continue; + } + } + + if( strcasecmp(w2,"warp") == 0 && count > 3 ) + { + p = npc_parse_warp(w1,w2,w3,w4, p, buffer, filepath); + } + else if( (!strcasecmp(w2,"shop") || !strcasecmp(w2,"cashshop")) && count > 3 ) + { + p = npc_parse_shop(w1,w2,w3,w4, p, buffer, filepath); + } + else if( strcasecmp(w2,"script") == 0 && count > 3 ) + { + if( strcasecmp(w1,"function") == 0 ) + p = npc_parse_function(w1, w2, w3, w4, p, buffer, filepath); + else + p = npc_parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit); + } + else if( (i=0, sscanf(w2,"duplicate%n",&i), (i > 0 && w2[i] == '(')) && count > 3 ) + { + p = npc_parse_duplicate(w1,w2,w3,w4, p, buffer, filepath); + } + else if( (strcmpi(w2,"monster") == 0 || strcmpi(w2,"boss_monster") == 0) && count > 3 ) + { + p = npc_parse_mob(w1, w2, w3, w4, p, buffer, filepath); + } + else if( strcmpi(w2,"mapflag") == 0 && count >= 3 ) + { + p = npc_parse_mapflag(w1, w2, trim(w3), trim(w4), p, buffer, filepath); + } + else + { + ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4); + p = strchr(p,'\n');// skip and continue + } + } + aFree(buffer); + + return; +} + +int npc_script_event(struct map_session_data* sd, enum npce_event type) +{ + int i; + if (type == NPCE_MAX) + return 0; + if (!sd) { + ShowError("npc_script_event: NULL sd. Event Type %d\n", type); + return 0; + } + for (i = 0; i<script_event[type].event_count; i++) + npc_event_sub(sd,script_event[type].event[i],script_event[type].event_name[i]); + return i; } void npc_read_event_script(void) { - int i; - struct { - char *name; - const char *event_name; - } config[] = { - {"Login Event",script_config.login_event_name}, - {"Logout Event",script_config.logout_event_name}, - {"Load Map Event",script_config.loadmap_event_name}, - {"Base LV Up Event",script_config.baselvup_event_name}, - {"Job LV Up Event",script_config.joblvup_event_name}, - {"Die Event",script_config.die_event_name}, - {"Kill PC Event",script_config.kill_pc_event_name}, - {"Kill NPC Event",script_config.kill_mob_event_name}, - }; - - for (i = 0; i < NPCE_MAX; i++) { - DBIterator *iter; - DBKey key; - DBData *data; - - char name[64]="::"; - strncpy(name+2,config[i].event_name,62); - - script_event[i].event_count = 0; - iter = db_iterator(ev_db); - for (data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key)) { - const char *p = key.str; - struct event_data *ed = db_data2ptr(data); - unsigned char count = script_event[i].event_count; - - if (count >= ARRAYLENGTH(script_event[i].event)) { - ShowWarning("npc_read_event_script: too many occurences of event '%s'!\n", config[i].event_name); - break; - } - - if ((p=strchr(p,':')) && p && strcmpi(name,p)==0) { - script_event[i].event[count] = ed; - script_event[i].event_name[count] = key.str; - script_event[i].event_count++; - } - } - dbi_destroy(iter); - } - - if (battle_config.etc_log) { - //Print summary. - for (i = 0; i < NPCE_MAX; i++) - ShowInfo("%s: %d '%s' events.\n", config[i].name, script_event[i].event_count, config[i].event_name); - } -} - -void npc_clear_pathlist(void) -{ - struct npc_path_data *npd = NULL; - DBIterator *path_list = db_iterator(npc_path_db); - - /* free all npc_path_data filepaths */ - for (npd = dbi_first(path_list); dbi_exists(path_list); npd = dbi_next(path_list)) { - if (npd->path) - aFree(npd->path); - } - - dbi_destroy(path_list); + int i; + struct { + char *name; + const char *event_name; + } config[] = { + {"Login Event",script_config.login_event_name}, + {"Logout Event",script_config.logout_event_name}, + {"Load Map Event",script_config.loadmap_event_name}, + {"Base LV Up Event",script_config.baselvup_event_name}, + {"Job LV Up Event",script_config.joblvup_event_name}, + {"Die Event",script_config.die_event_name}, + {"Kill PC Event",script_config.kill_pc_event_name}, + {"Kill NPC Event",script_config.kill_mob_event_name}, + }; + + for (i = 0; i < NPCE_MAX; i++) + { + DBIterator* iter; + DBKey key; + DBData *data; + + char name[64]="::"; + strncpy(name+2,config[i].event_name,62); + + script_event[i].event_count = 0; + iter = db_iterator(ev_db); + for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) + { + const char* p = key.str; + struct event_data* ed = db_data2ptr(data); + unsigned char count = script_event[i].event_count; + + if( count >= ARRAYLENGTH(script_event[i].event) ) + { + ShowWarning("npc_read_event_script: too many occurences of event '%s'!\n", config[i].event_name); + break; + } + + if( (p=strchr(p,':')) && p && strcmpi(name,p)==0 ) + { + script_event[i].event[count] = ed; + script_event[i].event_name[count] = key.str; + script_event[i].event_count++; + } + } + dbi_destroy(iter); + } + + if (battle_config.etc_log) { + //Print summary. + for (i = 0; i < NPCE_MAX; i++) + ShowInfo("%s: %d '%s' events.\n", config[i].name, script_event[i].event_count, config[i].event_name); + } +} + +void npc_clear_pathlist(void) { + struct npc_path_data *npd = NULL; + DBIterator *path_list = db_iterator(npc_path_db); + + /* free all npc_path_data filepaths */ + for( npd = dbi_first(path_list); dbi_exists(path_list); npd = dbi_next(path_list) ) { + if( npd->path ) + aFree(npd->path); + } + + dbi_destroy(path_list); } //Clear then reload npcs files -int npc_reload(void) -{ - struct npc_src_list *nsl; - int m, i; - int npc_new_min = npc_id; - struct s_mapiterator *iter; - struct block_list *bl; - - /* clear guild flag cache */ - guild_flags_clear(); - - npc_clear_pathlist(); - - db_clear(npc_path_db); - - db_clear(npcname_db); - db_clear(ev_db); - - //Remove all npcs/mobs. [Skotlex] - - iter = mapit_geteachiddb(); - for (bl = (struct block_list *)mapit_first(iter); mapit_exists(iter); bl = (struct block_list *)mapit_next(iter)) { - switch (bl->type) { - case BL_NPC: - if (bl->id != fake_nd->bl.id) // don't remove fake_nd - npc_unload((struct npc_data *)bl, false); - break; - case BL_MOB: - unit_free(bl,CLR_OUTSIGHT); - break; - } - } - mapit_free(iter); - - if (battle_config.dynamic_mobs) { - // dynamic check by [random] - for (m = 0; m < map_num; m++) { - for (i = 0; i < MAX_MOB_LIST_PER_MAP; i++) { - if (map[m].moblist[i] != NULL) { - aFree(map[m].moblist[i]); - map[m].moblist[i] = NULL; - } - if (map[m].mob_delete_timer != INVALID_TIMER) { - // Mobs were removed anyway,so delete the timer [Inkfish] - delete_timer(map[m].mob_delete_timer, map_removemobs_timer); - map[m].mob_delete_timer = INVALID_TIMER; - } - } - } - if (map[m].npc_num > 0) - ShowWarning("npc_reload: %d npcs weren't removed at map %s!\n", map[m].npc_num, map[m].name); - } - - // clear mob spawn lookup index - mob_clear_spawninfo(); - - npc_warp = npc_shop = npc_script = 0; - npc_mob = npc_cache_mob = npc_delay_mob = 0; - - // reset mapflags - map_flags_init(); - - //TODO: the following code is copy-pasted from do_init_npc(); clean it up - // Reloading npcs now - for (nsl = npc_src_files; nsl; nsl = nsl->next) { - ShowStatus("Loading NPC file: %s"CL_CLL"\r", nsl->name); - npc_parsesrcfile(nsl->name,false); - } - ShowInfo("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\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"' Spawn sets\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", - npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); - - do_final_instance(); - - for (i = 0; i < ARRAYLENGTH(instance); ++i) - instance_init(instance[i].instance_id); - - //Re-read the NPC Script Events cache. - npc_read_event_script(); - - /* refresh guild castle flags on both woe setups */ - npc_event_doall("OnAgitInit"); - npc_event_doall("OnAgitInit2"); - - //Execute the OnInit event for freshly loaded npcs. [Skotlex] - ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit")); - - // Execute rest of the startup events if connected to char-server. [Lance] - if (!CheckForCharServer()) { - ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit")); - ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce")); - } - return 0; +int npc_reload(void) { + struct npc_src_list *nsl; + int m, i; + int npc_new_min = npc_id; + struct s_mapiterator* iter; + struct block_list* bl; + + /* clear guild flag cache */ + guild_flags_clear(); + + npc_clear_pathlist(); + + db_clear(npc_path_db); + + db_clear(npcname_db); + db_clear(ev_db); + + //Remove all npcs/mobs. [Skotlex] + + iter = mapit_geteachiddb(); + for( bl = (struct block_list*)mapit_first(iter); mapit_exists(iter); bl = (struct block_list*)mapit_next(iter) ) { + switch(bl->type) { + case BL_NPC: + if( bl->id != fake_nd->bl.id )// don't remove fake_nd + npc_unload((struct npc_data *)bl, false); + break; + case BL_MOB: + unit_free(bl,CLR_OUTSIGHT); + break; + } + } + mapit_free(iter); + + if(battle_config.dynamic_mobs) + {// dynamic check by [random] + for (m = 0; m < map_num; m++) { + for (i = 0; i < MAX_MOB_LIST_PER_MAP; i++) { + if (map[m].moblist[i] != NULL) { + aFree(map[m].moblist[i]); + map[m].moblist[i] = NULL; + } + if( map[m].mob_delete_timer != INVALID_TIMER ) + { // Mobs were removed anyway,so delete the timer [Inkfish] + delete_timer(map[m].mob_delete_timer, map_removemobs_timer); + map[m].mob_delete_timer = INVALID_TIMER; + } + } + } + if (map[m].npc_num > 0) + ShowWarning("npc_reload: %d npcs weren't removed at map %s!\n", map[m].npc_num, map[m].name); + } + + // clear mob spawn lookup index + mob_clear_spawninfo(); + + npc_warp = npc_shop = npc_script = 0; + npc_mob = npc_cache_mob = npc_delay_mob = 0; + + // reset mapflags + map_flags_init(); + + //TODO: the following code is copy-pasted from do_init_npc(); clean it up + // Reloading npcs now + for (nsl = npc_src_files; nsl; nsl = nsl->next) { + ShowStatus("Loading NPC file: %s"CL_CLL"\r", nsl->name); + npc_parsesrcfile(nsl->name,false); + } + ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\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"' Spawn sets\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", + npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); + + do_final_instance(); + + for( i = 0; i < ARRAYLENGTH(instance); ++i ) + instance_init(instance[i].instance_id); + + //Re-read the NPC Script Events cache. + npc_read_event_script(); + + /* refresh guild castle flags on both woe setups */ + npc_event_doall("OnAgitInit"); + npc_event_doall("OnAgitInit2"); + + //Execute the OnInit event for freshly loaded npcs. [Skotlex] + ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit")); + + // Execute rest of the startup events if connected to char-server. [Lance] + if(!CheckForCharServer()){ + ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit")); + ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce")); + } + return 0; } //Unload all npc in the given file -bool npc_unloadfile(const char *path) -{ - DBIterator *iter = db_iterator(npcname_db); - struct npc_data *nd = NULL; - bool found = false; +bool npc_unloadfile( const char* path ) { + DBIterator * iter = db_iterator(npcname_db); + struct npc_data* nd = NULL; + bool found = false; - for (nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter)) { - if (nd->path && strcasecmp(nd->path,path) == 0) { - found = true; - npc_unload_duplicates(nd);/* unload any npcs which could duplicate this but be in a different file */ - npc_unload(nd, true); - } - } + for( nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter) ) { + if( nd->path && strcasecmp(nd->path,path) == 0 ) { + found = true; + npc_unload_duplicates(nd);/* unload any npcs which could duplicate this but be in a different file */ + npc_unload(nd, true); + } + } - dbi_destroy(iter); + dbi_destroy(iter); - if (found) /* refresh event cache */ - npc_read_event_script(); + if( found ) /* refresh event cache */ + npc_read_event_script(); - return found; + return found; } -void do_clear_npc(void) -{ - db_clear(npcname_db); - db_clear(ev_db); +void do_clear_npc(void) { + db_clear(npcname_db); + db_clear(ev_db); } /*========================================== * Destructor *------------------------------------------*/ -int do_final_npc(void) -{ - npc_clear_pathlist(); - ev_db->destroy(ev_db, NULL); - npcname_db->destroy(npcname_db, NULL); - npc_path_db->destroy(npc_path_db, NULL); - ers_destroy(timer_event_ers); - npc_clearsrcfile(); - - return 0; -} - -static void npc_debug_warps_sub(struct npc_data *nd) -{ - int m; - if (nd->bl.type != BL_NPC || nd->subtype != WARP || nd->bl.m < 0) - return; - - m = map_mapindex2mapid(nd->u.warp.mapindex); - if (m < 0) return; //Warps to another map, nothing to do about it. - if (nd->u.warp.x == 0 && nd->u.warp.y == 0) return; // random warp - - if (map_getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNPC)) { - ShowWarning("Warp %s at %s(%d,%d) warps directly on top of an area npc at %s(%d,%d)\n", - nd->name, - map[nd->bl.m].name, nd->bl.x, nd->bl.y, - map[m].name, nd->u.warp.x, nd->u.warp.y - ); - } - if (map_getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNOPASS)) { - ShowWarning("Warp %s at %s(%d,%d) warps to a non-walkable tile at %s(%d,%d)\n", - nd->name, - map[nd->bl.m].name, nd->bl.x, nd->bl.y, - map[m].name, nd->u.warp.x, nd->u.warp.y - ); - } +int do_final_npc(void) { + npc_clear_pathlist(); + ev_db->destroy(ev_db, NULL); + npcname_db->destroy(npcname_db, NULL); + npc_path_db->destroy(npc_path_db, NULL); + ers_destroy(timer_event_ers); + npc_clearsrcfile(); + + return 0; +} + +static void npc_debug_warps_sub(struct npc_data* nd) +{ + int m; + if (nd->bl.type != BL_NPC || nd->subtype != WARP || nd->bl.m < 0) + return; + + m = map_mapindex2mapid(nd->u.warp.mapindex); + if (m < 0) return; //Warps to another map, nothing to do about it. + if (nd->u.warp.x == 0 && nd->u.warp.y == 0) return; // random warp + + if (map_getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNPC)) { + ShowWarning("Warp %s at %s(%d,%d) warps directly on top of an area npc at %s(%d,%d)\n", + nd->name, + map[nd->bl.m].name, nd->bl.x, nd->bl.y, + map[m].name, nd->u.warp.x, nd->u.warp.y + ); + } + if (map_getcell(m, nd->u.warp.x, nd->u.warp.y, CELL_CHKNOPASS)) { + ShowWarning("Warp %s at %s(%d,%d) warps to a non-walkable tile at %s(%d,%d)\n", + nd->name, + map[nd->bl.m].name, nd->bl.x, nd->bl.y, + map[m].name, nd->u.warp.x, nd->u.warp.y + ); + } } static void npc_debug_warps(void) { - int m, i; - for (m = 0; m < map_num; m++) - for (i = 0; i < map[m].npc_num; i++) - npc_debug_warps_sub(map[m].npc[i]); + int m, i; + for (m = 0; m < map_num; m++) + for (i = 0; i < map[m].npc_num; i++) + npc_debug_warps_sub(map[m].npc[i]); } /*========================================== @@ -3639,64 +3795,64 @@ static void npc_debug_warps(void) *------------------------------------------*/ int do_init_npc(void) { - struct npc_src_list *file; - int i; - - //Stock view data for normal npcs. - memset(&npc_viewdb, 0, sizeof(npc_viewdb)); - npc_viewdb[0].class_ = INVISIBLE_CLASS; //Invisible class is stored here. - for (i = 1; i < MAX_NPC_CLASS; i++) - npc_viewdb[i].class_ = i; - - ev_db = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),2*NAME_LENGTH+2+1); - npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH); - npc_path_db = strdb_alloc(DB_OPT_BASE|DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,80); - - timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE); - - // process all npc files - ShowStatus("Loading NPCs...\r"); - for (file = npc_src_files; file != NULL; file = file->next) { - ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name); - npc_parsesrcfile(file->name,false); - } - ShowInfo("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\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"' Spawn sets\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" - "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", - npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); - - // set up the events cache - memset(script_event, 0, sizeof(script_event)); - npc_read_event_script(); - - //Debug function to locate all endless loop warps. - if (battle_config.warp_point_debug) - npc_debug_warps(); - - add_timer_func_list(npc_event_do_clock,"npc_event_do_clock"); - add_timer_func_list(npc_timerevent,"npc_timerevent"); - - // Init dummy NPC - fake_nd = (struct npc_data *)aCalloc(1,sizeof(struct npc_data)); - fake_nd->bl.m = -1; - fake_nd->bl.id = npc_get_new_npc_id(); - fake_nd->class_ = -1; - fake_nd->speed = 200; - strcpy(fake_nd->name,"FAKE_NPC"); - memcpy(fake_nd->exname, fake_nd->name, 9); - - npc_script++; - fake_nd->bl.type = BL_NPC; - fake_nd->subtype = SCRIPT; - - strdb_put(npcname_db, fake_nd->exname, fake_nd); - fake_nd->u.scr.timerid = INVALID_TIMER; - map_addiddb(&fake_nd->bl); - // End of initialization - - return 0; + struct npc_src_list *file; + int i; + + //Stock view data for normal npcs. + memset(&npc_viewdb, 0, sizeof(npc_viewdb)); + npc_viewdb[0].class_ = INVISIBLE_CLASS; //Invisible class is stored here. + for( i = 1; i < MAX_NPC_CLASS; i++ ) + npc_viewdb[i].class_ = i; + + ev_db = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),2*NAME_LENGTH+2+1); + npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH); + npc_path_db = strdb_alloc(DB_OPT_BASE|DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,80); + + timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE); + + // process all npc files + ShowStatus("Loading NPCs...\r"); + for( file = npc_src_files; file != NULL; file = file->next ) { + ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name); + npc_parsesrcfile(file->name,false); + } + ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\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"' Spawn sets\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" + "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", + npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); + + // set up the events cache + memset(script_event, 0, sizeof(script_event)); + npc_read_event_script(); + + //Debug function to locate all endless loop warps. + if (battle_config.warp_point_debug) + npc_debug_warps(); + + add_timer_func_list(npc_event_do_clock,"npc_event_do_clock"); + add_timer_func_list(npc_timerevent,"npc_timerevent"); + + // Init dummy NPC + fake_nd = (struct npc_data *)aCalloc(1,sizeof(struct npc_data)); + fake_nd->bl.m = -1; + fake_nd->bl.id = npc_get_new_npc_id(); + fake_nd->class_ = -1; + fake_nd->speed = 200; + strcpy(fake_nd->name,"FAKE_NPC"); + memcpy(fake_nd->exname, fake_nd->name, 9); + + npc_script++; + fake_nd->bl.type = BL_NPC; + fake_nd->subtype = SCRIPT; + + strdb_put(npcname_db, fake_nd->exname, fake_nd); + fake_nd->u.scr.timerid = INVALID_TIMER; + map_addiddb(&fake_nd->bl); + // End of initialization + + return 0; } diff --git a/src/map/npc.h b/src/map/npc.h index 6e0fe0ee5..0379ae634 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -13,74 +13,75 @@ struct view_data; struct npc_timerevent_list { - int timer,pos; + int timer,pos; }; struct npc_label_list { - char name[NAME_LENGTH]; - int pos; + char name[NAME_LENGTH]; + int pos; }; struct npc_item_list { - unsigned int nameid,value; + unsigned int nameid,value; }; struct npc_data { - struct block_list bl; - struct unit_data ud; //Because they need to be able to move.... - struct view_data *vd; - struct status_change sc; //They can't have status changes, but.. they want the visual opt values. - struct npc_data *master_nd; - short class_; - short speed; - char name[NAME_LENGTH+1];// display name - char exname[NAME_LENGTH+1];// unique npc name - int chat_id; - int touching_id; - unsigned int next_walktime; - - unsigned size : 2; - - void *chatdb; // pointer to a npc_parse struct (see npc_chat.c) - char *path;/* path dir */ - enum npc_subtype subtype; - int src_id; - union { - struct { - struct script_code *script; - short xs,ys; // OnTouch area radius - int guild_id; - int timer,timerid,timeramount,rid; - unsigned int timertick; - struct npc_timerevent_list *timer_event; - int label_list_num; - struct npc_label_list *label_list; - } scr; - struct { - struct npc_item_list *shop_item; - int count; - } shop; - struct { - short xs,ys; // OnTouch area radius - short x,y; // destination coords - unsigned short mapindex; // destination map - } warp; - struct { - struct mob_data *md; - time_t kill_time; - char killer_name[NAME_LENGTH]; - } tomb; - } u; + struct block_list bl; + struct unit_data ud; //Because they need to be able to move.... + struct view_data *vd; + struct status_change sc; //They can't have status changes, but.. they want the visual opt values. + struct npc_data *master_nd; + short class_; + short speed; + char name[NAME_LENGTH+1];// display name + char exname[NAME_LENGTH+1];// unique npc name + int chat_id; + int touching_id; + unsigned int next_walktime; + + unsigned size : 2; + + void* chatdb; // pointer to a npc_parse struct (see npc_chat.c) + char* path;/* path dir */ + enum npc_subtype subtype; + int src_id; + union { + struct { + struct script_code *script; + short xs,ys; // OnTouch area radius + int guild_id; + int timer,timerid,timeramount,rid; + unsigned int timertick; + struct npc_timerevent_list *timer_event; + int label_list_num; + struct npc_label_list *label_list; + } scr; + struct { + struct npc_item_list* shop_item; + int count; + } shop; + struct { + short xs,ys; // OnTouch area radius + short x,y; // destination coords + unsigned short mapindex; // destination map + } warp; + struct { + struct mob_data *md; + time_t kill_time; + char killer_name[NAME_LENGTH]; + } tomb; + } u; }; #define START_NPC_NUM 110000000 -enum actor_classes { - WARP_CLASS = 45, - HIDDEN_WARP_CLASS = 139, - WARP_DEBUG_CLASS = 722, - FLAG_CLASS = 722, - INVISIBLE_CLASS = 32767, +enum actor_classes +{ + WARP_CLASS = 45, + HIDDEN_WARP_CLASS = 139, + WARP_DEBUG_CLASS = 722, + FLAG_CLASS = 722, + INVISIBLE_CLASS = 32767, }; #define MAX_NPC_CLASS 1000 @@ -89,91 +90,91 @@ enum actor_classes { #define npcdb_checkid(id) ( ( (id) >= 46 && (id) <= 125) || (id) == HIDDEN_WARP_CLASS || ( (id) > 400 && (id) < MAX_NPC_CLASS ) || (id) == INVISIBLE_CLASS ) #ifdef PCRE_SUPPORT -void npc_chat_finalize(struct npc_data *nd); +void npc_chat_finalize(struct npc_data* nd); #endif //Script NPC events. enum npce_event { - NPCE_LOGIN, - NPCE_LOGOUT, - NPCE_LOADMAP, - NPCE_BASELVUP, - NPCE_JOBLVUP, - NPCE_DIE, - NPCE_KILLPC, - NPCE_KILLNPC, - NPCE_MAX + NPCE_LOGIN, + NPCE_LOGOUT, + NPCE_LOADMAP, + NPCE_BASELVUP, + NPCE_JOBLVUP, + NPCE_DIE, + NPCE_KILLPC, + NPCE_KILLNPC, + NPCE_MAX }; -struct view_data *npc_get_viewdata(int class_); -int npc_chat_sub(struct block_list *bl, va_list ap); -int npc_event_dequeue(struct map_session_data *sd); -int npc_event(struct map_session_data *sd, const char *eventname, int ontouch); -int npc_touch_areanpc(struct map_session_data *sd, int m, int x, int y); +struct view_data* npc_get_viewdata(int class_); +int npc_chat_sub(struct block_list* bl, va_list ap); +int npc_event_dequeue(struct map_session_data* sd); +int npc_event(struct map_session_data* sd, const char* eventname, int ontouch); +int npc_touch_areanpc(struct map_session_data* sd, int m, int x, int y); int npc_touch_areanpc2(struct mob_data *md); // [Skotlex] int npc_check_areanpc(int flag, int m, int x, int y, int range); -int npc_touchnext_areanpc(struct map_session_data *sd,bool leavemap); -int npc_click(struct map_session_data *sd, struct npc_data *nd); -int npc_scriptcont(struct map_session_data *sd, int id); -struct npc_data *npc_checknear(struct map_session_data *sd, struct block_list *bl); -int npc_buysellsel(struct map_session_data *sd, int id, int type); -int npc_buylist(struct map_session_data *sd,int n, unsigned short *item_list); -int npc_selllist(struct map_session_data *sd, int n, unsigned short *item_list); -void npc_parse_mob2(struct spawn_data *mob); -struct npc_data *npc_add_warp(char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y); -int npc_globalmessage(const char *name,const char *mes); - -void npc_setcells(struct npc_data *nd); -void npc_unsetcells(struct npc_data *nd); -void npc_movenpc(struct npc_data *nd, int x, int y); -int npc_enable(const char *name, int flag); -void npc_setdisplayname(struct npc_data *nd, const char *newname); -void npc_setclass(struct npc_data *nd, short class_); -struct npc_data *npc_name2id(const char *name); +int npc_touchnext_areanpc(struct map_session_data* sd,bool leavemap); +int npc_click(struct map_session_data* sd, struct npc_data* nd); +int npc_scriptcont(struct map_session_data* sd, int id); +struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* bl); +int npc_buysellsel(struct map_session_data* sd, int id, int type); +int npc_buylist(struct map_session_data* sd,int n, unsigned short* item_list); +int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list); +void npc_parse_mob2(struct spawn_data* mob); +struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y); +int npc_globalmessage(const char* name,const char* mes); + +void npc_setcells(struct npc_data* nd); +void npc_unsetcells(struct npc_data* nd); +void npc_movenpc(struct npc_data* nd, int x, int y); +int npc_enable(const char* name, int flag); +void npc_setdisplayname(struct npc_data* nd, const char* newname); +void npc_setclass(struct npc_data* nd, short class_); +struct npc_data* npc_name2id(const char* name); int npc_get_new_npc_id(void); -void npc_addsrcfile(const char *name); -void npc_delsrcfile(const char *name); -void npc_parsesrcfile(const char *filepath, bool runOnInit); +void npc_addsrcfile(const char* name); +void npc_delsrcfile(const char* name); +void npc_parsesrcfile(const char* filepath, bool runOnInit); void do_clear_npc(void); int do_final_npc(void); int do_init_npc(void); void npc_event_do_oninit(void); int npc_do_ontimer(int npc_id, int option); -int npc_event_do(const char *name); -int npc_event_doall(const char *name); -int npc_event_doall_id(const char *name, int rid); - -int npc_timerevent_start(struct npc_data *nd, int rid); -int npc_timerevent_stop(struct npc_data *nd); -void npc_timerevent_quit(struct map_session_data *sd); -int npc_gettimerevent_tick(struct npc_data *nd); -int npc_settimerevent_tick(struct npc_data *nd, int newtimer); -int npc_remove_map(struct npc_data *nd); -void npc_unload_duplicates(struct npc_data *nd); -int npc_unload(struct npc_data *nd, bool single); +int npc_event_do(const char* name); +int npc_event_doall(const char* name); +int npc_event_doall_id(const char* name, int rid); + +int npc_timerevent_start(struct npc_data* nd, int rid); +int npc_timerevent_stop(struct npc_data* nd); +void npc_timerevent_quit(struct map_session_data* sd); +int npc_gettimerevent_tick(struct npc_data* nd); +int npc_settimerevent_tick(struct npc_data* nd, int newtimer); +int npc_remove_map(struct npc_data* nd); +void npc_unload_duplicates (struct npc_data* nd); +int npc_unload(struct npc_data* nd, bool single); int npc_reload(void); void npc_read_event_script(void); -int npc_script_event(struct map_session_data *sd, enum npce_event type); +int npc_script_event(struct map_session_data* sd, enum npce_event type); int npc_duplicate4instance(struct npc_data *snd, int m); int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int points); -extern struct npc_data *fake_nd; +extern struct npc_data* fake_nd; -int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short *item_list); +int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list); /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ #if SECURE_NPCTIMEOUT -int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data); + int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data); #endif // @commands (script-based) -int npc_do_atcmd_event(struct map_session_data *sd, const char *command, const char *message, const char *eventname); +int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const char* message, const char* eventname); -bool npc_unloadfile(const char *path); +bool npc_unloadfile( const char* path ); #endif /* _NPC_H_ */ diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c index c0a965e9d..39a3a8584 100644 --- a/src/map/npc_chat.c +++ b/src/map/npc_chat.c @@ -40,7 +40,7 @@ * * defpattern 1, "[^:]+: (.*) loves (.*)", "label"; * - * this defines a new pattern in set 1 using perl syntax + * 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. @@ -50,7 +50,7 @@ * 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 @@ -71,22 +71,22 @@ /* 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; + 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 *prev; - struct pcrematch_set *next; - struct pcrematch_entry *head; - int setid; + struct pcrematch_set* prev; + struct pcrematch_set* next; + 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 @@ -96,8 +96,8 @@ struct pcrematch_set { * without having to do a large number of changes. */ struct npc_parse { - struct pcrematch_set *active; - struct pcrematch_set *inactive; + struct pcrematch_set* active; + struct pcrematch_set* inactive; }; @@ -106,50 +106,51 @@ struct npc_parse { * * This does NOT do the list management */ -void finalize_pcrematch_entry(struct pcrematch_entry *e) +void finalize_pcrematch_entry(struct pcrematch_entry* e) { - pcre_free(e->pcre_); - pcre_free(e->pcre_extra_); - aFree(e->pattern); - aFree(e->label); + pcre_free(e->pcre_); + 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; +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; } /** @@ -157,32 +158,32 @@ static struct pcrematch_set *lookup_pcreset(struct npc_data *nd, int setid) { * * if the setid does not exist, this will silently return */ -static void activate_pcreset(struct npc_data *nd, int setid) +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; + 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; } /** @@ -190,255 +191,260 @@ static void activate_pcreset(struct npc_data *nd, int setid) * * if the setid does not exist, this will silently return */ -static void deactivate_pcreset(struct npc_data *nd, int setid) +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; + 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) +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; - - if (active) - 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); - aFree(pcreset->head); // Cleanin' the last ones.. [Lance] - pcreset->head = n; - } - - aFree(pcreset); + 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; + + if(active) + 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); + aFree(pcreset->head); // Cleanin' the last ones.. [Lance] + pcreset->head = n; + } + + aFree(pcreset); } /** - * create a new pattern entry + * 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; +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) +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); + 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 + * matching code * * this could be more efficent but.. how often do you do this? */ -void npc_chat_finalize(struct npc_data *nd) +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); - - // Additional cleaning up [Lance] - aFree(npcParse); + 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); + + // Additional cleaning up [Lance] + aFree(npcParse); } /** * Handler called whenever a global message is spoken in a NPC's area */ -int npc_chat_sub(struct block_list *bl, va_list ap) +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; - char *msg; - int len, i; - struct map_session_data *sd; - struct npc_label_list *lst; - struct pcrematch_set *pcreset; - struct pcrematch_entry *e; - - // Not interested in anything you might have to say... - if (npcParse == NULL || npcParse->active == NULL) - return 0; - - msg = va_arg(ap,char *); - len = va_arg(ap,int); - sd = va_arg(ap,struct map_session_data *); - - // iterate across all active sets - for (pcreset = npcParse->active; pcreset != NULL; pcreset = pcreset->next) { - // interate across all patterns in that set - for (e = pcreset->head; e != NULL; e = e->next) { - int offsets[2*10 + 10]; // 1/3 reserved for temp space requred by pcre_exec - - // perform pattern match - int r = pcre_exec(e->pcre_, e->pcre_extra_, msg, len, 0, 0, offsets, ARRAYLENGTH(offsets)); - if (r > 0) { - // save out the matched strings - for (i = 0; i < r; i++) { - char var[6], val[255]; - snprintf(var, sizeof(var), "$@p%i$", i); - pcre_copy_substring(msg, offsets, r, i, val, sizeof(val)); - set_var(sd, var, val); - } - - // find the target label.. this sucks.. - lst = nd->u.scr.label_list; - ARR_FIND(0, nd->u.scr.label_list_num, i, strncmp(lst[i].name, e->label, sizeof(lst[i].name)) == 0); - if (i == nd->u.scr.label_list_num) { - ShowWarning("Unable to find label: %s\n", e->label); - return 0; - } - - // run the npc script - run_script(nd->u.scr.script,lst[i].pos,sd->bl.id,nd->bl.id); - return 0; - } - } - } - - return 0; + struct npc_data* nd = (struct npc_data *) bl; + struct npc_parse* npcParse = (struct npc_parse *) nd->chatdb; + char* msg; + int len, i; + struct map_session_data* sd; + struct npc_label_list* lst; + struct pcrematch_set* pcreset; + struct pcrematch_entry* e; + + // Not interested in anything you might have to say... + if (npcParse == NULL || npcParse->active == NULL) + return 0; + + msg = va_arg(ap,char*); + len = va_arg(ap,int); + sd = va_arg(ap,struct map_session_data *); + + // iterate across all active sets + for (pcreset = npcParse->active; pcreset != NULL; pcreset = pcreset->next) + { + // interate across all patterns in that set + for (e = pcreset->head; e != NULL; e = e->next) + { + int offsets[2*10 + 10]; // 1/3 reserved for temp space requred by pcre_exec + + // perform pattern match + int r = pcre_exec(e->pcre_, e->pcre_extra_, msg, len, 0, 0, offsets, ARRAYLENGTH(offsets)); + if (r > 0) + { + // save out the matched strings + for (i = 0; i < r; i++) + { + char var[6], val[255]; + snprintf(var, sizeof(var), "$@p%i$", i); + pcre_copy_substring(msg, offsets, r, i, val, sizeof(val)); + set_var(sd, var, val); + } + + // find the target label.. this sucks.. + lst = nd->u.scr.label_list; + ARR_FIND(0, nd->u.scr.label_list_num, i, strncmp(lst[i].name, e->label, sizeof(lst[i].name)) == 0); + if (i == nd->u.scr.label_list_num) { + ShowWarning("Unable to find label: %s\n", e->label); + return 0; + } + + // run the npc script + run_script(nd->u.scr.script,lst[i].pos,sd->bl.id,nd->bl.id); + return 0; + } + } + } + + return 0; } // Various script builtins used to support these functions -int buildin_defpattern(struct script_state *st) +int buildin_defpattern(struct script_state* st) { - int setid = conv_num(st,& (st->stack->stack_data[st->start+2])); - const char *pattern = conv_str(st,& (st->stack->stack_data[st->start+3])); - const 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 setid = conv_num(st,& (st->stack->stack_data[st->start+2])); + const char* pattern = conv_str(st,& (st->stack->stack_data[st->start+3])); + const 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 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 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 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 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 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; + 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 //PCRE_SUPPORT diff --git a/src/map/party.c b/src/map/party.c index d17112caf..f7a2ebc6a 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -12,7 +12,7 @@ #include "../common/strlib.h" #include "party.h" -#include "atcommand.h" //msg_txt() +#include "atcommand.h" //msg_txt() #include "pc.h" #include "map.h" #include "instance.h" @@ -29,8 +29,8 @@ #include <string.h> -static DBMap *party_db; // int party_id -> struct party_data* (releases data) -static DBMap *party_booking_db; // int char_id -> struct party_booking_ad_info* (releases data) // Party Booking [Spiria] +static DBMap* party_db; // int party_id -> struct party_data* (releases data) +static DBMap* party_booking_db; // int char_id -> struct party_booking_ad_info* (releases data) // Party Booking [Spiria] static unsigned long party_booking_nextid = 1; int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data); @@ -39,66 +39,67 @@ int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data); * Fills the given party_member structure according to the sd provided. * Used when creating/adding people to a party. [Skotlex] *------------------------------------------*/ -static void party_fill_member(struct party_member *member, struct map_session_data *sd, unsigned int leader) +static void party_fill_member(struct party_member* member, struct map_session_data* sd, unsigned int leader) { - member->account_id = sd->status.account_id; - member->char_id = sd->status.char_id; - safestrncpy(member->name, sd->status.name, NAME_LENGTH); - member->class_ = sd->status.class_; - member->map = sd->mapindex; - member->lv = sd->status.base_level; - member->online = 1; - member->leader = leader; + member->account_id = sd->status.account_id; + member->char_id = sd->status.char_id; + safestrncpy(member->name, sd->status.name, NAME_LENGTH); + member->class_ = sd->status.class_; + member->map = sd->mapindex; + member->lv = sd->status.base_level; + member->online = 1; + member->leader = leader; } /// Get the member_id of a party member. /// Return -1 if not in party. -int party_getmemberid(struct party_data *p, struct map_session_data *sd) +int party_getmemberid(struct party_data* p, struct map_session_data* sd) { - int member_id; - nullpo_retr(-1, p); - if (sd == NULL) - return -1;// no player - ARR_FIND(0, MAX_PARTY, member_id, - p->party.member[member_id].account_id == sd->status.account_id && - p->party.member[member_id].char_id == sd->status.char_id); - if (member_id == MAX_PARTY) - return -1;// not found - return member_id; + int member_id; + nullpo_retr(-1, p); + if( sd == NULL ) + return -1;// no player + ARR_FIND(0, MAX_PARTY, member_id, + p->party.member[member_id].account_id == sd->status.account_id && + p->party.member[member_id].char_id == sd->status.char_id); + if( member_id == MAX_PARTY ) + return -1;// not found + return member_id; } /*========================================== * Request an available sd of this party *------------------------------------------*/ -struct map_session_data *party_getavailablesd(struct party_data *p) { - int i; - nullpo_retr(NULL, p); - ARR_FIND(0, MAX_PARTY, i, p->data[i].sd != NULL); - return(i < MAX_PARTY) ? p->data[i].sd : NULL; +struct map_session_data* party_getavailablesd(struct party_data *p) +{ + int i; + nullpo_retr(NULL, p); + ARR_FIND(0, MAX_PARTY, i, p->data[i].sd != NULL); + return( i < MAX_PARTY ) ? p->data[i].sd : NULL; } /*========================================== * Retrieves and validates the sd pointer for this party member [Skotlex] *------------------------------------------*/ -static TBL_PC *party_sd_check(int party_id, int account_id, int char_id) +static TBL_PC* party_sd_check(int party_id, int account_id, int char_id) { - TBL_PC *sd = map_id2sd(account_id); + TBL_PC* sd = map_id2sd(account_id); - if (!(sd && sd->status.char_id == char_id)) - return NULL; + if (!(sd && sd->status.char_id == char_id)) + return NULL; - if (sd->status.party_id == 0) - sd->status.party_id = party_id;// auto-join if not in a party - if (sd->status.party_id != party_id) { - //If player belongs to a different party, kick him out. - intif_party_leave(party_id,account_id,char_id); - return NULL; - } + if( sd->status.party_id == 0 ) + sd->status.party_id = party_id;// auto-join if not in a party + if (sd->status.party_id != party_id) + { //If player belongs to a different party, kick him out. + intif_party_leave(party_id,account_id,char_id); + return NULL; + } - return sd; + return sd; } /*========================================== @@ -107,303 +108,318 @@ static TBL_PC *party_sd_check(int party_id, int account_id, int char_id) *------------------------------------------*/ void do_final_party(void) { - party_db->destroy(party_db,NULL); - party_booking_db->destroy(party_booking_db,NULL); // Party Booking [Spiria] + party_db->destroy(party_db,NULL); + party_booking_db->destroy(party_booking_db,NULL); // Party Booking [Spiria] } // Constructor, init vars void do_init_party(void) { - party_db = idb_alloc(DB_OPT_RELEASE_DATA); - party_booking_db = idb_alloc(DB_OPT_RELEASE_DATA); // Party Booking [Spiria] - add_timer_func_list(party_send_xy_timer, "party_send_xy_timer"); - add_timer_interval(gettick()+battle_config.party_update_interval, party_send_xy_timer, 0, 0, battle_config.party_update_interval); + party_db = idb_alloc(DB_OPT_RELEASE_DATA); + party_booking_db = idb_alloc(DB_OPT_RELEASE_DATA); // Party Booking [Spiria] + add_timer_func_list(party_send_xy_timer, "party_send_xy_timer"); + add_timer_interval(gettick()+battle_config.party_update_interval, party_send_xy_timer, 0, 0, battle_config.party_update_interval); } /// Party data lookup using party id. -struct party_data *party_search(int party_id) { - if (!party_id) - return NULL; - return (struct party_data *)idb_get(party_db,party_id); +struct party_data* party_search(int party_id) +{ + if(!party_id) + return NULL; + return (struct party_data*)idb_get(party_db,party_id); } /// Party data lookup using party name. -struct party_data *party_searchname(const char *str) { - struct party_data *p; +struct party_data* party_searchname(const char* str) +{ + struct party_data* p; - DBIterator *iter = db_iterator(party_db); - for (p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter)) { - if (strncmpi(p->party.name,str,NAME_LENGTH) == 0) - break; - } - dbi_destroy(iter); + DBIterator *iter = db_iterator(party_db); + for( p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter) ) + { + if( strncmpi(p->party.name,str,NAME_LENGTH) == 0 ) + break; + } + dbi_destroy(iter); - return p; + return p; } int party_create(struct map_session_data *sd,char *name,int item,int item2) { - struct party_member leader; - char tname[NAME_LENGTH]; + struct party_member leader; + char tname[NAME_LENGTH]; - safestrncpy(tname, name, NAME_LENGTH); - trim(tname); + safestrncpy(tname, name, NAME_LENGTH); + trim(tname); - if (!tname[0]) { - // empty name - return 0; - } + if( !tname[0] ) + {// empty name + return 0; + } - if (sd->status.party_id > 0 || sd->party_joining || sd->party_creating) { - // already associated with a party - clif_party_created(sd,2); - return 0; - } + if( sd->status.party_id > 0 || sd->party_joining || sd->party_creating ) + {// already associated with a party + clif_party_created(sd,2); + return 0; + } - sd->party_creating = true; + sd->party_creating = true; - party_fill_member(&leader, sd, 1); + party_fill_member(&leader, sd, 1); - intif_create_party(&leader,name,item,item2); - return 0; + intif_create_party(&leader,name,item,item2); + return 0; } void party_created(int account_id,int char_id,int fail,int party_id,char *name) { - struct map_session_data *sd; - sd=map_id2sd(account_id); - - if (!sd || sd->status.char_id != char_id || !sd->party_creating) { - //Character logged off before creation ack? - if (!fail) //break up party since player could not be added to it. - intif_party_leave(party_id,account_id,char_id); - return; - } - - sd->party_creating = false; - - if (!fail) { - sd->status.party_id = party_id; - clif_party_created(sd,0); //Success message - //We don't do any further work here because the char-server sends a party info packet right after creating the party. - } else { - clif_party_created(sd,1); // "party name already exists" - } + struct map_session_data *sd; + sd=map_id2sd(account_id); + + if (!sd || sd->status.char_id != char_id || !sd->party_creating ) + { //Character logged off before creation ack? + if (!fail) //break up party since player could not be added to it. + intif_party_leave(party_id,account_id,char_id); + return; + } + + sd->party_creating = false; + + if( !fail ) { + sd->status.party_id = party_id; + clif_party_created(sd,0); //Success message + //We don't do any further work here because the char-server sends a party info packet right after creating the party. + } else { + clif_party_created(sd,1); // "party name already exists" + } } int party_request_info(int party_id, int char_id) { - return intif_request_partyinfo(party_id, char_id); + return intif_request_partyinfo(party_id, char_id); } /// Invoked (from char-server) when the party info is not found. int party_recv_noinfo(int party_id, int char_id) { - struct map_session_data *sd; - - party_broken(party_id); - if (char_id != 0) { // requester - sd = map_charid2sd(char_id); - if (sd && sd->status.party_id == party_id) - sd->status.party_id = 0; - } - return 0; + struct map_session_data* sd; + + party_broken(party_id); + if( char_id != 0 )// requester + { + sd = map_charid2sd(char_id); + if( sd && sd->status.party_id == party_id ) + sd->status.party_id = 0; + } + return 0; } static void party_check_state(struct party_data *p) { - int i; - memset(&p->state, 0, sizeof(p->state)); - for (i = 0; i < MAX_PARTY; i ++) { - if (!p->party.member[i].online) continue; //Those not online shouldn't aport to skill usage and all that. - switch (p->party.member[i].class_) { - case JOB_MONK: - case JOB_BABY_MONK: - case JOB_CHAMPION: - p->state.monk = 1; - break; - case JOB_STAR_GLADIATOR: - p->state.sg = 1; - break; - case JOB_SUPER_NOVICE: - case JOB_SUPER_BABY: - p->state.snovice = 1; - break; - case JOB_TAEKWON: - p->state.tk = 1; - break; - } - } + int i; + memset(&p->state, 0, sizeof(p->state)); + for (i = 0; i < MAX_PARTY; i ++) + { + if (!p->party.member[i].online) continue; //Those not online shouldn't aport to skill usage and all that. + switch (p->party.member[i].class_) { + case JOB_MONK: + case JOB_BABY_MONK: + case JOB_CHAMPION: + p->state.monk = 1; + break; + case JOB_STAR_GLADIATOR: + p->state.sg = 1; + break; + case JOB_SUPER_NOVICE: + case JOB_SUPER_BABY: + p->state.snovice = 1; + break; + case JOB_TAEKWON: + p->state.tk = 1; + break; + } + } } -int party_recv_info(struct party *sp, int char_id) +int party_recv_info(struct party* sp, int char_id) { - struct party_data *p; - struct party_member *member; - struct map_session_data *sd; - int removed[MAX_PARTY];// member_id in old data - int removed_count = 0; - int added[MAX_PARTY];// member_id in new data - int added_count = 0; - int i; - int member_id; - - nullpo_ret(sp); - - p = (struct party_data *)idb_get(party_db, sp->party_id); - if (p != NULL) { // diff members - for (member_id = 0; member_id < MAX_PARTY; ++member_id) { - member = &p->party.member[member_id]; - if (member->char_id == 0) - continue;// empty - ARR_FIND(0, MAX_PARTY, i, - sp->member[i].account_id == member->account_id && - sp->member[i].char_id == member->char_id); - if (i == MAX_PARTY) - removed[removed_count++] = member_id; - } - for (member_id = 0; member_id < MAX_PARTY; ++member_id) { - member = &sp->member[member_id]; - if (member->char_id == 0) - continue;// empty - ARR_FIND(0, MAX_PARTY, i, - p->party.member[i].account_id == member->account_id && - p->party.member[i].char_id == member->char_id); - if (i == MAX_PARTY) - added[added_count++] = member_id; - } - } else { - for (member_id = 0; member_id < MAX_PARTY; ++member_id) - if (sp->member[member_id].char_id != 0) - added[added_count++] = member_id; - CREATE(p, struct party_data, 1); - idb_put(party_db, sp->party_id, p); - } - while (removed_count > 0) { // no longer in party - member_id = removed[--removed_count]; - sd = p->data[member_id].sd; - if (sd == NULL) - continue;// not online - party_member_withdraw(sp->party_id, sd->status.account_id, sd->status.char_id); - } - memcpy(&p->party, sp, sizeof(struct party)); - memset(&p->state, 0, sizeof(p->state)); - memset(&p->data, 0, sizeof(p->data)); - for (member_id = 0; member_id < MAX_PARTY; member_id++) { - member = &p->party.member[member_id]; - if (member->char_id == 0) - continue;// empty - p->data[member_id].sd = party_sd_check(sp->party_id, member->account_id, member->char_id); - } - party_check_state(p); - while (added_count > 0) { // new in party - member_id = added[--added_count]; - sd = p->data[member_id].sd; - if (sd == NULL) - continue;// not online - clif_charnameupdate(sd); //Update other people's display. [Skotlex] - clif_party_member_info(p,sd); - clif_party_option(p,sd,0x100); - clif_party_info(p,NULL); - if (p->instance_id != 0) - clif_instance_join(sd->fd, p->instance_id); - } - if (char_id != 0) { // requester - sd = map_charid2sd(char_id); - if (sd && sd->status.party_id == sp->party_id && party_getmemberid(p,sd) == -1) - sd->status.party_id = 0;// was not in the party - } - return 0; + struct party_data* p; + struct party_member* member; + struct map_session_data* sd; + int removed[MAX_PARTY];// member_id in old data + int removed_count = 0; + int added[MAX_PARTY];// member_id in new data + int added_count = 0; + int i; + int member_id; + + nullpo_ret(sp); + + p = (struct party_data*)idb_get(party_db, sp->party_id); + if( p != NULL )// diff members + { + for( member_id = 0; member_id < MAX_PARTY; ++member_id ) + { + member = &p->party.member[member_id]; + if( member->char_id == 0 ) + continue;// empty + ARR_FIND(0, MAX_PARTY, i, + sp->member[i].account_id == member->account_id && + sp->member[i].char_id == member->char_id); + if( i == MAX_PARTY ) + removed[removed_count++] = member_id; + } + for( member_id = 0; member_id < MAX_PARTY; ++member_id ) + { + member = &sp->member[member_id]; + if( member->char_id == 0 ) + continue;// empty + ARR_FIND(0, MAX_PARTY, i, + p->party.member[i].account_id == member->account_id && + p->party.member[i].char_id == member->char_id); + if( i == MAX_PARTY ) + added[added_count++] = member_id; + } + } + else + { + for( member_id = 0; member_id < MAX_PARTY; ++member_id ) + if( sp->member[member_id].char_id != 0 ) + added[added_count++] = member_id; + CREATE(p, struct party_data, 1); + idb_put(party_db, sp->party_id, p); + } + while( removed_count > 0 )// no longer in party + { + member_id = removed[--removed_count]; + sd = p->data[member_id].sd; + if( sd == NULL ) + continue;// not online + party_member_withdraw(sp->party_id, sd->status.account_id, sd->status.char_id); + } + memcpy(&p->party, sp, sizeof(struct party)); + memset(&p->state, 0, sizeof(p->state)); + memset(&p->data, 0, sizeof(p->data)); + for( member_id = 0; member_id < MAX_PARTY; member_id++ ) + { + member = &p->party.member[member_id]; + if ( member->char_id == 0 ) + continue;// empty + p->data[member_id].sd = party_sd_check(sp->party_id, member->account_id, member->char_id); + } + party_check_state(p); + while( added_count > 0 )// new in party + { + member_id = added[--added_count]; + sd = p->data[member_id].sd; + if( sd == NULL ) + continue;// not online + clif_charnameupdate(sd); //Update other people's display. [Skotlex] + clif_party_member_info(p,sd); + clif_party_option(p,sd,0x100); + clif_party_info(p,NULL); + if( p->instance_id != 0 ) + clif_instance_join(sd->fd, p->instance_id); + } + if( char_id != 0 )// requester + { + sd = map_charid2sd(char_id); + if( sd && sd->status.party_id == sp->party_id && party_getmemberid(p,sd) == -1 ) + sd->status.party_id = 0;// was not in the party + } + return 0; } int party_invite(struct map_session_data *sd,struct map_session_data *tsd) { - struct party_data *p; - int i; - - nullpo_ret(sd); - - if ((p = party_search(sd->status.party_id)) == NULL) - return 0; - - // confirm if this player is a party leader - ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd); - - if (i == MAX_PARTY || !p->party.member[i].leader) { - clif_displaymessage(sd->fd, msg_txt(282)); - return 0; - } - - // confirm if there is an open slot in the party - ARR_FIND(0, MAX_PARTY, i, p->party.member[i].account_id == 0); - - if (i == MAX_PARTY) { - clif_party_inviteack(sd, (tsd?tsd->status.name:""), 3); - return 0; - } - - // confirm whether the account has the ability to invite before checking the player - if (!pc_has_permission(sd, PC_PERM_PARTY) || (tsd && !pc_has_permission(tsd, PC_PERM_PARTY))) { - clif_displaymessage(sd->fd, msg_txt(81)); // "Your GM level doesn't authorize you to preform this action on the specified player." - return 0; - } - - if (tsd == NULL) { - clif_party_inviteack(sd, "", 7); - return 0; - } - - if (!battle_config.invite_request_check) { - if (tsd->guild_invite>0 || tsd->trade_partner || tsd->adopt_invite) { - clif_party_inviteack(sd,tsd->status.name,0); - return 0; - } - } - - if (!tsd->fd) { //You can't invite someone who has already disconnected. - clif_party_inviteack(sd,tsd->status.name,1); - return 0; - } - - if (tsd->status.party_id > 0 || tsd->party_invite > 0) { - // already associated with a party - clif_party_inviteack(sd,tsd->status.name,0); - return 0; - } - - tsd->party_invite=sd->status.party_id; - tsd->party_invite_account=sd->status.account_id; - - clif_party_invite(sd,tsd); - return 1; + struct party_data *p; + int i; + + nullpo_ret(sd); + + if( ( p = party_search(sd->status.party_id) ) == NULL ) + return 0; + + // confirm if this player is a party leader + ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd); + + if( i == MAX_PARTY || !p->party.member[i].leader ) { + clif_displaymessage(sd->fd, msg_txt(282)); + return 0; + } + + // confirm if there is an open slot in the party + ARR_FIND(0, MAX_PARTY, i, p->party.member[i].account_id == 0); + + if( i == MAX_PARTY ) { + clif_party_inviteack(sd, (tsd?tsd->status.name:""), 3); + return 0; + } + + // confirm whether the account has the ability to invite before checking the player + if( !pc_has_permission(sd, PC_PERM_PARTY) || (tsd && !pc_has_permission(tsd, PC_PERM_PARTY)) ) { + clif_displaymessage(sd->fd, msg_txt(81)); // "Your GM level doesn't authorize you to preform this action on the specified player." + return 0; + } + + if( tsd == NULL) { + clif_party_inviteack(sd, "", 7); + return 0; + } + + if(!battle_config.invite_request_check) { + if (tsd->guild_invite>0 || tsd->trade_partner || tsd->adopt_invite) { + clif_party_inviteack(sd,tsd->status.name,0); + return 0; + } + } + + if (!tsd->fd) { //You can't invite someone who has already disconnected. + clif_party_inviteack(sd,tsd->status.name,1); + return 0; + } + + if( tsd->status.party_id > 0 || tsd->party_invite > 0 ) + {// already associated with a party + clif_party_inviteack(sd,tsd->status.name,0); + return 0; + } + + tsd->party_invite=sd->status.party_id; + tsd->party_invite_account=sd->status.account_id; + + clif_party_invite(sd,tsd); + return 1; } void party_reply_invite(struct map_session_data *sd,int party_id,int flag) { - struct map_session_data *tsd; - struct party_member member; - - if (sd->party_invite != party_id) { - // forged - sd->party_invite = 0; - sd->party_invite_account = 0; - return; - } - tsd = map_id2sd(sd->party_invite_account); - - if (flag == 1 && !sd->party_creating && !sd->party_joining) { - // accepted and allowed - sd->party_joining = true; - party_fill_member(&member, sd, 0); - intif_party_addmember(sd->party_invite, &member); - } else { - // rejected or failure - sd->party_invite = 0; - sd->party_invite_account = 0; - if (tsd != NULL) - clif_party_inviteack(tsd,sd->status.name,1); - } + struct map_session_data* tsd; + struct party_member member; + + if( sd->party_invite != party_id ) + {// forged + sd->party_invite = 0; + sd->party_invite_account = 0; + return; + } + tsd = map_id2sd(sd->party_invite_account); + + if( flag == 1 && !sd->party_creating && !sd->party_joining ) + {// accepted and allowed + sd->party_joining = true; + party_fill_member(&member, sd, 0); + intif_party_addmember(sd->party_invite, &member); + } + else + {// rejected or failure + sd->party_invite = 0; + sd->party_invite_account = 0; + if( tsd != NULL ) + clif_party_inviteack(tsd,sd->status.name,1); + } } //Invoked when a player joins: @@ -412,253 +428,263 @@ void party_reply_invite(struct map_session_data *sd,int party_id,int flag) //- Player must be authed/active and belong to a party before calling this method void party_member_joined(struct map_session_data *sd) { - struct party_data *p = party_search(sd->status.party_id); - int i; - if (!p) { - party_request_info(sd->status.party_id, sd->status.char_id); - return; - } - ARR_FIND(0, MAX_PARTY, i, p->party.member[i].account_id == sd->status.account_id && p->party.member[i].char_id == sd->status.char_id); - if (i < MAX_PARTY) { - p->data[i].sd = sd; - if (p->instance_id) - clif_instance_join(sd->fd,p->instance_id); - } else - sd->status.party_id = 0; //He does not belongs to the party really? + struct party_data* p = party_search(sd->status.party_id); + int i; + if (!p) + { + party_request_info(sd->status.party_id, sd->status.char_id); + return; + } + ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == sd->status.account_id && p->party.member[i].char_id == sd->status.char_id ); + if (i < MAX_PARTY) + { + p->data[i].sd = sd; + if( p->instance_id ) + clif_instance_join(sd->fd,p->instance_id); + } + else + sd->status.party_id = 0; //He does not belongs to the party really? } /// Invoked (from char-server) when a new member is added to the party. /// flag: 0-success, 1-failure int party_member_added(int party_id,int account_id,int char_id, int flag) { - struct map_session_data *sd = map_id2sd(account_id),*sd2; - struct party_data *p = party_search(party_id); - int i; - - if (sd == NULL || sd->status.char_id != char_id || !sd->party_joining) { - if (!flag) //Char logged off before being accepted into party. - intif_party_leave(party_id,account_id,char_id); - return 0; - } - - sd2 = map_id2sd(sd->party_invite_account); - - sd->party_joining = false; - sd->party_invite = 0; - sd->party_invite_account = 0; - - if (!p) { - ShowError("party_member_added: party %d not found.\n",party_id); - intif_party_leave(party_id,account_id,char_id); - return 0; - } - - if (flag) { - // failed - if (sd2 != NULL) - clif_party_inviteack(sd2,sd->status.name,3); - return 0; - } - - sd->status.party_id = party_id; - - clif_party_member_info(p,sd); - clif_party_option(p,sd,0x100); - clif_party_info(p,sd); - - if (sd2 != NULL) - clif_party_inviteack(sd2,sd->status.name,2); - - for (i = 0; i < ARRAYLENGTH(p->data); ++i) { - // hp of the other party members - sd2 = p->data[i].sd; - if (sd2 && sd2->status.account_id != account_id && sd2->status.char_id != char_id) - clif_hpmeter_single(sd->fd, sd2->bl.id, sd2->battle_status.hp, sd2->battle_status.max_hp); - } - clif_party_hp(sd); - clif_party_xy(sd); - clif_charnameupdate(sd); //Update char name's display [Skotlex] - - if (p->instance_id) - clif_instance_join(sd->fd, p->instance_id); - - return 0; + struct map_session_data *sd = map_id2sd(account_id),*sd2; + struct party_data *p = party_search(party_id); + int i; + + if(sd == NULL || sd->status.char_id != char_id || !sd->party_joining ) { + if (!flag) //Char logged off before being accepted into party. + intif_party_leave(party_id,account_id,char_id); + return 0; + } + + sd2 = map_id2sd(sd->party_invite_account); + + sd->party_joining = false; + sd->party_invite = 0; + sd->party_invite_account = 0; + + if (!p) { + ShowError("party_member_added: party %d not found.\n",party_id); + intif_party_leave(party_id,account_id,char_id); + return 0; + } + + if( flag ) + {// failed + if( sd2 != NULL ) + clif_party_inviteack(sd2,sd->status.name,3); + return 0; + } + + sd->status.party_id = party_id; + + clif_party_member_info(p,sd); + clif_party_option(p,sd,0x100); + clif_party_info(p,sd); + + if( sd2 != NULL ) + clif_party_inviteack(sd2,sd->status.name,2); + + for( i = 0; i < ARRAYLENGTH(p->data); ++i ) + {// hp of the other party members + sd2 = p->data[i].sd; + if( sd2 && sd2->status.account_id != account_id && sd2->status.char_id != char_id ) + clif_hpmeter_single(sd->fd, sd2->bl.id, sd2->battle_status.hp, sd2->battle_status.max_hp); + } + clif_party_hp(sd); + clif_party_xy(sd); + clif_charnameupdate(sd); //Update char name's display [Skotlex] + + if( p->instance_id ) + clif_instance_join(sd->fd, p->instance_id); + + return 0; } /// Party member 'sd' requesting kick of member with <account_id, name>. -int party_removemember(struct map_session_data *sd, int account_id, char *name) +int party_removemember(struct map_session_data* sd, int account_id, char* name) { - struct party_data *p; - int i; - - p = party_search(sd->status.party_id); - if (p == NULL) - return 0; - - // check the requesting char's party membership - ARR_FIND(0, MAX_PARTY, i, p->party.member[i].account_id == sd->status.account_id && p->party.member[i].char_id == sd->status.char_id); - if (i == MAX_PARTY) - return 0; // request from someone not in party? o.O - if (!p->party.member[i].leader) - return 0; // only party leader may remove members - - ARR_FIND(0, MAX_PARTY, i, p->party.member[i].account_id == account_id && strncmp(p->party.member[i].name,name,NAME_LENGTH) == 0); - if (i == MAX_PARTY) - return 0; // no such char in party - - intif_party_leave(p->party.party_id,account_id,p->party.member[i].char_id); - return 1; + struct party_data *p; + int i; + + p = party_search(sd->status.party_id); + if( p == NULL ) + return 0; + + // check the requesting char's party membership + ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == sd->status.account_id && p->party.member[i].char_id == sd->status.char_id ); + if( i == MAX_PARTY ) + return 0; // request from someone not in party? o.O + if( !p->party.member[i].leader ) + return 0; // only party leader may remove members + + ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && strncmp(p->party.member[i].name,name,NAME_LENGTH) == 0 ); + if( i == MAX_PARTY ) + return 0; // no such char in party + + intif_party_leave(p->party.party_id,account_id,p->party.member[i].char_id); + return 1; } /// Party member 'sd' requesting exit from party. int party_leave(struct map_session_data *sd) { - struct party_data *p; - int i; + struct party_data *p; + int i; - p = party_search(sd->status.party_id); - if (p == NULL) - return 0; + p = party_search(sd->status.party_id); + if( p == NULL ) + return 0; - ARR_FIND(0, MAX_PARTY, i, p->party.member[i].account_id == sd->status.account_id && p->party.member[i].char_id == sd->status.char_id); - if (i == MAX_PARTY) - return 0; + ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == sd->status.account_id && p->party.member[i].char_id == sd->status.char_id ); + if( i == MAX_PARTY ) + return 0; - intif_party_leave(p->party.party_id,sd->status.account_id,sd->status.char_id); - return 1; + intif_party_leave(p->party.party_id,sd->status.account_id,sd->status.char_id); + return 1; } /// Invoked (from char-server) when a party member leaves the party. int party_member_withdraw(int party_id, int account_id, int char_id) { - struct map_session_data *sd = map_id2sd(account_id); - struct party_data *p = party_search(party_id); - - if (p) { - int i; - ARR_FIND(0, MAX_PARTY, i, p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id); - if (i < MAX_PARTY) { - clif_party_withdraw(p,sd,account_id,p->party.member[i].name,0x0); - memset(&p->party.member[i], 0, sizeof(p->party.member[0])); - memset(&p->data[i], 0, sizeof(p->data[0])); - p->party.count--; - party_check_state(p); - } - } - - if (sd && sd->status.party_id == party_id && sd->status.char_id == char_id) { - sd->status.party_id = 0; - clif_charnameupdate(sd); //Update name display [Skotlex] - //TODO: hp bars should be cleared too - if (p->instance_id) - instance_check_kick(sd); - } - - return 0; + struct map_session_data* sd = map_id2sd(account_id); + struct party_data* p = party_search(party_id); + + if( p ) + { + int i; + ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id ); + if( i < MAX_PARTY ) + { + clif_party_withdraw(p,sd,account_id,p->party.member[i].name,0x0); + memset(&p->party.member[i], 0, sizeof(p->party.member[0])); + memset(&p->data[i], 0, sizeof(p->data[0])); + p->party.count--; + party_check_state(p); + } + } + + if( sd && sd->status.party_id == party_id && sd->status.char_id == char_id ) + { + sd->status.party_id = 0; + clif_charnameupdate(sd); //Update name display [Skotlex] + //TODO: hp bars should be cleared too + if( p->instance_id ) + instance_check_kick(sd); + } + + return 0; } /// Invoked (from char-server) when a party is disbanded. int party_broken(int party_id) { - struct party_data *p; - int i; - - p = party_search(party_id); - if (p == NULL) - return 0; - - if (p->instance_id) { - instance[p->instance_id].party_id = 0; - instance_destroy(p->instance_id); - } - - for (i = 0; i < MAX_PARTY; i++) { - if (p->data[i].sd!=NULL) { - clif_party_withdraw(p,p->data[i].sd,p->party.member[i].account_id,p->party.member[i].name,0x10); - p->data[i].sd->status.party_id=0; - } - } - - idb_remove(party_db,party_id); - return 0; + struct party_data* p; + int i; + + p = party_search(party_id); + if( p == NULL ) + return 0; + + if( p->instance_id ) + { + instance[p->instance_id].party_id = 0; + instance_destroy( p->instance_id ); + } + + for( i = 0; i < MAX_PARTY; i++ ) + { + if( p->data[i].sd!=NULL ) + { + clif_party_withdraw(p,p->data[i].sd,p->party.member[i].account_id,p->party.member[i].name,0x10); + p->data[i].sd->status.party_id=0; + } + } + + idb_remove(party_db,party_id); + return 0; } int party_changeoption(struct map_session_data *sd,int exp,int item) { - nullpo_ret(sd); + nullpo_ret(sd); - if (sd->status.party_id==0) - return 0; - intif_party_changeoption(sd->status.party_id,sd->status.account_id,exp,item); - return 0; + if( sd->status.party_id==0) + return 0; + intif_party_changeoption(sd->status.party_id,sd->status.account_id,exp,item); + return 0; } int party_optionchanged(int party_id,int account_id,int exp,int item,int flag) { - struct party_data *p; - struct map_session_data *sd=map_id2sd(account_id); - if ((p=party_search(party_id))==NULL) - return 0; - - //Flag&1: Exp change denied. Flag&2: Item change denied. - if (!(flag&0x01) && p->party.exp != exp) - p->party.exp=exp; - if (!(flag&0x10) && p->party.item != item) { - p->party.item=item; - } - - clif_party_option(p,sd,flag); - return 0; + struct party_data *p; + struct map_session_data *sd=map_id2sd(account_id); + if( (p=party_search(party_id))==NULL) + return 0; + + //Flag&1: Exp change denied. Flag&2: Item change denied. + if(!(flag&0x01) && p->party.exp != exp) + p->party.exp=exp; + if(!(flag&0x10) && p->party.item != item) { + p->party.item=item; + } + + clif_party_option(p,sd,flag); + return 0; } bool party_changeleader(struct map_session_data *sd, struct map_session_data *tsd) { - struct party_data *p; - int mi, tmi; - - if (!sd || !sd->status.party_id) - return false; - - if (!tsd || tsd->status.party_id != sd->status.party_id) { - clif_displaymessage(sd->fd, msg_txt(283)); - return false; - } - - if (map[sd->bl.m].flag.partylock) { - clif_displaymessage(sd->fd, msg_txt(287)); - return false; - } - - if ((p = party_search(sd->status.party_id)) == NULL) - return false; - - ARR_FIND(0, MAX_PARTY, mi, p->data[mi].sd == sd); - if (mi == MAX_PARTY) - return false; //Shouldn't happen - - if (!p->party.member[mi].leader) { - //Need to be a party leader. - clif_displaymessage(sd->fd, msg_txt(282)); - return false; - } - - ARR_FIND(0, MAX_PARTY, tmi, p->data[tmi].sd == tsd); - if (tmi == MAX_PARTY) - return false; //Shouldn't happen - - //Change leadership. - p->party.member[mi].leader = 0; - if (p->data[mi].sd->fd) - clif_displaymessage(p->data[mi].sd->fd, msg_txt(284)); - - p->party.member[tmi].leader = 1; - if (p->data[tmi].sd->fd) - clif_displaymessage(p->data[tmi].sd->fd, msg_txt(285)); - - //Update info. - intif_party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id); - clif_party_info(p,NULL); - return true; + struct party_data *p; + int mi, tmi; + + if (!sd || !sd->status.party_id) + return false; + + if (!tsd || tsd->status.party_id != sd->status.party_id) { + clif_displaymessage(sd->fd, msg_txt(283)); + return false; + } + + if( map[sd->bl.m].flag.partylock ) + { + clif_displaymessage(sd->fd, msg_txt(287)); + return false; + } + + if ((p = party_search(sd->status.party_id)) == NULL) + return false; + + ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd ); + if (mi == MAX_PARTY) + return false; //Shouldn't happen + + if (!p->party.member[mi].leader) + { //Need to be a party leader. + clif_displaymessage(sd->fd, msg_txt(282)); + return false; + } + + ARR_FIND( 0, MAX_PARTY, tmi, p->data[tmi].sd == tsd); + if (tmi == MAX_PARTY) + return false; //Shouldn't happen + + //Change leadership. + p->party.member[mi].leader = 0; + if (p->data[mi].sd->fd) + clif_displaymessage(p->data[mi].sd->fd, msg_txt(284)); + + p->party.member[tmi].leader = 1; + if (p->data[tmi].sd->fd) + clif_displaymessage(p->data[tmi].sd->fd, msg_txt(285)); + + //Update info. + intif_party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id); + clif_party_info(p,NULL); + return true; } /// Invoked (from char-server) when a party member @@ -667,331 +693,338 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts /// - gains a level (disabled) int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short map,int online,int lv) { - struct party_member *m; - struct party_data *p; - int i; - - p = party_search(party_id); - if (p == NULL) - return 0; - - ARR_FIND(0, MAX_PARTY, i, p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id); - if (i == MAX_PARTY) { - ShowError("party_recv_movemap: char %d/%d not found in party %s (id:%d)",account_id,char_id,p->party.name,party_id); - return 0; - } - - m = &p->party.member[i]; - m->map = map; - m->online = online; - m->lv = lv; - //Check if they still exist on this map server - p->data[i].sd = party_sd_check(party_id, account_id, char_id); - - clif_party_info(p,NULL); - return 0; + struct party_member* m; + struct party_data* p; + int i; + + p = party_search(party_id); + if( p == NULL ) + return 0; + + ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id ); + if( i == MAX_PARTY ) + { + ShowError("party_recv_movemap: char %d/%d not found in party %s (id:%d)",account_id,char_id,p->party.name,party_id); + return 0; + } + + m = &p->party.member[i]; + m->map = map; + m->online = online; + m->lv = lv; + //Check if they still exist on this map server + p->data[i].sd = party_sd_check(party_id, account_id, char_id); + + clif_party_info(p,NULL); + return 0; } void party_send_movemap(struct map_session_data *sd) { - int i; - struct party_data *p; - - if (sd->status.party_id==0) - return; - - intif_party_changemap(sd,1); - - p=party_search(sd->status.party_id); - if (!p) return; - - if (sd->state.connect_new) { - //Note that this works because this function is invoked before connect_new is cleared. - clif_party_option(p,sd,0x100); - clif_party_info(p,sd); - clif_party_member_info(p,sd); - } - - if (sd->fd) { // synchronize minimap positions with the rest of the party - for (i=0; i < MAX_PARTY; i++) { - if (p->data[i].sd && - p->data[i].sd != sd && - p->data[i].sd->bl.m == sd->bl.m) { - clif_party_xy_single(sd->fd, p->data[i].sd); - clif_party_xy_single(p->data[i].sd->fd, sd); - } - } - } - return; + int i; + struct party_data *p; + + if( sd->status.party_id==0 ) + return; + + intif_party_changemap(sd,1); + + p=party_search(sd->status.party_id); + if (!p) return; + + if(sd->state.connect_new) { + //Note that this works because this function is invoked before connect_new is cleared. + clif_party_option(p,sd,0x100); + clif_party_info(p,sd); + clif_party_member_info(p,sd); + } + + if (sd->fd) { // synchronize minimap positions with the rest of the party + for(i=0; i < MAX_PARTY; i++) { + if (p->data[i].sd && + p->data[i].sd != sd && + p->data[i].sd->bl.m == sd->bl.m) + { + clif_party_xy_single(sd->fd, p->data[i].sd); + clif_party_xy_single(p->data[i].sd->fd, sd); + } + } + } + return; } void party_send_levelup(struct map_session_data *sd) { - intif_party_changemap(sd,1); + intif_party_changemap(sd,1); } int party_send_logout(struct map_session_data *sd) { - struct party_data *p; - int i; + struct party_data *p; + int i; - if (!sd->status.party_id) - return 0; + if(!sd->status.party_id) + return 0; - intif_party_changemap(sd,0); - p=party_search(sd->status.party_id); - if (!p) return 0; + intif_party_changemap(sd,0); + p=party_search(sd->status.party_id); + if(!p) return 0; - ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd); - if (i < MAX_PARTY) - memset(&p->data[i], 0, sizeof(p->data[0])); - else - ShowError("party_send_logout: Failed to locate member %d:%d in party %d!\n", sd->status.account_id, sd->status.char_id, p->party.party_id); + ARR_FIND( 0, MAX_PARTY, i, p->data[i].sd == sd ); + if( i < MAX_PARTY ) + memset(&p->data[i], 0, sizeof(p->data[0])); + else + ShowError("party_send_logout: Failed to locate member %d:%d in party %d!\n", sd->status.account_id, sd->status.char_id, p->party.party_id); - return 1; + return 1; } int party_send_message(struct map_session_data *sd,const 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); + 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); - // Chat logging type 'P' / Party Chat - log_chat(LOG_CHAT_PARTY, sd->status.party_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes); + // Chat logging type 'P' / Party Chat + log_chat(LOG_CHAT_PARTY, sd->status.party_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes); - return 0; + return 0; } int party_recv_message(int party_id,int account_id,const char *mes,int len) { - struct party_data *p; - if ((p=party_search(party_id))==NULL) - return 0; - clif_party_message(p,account_id,mes,len); - return 0; + struct party_data *p; + if( (p=party_search(party_id))==NULL) + return 0; + clif_party_message(p,account_id,mes,len); + return 0; } int party_skill_check(struct map_session_data *sd, int party_id, int skillid, int skilllv) { - struct party_data *p; - struct map_session_data *p_sd; - int i; - - if (!party_id || (p=party_search(party_id))==NULL) - return 0; - switch (skillid) { - case TK_COUNTER: //Increase Triple Attack rate of Monks. - if (!p->state.monk) return 0; - break; - case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators - if (!p->state.sg) return 0; - break; - case AM_TWILIGHT2: //Twilight Pharmacy, requires Super Novice - return p->state.snovice; - case AM_TWILIGHT3: //Twilight Pharmacy, Requires Taekwon - return p->state.tk; - default: - return 0; //Unknown case? - } - - for (i=0; i<MAX_PARTY; i++) { - if ((p_sd = p->data[i].sd) == NULL) - continue; - if (sd->bl.m != p_sd->bl.m) - continue; - switch (skillid) { - case TK_COUNTER: //Increase Triple Attack rate of Monks. - if ((p_sd->class_&MAPID_UPPERMASK) == MAPID_MONK - && pc_checkskill(p_sd,MO_TRIPLEATTACK)) { - sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,MO_TRIPLEATTACK, - 50+50*skilllv, //+100/150/200% rate - 0,0,skill_get_time(SG_FRIEND, 1)); - } - break; - case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators - if ((p_sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR - && sd->sc.data[SC_READYCOUNTER] - && pc_checkskill(p_sd,SG_FRIEND)) { - sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER, - 50+50*pc_checkskill(p_sd,SG_FRIEND), //+100/150/200% rate - 0,0,skill_get_time(SG_FRIEND, 1)); - } - break; - } - } - return 0; + struct party_data *p; + struct map_session_data *p_sd; + int i; + + if(!party_id || (p=party_search(party_id))==NULL) + return 0; + switch(skillid) { + case TK_COUNTER: //Increase Triple Attack rate of Monks. + if (!p->state.monk) return 0; + break; + case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators + if (!p->state.sg) return 0; + break; + case AM_TWILIGHT2: //Twilight Pharmacy, requires Super Novice + return p->state.snovice; + case AM_TWILIGHT3: //Twilight Pharmacy, Requires Taekwon + return p->state.tk; + default: + return 0; //Unknown case? + } + + for(i=0;i<MAX_PARTY;i++){ + if ((p_sd = p->data[i].sd) == NULL) + continue; + if (sd->bl.m != p_sd->bl.m) + continue; + switch(skillid) { + case TK_COUNTER: //Increase Triple Attack rate of Monks. + if((p_sd->class_&MAPID_UPPERMASK) == MAPID_MONK + && pc_checkskill(p_sd,MO_TRIPLEATTACK)) { + sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,MO_TRIPLEATTACK, + 50+50*skilllv, //+100/150/200% rate + 0,0,skill_get_time(SG_FRIEND, 1)); + } + break; + case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators + if((p_sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR + && sd->sc.data[SC_READYCOUNTER] + && pc_checkskill(p_sd,SG_FRIEND)) { + sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER, + 50+50*pc_checkskill(p_sd,SG_FRIEND), //+100/150/200% rate + 0,0,skill_get_time(SG_FRIEND, 1)); + } + break; + } + } + return 0; } int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct party_data *p; - - DBIterator *iter = db_iterator(party_db); - // for each existing party, - for (p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter)) { - int i; - - if (!p->party.count) { - // no online party members so do not iterate - continue; - } - - // for each member of this party, - for (i = 0; i < MAX_PARTY; i++) { - struct map_session_data *sd = p->data[i].sd; - if (!sd) continue; - - if (p->data[i].x != sd->bl.x || p->data[i].y != sd->bl.y) { - // perform position update - clif_party_xy(sd); - p->data[i].x = sd->bl.x; - p->data[i].y = sd->bl.y; - } - if (battle_config.party_hp_mode && p->data[i].hp != sd->battle_status.hp) { - // perform hp update - clif_party_hp(sd); - p->data[i].hp = sd->battle_status.hp; - } - } - } - dbi_destroy(iter); - - return 0; + struct party_data* p; + + DBIterator *iter = db_iterator(party_db); + // for each existing party, + for( p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter) ) + { + int i; + + if( !p->party.count ) + {// no online party members so do not iterate + continue; + } + + // for each member of this party, + for( i = 0; i < MAX_PARTY; i++ ) + { + struct map_session_data* sd = p->data[i].sd; + if( !sd ) continue; + + if( p->data[i].x != sd->bl.x || p->data[i].y != sd->bl.y ) + {// perform position update + clif_party_xy(sd); + p->data[i].x = sd->bl.x; + p->data[i].y = sd->bl.y; + } + if (battle_config.party_hp_mode && p->data[i].hp != sd->battle_status.hp) + {// perform hp update + clif_party_hp(sd); + p->data[i].hp = sd->battle_status.hp; + } + } + } + dbi_destroy(iter); + + return 0; } int party_send_xy_clear(struct party_data *p) { - int i; + int i; - nullpo_ret(p); + nullpo_ret(p); - for (i=0; i<MAX_PARTY; i++) { - if (!p->data[i].sd) continue; - p->data[i].hp = 0; - p->data[i].x = 0; - p->data[i].y = 0; - } - return 0; + for(i=0;i<MAX_PARTY;i++){ + if(!p->data[i].sd) continue; + p->data[i].hp = 0; + p->data[i].x = 0; + p->data[i].y = 0; + } + return 0; } // exp share and added zeny share [Valaris] -int party_exp_share(struct party_data *p, struct block_list *src, unsigned int base_exp, unsigned int job_exp, int zeny) +int party_exp_share(struct party_data* p, struct block_list* src, unsigned int base_exp, unsigned int job_exp, int zeny) { - struct map_session_data *sd[MAX_PARTY]; - unsigned int i, c; - - nullpo_ret(p); - - // count the number of players eligible for exp sharing - for (i = c = 0; i < MAX_PARTY; i++) { - if ((sd[c] = p->data[i].sd) == NULL || sd[c]->bl.m != src->m || pc_isdead(sd[c]) || (battle_config.idle_no_share && pc_isidle(sd[c]))) - continue; - c++; - } - if (c < 1) - return 0; - - base_exp/=c; - job_exp/=c; - zeny/=c; - - if (battle_config.party_even_share_bonus && c > 1) { - double bonus = 100 + battle_config.party_even_share_bonus*(c-1); - if (base_exp) - base_exp = (unsigned int) cap_value(base_exp * bonus/100, 0, UINT_MAX); - if (job_exp) - job_exp = (unsigned int) cap_value(job_exp * bonus/100, 0, UINT_MAX); - if (zeny) - zeny = (unsigned int) cap_value(zeny * bonus/100, INT_MIN, INT_MAX); - } - - for (i = 0; i < c; i++) { + struct map_session_data* sd[MAX_PARTY]; + unsigned int i, c; + + nullpo_ret(p); + + // count the number of players eligible for exp sharing + for (i = c = 0; i < MAX_PARTY; i++) { + if( (sd[c] = p->data[i].sd) == NULL || sd[c]->bl.m != src->m || pc_isdead(sd[c]) || (battle_config.idle_no_share && pc_isidle(sd[c])) ) + continue; + c++; + } + if (c < 1) + return 0; + + base_exp/=c; + job_exp/=c; + zeny/=c; + + if (battle_config.party_even_share_bonus && c > 1) + { + double bonus = 100 + battle_config.party_even_share_bonus*(c-1); + if (base_exp) + base_exp = (unsigned int) cap_value(base_exp * bonus/100, 0, UINT_MAX); + if (job_exp) + job_exp = (unsigned int) cap_value(job_exp * bonus/100, 0, UINT_MAX); + if (zeny) + zeny = (unsigned int) cap_value(zeny * bonus/100, INT_MIN, INT_MAX); + } + + for (i = 0; i < c; i++) { #ifdef RENEWAL_EXP - if (!(src && src->type == BL_MOB && ((TBL_MOB *)src)->db->mexp)) { - int rate = pc_level_penalty_mod(sd[i], (TBL_MOB *)src, 1); - base_exp = (unsigned int)cap_value(base_exp * rate / 100, 1, UINT_MAX); - job_exp = (unsigned int)cap_value(job_exp * rate / 100, 1, UINT_MAX); - } + if( !(src && src->type == BL_MOB && ((TBL_MOB*)src)->db->mexp) ){ + int rate = pc_level_penalty_mod(sd[i], (TBL_MOB*)src, 1); + base_exp = (unsigned int)cap_value(base_exp * rate / 100, 1, UINT_MAX); + job_exp = (unsigned int)cap_value(job_exp * rate / 100, 1, UINT_MAX); + } #endif - pc_gainexp(sd[i], src, base_exp, job_exp, false); + pc_gainexp(sd[i], src, base_exp, job_exp, false); - if (zeny) // zeny from mobs [Valaris] - pc_getzeny(sd[i],zeny,LOG_TYPE_PICKDROP_MONSTER,NULL); - } - return 0; + if (zeny) // zeny from mobs [Valaris] + pc_getzeny(sd[i],zeny,LOG_TYPE_PICKDROP_MONSTER,NULL); + } + return 0; } //Does party loot. first_charid holds the charid of the player who has time priority to take the item. -int party_share_loot(struct party_data *p, struct map_session_data *sd, struct item *item_data, int first_charid) +int party_share_loot(struct party_data* p, struct map_session_data* sd, struct item* item_data, int first_charid) { - TBL_PC *target = NULL; - int i; - if (p && p->party.item&2 && (first_charid || !(battle_config.party_share_type&1))) { - //item distribution to party members. - if (battle_config.party_share_type&2) { - //Round Robin - TBL_PC *psd; - i = p->itemc; - do { - i++; - if (i >= MAX_PARTY) - i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc" - - if ((psd = p->data[i].sd) == NULL || sd->bl.m != psd->bl.m || pc_isdead(psd) || (battle_config.idle_no_share && pc_isidle(psd))) - continue; - - if (pc_additem(psd,item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER)) - continue; //Chosen char can't pick up loot. - - //Successful pick. - p->itemc = i; - target = psd; - break; - } while (i != p->itemc); - } else { - //Random pick - TBL_PC *psd[MAX_PARTY]; - int count = 0; - //Collect pick candidates - for (i = 0; i < MAX_PARTY; i++) { - if ((psd[count] = p->data[i].sd) == NULL || psd[count]->bl.m != sd->bl.m || pc_isdead(psd[count]) || (battle_config.idle_no_share && pc_isidle(psd[count]))) - continue; - - count++; - } - while (count > 0) { //Pick a random member. - i = rnd()%count; - if (pc_additem(psd[i],item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER)) { - //Discard this receiver. - psd[i] = psd[count-1]; - count--; - } else { //Successful pick. - target = psd[i]; - break; - } - } - } - } - - if (!target) { - target = sd; //Give it to the char that picked it up - if ((i=pc_additem(sd,item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER))) - return i; - } - - if (p && battle_config.party_show_share_picker && battle_config.show_picker_item_type&(1<<itemdb_type(item_data->nameid))) - clif_party_show_picker(target, item_data); - - return 0; + TBL_PC* target = NULL; + int i; + if (p && p->party.item&2 && (first_charid || !(battle_config.party_share_type&1))) + { + //item distribution to party members. + if (battle_config.party_share_type&2) + { //Round Robin + TBL_PC* psd; + i = p->itemc; + do { + i++; + if (i >= MAX_PARTY) + i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc" + + if( (psd = p->data[i].sd) == NULL || sd->bl.m != psd->bl.m || pc_isdead(psd) || (battle_config.idle_no_share && pc_isidle(psd)) ) + continue; + + if (pc_additem(psd,item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER)) + continue; //Chosen char can't pick up loot. + + //Successful pick. + p->itemc = i; + target = psd; + break; + } while (i != p->itemc); + } + else + { //Random pick + TBL_PC* psd[MAX_PARTY]; + int count = 0; + //Collect pick candidates + for (i = 0; i < MAX_PARTY; i++) { + if( (psd[count] = p->data[i].sd) == NULL || psd[count]->bl.m != sd->bl.m || pc_isdead(psd[count]) || (battle_config.idle_no_share && pc_isidle(psd[count])) ) + continue; + + count++; + } + while (count > 0) { //Pick a random member. + i = rnd()%count; + if (pc_additem(psd[i],item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER)) + { //Discard this receiver. + psd[i] = psd[count-1]; + count--; + } else { //Successful pick. + target = psd[i]; + break; + } + } + } + } + + if (!target) { + target = sd; //Give it to the char that picked it up + if ((i=pc_additem(sd,item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER))) + return i; + } + + if( p && battle_config.party_show_share_picker && battle_config.show_picker_item_type&(1<<itemdb_type(item_data->nameid)) ) + clif_party_show_picker(target, item_data); + + return 0; } int party_send_dot_remove(struct map_session_data *sd) { - if (sd->status.party_id) - clif_party_xy_remove(sd); - return 0; + if (sd->status.party_id) + clif_party_xy_remove(sd); + return 0; } // To use for Taekwon's "Fighting Chant" @@ -999,166 +1032,174 @@ int party_send_dot_remove(struct map_session_data *sd) // party_foreachsamemap(party_sub_count, sd, 0, &c); int party_sub_count(struct block_list *bl, va_list ap) { - struct map_session_data *sd = (TBL_PC *)bl; + struct map_session_data *sd = (TBL_PC *)bl; - if (sd->state.autotrade) - return 0; + if (sd->state.autotrade) + return 0; - if (battle_config.idle_no_share && pc_isidle(sd)) - return 0; + if (battle_config.idle_no_share && pc_isidle(sd)) + return 0; - return 1; + return 1; } /// Executes 'func' for each party member on the same map and in range (0:whole map) -int party_foreachsamemap(int (*func)(struct block_list *,va_list),struct map_session_data *sd,int range,...) +int party_foreachsamemap(int (*func)(struct block_list*,va_list),struct map_session_data *sd,int range,...) { - struct party_data *p; - int i; - int x0,y0,x1,y1; - struct block_list *list[MAX_PARTY]; - int blockcount=0; - int total = 0; //Return value. - - nullpo_ret(sd); - - if ((p=party_search(sd->status.party_id))==NULL) - return 0; - - x0=sd->bl.x-range; - y0=sd->bl.y-range; - x1=sd->bl.x+range; - y1=sd->bl.y+range; - - for (i=0; i<MAX_PARTY; i++) { - struct map_session_data *psd = p->data[i].sd; - if (!psd) continue; - if (psd->bl.m!=sd->bl.m || !psd->bl.prev) - continue; - if (range && - (psd->bl.x<x0 || psd->bl.y<y0 || - psd->bl.x>x1 || psd->bl.y>y1)) - continue; - list[blockcount++]=&psd->bl; - } - - map_freeblock_lock(); - - for (i=0; i<blockcount; i++) { - va_list ap; - va_start(ap, range); - total += func(list[i], ap); - va_end(ap); - } - - map_freeblock_unlock(); - - return total; + struct party_data *p; + int i; + int x0,y0,x1,y1; + struct block_list *list[MAX_PARTY]; + int blockcount=0; + int total = 0; //Return value. + + nullpo_ret(sd); + + if((p=party_search(sd->status.party_id))==NULL) + return 0; + + x0=sd->bl.x-range; + y0=sd->bl.y-range; + x1=sd->bl.x+range; + y1=sd->bl.y+range; + + for(i=0;i<MAX_PARTY;i++) + { + struct map_session_data *psd = p->data[i].sd; + if(!psd) continue; + if(psd->bl.m!=sd->bl.m || !psd->bl.prev) + continue; + if(range && + (psd->bl.x<x0 || psd->bl.y<y0 || + psd->bl.x>x1 || psd->bl.y>y1 ) ) + continue; + list[blockcount++]=&psd->bl; + } + + map_freeblock_lock(); + + for(i=0;i<blockcount;i++) + { + va_list ap; + va_start(ap, range); + total += func(list[i], ap); + va_end(ap); + } + + map_freeblock_unlock(); + + return total; } /*========================================== * Party Booking in KRO [Spiria] *------------------------------------------*/ -static struct party_booking_ad_info *create_party_booking_data(void) { - struct party_booking_ad_info *pb_ad; - CREATE(pb_ad, struct party_booking_ad_info, 1); - pb_ad->index = party_booking_nextid++; - return pb_ad; +static struct party_booking_ad_info* create_party_booking_data(void) +{ + struct party_booking_ad_info *pb_ad; + CREATE(pb_ad, struct party_booking_ad_info, 1); + pb_ad->index = party_booking_nextid++; + return pb_ad; } -void party_booking_register(struct map_session_data *sd, short level, short mapid, short *job) +void party_booking_register(struct map_session_data *sd, short level, short mapid, short* job) { - struct party_booking_ad_info *pb_ad; - int i; - - pb_ad = (struct party_booking_ad_info *)idb_get(party_booking_db, sd->status.char_id); - - if (pb_ad == NULL) { - pb_ad = create_party_booking_data(); - idb_put(party_booking_db, sd->status.char_id, pb_ad); - } else { - // already registered - clif_PartyBookingRegisterAck(sd, 2); - return; - } - - memcpy(pb_ad->charname,sd->status.name,NAME_LENGTH); - pb_ad->starttime = (int)time(NULL); - pb_ad->p_detail.level = level; - pb_ad->p_detail.mapid = mapid; - - for (i=0; i<PARTY_BOOKING_JOBS; i++) - if (job[i] != 0xFF) - pb_ad->p_detail.job[i] = job[i]; - else pb_ad->p_detail.job[i] = -1; - - clif_PartyBookingRegisterAck(sd, 0); - clif_PartyBookingInsertNotify(sd, pb_ad); // Notice + struct party_booking_ad_info *pb_ad; + int i; + + pb_ad = (struct party_booking_ad_info*)idb_get(party_booking_db, sd->status.char_id); + + if( pb_ad == NULL ) + { + pb_ad = create_party_booking_data(); + idb_put(party_booking_db, sd->status.char_id, pb_ad); + } + else + {// already registered + clif_PartyBookingRegisterAck(sd, 2); + return; + } + + memcpy(pb_ad->charname,sd->status.name,NAME_LENGTH); + pb_ad->starttime = (int)time(NULL); + pb_ad->p_detail.level = level; + pb_ad->p_detail.mapid = mapid; + + for(i=0;i<PARTY_BOOKING_JOBS;i++) + if(job[i] != 0xFF) + pb_ad->p_detail.job[i] = job[i]; + else pb_ad->p_detail.job[i] = -1; + + clif_PartyBookingRegisterAck(sd, 0); + clif_PartyBookingInsertNotify(sd, pb_ad); // Notice } -void party_booking_update(struct map_session_data *sd, short *job) +void party_booking_update(struct map_session_data *sd, short* job) { - int i; - struct party_booking_ad_info *pb_ad; + int i; + struct party_booking_ad_info *pb_ad; - pb_ad = (struct party_booking_ad_info *)idb_get(party_booking_db, sd->status.char_id); + pb_ad = (struct party_booking_ad_info*)idb_get(party_booking_db, sd->status.char_id); - if (pb_ad == NULL) - return; + if( pb_ad == NULL ) + return; - pb_ad->starttime = (int)time(NULL);// Update time. + pb_ad->starttime = (int)time(NULL);// Update time. - for (i=0; i<PARTY_BOOKING_JOBS; i++) - if (job[i] != 0xFF) - pb_ad->p_detail.job[i] = job[i]; - else pb_ad->p_detail.job[i] = -1; + for(i=0;i<PARTY_BOOKING_JOBS;i++) + if(job[i] != 0xFF) + pb_ad->p_detail.job[i] = job[i]; + else pb_ad->p_detail.job[i] = -1; - clif_PartyBookingUpdateNotify(sd, pb_ad); + clif_PartyBookingUpdateNotify(sd, pb_ad); } void party_booking_search(struct map_session_data *sd, short level, short mapid, short job, unsigned long lastindex, short resultcount) { - struct party_booking_ad_info *pb_ad; - int i, count=0; - struct party_booking_ad_info *result_list[PARTY_BOOKING_RESULTS]; - bool more_result = false; - DBIterator *iter = db_iterator(party_booking_db); - - memset(result_list, 0, sizeof(result_list)); - - for (pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter)) { - if (pb_ad->index < lastindex || (level && (pb_ad->p_detail.level < level-15 || pb_ad->p_detail.level > level))) - continue; - if (count >= PARTY_BOOKING_RESULTS) { - more_result = true; - break; - } - if (mapid == 0 && job == -1) - result_list[count] = pb_ad; - else if (mapid == 0) { - for (i=0; i<PARTY_BOOKING_JOBS; i++) - if (pb_ad->p_detail.job[i] == job && job != -1) - result_list[count] = pb_ad; - } else if (job == -1) { - if (pb_ad->p_detail.mapid == mapid) - result_list[count] = pb_ad; - } - if (result_list[count]) { - count++; - } - } - dbi_destroy(iter); - clif_PartyBookingSearchAck(sd->fd, result_list, count, more_result); + struct party_booking_ad_info *pb_ad; + int i, count=0; + struct party_booking_ad_info* result_list[PARTY_BOOKING_RESULTS]; + bool more_result = false; + DBIterator* iter = db_iterator(party_booking_db); + + memset(result_list, 0, sizeof(result_list)); + + for( pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter) ) + { + if (pb_ad->index < lastindex || (level && (pb_ad->p_detail.level < level-15 || pb_ad->p_detail.level > level))) + continue; + if (count >= PARTY_BOOKING_RESULTS){ + more_result = true; + break; + } + if (mapid == 0 && job == -1) + result_list[count] = pb_ad; + else if (mapid == 0) { + for(i=0; i<PARTY_BOOKING_JOBS; i++) + if (pb_ad->p_detail.job[i] == job && job != -1) + result_list[count] = pb_ad; + } else if (job == -1){ + if (pb_ad->p_detail.mapid == mapid) + result_list[count] = pb_ad; + } + if( result_list[count] ) + { + count++; + } + } + dbi_destroy(iter); + clif_PartyBookingSearchAck(sd->fd, result_list, count, more_result); } bool party_booking_delete(struct map_session_data *sd) { - struct party_booking_ad_info *pb_ad; - - if ((pb_ad = (struct party_booking_ad_info *)idb_get(party_booking_db, sd->status.char_id))!=NULL) { - clif_PartyBookingDeleteNotify(sd, pb_ad->index); - idb_remove(party_booking_db,sd->status.char_id); - } - return true; + struct party_booking_ad_info* pb_ad; + + if((pb_ad = (struct party_booking_ad_info*)idb_get(party_booking_db, sd->status.char_id))!=NULL) + { + clif_PartyBookingDeleteNotify(sd, pb_ad->index); + idb_remove(party_booking_db,sd->status.char_id); + } + return true; } diff --git a/src/map/party.h b/src/map/party.h index 49f6513e9..9fde5a6a4 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -16,43 +16,43 @@ struct item; #define PARTY_BOOKING_RESULTS 10 struct party_member_data { - struct map_session_data *sd; - unsigned int hp; //For HP,x,y refreshing. - unsigned short x, y; + struct map_session_data *sd; + unsigned int hp; //For HP,x,y refreshing. + unsigned short x, y; }; struct party_data { - struct party party; - struct party_member_data data[MAX_PARTY]; - uint8 itemc; //For item distribution, position of last picker in party - unsigned int instance_id; - struct { - unsigned monk : 1; //There's at least one monk in party? - unsigned sg : 1; //There's at least one Star Gladiator in party? - unsigned snovice :1; //There's a Super Novice - unsigned tk : 1; //There's a taekwon - } state; + struct party party; + struct party_member_data data[MAX_PARTY]; + uint8 itemc; //For item distribution, position of last picker in party + unsigned int instance_id; + struct { + unsigned monk : 1; //There's at least one monk in party? + unsigned sg : 1; //There's at least one Star Gladiator in party? + unsigned snovice :1; //There's a Super Novice + unsigned tk : 1; //There's a taekwon + } state; }; struct party_booking_detail { - short level; + short level; short mapid; short job[PARTY_BOOKING_JOBS]; }; struct party_booking_ad_info { - unsigned long index; - char charname[NAME_LENGTH]; - long starttime; - struct party_booking_detail p_detail; + unsigned long index; + char charname[NAME_LENGTH]; + long starttime; + struct party_booking_detail p_detail; }; void do_init_party(void); void do_final_party(void); -struct party_data *party_search(int party_id); -struct party_data *party_searchname(const char *str); -int party_getmemberid(struct party_data *p, struct map_session_data *sd); -struct map_session_data *party_getavailablesd(struct party_data *p); +struct party_data* party_search(int party_id); +struct party_data* party_searchname(const char* str); +int party_getmemberid(struct party_data* p, struct map_session_data* sd); +struct map_session_data* party_getavailablesd(struct party_data *p); int party_create(struct map_session_data *sd,char *name, int item, int item2); void party_created(int account_id,int char_id,int fail,int party_id,char *name); @@ -65,7 +65,7 @@ int party_removemember(struct map_session_data *sd,int account_id,char *name); int party_member_withdraw(int party_id,int account_id,int char_id); void party_reply_invite(struct map_session_data *sd,int party_id,int flag); int party_recv_noinfo(int party_id, int char_id); -int party_recv_info(struct party *sp, int char_id); +int party_recv_info(struct party* sp, int char_id); int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short map,int online,int lv); int party_broken(int party_id); int party_optionchanged(int party_id,int account_id,int exp,int item,int flag); @@ -79,7 +79,7 @@ int party_recv_message(int party_id,int account_id,const char *mes,int len); int party_skill_check(struct map_session_data *sd, int party_id, int skillid, int skilllv); int party_send_xy_clear(struct party_data *p); int party_exp_share(struct party_data *p,struct block_list *src,unsigned int base_exp,unsigned int job_exp,int zeny); -int party_share_loot(struct party_data *p, struct map_session_data *sd, struct item *item_data, int first_charid); +int party_share_loot(struct party_data* p, struct map_session_data* sd, struct item* item_data, int first_charid); int party_send_dot_remove(struct map_session_data *sd); int party_sub_count(struct block_list *bl, va_list ap); int party_foreachsamemap(int (*func)(struct block_list *,va_list),struct map_session_data *sd,int range,...); @@ -87,8 +87,8 @@ int party_foreachsamemap(int (*func)(struct block_list *,va_list),struct map_ses /*========================================== * Party Booking in KRO [Spiria] *------------------------------------------*/ -void party_booking_register(struct map_session_data *sd, short level, short mapid, short *job); -void party_booking_update(struct map_session_data *sd, short *job); +void party_booking_register(struct map_session_data *sd, short level, short mapid, short* job); +void party_booking_update(struct map_session_data *sd, short* job); void party_booking_search(struct map_session_data *sd, short level, short mapid, short job, unsigned long lastindex, short resultcount); bool party_booking_delete(struct map_session_data *sd); diff --git a/src/map/path.c b/src/map/path.c index 4ccb73519..4505efcaa 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -17,15 +17,14 @@ #define MAX_HEAP 150 -struct tmp_path { - short x,y,dist,before,cost,flag; -}; +struct tmp_path { short x,y,dist,before,cost,flag;}; #define calc_index(x,y) (((x)+(y)*MAX_WALKPATH) & (MAX_WALKPATH*MAX_WALKPATH-1)) -const char walk_choices [3][3] = { - {1,0,7}, - {2,-1,6}, - {3,4,5}, +const char walk_choices [3][3] = +{ + {1,0,7}, + {2,-1,6}, + {3,4,5}, }; /*========================================== @@ -33,15 +32,15 @@ const char walk_choices [3][3] = { *------------------------------------------*/ static void push_heap_path(int *heap,struct tmp_path *tp,int index) { - int i,h; + int i,h; - h = heap[0]; - heap[0]++; + h = heap[0]; + heap[0]++; - for (i = (h-1)/2; h > 0 && tp[index].cost < tp[heap[i+1]].cost; i = (h-1)/2) - heap[h+1] = heap[i+1], h = i; + for( i = (h-1)/2; h > 0 && tp[index].cost < tp[heap[i+1]].cost; i = (h-1)/2 ) + heap[h+1] = heap[i+1], h = i; - heap[h+1] = index; + heap[h+1] = index; } /*========================================== @@ -50,18 +49,19 @@ static void push_heap_path(int *heap,struct tmp_path *tp,int index) *------------------------------------------*/ static void update_heap_path(int *heap,struct tmp_path *tp,int index) { - int i,h; + int i,h; - ARR_FIND(0, heap[0], h, heap[h+1] == index); - if (h == heap[0]) { - ShowError("update_heap_path bug\n"); - exit(EXIT_FAILURE); - } + ARR_FIND( 0, heap[0], h, heap[h+1] == index ); + if( h == heap[0] ) + { + ShowError("update_heap_path bug\n"); + exit(EXIT_FAILURE); + } - for (i = (h-1)/2; h > 0 && tp[index].cost < tp[heap[i+1]].cost; i = (h-1)/2) - heap[h+1] = heap[i+1], h = i; + for( i = (h-1)/2; h > 0 && tp[index].cost < tp[heap[i+1]].cost; i = (h-1)/2 ) + heap[h+1] = heap[i+1], h = i; - heap[h+1] = index; + heap[h+1] = index; } /*========================================== @@ -69,30 +69,31 @@ static void update_heap_path(int *heap,struct tmp_path *tp,int index) *------------------------------------------*/ static int pop_heap_path(int *heap,struct tmp_path *tp) { - int i,h,k; - int ret,last; + int i,h,k; + int ret,last; - if (heap[0] <= 0) - return -1; - ret = heap[1]; - last = heap[heap[0]]; - heap[0]--; + if( heap[0] <= 0 ) + return -1; + ret = heap[1]; + last = heap[heap[0]]; + heap[0]--; - for (h = 0, k = 2; k < heap[0]; k = k*2+2) { - if (tp[heap[k+1]].cost > tp[heap[k]].cost) - k--; - heap[h+1] = heap[k+1], h = k; - } + for( h = 0, k = 2; k < heap[0]; k = k*2+2 ) + { + if( tp[heap[k+1]].cost > tp[heap[k]].cost ) + k--; + heap[h+1] = heap[k+1], h = k; + } - if (k == heap[0]) - heap[h+1] = heap[k], h = k-1; + if( k == heap[0] ) + heap[h+1] = heap[k], h = k-1; - for (i = (h-1)/2; h > 0 && tp[heap[i+1]].cost > tp[last].cost; i = (h-1)/2) - heap[h+1] = heap[i+1], h = i; + for( i = (h-1)/2; h > 0 && tp[heap[i+1]].cost > tp[last].cost; i = (h-1)/2 ) + heap[h+1] = heap[i+1], h = i; - heap[h+1]=last; + heap[h+1]=last; - return ret; + return ret; } /*========================================== @@ -100,9 +101,9 @@ static int pop_heap_path(int *heap,struct tmp_path *tp) *------------------------------------------*/ static int calc_cost(struct tmp_path *p,int x1,int y1) { - int xd = abs(x1 - p->x); - int yd = abs(y1 - p->y); - return (xd + yd)*10 + p->dist; + int xd = abs(x1 - p->x); + int yd = abs(y1 - p->y); + return (xd + yd)*10 + p->dist; } /*========================================== @@ -110,36 +111,38 @@ static int calc_cost(struct tmp_path *p,int x1,int y1) *------------------------------------------*/ static int add_path(int *heap,struct tmp_path *tp,int x,int y,int dist,int before,int cost) { - int i; - - i = calc_index(x,y); - - if (tp[i].x == x && tp[i].y == y) { - if (tp[i].dist > dist) { - tp[i].dist = dist; - tp[i].before = before; - tp[i].cost = cost; - if (tp[i].flag) - push_heap_path(heap,tp,i); - else - update_heap_path(heap,tp,i); - tp[i].flag = 0; - } - return 0; - } - - if (tp[i].x || tp[i].y) - return 1; - - tp[i].x = x; - tp[i].y = y; - tp[i].dist = dist; - tp[i].before = before; - tp[i].cost = cost; - tp[i].flag = 0; - push_heap_path(heap,tp,i); - - return 0; + int i; + + i = calc_index(x,y); + + if( tp[i].x == x && tp[i].y == y ) + { + if( tp[i].dist > dist ) + { + tp[i].dist = dist; + tp[i].before = before; + tp[i].cost = cost; + if( tp[i].flag ) + push_heap_path(heap,tp,i); + else + update_heap_path(heap,tp,i); + tp[i].flag = 0; + } + return 0; + } + + if( tp[i].x || tp[i].y ) + return 1; + + tp[i].x = x; + tp[i].y = y; + tp[i].dist = dist; + tp[i].before = before; + tp[i].cost = cost; + tp[i].flag = 0; + push_heap_path(heap,tp,i); + + return 0; } /*========================================== @@ -148,45 +151,47 @@ static int add_path(int *heap,struct tmp_path *tp,int x,int y,int dist,int befor *------------------------------------------*/ int path_blownpos(int m,int x0,int y0,int dx,int dy,int count) { - struct map_data *md; - - if (!map[m].cell) - return -1; - md = &map[m]; - - if (count>25) { //Cap to prevent too much processing...? - ShowWarning("path_blownpos: count too many %d !\n",count); - count=25; - } - if (dx > 1 || dx < -1 || dy > 1 || dy < -1) { - ShowError("path_blownpos: illegal dx=%d or dy=%d !\n",dx,dy); - dx=(dx>0)?1:((dx<0)?-1:0); - dy=(dy>0)?1:((dy<0)?-1:0); - } - - while (count > 0 && (dx != 0 || dy != 0)) { - if (!map_getcellp(md,x0+dx,y0+dy,CELL_CHKPASS)) { - // attempt partial movement - int fx = (dx != 0 && map_getcellp(md,x0+dx,y0,CELL_CHKPASS)); - int fy = (dy != 0 && map_getcellp(md,x0,y0+dy,CELL_CHKPASS)); - if (fx && fy) { - if (rnd()&1) - dx=0; - else - dy=0; - } - if (!fx) - dx=0; - if (!fy) - dy=0; - } - - x0 += dx; - y0 += dy; - count--; - } - - return (x0<<16)|y0; //TODO: use 'struct point' here instead? + struct map_data *md; + + if( !map[m].cell ) + return -1; + md = &map[m]; + + if( count>25 ){ //Cap to prevent too much processing...? + ShowWarning("path_blownpos: count too many %d !\n",count); + count=25; + } + if( dx > 1 || dx < -1 || dy > 1 || dy < -1 ){ + ShowError("path_blownpos: illegal dx=%d or dy=%d !\n",dx,dy); + dx=(dx>0)?1:((dx<0)?-1:0); + dy=(dy>0)?1:((dy<0)?-1:0); + } + + while( count > 0 && (dx != 0 || dy != 0) ) + { + if( !map_getcellp(md,x0+dx,y0+dy,CELL_CHKPASS) ) + {// attempt partial movement + int fx = ( dx != 0 && map_getcellp(md,x0+dx,y0,CELL_CHKPASS) ); + int fy = ( dy != 0 && map_getcellp(md,x0,y0+dy,CELL_CHKPASS) ); + if( fx && fy ) + { + if(rnd()&1) + dx=0; + else + dy=0; + } + if( !fx ) + dx=0; + if( !fy ) + dy=0; + } + + x0 += dx; + y0 += dy; + count--; + } + + return (x0<<16)|y0; //TODO: use 'struct point' here instead? } /*========================================== @@ -194,67 +199,69 @@ int path_blownpos(int m,int x0,int y0,int dx,int dy,int count) *------------------------------------------*/ bool path_search_long(struct shootpath_data *spd,int m,int x0,int y0,int x1,int y1,cell_chk cell) { - int dx, dy; - int wx = 0, wy = 0; - int weight; - struct map_data *md; - struct shootpath_data s_spd; - - if (spd == NULL) - spd = &s_spd; // use dummy output variable - - if (!map[m].cell) - return false; - md = &map[m]; - - dx = (x1 - x0); - if (dx < 0) { - swap(x0, x1); - swap(y0, y1); - dx = -dx; - } - dy = (y1 - y0); - - spd->rx = spd->ry = 0; - spd->len = 1; - spd->x[0] = x0; - spd->y[0] = y0; - - if (map_getcellp(md,x1,y1,cell)) - return false; - - if (dx > abs(dy)) { - weight = dx; - spd->ry = 1; - } else { - weight = abs(y1 - y0); - spd->rx = 1; - } - - while (x0 != x1 || y0 != y1) { - if (map_getcellp(md,x0,y0,cell)) - return false; - 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->len<MAX_WALKPATH) { - spd->x[spd->len] = x0; - spd->y[spd->len] = y0; - spd->len++; - } - } - - return true; + int dx, dy; + int wx = 0, wy = 0; + int weight; + struct map_data *md; + struct shootpath_data s_spd; + + if( spd == NULL ) + spd = &s_spd; // use dummy output variable + + if (!map[m].cell) + return false; + md = &map[m]; + + dx = (x1 - x0); + if (dx < 0) { + swap(x0, x1); + swap(y0, y1); + dx = -dx; + } + dy = (y1 - y0); + + spd->rx = spd->ry = 0; + spd->len = 1; + spd->x[0] = x0; + spd->y[0] = y0; + + if (map_getcellp(md,x1,y1,cell)) + return false; + + if (dx > abs(dy)) { + weight = dx; + spd->ry = 1; + } else { + weight = abs(y1 - y0); + spd->rx = 1; + } + + while (x0 != x1 || y0 != y1) + { + if (map_getcellp(md,x0,y0,cell)) + return false; + 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->len<MAX_WALKPATH ) + { + spd->x[spd->len] = x0; + spd->y[spd->len] = y0; + spd->len++; + } + } + + return true; } /*========================================== @@ -265,154 +272,152 @@ bool path_search_long(struct shootpath_data *spd,int m,int x0,int y0,int x1,int *------------------------------------------*/ bool path_search(struct walkpath_data *wpd,int m,int x0,int y0,int x1,int y1,int flag,cell_chk cell) { - int heap[MAX_HEAP+1]; - struct tmp_path tp[MAX_WALKPATH*MAX_WALKPATH]; - register int i,j,len,x,y,dx,dy; - int rp,xs,ys; - struct map_data *md; - struct walkpath_data s_wpd; + int heap[MAX_HEAP+1]; + struct tmp_path tp[MAX_WALKPATH*MAX_WALKPATH]; + register int i,j,len,x,y,dx,dy; + int rp,xs,ys; + struct map_data *md; + struct walkpath_data s_wpd; - if (wpd == NULL) - wpd = &s_wpd; // use dummy output variable + if( wpd == NULL ) + wpd = &s_wpd; // use dummy output variable - if (!map[m].cell) - return false; - md = &map[m]; + if( !map[m].cell ) + return false; + md = &map[m]; #ifdef CELL_NOSTACK - //Do not check starting cell as that would get you stuck. - if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys) + //Do not check starting cell as that would get you stuck. + if( x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys ) #else - if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| map_getcellp(md,x0,y0,cell)*/) + if( x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| map_getcellp(md,x0,y0,cell)*/ ) #endif - return false; - if (x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || map_getcellp(md,x1,y1,cell)) - return false; - - // calculate (sgn(x1-x0), sgn(y1-y0)) - dx = ((dx = x1-x0)) ? ((dx<0) ? -1 : 1) : 0; - dy = ((dy = y1-y0)) ? ((dy<0) ? -1 : 1) : 0; - - // try finding direct path to target - x = x0; - y = y0; - i = 0; - while (i < ARRAYLENGTH(wpd->path)) { - wpd->path[i] = walk_choices[-dy + 1][dx + 1]; - i++; - - x += dx; - y += dy; - - if (x == x1) dx = 0; - if (y == y1) dy = 0; - - if (dx == 0 && dy == 0) - break; // success - if (map_getcellp(md,x,y,cell)) - break; // obstacle = failure - } - - if (x == x1 && y == y1) { - //easy path successful. - wpd->path_len = i; - wpd->path_pos = 0; - return true; - } - - if (flag&1) - return false; - - memset(tp,0,sizeof(tp)); - - i=calc_index(x0,y0); - tp[i].x=x0; - tp[i].y=y0; - tp[i].dist=0; - tp[i].before=0; - tp[i].cost=calc_cost(&tp[i],x1,y1); - tp[i].flag=0; - heap[0]=0; - push_heap_path(heap,tp,calc_index(x0,y0)); + return false; + if( x1 < 0 || x1 >= md->xs || y1 < 0 || y1 >= md->ys || map_getcellp(md,x1,y1,cell) ) + return false; + + // calculate (sgn(x1-x0), sgn(y1-y0)) + dx = ((dx = x1-x0)) ? ((dx<0) ? -1 : 1) : 0; + dy = ((dy = y1-y0)) ? ((dy<0) ? -1 : 1) : 0; + + // try finding direct path to target + x = x0; + y = y0; + i = 0; + while( i < ARRAYLENGTH(wpd->path) ) + { + wpd->path[i] = walk_choices[-dy + 1][dx + 1]; + i++; + + x += dx; + y += dy; + + if( x == x1 ) dx = 0; + if( y == y1 ) dy = 0; + + if( dx == 0 && dy == 0 ) + break; // success + if( map_getcellp(md,x,y,cell) ) + break; // obstacle = failure + } + + if( x == x1 && y == y1 ) + { //easy path successful. + wpd->path_len = i; + wpd->path_pos = 0; + return true; + } + + if( flag&1 ) + return false; + + memset(tp,0,sizeof(tp)); + + i=calc_index(x0,y0); + tp[i].x=x0; + tp[i].y=y0; + tp[i].dist=0; + tp[i].before=0; + tp[i].cost=calc_cost(&tp[i],x1,y1); + tp[i].flag=0; + heap[0]=0; + push_heap_path(heap,tp,calc_index(x0,y0)); xs = md->xs - 1; // Place by subtracting a pre- - ys = md->ys-1; - - for (;;) { - int e=0,f=0,dist,cost,dc[4]= {0,0,0,0}; - - if (heap[0]==0) - return false; - rp = pop_heap_path(heap,tp); - x = tp[rp].x; - y = tp[rp].y; - dist = tp[rp].dist + 10; - cost = tp[rp].cost; - - if (x==x1 && y==y1) - break; - - // dc[0] : y++ Incremental cost at the time - // dc[1] : x-- - // dc[2] : y-- - // dc[3] : x++ - - if (y < ys && !map_getcellp(md,x ,y+1,cell)) { - f |= 1; - dc[0] = (y >= y1 ? 20 : 0); - e+=add_path(heap,tp,x ,y+1,dist,rp,cost+dc[0]); // (x, y+1) - } - if (x > 0 && !map_getcellp(md,x-1,y ,cell)) { - f |= 2; - dc[1] = (x <= x1 ? 20 : 0); - e+=add_path(heap,tp,x-1,y ,dist,rp,cost+dc[1]); // (x-1, y ) - } - if (y > 0 && !map_getcellp(md,x ,y-1,cell)) { - f |= 4; - dc[2] = (y <= y1 ? 20 : 0); - e+=add_path(heap,tp,x ,y-1,dist,rp,cost+dc[2]); // (x , y-1) - } - if (x < xs && !map_getcellp(md,x+1,y ,cell)) { - f |= 8; - dc[3] = (x >= x1 ? 20 : 0); - e+=add_path(heap,tp,x+1,y ,dist,rp,cost+dc[3]); // (x+1, y ) - } - if ((f & (2+1)) == (2+1) && !map_getcellp(md,x-1,y+1,cell)) - e+=add_path(heap,tp,x-1,y+1,dist+4,rp,cost+dc[1]+dc[0]-6); // (x-1, y+1) - if ((f & (2+4)) == (2+4) && !map_getcellp(md,x-1,y-1,cell)) - e+=add_path(heap,tp,x-1,y-1,dist+4,rp,cost+dc[1]+dc[2]-6); // (x-1, y-1) - if ((f & (8+4)) == (8+4) && !map_getcellp(md,x+1,y-1,cell)) - e+=add_path(heap,tp,x+1,y-1,dist+4,rp,cost+dc[3]+dc[2]-6); // (x+1, y-1) - if ((f & (8+1)) == (8+1) && !map_getcellp(md,x+1,y+1,cell)) - e+=add_path(heap,tp,x+1,y+1,dist+4,rp,cost+dc[3]+dc[0]-6); // (x+1, y+1) - tp[rp].flag=1; - if (e || heap[0]>=MAX_HEAP-5) - return false; - } - - if (!(x==x1 && y==y1)) // will never happen... - return false; - - for (len=0,i=rp; len<100 && i!=calc_index(x0,y0); i=tp[i].before,len++); - if (len==100 || len>=sizeof(wpd->path)) - return false; - - wpd->path_len = len; - wpd->path_pos = 0; - for (i=rp,j=len-1; j>=0; i=tp[i].before,j--) { - int dx = tp[i].x - tp[tp[i].before].x; - int dy = tp[i].y - tp[tp[i].before].y; - int dir; - if (dx == 0) { - dir = (dy > 0 ? 0 : 4); - } else if (dx > 0) { - dir = (dy == 0 ? 6 : (dy < 0 ? 5 : 7)); - } else { - dir = (dy == 0 ? 2 : (dy > 0 ? 1 : 3)); - } - wpd->path[j] = dir; - } - - return true; + ys = md->ys-1; + + for(;;) + { + int e=0,f=0,dist,cost,dc[4]={0,0,0,0}; + + if(heap[0]==0) + return false; + rp = pop_heap_path(heap,tp); + x = tp[rp].x; + y = tp[rp].y; + dist = tp[rp].dist + 10; + cost = tp[rp].cost; + + if(x==x1 && y==y1) + break; + + // dc[0] : y++ Incremental cost at the time + // dc[1] : x-- + // dc[2] : y-- + // dc[3] : x++ + + if(y < ys && !map_getcellp(md,x ,y+1,cell)) { + f |= 1; dc[0] = (y >= y1 ? 20 : 0); + e+=add_path(heap,tp,x ,y+1,dist,rp,cost+dc[0]); // (x, y+1) + } + if(x > 0 && !map_getcellp(md,x-1,y ,cell)) { + f |= 2; dc[1] = (x <= x1 ? 20 : 0); + e+=add_path(heap,tp,x-1,y ,dist,rp,cost+dc[1]); // (x-1, y ) + } + if(y > 0 && !map_getcellp(md,x ,y-1,cell)) { + f |= 4; dc[2] = (y <= y1 ? 20 : 0); + e+=add_path(heap,tp,x ,y-1,dist,rp,cost+dc[2]); // (x , y-1) + } + if(x < xs && !map_getcellp(md,x+1,y ,cell)) { + f |= 8; dc[3] = (x >= x1 ? 20 : 0); + e+=add_path(heap,tp,x+1,y ,dist,rp,cost+dc[3]); // (x+1, y ) + } + if( (f & (2+1)) == (2+1) && !map_getcellp(md,x-1,y+1,cell)) + e+=add_path(heap,tp,x-1,y+1,dist+4,rp,cost+dc[1]+dc[0]-6); // (x-1, y+1) + if( (f & (2+4)) == (2+4) && !map_getcellp(md,x-1,y-1,cell)) + e+=add_path(heap,tp,x-1,y-1,dist+4,rp,cost+dc[1]+dc[2]-6); // (x-1, y-1) + if( (f & (8+4)) == (8+4) && !map_getcellp(md,x+1,y-1,cell)) + e+=add_path(heap,tp,x+1,y-1,dist+4,rp,cost+dc[3]+dc[2]-6); // (x+1, y-1) + if( (f & (8+1)) == (8+1) && !map_getcellp(md,x+1,y+1,cell)) + e+=add_path(heap,tp,x+1,y+1,dist+4,rp,cost+dc[3]+dc[0]-6); // (x+1, y+1) + tp[rp].flag=1; + if(e || heap[0]>=MAX_HEAP-5) + return false; + } + + if( !(x==x1 && y==y1) ) // will never happen... + return false; + + for(len=0,i=rp;len<100 && i!=calc_index(x0,y0);i=tp[i].before,len++); + if(len==100 || len>=sizeof(wpd->path)) + return false; + + wpd->path_len = len; + wpd->path_pos = 0; + for(i=rp,j=len-1;j>=0;i=tp[i].before,j--) { + int dx = tp[i].x - tp[tp[i].before].x; + int dy = tp[i].y - tp[tp[i].before].y; + int dir; + if( dx == 0 ) { + dir = (dy > 0 ? 0 : 4); + } else if( dx > 0 ) { + dir = (dy == 0 ? 6 : (dy < 0 ? 5 : 7) ); + } else { + dir = (dy == 0 ? 2 : (dy > 0 ? 1 : 3) ); + } + wpd->path[j] = dir; + } + + return true; } @@ -420,39 +425,40 @@ bool path_search(struct walkpath_data *wpd,int m,int x0,int y0,int x1,int y1,int int check_distance(int dx, int dy, int distance) { #ifdef CIRCULAR_AREA - //In this case, we just do a square comparison. Add 1 tile grace for diagonal range checks. - return (dx*dx + dy*dy <= distance*distance + (dx&&dy?1:0)); + //In this case, we just do a square comparison. Add 1 tile grace for diagonal range checks. + return (dx*dx + dy*dy <= distance*distance + (dx&&dy?1:0)); #else - if (dx < 0) dx = -dx; - if (dy < 0) dy = -dy; - return ((dx<dy?dy:dx) <= distance); + if (dx < 0) dx = -dx; + if (dy < 0) dy = -dy; + return ((dx<dy?dy:dx) <= distance); #endif } unsigned int distance(int dx, int dy) { #ifdef CIRCULAR_AREA - unsigned int min, max; - - if (dx < 0) dx = -dx; - if (dy < 0) dy = -dy; - //There appears to be something wrong with the aproximation below when either dx/dy is 0! [Skotlex] - if (dx == 0) return dy; - if (dy == 0) return dx; - - if (dx < dy) { - min = dx; - max = dy; - } else { - min = dy; - max = dx; - } - // coefficients equivalent to ( 123/128 * max ) and ( 51/128 * min ) - return (((max << 8) + (max << 3) - (max << 4) - (max << 1) + - (min << 7) - (min << 5) + (min << 3) - (min << 1)) >> 8); + unsigned int min, max; + + if ( dx < 0 ) dx = -dx; + if ( dy < 0 ) dy = -dy; + //There appears to be something wrong with the aproximation below when either dx/dy is 0! [Skotlex] + if ( dx == 0 ) return dy; + if ( dy == 0 ) return dx; + + if ( dx < dy ) + { + min = dx; + max = dy; + } else { + min = dy; + max = dx; + } + // coefficients equivalent to ( 123/128 * max ) and ( 51/128 * min ) + return ((( max << 8 ) + ( max << 3 ) - ( max << 4 ) - ( max << 1 ) + + ( min << 7 ) - ( min << 5 ) + ( min << 3 ) - ( min << 1 )) >> 8 ); #else - if (dx < 0) dx = -dx; - if (dy < 0) dy = -dy; - return (dx<dy?dy:dx); + if (dx < 0) dx = -dx; + if (dy < 0) dy = -dy; + return (dx<dy?dy:dx); #endif } diff --git a/src/map/path.h b/src/map/path.h index 10f05f82d..1dc024655 100644 --- a/src/map/path.h +++ b/src/map/path.h @@ -9,14 +9,14 @@ #define MAX_WALKPATH 32 struct walkpath_data { - unsigned char path_len,path_pos; - unsigned char path[MAX_WALKPATH]; + unsigned char path_len,path_pos; + unsigned char path[MAX_WALKPATH]; }; struct shootpath_data { - int rx,ry,len; - int x[MAX_WALKPATH]; - int y[MAX_WALKPATH]; + int rx,ry,len; + int x[MAX_WALKPATH]; + int y[MAX_WALKPATH]; }; // calculates destination cell for knockback diff --git a/src/map/pc.c b/src/map/pc.c index c2ca012ac..59709cdf1 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -47,7 +47,7 @@ #include <time.h> -#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval +#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval static unsigned int exp_table[CLASS_COUNT][2][MAX_LEVEL]; static unsigned int max_level[CLASS_COUNT][2]; static unsigned int statp[MAX_LEVEL+1]; @@ -65,17 +65,17 @@ struct fame_list smith_fame_list[MAX_FAME_LIST]; struct fame_list chemist_fame_list[MAX_FAME_LIST]; struct fame_list taekwon_fame_list[MAX_FAME_LIST]; -static unsigned short equip_pos[EQI_MAX]= {EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_AMMO}; +static unsigned short equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_AMMO}; #define MOTD_LINE_SIZE 128 static char motd_text[MOTD_LINE_SIZE][CHAT_SIZE_MAX]; // Message of the day buffer [Valaris] //Links related info to the sd->hate_mob[]/sd->feel_map[] entries const struct sg_data sg_info[MAX_PC_FEELHATE] = { - { SG_SUN_ANGER, SG_SUN_BLESS, SG_SUN_COMFORT, "PC_FEEL_SUN", "PC_HATE_MOB_SUN", is_day_of_sun }, - { SG_MOON_ANGER, SG_MOON_BLESS, SG_MOON_COMFORT, "PC_FEEL_MOON", "PC_HATE_MOB_MOON", is_day_of_moon }, - { SG_STAR_ANGER, SG_STAR_BLESS, SG_STAR_COMFORT, "PC_FEEL_STAR", "PC_HATE_MOB_STAR", is_day_of_star } -}; + { SG_SUN_ANGER, SG_SUN_BLESS, SG_SUN_COMFORT, "PC_FEEL_SUN", "PC_HATE_MOB_SUN", is_day_of_sun }, + { SG_MOON_ANGER, SG_MOON_BLESS, SG_MOON_COMFORT, "PC_FEEL_MOON", "PC_HATE_MOB_MOON", is_day_of_moon }, + { SG_STAR_ANGER, SG_STAR_BLESS, SG_STAR_COMFORT, "PC_FEEL_STAR", "PC_HATE_MOB_STAR", is_day_of_star } + }; /** * Item Cool Down Delay Saving @@ -83,410 +83,420 @@ const struct sg_data sg_info[MAX_PC_FEELHATE] = { * to keep cooldowns in memory between player log-ins. * All cooldowns are reset when server is restarted. **/ -DBMap *itemcd_db = NULL; // char_id -> struct skill_cd +DBMap* itemcd_db = NULL; // char_id -> struct skill_cd struct item_cd { - unsigned int tick[MAX_ITEMDELAYS];//tick - short nameid[MAX_ITEMDELAYS];//skill id + unsigned int tick[MAX_ITEMDELAYS];//tick + short nameid[MAX_ITEMDELAYS];//skill id }; //Converts a class to its array index for CLASS_COUNT defined arrays. //Note that it does not do a validity check for speed purposes, where parsing //player input make sure to use a pcdb_checkid first! -int pc_class2idx(int class_) -{ - if (class_ >= JOB_NOVICE_HIGH) - return class_- JOB_NOVICE_HIGH+JOB_MAX_BASIC; - return class_; +int pc_class2idx(int class_) { + if (class_ >= JOB_NOVICE_HIGH) + return class_- JOB_NOVICE_HIGH+JOB_MAX_BASIC; + return class_; } -inline int pc_get_group_id(struct map_session_data *sd) -{ - return sd->group_id; +inline int pc_get_group_id(struct map_session_data *sd) { + return sd->group_id; } -inline int pc_get_group_level(struct map_session_data *sd) -{ - return sd->group_level; +inline int pc_get_group_level(struct map_session_data *sd) { + return sd->group_level; } static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd; + struct map_session_data *sd; - if ((sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC) - return 1; + if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC ) + return 1; - if (sd->invincible_timer != tid) { - ShowError("invincible_timer %d != %d\n",sd->invincible_timer,tid); - return 0; - } - sd->invincible_timer = INVALID_TIMER; - skill_unit_move(&sd->bl,tick,1); + if(sd->invincible_timer != tid){ + ShowError("invincible_timer %d != %d\n",sd->invincible_timer,tid); + return 0; + } + sd->invincible_timer = INVALID_TIMER; + skill_unit_move(&sd->bl,tick,1); - return 0; + return 0; } -void pc_setinvincibletimer(struct map_session_data *sd, int val) +void pc_setinvincibletimer(struct map_session_data* sd, int val) { - nullpo_retv(sd); + nullpo_retv(sd); - if (sd->invincible_timer != INVALID_TIMER) - delete_timer(sd->invincible_timer,pc_invincible_timer); - sd->invincible_timer = add_timer(gettick()+val,pc_invincible_timer,sd->bl.id,0); + if( sd->invincible_timer != INVALID_TIMER ) + delete_timer(sd->invincible_timer,pc_invincible_timer); + sd->invincible_timer = add_timer(gettick()+val,pc_invincible_timer,sd->bl.id,0); } -void pc_delinvincibletimer(struct map_session_data *sd) +void pc_delinvincibletimer(struct map_session_data* sd) { - nullpo_retv(sd); + nullpo_retv(sd); - if (sd->invincible_timer != INVALID_TIMER) { - delete_timer(sd->invincible_timer,pc_invincible_timer); - sd->invincible_timer = INVALID_TIMER; - skill_unit_move(&sd->bl,gettick(),1); - } + if( sd->invincible_timer != INVALID_TIMER ) + { + delete_timer(sd->invincible_timer,pc_invincible_timer); + sd->invincible_timer = INVALID_TIMER; + skill_unit_move(&sd->bl,gettick(),1); + } } static int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd; - int i; + struct map_session_data *sd; + int i; - if ((sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC) - return 1; + if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC ) + return 1; - if (sd->spiritball <= 0) { - ShowError("pc_spiritball_timer: %d spiritball's available. (aid=%d cid=%d tid=%d)\n", sd->spiritball, sd->status.account_id, sd->status.char_id, tid); - sd->spiritball = 0; - return 0; - } + if( sd->spiritball <= 0 ) + { + ShowError("pc_spiritball_timer: %d spiritball's available. (aid=%d cid=%d tid=%d)\n", sd->spiritball, sd->status.account_id, sd->status.char_id, tid); + sd->spiritball = 0; + return 0; + } - ARR_FIND(0, sd->spiritball, i, sd->spirit_timer[i] == tid); - if (i == sd->spiritball) { - ShowError("pc_spiritball_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid); - return 0; - } + ARR_FIND(0, sd->spiritball, i, sd->spirit_timer[i] == tid); + if( i == sd->spiritball ) + { + ShowError("pc_spiritball_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid); + return 0; + } - sd->spiritball--; - if (i != sd->spiritball) - memmove(sd->spirit_timer+i, sd->spirit_timer+i+1, (sd->spiritball-i)*sizeof(int)); - sd->spirit_timer[sd->spiritball] = INVALID_TIMER; + sd->spiritball--; + if( i != sd->spiritball ) + memmove(sd->spirit_timer+i, sd->spirit_timer+i+1, (sd->spiritball-i)*sizeof(int)); + sd->spirit_timer[sd->spiritball] = INVALID_TIMER; - clif_spiritball(&sd->bl); + clif_spiritball(&sd->bl); - return 0; + return 0; } int pc_addspiritball(struct map_session_data *sd,int interval,int max) { - int tid, i; + int tid, i; - nullpo_ret(sd); + nullpo_ret(sd); - if (max > MAX_SKILL_LEVEL) - max = MAX_SKILL_LEVEL; - if (sd->spiritball < 0) - sd->spiritball = 0; + if(max > MAX_SKILL_LEVEL) + max = MAX_SKILL_LEVEL; + if(sd->spiritball < 0) + sd->spiritball = 0; - if (sd->spiritball && sd->spiritball >= max) { - if (sd->spirit_timer[0] != INVALID_TIMER) - delete_timer(sd->spirit_timer[0],pc_spiritball_timer); - sd->spiritball--; - if (sd->spiritball != 0) - memmove(sd->spirit_timer+0, sd->spirit_timer+1, (sd->spiritball)*sizeof(int)); - sd->spirit_timer[sd->spiritball] = INVALID_TIMER; - } + if( sd->spiritball && sd->spiritball >= max ) + { + if(sd->spirit_timer[0] != INVALID_TIMER) + delete_timer(sd->spirit_timer[0],pc_spiritball_timer); + sd->spiritball--; + if( sd->spiritball != 0 ) + memmove(sd->spirit_timer+0, sd->spirit_timer+1, (sd->spiritball)*sizeof(int)); + sd->spirit_timer[sd->spiritball] = INVALID_TIMER; + } - tid = add_timer(gettick()+interval, pc_spiritball_timer, sd->bl.id, 0); - ARR_FIND(0, sd->spiritball, i, sd->spirit_timer[i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->spirit_timer[i])->tick) < 0); - if (i != sd->spiritball) - memmove(sd->spirit_timer+i+1, sd->spirit_timer+i, (sd->spiritball-i)*sizeof(int)); - sd->spirit_timer[i] = tid; - sd->spiritball++; - if ((sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD) - clif_millenniumshield(sd,sd->spiritball); - else - clif_spiritball(&sd->bl); + tid = add_timer(gettick()+interval, pc_spiritball_timer, sd->bl.id, 0); + ARR_FIND(0, sd->spiritball, i, sd->spirit_timer[i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->spirit_timer[i])->tick) < 0); + if( i != sd->spiritball ) + memmove(sd->spirit_timer+i+1, sd->spirit_timer+i, (sd->spiritball-i)*sizeof(int)); + sd->spirit_timer[i] = tid; + sd->spiritball++; + if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD ) + clif_millenniumshield(sd,sd->spiritball); + else + clif_spiritball(&sd->bl); - return 0; + return 0; } int pc_delspiritball(struct map_session_data *sd,int count,int type) { - int i; - - nullpo_ret(sd); - - if (sd->spiritball <= 0) { - sd->spiritball = 0; - return 0; - } - - if (count <= 0) - return 0; - if (count > sd->spiritball) - count = sd->spiritball; - sd->spiritball -= count; - if (count > MAX_SKILL_LEVEL) - count = MAX_SKILL_LEVEL; - - for (i=0; i<count; i++) { - if (sd->spirit_timer[i] != INVALID_TIMER) { - delete_timer(sd->spirit_timer[i],pc_spiritball_timer); - sd->spirit_timer[i] = INVALID_TIMER; - } - } - for (i=count; i<MAX_SKILL_LEVEL; i++) { - sd->spirit_timer[i-count] = sd->spirit_timer[i]; - sd->spirit_timer[i] = INVALID_TIMER; - } - - if (!type) { - if ((sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD) - clif_millenniumshield(sd,sd->spiritball); - else - clif_spiritball(&sd->bl); - } - return 0; -} -static int pc_check_banding(struct block_list *bl, va_list ap) -{ - int *c, *b_sd; - struct block_list *src; - struct map_session_data *tsd; - struct status_change *sc; - - nullpo_ret(bl); - nullpo_ret(tsd = (struct map_session_data *)bl); - nullpo_ret(src = va_arg(ap,struct block_list *)); - c = va_arg(ap,int *); - b_sd = va_arg(ap, int *); - - if (pc_isdead(tsd)) - return 0; - - sc = status_get_sc(bl); - - if (bl == src) - return 0; - - if (sc && sc->data[SC_BANDING]) { - b_sd[(*c)++] = tsd->bl.id; - return 1; - } - - return 0; -} -int pc_banding(struct map_session_data *sd, short skill_lv) -{ - int c; - int b_sd[MAX_PARTY]; // In case of a full Royal Guard party. - int i, j, hp, extra_hp = 0, tmp_qty = 0, tmp_hp; - struct map_session_data *bsd; - struct status_change *sc; - int range = skill_get_splash(LG_BANDING,skill_lv); - - nullpo_ret(sd); - - c = 0; - memset(b_sd, 0, sizeof(b_sd)); - i = party_foreachsamemap(pc_check_banding,sd,range,&sd->bl,&c,&b_sd); - - if (c < 1) { //just recalc status no need to recalc hp - // No more Royal Guards in Banding found. - if ((sc = status_get_sc(&sd->bl)) != NULL && sc->data[SC_BANDING]) { - sc->data[SC_BANDING]->val2 = 0; // Reset the counter - status_calc_bl(&sd->bl, status_sc2scb_flag(SC_BANDING)); - } - return 0; - } - - //Add yourself - hp = status_get_hp(&sd->bl); - i++; - - // Get total HP of all Royal Guards in party. - for (j = 0; j < i; j++) { - bsd = map_id2sd(b_sd[j]); - if (bsd != NULL) - hp += status_get_hp(&bsd->bl); - } - - // Set average HP. - hp = hp / i; - - // If a Royal Guard have full HP, give more HP to others that haven't full HP. - for (j = 0; j < i; j++) { - bsd = map_id2sd(b_sd[j]); - if (bsd != NULL && (tmp_hp = hp - status_get_max_hp(&bsd->bl)) > 0) { - extra_hp += tmp_hp; - tmp_qty++; - } - } - - if (extra_hp > 0 && tmp_qty > 0) - hp += extra_hp / tmp_qty; - - for (j = 0; j < i; j++) { - bsd = map_id2sd(b_sd[j]); - if (bsd != NULL) { - status_set_hp(&bsd->bl,hp,0); // Set hp - if ((sc = status_get_sc(&bsd->bl)) != NULL && sc->data[SC_BANDING]) { - sc->data[SC_BANDING]->val2 = c; // Set the counter. It doesn't count your self. - status_calc_bl(&bsd->bl, status_sc2scb_flag(SC_BANDING)); // Set atk and def. - } - } - } - - return c; + int i; + + nullpo_ret(sd); + + if(sd->spiritball <= 0) { + sd->spiritball = 0; + return 0; + } + + if(count <= 0) + return 0; + if(count > sd->spiritball) + count = sd->spiritball; + sd->spiritball -= count; + if(count > MAX_SKILL_LEVEL) + count = MAX_SKILL_LEVEL; + + for(i=0;i<count;i++) { + if(sd->spirit_timer[i] != INVALID_TIMER) { + delete_timer(sd->spirit_timer[i],pc_spiritball_timer); + sd->spirit_timer[i] = INVALID_TIMER; + } + } + for(i=count;i<MAX_SKILL_LEVEL;i++) { + sd->spirit_timer[i-count] = sd->spirit_timer[i]; + sd->spirit_timer[i] = INVALID_TIMER; + } + + if(!type) { + if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD ) + clif_millenniumshield(sd,sd->spiritball); + else + clif_spiritball(&sd->bl); + } + return 0; +} +static int pc_check_banding( struct block_list *bl, va_list ap ) { + int *c, *b_sd; + struct block_list *src; + struct map_session_data *tsd; + struct status_change *sc; + + nullpo_ret(bl); + nullpo_ret(tsd = (struct map_session_data*)bl); + nullpo_ret(src = va_arg(ap,struct block_list *)); + c = va_arg(ap,int *); + b_sd = va_arg(ap, int *); + + if(pc_isdead(tsd)) + return 0; + + sc = status_get_sc(bl); + + if( bl == src ) + return 0; + + if( sc && sc->data[SC_BANDING] ) + { + b_sd[(*c)++] = tsd->bl.id; + return 1; + } + + return 0; +} +int pc_banding(struct map_session_data *sd, short skill_lv) { + int c; + int b_sd[MAX_PARTY]; // In case of a full Royal Guard party. + int i, j, hp, extra_hp = 0, tmp_qty = 0, tmp_hp; + struct map_session_data *bsd; + struct status_change *sc; + int range = skill_get_splash(LG_BANDING,skill_lv); + + nullpo_ret(sd); + + c = 0; + memset(b_sd, 0, sizeof(b_sd)); + i = party_foreachsamemap(pc_check_banding,sd,range,&sd->bl,&c,&b_sd); + + if( c < 1 ) //just recalc status no need to recalc hp + { // No more Royal Guards in Banding found. + if( (sc = status_get_sc(&sd->bl)) != NULL && sc->data[SC_BANDING] ) + { + sc->data[SC_BANDING]->val2 = 0; // Reset the counter + status_calc_bl(&sd->bl, status_sc2scb_flag(SC_BANDING)); + } + return 0; + } + + //Add yourself + hp = status_get_hp(&sd->bl); + i++; + + // Get total HP of all Royal Guards in party. + for( j = 0; j < i; j++ ) + { + bsd = map_id2sd(b_sd[j]); + if( bsd != NULL ) + hp += status_get_hp(&bsd->bl); + } + + // Set average HP. + hp = hp / i; + + // If a Royal Guard have full HP, give more HP to others that haven't full HP. + for( j = 0; j < i; j++ ) + { + bsd = map_id2sd(b_sd[j]); + if( bsd != NULL && (tmp_hp = hp - status_get_max_hp(&bsd->bl)) > 0 ) + { + extra_hp += tmp_hp; + tmp_qty++; + } + } + + if( extra_hp > 0 && tmp_qty > 0 ) + hp += extra_hp / tmp_qty; + + for( j = 0; j < i; j++ ) + { + bsd = map_id2sd(b_sd[j]); + if( bsd != NULL ) + { + status_set_hp(&bsd->bl,hp,0); // Set hp + if( (sc = status_get_sc(&bsd->bl)) != NULL && sc->data[SC_BANDING] ) + { + sc->data[SC_BANDING]->val2 = c; // Set the counter. It doesn't count your self. + status_calc_bl(&bsd->bl, status_sc2scb_flag(SC_BANDING)); // Set atk and def. + } + } + } + + return c; } // Increases a player's fame points and displays a notice to him void pc_addfame(struct map_session_data *sd,int count) { - nullpo_retv(sd); - sd->status.fame += count; - if (sd->status.fame > MAX_FAME) - sd->status.fame = MAX_FAME; - switch (sd->class_&MAPID_UPPERMASK) { - case MAPID_BLACKSMITH: // Blacksmith - clif_fame_blacksmith(sd,count); - break; - case MAPID_ALCHEMIST: // Alchemist - clif_fame_alchemist(sd,count); - break; - case MAPID_TAEKWON: // Taekwon - clif_fame_taekwon(sd,count); - break; - } - chrif_updatefamelist(sd); + nullpo_retv(sd); + sd->status.fame += count; + if(sd->status.fame > MAX_FAME) + sd->status.fame = MAX_FAME; + switch(sd->class_&MAPID_UPPERMASK){ + case MAPID_BLACKSMITH: // Blacksmith + clif_fame_blacksmith(sd,count); + break; + case MAPID_ALCHEMIST: // Alchemist + clif_fame_alchemist(sd,count); + break; + case MAPID_TAEKWON: // Taekwon + clif_fame_taekwon(sd,count); + break; + } + chrif_updatefamelist(sd); } // Check whether a player ID is in the fame rankers' list of its job, returns his/her position if so, 0 else unsigned char pc_famerank(int char_id, int job) { - int i; - - switch (job) { - case MAPID_BLACKSMITH: // Blacksmith - for (i = 0; i < MAX_FAME_LIST; i++) { - if (smith_fame_list[i].id == char_id) - return i + 1; - } - break; - case MAPID_ALCHEMIST: // Alchemist - for (i = 0; i < MAX_FAME_LIST; i++) { - if (chemist_fame_list[i].id == char_id) - return i + 1; - } - break; - case MAPID_TAEKWON: // Taekwon - for (i = 0; i < MAX_FAME_LIST; i++) { - if (taekwon_fame_list[i].id == char_id) - return i + 1; - } - break; - } - - return 0; -} - -int pc_setrestartvalue(struct map_session_data *sd,int type) -{ - struct status_data *status, *b_status; - nullpo_ret(sd); - - b_status = &sd->base_status; - status = &sd->battle_status; - - if (type&1) { //Normal resurrection - status->hp = 1; //Otherwise status_heal may fail if dead. - status_heal(&sd->bl, b_status->hp, 0, 1); - if (status->sp < b_status->sp) - status_set_sp(&sd->bl, b_status->sp, 1); - } else { //Just for saving on the char-server (with values as if respawned) - sd->status.hp = b_status->hp; - sd->status.sp = (status->sp < b_status->sp)?b_status->sp:status->sp; - } - return 0; + int i; + + switch(job){ + case MAPID_BLACKSMITH: // Blacksmith + for(i = 0; i < MAX_FAME_LIST; i++){ + if(smith_fame_list[i].id == char_id) + return i + 1; + } + break; + case MAPID_ALCHEMIST: // Alchemist + for(i = 0; i < MAX_FAME_LIST; i++){ + if(chemist_fame_list[i].id == char_id) + return i + 1; + } + break; + case MAPID_TAEKWON: // Taekwon + for(i = 0; i < MAX_FAME_LIST; i++){ + if(taekwon_fame_list[i].id == char_id) + return i + 1; + } + break; + } + + return 0; +} + +int pc_setrestartvalue(struct map_session_data *sd,int type) { + struct status_data *status, *b_status; + nullpo_ret(sd); + + b_status = &sd->base_status; + status = &sd->battle_status; + + if (type&1) { //Normal resurrection + status->hp = 1; //Otherwise status_heal may fail if dead. + status_heal(&sd->bl, b_status->hp, 0, 1); + if( status->sp < b_status->sp ) + status_set_sp(&sd->bl, b_status->sp, 1); + } else { //Just for saving on the char-server (with values as if respawned) + sd->status.hp = b_status->hp; + sd->status.sp = (status->sp < b_status->sp)?b_status->sp:status->sp; + } + return 0; } /*========================================== - Rental System + Rental System *------------------------------------------*/ static int pc_inventory_rental_end(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd = map_id2sd(id); - if (sd == NULL) - return 0; - if (tid != sd->rental_timer) { - ShowError("pc_inventory_rental_end: invalid timer id.\n"); - return 0; - } + struct map_session_data *sd = map_id2sd(id); + if( sd == NULL ) + return 0; + if( tid != sd->rental_timer ) + { + ShowError("pc_inventory_rental_end: invalid timer id.\n"); + return 0; + } - pc_inventory_rentals(sd); - return 1; + pc_inventory_rentals(sd); + return 1; } int pc_inventory_rental_clear(struct map_session_data *sd) { - if (sd->rental_timer != INVALID_TIMER) { - delete_timer(sd->rental_timer, pc_inventory_rental_end); - sd->rental_timer = INVALID_TIMER; - } + if( sd->rental_timer != INVALID_TIMER ) + { + delete_timer(sd->rental_timer, pc_inventory_rental_end); + sd->rental_timer = INVALID_TIMER; + } - return 1; + return 1; } void pc_inventory_rentals(struct map_session_data *sd) { - int i, c = 0; - unsigned int expire_tick, next_tick = UINT_MAX; - - for (i = 0; i < MAX_INVENTORY; i++) { - // Check for Rentals on Inventory - if (sd->status.inventory[i].nameid == 0) - continue; // Nothing here - if (sd->status.inventory[i].expire_time == 0) - continue; - - if (sd->status.inventory[i].expire_time <= time(NULL)) { - if (sd->status.inventory[i].nameid == ITEMID_REINS_OF_MOUNT - && sd->sc.option&OPTION_MOUNTING) { - pc_setoption(sd, sd->sc.option&~OPTION_MOUNTING); - } - clif_rental_expired(sd->fd, i, sd->status.inventory[i].nameid); - pc_delitem(sd, i, sd->status.inventory[i].amount, 1, 0, LOG_TYPE_OTHER); - } else { - expire_tick = (unsigned int)(sd->status.inventory[i].expire_time - time(NULL)) * 1000; - clif_rental_time(sd->fd, sd->status.inventory[i].nameid, (int)(expire_tick / 1000)); - next_tick = min(expire_tick, next_tick); - c++; - } - } - - if (c > 0) // min(next_tick,3600000) 1 hour each timer to keep announcing to the owner, and to avoid a but with rental time > 15 days - sd->rental_timer = add_timer(gettick() + min(next_tick,3600000), pc_inventory_rental_end, sd->bl.id, 0); - else - sd->rental_timer = INVALID_TIMER; + int i, c = 0; + unsigned int expire_tick, next_tick = UINT_MAX; + + for( i = 0; i < MAX_INVENTORY; i++ ) + { // Check for Rentals on Inventory + if( sd->status.inventory[i].nameid == 0 ) + continue; // Nothing here + if( sd->status.inventory[i].expire_time == 0 ) + continue; + + if( sd->status.inventory[i].expire_time <= time(NULL) ) { + if( sd->status.inventory[i].nameid == ITEMID_REINS_OF_MOUNT + && sd->sc.option&OPTION_MOUNTING ) { + pc_setoption(sd, sd->sc.option&~OPTION_MOUNTING); + } + clif_rental_expired(sd->fd, i, sd->status.inventory[i].nameid); + pc_delitem(sd, i, sd->status.inventory[i].amount, 1, 0, LOG_TYPE_OTHER); + } else { + expire_tick = (unsigned int)(sd->status.inventory[i].expire_time - time(NULL)) * 1000; + clif_rental_time(sd->fd, sd->status.inventory[i].nameid, (int)(expire_tick / 1000)); + next_tick = min(expire_tick, next_tick); + c++; + } + } + + if( c > 0 ) // min(next_tick,3600000) 1 hour each timer to keep announcing to the owner, and to avoid a but with rental time > 15 days + sd->rental_timer = add_timer(gettick() + min(next_tick,3600000), pc_inventory_rental_end, sd->bl.id, 0); + else + sd->rental_timer = INVALID_TIMER; } void pc_inventory_rental_add(struct map_session_data *sd, int seconds) { - const struct TimerData *td; - int tick = seconds * 1000; + const struct TimerData * td; + int tick = seconds * 1000; - if (sd == NULL) - return; + if( sd == NULL ) + return; - if (sd->rental_timer != INVALID_TIMER) { - td = get_timer(sd->rental_timer); - if (DIFF_TICK(td->tick, gettick()) > tick) { - // Update Timer as this one ends first than the current one - pc_inventory_rental_clear(sd); - sd->rental_timer = add_timer(gettick() + tick, pc_inventory_rental_end, sd->bl.id, 0); - } - } else - sd->rental_timer = add_timer(gettick() + min(tick,3600000), pc_inventory_rental_end, sd->bl.id, 0); + if( sd->rental_timer != INVALID_TIMER ) + { + td = get_timer(sd->rental_timer); + if( DIFF_TICK(td->tick, gettick()) > tick ) + { // Update Timer as this one ends first than the current one + pc_inventory_rental_clear(sd); + sd->rental_timer = add_timer(gettick() + tick, pc_inventory_rental_end, sd->bl.id, 0); + } + } + else + sd->rental_timer = add_timer(gettick() + min(tick,3600000), pc_inventory_rental_end, sd->bl.id, 0); } /** @@ -494,7 +504,7 @@ void pc_inventory_rental_add(struct map_session_data *sd, int seconds) */ bool pc_can_give_items(struct map_session_data *sd) { - return pc_has_permission(sd, PC_PERM_TRADE); + return pc_has_permission(sd, PC_PERM_TRADE); } /*========================================== @@ -502,52 +512,52 @@ bool pc_can_give_items(struct map_session_data *sd) *------------------------------------------*/ int pc_makesavestatus(struct map_session_data *sd) { - nullpo_ret(sd); + nullpo_ret(sd); - if (!battle_config.save_clothcolor) - sd->status.clothes_color=0; + if(!battle_config.save_clothcolor) + sd->status.clothes_color=0; - //Only copy the Cart/Peco/Falcon options, the rest are handled via - //status change load/saving. [Skotlex] + //Only copy the Cart/Peco/Falcon options, the rest are handled via + //status change load/saving. [Skotlex] #ifdef NEW_CARTS - sd->status.option = sd->sc.option&(OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_MOUNTING); + sd->status.option = sd->sc.option&(OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_MOUNTING); #else - sd->status.option = sd->sc.option&(OPTION_CART|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_MOUNTING); + sd->status.option = sd->sc.option&(OPTION_CART|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_MOUNTING); #endif - if (sd->sc.data[SC_JAILED]) { - //When Jailed, do not move last point. - if (pc_isdead(sd)) { - pc_setrestartvalue(sd,0); - } else { - sd->status.hp = sd->battle_status.hp; - sd->status.sp = sd->battle_status.sp; - } - sd->status.last_point.map = sd->mapindex; - sd->status.last_point.x = sd->bl.x; - sd->status.last_point.y = sd->bl.y; - return 0; - } - - if (pc_isdead(sd)) { - pc_setrestartvalue(sd,0); - memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point)); - } else { - sd->status.hp = sd->battle_status.hp; - sd->status.sp = sd->battle_status.sp; - sd->status.last_point.map = sd->mapindex; - sd->status.last_point.x = sd->bl.x; - sd->status.last_point.y = sd->bl.y; - } - - if (map[sd->bl.m].flag.nosave) { - struct map_data *m=&map[sd->bl.m]; - if (m->save.map) - memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point)); - else - memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point)); - } - - return 0; + if (sd->sc.data[SC_JAILED]) + { //When Jailed, do not move last point. + if(pc_isdead(sd)){ + pc_setrestartvalue(sd,0); + } else { + sd->status.hp = sd->battle_status.hp; + sd->status.sp = sd->battle_status.sp; + } + sd->status.last_point.map = sd->mapindex; + sd->status.last_point.x = sd->bl.x; + sd->status.last_point.y = sd->bl.y; + return 0; + } + + if(pc_isdead(sd)){ + pc_setrestartvalue(sd,0); + memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point)); + } else { + sd->status.hp = sd->battle_status.hp; + sd->status.sp = sd->battle_status.sp; + sd->status.last_point.map = sd->mapindex; + sd->status.last_point.x = sd->bl.x; + sd->status.last_point.y = sd->bl.y; + } + + if(map[sd->bl.m].flag.nosave){ + struct map_data *m=&map[sd->bl.m]; + if(m->save.map) + memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point)); + else + memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point)); + } + + return 0; } /*========================================== @@ -555,246 +565,231 @@ int pc_makesavestatus(struct map_session_data *sd) *------------------------------------------*/ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int login_id1, unsigned int client_tick, int sex, int fd) { - nullpo_ret(sd); + nullpo_ret(sd); - sd->bl.id = account_id; - sd->status.account_id = account_id; - sd->status.char_id = char_id; - sd->status.sex = sex; - sd->login_id1 = login_id1; - sd->login_id2 = 0; // at this point, we can not know the value :( - sd->client_tick = client_tick; - sd->state.active = 0; //to be set to 1 after player is fully authed and loaded. - sd->bl.type = BL_PC; - sd->canlog_tick = gettick(); - //Required to prevent homunculus copuing a base speed of 0. - sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED; - return 0; + sd->bl.id = account_id; + sd->status.account_id = account_id; + sd->status.char_id = char_id; + sd->status.sex = sex; + sd->login_id1 = login_id1; + sd->login_id2 = 0; // at this point, we can not know the value :( + sd->client_tick = client_tick; + sd->state.active = 0; //to be set to 1 after player is fully authed and loaded. + sd->bl.type = BL_PC; + sd->canlog_tick = gettick(); + //Required to prevent homunculus copuing a base speed of 0. + sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED; + return 0; } int pc_equippoint(struct map_session_data *sd,int n) { - int ep = 0; + int ep = 0; - nullpo_ret(sd); + nullpo_ret(sd); - if (!sd->inventory_data[n]) - return 0; + if(!sd->inventory_data[n]) + return 0; - if (!itemdb_isequip2(sd->inventory_data[n])) - return 0; //Not equippable by players. + if (!itemdb_isequip2(sd->inventory_data[n])) + return 0; //Not equippable by players. - ep = sd->inventory_data[n]->equip; - if (sd->inventory_data[n]->look == W_DAGGER || - sd->inventory_data[n]->look == W_1HSWORD || - sd->inventory_data[n]->look == W_1HAXE) { - if (ep == EQP_HAND_R && (pc_checkskill(sd,AS_LEFT) > 0 || (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN || - (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO))//Kagerou and Oboro can dual wield daggers. [Rytech] - return EQP_ARMS; - } - return ep; + ep = sd->inventory_data[n]->equip; + if(sd->inventory_data[n]->look == W_DAGGER || + sd->inventory_data[n]->look == W_1HSWORD || + sd->inventory_data[n]->look == W_1HAXE) { + if(ep == EQP_HAND_R && (pc_checkskill(sd,AS_LEFT) > 0 || (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN || + (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO))//Kagerou and Oboro can dual wield daggers. [Rytech] + return EQP_ARMS; + } + return ep; } int pc_setinventorydata(struct map_session_data *sd) { - int i,id; + int i,id; - nullpo_ret(sd); + nullpo_ret(sd); - for (i=0; i<MAX_INVENTORY; i++) { - id = sd->status.inventory[i].nameid; - sd->inventory_data[i] = id?itemdb_search(id):NULL; - } - return 0; + for(i=0;i<MAX_INVENTORY;i++) { + id = sd->status.inventory[i].nameid; + sd->inventory_data[i] = id?itemdb_search(id):NULL; + } + return 0; } int pc_calcweapontype(struct map_session_data *sd) { - nullpo_ret(sd); - - // single-hand - if (sd->weapontype2 == W_FIST) { - sd->status.weapon = sd->weapontype1; - return 1; - } - if (sd->weapontype1 == W_FIST) { - sd->status.weapon = sd->weapontype2; - return 1; - } - // dual-wield - sd->status.weapon = 0; - switch (sd->weapontype1) { - case W_DAGGER: - switch (sd->weapontype2) { - case W_DAGGER: - sd->status.weapon = W_DOUBLE_DD; - break; - case W_1HSWORD: - sd->status.weapon = W_DOUBLE_DS; - break; - case W_1HAXE: - sd->status.weapon = W_DOUBLE_DA; - break; - } - break; - case W_1HSWORD: - switch (sd->weapontype2) { - case W_DAGGER: - sd->status.weapon = W_DOUBLE_DS; - break; - case W_1HSWORD: - sd->status.weapon = W_DOUBLE_SS; - break; - case W_1HAXE: - sd->status.weapon = W_DOUBLE_SA; - break; - } - break; - case W_1HAXE: - switch (sd->weapontype2) { - case W_DAGGER: - sd->status.weapon = W_DOUBLE_DA; - break; - case W_1HSWORD: - sd->status.weapon = W_DOUBLE_SA; - break; - case W_1HAXE: - sd->status.weapon = W_DOUBLE_AA; - break; - } - } - // unknown, default to right hand type - if (!sd->status.weapon) - sd->status.weapon = sd->weapontype1; - - return 2; + nullpo_ret(sd); + + // single-hand + if(sd->weapontype2 == W_FIST) { + sd->status.weapon = sd->weapontype1; + return 1; + } + if(sd->weapontype1 == W_FIST) { + sd->status.weapon = sd->weapontype2; + return 1; + } + // dual-wield + sd->status.weapon = 0; + switch (sd->weapontype1){ + case W_DAGGER: + switch (sd->weapontype2) { + case W_DAGGER: sd->status.weapon = W_DOUBLE_DD; break; + case W_1HSWORD: sd->status.weapon = W_DOUBLE_DS; break; + case W_1HAXE: sd->status.weapon = W_DOUBLE_DA; break; + } + break; + case W_1HSWORD: + switch (sd->weapontype2) { + case W_DAGGER: sd->status.weapon = W_DOUBLE_DS; break; + case W_1HSWORD: sd->status.weapon = W_DOUBLE_SS; break; + case W_1HAXE: sd->status.weapon = W_DOUBLE_SA; break; + } + break; + case W_1HAXE: + switch (sd->weapontype2) { + case W_DAGGER: sd->status.weapon = W_DOUBLE_DA; break; + case W_1HSWORD: sd->status.weapon = W_DOUBLE_SA; break; + case W_1HAXE: sd->status.weapon = W_DOUBLE_AA; break; + } + } + // unknown, default to right hand type + if (!sd->status.weapon) + sd->status.weapon = sd->weapontype1; + + return 2; } int pc_setequipindex(struct map_session_data *sd) { - int i,j; + int i,j; - nullpo_ret(sd); + nullpo_ret(sd); - for (i=0; i<EQI_MAX; i++) - sd->equip_index[i] = -1; + for(i=0;i<EQI_MAX;i++) + sd->equip_index[i] = -1; - for (i=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid <= 0) - continue; - if (sd->status.inventory[i].equip) { - for (j=0; j<EQI_MAX; j++) - if (sd->status.inventory[i].equip & equip_pos[j]) - sd->equip_index[j] = i; + for(i=0;i<MAX_INVENTORY;i++) { + if(sd->status.inventory[i].nameid <= 0) + continue; + if(sd->status.inventory[i].equip) { + for(j=0;j<EQI_MAX;j++) + if(sd->status.inventory[i].equip & equip_pos[j]) + sd->equip_index[j] = i; - if (sd->status.inventory[i].equip & EQP_HAND_R) { - if (sd->inventory_data[i]) - sd->weapontype1 = sd->inventory_data[i]->look; - else - sd->weapontype1 = 0; - } + if(sd->status.inventory[i].equip & EQP_HAND_R) + { + if(sd->inventory_data[i]) + sd->weapontype1 = sd->inventory_data[i]->look; + else + sd->weapontype1 = 0; + } - if (sd->status.inventory[i].equip & EQP_HAND_L) { - if (sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) - sd->weapontype2 = sd->inventory_data[i]->look; - else - sd->weapontype2 = 0; - } - } - } - pc_calcweapontype(sd); + if( sd->status.inventory[i].equip & EQP_HAND_L ) + { + if( sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON ) + sd->weapontype2 = sd->inventory_data[i]->look; + else + sd->weapontype2 = 0; + } + } + } + pc_calcweapontype(sd); - return 0; + return 0; } static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int flag) { - int i; - struct item *item = &sd->status.inventory[eqindex]; - struct item_data *data; + int i; + struct item *item = &sd->status.inventory[eqindex]; + struct item_data *data; - //Crafted/made/hatched items. - if (itemdb_isspecial(item->card[0])) - return 1; + //Crafted/made/hatched items. + if (itemdb_isspecial(item->card[0])) + return 1; - /* scan for enchant armor gems */ - if (item->card[MAX_SLOTS - 1] && s < MAX_SLOTS - 1) - s = MAX_SLOTS - 1; + /* scan for enchant armor gems */ + if( item->card[MAX_SLOTS - 1] && s < MAX_SLOTS - 1 ) + s = MAX_SLOTS - 1; - ARR_FIND(0, s, i, item->card[i] && (data = itemdb_exists(item->card[i])) != NULL && data->flag.no_equip&flag); - return(i < s) ? 0 : 1; + ARR_FIND( 0, s, i, item->card[i] && (data = itemdb_exists(item->card[i])) != NULL && data->flag.no_equip&flag ); + return( i < s ) ? 0 : 1; } bool pc_isequipped(struct map_session_data *sd, int nameid) { - int i, j, index; + int i, j, index; - for (i = 0; i < EQI_MAX; i++) { - index = sd->equip_index[i]; - if (index < 0) continue; + for( i = 0; i < EQI_MAX; i++ ) + { + index = sd->equip_index[i]; + if( index < 0 ) continue; - if (i == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue; - if (i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue; - if (i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue; + if( i == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index ) continue; + if( i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index ) continue; + if( i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index) ) continue; - if (!sd->inventory_data[index]) continue; + if( !sd->inventory_data[index] ) continue; - if (sd->inventory_data[index]->nameid == nameid) - return true; + if( sd->inventory_data[index]->nameid == nameid ) + return true; - for (j = 0; j < sd->inventory_data[index]->slot; j++) - if (sd->status.inventory[index].card[j] == nameid) - return true; - } + for( j = 0; j < sd->inventory_data[index]->slot; j++ ) + if( sd->status.inventory[index].card[j] == nameid ) + return true; + } - return false; + return false; } -bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd) +bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd ) { - if (!p1_sd || !p2_sd || !b_sd) - return false; + if( !p1_sd || !p2_sd || !b_sd ) + return false; - if (b_sd->status.father || b_sd->status.mother || b_sd->adopt_invite) - return false; // already adopted baby / in adopt request + if( b_sd->status.father || b_sd->status.mother || b_sd->adopt_invite ) + return false; // already adopted baby / in adopt request - if (!p1_sd->status.partner_id || !p1_sd->status.party_id || p1_sd->status.party_id != b_sd->status.party_id) - return false; // You need to be married and in party with baby to adopt + if( !p1_sd->status.partner_id || !p1_sd->status.party_id || p1_sd->status.party_id != b_sd->status.party_id ) + return false; // You need to be married and in party with baby to adopt - if (p1_sd->status.partner_id != p2_sd->status.char_id || p2_sd->status.partner_id != p1_sd->status.char_id) - return false; // Not married, wrong married + if( p1_sd->status.partner_id != p2_sd->status.char_id || p2_sd->status.partner_id != p1_sd->status.char_id ) + return false; // Not married, wrong married - if (p2_sd->status.party_id != p1_sd->status.party_id) - return false; // Both parents need to be in the same party + if( p2_sd->status.party_id != p1_sd->status.party_id ) + return false; // Both parents need to be in the same party - // Parents need to have their ring equipped - if (!pc_isequipped(p1_sd, WEDDING_RING_M) && !pc_isequipped(p1_sd, WEDDING_RING_F)) - return false; + // Parents need to have their ring equipped + if( !pc_isequipped(p1_sd, WEDDING_RING_M) && !pc_isequipped(p1_sd, WEDDING_RING_F) ) + return false; - if (!pc_isequipped(p2_sd, WEDDING_RING_M) && !pc_isequipped(p2_sd, WEDDING_RING_F)) - return false; + if( !pc_isequipped(p2_sd, WEDDING_RING_M) && !pc_isequipped(p2_sd, WEDDING_RING_F) ) + return false; - // Already adopted a baby - if (p1_sd->status.child || p2_sd->status.child) { - clif_Adopt_reply(p1_sd, 0); - return false; - } + // Already adopted a baby + if( p1_sd->status.child || p2_sd->status.child ) { + clif_Adopt_reply(p1_sd, 0); + return false; + } - // Parents need at least lvl 70 to adopt - if (p1_sd->status.base_level < 70 || p2_sd->status.base_level < 70) { - clif_Adopt_reply(p1_sd, 1); - return false; - } + // Parents need at least lvl 70 to adopt + if( p1_sd->status.base_level < 70 || p2_sd->status.base_level < 70 ) { + clif_Adopt_reply(p1_sd, 1); + return false; + } - if (b_sd->status.partner_id) { - clif_Adopt_reply(p1_sd, 2); - return false; - } + if( b_sd->status.partner_id ) { + clif_Adopt_reply(p1_sd, 2); + return false; + } - if (!((b_sd->status.class_ >= JOB_NOVICE && b_sd->status.class_ <= JOB_THIEF) || b_sd->status.class_ == JOB_SUPER_NOVICE)) - return false; + if( !( ( b_sd->status.class_ >= JOB_NOVICE && b_sd->status.class_ <= JOB_THIEF ) || b_sd->status.class_ == JOB_SUPER_NOVICE ) ) + return false; - return true; + return true; } /*========================================== @@ -802,42 +797,42 @@ bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd *------------------------------------------*/ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd) { - int job, joblevel; - unsigned int jobexp; + int job, joblevel; + unsigned int jobexp; - if (!pc_can_Adopt(p1_sd, p2_sd, b_sd)) - return false; + if( !pc_can_Adopt(p1_sd, p2_sd, b_sd) ) + return false; - // Preserve current job levels and progress - joblevel = b_sd->status.job_level; - jobexp = b_sd->status.job_exp; + // Preserve current job levels and progress + joblevel = b_sd->status.job_level; + jobexp = b_sd->status.job_exp; - job = pc_mapid2jobid(b_sd->class_|JOBL_BABY, b_sd->status.sex); - if (job != -1 && !pc_jobchange(b_sd, job, 0)) { - // Success, proceed to configure parents and baby skills - p1_sd->status.child = b_sd->status.char_id; - p2_sd->status.child = b_sd->status.char_id; - b_sd->status.father = p1_sd->status.char_id; - b_sd->status.mother = p2_sd->status.char_id; + job = pc_mapid2jobid(b_sd->class_|JOBL_BABY, b_sd->status.sex); + if( job != -1 && !pc_jobchange(b_sd, job, 0) ) + { // Success, proceed to configure parents and baby skills + p1_sd->status.child = b_sd->status.char_id; + p2_sd->status.child = b_sd->status.char_id; + b_sd->status.father = p1_sd->status.char_id; + b_sd->status.mother = p2_sd->status.char_id; - // Restore progress - b_sd->status.job_level = joblevel; - clif_updatestatus(b_sd, SP_JOBLEVEL); - b_sd->status.job_exp = jobexp; - clif_updatestatus(b_sd, SP_JOBEXP); + // Restore progress + b_sd->status.job_level = joblevel; + clif_updatestatus(b_sd, SP_JOBLEVEL); + b_sd->status.job_exp = jobexp; + clif_updatestatus(b_sd, SP_JOBEXP); - // Baby Skills - pc_skill(b_sd, WE_BABY, 1, 0); - pc_skill(b_sd, WE_CALLPARENT, 1, 0); + // Baby Skills + pc_skill(b_sd, WE_BABY, 1, 0); + pc_skill(b_sd, WE_CALLPARENT, 1, 0); - // Parents Skills - pc_skill(p1_sd, WE_CALLBABY, 1, 0); - pc_skill(p2_sd, WE_CALLBABY, 1, 0); + // Parents Skills + pc_skill(p1_sd, WE_CALLBABY, 1, 0); + pc_skill(p2_sd, WE_CALLBABY, 1, 0); - return true; - } + return true; + } - return false; // Job Change Fail + return false; // Job Change Fail } /*================================================= @@ -846,83 +841,84 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, *------------------------------------------------*/ int pc_isequip(struct map_session_data *sd,int n) { - struct item_data *item; + struct item_data *item; - nullpo_ret(sd); + nullpo_ret(sd); - item = sd->inventory_data[n]; + item = sd->inventory_data[n]; - if (pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT)) - return 1; + if(pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT)) + return 1; - if (item == NULL) - return 0; - if (item->elv && sd->status.base_level < (unsigned int)item->elv) - return 0; + if(item == NULL) + return 0; + if(item->elv && sd->status.base_level < (unsigned int)item->elv) + return 0; #ifdef RENEWAL - if (item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) - return 0; + if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) + return 0; #endif - if (item->sex != 2 && sd->status.sex != item->sex) - return 0; - if (!map_flag_vs(sd->bl.m) && ((item->flag.no_equip&1) || !pc_isAllowedCardOn(sd,item->slot,n,1))) - return 0; - if (map[sd->bl.m].flag.pvp && ((item->flag.no_equip&2) || !pc_isAllowedCardOn(sd,item->slot,n,2))) - return 0; - if (map_flag_gvg(sd->bl.m) && ((item->flag.no_equip&4) || !pc_isAllowedCardOn(sd,item->slot,n,4))) - return 0; - if (map[sd->bl.m].flag.battleground && ((item->flag.no_equip&8) || !pc_isAllowedCardOn(sd,item->slot,n,8))) - return 0; - if (map[sd->bl.m].flag.restricted) { - int flag =8*map[sd->bl.m].zone; - if (item->flag.no_equip&flag || !pc_isAllowedCardOn(sd,item->slot,n,flag)) - return 0; - } - - if (sd->sc.count) { - - if (item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_STRIPWEAPON]) // Also works with left-hand weapons [DracoRPG] - return 0; - if (item->equip & EQP_SHIELD && item->type == IT_ARMOR && sd->sc.data[SC_STRIPSHIELD]) - return 0; - if (item->equip & EQP_ARMOR && sd->sc.data[SC_STRIPARMOR]) - return 0; - if (item->equip & EQP_HEAD_TOP && sd->sc.data[SC_STRIPHELM]) - return 0; - if (item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSORY]) - return 0; - if (item->equip && sd->sc.data[SC_KYOUGAKU]) - return 0; - - if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SUPERNOVICE) { - //Spirit of Super Novice equip bonuses. [Skotlex] - if (sd->status.base_level > 90 && item->equip & EQP_HELM) - return 1; //Can equip all helms - - if (sd->status.base_level > 96 && item->equip & EQP_ARMS && item->type == IT_WEAPON) - switch (item->look) { //In weapons, the look determines type of weapon. - case W_DAGGER: //Level 4 Knives are equippable.. this means all knives, I'd guess? - case W_1HSWORD: //All 1H swords - case W_1HAXE: //All 1H Axes - case W_MACE: //All 1H Maces - case W_STAFF: //All 1H Staves - return 1; - } - } - } - //Not equipable by class. [Skotlex] - if (!(1<<(sd->class_&MAPID_BASEMASK)&item->class_base[(sd->class_&JOBL_2_1)?1:((sd->class_&JOBL_2_2)?2:0)])) - return 0; - //Not usable by upper class. [Inkfish] - while (1) { - if (item->class_upper&1 && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY))) break; - if (item->class_upper&2 && sd->class_&(JOBL_UPPER|JOBL_THIRD)) break; - if (item->class_upper&4 && sd->class_&JOBL_BABY) break; - if (item->class_upper&8 && sd->class_&JOBL_THIRD) break; - return 0; - } - - return 1; + if(item->sex != 2 && sd->status.sex != item->sex) + return 0; + if(!map_flag_vs(sd->bl.m) && ((item->flag.no_equip&1) || !pc_isAllowedCardOn(sd,item->slot,n,1))) + return 0; + if(map[sd->bl.m].flag.pvp && ((item->flag.no_equip&2) || !pc_isAllowedCardOn(sd,item->slot,n,2))) + return 0; + if(map_flag_gvg(sd->bl.m) && ((item->flag.no_equip&4) || !pc_isAllowedCardOn(sd,item->slot,n,4))) + return 0; + if(map[sd->bl.m].flag.battleground && ((item->flag.no_equip&8) || !pc_isAllowedCardOn(sd,item->slot,n,8))) + return 0; + if(map[sd->bl.m].flag.restricted) + { + int flag =8*map[sd->bl.m].zone; + if (item->flag.no_equip&flag || !pc_isAllowedCardOn(sd,item->slot,n,flag)) + return 0; + } + + if (sd->sc.count) { + + if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_STRIPWEAPON]) // Also works with left-hand weapons [DracoRPG] + return 0; + if(item->equip & EQP_SHIELD && item->type == IT_ARMOR && sd->sc.data[SC_STRIPSHIELD]) + return 0; + if(item->equip & EQP_ARMOR && sd->sc.data[SC_STRIPARMOR]) + return 0; + if(item->equip & EQP_HEAD_TOP && sd->sc.data[SC_STRIPHELM]) + return 0; + if(item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSORY]) + return 0; + if(item->equip && sd->sc.data[SC_KYOUGAKU]) + return 0; + + if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SUPERNOVICE) { + //Spirit of Super Novice equip bonuses. [Skotlex] + if (sd->status.base_level > 90 && item->equip & EQP_HELM) + return 1; //Can equip all helms + + if (sd->status.base_level > 96 && item->equip & EQP_ARMS && item->type == IT_WEAPON) + switch(item->look) { //In weapons, the look determines type of weapon. + case W_DAGGER: //Level 4 Knives are equippable.. this means all knives, I'd guess? + case W_1HSWORD: //All 1H swords + case W_1HAXE: //All 1H Axes + case W_MACE: //All 1H Maces + case W_STAFF: //All 1H Staves + return 1; + } + } + } + //Not equipable by class. [Skotlex] + if (!(1<<(sd->class_&MAPID_BASEMASK)&item->class_base[(sd->class_&JOBL_2_1)?1:((sd->class_&JOBL_2_2)?2:0)])) + return 0; + //Not usable by upper class. [Inkfish] + while( 1 ) { + if( item->class_upper&1 && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break; + if( item->class_upper&2 && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break; + if( item->class_upper&4 && sd->class_&JOBL_BABY ) break; + if( item->class_upper&8 && sd->class_&JOBL_THIRD ) break; + return 0; + } + + return 1; } /*========================================== @@ -931,187 +927,190 @@ int pc_isequip(struct map_session_data *sd,int n) *------------------------------------------*/ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers) { - int i; - unsigned long tick = gettick(); - uint32 ip = session[sd->fd]->client_addr; - - sd->login_id2 = login_id2; - sd->group_id = group_id; - - /* load user permissions */ - pc_group_pc_load(sd); - - memcpy(&sd->status, st, sizeof(*st)); - - if (st->sex != sd->status.sex) { - clif_authfail_fd(sd->fd, 0); - return false; - } - - //Set the map-server used job id. [Skotlex] - i = pc_jobid2mapid(sd->status.class_); - if (i == -1) { //Invalid class? - ShowError("pc_authok: Invalid class %d for player %s (%d:%d). Class was changed to novice.\n", sd->status.class_, sd->status.name, sd->status.account_id, sd->status.char_id); - sd->status.class_ = JOB_NOVICE; - sd->class_ = MAPID_NOVICE; - } else - sd->class_ = i; - - // Checks and fixes to character status data, that are required - // in case of configuration change or stuff, which cannot be - // checked on char-server. - if (sd->status.hair < MIN_HAIR_STYLE || sd->status.hair > MAX_HAIR_STYLE) { - sd->status.hair = MIN_HAIR_STYLE; - } - if (sd->status.hair_color < MIN_HAIR_COLOR || sd->status.hair_color > MAX_HAIR_COLOR) { - sd->status.hair_color = MIN_HAIR_COLOR; - } - if (sd->status.clothes_color < MIN_CLOTH_COLOR || sd->status.clothes_color > MAX_CLOTH_COLOR) { - sd->status.clothes_color = MIN_CLOTH_COLOR; - } - - //Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation. - if (!sd->status.hp) pc_setdead(sd); - sd->state.connect_new = 1; - - sd->followtimer = INVALID_TIMER; // [MouseJstr] - sd->invincible_timer = INVALID_TIMER; - sd->npc_timer_id = INVALID_TIMER; - sd->pvp_timer = INVALID_TIMER; - /** - * For the Secure NPC Timeout option (check config/Secure.h) [RR] - **/ + int i; + unsigned long tick = gettick(); + uint32 ip = session[sd->fd]->client_addr; + + sd->login_id2 = login_id2; + sd->group_id = group_id; + + /* load user permissions */ + pc_group_pc_load(sd); + + memcpy(&sd->status, st, sizeof(*st)); + + if (st->sex != sd->status.sex) { + clif_authfail_fd(sd->fd, 0); + return false; + } + + //Set the map-server used job id. [Skotlex] + i = pc_jobid2mapid(sd->status.class_); + if (i == -1) { //Invalid class? + ShowError("pc_authok: Invalid class %d for player %s (%d:%d). Class was changed to novice.\n", sd->status.class_, sd->status.name, sd->status.account_id, sd->status.char_id); + sd->status.class_ = JOB_NOVICE; + sd->class_ = MAPID_NOVICE; + } else + sd->class_ = i; + + // Checks and fixes to character status data, that are required + // in case of configuration change or stuff, which cannot be + // checked on char-server. + if( sd->status.hair < MIN_HAIR_STYLE || sd->status.hair > MAX_HAIR_STYLE ) + { + sd->status.hair = MIN_HAIR_STYLE; + } + if( sd->status.hair_color < MIN_HAIR_COLOR || sd->status.hair_color > MAX_HAIR_COLOR ) + { + sd->status.hair_color = MIN_HAIR_COLOR; + } + if( sd->status.clothes_color < MIN_CLOTH_COLOR || sd->status.clothes_color > MAX_CLOTH_COLOR ) + { + sd->status.clothes_color = MIN_CLOTH_COLOR; + } + + //Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation. + if(!sd->status.hp) pc_setdead(sd); + sd->state.connect_new = 1; + + sd->followtimer = INVALID_TIMER; // [MouseJstr] + sd->invincible_timer = INVALID_TIMER; + sd->npc_timer_id = INVALID_TIMER; + sd->pvp_timer = INVALID_TIMER; + /** + * For the Secure NPC Timeout option (check config/Secure.h) [RR] + **/ #if SECURE_NPCTIMEOUT - /** - * Initialize to defaults/expected - **/ - sd->npc_idle_timer = INVALID_TIMER; - sd->npc_idle_tick = tick; + /** + * Initialize to defaults/expected + **/ + sd->npc_idle_timer = INVALID_TIMER; + sd->npc_idle_tick = tick; #endif - sd->canuseitem_tick = tick; - sd->canusecashfood_tick = tick; - sd->canequip_tick = tick; - sd->cantalk_tick = tick; - sd->canskill_tick = tick; - sd->cansendmail_tick = tick; + sd->canuseitem_tick = tick; + sd->canusecashfood_tick = tick; + sd->canequip_tick = tick; + sd->cantalk_tick = tick; + sd->canskill_tick = tick; + sd->cansendmail_tick = tick; - for (i = 0; i < MAX_SKILL_LEVEL; i++) - sd->spirit_timer[i] = INVALID_TIMER; - for (i = 0; i < ARRAYLENGTH(sd->autobonus); i++) - sd->autobonus[i].active = INVALID_TIMER; - for (i = 0; i < ARRAYLENGTH(sd->autobonus2); i++) - sd->autobonus2[i].active = INVALID_TIMER; - for (i = 0; i < ARRAYLENGTH(sd->autobonus3); i++) - sd->autobonus3[i].active = INVALID_TIMER; + for(i = 0; i < MAX_SKILL_LEVEL; i++) + sd->spirit_timer[i] = INVALID_TIMER; + for(i = 0; i < ARRAYLENGTH(sd->autobonus); i++) + sd->autobonus[i].active = INVALID_TIMER; + for(i = 0; i < ARRAYLENGTH(sd->autobonus2); i++) + sd->autobonus2[i].active = INVALID_TIMER; + for(i = 0; i < ARRAYLENGTH(sd->autobonus3); i++) + sd->autobonus3[i].active = INVALID_TIMER; - if (battle_config.item_auto_get) - sd->state.autoloot = 10000; + if (battle_config.item_auto_get) + sd->state.autoloot = 10000; - if (battle_config.disp_experience) - sd->state.showexp = 1; - if (battle_config.disp_zeny) - sd->state.showzeny = 1; + if (battle_config.disp_experience) + sd->state.showexp = 1; + if (battle_config.disp_zeny) + sd->state.showzeny = 1; - if (!(battle_config.display_skill_fail&2)) - sd->state.showdelay = 1; + if (!(battle_config.display_skill_fail&2)) + sd->state.showdelay = 1; - pc_setinventorydata(sd); - pc_setequipindex(sd); + pc_setinventorydata(sd); + pc_setequipindex(sd); - status_change_init(&sd->bl); + status_change_init(&sd->bl); - if (pc_can_use_command(sd, "hide", COMMAND_ATCOMMAND)) - sd->status.option &= (OPTION_MASK | OPTION_INVISIBLE); - else - sd->status.option &= OPTION_MASK; + if (pc_can_use_command(sd, "hide", COMMAND_ATCOMMAND)) + sd->status.option &= (OPTION_MASK | OPTION_INVISIBLE); + else + sd->status.option &= OPTION_MASK; - sd->sc.option = sd->status.option; //This is the actual option used in battle. - //Set here because we need the inventory data for weapon sprite parsing. - status_set_viewdata(&sd->bl, sd->status.class_); - unit_dataset(&sd->bl); + sd->sc.option = sd->status.option; //This is the actual option used in battle. + //Set here because we need the inventory data for weapon sprite parsing. + status_set_viewdata(&sd->bl, sd->status.class_); + unit_dataset(&sd->bl); - sd->guild_x = -1; - sd->guild_y = -1; + sd->guild_x = -1; + sd->guild_y = -1; - // Event Timers - for (i = 0; i < MAX_EVENTTIMER; i++) - sd->eventtimer[i] = INVALID_TIMER; - // Rental Timer - sd->rental_timer = INVALID_TIMER; + // Event Timers + for( i = 0; i < MAX_EVENTTIMER; i++ ) + sd->eventtimer[i] = INVALID_TIMER; + // Rental Timer + sd->rental_timer = INVALID_TIMER; - for (i = 0; i < 3; i++) - sd->hate_mob[i] = -1; + for( i = 0; i < 3; i++ ) + sd->hate_mob[i] = -1; //warp player - if ((i=pc_setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, CLR_OUTSIGHT)) != 0) { - ShowError("Last_point_map %s - id %d not found (error code %d)\n", mapindex_id2name(sd->status.last_point.map), sd->status.last_point.map, i); - - // try warping to a default map instead (church graveyard) - if (pc_setpos(sd, mapindex_name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != 0) { - // if we fail again - clif_authfail_fd(sd->fd, 0); - return false; - } - } - - clif_authok(sd); - - //Prevent S. Novices from getting the no-death bonus just yet. [Skotlex] - sd->die_counter=-1; - - //display login notice - ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in." - " (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"'," - " Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'," - " Group '"CL_WHITE"%d"CL_RESET"').\n", - sd->status.name, sd->status.account_id, sd->status.char_id, - sd->packet_ver, CONVIP(ip), sd->group_id); - // Send friends list - clif_friendslist_send(sd); - - if (!changing_mapservers) { - - if (battle_config.display_version == 1) { - char buf[256]; - sprintf(buf, "SVN version: %s", get_svn_revision()); - clif_displaymessage(sd->fd, buf); - } - - // Message of the Day [Valaris] - for (i=0; motd_text[i][0] && i < MOTD_LINE_SIZE; i++) { - if (battle_config.motd_type) - clif_disp_onlyself(sd,motd_text[i],strlen(motd_text[i])); - else - clif_displaymessage(sd->fd, motd_text[i]); - } - - // message of the limited time of the account - if (expiration_time != 0) { // don't display if it's unlimited or unknow value - char tmpstr[1024]; - strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(501), localtime(&expiration_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S." - clif_wis_message(sd->fd, wisp_server_name, tmpstr, strlen(tmpstr)+1); - } - - /** - * Fixes login-without-aura glitch (the screen won't blink at this point, don't worry :P) - **/ - clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y); - } - - /** - * Check if player have any cool downs on - **/ - skill_cooldown_load(sd); - - /** - * Check if player have any item cooldowns on - **/ - pc_itemcd_do(sd,true); - - // Request all registries (auth is considered completed whence they arrive) - intif_request_registry(sd,7); - return true; + if ((i=pc_setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, CLR_OUTSIGHT)) != 0) { + ShowError ("Last_point_map %s - id %d not found (error code %d)\n", mapindex_id2name(sd->status.last_point.map), sd->status.last_point.map, i); + + // try warping to a default map instead (church graveyard) + if (pc_setpos(sd, mapindex_name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != 0) { + // if we fail again + clif_authfail_fd(sd->fd, 0); + return false; + } + } + + clif_authok(sd); + + //Prevent S. Novices from getting the no-death bonus just yet. [Skotlex] + sd->die_counter=-1; + + //display login notice + ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in." + " (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"'," + " Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'," + " Group '"CL_WHITE"%d"CL_RESET"').\n", + sd->status.name, sd->status.account_id, sd->status.char_id, + sd->packet_ver, CONVIP(ip), sd->group_id); + // Send friends list + clif_friendslist_send(sd); + + if( !changing_mapservers ) { + + if (battle_config.display_version == 1){ + char buf[256]; + sprintf(buf, "SVN version: %s", get_svn_revision()); + clif_displaymessage(sd->fd, buf); + } + + // Message of the Day [Valaris] + for(i=0; motd_text[i][0] && i < MOTD_LINE_SIZE; i++) { + if (battle_config.motd_type) + clif_disp_onlyself(sd,motd_text[i],strlen(motd_text[i])); + else + clif_displaymessage(sd->fd, motd_text[i]); + } + + // message of the limited time of the account + if (expiration_time != 0) { // don't display if it's unlimited or unknow value + char tmpstr[1024]; + strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(501), localtime(&expiration_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S." + clif_wis_message(sd->fd, wisp_server_name, tmpstr, strlen(tmpstr)+1); + } + + /** + * Fixes login-without-aura glitch (the screen won't blink at this point, don't worry :P) + **/ + clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y); + } + + /** + * Check if player have any cool downs on + **/ + skill_cooldown_load(sd); + + /** + * Check if player have any item cooldowns on + **/ + pc_itemcd_do(sd,true); + + // Request all registries (auth is considered completed whence they arrive) + intif_request_registry(sd,7); + return true; } /*========================================== @@ -1119,34 +1118,34 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim *------------------------------------------*/ void pc_authfail(struct map_session_data *sd) { - clif_authfail_fd(sd->fd, 0); - return; + clif_authfail_fd(sd->fd, 0); + return; } //Attempts to set a mob. int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl) { - int class_; - if (!sd || !bl || pos < 0 || pos > 2) - return 0; - if (sd->hate_mob[pos] != -1) { - //Can't change hate targets. - clif_hate_info(sd, pos, sd->hate_mob[pos], 0); //Display current - return 0; - } - - class_ = status_get_class(bl); - if (!pcdb_checkid(class_)) { - unsigned int max_hp = status_get_max_hp(bl); - if ((pos == 1 && max_hp < 6000) || (pos == 2 && max_hp < 20000)) - return 0; - if (pos != status_get_size(bl)) - return 0; //Wrong size - } - sd->hate_mob[pos] = class_; - pc_setglobalreg(sd,sg_info[pos].hate_var,class_+1); - clif_hate_info(sd, pos, class_, 1); - return 1; + int class_; + if (!sd || !bl || pos < 0 || pos > 2) + return 0; + if (sd->hate_mob[pos] != -1) + { //Can't change hate targets. + clif_hate_info(sd, pos, sd->hate_mob[pos], 0); //Display current + return 0; + } + + class_ = status_get_class(bl); + if (!pcdb_checkid(class_)) { + unsigned int max_hp = status_get_max_hp(bl); + if ((pos == 1 && max_hp < 6000) || (pos == 2 && max_hp < 20000)) + return 0; + if (pos != status_get_size(bl)) + return 0; //Wrong size + } + sd->hate_mob[pos] = class_; + pc_setglobalreg(sd,sg_info[pos].hate_var,class_+1); + clif_hate_info(sd, pos, class_, 1); + return 1; } /*========================================== @@ -1154,124 +1153,126 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl) *------------------------------------------*/ int pc_reg_received(struct map_session_data *sd) { - int i,j; - - sd->change_level_2nd = pc_readglobalreg(sd,"jobchange_level"); - sd->change_level_3rd = pc_readglobalreg(sd,"jobchange_level_3rd"); - sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER"); - - // Cash shop - sd->cashPoints = pc_readaccountreg(sd,"#CASHPOINTS"); - sd->kafraPoints = pc_readaccountreg(sd,"#KAFRAPOINTS"); - - // Cooking Exp - sd->cook_mastery = pc_readglobalreg(sd,"COOK_MASTERY"); - - if ((sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON) { - // Better check for class rather than skill to prevent "skill resets" from unsetting this - sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID"); - sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT"); - } - - //SG map and mob read [Komurka] - for (i=0; i<MAX_PC_FEELHATE; i++) { //for now - someone need to make reading from txt/sql - if ((j = pc_readglobalreg(sd,sg_info[i].feel_var))!=0) { - sd->feel_map[i].index = j; - sd->feel_map[i].m = map_mapindex2mapid(j); - } else { - sd->feel_map[i].index = 0; - sd->feel_map[i].m = -1; - } - sd->hate_mob[i] = pc_readglobalreg(sd,sg_info[i].hate_var)-1; - } - - if ((i = pc_checkskill(sd,RG_PLAGIARISM)) > 0) { - sd->cloneskill_id = pc_readglobalreg(sd,"CLONE_SKILL"); - if (sd->cloneskill_id > 0) { - sd->status.skill[sd->cloneskill_id].id = sd->cloneskill_id; - sd->status.skill[sd->cloneskill_id].lv = pc_readglobalreg(sd,"CLONE_SKILL_LV"); - if (sd->status.skill[sd->cloneskill_id].lv > i) - sd->status.skill[sd->cloneskill_id].lv = i; - sd->status.skill[sd->cloneskill_id].flag = SKILL_FLAG_PLAGIARIZED; - } - } - if ((i = pc_checkskill(sd,SC_REPRODUCE)) > 0) { - sd->reproduceskill_id = pc_readglobalreg(sd,"REPRODUCE_SKILL"); - if (sd->reproduceskill_id > 0) { - sd->status.skill[sd->reproduceskill_id].id = sd->reproduceskill_id; - sd->status.skill[sd->reproduceskill_id].lv = pc_readglobalreg(sd,"REPRODUCE_SKILL_LV"); - if (i < sd->status.skill[sd->reproduceskill_id].lv) - sd->status.skill[sd->reproduceskill_id].lv = i; - sd->status.skill[sd->reproduceskill_id].flag = SKILL_FLAG_PLAGIARIZED; - } - } - //Weird... maybe registries were reloaded? - if (sd->state.active) - return 0; - sd->state.active = 1; - - if (sd->status.party_id) - party_member_joined(sd); - if (sd->status.guild_id) - guild_member_joined(sd); - - // pet - if (sd->status.pet_id > 0) - intif_request_petdata(sd->status.account_id, sd->status.char_id, sd->status.pet_id); - - // Homunculus [albator] - if (sd->status.hom_id > 0) - intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); - if (sd->status.mer_id > 0) - intif_mercenary_request(sd->status.mer_id, sd->status.char_id); - if (sd->status.ele_id > 0) - intif_elemental_request(sd->status.ele_id, sd->status.char_id); - - map_addiddb(&sd->bl); - map_delnickdb(sd->status.char_id, sd->status.name); - if (!chrif_auth_finished(sd)) - ShowError("pc_reg_received: Failed to properly remove player %d:%d from logging db!\n", sd->status.account_id, sd->status.char_id); - - pc_load_combo(sd); - - status_calc_pc(sd,1); - chrif_scdata_request(sd->status.account_id, sd->status.char_id); - - intif_Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox - intif_request_questlog(sd); - - if (sd->state.connect_new == 0 && sd->fd) { - //Character already loaded map! Gotta trigger LoadEndAck manually. - sd->state.connect_new = 1; - clif_parse_LoadEndAck(sd->fd, sd); - } - - pc_inventory_rentals(sd); - - return 1; -} - -static int pc_calc_skillpoint(struct map_session_data *sd) -{ - int i,skill,inf2,skill_point=0; - - nullpo_ret(sd); - - for (i=1; i<MAX_SKILL; i++) { - if ((skill = pc_checkskill(sd,i)) > 0) { - inf2 = skill_get_inf2(i); - if ((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) && - !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex] - ) { - if (sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) - skill_point += skill; - else if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) - skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0); - } - } - } - - return skill_point; + int i,j; + + sd->change_level_2nd = pc_readglobalreg(sd,"jobchange_level"); + sd->change_level_3rd = pc_readglobalreg(sd,"jobchange_level_3rd"); + sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER"); + + // Cash shop + sd->cashPoints = pc_readaccountreg(sd,"#CASHPOINTS"); + sd->kafraPoints = pc_readaccountreg(sd,"#KAFRAPOINTS"); + + // Cooking Exp + sd->cook_mastery = pc_readglobalreg(sd,"COOK_MASTERY"); + + if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) + { // Better check for class rather than skill to prevent "skill resets" from unsetting this + sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID"); + sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT"); + } + + //SG map and mob read [Komurka] + for(i=0;i<MAX_PC_FEELHATE;i++) //for now - someone need to make reading from txt/sql + { + if ((j = pc_readglobalreg(sd,sg_info[i].feel_var))!=0) { + sd->feel_map[i].index = j; + sd->feel_map[i].m = map_mapindex2mapid(j); + } else { + sd->feel_map[i].index = 0; + sd->feel_map[i].m = -1; + } + sd->hate_mob[i] = pc_readglobalreg(sd,sg_info[i].hate_var)-1; + } + + if ((i = pc_checkskill(sd,RG_PLAGIARISM)) > 0) { + sd->cloneskill_id = pc_readglobalreg(sd,"CLONE_SKILL"); + if (sd->cloneskill_id > 0) { + sd->status.skill[sd->cloneskill_id].id = sd->cloneskill_id; + sd->status.skill[sd->cloneskill_id].lv = pc_readglobalreg(sd,"CLONE_SKILL_LV"); + if (sd->status.skill[sd->cloneskill_id].lv > i) + sd->status.skill[sd->cloneskill_id].lv = i; + sd->status.skill[sd->cloneskill_id].flag = SKILL_FLAG_PLAGIARIZED; + } + } + if ((i = pc_checkskill(sd,SC_REPRODUCE)) > 0) { + sd->reproduceskill_id = pc_readglobalreg(sd,"REPRODUCE_SKILL"); + if( sd->reproduceskill_id > 0) { + sd->status.skill[sd->reproduceskill_id].id = sd->reproduceskill_id; + sd->status.skill[sd->reproduceskill_id].lv = pc_readglobalreg(sd,"REPRODUCE_SKILL_LV"); + if( i < sd->status.skill[sd->reproduceskill_id].lv) + sd->status.skill[sd->reproduceskill_id].lv = i; + sd->status.skill[sd->reproduceskill_id].flag = SKILL_FLAG_PLAGIARIZED; + } + } + //Weird... maybe registries were reloaded? + if (sd->state.active) + return 0; + sd->state.active = 1; + + if (sd->status.party_id) + party_member_joined(sd); + if (sd->status.guild_id) + guild_member_joined(sd); + + // pet + if (sd->status.pet_id > 0) + intif_request_petdata(sd->status.account_id, sd->status.char_id, sd->status.pet_id); + + // Homunculus [albator] + if( sd->status.hom_id > 0 ) + intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); + if( sd->status.mer_id > 0 ) + intif_mercenary_request(sd->status.mer_id, sd->status.char_id); + if( sd->status.ele_id > 0 ) + intif_elemental_request(sd->status.ele_id, sd->status.char_id); + + map_addiddb(&sd->bl); + map_delnickdb(sd->status.char_id, sd->status.name); + if (!chrif_auth_finished(sd)) + ShowError("pc_reg_received: Failed to properly remove player %d:%d from logging db!\n", sd->status.account_id, sd->status.char_id); + + pc_load_combo(sd); + + status_calc_pc(sd,1); + chrif_scdata_request(sd->status.account_id, sd->status.char_id); + + intif_Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox + intif_request_questlog(sd); + + if (sd->state.connect_new == 0 && sd->fd) + { //Character already loaded map! Gotta trigger LoadEndAck manually. + sd->state.connect_new = 1; + clif_parse_LoadEndAck(sd->fd, sd); + } + + pc_inventory_rentals(sd); + + return 1; +} + +static int pc_calc_skillpoint(struct map_session_data* sd) +{ + int i,skill,inf2,skill_point=0; + + nullpo_ret(sd); + + for(i=1;i<MAX_SKILL;i++){ + if( (skill = pc_checkskill(sd,i)) > 0) { + inf2 = skill_get_inf2(i); + if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) && + !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex] + ) { + if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) + skill_point += skill; + else + if(sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) + skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0); + } + } + } + + return skill_point; } @@ -1280,298 +1281,327 @@ static int pc_calc_skillpoint(struct map_session_data *sd) *------------------------------------------*/ int pc_calc_skilltree(struct map_session_data *sd) { - int i,id=0,flag; - int c=0; - - nullpo_ret(sd); - i = pc_calc_skilltree_normalize_job(sd); - c = pc_mapid2jobid(i, sd->status.sex); - if (c == -1) { - //Unable to normalize job?? - ShowError("pc_calc_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id); - return 1; - } - c = pc_class2idx(c); - - for (i = 0; i < MAX_SKILL; i++) { - if (sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) //Don't touch plagiarized skills - sd->status.skill[i].id = 0; //First clear skills. - } - - for (i = 0; i < MAX_SKILL; i++) { - if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) { - // Restore original level of skills after deleting earned skills. - sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; - sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; - } - - if (sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU) { - //Enable Bard/Dancer spirit linked skills. - if (sd->status.sex) { - //Link dancer skills to bard. - if (sd->status.skill[i-8].lv < 10) - continue; - sd->status.skill[i].id = i; - sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill - sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill - } else { - //Link bard skills to dancer. - if (sd->status.skill[i].lv < 10) - continue; - sd->status.skill[i-8].id = i - 8; - sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill - sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill - } - } - } - - if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) { - for (i = 0; i < MAX_SKILL; i++) { - switch (i) { - /** - * Dummy skills must be added here otherwise they'll be displayed in the, - * skill tree and since they have no icons they'll give resource errors - **/ - case SM_SELFPROVOKE: - case AB_DUPLELIGHT_MELEE: - case AB_DUPLELIGHT_MAGIC: - case WL_CHAINLIGHTNING_ATK: - case WL_TETRAVORTEX_FIRE: - case WL_TETRAVORTEX_WATER: - case WL_TETRAVORTEX_WIND: - case WL_TETRAVORTEX_GROUND: - case WL_SUMMON_ATK_FIRE: - case WL_SUMMON_ATK_WIND: - case WL_SUMMON_ATK_WATER: - case WL_SUMMON_ATK_GROUND: - case LG_OVERBRAND_BRANDISH: - case LG_OVERBRAND_PLUSATK: - case WM_SEVERE_RAINSTORM_MELEE: - continue; - default: - break; - } - if (skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) - continue; //Only skills you can't have are npc/guild ones - if (skill_get_max(i) > 0) - sd->status.skill[i].id = i; - } - return 0; - } - - do { - flag = 0; - for (i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++) { - int j, f, k, inf2; - - if (sd->status.skill[id].id) - continue; //Skill already known. - - f = 1; - if (!battle_config.skillfree) { - for (j = 0; j < MAX_PC_SKILL_REQUIRE; j++) { - if ((k=skill_tree[c][i].need[j].id)) { - if (sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED) - k = 0; //Not learned. - else if (sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level - k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; - else - k = pc_checkskill(sd,k); - if (k < skill_tree[c][i].need[j].lv) { - f = 0; - break; - } - } - } - if (sd->status.job_level < skill_tree[c][i].joblv) - f = 0; // job level requirement wasn't satisfied - } - - if (f) { - inf2 = skill_get_inf2(id); - - if (!sd->status.skill[id].lv && ( - (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || - inf2&INF2_WEDDING_SKILL || - (inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) - )) - continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills. - - sd->status.skill[id].id = id; - - if (inf2&INF2_SPIRIT_SKILL) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed. - sd->status.skill[id].lv = 1; // need to manually specify a skill level - sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill. - } - flag = 1; // skill list has changed, perform another pass - } - } - } while (flag); - - // - if (c > 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && sd->status.skill_point == 0 && pc_famerank(sd->status.char_id, MAPID_TAEKWON)) { - /* Taekwon Ranger Bonus Skill Tree - ============================================ - - Grant All Taekwon Tree, but only as Bonus Skills in case they drop from ranking. - - (c > 0) to avoid grant Novice Skill Tree in case of Skill Reset (need more logic) - - (sd->status.skill_point == 0) to wait until all skill points are asigned to avoid problems with Job Change quest. */ - - for (i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++) { - if ((skill_get_inf2(id)&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL))) - continue; //Do not include Quest/Wedding skills. - - if (sd->status.skill[id].id == 0) { - sd->status.skill[id].id = id; - sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill. - } else { - sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Remember original level - } - - sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); - } - } - - return 0; + int i,id=0,flag; + int c=0; + + nullpo_ret(sd); + i = pc_calc_skilltree_normalize_job(sd); + c = pc_mapid2jobid(i, sd->status.sex); + if( c == -1 ) + { //Unable to normalize job?? + ShowError("pc_calc_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id); + return 1; + } + c = pc_class2idx(c); + + for( i = 0; i < MAX_SKILL; i++ ) + { + if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) //Don't touch plagiarized skills + sd->status.skill[i].id = 0; //First clear skills. + } + + for( i = 0; i < MAX_SKILL; i++ ) + { + if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) + { // Restore original level of skills after deleting earned skills. + sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; + sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; + } + + if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU ) + { //Enable Bard/Dancer spirit linked skills. + if( sd->status.sex ) + { //Link dancer skills to bard. + if( sd->status.skill[i-8].lv < 10 ) + continue; + sd->status.skill[i].id = i; + sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill + sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill + } + else + { //Link bard skills to dancer. + if( sd->status.skill[i].lv < 10 ) + continue; + sd->status.skill[i-8].id = i - 8; + sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill + sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill + } + } + } + + if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) { + for( i = 0; i < MAX_SKILL; i++ ) { + switch(i) { + /** + * Dummy skills must be added here otherwise they'll be displayed in the, + * skill tree and since they have no icons they'll give resource errors + **/ + case SM_SELFPROVOKE: + case AB_DUPLELIGHT_MELEE: + case AB_DUPLELIGHT_MAGIC: + case WL_CHAINLIGHTNING_ATK: + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + case WL_SUMMON_ATK_FIRE: + case WL_SUMMON_ATK_WIND: + case WL_SUMMON_ATK_WATER: + case WL_SUMMON_ATK_GROUND: + case LG_OVERBRAND_BRANDISH: + case LG_OVERBRAND_PLUSATK: + case WM_SEVERE_RAINSTORM_MELEE: + continue; + default: + break; + } + if( skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL) ) + continue; //Only skills you can't have are npc/guild ones + if( skill_get_max(i) > 0 ) + sd->status.skill[i].id = i; + } + return 0; + } + + do { + flag = 0; + for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ ) + { + int j, f, k, inf2; + + if( sd->status.skill[id].id ) + continue; //Skill already known. + + f = 1; + if(!battle_config.skillfree) { + for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) { + if((k=skill_tree[c][i].need[j].id)) + { + if (sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED) + k = 0; //Not learned. + else + if (sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level + k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; + else + k = pc_checkskill(sd,k); + if (k < skill_tree[c][i].need[j].lv) + { + f = 0; + break; + } + } + } + if( sd->status.job_level < skill_tree[c][i].joblv ) + f = 0; // job level requirement wasn't satisfied + } + + if( f ) { + inf2 = skill_get_inf2(id); + + if(!sd->status.skill[id].lv && ( + (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || + inf2&INF2_WEDDING_SKILL || + (inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) + )) + continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills. + + sd->status.skill[id].id = id; + + if(inf2&INF2_SPIRIT_SKILL) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed. + sd->status.skill[id].lv = 1; // need to manually specify a skill level + sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill. + } + flag = 1; // skill list has changed, perform another pass + } + } + } while(flag); + + // + if( c > 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && sd->status.skill_point == 0 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) ) + { + /* Taekwon Ranger Bonus Skill Tree + ============================================ + - Grant All Taekwon Tree, but only as Bonus Skills in case they drop from ranking. + - (c > 0) to avoid grant Novice Skill Tree in case of Skill Reset (need more logic) + - (sd->status.skill_point == 0) to wait until all skill points are asigned to avoid problems with Job Change quest. */ + + for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ ) + { + if( (skill_get_inf2(id)&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) ) + continue; //Do not include Quest/Wedding skills. + + if( sd->status.skill[id].id == 0 ) + { + sd->status.skill[id].id = id; + sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill. + } + else + { + sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Remember original level + } + + sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); + } + } + + return 0; } //Checks if you can learn a new skill after having leveled up a skill. static void pc_check_skilltree(struct map_session_data *sd, int skill) { - int i,id=0,flag; - int c=0; - - if (battle_config.skillfree) - return; //Function serves no purpose if this is set - - i = pc_calc_skilltree_normalize_job(sd); - c = pc_mapid2jobid(i, sd->status.sex); - if (c == -1) { //Unable to normalize job?? - ShowError("pc_check_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id); - return; - } - c = pc_class2idx(c); - do { - flag = 0; - for (i = 0; i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0; i++) { - int j, f = 1, k; - - if (sd->status.skill[id].id) //Already learned - continue; - - for (j = 0; j < MAX_PC_SKILL_REQUIRE; j++) { - if ((k = skill_tree[c][i].need[j].id)) { - if (sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED) - k = 0; //Not learned. - else if (sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level - k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; - else - k = pc_checkskill(sd,k); - if (k < skill_tree[c][i].need[j].lv) { - f = 0; - break; - } - } - } - if (!f) - continue; - if (sd->status.job_level < skill_tree[c][i].joblv) - continue; - - j = skill_get_inf2(id); - if (!sd->status.skill[id].lv && ( - (j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || - j&INF2_WEDDING_SKILL || - (j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) - )) - continue; //Cannot be learned via normal means. - - sd->status.skill[id].id = id; - flag = 1; - } - } while (flag); + int i,id=0,flag; + int c=0; + + if(battle_config.skillfree) + return; //Function serves no purpose if this is set + + i = pc_calc_skilltree_normalize_job(sd); + c = pc_mapid2jobid(i, sd->status.sex); + if (c == -1) { //Unable to normalize job?? + ShowError("pc_check_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id); + return; + } + c = pc_class2idx(c); + do { + flag = 0; + for( i = 0; i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0; i++ ) + { + int j, f = 1, k; + + if( sd->status.skill[id].id ) //Already learned + continue; + + for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) + { + if( (k = skill_tree[c][i].need[j].id) ) + { + if( sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED ) + k = 0; //Not learned. + else + if( sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level + k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; + else + k = pc_checkskill(sd,k); + if( k < skill_tree[c][i].need[j].lv ) + { + f = 0; + break; + } + } + } + if( !f ) + continue; + if( sd->status.job_level < skill_tree[c][i].joblv ) + continue; + + j = skill_get_inf2(id); + if( !sd->status.skill[id].lv && ( + (j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || + j&INF2_WEDDING_SKILL || + (j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) + ) ) + continue; //Cannot be learned via normal means. + + sd->status.skill[id].id = id; + flag = 1; + } + } while(flag); } // 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 == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) { - sd->status.skill[i].id = 0; - sd->status.skill[i].lv = 0; - sd->status.skill[i].flag = 0; - } else if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) { - sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; - sd->status.skill[i].flag = 0; - } - } + int i; + for (i = 0; i < MAX_SKILL; i++){ + if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) + { + sd->status.skill[i].id = 0; + sd->status.skill[i].lv = 0; + sd->status.skill[i].flag = 0; + } + else + if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0){ + sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; + sd->status.skill[i].flag = 0; + } + } - return 0; + return 0; } int pc_calc_skilltree_normalize_job(struct map_session_data *sd) { - int skill_point, novice_skills; - int c = sd->class_; - - if (!battle_config.skillup_limit || pc_has_permission(sd, PC_PERM_ALL_SKILL)) - return c; - - skill_point = pc_calc_skillpoint(sd); - - novice_skills = max_level[pc_class2idx(JOB_NOVICE)][1] - 1; - - // limit 1st class and above to novice job levels - if (skill_point < novice_skills) { - c = MAPID_NOVICE; - } - // limit 2nd class and above to first class job levels (super novices are exempt) - else if ((sd->class_&JOBL_2) && (sd->class_&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) { - // regenerate change_level_2nd - if (!sd->change_level_2nd) { - if (sd->class_&JOBL_THIRD) { - // if neither 2nd nor 3rd jobchange levels are known, we have to assume a default for 2nd - if (!sd->change_level_3rd) - sd->change_level_2nd = max_level[pc_class2idx(pc_mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex))][1]; - else - sd->change_level_2nd = 1 + skill_point + sd->status.skill_point - - (sd->status.job_level - 1) - - (sd->change_level_3rd - 1) - - novice_skills; - } else { - sd->change_level_2nd = 1 + skill_point + sd->status.skill_point - - (sd->status.job_level - 1) - - novice_skills; - - } - - pc_setglobalreg(sd, "jobchange_level", sd->change_level_2nd); - } - - if (skill_point < novice_skills + (sd->change_level_2nd - 1)) { - c &= MAPID_BASEMASK; - } - // limit 3rd class to 2nd class/trans job levels - else if (sd->class_&JOBL_THIRD) { - // regenerate change_level_3rd - if (!sd->change_level_3rd) { - sd->change_level_3rd = 1 + skill_point + sd->status.skill_point - - (sd->status.job_level - 1) - - (sd->change_level_2nd - 1) - - novice_skills; - pc_setglobalreg(sd, "jobchange_level_3rd", sd->change_level_3rd); - } - - if (skill_point < novice_skills + (sd->change_level_2nd - 1) + (sd->change_level_3rd - 1)) - c &= MAPID_UPPERMASK; - } - } - - // restore non-limiting flags - c |= sd->class_&(JOBL_UPPER|JOBL_BABY); - - return c; + int skill_point, novice_skills; + int c = sd->class_; + + if (!battle_config.skillup_limit || pc_has_permission(sd, PC_PERM_ALL_SKILL)) + return c; + + skill_point = pc_calc_skillpoint(sd); + + novice_skills = max_level[pc_class2idx(JOB_NOVICE)][1] - 1; + + // limit 1st class and above to novice job levels + if(skill_point < novice_skills) + { + c = MAPID_NOVICE; + } + // limit 2nd class and above to first class job levels (super novices are exempt) + else if ((sd->class_&JOBL_2) && (sd->class_&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) + { + // regenerate change_level_2nd + if (!sd->change_level_2nd) + { + if (sd->class_&JOBL_THIRD) + { + // if neither 2nd nor 3rd jobchange levels are known, we have to assume a default for 2nd + if (!sd->change_level_3rd) + sd->change_level_2nd = max_level[pc_class2idx(pc_mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex))][1]; + else + sd->change_level_2nd = 1 + skill_point + sd->status.skill_point + - (sd->status.job_level - 1) + - (sd->change_level_3rd - 1) + - novice_skills; + } + else + { + sd->change_level_2nd = 1 + skill_point + sd->status.skill_point + - (sd->status.job_level - 1) + - novice_skills; + + } + + pc_setglobalreg (sd, "jobchange_level", sd->change_level_2nd); + } + + if (skill_point < novice_skills + (sd->change_level_2nd - 1)) + { + c &= MAPID_BASEMASK; + } + // limit 3rd class to 2nd class/trans job levels + else if(sd->class_&JOBL_THIRD) + { + // regenerate change_level_3rd + if (!sd->change_level_3rd) + { + sd->change_level_3rd = 1 + skill_point + sd->status.skill_point + - (sd->status.job_level - 1) + - (sd->change_level_2nd - 1) + - novice_skills; + pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd); + } + + if (skill_point < novice_skills + (sd->change_level_2nd - 1) + (sd->change_level_3rd - 1)) + c &= MAPID_UPPERMASK; + } + } + + // restore non-limiting flags + c |= sd->class_&(JOBL_UPPER|JOBL_BABY); + + return c; } /*========================================== @@ -1583,384 +1613,405 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd) */ int pc_updateweightstatus(struct map_session_data *sd) { - int old_overweight; - int new_overweight; + int old_overweight; + int new_overweight; - nullpo_retr(1, sd); + nullpo_retr(1, sd); - old_overweight = (sd->sc.data[SC_WEIGHT90]) ? 2 : (sd->sc.data[SC_WEIGHT50]) ? 1 : 0; - new_overweight = (pc_is90overweight(sd)) ? 2 : (pc_is50overweight(sd)) ? 1 : 0; + old_overweight = (sd->sc.data[SC_WEIGHT90]) ? 2 : (sd->sc.data[SC_WEIGHT50]) ? 1 : 0; + new_overweight = (pc_is90overweight(sd)) ? 2 : (pc_is50overweight(sd)) ? 1 : 0; - if (old_overweight == new_overweight) - return 0; // no change + if( old_overweight == new_overweight ) + return 0; // no change - // stop old status change - if (old_overweight == 1) - status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER); - else if (old_overweight == 2) - status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER); + // stop old status change + if( old_overweight == 1 ) + status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER); + else if( old_overweight == 2 ) + status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER); - // start new status change - if (new_overweight == 1) - sc_start(&sd->bl, SC_WEIGHT50, 100, 0, 0); - else if (new_overweight == 2) - sc_start(&sd->bl, SC_WEIGHT90, 100, 0, 0); + // start new status change + if( new_overweight == 1 ) + sc_start(&sd->bl, SC_WEIGHT50, 100, 0, 0); + else if( new_overweight == 2 ) + sc_start(&sd->bl, SC_WEIGHT90, 100, 0, 0); - // update overweight status - sd->regen.state.overweight = new_overweight; + // update overweight status + sd->regen.state.overweight = new_overweight; - return 0; + return 0; } int pc_disguise(struct map_session_data *sd, int class_) { - if (!class_ && !sd->disguise) - return 0; - if (class_ && sd->disguise == class_) - return 0; - - if (sd->sc.option&OPTION_INVISIBLE) { - //Character is invisible. Stealth class-change. [Skotlex] - sd->disguise = class_; //viewdata is set on uncloaking. - return 2; - } - - if (sd->bl.prev != NULL) { - pc_stop_walking(sd, 0); - clif_clearunit_area(&sd->bl, CLR_OUTSIGHT); - } - - if (!class_) { - sd->disguise = 0; - class_ = sd->status.class_; - } else - sd->disguise=class_; - - status_set_viewdata(&sd->bl, class_); - clif_changeoption(&sd->bl); - - if (sd->bl.prev != NULL) { - clif_spawn(&sd->bl); - if (class_ == sd->status.class_ && pc_iscarton(sd)) { - //It seems the cart info is lost on undisguise. - clif_cartlist(sd); - clif_updatestatus(sd,SP_CARTINFO); - } - } - return 1; + if (!class_ && !sd->disguise) + return 0; + if (class_ && sd->disguise == class_) + return 0; + + if(sd->sc.option&OPTION_INVISIBLE) + { //Character is invisible. Stealth class-change. [Skotlex] + sd->disguise = class_; //viewdata is set on uncloaking. + return 2; + } + + if (sd->bl.prev != NULL) { + pc_stop_walking(sd, 0); + clif_clearunit_area(&sd->bl, CLR_OUTSIGHT); + } + + if (!class_) { + sd->disguise = 0; + class_ = sd->status.class_; + } else + sd->disguise=class_; + + status_set_viewdata(&sd->bl, class_); + clif_changeoption(&sd->bl); + + if (sd->bl.prev != NULL) { + clif_spawn(&sd->bl); + if (class_ == sd->status.class_ && pc_iscarton(sd)) + { //It seems the cart info is lost on undisguise. + clif_cartlist(sd); + clif_updatestatus(sd,SP_CARTINFO); + } + } + return 1; } static int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short flag, short card_id) { - int i; - - if (!rate) - return 0; - - for (i = 0; i < max && spell[i].id; i++) { - if ((spell[i].card_id == card_id || spell[i].rate < 0 || rate < 0) && spell[i].id == id && spell[i].lv == lv) { - if (!battle_config.autospell_stacking && spell[i].rate > 0 && rate > 0) - return 0; - rate += spell[i].rate; - break; - } - } - if (i == max) { - ShowWarning("pc_bonus: Reached max (%d) number of autospells per character!\n", max); - return 0; - } - spell[i].id = id; - spell[i].lv = lv; - spell[i].rate = rate; - //Auto-update flag value. - if (!(flag&BF_RANGEMASK)) flag|=BF_SHORT|BF_LONG; //No range defined? Use both. - if (!(flag&BF_WEAPONMASK)) flag|=BF_WEAPON; //No attack type defined? Use weapon. - if (!(flag&BF_SKILLMASK)) { - if (flag&(BF_MAGIC|BF_MISC)) flag|=BF_SKILL; //These two would never trigger without BF_SKILL - if (flag&BF_WEAPON) flag|=BF_NORMAL; //By default autospells should only trigger on normal weapon attacks. - } - spell[i].flag|= flag; - spell[i].card_id = card_id; - return 1; + int i; + + if( !rate ) + return 0; + + for( i = 0; i < max && spell[i].id; i++ ) + { + if( (spell[i].card_id == card_id || spell[i].rate < 0 || rate < 0) && spell[i].id == id && spell[i].lv == lv ) + { + if( !battle_config.autospell_stacking && spell[i].rate > 0 && rate > 0 ) + return 0; + rate += spell[i].rate; + break; + } + } + if (i == max) { + ShowWarning("pc_bonus: Reached max (%d) number of autospells per character!\n", max); + return 0; + } + spell[i].id = id; + spell[i].lv = lv; + spell[i].rate = rate; + //Auto-update flag value. + if (!(flag&BF_RANGEMASK)) flag|=BF_SHORT|BF_LONG; //No range defined? Use both. + if (!(flag&BF_WEAPONMASK)) flag|=BF_WEAPON; //No attack type defined? Use weapon. + if (!(flag&BF_SKILLMASK)) { + if (flag&(BF_MAGIC|BF_MISC)) flag|=BF_SKILL; //These two would never trigger without BF_SKILL + if (flag&BF_WEAPON) flag|=BF_NORMAL; //By default autospells should only trigger on normal weapon attacks. + } + spell[i].flag|= flag; + spell[i].card_id = card_id; + return 1; } static int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_skill, short id, short lv, short rate, short card_id) { - int i; - - if (!rate) - return 0; - - for (i = 0; i < max && spell[i].id; i++) { - ; // each autospell works independently - } - - if (i == max) { - ShowWarning("pc_bonus: Reached max (%d) number of autospells per character!\n", max); - return 0; - } - - spell[i].flag = src_skill; - spell[i].id = id; - spell[i].lv = lv; - spell[i].rate = rate; - spell[i].card_id = card_id; - return 1; -} - -static int pc_bonus_addeff(struct s_addeffect *effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag) -{ - int i; - if (!(flag&(ATF_SHORT|ATF_LONG))) - flag|=ATF_SHORT|ATF_LONG; //Default range: both - if (!(flag&(ATF_TARGET|ATF_SELF))) - flag|=ATF_TARGET; //Default target: enemy. - if (!(flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC))) - flag|=ATF_WEAPON; //Default type: weapon. - - for (i = 0; i < max && effect[i].flag; i++) { - if (effect[i].id == id && effect[i].flag == flag) { - effect[i].rate += rate; - effect[i].arrow_rate += arrow_rate; - return 1; - } - } - if (i == max) { - ShowWarning("pc_bonus: Reached max (%d) number of add effects per character!\n", max); - return 0; - } - effect[i].id = id; - effect[i].rate = rate; - effect[i].arrow_rate = arrow_rate; - effect[i].flag = flag; - return 1; -} - -static int pc_bonus_addeff_onskill(struct s_addeffectonskill *effect, int max, enum sc_type id, short rate, short skill, unsigned char target) -{ - int i; - for (i = 0; i < max && effect[i].skill; i++) { - if (effect[i].id == id && effect[i].skill == skill && effect[i].target == target) { - effect[i].rate += rate; - return 1; - } - } - if (i == max) { - ShowWarning("pc_bonus: Reached max (%d) number of add effects on skill per character!\n", max); - return 0; - } - effect[i].id = id; - effect[i].rate = rate; - effect[i].skill = skill; - effect[i].target = target; - return 1; + int i; + + if( !rate ) + return 0; + + for( i = 0; i < max && spell[i].id; i++ ) + { + ; // each autospell works independently + } + + if( i == max ) + { + ShowWarning("pc_bonus: Reached max (%d) number of autospells per character!\n", max); + return 0; + } + + spell[i].flag = src_skill; + spell[i].id = id; + spell[i].lv = lv; + spell[i].rate = rate; + spell[i].card_id = card_id; + return 1; +} + +static int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, short rate, short arrow_rate, unsigned char flag) +{ + int i; + if (!(flag&(ATF_SHORT|ATF_LONG))) + flag|=ATF_SHORT|ATF_LONG; //Default range: both + if (!(flag&(ATF_TARGET|ATF_SELF))) + flag|=ATF_TARGET; //Default target: enemy. + if (!(flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC))) + flag|=ATF_WEAPON; //Default type: weapon. + + for (i = 0; i < max && effect[i].flag; i++) { + if (effect[i].id == id && effect[i].flag == flag) + { + effect[i].rate += rate; + effect[i].arrow_rate += arrow_rate; + return 1; + } + } + if (i == max) { + ShowWarning("pc_bonus: Reached max (%d) number of add effects per character!\n", max); + return 0; + } + effect[i].id = id; + effect[i].rate = rate; + effect[i].arrow_rate = arrow_rate; + effect[i].flag = flag; + return 1; +} + +static int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill, unsigned char target) +{ + int i; + for( i = 0; i < max && effect[i].skill; i++ ) + { + if( effect[i].id == id && effect[i].skill == skill && effect[i].target == target ) + { + effect[i].rate += rate; + return 1; + } + } + if( i == max ) { + ShowWarning("pc_bonus: Reached max (%d) number of add effects on skill per character!\n", max); + return 0; + } + effect[i].id = id; + effect[i].rate = rate; + effect[i].skill = skill; + effect[i].target = target; + return 1; } static int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short group, int race, int rate) { - int i; - //Apply config rate adjustment settings. - if (rate >= 0) { //Absolute drop. - if (battle_config.item_rate_adddrop != 100) - rate = rate*battle_config.item_rate_adddrop/100; - if (rate < battle_config.item_drop_adddrop_min) - rate = battle_config.item_drop_adddrop_min; - else if (rate > battle_config.item_drop_adddrop_max) - rate = battle_config.item_drop_adddrop_max; - } else { //Relative drop, max/min limits are applied at drop time. - if (battle_config.item_rate_adddrop != 100) - rate = rate*battle_config.item_rate_adddrop/100; - if (rate > -1) - rate = -1; - } - for (i = 0; i < max && (drop[i].id || drop[i].group); i++) { - if ( - ((id && drop[i].id == id) || - (group && drop[i].group == group)) - && race > 0 - ) { - drop[i].race |= race; - if (drop[i].rate > 0 && rate > 0) { - //Both are absolute rates. - if (drop[i].rate < rate) - drop[i].rate = rate; - } else if (drop[i].rate < 0 && rate < 0) { - //Both are relative rates. - if (drop[i].rate > rate) - drop[i].rate = rate; - } else if (rate < 0) //Give preference to relative rate. - drop[i].rate = rate; - return 1; - } - } - if (i == max) { - ShowWarning("pc_bonus: Reached max (%d) number of added drops per character!\n", max); - return 0; - } - drop[i].id = id; - drop[i].group = group; - drop[i].race |= race; - drop[i].rate = rate; - return 1; + int i; + //Apply config rate adjustment settings. + if (rate >= 0) { //Absolute drop. + if (battle_config.item_rate_adddrop != 100) + rate = rate*battle_config.item_rate_adddrop/100; + if (rate < battle_config.item_drop_adddrop_min) + rate = battle_config.item_drop_adddrop_min; + else if (rate > battle_config.item_drop_adddrop_max) + rate = battle_config.item_drop_adddrop_max; + } else { //Relative drop, max/min limits are applied at drop time. + if (battle_config.item_rate_adddrop != 100) + rate = rate*battle_config.item_rate_adddrop/100; + if (rate > -1) + rate = -1; + } + for(i = 0; i < max && (drop[i].id || drop[i].group); i++) { + if( + ((id && drop[i].id == id) || + (group && drop[i].group == group)) + && race > 0 + ) { + drop[i].race |= race; + if(drop[i].rate > 0 && rate > 0) + { //Both are absolute rates. + if (drop[i].rate < rate) + drop[i].rate = rate; + } else + if(drop[i].rate < 0 && rate < 0) { + //Both are relative rates. + if (drop[i].rate > rate) + drop[i].rate = rate; + } else if (rate < 0) //Give preference to relative rate. + drop[i].rate = rate; + return 1; + } + } + if(i == max) { + ShowWarning("pc_bonus: Reached max (%d) number of added drops per character!\n", max); + return 0; + } + drop[i].id = id; + drop[i].group = group; + drop[i].race |= race; + drop[i].rate = rate; + return 1; } int pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short flag,const char *other_script,unsigned short pos,bool onskill) { - int i; - - ARR_FIND(0, max, i, bonus[i].rate == 0); - if (i == max) { - ShowWarning("pc_addautobonus: Reached max (%d) number of autobonus per character!\n", max); - return 0; - } - - if (!onskill) { - if (!(flag&BF_RANGEMASK)) - flag|=BF_SHORT|BF_LONG; //No range defined? Use both. - if (!(flag&BF_WEAPONMASK)) - flag|=BF_WEAPON; //No attack type defined? Use weapon. - if (!(flag&BF_SKILLMASK)) { - if (flag&(BF_MAGIC|BF_MISC)) - flag|=BF_SKILL; //These two would never trigger without BF_SKILL - if (flag&BF_WEAPON) - flag|=BF_NORMAL|BF_SKILL; - } - } - - bonus[i].rate = rate; - bonus[i].duration = dur; - bonus[i].active = INVALID_TIMER; - bonus[i].atk_type = flag; - bonus[i].pos = pos; - bonus[i].bonus_script = aStrdup(script); - bonus[i].other_script = other_script?aStrdup(other_script):NULL; - return 1; -} - -int pc_delautobonus(struct map_session_data *sd, struct s_autobonus *autobonus,char max,bool restore) -{ - int i; - nullpo_ret(sd); - - for (i = 0; i < max; i++) { - if (autobonus[i].active != INVALID_TIMER) { - if (restore && sd->state.autobonus&autobonus[i].pos) { - if (autobonus[i].bonus_script) { - int j; - ARR_FIND(0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos); - if (j < EQI_MAX-1) - script_run_autobonus(autobonus[i].bonus_script,sd->bl.id,sd->equip_index[j]); - } - continue; - } else { - // Logout / Unequipped an item with an activated bonus - delete_timer(autobonus[i].active,pc_endautobonus); - autobonus[i].active = INVALID_TIMER; - } - } - - if (autobonus[i].bonus_script) aFree(autobonus[i].bonus_script); - if (autobonus[i].other_script) aFree(autobonus[i].other_script); - autobonus[i].bonus_script = autobonus[i].other_script = NULL; - autobonus[i].rate = autobonus[i].atk_type = autobonus[i].duration = autobonus[i].pos = 0; - autobonus[i].active = INVALID_TIMER; - } - - return 0; + int i; + + ARR_FIND(0, max, i, bonus[i].rate == 0); + if( i == max ) + { + ShowWarning("pc_addautobonus: Reached max (%d) number of autobonus per character!\n", max); + return 0; + } + + if( !onskill ) + { + if( !(flag&BF_RANGEMASK) ) + flag|=BF_SHORT|BF_LONG; //No range defined? Use both. + if( !(flag&BF_WEAPONMASK) ) + flag|=BF_WEAPON; //No attack type defined? Use weapon. + if( !(flag&BF_SKILLMASK) ) + { + if( flag&(BF_MAGIC|BF_MISC) ) + flag|=BF_SKILL; //These two would never trigger without BF_SKILL + if( flag&BF_WEAPON ) + flag|=BF_NORMAL|BF_SKILL; + } + } + + bonus[i].rate = rate; + bonus[i].duration = dur; + bonus[i].active = INVALID_TIMER; + bonus[i].atk_type = flag; + bonus[i].pos = pos; + bonus[i].bonus_script = aStrdup(script); + bonus[i].other_script = other_script?aStrdup(other_script):NULL; + return 1; +} + +int pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,char max,bool restore) +{ + int i; + nullpo_ret(sd); + + for( i = 0; i < max; i++ ) + { + if( autobonus[i].active != INVALID_TIMER ) + { + if( restore && sd->state.autobonus&autobonus[i].pos ) + { + if( autobonus[i].bonus_script ) + { + int j; + ARR_FIND( 0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos ); + if( j < EQI_MAX-1 ) + script_run_autobonus(autobonus[i].bonus_script,sd->bl.id,sd->equip_index[j]); + } + continue; + } + else + { // Logout / Unequipped an item with an activated bonus + delete_timer(autobonus[i].active,pc_endautobonus); + autobonus[i].active = INVALID_TIMER; + } + } + + if( autobonus[i].bonus_script ) aFree(autobonus[i].bonus_script); + if( autobonus[i].other_script ) aFree(autobonus[i].other_script); + autobonus[i].bonus_script = autobonus[i].other_script = NULL; + autobonus[i].rate = autobonus[i].atk_type = autobonus[i].duration = autobonus[i].pos = 0; + autobonus[i].active = INVALID_TIMER; + } + + return 0; } int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus) { - nullpo_ret(sd); - nullpo_ret(autobonus); + nullpo_ret(sd); + nullpo_ret(autobonus); - if (autobonus->other_script) { - int j; - ARR_FIND(0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos); - if (j < EQI_MAX-1) - script_run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]); - } + if( autobonus->other_script ) + { + int j; + ARR_FIND( 0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos ); + if( j < EQI_MAX-1 ) + script_run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]); + } - autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)autobonus); - sd->state.autobonus |= autobonus->pos; - status_calc_pc(sd,0); + autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)autobonus); + sd->state.autobonus |= autobonus->pos; + status_calc_pc(sd,0); - return 0; + return 0; } int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd = map_id2sd(id); - struct s_autobonus *autobonus = (struct s_autobonus *)data; + struct map_session_data *sd = map_id2sd(id); + struct s_autobonus *autobonus = (struct s_autobonus *)data; - nullpo_ret(sd); - nullpo_ret(autobonus); + nullpo_ret(sd); + nullpo_ret(autobonus); - autobonus->active = INVALID_TIMER; - sd->state.autobonus &= ~autobonus->pos; - status_calc_pc(sd,0); - return 0; + autobonus->active = INVALID_TIMER; + sd->state.autobonus &= ~autobonus->pos; + status_calc_pc(sd,0); + return 0; } -int pc_bonus_addele(struct map_session_data *sd, unsigned char ele, short rate, short flag) +int pc_bonus_addele(struct map_session_data* sd, unsigned char ele, short rate, short flag) { - int i; - struct weapon_data *wd; + int i; + struct weapon_data* wd; - wd = (sd->state.lr_flag ? &sd->left_weapon : &sd->right_weapon); + wd = (sd->state.lr_flag ? &sd->left_weapon : &sd->right_weapon); - ARR_FIND(0, MAX_PC_BONUS, i, wd->addele2[i].rate == 0); + ARR_FIND(0, MAX_PC_BONUS, i, wd->addele2[i].rate == 0); - if (i == MAX_PC_BONUS) { - ShowWarning("pc_addele: Reached max (%d) possible bonuses for this player.\n", MAX_PC_BONUS); - return 0; - } + if (i == MAX_PC_BONUS) + { + ShowWarning("pc_addele: Reached max (%d) possible bonuses for this player.\n", MAX_PC_BONUS); + return 0; + } - if (!(flag&BF_RANGEMASK)) - flag |= BF_SHORT|BF_LONG; - if (!(flag&BF_WEAPONMASK)) - flag |= BF_WEAPON; - if (!(flag&BF_SKILLMASK)) { - if (flag&(BF_MAGIC|BF_MISC)) - flag |= BF_SKILL; - if (flag&BF_WEAPON) - flag |= BF_NORMAL|BF_SKILL; - } + if (!(flag&BF_RANGEMASK)) + flag |= BF_SHORT|BF_LONG; + if (!(flag&BF_WEAPONMASK)) + flag |= BF_WEAPON; + if (!(flag&BF_SKILLMASK)) + { + if (flag&(BF_MAGIC|BF_MISC)) + flag |= BF_SKILL; + if (flag&BF_WEAPON) + flag |= BF_NORMAL|BF_SKILL; + } - wd->addele2[i].ele = ele; - wd->addele2[i].rate = rate; - wd->addele2[i].flag = flag; + wd->addele2[i].ele = ele; + wd->addele2[i].rate = rate; + wd->addele2[i].flag = flag; - return 0; + return 0; } -int pc_bonus_subele(struct map_session_data *sd, unsigned char ele, short rate, short flag) +int pc_bonus_subele(struct map_session_data* sd, unsigned char ele, short rate, short flag) { - int i; + int i; - ARR_FIND(0, MAX_PC_BONUS, i, sd->subele2[i].rate == 0); + ARR_FIND(0, MAX_PC_BONUS, i, sd->subele2[i].rate == 0); - if (i == MAX_PC_BONUS) { - ShowWarning("pc_subele: Reached max (%d) possible bonuses for this player.\n", MAX_PC_BONUS); - return 0; - } + if (i == MAX_PC_BONUS) + { + ShowWarning("pc_subele: Reached max (%d) possible bonuses for this player.\n", MAX_PC_BONUS); + return 0; + } - if (!(flag&BF_RANGEMASK)) - flag |= BF_SHORT|BF_LONG; - if (!(flag&BF_WEAPONMASK)) - flag |= BF_WEAPON; - if (!(flag&BF_SKILLMASK)) { - if (flag&(BF_MAGIC|BF_MISC)) - flag |= BF_SKILL; - if (flag&BF_WEAPON) - flag |= BF_NORMAL|BF_SKILL; - } + if (!(flag&BF_RANGEMASK)) + flag |= BF_SHORT|BF_LONG; + if (!(flag&BF_WEAPONMASK)) + flag |= BF_WEAPON; + if (!(flag&BF_SKILLMASK)) + { + if (flag&(BF_MAGIC|BF_MISC)) + flag |= BF_SKILL; + if (flag&BF_WEAPON) + flag |= BF_NORMAL|BF_SKILL; + } - sd->subele2[i].ele = ele; - sd->subele2[i].rate = rate; - sd->subele2[i].flag = flag; + sd->subele2[i].ele = ele; + sd->subele2[i].rate = rate; + sd->subele2[i].flag = flag; - return 0; + return 0; } /*========================================== @@ -1968,588 +2019,597 @@ int pc_bonus_subele(struct map_session_data *sd, unsigned char ele, short rate, *------------------------------------------*/ int pc_bonus(struct map_session_data *sd,int type,int val) { - struct status_data *status; - int bonus; - nullpo_ret(sd); - - status = &sd->base_status; - - switch (type) { - case SP_STR: - case SP_AGI: - case SP_VIT: - case SP_INT: - case SP_DEX: - case SP_LUK: - if (sd->state.lr_flag != 2) - sd->param_bonus[type-SP_STR]+=val; - break; - case SP_ATK1: - if (!sd->state.lr_flag) { - bonus = status->rhw.atk + val; - status->rhw.atk = cap_value(bonus, 0, USHRT_MAX); - } else if (sd->state.lr_flag == 1) { - bonus = status->lhw.atk + val; - status->lhw.atk = cap_value(bonus, 0, USHRT_MAX); - } - break; - case SP_ATK2: - if (!sd->state.lr_flag) { - bonus = status->rhw.atk2 + val; - status->rhw.atk2 = cap_value(bonus, 0, USHRT_MAX); - } else if (sd->state.lr_flag == 1) { - bonus = status->lhw.atk2 + val; - status->lhw.atk2 = cap_value(bonus, 0, USHRT_MAX); - } - break; - case SP_BASE_ATK: - if (sd->state.lr_flag != 2) { - bonus = status->batk + val; - status->batk = cap_value(bonus, 0, USHRT_MAX); - } - break; - case SP_DEF1: - if (sd->state.lr_flag != 2) { - bonus = status->def + val; + struct status_data *status; + int bonus; + nullpo_ret(sd); + + status = &sd->base_status; + + switch(type){ + case SP_STR: + case SP_AGI: + case SP_VIT: + case SP_INT: + case SP_DEX: + case SP_LUK: + if(sd->state.lr_flag != 2) + sd->param_bonus[type-SP_STR]+=val; + break; + case SP_ATK1: + if(!sd->state.lr_flag) { + bonus = status->rhw.atk + val; + status->rhw.atk = cap_value(bonus, 0, USHRT_MAX); + } + else if(sd->state.lr_flag == 1) { + bonus = status->lhw.atk + val; + status->lhw.atk = cap_value(bonus, 0, USHRT_MAX); + } + break; + case SP_ATK2: + if(!sd->state.lr_flag) { + bonus = status->rhw.atk2 + val; + status->rhw.atk2 = cap_value(bonus, 0, USHRT_MAX); + } + else if(sd->state.lr_flag == 1) { + bonus = status->lhw.atk2 + val; + status->lhw.atk2 = cap_value(bonus, 0, USHRT_MAX); + } + break; + case SP_BASE_ATK: + if(sd->state.lr_flag != 2) { + bonus = status->batk + val; + status->batk = cap_value(bonus, 0, USHRT_MAX); + } + break; + case SP_DEF1: + if(sd->state.lr_flag != 2) { + bonus = status->def + val; #ifdef RENEWAL - status->def = cap_value(bonus, SHRT_MIN, SHRT_MAX); + status->def = cap_value(bonus, SHRT_MIN, SHRT_MAX); #else - status->def = cap_value(bonus, CHAR_MIN, CHAR_MAX); + status->def = cap_value(bonus, CHAR_MIN, CHAR_MAX); #endif - } - break; - case SP_DEF2: - if (sd->state.lr_flag != 2) { - bonus = status->def2 + val; - status->def2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } - break; - case SP_MDEF1: - if (sd->state.lr_flag != 2) { - bonus = status->mdef + val; + } + break; + case SP_DEF2: + if(sd->state.lr_flag != 2) { + bonus = status->def2 + val; + status->def2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } + break; + case SP_MDEF1: + if(sd->state.lr_flag != 2) { + bonus = status->mdef + val; #ifdef RENEWAL - status->mdef = cap_value(bonus, SHRT_MIN, SHRT_MAX); + status->mdef = cap_value(bonus, SHRT_MIN, SHRT_MAX); #else - status->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX); + status->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX); #endif - if (sd->state.lr_flag == 3) { //Shield, used for royal guard - sd->bonus.shieldmdef += bonus; - } - } - break; - case SP_MDEF2: - if (sd->state.lr_flag != 2) { - bonus = status->mdef2 + val; - status->mdef2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } - break; - case SP_HIT: - if (sd->state.lr_flag != 2) { - bonus = status->hit + val; - status->hit = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } else - sd->bonus.arrow_hit+=val; - break; - case SP_FLEE1: - if (sd->state.lr_flag != 2) { - bonus = status->flee + val; - status->flee = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } - break; - case SP_FLEE2: - if (sd->state.lr_flag != 2) { - bonus = status->flee2 + val*10; - status->flee2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } - break; - case SP_CRITICAL: - if (sd->state.lr_flag != 2) { - bonus = status->cri + val*10; - status->cri = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } else - sd->bonus.arrow_cri += val*10; - break; - case SP_ATKELE: - if (val >= ELE_MAX) { - ShowError("pc_bonus: SP_ATKELE: Invalid element %d\n", val); - break; - } - switch (sd->state.lr_flag) { - case 2: - switch (sd->status.weapon) { - case W_BOW: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - //Become weapon element. - status->rhw.ele=val; - break; - default: //Become arrow element. - sd->bonus.arrow_ele=val; - break; - } - break; - case 1: - status->lhw.ele=val; - break; - default: - status->rhw.ele=val; - break; - } - break; - case SP_DEFELE: - if (val >= ELE_MAX) { - ShowError("pc_bonus: SP_DEFELE: Invalid element %d\n", val); - break; - } - if (sd->state.lr_flag != 2) - status->def_ele=val; - break; - case SP_MAXHP: - if (sd->state.lr_flag == 2) - break; - val += (int)status->max_hp; - //Negative bonuses will underflow, this will be handled in status_calc_pc through casting - //If this is called outside of status_calc_pc, you'd better pray they do not underflow and end with UINT_MAX max_hp. - status->max_hp = (unsigned int)val; - break; - case SP_MAXSP: - if (sd->state.lr_flag == 2) - break; - val += (int)status->max_sp; - status->max_sp = (unsigned int)val; - break; - case SP_CASTRATE: - if (sd->state.lr_flag != 2) - sd->castrate+=val; - break; - case SP_MAXHPRATE: - if (sd->state.lr_flag != 2) - sd->hprate+=val; - break; - case SP_MAXSPRATE: - if (sd->state.lr_flag != 2) - sd->sprate+=val; - break; - case SP_SPRATE: - if (sd->state.lr_flag != 2) - sd->dsprate+=val; - break; - case SP_ATTACKRANGE: - switch (sd->state.lr_flag) { - case 2: - switch (sd->status.weapon) { - case W_BOW: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - status->rhw.range += val; - } - break; - case 1: - status->lhw.range += val; - break; - default: - status->rhw.range += val; - break; - } - break; - case SP_SPEED_RATE: //Non stackable increase - if (sd->state.lr_flag != 2) - sd->bonus.speed_rate = min(sd->bonus.speed_rate, -val); - break; - case SP_SPEED_ADDRATE: //Stackable increase - if (sd->state.lr_flag != 2) - sd->bonus.speed_add_rate -= val; - break; - case SP_ASPD: //Raw increase - if (sd->state.lr_flag != 2) - sd->bonus.aspd_add -= 10*val; - break; - case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone - if (sd->state.lr_flag != 2) + if( sd->state.lr_flag == 3 ) {//Shield, used for royal guard + sd->bonus.shieldmdef += bonus; + } + } + break; + case SP_MDEF2: + if(sd->state.lr_flag != 2) { + bonus = status->mdef2 + val; + status->mdef2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } + break; + case SP_HIT: + if(sd->state.lr_flag != 2) { + bonus = status->hit + val; + status->hit = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } else + sd->bonus.arrow_hit+=val; + break; + case SP_FLEE1: + if(sd->state.lr_flag != 2) { + bonus = status->flee + val; + status->flee = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } + break; + case SP_FLEE2: + if(sd->state.lr_flag != 2) { + bonus = status->flee2 + val*10; + status->flee2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } + break; + case SP_CRITICAL: + if(sd->state.lr_flag != 2) { + bonus = status->cri + val*10; + status->cri = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } else + sd->bonus.arrow_cri += val*10; + break; + case SP_ATKELE: + if(val >= ELE_MAX) { + ShowError("pc_bonus: SP_ATKELE: Invalid element %d\n", val); + break; + } + switch (sd->state.lr_flag) + { + case 2: + switch (sd->status.weapon) { + case W_BOW: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + //Become weapon element. + status->rhw.ele=val; + break; + default: //Become arrow element. + sd->bonus.arrow_ele=val; + break; + } + break; + case 1: + status->lhw.ele=val; + break; + default: + status->rhw.ele=val; + break; + } + break; + case SP_DEFELE: + if(val >= ELE_MAX) { + ShowError("pc_bonus: SP_DEFELE: Invalid element %d\n", val); + break; + } + if(sd->state.lr_flag != 2) + status->def_ele=val; + break; + case SP_MAXHP: + if(sd->state.lr_flag == 2) + break; + val += (int)status->max_hp; + //Negative bonuses will underflow, this will be handled in status_calc_pc through casting + //If this is called outside of status_calc_pc, you'd better pray they do not underflow and end with UINT_MAX max_hp. + status->max_hp = (unsigned int)val; + break; + case SP_MAXSP: + if(sd->state.lr_flag == 2) + break; + val += (int)status->max_sp; + status->max_sp = (unsigned int)val; + break; + case SP_CASTRATE: + if(sd->state.lr_flag != 2) + sd->castrate+=val; + break; + case SP_MAXHPRATE: + if(sd->state.lr_flag != 2) + sd->hprate+=val; + break; + case SP_MAXSPRATE: + if(sd->state.lr_flag != 2) + sd->sprate+=val; + break; + case SP_SPRATE: + if(sd->state.lr_flag != 2) + sd->dsprate+=val; + break; + case SP_ATTACKRANGE: + switch (sd->state.lr_flag) { + case 2: + switch (sd->status.weapon) { + case W_BOW: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + status->rhw.range += val; + } + break; + case 1: + status->lhw.range += val; + break; + default: + status->rhw.range += val; + break; + } + break; + case SP_SPEED_RATE: //Non stackable increase + if(sd->state.lr_flag != 2) + sd->bonus.speed_rate = min(sd->bonus.speed_rate, -val); + break; + case SP_SPEED_ADDRATE: //Stackable increase + if(sd->state.lr_flag != 2) + sd->bonus.speed_add_rate -= val; + break; + case SP_ASPD: //Raw increase + if(sd->state.lr_flag != 2) + sd->bonus.aspd_add -= 10*val; + break; + case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone + if(sd->state.lr_flag != 2) #ifndef RENEWAL_ASPD - status->aspd_rate -= 10*val; + status->aspd_rate -= 10*val; #else - status->aspd_rate2 += val; + status->aspd_rate2 += val; #endif - break; - case SP_HP_RECOV_RATE: - if (sd->state.lr_flag != 2) - sd->hprecov_rate += val; - break; - case SP_SP_RECOV_RATE: - if (sd->state.lr_flag != 2) - sd->sprecov_rate += val; - break; - case SP_CRITICAL_DEF: - if (sd->state.lr_flag != 2) - sd->bonus.critical_def += val; - break; - case SP_NEAR_ATK_DEF: - if (sd->state.lr_flag != 2) - sd->bonus.near_attack_def_rate += val; - break; - case SP_LONG_ATK_DEF: - if (sd->state.lr_flag != 2) - sd->bonus.long_attack_def_rate += val; - break; - case SP_DOUBLE_RATE: - if (sd->state.lr_flag == 0 && sd->bonus.double_rate < val) - sd->bonus.double_rate = val; - break; - case SP_DOUBLE_ADD_RATE: - if (sd->state.lr_flag == 0) - sd->bonus.double_add_rate += val; - break; - case SP_MATK_RATE: - if (sd->state.lr_flag != 2) - sd->matk_rate += val; - break; - case SP_IGNORE_DEF_ELE: - if (val >= ELE_MAX) { - ShowError("pc_bonus: SP_IGNORE_DEF_ELE: Invalid element %d\n", val); - break; - } - if (!sd->state.lr_flag) - sd->right_weapon.ignore_def_ele |= 1<<val; - else if (sd->state.lr_flag == 1) - sd->left_weapon.ignore_def_ele |= 1<<val; - break; - case SP_IGNORE_DEF_RACE: - if (!sd->state.lr_flag) - sd->right_weapon.ignore_def_race |= 1<<val; - else if (sd->state.lr_flag == 1) - sd->left_weapon.ignore_def_race |= 1<<val; - break; - case SP_ATK_RATE: - if (sd->state.lr_flag != 2) - sd->bonus.atk_rate += val; - break; - case SP_MAGIC_ATK_DEF: - if (sd->state.lr_flag != 2) - sd->bonus.magic_def_rate += val; - break; - case SP_MISC_ATK_DEF: - if (sd->state.lr_flag != 2) - sd->bonus.misc_def_rate += val; - break; - case SP_IGNORE_MDEF_RATE: - if (sd->state.lr_flag != 2) { - sd->ignore_mdef[RC_NONBOSS] += val; - sd->ignore_mdef[RC_BOSS] += val; - } - break; - case SP_IGNORE_MDEF_ELE: - if (val >= ELE_MAX) { - ShowError("pc_bonus: SP_IGNORE_MDEF_ELE: Invalid element %d\n", val); - break; - } - if (sd->state.lr_flag != 2) - sd->bonus.ignore_mdef_ele |= 1<<val; - break; - case SP_IGNORE_MDEF_RACE: - if (sd->state.lr_flag != 2) - sd->bonus.ignore_mdef_race |= 1<<val; - break; - case SP_PERFECT_HIT_RATE: - if (sd->state.lr_flag != 2 && sd->bonus.perfect_hit < val) - sd->bonus.perfect_hit = val; - break; - case SP_PERFECT_HIT_ADD_RATE: - if (sd->state.lr_flag != 2) - sd->bonus.perfect_hit_add += val; - break; - case SP_CRITICAL_RATE: - if (sd->state.lr_flag != 2) - sd->critical_rate+=val; - break; - case SP_DEF_RATIO_ATK_ELE: - if (val >= ELE_MAX) { - ShowError("pc_bonus: SP_DEF_RATIO_ATK_ELE: Invalid element %d\n", val); - break; - } - if (!sd->state.lr_flag) - sd->right_weapon.def_ratio_atk_ele |= 1<<val; - else if (sd->state.lr_flag == 1) - sd->left_weapon.def_ratio_atk_ele |= 1<<val; - break; - case SP_DEF_RATIO_ATK_RACE: - if (val >= RC_MAX) { - ShowError("pc_bonus: SP_DEF_RATIO_ATK_RACE: Invalid race %d\n", val); - break; - } - if (!sd->state.lr_flag) - sd->right_weapon.def_ratio_atk_race |= 1<<val; - else if (sd->state.lr_flag == 1) - sd->left_weapon.def_ratio_atk_race |= 1<<val; - break; - case SP_HIT_RATE: - if (sd->state.lr_flag != 2) - sd->hit_rate += val; - break; - case SP_FLEE_RATE: - if (sd->state.lr_flag != 2) - sd->flee_rate += val; - break; - case SP_FLEE2_RATE: - if (sd->state.lr_flag != 2) - sd->flee2_rate += val; - break; - case SP_DEF_RATE: - if (sd->state.lr_flag != 2) - sd->def_rate += val; - break; - case SP_DEF2_RATE: - if (sd->state.lr_flag != 2) - sd->def2_rate += val; - break; - case SP_MDEF_RATE: - if (sd->state.lr_flag != 2) - sd->mdef_rate += val; - break; - case SP_MDEF2_RATE: - if (sd->state.lr_flag != 2) - sd->mdef2_rate += val; - break; - case SP_RESTART_FULL_RECOVER: - if (sd->state.lr_flag != 2) - sd->special_state.restart_full_recover = 1; - break; - case SP_NO_CASTCANCEL: - if (sd->state.lr_flag != 2) - sd->special_state.no_castcancel = 1; - break; - case SP_NO_CASTCANCEL2: - if (sd->state.lr_flag != 2) - sd->special_state.no_castcancel2 = 1; - break; - case SP_NO_SIZEFIX: - if (sd->state.lr_flag != 2) - sd->special_state.no_sizefix = 1; - break; - case SP_NO_MAGIC_DAMAGE: - if (sd->state.lr_flag == 2) - break; - val+= sd->special_state.no_magic_damage; - sd->special_state.no_magic_damage = cap_value(val,0,100); - break; - case SP_NO_WEAPON_DAMAGE: - if (sd->state.lr_flag == 2) - break; - val+= sd->special_state.no_weapon_damage; - sd->special_state.no_weapon_damage = cap_value(val,0,100); - break; - case SP_NO_MISC_DAMAGE: - if (sd->state.lr_flag == 2) - break; - val+= sd->special_state.no_misc_damage; - sd->special_state.no_misc_damage = cap_value(val,0,100); - break; - case SP_NO_GEMSTONE: - if (sd->state.lr_flag != 2) - sd->special_state.no_gemstone = 1; - break; - case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG] - if (sd->state.lr_flag != 2) { - sd->special_state.intravision = 1; - clif_status_load(&sd->bl, SI_INTRAVISION, 1); - } - break; - case SP_NO_KNOCKBACK: - if (sd->state.lr_flag != 2) - sd->special_state.no_knockback = 1; - break; - case SP_SPLASH_RANGE: - if (sd->bonus.splash_range < val) - sd->bonus.splash_range = val; - break; - case SP_SPLASH_ADD_RANGE: - sd->bonus.splash_add_range += val; - break; - case SP_SHORT_WEAPON_DAMAGE_RETURN: - if (sd->state.lr_flag != 2) - sd->bonus.short_weapon_damage_return += val; - break; - case SP_LONG_WEAPON_DAMAGE_RETURN: - if (sd->state.lr_flag != 2) - sd->bonus.long_weapon_damage_return += val; - break; - case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here - if (sd->state.lr_flag != 2) - sd->bonus.magic_damage_return += val; - break; - case SP_ALL_STATS: // [Valaris] - if (sd->state.lr_flag!=2) { - sd->param_bonus[SP_STR-SP_STR]+=val; - sd->param_bonus[SP_AGI-SP_STR]+=val; - sd->param_bonus[SP_VIT-SP_STR]+=val; - sd->param_bonus[SP_INT-SP_STR]+=val; - sd->param_bonus[SP_DEX-SP_STR]+=val; - sd->param_bonus[SP_LUK-SP_STR]+=val; - } - break; - case SP_AGI_VIT: // [Valaris] - if (sd->state.lr_flag!=2) { - sd->param_bonus[SP_AGI-SP_STR]+=val; - sd->param_bonus[SP_VIT-SP_STR]+=val; - } - break; - case SP_AGI_DEX_STR: // [Valaris] - if (sd->state.lr_flag!=2) { - sd->param_bonus[SP_AGI-SP_STR]+=val; - sd->param_bonus[SP_DEX-SP_STR]+=val; - sd->param_bonus[SP_STR-SP_STR]+=val; - } - break; - case SP_PERFECT_HIDE: // [Valaris] - if (sd->state.lr_flag!=2) - sd->special_state.perfect_hiding=1; - break; - case SP_UNBREAKABLE: - if (sd->state.lr_flag!=2) - sd->bonus.unbreakable += val; - break; - case SP_UNBREAKABLE_WEAPON: - if (sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_WEAPON; - break; - case SP_UNBREAKABLE_ARMOR: - if (sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_ARMOR; - break; - case SP_UNBREAKABLE_HELM: - if (sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_HELM; - break; - case SP_UNBREAKABLE_SHIELD: - if (sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_SHIELD; - break; - case SP_UNBREAKABLE_GARMENT: - if (sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_GARMENT; - break; - case SP_UNBREAKABLE_SHOES: - if (sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_SHOES; - break; - case SP_CLASSCHANGE: // [Valaris] - if (sd->state.lr_flag !=2) - sd->bonus.classchange=val; - break; - case SP_LONG_ATK_RATE: - if (sd->state.lr_flag != 2) //[Lupus] it should stack, too. As any other cards rate bonuses - sd->bonus.long_attack_atk_rate+=val; - break; - case SP_BREAK_WEAPON_RATE: - if (sd->state.lr_flag != 2) - sd->bonus.break_weapon_rate+=val; - break; - case SP_BREAK_ARMOR_RATE: - if (sd->state.lr_flag != 2) - sd->bonus.break_armor_rate+=val; - break; - case SP_ADD_STEAL_RATE: - if (sd->state.lr_flag != 2) - sd->bonus.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->bonus.crit_atk_rate += val; - break; - case SP_NO_REGEN: - if (sd->state.lr_flag != 2) - sd->regen.state.block|=val; - break; - case SP_UNSTRIPABLE_WEAPON: - if (sd->state.lr_flag != 2) - sd->bonus.unstripable_equip |= EQP_WEAPON; - break; - case SP_UNSTRIPABLE: - case SP_UNSTRIPABLE_ARMOR: - if (sd->state.lr_flag != 2) - sd->bonus.unstripable_equip |= EQP_ARMOR; - break; - case SP_UNSTRIPABLE_HELM: - if (sd->state.lr_flag != 2) - sd->bonus.unstripable_equip |= EQP_HELM; - break; - case SP_UNSTRIPABLE_SHIELD: - if (sd->state.lr_flag != 2) - sd->bonus.unstripable_equip |= EQP_SHIELD; - break; - case SP_HP_DRAIN_VALUE: - if (!sd->state.lr_flag) { - sd->right_weapon.hp_drain[RC_NONBOSS].value += val; - sd->right_weapon.hp_drain[RC_BOSS].value += val; - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.hp_drain[RC_NONBOSS].value += val; - sd->left_weapon.hp_drain[RC_BOSS].value += val; - } - break; - case SP_SP_DRAIN_VALUE: - if (!sd->state.lr_flag) { - sd->right_weapon.sp_drain[RC_NONBOSS].value += val; - sd->right_weapon.sp_drain[RC_BOSS].value += val; - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[RC_NONBOSS].value += val; - sd->left_weapon.sp_drain[RC_BOSS].value += val; - } - break; - case SP_SP_GAIN_VALUE: - if (!sd->state.lr_flag) - sd->bonus.sp_gain_value += val; - break; - case SP_HP_GAIN_VALUE: - if (!sd->state.lr_flag) - sd->bonus.hp_gain_value += val; - break; - case SP_MAGIC_SP_GAIN_VALUE: - if (!sd->state.lr_flag) - sd->bonus.magic_sp_gain_value += val; - break; - case SP_MAGIC_HP_GAIN_VALUE: - if (!sd->state.lr_flag) - sd->bonus.magic_hp_gain_value += val; - break; - case SP_ADD_HEAL_RATE: - if (sd->state.lr_flag != 2) - sd->bonus.add_heal_rate += val; - break; - case SP_ADD_HEAL2_RATE: - if (sd->state.lr_flag != 2) - sd->bonus.add_heal2_rate += val; - break; - case SP_ADD_ITEM_HEAL_RATE: - if (sd->state.lr_flag != 2) - sd->bonus.itemhealrate2 += val; - break; - case SP_EMATK: - if(sd->state.lr_flag != 2) - sd->bonus.ematk += val; - break; - case SP_FIXCASTRATE: - if (sd->state.lr_flag != 2) - sd->bonus.fixcastrate -= val; - break; - case SP_VARCASTRATE: - if (sd->state.lr_flag != 2) - sd->bonus.varcastrate -= val; - break; - default: - ShowWarning("pc_bonus: unknown type %d %d !\n",type,val); - break; - } - return 0; + break; + case SP_HP_RECOV_RATE: + if(sd->state.lr_flag != 2) + sd->hprecov_rate += val; + break; + case SP_SP_RECOV_RATE: + if(sd->state.lr_flag != 2) + sd->sprecov_rate += val; + break; + case SP_CRITICAL_DEF: + if(sd->state.lr_flag != 2) + sd->bonus.critical_def += val; + break; + case SP_NEAR_ATK_DEF: + if(sd->state.lr_flag != 2) + sd->bonus.near_attack_def_rate += val; + break; + case SP_LONG_ATK_DEF: + if(sd->state.lr_flag != 2) + sd->bonus.long_attack_def_rate += val; + break; + case SP_DOUBLE_RATE: + if(sd->state.lr_flag == 0 && sd->bonus.double_rate < val) + sd->bonus.double_rate = val; + break; + case SP_DOUBLE_ADD_RATE: + if(sd->state.lr_flag == 0) + sd->bonus.double_add_rate += val; + break; + case SP_MATK_RATE: + if(sd->state.lr_flag != 2) + sd->matk_rate += val; + break; + case SP_IGNORE_DEF_ELE: + if(val >= ELE_MAX) { + ShowError("pc_bonus: SP_IGNORE_DEF_ELE: Invalid element %d\n", val); + break; + } + if(!sd->state.lr_flag) + sd->right_weapon.ignore_def_ele |= 1<<val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.ignore_def_ele |= 1<<val; + break; + case SP_IGNORE_DEF_RACE: + if(!sd->state.lr_flag) + sd->right_weapon.ignore_def_race |= 1<<val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.ignore_def_race |= 1<<val; + break; + case SP_ATK_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.atk_rate += val; + break; + case SP_MAGIC_ATK_DEF: + if(sd->state.lr_flag != 2) + sd->bonus.magic_def_rate += val; + break; + case SP_MISC_ATK_DEF: + if(sd->state.lr_flag != 2) + sd->bonus.misc_def_rate += val; + break; + case SP_IGNORE_MDEF_RATE: + if(sd->state.lr_flag != 2) { + sd->ignore_mdef[RC_NONBOSS] += val; + sd->ignore_mdef[RC_BOSS] += val; + } + break; + case SP_IGNORE_MDEF_ELE: + if(val >= ELE_MAX) { + ShowError("pc_bonus: SP_IGNORE_MDEF_ELE: Invalid element %d\n", val); + break; + } + if(sd->state.lr_flag != 2) + sd->bonus.ignore_mdef_ele |= 1<<val; + break; + case SP_IGNORE_MDEF_RACE: + if(sd->state.lr_flag != 2) + sd->bonus.ignore_mdef_race |= 1<<val; + break; + case SP_PERFECT_HIT_RATE: + if(sd->state.lr_flag != 2 && sd->bonus.perfect_hit < val) + sd->bonus.perfect_hit = val; + break; + case SP_PERFECT_HIT_ADD_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.perfect_hit_add += val; + break; + case SP_CRITICAL_RATE: + if(sd->state.lr_flag != 2) + sd->critical_rate+=val; + break; + case SP_DEF_RATIO_ATK_ELE: + if(val >= ELE_MAX) { + ShowError("pc_bonus: SP_DEF_RATIO_ATK_ELE: Invalid element %d\n", val); + break; + } + if(!sd->state.lr_flag) + sd->right_weapon.def_ratio_atk_ele |= 1<<val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.def_ratio_atk_ele |= 1<<val; + break; + case SP_DEF_RATIO_ATK_RACE: + if(val >= RC_MAX) { + ShowError("pc_bonus: SP_DEF_RATIO_ATK_RACE: Invalid race %d\n", val); + break; + } + if(!sd->state.lr_flag) + sd->right_weapon.def_ratio_atk_race |= 1<<val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.def_ratio_atk_race |= 1<<val; + break; + case SP_HIT_RATE: + if(sd->state.lr_flag != 2) + sd->hit_rate += val; + break; + case SP_FLEE_RATE: + if(sd->state.lr_flag != 2) + sd->flee_rate += val; + break; + case SP_FLEE2_RATE: + if(sd->state.lr_flag != 2) + sd->flee2_rate += val; + break; + case SP_DEF_RATE: + if(sd->state.lr_flag != 2) + sd->def_rate += val; + break; + case SP_DEF2_RATE: + if(sd->state.lr_flag != 2) + sd->def2_rate += val; + break; + case SP_MDEF_RATE: + if(sd->state.lr_flag != 2) + sd->mdef_rate += val; + break; + case SP_MDEF2_RATE: + if(sd->state.lr_flag != 2) + sd->mdef2_rate += val; + break; + case SP_RESTART_FULL_RECOVER: + if(sd->state.lr_flag != 2) + sd->special_state.restart_full_recover = 1; + break; + case SP_NO_CASTCANCEL: + if(sd->state.lr_flag != 2) + sd->special_state.no_castcancel = 1; + break; + case SP_NO_CASTCANCEL2: + if(sd->state.lr_flag != 2) + sd->special_state.no_castcancel2 = 1; + break; + case SP_NO_SIZEFIX: + if(sd->state.lr_flag != 2) + sd->special_state.no_sizefix = 1; + break; + case SP_NO_MAGIC_DAMAGE: + if(sd->state.lr_flag == 2) + break; + val+= sd->special_state.no_magic_damage; + sd->special_state.no_magic_damage = cap_value(val,0,100); + break; + case SP_NO_WEAPON_DAMAGE: + if(sd->state.lr_flag == 2) + break; + val+= sd->special_state.no_weapon_damage; + sd->special_state.no_weapon_damage = cap_value(val,0,100); + break; + case SP_NO_MISC_DAMAGE: + if(sd->state.lr_flag == 2) + break; + val+= sd->special_state.no_misc_damage; + sd->special_state.no_misc_damage = cap_value(val,0,100); + break; + case SP_NO_GEMSTONE: + if(sd->state.lr_flag != 2) + sd->special_state.no_gemstone = 1; + break; + case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG] + if(sd->state.lr_flag != 2) { + sd->special_state.intravision = 1; + clif_status_load(&sd->bl, SI_INTRAVISION, 1); + } + break; + case SP_NO_KNOCKBACK: + if(sd->state.lr_flag != 2) + sd->special_state.no_knockback = 1; + break; + case SP_SPLASH_RANGE: + if(sd->bonus.splash_range < val) + sd->bonus.splash_range = val; + break; + case SP_SPLASH_ADD_RANGE: + sd->bonus.splash_add_range += val; + break; + case SP_SHORT_WEAPON_DAMAGE_RETURN: + if(sd->state.lr_flag != 2) + sd->bonus.short_weapon_damage_return += val; + break; + case SP_LONG_WEAPON_DAMAGE_RETURN: + if(sd->state.lr_flag != 2) + sd->bonus.long_weapon_damage_return += val; + break; + case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here + if(sd->state.lr_flag != 2) + sd->bonus.magic_damage_return += val; + break; + case SP_ALL_STATS: // [Valaris] + if(sd->state.lr_flag!=2) { + sd->param_bonus[SP_STR-SP_STR]+=val; + sd->param_bonus[SP_AGI-SP_STR]+=val; + sd->param_bonus[SP_VIT-SP_STR]+=val; + sd->param_bonus[SP_INT-SP_STR]+=val; + sd->param_bonus[SP_DEX-SP_STR]+=val; + sd->param_bonus[SP_LUK-SP_STR]+=val; + } + break; + case SP_AGI_VIT: // [Valaris] + if(sd->state.lr_flag!=2) { + sd->param_bonus[SP_AGI-SP_STR]+=val; + sd->param_bonus[SP_VIT-SP_STR]+=val; + } + break; + case SP_AGI_DEX_STR: // [Valaris] + if(sd->state.lr_flag!=2) { + sd->param_bonus[SP_AGI-SP_STR]+=val; + sd->param_bonus[SP_DEX-SP_STR]+=val; + sd->param_bonus[SP_STR-SP_STR]+=val; + } + break; + case SP_PERFECT_HIDE: // [Valaris] + if(sd->state.lr_flag!=2) + sd->special_state.perfect_hiding=1; + break; + case SP_UNBREAKABLE: + if(sd->state.lr_flag!=2) + sd->bonus.unbreakable += val; + break; + case SP_UNBREAKABLE_WEAPON: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_WEAPON; + break; + case SP_UNBREAKABLE_ARMOR: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_ARMOR; + break; + case SP_UNBREAKABLE_HELM: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_HELM; + break; + case SP_UNBREAKABLE_SHIELD: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_SHIELD; + break; + case SP_UNBREAKABLE_GARMENT: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_GARMENT; + break; + case SP_UNBREAKABLE_SHOES: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_SHOES; + break; + case SP_CLASSCHANGE: // [Valaris] + if(sd->state.lr_flag !=2) + sd->bonus.classchange=val; + break; + case SP_LONG_ATK_RATE: + if(sd->state.lr_flag != 2) //[Lupus] it should stack, too. As any other cards rate bonuses + sd->bonus.long_attack_atk_rate+=val; + break; + case SP_BREAK_WEAPON_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.break_weapon_rate+=val; + break; + case SP_BREAK_ARMOR_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.break_armor_rate+=val; + break; + case SP_ADD_STEAL_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.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->bonus.crit_atk_rate += val; + break; + case SP_NO_REGEN: + if(sd->state.lr_flag != 2) + sd->regen.state.block|=val; + break; + case SP_UNSTRIPABLE_WEAPON: + if(sd->state.lr_flag != 2) + sd->bonus.unstripable_equip |= EQP_WEAPON; + break; + case SP_UNSTRIPABLE: + case SP_UNSTRIPABLE_ARMOR: + if(sd->state.lr_flag != 2) + sd->bonus.unstripable_equip |= EQP_ARMOR; + break; + case SP_UNSTRIPABLE_HELM: + if(sd->state.lr_flag != 2) + sd->bonus.unstripable_equip |= EQP_HELM; + break; + case SP_UNSTRIPABLE_SHIELD: + if(sd->state.lr_flag != 2) + sd->bonus.unstripable_equip |= EQP_SHIELD; + break; + case SP_HP_DRAIN_VALUE: + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[RC_NONBOSS].value += val; + sd->right_weapon.hp_drain[RC_BOSS].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[RC_NONBOSS].value += val; + sd->left_weapon.hp_drain[RC_BOSS].value += val; + } + break; + case SP_SP_DRAIN_VALUE: + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[RC_NONBOSS].value += val; + sd->right_weapon.sp_drain[RC_BOSS].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[RC_NONBOSS].value += val; + sd->left_weapon.sp_drain[RC_BOSS].value += val; + } + break; + case SP_SP_GAIN_VALUE: + if(!sd->state.lr_flag) + sd->bonus.sp_gain_value += val; + break; + case SP_HP_GAIN_VALUE: + if(!sd->state.lr_flag) + sd->bonus.hp_gain_value += val; + break; + case SP_MAGIC_SP_GAIN_VALUE: + if(!sd->state.lr_flag) + sd->bonus.magic_sp_gain_value += val; + break; + case SP_MAGIC_HP_GAIN_VALUE: + if(!sd->state.lr_flag) + sd->bonus.magic_hp_gain_value += val; + break; + case SP_ADD_HEAL_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.add_heal_rate += val; + break; + case SP_ADD_HEAL2_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.add_heal2_rate += val; + break; + case SP_ADD_ITEM_HEAL_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.itemhealrate2 += val; + break; + case SP_WEAPON_MATK: + if(sd->state.lr_flag != 2) + sd->bonus.sp_weapon_matk += val; + break; + case SP_BASE_MATK: + if(sd->state.lr_flag != 2) + sd->bonus.sp_base_matk += val; + break; + case SP_FIXCASTRATE: + if(sd->state.lr_flag != 2) + sd->bonus.fixcastrate -= val; + break; + case SP_VARCASTRATE: + if(sd->state.lr_flag != 2) + sd->bonus.varcastrate -= val; + break; + default: + ShowWarning("pc_bonus: unknown type %d %d !\n",type,val); + break; + } + return 0; } /*========================================== @@ -2557,855 +2617,879 @@ int pc_bonus(struct map_session_data *sd,int type,int val) *------------------------------------------*/ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) { - int i; - - nullpo_ret(sd); - - switch (type) { - case SP_ADDELE: - if (type2 >= ELE_MAX) { - ShowError("pc_bonus2: SP_ADDELE: Invalid element %d\n", type2); - break; - } - if (!sd->state.lr_flag) - sd->right_weapon.addele[type2]+=val; - else if (sd->state.lr_flag == 1) - sd->left_weapon.addele[type2]+=val; - else if (sd->state.lr_flag == 2) - sd->arrow_addele[type2]+=val; - break; - case SP_ADDRACE: - if (!sd->state.lr_flag) - sd->right_weapon.addrace[type2]+=val; - else if (sd->state.lr_flag == 1) - sd->left_weapon.addrace[type2]+=val; - else if (sd->state.lr_flag == 2) - sd->arrow_addrace[type2]+=val; - break; - case SP_ADDSIZE: - if (!sd->state.lr_flag) - sd->right_weapon.addsize[type2]+=val; - else if (sd->state.lr_flag == 1) - sd->left_weapon.addsize[type2]+=val; - else if (sd->state.lr_flag == 2) - sd->arrow_addsize[type2]+=val; - break; - case SP_SUBELE: - if (type2 >= ELE_MAX) { - ShowError("pc_bonus2: SP_SUBELE: Invalid element %d\n", type2); - break; - } - if (sd->state.lr_flag != 2) - sd->subele[type2]+=val; - break; - case SP_SUBRACE: - if (sd->state.lr_flag != 2) - sd->subrace[type2]+=val; - break; - case SP_ADDEFF: - if (type2 > SC_MAX) { - ShowWarning("pc_bonus2 (Add Effect): %d is not supported.\n", type2); - break; - } - pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, 0); - break; - case SP_ADDEFF2: - if (type2 > SC_MAX) { - ShowWarning("pc_bonus2 (Add Effect2): %d is not supported.\n", type2); - break; - } - pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, ATF_SELF); - break; - case SP_RESEFF: - if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) { - ShowWarning("pc_bonus2 (Resist Effect): %d is not supported.\n", type2); - break; - } - if (sd->state.lr_flag == 2) - break; - i = sd->reseff[type2-SC_COMMON_MIN]+val; - sd->reseff[type2-SC_COMMON_MIN]= cap_value(i, 0, 10000); - break; - case SP_MAGIC_ADDELE: - if (type2 >= ELE_MAX) { - ShowError("pc_bonus2: SP_MAGIC_ADDELE: Invalid element %d\n", type2); - break; - } - if (sd->state.lr_flag != 2) - sd->magic_addele[type2]+=val; - break; - case SP_MAGIC_ADDRACE: - if (sd->state.lr_flag != 2) - sd->magic_addrace[type2]+=val; - break; - case SP_MAGIC_ADDSIZE: - if (sd->state.lr_flag != 2) - sd->magic_addsize[type2]+=val; - break; - case SP_ADD_DAMAGE_CLASS: - switch (sd->state.lr_flag) { - case 0: //Right hand - ARR_FIND(0, ARRAYLENGTH(sd->right_weapon.add_dmg), i, sd->right_weapon.add_dmg[i].rate == 0 || sd->right_weapon.add_dmg[i].class_ == type2); - if (i == ARRAYLENGTH(sd->right_weapon.add_dmg)) { - ShowWarning("pc_bonus2: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->right_weapon.add_dmg)); - break; - } - sd->right_weapon.add_dmg[i].class_ = type2; - sd->right_weapon.add_dmg[i].rate += val; - if (!sd->right_weapon.add_dmg[i].rate) //Shift the rest of elements up. - memmove(&sd->right_weapon.add_dmg[i], &sd->right_weapon.add_dmg[i+1], sizeof(sd->right_weapon.add_dmg) - (i+1)*sizeof(sd->right_weapon.add_dmg[0])); - break; - case 1: //Left hand - ARR_FIND(0, ARRAYLENGTH(sd->left_weapon.add_dmg), i, sd->left_weapon.add_dmg[i].rate == 0 || sd->left_weapon.add_dmg[i].class_ == type2); - if (i == ARRAYLENGTH(sd->left_weapon.add_dmg)) { - ShowWarning("pc_bonus2: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->left_weapon.add_dmg)); - break; - } - sd->left_weapon.add_dmg[i].class_ = type2; - sd->left_weapon.add_dmg[i].rate += val; - if (!sd->left_weapon.add_dmg[i].rate) //Shift the rest of elements up. - memmove(&sd->left_weapon.add_dmg[i], &sd->left_weapon.add_dmg[i+1], sizeof(sd->left_weapon.add_dmg) - (i+1)*sizeof(sd->left_weapon.add_dmg[0])); - break; - } - break; - case SP_ADD_MAGIC_DAMAGE_CLASS: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->add_mdmg), i, sd->add_mdmg[i].rate == 0 || sd->add_mdmg[i].class_ == type2); - if (i == ARRAYLENGTH(sd->add_mdmg)) { - ShowWarning("pc_bonus2: Reached max (%d) number of add Class magic dmg bonuses per character!\n", ARRAYLENGTH(sd->add_mdmg)); - break; - } - sd->add_mdmg[i].class_ = type2; - sd->add_mdmg[i].rate += val; - if (!sd->add_mdmg[i].rate) //Shift the rest of elements up. - memmove(&sd->add_mdmg[i], &sd->add_mdmg[i+1], sizeof(sd->add_mdmg) - (i+1)*sizeof(sd->add_mdmg[0])); - break; - case SP_ADD_DEF_CLASS: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->add_def), i, sd->add_def[i].rate == 0 || sd->add_def[i].class_ == type2); - if (i == ARRAYLENGTH(sd->add_def)) { - ShowWarning("pc_bonus2: Reached max (%d) number of add Class def bonuses per character!\n", ARRAYLENGTH(sd->add_def)); - break; - } - sd->add_def[i].class_ = type2; - sd->add_def[i].rate += val; - if (!sd->add_def[i].rate) //Shift the rest of elements up. - memmove(&sd->add_def[i], &sd->add_def[i+1], sizeof(sd->add_def) - (i+1)*sizeof(sd->add_def[0])); - break; - case SP_ADD_MDEF_CLASS: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->add_mdef), i, sd->add_mdef[i].rate == 0 || sd->add_mdef[i].class_ == type2); - if (i == ARRAYLENGTH(sd->add_mdef)) { - ShowWarning("pc_bonus2: Reached max (%d) number of add Class mdef bonuses per character!\n", ARRAYLENGTH(sd->add_mdef)); - break; - } - sd->add_mdef[i].class_ = type2; - sd->add_mdef[i].rate += val; - if (!sd->add_mdef[i].rate) //Shift the rest of elements up. - memmove(&sd->add_mdef[i], &sd->add_mdef[i+1], sizeof(sd->add_mdef) - (i+1)*sizeof(sd->add_mdef[0])); - break; - case SP_HP_DRAIN_RATE: - if (!sd->state.lr_flag) { - sd->right_weapon.hp_drain[RC_NONBOSS].rate += type2; - sd->right_weapon.hp_drain[RC_NONBOSS].per += val; - sd->right_weapon.hp_drain[RC_BOSS].rate += type2; - sd->right_weapon.hp_drain[RC_BOSS].per += val; - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.hp_drain[RC_NONBOSS].rate += type2; - sd->left_weapon.hp_drain[RC_NONBOSS].per += val; - sd->left_weapon.hp_drain[RC_BOSS].rate += type2; - sd->left_weapon.hp_drain[RC_BOSS].per += val; - } - break; - case SP_HP_DRAIN_VALUE: - if (!sd->state.lr_flag) { - sd->right_weapon.hp_drain[RC_NONBOSS].value += type2; - sd->right_weapon.hp_drain[RC_NONBOSS].type = val; - sd->right_weapon.hp_drain[RC_BOSS].value += type2; - sd->right_weapon.hp_drain[RC_BOSS].type = val; - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.hp_drain[RC_NONBOSS].value += type2; - sd->left_weapon.hp_drain[RC_NONBOSS].type = val; - sd->left_weapon.hp_drain[RC_BOSS].value += type2; - sd->left_weapon.hp_drain[RC_BOSS].type = val; - } - break; - case SP_SP_DRAIN_RATE: - if (!sd->state.lr_flag) { - sd->right_weapon.sp_drain[RC_NONBOSS].rate += type2; - sd->right_weapon.sp_drain[RC_NONBOSS].per += val; - sd->right_weapon.sp_drain[RC_BOSS].rate += type2; - sd->right_weapon.sp_drain[RC_BOSS].per += val; - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[RC_NONBOSS].rate += type2; - sd->left_weapon.sp_drain[RC_NONBOSS].per += val; - sd->left_weapon.sp_drain[RC_BOSS].rate += type2; - sd->left_weapon.sp_drain[RC_BOSS].per += val; - } - break; - case SP_SP_DRAIN_VALUE: - if (!sd->state.lr_flag) { - sd->right_weapon.sp_drain[RC_NONBOSS].value += type2; - sd->right_weapon.sp_drain[RC_NONBOSS].type = val; - sd->right_weapon.sp_drain[RC_BOSS].value += type2; - sd->right_weapon.sp_drain[RC_BOSS].type = val; - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[RC_NONBOSS].value += type2; - sd->left_weapon.sp_drain[RC_NONBOSS].type = val; - sd->left_weapon.sp_drain[RC_BOSS].value += type2; - sd->left_weapon.sp_drain[RC_BOSS].type = val; - } - break; - case SP_SP_VANISH_RATE: - if (sd->state.lr_flag != 2) { - sd->bonus.sp_vanish_rate += type2; - sd->bonus.sp_vanish_per += val; - } - break; - case SP_GET_ZENY_NUM: - if (sd->state.lr_flag != 2 && sd->bonus.get_zeny_rate < val) { - sd->bonus.get_zeny_rate = val; - sd->bonus.get_zeny_num = type2; - } - break; - case SP_ADD_GET_ZENY_NUM: - if (sd->state.lr_flag != 2) { - sd->bonus.get_zeny_rate += val; - sd->bonus.get_zeny_num += type2; - } - break; - case SP_WEAPON_COMA_ELE: - if (type2 >= ELE_MAX) { - ShowError("pc_bonus2: SP_WEAPON_COMA_ELE: Invalid element %d\n", type2); - break; - } - if (sd->state.lr_flag == 2) - break; - sd->weapon_coma_ele[type2] += val; - sd->special_state.bonus_coma = 1; - break; - case SP_WEAPON_COMA_RACE: - if (sd->state.lr_flag == 2) - break; - sd->weapon_coma_race[type2] += val; - sd->special_state.bonus_coma = 1; - 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*10; - break; - case SP_ADDEFF_WHENHIT: - if (type2 > SC_MAX) { - ShowWarning("pc_bonus2 (Add Effect when hit): %d is not supported.\n", type2); - break; - } - if (sd->state.lr_flag != 2) - pc_bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, val, 0, 0); - break; - case SP_SKILL_ATK: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == 0 || sd->skillatk[i].id == type2); - if (i == ARRAYLENGTH(sd->skillatk)) { - //Better mention this so the array length can be updated. [Skotlex] - ShowDebug("run_script: bonus2 bSkillAtk reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillatk), type2, val); - break; - } - if (sd->skillatk[i].id == type2) - sd->skillatk[i].val += val; - else { - sd->skillatk[i].id = type2; - sd->skillatk[i].val = val; - } - break; - case SP_SKILL_HEAL: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == 0 || sd->skillheal[i].id == type2); - if (i == ARRAYLENGTH(sd->skillheal)) { - // Better mention this so the array length can be updated. [Skotlex] - ShowDebug("run_script: bonus2 bSkillHeal reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal), type2, val); - break; - } - if (sd->skillheal[i].id == type2) - sd->skillheal[i].val += val; - else { - sd->skillheal[i].id = type2; - sd->skillheal[i].val = val; - } - break; - case SP_SKILL_HEAL2: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == 0 || sd->skillheal2[i].id == type2); - if (i == ARRAYLENGTH(sd->skillheal2)) { - // Better mention this so the array length can be updated. [Skotlex] - ShowDebug("run_script: bonus2 bSkillHeal2 reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal2), type2, val); - break; - } - if (sd->skillheal2[i].id == type2) - sd->skillheal2[i].val += val; - else { - sd->skillheal2[i].id = type2; - sd->skillheal2[i].val = val; - } - break; - case SP_ADD_SKILL_BLOW: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillblown), i, sd->skillblown[i].id == 0 || sd->skillblown[i].id == type2); - if (i == ARRAYLENGTH(sd->skillblown)) { - //Better mention this so the array length can be updated. [Skotlex] - ShowDebug("run_script: bonus2 bSkillBlown reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillblown), type2, val); - break; - } - if (sd->skillblown[i].id == type2) - sd->skillblown[i].val += val; - else { - sd->skillblown[i].id = type2; - sd->skillblown[i].val = val; - } - break; - - case SP_CASTRATE: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2); - if (i == ARRAYLENGTH(sd->skillcast)) { - //Better mention this so the array length can be updated. [Skotlex] - ShowDebug("run_script: bonus2 bCastRate reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillcast), type2, val); - break; - } - if (sd->skillcast[i].id == type2) - sd->skillcast[i].val += val; - else { - sd->skillcast[i].id = type2; - sd->skillcast[i].val = val; - } - 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_HP_REGEN_RATE: - if (sd->state.lr_flag != 2) { - sd->hp_regen.value = type2; - sd->hp_regen.rate = val; - } - break; - case SP_ADDRACE2: - if (!(type2 > RC2_NONE && type2 < RC2_MAX)) - break; - if (sd->state.lr_flag != 2) - sd->right_weapon.addrace2[type2] += val; - else - sd->left_weapon.addrace2[type2] += val; - break; - case SP_SUBSIZE: - if (sd->state.lr_flag != 2) - sd->subsize[type2]+=val; - break; - case SP_SUBRACE2: - if (!(type2 > RC2_NONE && type2 < RC2_MAX)) - break; - if (sd->state.lr_flag != 2) - sd->subrace2[type2]+=val; - break; - case SP_ADD_ITEM_HEAL_RATE: - if (sd->state.lr_flag == 2) - break; - if (type2 < MAX_ITEMGROUP) { //Group bonus - sd->itemgrouphealrate[type2] += val; - break; - } - //Standard item bonus. - for (i=0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid && sd->itemhealrate[i].nameid != type2; i++); - if (i == ARRAYLENGTH(sd->itemhealrate)) { - ShowWarning("pc_bonus2: Reached max (%d) number of item heal bonuses per character!\n", ARRAYLENGTH(sd->itemhealrate)); - break; - } - sd->itemhealrate[i].nameid = type2; - sd->itemhealrate[i].rate += 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; - case SP_ADD_MONSTER_DROP_ITEM: - if (sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, (1<<RC_BOSS)|(1<<RC_NONBOSS), val); - break; - case SP_ADD_MONSTER_DROP_ITEMGROUP: - if (sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, (1<<RC_BOSS)|(1<<RC_NONBOSS), val); - break; - case SP_SP_LOSS_RATE: - if (sd->state.lr_flag != 2) { - sd->sp_loss.value = type2; - sd->sp_loss.rate = val; - } - break; - case SP_SP_REGEN_RATE: - if (sd->state.lr_flag != 2) { - sd->sp_regen.value = type2; - sd->sp_regen.rate = val; - } - break; - case SP_HP_DRAIN_VALUE_RACE: - if (!sd->state.lr_flag) { - sd->right_weapon.hp_drain[type2].value += val; - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.hp_drain[type2].value += val; - } - break; - case SP_SP_DRAIN_VALUE_RACE: - if (!sd->state.lr_flag) { - sd->right_weapon.sp_drain[type2].value += val; - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[type2].value += val; - } - break; - case SP_IGNORE_MDEF_RATE: - if (sd->state.lr_flag != 2) - sd->ignore_mdef[type2] += val; - break; - case SP_IGNORE_DEF_RATE: - if (sd->state.lr_flag != 2) - sd->ignore_def[type2] += val; - break; - case SP_SP_GAIN_RACE_ATTACK: - if (sd->state.lr_flag != 2) - sd->sp_gain_race_attack[type2] = cap_value(sd->sp_gain_race_attack[type2] + val, 0, INT16_MAX); - break; - case SP_HP_GAIN_RACE_ATTACK: - if (sd->state.lr_flag != 2) - sd->hp_gain_race_attack[type2] = cap_value(sd->hp_gain_race_attack[type2] + val, 0, INT16_MAX); - break; - case SP_SKILL_USE_SP_RATE: //bonus2 bSkillUseSPrate,n,x; - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillusesprate), i, sd->skillusesprate[i].id == 0 || sd->skillusesprate[i].id == type2); - if (i == ARRAYLENGTH(sd->skillusesprate)) { - ShowDebug("run_script: bonus2 bSkillUseSPrate reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesprate), type2, val); - break; - } - if (sd->skillusesprate[i].id == type2) - sd->skillusesprate[i].val += val; - else { - sd->skillusesprate[i].id = type2; - sd->skillusesprate[i].val = val; - } - break; - case SP_SKILL_COOLDOWN: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillcooldown), i, sd->skillcooldown[i].id == 0 || sd->skillcooldown[i].id == type2); - if (i == ARRAYLENGTH(sd->skillcooldown)) { - ShowDebug("run_script: bonus2 bSkillCoolDown reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillcooldown), type2, val); - break; - } - if (sd->skillcooldown[i].id == type2) - sd->skillcooldown[i].val += val; - else { - sd->skillcooldown[i].id = type2; - sd->skillcooldown[i].val = val; - } - break; - case SP_SKILL_FIXEDCAST: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillfixcast), i, sd->skillfixcast[i].id == 0 || sd->skillfixcast[i].id == type2); - if (i == ARRAYLENGTH(sd->skillfixcast)) { - ShowDebug("run_script: bonus2 bSkillFixedCast reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcast), type2, val); - break; - } - if (sd->skillfixcast[i].id == type2) - sd->skillfixcast[i].val += val; - else { - sd->skillfixcast[i].id = type2; - sd->skillfixcast[i].val = val; - } - break; - case SP_SKILL_VARIABLECAST: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillvarcast), i, sd->skillvarcast[i].id == 0 || sd->skillvarcast[i].id == type2); - if (i == ARRAYLENGTH(sd->skillvarcast)) { - ShowDebug("run_script: bonus2 bSkillVariableCast reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillvarcast), type2, val); - break; - } - if (sd->skillvarcast[i].id == type2) - sd->skillvarcast[i].val += val; - else { - sd->skillvarcast[i].id = type2; - sd->skillvarcast[i].val = val; - } - break; - case SP_VARCASTRATE: - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2); - if (i == ARRAYLENGTH(sd->skillcast)) { - ShowDebug("run_script: bonus2 bVariableCastrate reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n",ARRAYLENGTH(sd->skillcast), type2, val); - break; - } - if (sd->skillcast[i].id == type2) - sd->skillcast[i].val -= val; - else { - sd->skillcast[i].id = type2; - sd->skillcast[i].val -= val; - } - break; - case SP_SKILL_USE_SP: //bonus2 bSkillUseSP,n,x; - if (sd->state.lr_flag == 2) - break; - ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == 0 || sd->skillusesp[i].id == type2); - if (i == ARRAYLENGTH(sd->skillusesp)) { - ShowDebug("run_script: bonus2 bSkillUseSP reached its limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesp), type2, val); - break; - } - if (sd->skillusesp[i].id == type2) - sd->skillusesp[i].val += val; - else { - sd->skillusesp[i].id = type2; - sd->skillusesp[i].val = val; - } - break; - default: - ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val); - break; - } - return 0; + int i; + + nullpo_ret(sd); + + switch(type){ + case SP_ADDELE: + if(type2 >= ELE_MAX) { + ShowError("pc_bonus2: SP_ADDELE: Invalid element %d\n", type2); + break; + } + if(!sd->state.lr_flag) + sd->right_weapon.addele[type2]+=val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.addele[type2]+=val; + else if(sd->state.lr_flag == 2) + sd->arrow_addele[type2]+=val; + break; + case SP_ADDRACE: + if(!sd->state.lr_flag) + sd->right_weapon.addrace[type2]+=val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.addrace[type2]+=val; + else if(sd->state.lr_flag == 2) + sd->arrow_addrace[type2]+=val; + break; + case SP_ADDSIZE: + if(!sd->state.lr_flag) + sd->right_weapon.addsize[type2]+=val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.addsize[type2]+=val; + else if(sd->state.lr_flag == 2) + sd->arrow_addsize[type2]+=val; + break; + case SP_SUBELE: + if(type2 >= ELE_MAX) { + ShowError("pc_bonus2: SP_SUBELE: Invalid element %d\n", type2); + break; + } + if(sd->state.lr_flag != 2) + sd->subele[type2]+=val; + break; + case SP_SUBRACE: + if(sd->state.lr_flag != 2) + sd->subrace[type2]+=val; + break; + case SP_ADDEFF: + if (type2 > SC_MAX) { + ShowWarning("pc_bonus2 (Add Effect): %d is not supported.\n", type2); + break; + } + pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, + sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, 0); + break; + case SP_ADDEFF2: + if (type2 > SC_MAX) { + ShowWarning("pc_bonus2 (Add Effect2): %d is not supported.\n", type2); + break; + } + pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, + sd->state.lr_flag!=2?val:0, sd->state.lr_flag==2?val:0, ATF_SELF); + break; + case SP_RESEFF: + if (type2 < SC_COMMON_MIN || type2 > SC_COMMON_MAX) { + ShowWarning("pc_bonus2 (Resist Effect): %d is not supported.\n", type2); + break; + } + if(sd->state.lr_flag == 2) + break; + i = sd->reseff[type2-SC_COMMON_MIN]+val; + sd->reseff[type2-SC_COMMON_MIN]= cap_value(i, 0, 10000); + break; + case SP_MAGIC_ADDELE: + if(type2 >= ELE_MAX) { + ShowError("pc_bonus2: SP_MAGIC_ADDELE: Invalid element %d\n", type2); + break; + } + if(sd->state.lr_flag != 2) + sd->magic_addele[type2]+=val; + break; + case SP_MAGIC_ADDRACE: + if(sd->state.lr_flag != 2) + sd->magic_addrace[type2]+=val; + break; + case SP_MAGIC_ADDSIZE: + if(sd->state.lr_flag != 2) + sd->magic_addsize[type2]+=val; + break; + case SP_ADD_DAMAGE_CLASS: + switch (sd->state.lr_flag) { + case 0: //Right hand + ARR_FIND(0, ARRAYLENGTH(sd->right_weapon.add_dmg), i, sd->right_weapon.add_dmg[i].rate == 0 || sd->right_weapon.add_dmg[i].class_ == type2); + if (i == ARRAYLENGTH(sd->right_weapon.add_dmg)) + { + ShowWarning("pc_bonus2: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->right_weapon.add_dmg)); + break; + } + sd->right_weapon.add_dmg[i].class_ = type2; + sd->right_weapon.add_dmg[i].rate += val; + if (!sd->right_weapon.add_dmg[i].rate) //Shift the rest of elements up. + memmove(&sd->right_weapon.add_dmg[i], &sd->right_weapon.add_dmg[i+1], sizeof(sd->right_weapon.add_dmg) - (i+1)*sizeof(sd->right_weapon.add_dmg[0])); + break; + case 1: //Left hand + ARR_FIND(0, ARRAYLENGTH(sd->left_weapon.add_dmg), i, sd->left_weapon.add_dmg[i].rate == 0 || sd->left_weapon.add_dmg[i].class_ == type2); + if (i == ARRAYLENGTH(sd->left_weapon.add_dmg)) + { + ShowWarning("pc_bonus2: Reached max (%d) number of add Class dmg bonuses per character!\n", ARRAYLENGTH(sd->left_weapon.add_dmg)); + break; + } + sd->left_weapon.add_dmg[i].class_ = type2; + sd->left_weapon.add_dmg[i].rate += val; + if (!sd->left_weapon.add_dmg[i].rate) //Shift the rest of elements up. + memmove(&sd->left_weapon.add_dmg[i], &sd->left_weapon.add_dmg[i+1], sizeof(sd->left_weapon.add_dmg) - (i+1)*sizeof(sd->left_weapon.add_dmg[0])); + break; + } + break; + case SP_ADD_MAGIC_DAMAGE_CLASS: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->add_mdmg), i, sd->add_mdmg[i].rate == 0 || sd->add_mdmg[i].class_ == type2); + if (i == ARRAYLENGTH(sd->add_mdmg)) + { + ShowWarning("pc_bonus2: Reached max (%d) number of add Class magic dmg bonuses per character!\n", ARRAYLENGTH(sd->add_mdmg)); + break; + } + sd->add_mdmg[i].class_ = type2; + sd->add_mdmg[i].rate += val; + if (!sd->add_mdmg[i].rate) //Shift the rest of elements up. + memmove(&sd->add_mdmg[i], &sd->add_mdmg[i+1], sizeof(sd->add_mdmg) - (i+1)*sizeof(sd->add_mdmg[0])); + break; + case SP_ADD_DEF_CLASS: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->add_def), i, sd->add_def[i].rate == 0 || sd->add_def[i].class_ == type2); + if (i == ARRAYLENGTH(sd->add_def)) + { + ShowWarning("pc_bonus2: Reached max (%d) number of add Class def bonuses per character!\n", ARRAYLENGTH(sd->add_def)); + break; + } + sd->add_def[i].class_ = type2; + sd->add_def[i].rate += val; + if (!sd->add_def[i].rate) //Shift the rest of elements up. + memmove(&sd->add_def[i], &sd->add_def[i+1], sizeof(sd->add_def) - (i+1)*sizeof(sd->add_def[0])); + break; + case SP_ADD_MDEF_CLASS: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->add_mdef), i, sd->add_mdef[i].rate == 0 || sd->add_mdef[i].class_ == type2); + if (i == ARRAYLENGTH(sd->add_mdef)) + { + ShowWarning("pc_bonus2: Reached max (%d) number of add Class mdef bonuses per character!\n", ARRAYLENGTH(sd->add_mdef)); + break; + } + sd->add_mdef[i].class_ = type2; + sd->add_mdef[i].rate += val; + if (!sd->add_mdef[i].rate) //Shift the rest of elements up. + memmove(&sd->add_mdef[i], &sd->add_mdef[i+1], sizeof(sd->add_mdef) - (i+1)*sizeof(sd->add_mdef[0])); + break; + case SP_HP_DRAIN_RATE: + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[RC_NONBOSS].rate += type2; + sd->right_weapon.hp_drain[RC_NONBOSS].per += val; + sd->right_weapon.hp_drain[RC_BOSS].rate += type2; + sd->right_weapon.hp_drain[RC_BOSS].per += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[RC_NONBOSS].rate += type2; + sd->left_weapon.hp_drain[RC_NONBOSS].per += val; + sd->left_weapon.hp_drain[RC_BOSS].rate += type2; + sd->left_weapon.hp_drain[RC_BOSS].per += val; + } + break; + case SP_HP_DRAIN_VALUE: + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[RC_NONBOSS].value += type2; + sd->right_weapon.hp_drain[RC_NONBOSS].type = val; + sd->right_weapon.hp_drain[RC_BOSS].value += type2; + sd->right_weapon.hp_drain[RC_BOSS].type = val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[RC_NONBOSS].value += type2; + sd->left_weapon.hp_drain[RC_NONBOSS].type = val; + sd->left_weapon.hp_drain[RC_BOSS].value += type2; + sd->left_weapon.hp_drain[RC_BOSS].type = val; + } + break; + case SP_SP_DRAIN_RATE: + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[RC_NONBOSS].rate += type2; + sd->right_weapon.sp_drain[RC_NONBOSS].per += val; + sd->right_weapon.sp_drain[RC_BOSS].rate += type2; + sd->right_weapon.sp_drain[RC_BOSS].per += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[RC_NONBOSS].rate += type2; + sd->left_weapon.sp_drain[RC_NONBOSS].per += val; + sd->left_weapon.sp_drain[RC_BOSS].rate += type2; + sd->left_weapon.sp_drain[RC_BOSS].per += val; + } + break; + case SP_SP_DRAIN_VALUE: + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[RC_NONBOSS].value += type2; + sd->right_weapon.sp_drain[RC_NONBOSS].type = val; + sd->right_weapon.sp_drain[RC_BOSS].value += type2; + sd->right_weapon.sp_drain[RC_BOSS].type = val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[RC_NONBOSS].value += type2; + sd->left_weapon.sp_drain[RC_NONBOSS].type = val; + sd->left_weapon.sp_drain[RC_BOSS].value += type2; + sd->left_weapon.sp_drain[RC_BOSS].type = val; + } + break; + case SP_SP_VANISH_RATE: + if(sd->state.lr_flag != 2) { + sd->bonus.sp_vanish_rate += type2; + sd->bonus.sp_vanish_per += val; + } + break; + case SP_GET_ZENY_NUM: + if(sd->state.lr_flag != 2 && sd->bonus.get_zeny_rate < val) { + sd->bonus.get_zeny_rate = val; + sd->bonus.get_zeny_num = type2; + } + break; + case SP_ADD_GET_ZENY_NUM: + if(sd->state.lr_flag != 2) { + sd->bonus.get_zeny_rate += val; + sd->bonus.get_zeny_num += type2; + } + break; + case SP_WEAPON_COMA_ELE: + if(type2 >= ELE_MAX) { + ShowError("pc_bonus2: SP_WEAPON_COMA_ELE: Invalid element %d\n", type2); + break; + } + if(sd->state.lr_flag == 2) + break; + sd->weapon_coma_ele[type2] += val; + sd->special_state.bonus_coma = 1; + break; + case SP_WEAPON_COMA_RACE: + if(sd->state.lr_flag == 2) + break; + sd->weapon_coma_race[type2] += val; + sd->special_state.bonus_coma = 1; + 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*10; + break; + case SP_ADDEFF_WHENHIT: + if (type2 > SC_MAX) { + ShowWarning("pc_bonus2 (Add Effect when hit): %d is not supported.\n", type2); + break; + } + if(sd->state.lr_flag != 2) + pc_bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, val, 0, 0); + break; + case SP_SKILL_ATK: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == 0 || sd->skillatk[i].id == type2); + if (i == ARRAYLENGTH(sd->skillatk)) + { //Better mention this so the array length can be updated. [Skotlex] + ShowDebug("run_script: bonus2 bSkillAtk reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillatk), type2, val); + break; + } + if (sd->skillatk[i].id == type2) + sd->skillatk[i].val += val; + else { + sd->skillatk[i].id = type2; + sd->skillatk[i].val = val; + } + break; + case SP_SKILL_HEAL: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == 0 || sd->skillheal[i].id == type2); + if (i == ARRAYLENGTH(sd->skillheal)) + { // Better mention this so the array length can be updated. [Skotlex] + ShowDebug("run_script: bonus2 bSkillHeal reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal), type2, val); + break; + } + if (sd->skillheal[i].id == type2) + sd->skillheal[i].val += val; + else { + sd->skillheal[i].id = type2; + sd->skillheal[i].val = val; + } + break; + case SP_SKILL_HEAL2: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == 0 || sd->skillheal2[i].id == type2); + if (i == ARRAYLENGTH(sd->skillheal2)) + { // Better mention this so the array length can be updated. [Skotlex] + ShowDebug("run_script: bonus2 bSkillHeal2 reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillheal2), type2, val); + break; + } + if (sd->skillheal2[i].id == type2) + sd->skillheal2[i].val += val; + else { + sd->skillheal2[i].id = type2; + sd->skillheal2[i].val = val; + } + break; + case SP_ADD_SKILL_BLOW: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillblown), i, sd->skillblown[i].id == 0 || sd->skillblown[i].id == type2); + if (i == ARRAYLENGTH(sd->skillblown)) + { //Better mention this so the array length can be updated. [Skotlex] + ShowDebug("run_script: bonus2 bSkillBlown reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillblown), type2, val); + break; + } + if(sd->skillblown[i].id == type2) + sd->skillblown[i].val += val; + else { + sd->skillblown[i].id = type2; + sd->skillblown[i].val = val; + } + break; + + case SP_CASTRATE: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2); + if (i == ARRAYLENGTH(sd->skillcast)) + { //Better mention this so the array length can be updated. [Skotlex] + ShowDebug("run_script: bonus2 bCastRate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillcast), type2, val); + break; + } + if(sd->skillcast[i].id == type2) + sd->skillcast[i].val += val; + else { + sd->skillcast[i].id = type2; + sd->skillcast[i].val = val; + } + 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_HP_REGEN_RATE: + if(sd->state.lr_flag != 2) { + sd->hp_regen.value = type2; + sd->hp_regen.rate = val; + } + break; + case SP_ADDRACE2: + if (!(type2 > RC2_NONE && type2 < RC2_MAX)) + break; + if(sd->state.lr_flag != 2) + sd->right_weapon.addrace2[type2] += val; + else + sd->left_weapon.addrace2[type2] += val; + break; + case SP_SUBSIZE: + if(sd->state.lr_flag != 2) + sd->subsize[type2]+=val; + break; + case SP_SUBRACE2: + if (!(type2 > RC2_NONE && type2 < RC2_MAX)) + break; + if(sd->state.lr_flag != 2) + sd->subrace2[type2]+=val; + break; + case SP_ADD_ITEM_HEAL_RATE: + if(sd->state.lr_flag == 2) + break; + if (type2 < MAX_ITEMGROUP) { //Group bonus + sd->itemgrouphealrate[type2] += val; + break; + } + //Standard item bonus. + for(i=0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid && sd->itemhealrate[i].nameid != type2; i++); + if(i == ARRAYLENGTH(sd->itemhealrate)) { + ShowWarning("pc_bonus2: Reached max (%d) number of item heal bonuses per character!\n", ARRAYLENGTH(sd->itemhealrate)); + break; + } + sd->itemhealrate[i].nameid = type2; + sd->itemhealrate[i].rate += 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; + case SP_ADD_MONSTER_DROP_ITEM: + if (sd->state.lr_flag != 2) + pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, (1<<RC_BOSS)|(1<<RC_NONBOSS), val); + break; + case SP_ADD_MONSTER_DROP_ITEMGROUP: + if (sd->state.lr_flag != 2) + pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, (1<<RC_BOSS)|(1<<RC_NONBOSS), val); + break; + case SP_SP_LOSS_RATE: + if(sd->state.lr_flag != 2) { + sd->sp_loss.value = type2; + sd->sp_loss.rate = val; + } + break; + case SP_SP_REGEN_RATE: + if(sd->state.lr_flag != 2) { + sd->sp_regen.value = type2; + sd->sp_regen.rate = val; + } + break; + case SP_HP_DRAIN_VALUE_RACE: + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[type2].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[type2].value += val; + } + break; + case SP_SP_DRAIN_VALUE_RACE: + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[type2].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[type2].value += val; + } + break; + case SP_IGNORE_MDEF_RATE: + if(sd->state.lr_flag != 2) + sd->ignore_mdef[type2] += val; + break; + case SP_IGNORE_DEF_RATE: + if(sd->state.lr_flag != 2) + sd->ignore_def[type2] += val; + break; + case SP_SP_GAIN_RACE_ATTACK: + if(sd->state.lr_flag != 2) + sd->sp_gain_race_attack[type2] = cap_value(sd->sp_gain_race_attack[type2] + val, 0, INT16_MAX); + break; + case SP_HP_GAIN_RACE_ATTACK: + if(sd->state.lr_flag != 2) + sd->hp_gain_race_attack[type2] = cap_value(sd->hp_gain_race_attack[type2] + val, 0, INT16_MAX); + break; + case SP_SKILL_USE_SP_RATE: //bonus2 bSkillUseSPrate,n,x; + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillusesprate), i, sd->skillusesprate[i].id == 0 || sd->skillusesprate[i].id == type2); + if (i == ARRAYLENGTH(sd->skillusesprate)) { + ShowDebug("run_script: bonus2 bSkillUseSPrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesprate), type2, val); + break; + } + if (sd->skillusesprate[i].id == type2) + sd->skillusesprate[i].val += val; + else { + sd->skillusesprate[i].id = type2; + sd->skillusesprate[i].val = val; + } + break; + case SP_SKILL_COOLDOWN: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillcooldown), i, sd->skillcooldown[i].id == 0 || sd->skillcooldown[i].id == type2); + if (i == ARRAYLENGTH(sd->skillcooldown)) + { + ShowDebug("run_script: bonus2 bSkillCoolDown reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillcooldown), type2, val); + break; + } + if (sd->skillcooldown[i].id == type2) + sd->skillcooldown[i].val += val; + else { + sd->skillcooldown[i].id = type2; + sd->skillcooldown[i].val = val; + } + break; + case SP_SKILL_FIXEDCAST: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillfixcast), i, sd->skillfixcast[i].id == 0 || sd->skillfixcast[i].id == type2); + if (i == ARRAYLENGTH(sd->skillfixcast)) + { + ShowDebug("run_script: bonus2 bSkillFixedCast reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcast), type2, val); + break; + } + if (sd->skillfixcast[i].id == type2) + sd->skillfixcast[i].val += val; + else { + sd->skillfixcast[i].id = type2; + sd->skillfixcast[i].val = val; + } + break; + case SP_SKILL_VARIABLECAST: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillvarcast), i, sd->skillvarcast[i].id == 0 || sd->skillvarcast[i].id == type2); + if (i == ARRAYLENGTH(sd->skillvarcast)) + { + ShowDebug("run_script: bonus2 bSkillVariableCast reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillvarcast), type2, val); + break; + } + if (sd->skillvarcast[i].id == type2) + sd->skillvarcast[i].val += val; + else { + sd->skillvarcast[i].id = type2; + sd->skillvarcast[i].val = val; + } + break; + case SP_VARCASTRATE: + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2); + if (i == ARRAYLENGTH(sd->skillcast)) + { + ShowDebug("run_script: bonus2 bVariableCastrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n",ARRAYLENGTH(sd->skillcast), type2, val); + break; + } + if(sd->skillcast[i].id == type2) + sd->skillcast[i].val -= val; + else { + sd->skillcast[i].id = type2; + sd->skillcast[i].val -= val; + } + break; + case SP_SKILL_USE_SP: //bonus2 bSkillUseSP,n,x; + if(sd->state.lr_flag == 2) + break; + ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == 0 || sd->skillusesp[i].id == type2); + if (i == ARRAYLENGTH(sd->skillusesp)) { + ShowDebug("run_script: bonus2 bSkillUseSP reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesp), type2, val); + break; + } + if (sd->skillusesp[i].id == type2) + sd->skillusesp[i].val += val; + else { + sd->skillusesp[i].id = type2; + sd->skillusesp[i].val = val; + } + break; + default: + ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val); + break; + } + return 0; } int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) { - nullpo_ret(sd); - - switch (type) { - case SP_ADD_MONSTER_DROP_ITEM: - if (sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, 1<<type3, val); - break; - case SP_ADD_CLASS_DROP_ITEM: - if (sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, -type3, val); - break; - case SP_AUTOSPELL: - if (sd->state.lr_flag != 2) { - int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. - target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); - pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), - target?-type2:type2, type3, val, 0, current_equip_card_id); - } - break; - case SP_AUTOSPELL_WHENHIT: - if (sd->state.lr_flag != 2) { - int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. - target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); - pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), - target?-type2:type2, type3, val, BF_NORMAL|BF_SKILL, current_equip_card_id); - } - break; - case SP_SP_DRAIN_RATE: - if (!sd->state.lr_flag) { - sd->right_weapon.sp_drain[RC_NONBOSS].rate += type2; - sd->right_weapon.sp_drain[RC_NONBOSS].per += type3; - sd->right_weapon.sp_drain[RC_NONBOSS].type = val; - sd->right_weapon.sp_drain[RC_BOSS].rate += type2; - sd->right_weapon.sp_drain[RC_BOSS].per += type3; - sd->right_weapon.sp_drain[RC_BOSS].type = val; - - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[RC_NONBOSS].rate += type2; - sd->left_weapon.sp_drain[RC_NONBOSS].per += type3; - sd->left_weapon.sp_drain[RC_NONBOSS].type = val; - sd->left_weapon.sp_drain[RC_BOSS].rate += type2; - sd->left_weapon.sp_drain[RC_BOSS].per += type3; - sd->left_weapon.sp_drain[RC_BOSS].type = val; - } - break; - case SP_HP_DRAIN_RATE_RACE: - if (!sd->state.lr_flag) { - sd->right_weapon.hp_drain[type2].rate += type3; - sd->right_weapon.hp_drain[type2].per += val; - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.hp_drain[type2].rate += type3; - sd->left_weapon.hp_drain[type2].per += val; - } - break; - case SP_SP_DRAIN_RATE_RACE: - if (!sd->state.lr_flag) { - sd->right_weapon.sp_drain[type2].rate += type3; - sd->right_weapon.sp_drain[type2].per += val; - } else if (sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[type2].rate += type3; - sd->left_weapon.sp_drain[type2].per += val; - } - break; - case SP_ADD_MONSTER_DROP_ITEMGROUP: - if (sd->state.lr_flag != 2) - pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, 1<<type3, val); - break; - - case SP_ADDEFF: - if (type2 > SC_MAX) { - ShowWarning("pc_bonus3 (Add Effect): %d is not supported.\n", type2); - break; - } - pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, - sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, val); - break; - - case SP_ADDEFF_WHENHIT: - if (type2 > SC_MAX) { - ShowWarning("pc_bonus3 (Add Effect when hit): %d is not supported.\n", type2); - break; - } - if (sd->state.lr_flag != 2) - pc_bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, type3, 0, val); - break; - - case SP_ADDEFF_ONSKILL: - if (type3 > SC_MAX) { - ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type3); - break; - } - if (sd->state.lr_flag != 2) - pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, val, type2, ATF_TARGET); - break; - - case SP_ADDELE: - if (type2 > ELE_MAX) { - ShowWarning("pc_bonus3 (SP_ADDELE): element %d is out of range.\n", type2); - break; - } - if (sd->state.lr_flag != 2) - pc_bonus_addele(sd, (unsigned char)type2, type3, val); - break; - - case SP_SUBELE: - if (type2 > ELE_MAX) { - ShowWarning("pc_bonus3 (SP_SUBELE): element %d is out of range.\n", type2); - break; - } - if (sd->state.lr_flag != 2) - pc_bonus_subele(sd, (unsigned char)type2, type3, val); - break; - - default: - ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val); - break; - } - - return 0; + nullpo_ret(sd); + + switch(type){ + case SP_ADD_MONSTER_DROP_ITEM: + if(sd->state.lr_flag != 2) + pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, 1<<type3, val); + break; + case SP_ADD_CLASS_DROP_ITEM: + if(sd->state.lr_flag != 2) + pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), type2, 0, -type3, val); + break; + case SP_AUTOSPELL: + if(sd->state.lr_flag != 2) + { + int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. + target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); + pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), + target?-type2:type2, type3, val, 0, current_equip_card_id); + } + break; + case SP_AUTOSPELL_WHENHIT: + if(sd->state.lr_flag != 2) + { + int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. + target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); + pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), + target?-type2:type2, type3, val, BF_NORMAL|BF_SKILL, current_equip_card_id); + } + break; + case SP_SP_DRAIN_RATE: + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[RC_NONBOSS].rate += type2; + sd->right_weapon.sp_drain[RC_NONBOSS].per += type3; + sd->right_weapon.sp_drain[RC_NONBOSS].type = val; + sd->right_weapon.sp_drain[RC_BOSS].rate += type2; + sd->right_weapon.sp_drain[RC_BOSS].per += type3; + sd->right_weapon.sp_drain[RC_BOSS].type = val; + + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[RC_NONBOSS].rate += type2; + sd->left_weapon.sp_drain[RC_NONBOSS].per += type3; + sd->left_weapon.sp_drain[RC_NONBOSS].type = val; + sd->left_weapon.sp_drain[RC_BOSS].rate += type2; + sd->left_weapon.sp_drain[RC_BOSS].per += type3; + sd->left_weapon.sp_drain[RC_BOSS].type = val; + } + break; + case SP_HP_DRAIN_RATE_RACE: + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[type2].rate += type3; + sd->right_weapon.hp_drain[type2].per += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[type2].rate += type3; + sd->left_weapon.hp_drain[type2].per += val; + } + break; + case SP_SP_DRAIN_RATE_RACE: + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[type2].rate += type3; + sd->right_weapon.sp_drain[type2].per += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[type2].rate += type3; + sd->left_weapon.sp_drain[type2].per += val; + } + break; + case SP_ADD_MONSTER_DROP_ITEMGROUP: + if (sd->state.lr_flag != 2) + pc_bonus_item_drop(sd->add_drop, ARRAYLENGTH(sd->add_drop), 0, type2, 1<<type3, val); + break; + + case SP_ADDEFF: + if (type2 > SC_MAX) { + ShowWarning("pc_bonus3 (Add Effect): %d is not supported.\n", type2); + break; + } + pc_bonus_addeff(sd->addeff, ARRAYLENGTH(sd->addeff), (sc_type)type2, + sd->state.lr_flag!=2?type3:0, sd->state.lr_flag==2?type3:0, val); + break; + + case SP_ADDEFF_WHENHIT: + if (type2 > SC_MAX) { + ShowWarning("pc_bonus3 (Add Effect when hit): %d is not supported.\n", type2); + break; + } + if(sd->state.lr_flag != 2) + pc_bonus_addeff(sd->addeff2, ARRAYLENGTH(sd->addeff2), (sc_type)type2, type3, 0, val); + break; + + case SP_ADDEFF_ONSKILL: + if( type3 > SC_MAX ) { + ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type3); + break; + } + if( sd->state.lr_flag != 2 ) + pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, val, type2, ATF_TARGET); + break; + + case SP_ADDELE: + if (type2 > ELE_MAX) { + ShowWarning("pc_bonus3 (SP_ADDELE): element %d is out of range.\n", type2); + break; + } + if (sd->state.lr_flag != 2) + pc_bonus_addele(sd, (unsigned char)type2, type3, val); + break; + + case SP_SUBELE: + if (type2 > ELE_MAX) { + ShowWarning("pc_bonus3 (SP_SUBELE): element %d is out of range.\n", type2); + break; + } + if (sd->state.lr_flag != 2) + pc_bonus_subele(sd, (unsigned char)type2, type3, val); + break; + + default: + ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val); + break; + } + + return 0; } int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val) { - nullpo_ret(sd); + nullpo_ret(sd); - switch (type) { - case SP_AUTOSPELL: - if (sd->state.lr_flag != 2) - pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, 0, current_equip_card_id); - break; + switch(type){ + case SP_AUTOSPELL: + if(sd->state.lr_flag != 2) + pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, 0, current_equip_card_id); + break; - case SP_AUTOSPELL_WHENHIT: - if (sd->state.lr_flag != 2) - pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, BF_NORMAL|BF_SKILL, current_equip_card_id); - break; + case SP_AUTOSPELL_WHENHIT: + if(sd->state.lr_flag != 2) + pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, BF_NORMAL|BF_SKILL, current_equip_card_id); + break; - case SP_AUTOSPELL_ONSKILL: - if (sd->state.lr_flag != 2) { - int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. - target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); + case SP_AUTOSPELL_ONSKILL: + if(sd->state.lr_flag != 2) + { + int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. + target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); - pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, target?-type3:type3, type4, val, current_equip_card_id); - } - break; + pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, target?-type3:type3, type4, val, current_equip_card_id); + } + break; - case SP_ADDEFF_ONSKILL: - if (type2 > SC_MAX) { - ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type2); - break; - } - if (sd->state.lr_flag != 2) - pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, type4, type2, val); - break; + case SP_ADDEFF_ONSKILL: + if( type2 > SC_MAX ) { + ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type2); + break; + } + if( sd->state.lr_flag != 2 ) + pc_bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, type4, type2, val); + break; - default: - ShowWarning("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val); - break; - } + default: + ShowWarning("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val); + break; + } - return 0; + return 0; } int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4,int type5,int val) { - nullpo_ret(sd); + nullpo_ret(sd); - switch (type) { - case SP_AUTOSPELL: - if (sd->state.lr_flag != 2) - pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id); - break; + switch(type){ + case SP_AUTOSPELL: + if(sd->state.lr_flag != 2) + pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id); + break; - case SP_AUTOSPELL_WHENHIT: - if (sd->state.lr_flag != 2) - pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id); - break; + case SP_AUTOSPELL_WHENHIT: + if(sd->state.lr_flag != 2) + pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), (val&1?type2:-type2), (val&2?-type3:type3), type4, type5, current_equip_card_id); + break; - case SP_AUTOSPELL_ONSKILL: - if (sd->state.lr_flag != 2) - pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, (val&1?-type3:type3), (val&2?-type4:type4), type5, current_equip_card_id); - break; + case SP_AUTOSPELL_ONSKILL: + if(sd->state.lr_flag != 2) + pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, (val&1?-type3:type3), (val&2?-type4:type4), type5, current_equip_card_id); + break; - default: - ShowWarning("pc_bonus5: unknown type %d %d %d %d %d %d!\n",type,type2,type3,type4,type5,val); - break; - } + default: + ShowWarning("pc_bonus5: unknown type %d %d %d %d %d %d!\n",type,type2,type3,type4,type5,val); + break; + } - return 0; + return 0; } /*========================================== - * Grants a player a given skill. Flag values are: - * 0 - Grant skill unconditionally and forever (only this one invokes status_calc_pc, - * as the other two are assumed to be invoked from within it) - * 1 - Grant an item skill (temporary) - * 2 - Like 1, except the level granted can stack with previously learned level. + * Grants a player a given skill. Flag values are: + * 0 - Grant skill unconditionally and forever (only this one invokes status_calc_pc, + * as the other two are assumed to be invoked from within it) + * 1 - Grant an item skill (temporary) + * 2 - Like 1, except the level granted can stack with previously learned level. *------------------------------------------*/ -int pc_skill(TBL_PC *sd, int id, int level, int flag) -{ - nullpo_ret(sd); - - if (id <= 0 || id >= MAX_SKILL || skill_db[id].name == NULL) { - ShowError("pc_skill: Skill with id %d does not exist in the skill database\n", id); - return 0; - } - if (level > MAX_SKILL_LEVEL) { - ShowError("pc_skill: Skill level %d too high. Max lv supported is %d\n", level, MAX_SKILL_LEVEL); - return 0; - } - if (flag == 2 && sd->status.skill[id].lv + level > MAX_SKILL_LEVEL) { - ShowError("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d\n", level, MAX_SKILL_LEVEL, sd->status.skill[id].lv); - return 0; - } - - switch (flag) { - case 0: //Set skill data overwriting whatever was there before. - sd->status.skill[id].id = id; - sd->status.skill[id].lv = level; - sd->status.skill[id].flag = SKILL_FLAG_PERMANENT; - if (level == 0) { //Remove skill. - sd->status.skill[id].id = 0; - clif_deleteskill(sd,id); - } else - clif_addskill(sd,id); - if (!skill_get_inf(id)) //Only recalculate for passive skills. - status_calc_pc(sd, 0); - break; - case 1: //Item bonus skill. - if (sd->status.skill[id].id == id) { - if (sd->status.skill[id].lv >= level) - return 0; - if (sd->status.skill[id].flag == SKILL_FLAG_PERMANENT) //Non-granted skill, store it's level. - sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; - } else { - sd->status.skill[id].id = id; - sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; - } - sd->status.skill[id].lv = level; - break; - case 2: //Add skill bonus on top of what you had. - if (sd->status.skill[id].id == id) { - if (sd->status.skill[id].flag == SKILL_FLAG_PERMANENT) - sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level. - } else { - sd->status.skill[id].id = id; - sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill. - } - sd->status.skill[id].lv += level; - break; - default: //Unknown flag? - return 0; - } - return 1; +int pc_skill(TBL_PC* sd, int id, int level, int flag) +{ + nullpo_ret(sd); + + if( id <= 0 || id >= MAX_SKILL || skill_db[id].name == NULL) { + ShowError("pc_skill: Skill with id %d does not exist in the skill database\n", id); + return 0; + } + if( level > MAX_SKILL_LEVEL ) { + ShowError("pc_skill: Skill level %d too high. Max lv supported is %d\n", level, MAX_SKILL_LEVEL); + return 0; + } + if( flag == 2 && sd->status.skill[id].lv + level > MAX_SKILL_LEVEL ) { + ShowError("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d\n", level, MAX_SKILL_LEVEL, sd->status.skill[id].lv); + return 0; + } + + switch( flag ){ + case 0: //Set skill data overwriting whatever was there before. + sd->status.skill[id].id = id; + sd->status.skill[id].lv = level; + sd->status.skill[id].flag = SKILL_FLAG_PERMANENT; + if( level == 0 ) //Remove skill. + { + sd->status.skill[id].id = 0; + clif_deleteskill(sd,id); + } + else + clif_addskill(sd,id); + if( !skill_get_inf(id) ) //Only recalculate for passive skills. + status_calc_pc(sd, 0); + break; + case 1: //Item bonus skill. + if( sd->status.skill[id].id == id ){ + if( sd->status.skill[id].lv >= level ) + return 0; + if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level. + sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; + } else { + sd->status.skill[id].id = id; + sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; + } + sd->status.skill[id].lv = level; + break; + case 2: //Add skill bonus on top of what you had. + if( sd->status.skill[id].id == id ){ + if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) + sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level. + } else { + sd->status.skill[id].id = id; + sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill. + } + sd->status.skill[id].lv += level; + break; + default: //Unknown flag? + return 0; + } + return 1; } /*========================================== * Append a card to an item ? *------------------------------------------*/ -int pc_insert_card(struct map_session_data *sd, int idx_card, int idx_equip) -{ - int i; - int nameid; - - nullpo_ret(sd); - - if (idx_equip < 0 || idx_equip >= MAX_INVENTORY || sd->inventory_data[idx_equip] == NULL) - return 0; //Invalid item index. - if (idx_card < 0 || idx_card >= MAX_INVENTORY || sd->inventory_data[idx_card] == NULL) - return 0; //Invalid card index. - if (sd->status.inventory[idx_equip].nameid <= 0 || sd->status.inventory[idx_equip].amount < 1) - return 0; // target item missing - if (sd->status.inventory[idx_card].nameid <= 0 || sd->status.inventory[idx_card].amount < 1) - return 0; // target card missing - if (sd->inventory_data[idx_equip]->type != IT_WEAPON && sd->inventory_data[idx_equip]->type != IT_ARMOR) - return 0; // only weapons and armor are allowed - if (sd->inventory_data[idx_card]->type != IT_CARD) - return 0; // must be a card - if (sd->status.inventory[idx_equip].identify == 0) - return 0; // target must be identified - if (itemdb_isspecial(sd->status.inventory[idx_equip].card[0])) - return 0; // card slots reserved for other purposes - if ((sd->inventory_data[idx_equip]->equip & sd->inventory_data[idx_card]->equip) == 0) - return 0; // card cannot be compounded on this item type - if (sd->inventory_data[idx_equip]->type == IT_WEAPON && sd->inventory_data[idx_card]->equip == EQP_SHIELD) - return 0; // attempted to place shield card on left-hand weapon. - if (sd->status.inventory[idx_equip].equip != 0) - return 0; // item must be unequipped - - ARR_FIND(0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0); - if (i == sd->inventory_data[idx_equip]->slot) - return 0; // no free slots - - // remember the card id to insert - nameid = sd->status.inventory[idx_card].nameid; - - if (pc_delitem(sd,idx_card,1,1,0,LOG_TYPE_OTHER) == 1) { - // failed - clif_insert_card(sd,idx_equip,idx_card,1); - } else { - // success - log_pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->status.inventory[idx_equip]); - sd->status.inventory[idx_equip].card[i] = nameid; - log_pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip]); - clif_insert_card(sd,idx_equip,idx_card,0); - } - - return 0; +int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip) +{ + int i; + int nameid; + + nullpo_ret(sd); + + if( idx_equip < 0 || idx_equip >= MAX_INVENTORY || sd->inventory_data[idx_equip] == NULL ) + return 0; //Invalid item index. + if( idx_card < 0 || idx_card >= MAX_INVENTORY || sd->inventory_data[idx_card] == NULL ) + return 0; //Invalid card index. + if( sd->status.inventory[idx_equip].nameid <= 0 || sd->status.inventory[idx_equip].amount < 1 ) + return 0; // target item missing + if( sd->status.inventory[idx_card].nameid <= 0 || sd->status.inventory[idx_card].amount < 1 ) + return 0; // target card missing + if( sd->inventory_data[idx_equip]->type != IT_WEAPON && sd->inventory_data[idx_equip]->type != IT_ARMOR ) + return 0; // only weapons and armor are allowed + if( sd->inventory_data[idx_card]->type != IT_CARD ) + return 0; // must be a card + if( sd->status.inventory[idx_equip].identify == 0 ) + return 0; // target must be identified + if( itemdb_isspecial(sd->status.inventory[idx_equip].card[0]) ) + return 0; // card slots reserved for other purposes + if( (sd->inventory_data[idx_equip]->equip & sd->inventory_data[idx_card]->equip) == 0 ) + return 0; // card cannot be compounded on this item type + if( sd->inventory_data[idx_equip]->type == IT_WEAPON && sd->inventory_data[idx_card]->equip == EQP_SHIELD ) + return 0; // attempted to place shield card on left-hand weapon. + if( sd->status.inventory[idx_equip].equip != 0 ) + return 0; // item must be unequipped + + ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0 ); + if( i == sd->inventory_data[idx_equip]->slot ) + return 0; // no free slots + + // remember the card id to insert + nameid = sd->status.inventory[idx_card].nameid; + + if( pc_delitem(sd,idx_card,1,1,0,LOG_TYPE_OTHER) == 1 ) + {// failed + clif_insert_card(sd,idx_equip,idx_card,1); + } + else + {// success + log_pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->status.inventory[idx_equip]); + sd->status.inventory[idx_equip].card[i] = nameid; + log_pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip]); + clif_insert_card(sd,idx_equip,idx_card,0); + } + + return 0; } // @@ -3417,18 +3501,18 @@ int pc_insert_card(struct map_session_data *sd, int idx_card, int idx_equip) *------------------------------------------*/ int pc_modifybuyvalue(struct map_session_data *sd,int orig_value) { - int skill,val = orig_value,rate1 = 0,rate2 = 0; - if ((skill=pc_checkskill(sd,MC_DISCOUNT))>0) // merchant discount - rate1 = 5+skill*2-((skill==10)? 1:0); - if ((skill=pc_checkskill(sd,RG_COMPULSION))>0) // rogue discount - rate2 = 5+skill*4; - if (rate1 < rate2) rate1 = rate2; - if (rate1) - val = (int)((double)orig_value*(double)(100-rate1)/100.); - if (val < 0) val = 0; - if (orig_value > 0 && val < 1) val = 1; + int skill,val = orig_value,rate1 = 0,rate2 = 0; + if((skill=pc_checkskill(sd,MC_DISCOUNT))>0) // merchant discount + rate1 = 5+skill*2-((skill==10)? 1:0); + if((skill=pc_checkskill(sd,RG_COMPULSION))>0) // rogue discount + rate2 = 5+skill*4; + if(rate1 < rate2) rate1 = rate2; + if(rate1) + val = (int)((double)orig_value*(double)(100-rate1)/100.); + if(val < 0) val = 0; + if(orig_value > 0 && val < 1) val = 1; - return val; + return val; } /*========================================== @@ -3436,15 +3520,15 @@ int pc_modifybuyvalue(struct map_session_data *sd,int orig_value) *------------------------------------------*/ int pc_modifysellvalue(struct map_session_data *sd,int orig_value) { - int skill,val = orig_value,rate = 0; - if ((skill=pc_checkskill(sd,MC_OVERCHARGE))>0) //OverCharge - rate = 5+skill*2-((skill==10)? 1:0); - if (rate) - val = (int)((double)orig_value*(double)(100+rate)/100.); - if (val < 0) val = 0; - if (orig_value > 0 && val < 1) val = 1; + int skill,val = orig_value,rate = 0; + if((skill=pc_checkskill(sd,MC_OVERCHARGE))>0) //OverCharge + rate = 5+skill*2-((skill==10)? 1:0); + if(rate) + val = (int)((double)orig_value*(double)(100+rate)/100.); + if(val < 0) val = 0; + if(orig_value > 0 && val < 1) val = 1; - return val; + return val; } /*========================================== @@ -3453,32 +3537,32 @@ int pc_modifysellvalue(struct map_session_data *sd,int orig_value) *------------------------------------------*/ int pc_checkadditem(struct map_session_data *sd,int nameid,int amount) { - int i; - struct item_data *data; + int i; + struct item_data* data; - nullpo_ret(sd); + nullpo_ret(sd); - if (amount > MAX_AMOUNT) - return ADDITEM_OVERAMOUNT; + if(amount > MAX_AMOUNT) + return ADDITEM_OVERAMOUNT; - data = itemdb_search(nameid); + data = itemdb_search(nameid); - if (!itemdb_isstackable2(data)) - return ADDITEM_NEW; + if(!itemdb_isstackable2(data)) + return ADDITEM_NEW; - if (data->stack.inventory && amount > data->stack.amount) - return ADDITEM_OVERAMOUNT; + if( data->stack.inventory && amount > data->stack.amount ) + return ADDITEM_OVERAMOUNT; - for (i=0; i<MAX_INVENTORY; i++) { - // FIXME: This does not consider the checked item's cards, thus could check a wrong slot for stackability. - if (sd->status.inventory[i].nameid==nameid) { - if (amount > MAX_AMOUNT - sd->status.inventory[i].amount || (data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount)) - return ADDITEM_OVERAMOUNT; - return ADDITEM_EXIST; - } - } + for(i=0;i<MAX_INVENTORY;i++){ + // FIXME: This does not consider the checked item's cards, thus could check a wrong slot for stackability. + if(sd->status.inventory[i].nameid==nameid){ + if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) ) + return ADDITEM_OVERAMOUNT; + return ADDITEM_EXIST; + } + } - return ADDITEM_NEW; + return ADDITEM_NEW; } /*========================================== @@ -3487,16 +3571,16 @@ int pc_checkadditem(struct map_session_data *sd,int nameid,int amount) *------------------------------------------*/ int pc_inventoryblank(struct map_session_data *sd) { - int i,b; + int i,b; - nullpo_ret(sd); + nullpo_ret(sd); - for (i=0,b=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid==0) - b++; - } + for(i=0,b=0;i<MAX_INVENTORY;i++){ + if(sd->status.inventory[i].nameid==0) + b++; + } - return b; + return b; } /*========================================== @@ -3504,29 +3588,30 @@ int pc_inventoryblank(struct map_session_data *sd) *------------------------------------------*/ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd) { - nullpo_retr(-1,sd); + nullpo_retr(-1,sd); - zeny = cap_value(zeny,-MAX_ZENY,MAX_ZENY); //prevent command UB - if (zeny < 0) { - ShowError("pc_payzeny: Paying negative Zeny (zeny=%d, account_id=%d, char_id=%d).\n", zeny, sd->status.account_id, sd->status.char_id); - return 1; - } + zeny = cap_value(zeny,-MAX_ZENY,MAX_ZENY); //prevent command UB + if( zeny < 0 ) + { + ShowError("pc_payzeny: Paying negative Zeny (zeny=%d, account_id=%d, char_id=%d).\n", zeny, sd->status.account_id, sd->status.char_id); + return 1; + } - if (sd->status.zeny < zeny) - return 1; //Not enough. + if( sd->status.zeny < zeny ) + return 1; //Not enough. - sd->status.zeny -= zeny; - clif_updatestatus(sd,SP_ZENY); + sd->status.zeny -= zeny; + clif_updatestatus(sd,SP_ZENY); - if (!tsd) tsd = sd; - log_zeny(sd, type, tsd, -zeny); - if (zeny > 0 && sd->state.showzeny) { - char output[255]; - sprintf(output, "Removed %dz.", zeny); - clif_disp_onlyself(sd,output,strlen(output)); - } + if(!tsd) tsd = sd; + log_zeny(sd, type, tsd, -zeny); + if( zeny > 0 && sd->state.showzeny ) { + char output[255]; + sprintf(output, "Removed %dz.", zeny); + clif_disp_onlyself(sd,output,strlen(output)); + } - return 0; + return 0; } /*========================================== * Cash Shop @@ -3534,81 +3619,95 @@ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, int pc_paycash(struct map_session_data *sd, int price, int points) { - char output[128]; - int cash; - nullpo_retr(-1,sd); + char output[128]; + int cash; + nullpo_retr(-1,sd); - points = cap_value(points,-MAX_ZENY,MAX_ZENY); //prevent command UB - if (price < 0 || points < 0) { - ShowError("pc_paycash: Paying negative points (price=%d, points=%d, account_id=%d, char_id=%d).\n", price, points, sd->status.account_id, sd->status.char_id); - return -2; - } + points = cap_value(points,-MAX_ZENY,MAX_ZENY); //prevent command UB + if( price < 0 || points < 0 ) + { + ShowError("pc_paycash: Paying negative points (price=%d, points=%d, account_id=%d, char_id=%d).\n", price, points, sd->status.account_id, sd->status.char_id); + return -2; + } - if (points > price) { - ShowWarning("pc_paycash: More kafra points provided than needed (price=%d, points=%d, account_id=%d, char_id=%d).\n", price, points, sd->status.account_id, sd->status.char_id); - points = price; - } + if( points > price ) + { + ShowWarning("pc_paycash: More kafra points provided than needed (price=%d, points=%d, account_id=%d, char_id=%d).\n", price, points, sd->status.account_id, sd->status.char_id); + points = price; + } - cash = price-points; + cash = price-points; - if (sd->cashPoints < cash || sd->kafraPoints < points) { - ShowError("pc_paycash: Not enough points (cash=%d, kafra=%d) to cover the price (cash=%d, kafra=%d) (account_id=%d, char_id=%d).\n", sd->cashPoints, sd->kafraPoints, cash, points, sd->status.account_id, sd->status.char_id); - return -1; - } + if( sd->cashPoints < cash || sd->kafraPoints < points ) + { + ShowError("pc_paycash: Not enough points (cash=%d, kafra=%d) to cover the price (cash=%d, kafra=%d) (account_id=%d, char_id=%d).\n", sd->cashPoints, sd->kafraPoints, cash, points, sd->status.account_id, sd->status.char_id); + return -1; + } - pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints-cash); - pc_setaccountreg(sd, "#KAFRAPOINTS", sd->kafraPoints-points); + pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints-cash); + pc_setaccountreg(sd, "#KAFRAPOINTS", sd->kafraPoints-points); - if (battle_config.cashshop_show_points) { - sprintf(output, msg_txt(504), points, cash, sd->kafraPoints, sd->cashPoints); - clif_disp_onlyself(sd, output, strlen(output)); - } - return cash+points; + if( battle_config.cashshop_show_points ) + { + sprintf(output, msg_txt(504), points, cash, sd->kafraPoints, sd->cashPoints); + clif_disp_onlyself(sd, output, strlen(output)); + } + return cash+points; } int pc_getcash(struct map_session_data *sd, int cash, int points) { - char output[128]; - nullpo_retr(-1,sd); - - cash = cap_value(cash,-MAX_ZENY,MAX_ZENY); //prevent command UB - points = cap_value(points,-MAX_ZENY,MAX_ZENY); //prevent command UB - if (cash > 0) { - if (cash > MAX_ZENY-sd->cashPoints) { - ShowWarning("pc_getcash: Cash point overflow (cash=%d, have cash=%d, account_id=%d, char_id=%d).\n", cash, sd->cashPoints, sd->status.account_id, sd->status.char_id); - cash = MAX_ZENY-sd->cashPoints; - } - - pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints+cash); - - if (battle_config.cashshop_show_points) { - sprintf(output, msg_txt(505), cash, sd->cashPoints); - clif_disp_onlyself(sd, output, strlen(output)); - } - return cash; - } else if (cash < 0) { - ShowError("pc_getcash: Obtaining negative cash points (cash=%d, account_id=%d, char_id=%d).\n", cash, sd->status.account_id, sd->status.char_id); - return -1; - } - - if (points > 0) { - if (points > MAX_ZENY-sd->kafraPoints) { - ShowWarning("pc_getcash: Kafra point overflow (points=%d, have points=%d, account_id=%d, char_id=%d).\n", points, sd->kafraPoints, sd->status.account_id, sd->status.char_id); - points = MAX_ZENY-sd->kafraPoints; - } - - pc_setaccountreg(sd, "#KAFRAPOINTS", sd->kafraPoints+points); - - if (battle_config.cashshop_show_points) { - sprintf(output, msg_txt(506), points, sd->kafraPoints); - clif_disp_onlyself(sd, output, strlen(output)); - } - return points; - } else if (points < 0) { - ShowError("pc_getcash: Obtaining negative kafra points (points=%d, account_id=%d, char_id=%d).\n", points, sd->status.account_id, sd->status.char_id); - return -1; - } - return -2; //shouldn't happen but jsut in case + char output[128]; + nullpo_retr(-1,sd); + + cash = cap_value(cash,-MAX_ZENY,MAX_ZENY); //prevent command UB + points = cap_value(points,-MAX_ZENY,MAX_ZENY); //prevent command UB + if( cash > 0 ) + { + if( cash > MAX_ZENY-sd->cashPoints ) + { + ShowWarning("pc_getcash: Cash point overflow (cash=%d, have cash=%d, account_id=%d, char_id=%d).\n", cash, sd->cashPoints, sd->status.account_id, sd->status.char_id); + cash = MAX_ZENY-sd->cashPoints; + } + + pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints+cash); + + if( battle_config.cashshop_show_points ) + { + sprintf(output, msg_txt(505), cash, sd->cashPoints); + clif_disp_onlyself(sd, output, strlen(output)); + } + return cash; + } + else if( cash < 0 ) + { + ShowError("pc_getcash: Obtaining negative cash points (cash=%d, account_id=%d, char_id=%d).\n", cash, sd->status.account_id, sd->status.char_id); + return -1; + } + + if( points > 0 ) + { + if( points > MAX_ZENY-sd->kafraPoints ) + { + ShowWarning("pc_getcash: Kafra point overflow (points=%d, have points=%d, account_id=%d, char_id=%d).\n", points, sd->kafraPoints, sd->status.account_id, sd->status.char_id); + points = MAX_ZENY-sd->kafraPoints; + } + + pc_setaccountreg(sd, "#KAFRAPOINTS", sd->kafraPoints+points); + + if( battle_config.cashshop_show_points ) + { + sprintf(output, msg_txt(506), points, sd->kafraPoints); + clif_disp_onlyself(sd, output, strlen(output)); + } + return points; + } + else if( points < 0 ) + { + ShowError("pc_getcash: Obtaining negative kafra points (points=%d, account_id=%d, char_id=%d).\n", points, sd->status.account_id, sd->status.char_id); + return -1; + } + return -2; //shouldn't happen but jsut in case } /*========================================== @@ -3617,29 +3716,30 @@ int pc_getcash(struct map_session_data *sd, int cash, int points) *------------------------------------------*/ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd) { - nullpo_retr(-1,sd); + nullpo_retr(-1,sd); - zeny = cap_value(zeny,-MAX_ZENY,MAX_ZENY); //prevent command UB - if (zeny < 0) { - ShowError("pc_getzeny: Obtaining negative Zeny (zeny=%d, account_id=%d, char_id=%d).\n", zeny, sd->status.account_id, sd->status.char_id); - return 1; - } + zeny = cap_value(zeny,-MAX_ZENY,MAX_ZENY); //prevent command UB + if( zeny < 0 ) + { + ShowError("pc_getzeny: Obtaining negative Zeny (zeny=%d, account_id=%d, char_id=%d).\n", zeny, sd->status.account_id, sd->status.char_id); + return 1; + } - if (zeny > MAX_ZENY - sd->status.zeny) - zeny = MAX_ZENY - sd->status.zeny; + if( zeny > MAX_ZENY - sd->status.zeny ) + zeny = MAX_ZENY - sd->status.zeny; - sd->status.zeny += zeny; - clif_updatestatus(sd,SP_ZENY); + sd->status.zeny += zeny; + clif_updatestatus(sd,SP_ZENY); - if (!tsd) tsd = sd; - log_zeny(sd, type, tsd, zeny); - if (zeny > 0 && sd->state.showzeny) { - char output[255]; - sprintf(output, "Gained %dz.", zeny); - clif_disp_onlyself(sd,output,strlen(output)); - } + if(!tsd) tsd = sd; + log_zeny(sd, type, tsd, zeny); + if( zeny > 0 && sd->state.showzeny ) { + char output[255]; + sprintf(output, "Gained %dz.", zeny); + clif_disp_onlyself(sd,output,strlen(output)); + } - return 0; + return 0; } /*========================================== @@ -3647,11 +3747,11 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, *------------------------------------------*/ int pc_search_inventory(struct map_session_data *sd,int item_id) { - int i; - nullpo_retr(-1, sd); + int i; + nullpo_retr(-1, sd); - ARR_FIND(0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == item_id && (sd->status.inventory[i].amount > 0 || item_id == 0)); - return (i < MAX_INVENTORY) ? i : -1; + ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == item_id && (sd->status.inventory[i].amount > 0 || item_id == 0) ); + return ( i < MAX_INVENTORY ) ? i : -1; } /*========================================== @@ -3660,641 +3760,676 @@ int pc_search_inventory(struct map_session_data *sd,int item_id) 0 = success 1 = invalid itemid not found or negative amount 2 = overweight - 3 = ? + 3 = ? 4 = no free place found 5 = max amount reached - 6 = ? - 7 = stack limitation + 6 = ? + 7 = stack limitation *------------------------------------------*/ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type) { - struct item_data *data; - int i; - unsigned int w; - - nullpo_retr(1, sd); - nullpo_retr(1, item_data); - - if (item_data->nameid <= 0 || amount <= 0) - return 1; - if (amount > MAX_AMOUNT) - return 5; - - data = itemdb_search(item_data->nameid); - - if (data->stack.inventory && amount > data->stack.amount) { - // item stack limitation - return 7; - } - - w = data->weight*amount; - if (sd->weight + w > sd->max_weight) - return 2; - - i = MAX_INVENTORY; - - if (itemdb_isstackable2(data) && item_data->expire_time == 0) { - // Stackable | Non Rental - for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid == item_data->nameid && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0) { - if (amount > MAX_AMOUNT - sd->status.inventory[i].amount || (data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount)) - return 5; - sd->status.inventory[i].amount += amount; - clif_additem(sd,i,amount,0); - break; - } - } - } - - if (i >= MAX_INVENTORY) { - i = pc_search_inventory(sd,0); - if (i < 0) - return 4; - - memcpy(&sd->status.inventory[i], item_data, sizeof(sd->status.inventory[0])); - // clear equips field first, just in case - if (item_data->equip) - sd->status.inventory[i].equip = 0; - - sd->status.inventory[i].amount = amount; - sd->inventory_data[i] = data; - clif_additem(sd,i,amount,0); - } - log_pick_pc(sd, log_type, amount, &sd->status.inventory[i]); - - sd->weight += w; - clif_updatestatus(sd,SP_WEIGHT); - //Auto-equip - if (data->flag.autoequip) - pc_equipitem(sd, i, data->equip); - - /* rental item check */ - if (item_data->expire_time) { - if (time(NULL) > item_data->expire_time) { - clif_rental_expired(sd->fd, i, sd->status.inventory[i].nameid); - pc_delitem(sd, i, sd->status.inventory[i].amount, 1, 0, LOG_TYPE_OTHER); - } else { - int seconds = (int)(item_data->expire_time - time(NULL)); - clif_rental_time(sd->fd, sd->status.inventory[i].nameid, seconds); - pc_inventory_rental_add(sd, seconds); - } - } - - return 0; + struct item_data *data; + int i; + unsigned int w; + + nullpo_retr(1, sd); + nullpo_retr(1, item_data); + + if( item_data->nameid <= 0 || amount <= 0 ) + return 1; + if( amount > MAX_AMOUNT ) + return 5; + + data = itemdb_search(item_data->nameid); + + if( data->stack.inventory && amount > data->stack.amount ) + {// item stack limitation + return 7; + } + + w = data->weight*amount; + if(sd->weight + w > sd->max_weight) + return 2; + + i = MAX_INVENTORY; + + if( itemdb_isstackable2(data) && item_data->expire_time == 0 ) + { // Stackable | Non Rental + for( i = 0; i < MAX_INVENTORY; i++ ) + { + if( sd->status.inventory[i].nameid == item_data->nameid && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 ) + { + if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) ) + return 5; + sd->status.inventory[i].amount += amount; + clif_additem(sd,i,amount,0); + break; + } + } + } + + if( i >= MAX_INVENTORY ) + { + i = pc_search_inventory(sd,0); + if( i < 0 ) + return 4; + + memcpy(&sd->status.inventory[i], item_data, sizeof(sd->status.inventory[0])); + // clear equips field first, just in case + if( item_data->equip ) + sd->status.inventory[i].equip = 0; + + sd->status.inventory[i].amount = amount; + sd->inventory_data[i] = data; + clif_additem(sd,i,amount,0); + } + log_pick_pc(sd, log_type, amount, &sd->status.inventory[i]); + + sd->weight += w; + clif_updatestatus(sd,SP_WEIGHT); + //Auto-equip + if(data->flag.autoequip) + pc_equipitem(sd, i, data->equip); + + /* rental item check */ + if( item_data->expire_time ) { + if( time(NULL) > item_data->expire_time ) { + clif_rental_expired(sd->fd, i, sd->status.inventory[i].nameid); + pc_delitem(sd, i, sd->status.inventory[i].amount, 1, 0, LOG_TYPE_OTHER); + } else { + int seconds = (int)( item_data->expire_time - time(NULL) ); + clif_rental_time(sd->fd, sd->status.inventory[i].nameid, seconds); + pc_inventory_rental_add(sd, seconds); + } + } + + return 0; } /*========================================== * Remove an item at index n from inventory by amount. * Parameters : * @type - * 1 : don't notify deletion - * 2 : don't notify weight change + * 1 : don't notify deletion + * 2 : don't notify weight change * Return: - * 0 = success - * 1 = invalid itemid or negative amount + * 0 = success + * 1 = invalid itemid or negative amount *------------------------------------------*/ int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type) { - nullpo_retr(1, sd); + nullpo_retr(1, sd); - if (sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || sd->inventory_data[n] == NULL) - return 1; + if(sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || sd->inventory_data[n] == NULL) + return 1; - log_pick_pc(sd, log_type, -amount, &sd->status.inventory[n]); + log_pick_pc(sd, log_type, -amount, &sd->status.inventory[n]); - sd->status.inventory[n].amount -= amount; - 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,3); - memset(&sd->status.inventory[n],0,sizeof(sd->status.inventory[0])); - sd->inventory_data[n] = NULL; - } - if (!(type&1)) - clif_delitem(sd,n,amount,reason); - if (!(type&2)) - clif_updatestatus(sd,SP_WEIGHT); + sd->status.inventory[n].amount -= amount; + 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,3); + memset(&sd->status.inventory[n],0,sizeof(sd->status.inventory[0])); + sd->inventory_data[n] = NULL; + } + if(!(type&1)) + clif_delitem(sd,n,amount,reason); + if(!(type&2)) + clif_updatestatus(sd,SP_WEIGHT); - return 0; + return 0; } /*========================================== * Attempt to drop an item. * Return: - * 0 = fail - * 1 = success + * 0 = fail + * 1 = success *------------------------------------------*/ int pc_dropitem(struct map_session_data *sd,int n,int amount) { - nullpo_retr(1, sd); + nullpo_retr(1, sd); - if (n < 0 || n >= MAX_INVENTORY) - return 0; + if(n < 0 || n >= MAX_INVENTORY) + return 0; - if (amount <= 0) - return 0; + if(amount <= 0) + return 0; - if (sd->status.inventory[n].nameid <= 0 || - sd->status.inventory[n].amount <= 0 || - sd->status.inventory[n].amount < amount || - sd->state.trading || sd->state.vending || - !sd->inventory_data[n] //pc_delitem would fail on this case. - ) - return 0; + if(sd->status.inventory[n].nameid <= 0 || + sd->status.inventory[n].amount <= 0 || + sd->status.inventory[n].amount < amount || + sd->state.trading || sd->state.vending || + !sd->inventory_data[n] //pc_delitem would fail on this case. + ) + return 0; - if (map[sd->bl.m].flag.nodrop) { - clif_displaymessage(sd->fd, msg_txt(271)); - return 0; //Can't drop items in nodrop mapflag maps. - } + if( map[sd->bl.m].flag.nodrop ) + { + clif_displaymessage (sd->fd, msg_txt(271)); + return 0; //Can't drop items in nodrop mapflag maps. + } - if (!pc_candrop(sd,&sd->status.inventory[n])) { - clif_displaymessage(sd->fd, msg_txt(263)); - return 0; - } + if( !pc_candrop(sd,&sd->status.inventory[n]) ) + { + clif_displaymessage (sd->fd, msg_txt(263)); + return 0; + } - if (!map_addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 2)) - return 0; + if (!map_addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 2)) + return 0; - pc_delitem(sd, n, amount, 1, 0, LOG_TYPE_PICKDROP_PLAYER); - clif_dropitem(sd, n, amount); - return 1; + pc_delitem(sd, n, amount, 1, 0, LOG_TYPE_PICKDROP_PLAYER); + clif_dropitem(sd, n, amount); + return 1; } /*========================================== * Attempt to pick up an item. * Return: - * 0 = fail - * 1 = success + * 0 = fail + * 1 = success *------------------------------------------*/ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem) { - int flag=0; - unsigned int tick = gettick(); - struct map_session_data *first_sd = NULL,*second_sd = NULL,*third_sd = NULL; - struct party_data *p=NULL; - - nullpo_ret(sd); - nullpo_ret(fitem); - - if (!check_distance_bl(&fitem->bl, &sd->bl, 2) && sd->ud.skillid!=BS_GREED) - return 0; // Distance is too far - - if (sd->status.party_id) - p = party_search(sd->status.party_id); - - if (fitem->first_get_charid > 0 && fitem->first_get_charid != sd->status.char_id) { - first_sd = map_charid2sd(fitem->first_get_charid); - if (DIFF_TICK(tick,fitem->first_get_tick) < 0) { - if (!(p && p->party.item&1 && - first_sd && first_sd->status.party_id == sd->status.party_id - )) - return 0; - } else if (fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id) { - second_sd = map_charid2sd(fitem->second_get_charid); - if (DIFF_TICK(tick, fitem->second_get_tick) < 0) { - if (!(p && p->party.item&1 && - ((first_sd && first_sd->status.party_id == sd->status.party_id) || - (second_sd && second_sd->status.party_id == sd->status.party_id)) - )) - return 0; - } else if (fitem->third_get_charid > 0 && fitem->third_get_charid != sd->status.char_id) { - third_sd = map_charid2sd(fitem->third_get_charid); - if (DIFF_TICK(tick,fitem->third_get_tick) < 0) { - if (!(p && p->party.item&1 && - ((first_sd && first_sd->status.party_id == sd->status.party_id) || - (second_sd && second_sd->status.party_id == sd->status.party_id) || - (third_sd && third_sd->status.party_id == sd->status.party_id)) - )) - return 0; - } - } - } - } - - //This function takes care of giving the item to whoever should have it, considering party-share options. - if ((flag = party_share_loot(p,sd,&fitem->item_data, fitem->first_get_charid))) { - clif_additem(sd,0,0,flag); - return 1; - } - - //Display pickup animation. - pc_stop_attack(sd); - clif_takeitem(&sd->bl,&fitem->bl); - map_clearflooritem(&fitem->bl); - return 1; + int flag=0; + unsigned int tick = gettick(); + struct map_session_data *first_sd = NULL,*second_sd = NULL,*third_sd = NULL; + struct party_data *p=NULL; + + nullpo_ret(sd); + nullpo_ret(fitem); + + if(!check_distance_bl(&fitem->bl, &sd->bl, 2) && sd->ud.skillid!=BS_GREED) + return 0; // Distance is too far + + if (sd->status.party_id) + p = party_search(sd->status.party_id); + + if(fitem->first_get_charid > 0 && fitem->first_get_charid != sd->status.char_id) + { + first_sd = map_charid2sd(fitem->first_get_charid); + if(DIFF_TICK(tick,fitem->first_get_tick) < 0) { + if (!(p && p->party.item&1 && + first_sd && first_sd->status.party_id == sd->status.party_id + )) + return 0; + } + else + if(fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id) + { + second_sd = map_charid2sd(fitem->second_get_charid); + if(DIFF_TICK(tick, fitem->second_get_tick) < 0) { + if(!(p && p->party.item&1 && + ((first_sd && first_sd->status.party_id == sd->status.party_id) || + (second_sd && second_sd->status.party_id == sd->status.party_id)) + )) + return 0; + } + else + if(fitem->third_get_charid > 0 && fitem->third_get_charid != sd->status.char_id) + { + third_sd = map_charid2sd(fitem->third_get_charid); + if(DIFF_TICK(tick,fitem->third_get_tick) < 0) { + if(!(p && p->party.item&1 && + ((first_sd && first_sd->status.party_id == sd->status.party_id) || + (second_sd && second_sd->status.party_id == sd->status.party_id) || + (third_sd && third_sd->status.party_id == sd->status.party_id)) + )) + return 0; + } + } + } + } + + //This function takes care of giving the item to whoever should have it, considering party-share options. + if ((flag = party_share_loot(p,sd,&fitem->item_data, fitem->first_get_charid))) { + clif_additem(sd,0,0,flag); + return 1; + } + + //Display pickup animation. + pc_stop_attack(sd); + clif_takeitem(&sd->bl,&fitem->bl); + map_clearflooritem(&fitem->bl); + return 1; } /*========================================== * Check if item is usable. * Return: - * 0 = no - * 1 = yes + * 0 = no + * 1 = yes *------------------------------------------*/ int pc_isUseitem(struct map_session_data *sd,int n) { - struct item_data *item; - int nameid; - - nullpo_ret(sd); - - item = sd->inventory_data[n]; - nameid = sd->status.inventory[n].nameid; - - if (item == NULL) - return 0; - //Not consumable item - if (item->type != IT_HEALING && item->type != IT_USABLE && item->type != IT_CASH) - return 0; - if (!item->script) //if it has no script, you can't really consume it! - return 0; - - switch (nameid) { //@TODO, lot oh harcoded nameid here - case 605: // Anodyne - if (map_flag_gvg(sd->bl.m)) - return 0; - case 606: - if (pc_issit(sd)) - return 0; - break; - case 601: // Fly Wing - case 12212: // Giant Fly Wing - if (map[sd->bl.m].flag.noteleport || map_flag_gvg(sd->bl.m)) { - clif_skill_teleportmessage(sd,0); - return 0; - } - case 602: // ButterFly Wing - case 14527: // Dungeon Teleport Scroll - case 14581: // Dungeon Teleport Scroll - case 14582: // Yellow Butterfly Wing - case 14583: // Green Butterfly Wing - case 14584: // Red Butterfly Wing - case 14585: // Blue Butterfly Wing - case 14591: // Siege Teleport Scroll - if (sd->duel_group && !battle_config.duel_allow_teleport) { - clif_displaymessage(sd->fd, msg_txt(663)); - return 0; - } - if (nameid != 601 && nameid != 12212 && map[sd->bl.m].flag.noreturn) - return 0; - break; - case 604: // Dead Branch - case 12024: // Red Pouch - case 12103: // Bloody Branch - case 12109: // Poring Box - if (map[sd->bl.m].flag.nobranch || map_flag_gvg(sd->bl.m)) - return 0; - break; - case 12210: // Bubble Gum - case 12264: // Comp Bubble Gum - if (sd->sc.data[SC_ITEMBOOST]) - return 0; - break; - case 12208: // Battle Manual - case 12263: // Comp Battle Manual - case 12312: // Thick Battle Manual - case 12705: // Noble Nameplate - case 14532: // Battle_Manual25 - case 14533: // Battle_Manual100 - case 14545: // Battle_Manual300 - if (sd->sc.data[SC_EXPBOOST]) - return 0; - break; - case 14592: // JOB_Battle_Manual - if (sd->sc.data[SC_JEXPBOOST]) - return 0; - break; - - // Mercenary Items - - case 12184: // Mercenary's Red Potion - case 12185: // Mercenary's Blue Potion - case 12241: // Mercenary's Concentration Potion - case 12242: // Mercenary's Awakening Potion - case 12243: // Mercenary's Berserk Potion - if (sd->md == NULL || sd->md->db == NULL) - return 0; - if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAYNIGHTFEVER] || sd->md->sc.data[SC__BLOODYLUST]) - return 0; - if (nameid == 12242 && sd->md->db->lv < 40) - return 0; - if (nameid == 12243 && sd->md->db->lv < 80) - return 0; - break; - - case 12213: //Neuralizer - if (!map[sd->bl.m].flag.reset) - return 0; - break; - } - - if (nameid >= 12153 && nameid <= 12182 && sd->md != NULL) - return 0; // Mercenary Scrolls - - /** - * Only Rune Knights may use runes - **/ - if (itemdb_is_rune(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT) - return 0; - /** - * Only GCross may use poisons - **/ - else if (itemdb_is_poison(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_GUILLOTINE_CROSS) - return 0; - - //added item_noequip.txt items check by Maya&[Lupus] - if ( - (!map_flag_vs(sd->bl.m) && item->flag.no_equip&1) || // Normal - (map[sd->bl.m].flag.pvp && item->flag.no_equip&2) || // PVP - (map_flag_gvg(sd->bl.m) && item->flag.no_equip&4) || // GVG - (map[sd->bl.m].flag.battleground && item->flag.no_equip&8) || // Battleground - (map[sd->bl.m].flag.restricted && item->flag.no_equip&(8*map[sd->bl.m].zone)) // Zone restriction - ) - return 0; - - //Gender check - if (item->sex != 2 && sd->status.sex != item->sex) - return 0; - //Required level check - if (item->elv && sd->status.base_level < (unsigned int)item->elv) - return 0; + struct item_data *item; + int nameid; + + nullpo_ret(sd); + + item = sd->inventory_data[n]; + nameid = sd->status.inventory[n].nameid; + + if( item == NULL ) + return 0; + //Not consumable item + if( item->type != IT_HEALING && item->type != IT_USABLE && item->type != IT_CASH ) + return 0; + if( !item->script ) //if it has no script, you can't really consume it! + return 0; + + switch( nameid ) //@TODO, lot oh harcoded nameid here + { + case 605: // Anodyne + if( map_flag_gvg(sd->bl.m) ) + return 0; + case 606: + if( pc_issit(sd) ) + return 0; + break; + case 601: // Fly Wing + case 12212: // Giant Fly Wing + if( map[sd->bl.m].flag.noteleport || map_flag_gvg(sd->bl.m) ) + { + clif_skill_teleportmessage(sd,0); + return 0; + } + case 602: // ButterFly Wing + case 14527: // Dungeon Teleport Scroll + case 14581: // Dungeon Teleport Scroll + case 14582: // Yellow Butterfly Wing + case 14583: // Green Butterfly Wing + case 14584: // Red Butterfly Wing + case 14585: // Blue Butterfly Wing + case 14591: // Siege Teleport Scroll + if( sd->duel_group && !battle_config.duel_allow_teleport ) + { + clif_displaymessage(sd->fd, msg_txt(663)); + return 0; + } + if( nameid != 601 && nameid != 12212 && map[sd->bl.m].flag.noreturn ) + return 0; + break; + case 604: // Dead Branch + case 12024: // Red Pouch + case 12103: // Bloody Branch + case 12109: // Poring Box + if( map[sd->bl.m].flag.nobranch || map_flag_gvg(sd->bl.m) ) + return 0; + break; + case 12210: // Bubble Gum + case 12264: // Comp Bubble Gum + if( sd->sc.data[SC_ITEMBOOST] ) + return 0; + break; + case 12208: // Battle Manual + case 12263: // Comp Battle Manual + case 12312: // Thick Battle Manual + case 12705: // Noble Nameplate + case 14532: // Battle_Manual25 + case 14533: // Battle_Manual100 + case 14545: // Battle_Manual300 + if( sd->sc.data[SC_EXPBOOST] ) + return 0; + break; + case 14592: // JOB_Battle_Manual + if( sd->sc.data[SC_JEXPBOOST] ) + return 0; + break; + + // Mercenary Items + + case 12184: // Mercenary's Red Potion + case 12185: // Mercenary's Blue Potion + case 12241: // Mercenary's Concentration Potion + case 12242: // Mercenary's Awakening Potion + case 12243: // Mercenary's Berserk Potion + if( sd->md == NULL || sd->md->db == NULL ) + return 0; + if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAYNIGHTFEVER] || sd->md->sc.data[SC__BLOODYLUST]) + return 0; + if( nameid == 12242 && sd->md->db->lv < 40 ) + return 0; + if( nameid == 12243 && sd->md->db->lv < 80 ) + return 0; + break; + + case 12213: //Neuralizer + if( !map[sd->bl.m].flag.reset ) + return 0; + break; + } + + if( nameid >= 12153 && nameid <= 12182 && sd->md != NULL ) + return 0; // Mercenary Scrolls + + /** + * Only Rune Knights may use runes + **/ + if( itemdb_is_rune(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT ) + return 0; + /** + * Only GCross may use poisons + **/ + else if( itemdb_is_poison(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_GUILLOTINE_CROSS ) + return 0; + + //added item_noequip.txt items check by Maya&[Lupus] + if ( + (!map_flag_vs(sd->bl.m) && item->flag.no_equip&1) || // Normal + (map[sd->bl.m].flag.pvp && item->flag.no_equip&2) || // PVP + (map_flag_gvg(sd->bl.m) && item->flag.no_equip&4) || // GVG + (map[sd->bl.m].flag.battleground && item->flag.no_equip&8) || // Battleground + (map[sd->bl.m].flag.restricted && item->flag.no_equip&(8*map[sd->bl.m].zone)) // Zone restriction + ) + return 0; + + //Gender check + if(item->sex != 2 && sd->status.sex != item->sex) + return 0; + //Required level check + if(item->elv && sd->status.base_level < (unsigned int)item->elv) + return 0; #ifdef RENEWAL - if (item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) - return 0; + if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) + return 0; #endif - //Not equipable by class. [Skotlex] - if (!( - (1<<(sd->class_&MAPID_BASEMASK)) & - (item->class_base[sd->class_&JOBL_2_1?1:(sd->class_&JOBL_2_2?2:0)]) - )) - return 0; - //Not usable by upper class. [Inkfish] - while (1) { - if (item->class_upper&1 && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY))) break; - if (item->class_upper&2 && sd->class_&(JOBL_UPPER|JOBL_THIRD)) break; - if (item->class_upper&4 && sd->class_&JOBL_BABY) break; - if (item->class_upper&8 && sd->class_&JOBL_THIRD) break; - return 0; - } - - //Dead Branch & Bloody Branch & Porings Box - // FIXME: outdated, use constants or database - if (nameid == 604 || nameid == 12103 || nameid == 12109) - log_branch(sd); - - return 1; + //Not equipable by class. [Skotlex] + if (!( + (1<<(sd->class_&MAPID_BASEMASK)) & + (item->class_base[sd->class_&JOBL_2_1?1:(sd->class_&JOBL_2_2?2:0)]) + )) + return 0; + //Not usable by upper class. [Inkfish] + while( 1 ) { + if( item->class_upper&1 && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break; + if( item->class_upper&2 && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break; + if( item->class_upper&4 && sd->class_&JOBL_BABY ) break; + if( item->class_upper&8 && sd->class_&JOBL_THIRD ) break; + return 0; + } + + //Dead Branch & Bloody Branch & Porings Box + // FIXME: outdated, use constants or database + if( nameid == 604 || nameid == 12103 || nameid == 12109 ) + log_branch(sd); + + return 1; } /*========================================== * Last checks to use an item. * Return: - * 0 = fail - * 1 = success + * 0 = fail + * 1 = success *------------------------------------------*/ int pc_useitem(struct map_session_data *sd,int n) { - unsigned int tick = gettick(); - int amount, i, nameid; - struct script_code *script; - - nullpo_ret(sd); - - if (sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0) - return 0; - - if (!pc_isUseitem(sd,n)) - return 0; - - // Store information for later use before it is lost (via pc_delitem) [Paradox924X] - nameid = sd->inventory_data[n]->nameid; - - if (nameid != ITEMID_NAUTHIZ && sd->sc.opt1 > 0 && sd->sc.opt1 != OPT1_STONEWAIT && sd->sc.opt1 != OPT1_BURNING) - return 0; - - if (sd->sc.count && ( - sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) || - sd->sc.data[SC_TRICKDEAD] || - sd->sc.data[SC_HIDING] || - sd->sc.data[SC__SHADOWFORM] || - sd->sc.data[SC__MANHOLE] || - sd->sc.data[SC_KAGEHUMI] || - (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) - )) - return 0; - - //Prevent mass item usage. [Skotlex] - if (DIFF_TICK(sd->canuseitem_tick, tick) > 0 || - (itemdb_iscashfood(nameid) && DIFF_TICK(sd->canusecashfood_tick, tick) > 0) - ) - return 0; - - /* Items with delayed consume are not meant to work while in mounts except reins of mount(12622) */ - if (sd->inventory_data[n]->flag.delay_consume) { - if (nameid != ITEMID_REINS_OF_MOUNT && sd->sc.option&OPTION_MOUNTING) - return 0; - else if (pc_issit(sd)) - return 0; - } - //Since most delay-consume items involve using a "skill-type" target cursor, - //perform a skill-use check before going through. [Skotlex] - //resurrection was picked as testing skill, as a non-offensive, generic skill, it will do. - //FIXME: Is this really needed here? It'll be checked in unit.c after all and this prevents skill items using when silenced [Inkfish] - if (sd->inventory_data[n]->flag.delay_consume && (sd->ud.skilltimer != INVALID_TIMER /*|| !status_check_skilluse(&sd->bl, &sd->bl, ALL_RESURRECTION, 0)*/)) - return 0; - - if (sd->inventory_data[n]->delay > 0) { - ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid); - if (i == MAX_ITEMDELAYS) /* item not found. try first empty now */ - ARR_FIND(0, MAX_ITEMDELAYS, i, !sd->item_delay[i].nameid); - if (i < MAX_ITEMDELAYS) { - if (sd->item_delay[i].nameid) { // found - if (DIFF_TICK(sd->item_delay[i].tick, tick) > 0) { - int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000; - char e_msg[100]; - if (e_tick > 99) - sprintf(e_msg,"Item Failed. [%s] is cooling down. wait %.1f minutes.", - itemdb_jname(sd->status.inventory[n].nameid), - (double)e_tick / 60); - else - sprintf(e_msg,"Item Failed. [%s] is cooling down. wait %d seconds.", - itemdb_jname(sd->status.inventory[n].nameid), - e_tick+1); - clif_colormes(sd,COLOR_RED,e_msg); - return 0; // Delay has not expired yet - } - } else {// not yet used item (all slots are initially empty) - sd->item_delay[i].nameid = nameid; - } - sd->item_delay[i].tick = tick + sd->inventory_data[n]->delay; - } else {// should not happen - ShowError("pc_useitem: Exceeded item delay array capacity! (nameid=%d, char_id=%d)\n", nameid, sd->status.char_id); - } - //clean up used delays so we can give room for more - for (i = 0; i < MAX_ITEMDELAYS; i++) { - if (DIFF_TICK(sd->item_delay[i].tick, tick) <= 0) { - sd->item_delay[i].tick = 0; - sd->item_delay[i].nameid = 0; - } - } - } - - sd->itemid = sd->status.inventory[n].nameid; - sd->itemindex = n; - if (sd->catch_target_class != -1) //Abort pet catching. - sd->catch_target_class = -1; - - amount = sd->status.inventory[n].amount; - script = sd->inventory_data[n]->script; - //Check if the item is to be consumed immediately [Skotlex] - if (sd->inventory_data[n]->flag.delay_consume) - clif_useitemack(sd,n,amount,true); - else { - if (sd->status.inventory[n].expire_time == 0) { - clif_useitemack(sd,n,amount-1,true); - pc_delitem(sd,n,1,1,0,LOG_TYPE_CONSUME); // Rental Usable Items are not deleted until expiration - } else - clif_useitemack(sd,n,0,false); - } - if (sd->status.inventory[n].card[0]==CARD0_CREATE && - pc_famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST)) { - potion_flag = 2; // Famous player's potions have 50% more efficiency - if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ROGUE) - potion_flag = 3; //Even more effective potions. - } - - //Update item use time. - sd->canuseitem_tick = tick + battle_config.item_use_interval; - if (itemdb_iscashfood(nameid)) - sd->canusecashfood_tick = tick + battle_config.cashfood_use_interval; - - run_script(script,0,sd->bl.id,fake_nd->bl.id); - potion_flag = 0; - return 1; + unsigned int tick = gettick(); + int amount, i, nameid; + struct script_code *script; + + nullpo_ret(sd); + + if( sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0 ) + return 0; + + if( !pc_isUseitem(sd,n) ) + return 0; + + // Store information for later use before it is lost (via pc_delitem) [Paradox924X] + nameid = sd->inventory_data[n]->nameid; + + if (nameid != ITEMID_NAUTHIZ && sd->sc.opt1 > 0 && sd->sc.opt1 != OPT1_STONEWAIT && sd->sc.opt1 != OPT1_BURNING) + return 0; + + if( sd->sc.count){ + if((nameid == ITEMID_NAUTHIZ) && ( //bugreport 6751 + sd->sc.data[SC_FREEZE] || + sd->sc.data[SC_STUN] || + sd->sc.data[SC_DEEPSLEEP] || + sd->sc.data[SC_STONE] || + sd->sc.data[SC_CRYSTALIZE] + ) + ){ + sd->sc.opt1 = 0; //remove option and status to allow skill + status_change_end(&sd->bl,SC_FREEZE,INVALID_TIMER); + status_change_end(&sd->bl,SC_STUN,INVALID_TIMER); + status_change_end(&sd->bl,SC_DEEPSLEEP,INVALID_TIMER); + status_change_end(&sd->bl,SC_STONE,INVALID_TIMER); + status_change_end(&sd->bl,SC_CRYSTALIZE,INVALID_TIMER); + } //let us continue + else if( + sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || + (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) || + sd->sc.data[SC_TRICKDEAD] || + sd->sc.data[SC_HIDING] || + sd->sc.data[SC__SHADOWFORM] || + sd->sc.data[SC__MANHOLE] || + sd->sc.data[SC_KAGEHUMI] || + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) + ) + return 0; + } + + //Prevent mass item usage. [Skotlex] + if( DIFF_TICK(sd->canuseitem_tick, tick) > 0 || + (itemdb_iscashfood(nameid) && DIFF_TICK(sd->canusecashfood_tick, tick) > 0) + ) + return 0; + + /* Items with delayed consume are not meant to work while in mounts except reins of mount(12622) */ + if( sd->inventory_data[n]->flag.delay_consume ) { + if( nameid != ITEMID_REINS_OF_MOUNT && sd->sc.option&OPTION_MOUNTING ) + return 0; + else if( pc_issit(sd) ) + return 0; + } + //Since most delay-consume items involve using a "skill-type" target cursor, + //perform a skill-use check before going through. [Skotlex] + //resurrection was picked as testing skill, as a non-offensive, generic skill, it will do. + //FIXME: Is this really needed here? It'll be checked in unit.c after all and this prevents skill items using when silenced [Inkfish] + if( sd->inventory_data[n]->flag.delay_consume && ( sd->ud.skilltimer != INVALID_TIMER /*|| !status_check_skilluse(&sd->bl, &sd->bl, ALL_RESURRECTION, 0)*/ ) ) + return 0; + + if( sd->inventory_data[n]->delay > 0 ) { + ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid ); + if( i == MAX_ITEMDELAYS ) /* item not found. try first empty now */ + ARR_FIND(0, MAX_ITEMDELAYS, i, !sd->item_delay[i].nameid ); + if( i < MAX_ITEMDELAYS ) { + if( sd->item_delay[i].nameid ) {// found + if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) { + int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000; + char e_msg[100]; + if( e_tick > 99 ) + sprintf(e_msg,"Item Failed. [%s] is cooling down. wait %.1f minutes.", + itemdb_jname(sd->status.inventory[n].nameid), + (double)e_tick / 60); + else + sprintf(e_msg,"Item Failed. [%s] is cooling down. wait %d seconds.", + itemdb_jname(sd->status.inventory[n].nameid), + e_tick+1); + clif_colormes(sd,COLOR_RED,e_msg); + return 0; // Delay has not expired yet + } + } else {// not yet used item (all slots are initially empty) + sd->item_delay[i].nameid = nameid; + } + sd->item_delay[i].tick = tick + sd->inventory_data[n]->delay; + } else {// should not happen + ShowError("pc_useitem: Exceeded item delay array capacity! (nameid=%d, char_id=%d)\n", nameid, sd->status.char_id); + } + //clean up used delays so we can give room for more + for(i = 0; i < MAX_ITEMDELAYS; i++) { + if( DIFF_TICK(sd->item_delay[i].tick, tick) <= 0 ) { + sd->item_delay[i].tick = 0; + sd->item_delay[i].nameid = 0; + } + } + } + + sd->itemid = sd->status.inventory[n].nameid; + sd->itemindex = n; + if(sd->catch_target_class != -1) //Abort pet catching. + sd->catch_target_class = -1; + + amount = sd->status.inventory[n].amount; + script = sd->inventory_data[n]->script; + //Check if the item is to be consumed immediately [Skotlex] + if( sd->inventory_data[n]->flag.delay_consume ) + clif_useitemack(sd,n,amount,true); + else { + if( sd->status.inventory[n].expire_time == 0 ) { + clif_useitemack(sd,n,amount-1,true); + pc_delitem(sd,n,1,1,0,LOG_TYPE_CONSUME); // Rental Usable Items are not deleted until expiration + } else + clif_useitemack(sd,n,0,false); + } + if(sd->status.inventory[n].card[0]==CARD0_CREATE && + pc_famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST)) + { + potion_flag = 2; // Famous player's potions have 50% more efficiency + if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ROGUE) + potion_flag = 3; //Even more effective potions. + } + + //Update item use time. + sd->canuseitem_tick = tick + battle_config.item_use_interval; + if( itemdb_iscashfood(nameid) ) + sd->canusecashfood_tick = tick + battle_config.cashfood_use_interval; + + run_script(script,0,sd->bl.id,fake_nd->bl.id); + potion_flag = 0; + return 1; } /*========================================== * Add item on cart for given index. * Return: - * 0 = success - * 1 = fail + * 0 = success + * 1 = fail *------------------------------------------*/ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type) { - struct item_data *data; - int i,w; - - nullpo_retr(1, sd); - nullpo_retr(1, item_data); - - if (item_data->nameid <= 0 || amount <= 0) - return 1; - data = itemdb_search(item_data->nameid); - - if (data->stack.cart && amount > data->stack.amount) { - // item stack limitation - return 1; - } - - if (!itemdb_cancartstore(item_data, pc_get_group_level(sd))) { - // Check item trade restrictions [Skotlex] - clif_displaymessage(sd->fd, msg_txt(264)); - return 1; - } - - if ((w = data->weight*amount) + sd->cart_weight > sd->cart_weight_max) - return 1; - - i = MAX_CART; - if (itemdb_isstackable2(data) && !item_data->expire_time) { - ARR_FIND(0, MAX_CART, i, - 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] && - sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3]); - }; - - if (i < MAX_CART) { - // item already in cart, stack it - if (amount > MAX_AMOUNT - sd->status.cart[i].amount || (data->stack.cart && amount > data->stack.amount - sd->status.cart[i].amount)) - return 1; // no room - - sd->status.cart[i].amount+=amount; - clif_cart_additem(sd,i,amount,0); - } else { - // item not stackable or not present, add it - ARR_FIND(0, MAX_CART, i, sd->status.cart[i].nameid == 0); - if (i == MAX_CART) - return 1; // no room - - memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0])); - sd->status.cart[i].amount=amount; - sd->cart_num++; - clif_cart_additem(sd,i,amount,0); - } - sd->status.cart[i].favorite = 0;/* clear */ - log_pick_pc(sd, log_type, amount, &sd->status.cart[i]); - - sd->cart_weight += w; - clif_updatestatus(sd,SP_CARTINFO); - - return 0; + struct item_data *data; + int i,w; + + nullpo_retr(1, sd); + nullpo_retr(1, item_data); + + if(item_data->nameid <= 0 || amount <= 0) + return 1; + data = itemdb_search(item_data->nameid); + + if( data->stack.cart && amount > data->stack.amount ) + {// item stack limitation + return 1; + } + + if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) ) + { // Check item trade restrictions [Skotlex] + clif_displaymessage (sd->fd, msg_txt(264)); + return 1; + } + + if( (w = data->weight*amount) + sd->cart_weight > sd->cart_weight_max ) + return 1; + + i = MAX_CART; + if( itemdb_isstackable2(data) && !item_data->expire_time ) + { + ARR_FIND( 0, MAX_CART, i, + 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] && + sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3] ); + }; + + if( i < MAX_CART ) + {// item already in cart, stack it + if( amount > MAX_AMOUNT - sd->status.cart[i].amount || ( data->stack.cart && amount > data->stack.amount - sd->status.cart[i].amount ) ) + return 1; // no room + + sd->status.cart[i].amount+=amount; + clif_cart_additem(sd,i,amount,0); + } + else + {// item not stackable or not present, add it + ARR_FIND( 0, MAX_CART, i, sd->status.cart[i].nameid == 0 ); + if( i == MAX_CART ) + return 1; // no room + + memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0])); + sd->status.cart[i].amount=amount; + sd->cart_num++; + clif_cart_additem(sd,i,amount,0); + } + sd->status.cart[i].favorite = 0;/* clear */ + log_pick_pc(sd, log_type, amount, &sd->status.cart[i]); + + sd->cart_weight += w; + clif_updatestatus(sd,SP_CARTINFO); + + return 0; } /*========================================== * Delete item on cart for given index. * Return: - * 0 = success - * 1 = fail + * 0 = success + * 1 = fail *------------------------------------------*/ int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type) { - nullpo_retr(1, sd); + nullpo_retr(1, sd); - if (sd->status.cart[n].nameid==0 || - sd->status.cart[n].amount<amount) - return 1; + if(sd->status.cart[n].nameid==0 || + sd->status.cart[n].amount<amount) + return 1; - log_pick_pc(sd, log_type, -amount, &sd->status.cart[n]); + log_pick_pc(sd, log_type, -amount, &sd->status.cart[n]); - sd->status.cart[n].amount -= amount; - sd->cart_weight -= itemdb_weight(sd->status.cart[n].nameid)*amount ; - if (sd->status.cart[n].amount <= 0) { - memset(&sd->status.cart[n],0,sizeof(sd->status.cart[0])); - sd->cart_num--; - } - if (!type) { - clif_cart_delitem(sd,n,amount); - clif_updatestatus(sd,SP_CARTINFO); - } + sd->status.cart[n].amount -= amount; + sd->cart_weight -= itemdb_weight(sd->status.cart[n].nameid)*amount ; + if(sd->status.cart[n].amount <= 0){ + memset(&sd->status.cart[n],0,sizeof(sd->status.cart[0])); + sd->cart_num--; + } + if(!type) { + clif_cart_delitem(sd,n,amount); + clif_updatestatus(sd,SP_CARTINFO); + } - return 0; + return 0; } /*========================================== * Transfer item from inventory to cart. * Return: - * 0 = fail - * 1 = succes + * 0 = fail + * 1 = succes *------------------------------------------*/ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount) { - struct item *item_data; + struct item *item_data; - nullpo_ret(sd); + nullpo_ret(sd); - if (idx < 0 || idx >= MAX_INVENTORY) //Invalid index check [Skotlex] - return 1; + if (idx < 0 || idx >= MAX_INVENTORY) //Invalid index check [Skotlex] + return 1; - item_data = &sd->status.inventory[idx]; + item_data = &sd->status.inventory[idx]; - if (item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending) - return 1; + if( item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending ) + return 1; - if (pc_cart_additem(sd,item_data,amount,LOG_TYPE_NONE) == 0) - return pc_delitem(sd,idx,amount,0,5,LOG_TYPE_NONE); + if( pc_cart_additem(sd,item_data,amount,LOG_TYPE_NONE) == 0 ) + return pc_delitem(sd,idx,amount,0,5,LOG_TYPE_NONE); - return 1; + return 1; } /*========================================== @@ -4303,44 +4438,44 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount) -1 = itemid not found or no amount found x = remaining itemid on cart after get *------------------------------------------*/ -int pc_cartitem_amount(struct map_session_data *sd, int idx, int amount) +int pc_cartitem_amount(struct map_session_data* sd, int idx, int amount) { - struct item *item_data; + struct item* item_data; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - item_data = &sd->status.cart[idx]; - if (item_data->nameid == 0 || item_data->amount == 0) - return -1; + item_data = &sd->status.cart[idx]; + if( item_data->nameid == 0 || item_data->amount == 0 ) + return -1; - return item_data->amount - amount; + return item_data->amount - amount; } /*========================================== * Retrieve an item at index idx from cart. * Return: - * 0 = player not found or (FIXME) succes (from pc_cart_delitem) - * 1 = failure + * 0 = player not found or (FIXME) succes (from pc_cart_delitem) + * 1 = failure *------------------------------------------*/ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount) { - struct item *item_data; - int flag; + struct item *item_data; + int flag; - nullpo_ret(sd); + nullpo_ret(sd); - if (idx < 0 || idx >= MAX_CART) //Invalid index check [Skotlex] - return 1; + if (idx < 0 || idx >= MAX_CART) //Invalid index check [Skotlex] + return 1; - item_data=&sd->status.cart[idx]; + item_data=&sd->status.cart[idx]; - if (item_data->nameid==0 || amount < 1 || item_data->amount<amount || sd->state.vending) - return 1; - if ((flag = pc_additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0) - return pc_cart_delitem(sd,idx,amount,0,LOG_TYPE_NONE); + if(item_data->nameid==0 || amount < 1 || item_data->amount<amount || sd->state.vending ) + return 1; + if((flag = pc_additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0) + return pc_cart_delitem(sd,idx,amount,0,LOG_TYPE_NONE); - clif_additem(sd,0,0,flag); - return 1; + clif_additem(sd,0,0,flag); + return 1; } /*========================================== @@ -4348,136 +4483,137 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount) *------------------------------------------*/ int pc_show_steal(struct block_list *bl,va_list ap) { - struct map_session_data *sd; - int itemid; + struct map_session_data *sd; + int itemid; - struct item_data *item=NULL; - char output[100]; + struct item_data *item=NULL; + char output[100]; - sd=va_arg(ap,struct map_session_data *); - itemid=va_arg(ap,int); + sd=va_arg(ap,struct map_session_data *); + itemid=va_arg(ap,int); - if ((item=itemdb_exists(itemid))==NULL) - sprintf(output,"%s stole an Unknown Item (id: %i).",sd->status.name, itemid); - else - sprintf(output,"%s stole %s.",sd->status.name,item->jname); - clif_displaymessage(((struct map_session_data *)bl)->fd, output); + if((item=itemdb_exists(itemid))==NULL) + sprintf(output,"%s stole an Unknown Item (id: %i).",sd->status.name, itemid); + else + sprintf(output,"%s stole %s.",sd->status.name,item->jname); + clif_displaymessage( ((struct map_session_data *)bl)->fd, output); - return 0; + return 0; } /*========================================== * Steal an item from bl (mob). * Return: - * 0 = fail - * 1 = succes + * 0 = fail + * 1 = succes *------------------------------------------*/ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, int lv) { - int i,itemid,flag; - double rate; - struct status_data *sd_status, *md_status; - struct mob_data *md; - struct item tmp_item; - - if (!sd || !bl || bl->type!=BL_MOB) - return 0; - - md = (TBL_MOB *)bl; - - if (md->state.steal_flag == UCHAR_MAX || (md->sc.opt1 && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE)) //already stolen from / status change check - return 0; - - sd_status= status_get_status_data(&sd->bl); - md_status= status_get_status_data(bl); - - if (md->master_id || md_status->mode&MD_BOSS || mob_is_treasure(md) || - map[bl->m].flag.nomobloot || // check noloot map flag [Lorky] - (battle_config.skill_steal_max_tries && //Reached limit of steal attempts. [Lupus] - md->state.steal_flag++ >= battle_config.skill_steal_max_tries) - ) { //Can't steal from - md->state.steal_flag = UCHAR_MAX; - return 0; - } - - // base skill success chance (percentual) - rate = (sd_status->dex - md_status->dex)/2 + lv*6 + 4; - rate += sd->bonus.add_steal_rate; - - if (rate < 1) - return 0; - - // Try dropping one item, in the order from first to last possible slot. - // Droprate is affected by the skill success rate. - for (i = 0; i < MAX_STEAL_DROP; i++) - if (md->db->dropitem[i].nameid > 0 && itemdb_exists(md->db->dropitem[i].nameid) && rnd() % 10000 < md->db->dropitem[i].p * rate/100.) - break; - if (i == MAX_STEAL_DROP) - return 0; - - itemid = md->db->dropitem[i].nameid; - memset(&tmp_item,0,sizeof(tmp_item)); - tmp_item.nameid = itemid; - tmp_item.amount = 1; - tmp_item.identify = itemdb_isidentified(itemid); - flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER); - - //TODO: Should we disable stealing when the item you stole couldn't be added to your inventory? Perhaps players will figure out a way to exploit this behaviour otherwise? - md->state.steal_flag = UCHAR_MAX; //you can't steal from this mob any more - - if (flag) { //Failed to steal due to overweight - clif_additem(sd,0,0,flag); - return 0; - } - - if (battle_config.show_steal_in_same_party) - party_foreachsamemap(pc_show_steal,sd,AREA_SIZE,sd,tmp_item.nameid); - - //Logs items, Stolen from mobs [Lupus] - log_pick_mob(md, LOG_TYPE_STEAL, -1, &tmp_item); - - //A Rare Steal Global Announce by Lupus - if (md->db->dropitem[i].p<=battle_config.rare_drop_announce) { - struct item_data *i_data; - char message[128]; - i_data = itemdb_search(itemid); - sprintf(message, msg_txt(542), (sd->status.name != NULL)?sd->status.name :"GM", md->db->jname, i_data->jname, (float)md->db->dropitem[i].p/100); - //MSG: "'%s' stole %s's %s (chance: %0.02f%%)" - intif_broadcast(message,strlen(message)+1,0); - } - return 1; + int i,itemid,flag; + double rate; + struct status_data *sd_status, *md_status; + struct mob_data *md; + struct item tmp_item; + + if(!sd || !bl || bl->type!=BL_MOB) + return 0; + + md = (TBL_MOB *)bl; + + if(md->state.steal_flag == UCHAR_MAX || ( md->sc.opt1 && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE ) ) //already stolen from / status change check + return 0; + + sd_status= status_get_status_data(&sd->bl); + md_status= status_get_status_data(bl); + + if( md->master_id || md_status->mode&MD_BOSS || mob_is_treasure(md) || + map[bl->m].flag.nomobloot || // check noloot map flag [Lorky] + (battle_config.skill_steal_max_tries && //Reached limit of steal attempts. [Lupus] + md->state.steal_flag++ >= battle_config.skill_steal_max_tries) + ) { //Can't steal from + md->state.steal_flag = UCHAR_MAX; + return 0; + } + + // base skill success chance (percentual) + rate = (sd_status->dex - md_status->dex)/2 + lv*6 + 4; + rate += sd->bonus.add_steal_rate; + + if( rate < 1 ) + return 0; + + // Try dropping one item, in the order from first to last possible slot. + // Droprate is affected by the skill success rate. + for( i = 0; i < MAX_STEAL_DROP; i++ ) + if( md->db->dropitem[i].nameid > 0 && itemdb_exists(md->db->dropitem[i].nameid) && rnd() % 10000 < md->db->dropitem[i].p * rate/100. ) + break; + if( i == MAX_STEAL_DROP ) + return 0; + + itemid = md->db->dropitem[i].nameid; + memset(&tmp_item,0,sizeof(tmp_item)); + tmp_item.nameid = itemid; + tmp_item.amount = 1; + tmp_item.identify = itemdb_isidentified(itemid); + flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER); + + //TODO: Should we disable stealing when the item you stole couldn't be added to your inventory? Perhaps players will figure out a way to exploit this behaviour otherwise? + md->state.steal_flag = UCHAR_MAX; //you can't steal from this mob any more + + if(flag) { //Failed to steal due to overweight + clif_additem(sd,0,0,flag); + return 0; + } + + if(battle_config.show_steal_in_same_party) + party_foreachsamemap(pc_show_steal,sd,AREA_SIZE,sd,tmp_item.nameid); + + //Logs items, Stolen from mobs [Lupus] + log_pick_mob(md, LOG_TYPE_STEAL, -1, &tmp_item); + + //A Rare Steal Global Announce by Lupus + if(md->db->dropitem[i].p<=battle_config.rare_drop_announce) { + struct item_data *i_data; + char message[128]; + i_data = itemdb_search(itemid); + sprintf (message, msg_txt(542), (sd->status.name != NULL)?sd->status.name :"GM", md->db->jname, i_data->jname, (float)md->db->dropitem[i].p/100); + //MSG: "'%s' stole %s's %s (chance: %0.02f%%)" + intif_broadcast(message,strlen(message)+1,0); + } + return 1; } /*========================================== * Stole zeny from bl (mob) * return - * 0 = fail - * 1 = success + * 0 = fail + * 1 = success *------------------------------------------*/ int pc_steal_coin(struct map_session_data *sd,struct block_list *target) { - int rate,skill; - struct mob_data *md; - if (!sd || !target || target->type != BL_MOB) - return 0; + int rate,skill; + struct mob_data *md; + if(!sd || !target || target->type != BL_MOB) + return 0; - md = (TBL_MOB *)target; - if (md->state.steal_coin_flag || md->sc.data[SC_STONE] || md->sc.data[SC_FREEZE] || md->status.mode&MD_BOSS) - return 0; + md = (TBL_MOB*)target; + if( md->state.steal_coin_flag || md->sc.data[SC_STONE] || md->sc.data[SC_FREEZE] || md->status.mode&MD_BOSS ) + return 0; - if (mob_is_treasure(md)) - return 0; + if( mob_is_treasure(md) ) + return 0; - // FIXME: This formula is either custom or outdated. - skill = pc_checkskill(sd,RG_STEALCOIN)*10; - rate = skill + (sd->status.base_level - md->level)*3 + sd->battle_status.dex*2 + sd->battle_status.luk*2; - if (rnd()%1000 < rate) { - int amount = md->level*10 + rnd()%100; + // FIXME: This formula is either custom or outdated. + skill = pc_checkskill(sd,RG_STEALCOIN)*10; + rate = skill + (sd->status.base_level - md->level)*3 + sd->battle_status.dex*2 + sd->battle_status.luk*2; + if(rnd()%1000 < rate) + { + int amount = md->level*10 + rnd()%100; - pc_getzeny(sd, amount, LOG_TYPE_STEAL, NULL); - md->state.steal_coin_flag = 1; - return 1; - } - return 0; + pc_getzeny(sd, amount, LOG_TYPE_STEAL, NULL); + md->state.steal_coin_flag = 1; + return 1; + } + return 0; } /*========================================== @@ -4487,242 +4623,250 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target) * 1 - Invalid map index. * 2 - Map not in this map-server, and failed to locate alternate map-server. *------------------------------------------*/ -int pc_setpos(struct map_session_data *sd, unsigned short mapindex, int x, int y, clr_type clrtype) -{ - struct party_data *p; - int m; - - nullpo_ret(sd); - - if (!mapindex || !mapindex_id2name(mapindex)) { - ShowDebug("pc_setpos: Passed mapindex(%d) is invalid!\n", mapindex); - return 1; - } - - if (pc_isdead(sd)) { - //Revive dead people before warping them - pc_setstand(sd); - pc_setrestartvalue(sd,1); - } - - m = map_mapindex2mapid(mapindex); - if (map[m].flag.src4instance && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id) { - // Request the mapid of this src map into the instance of the party - int im = instance_map2imap(m, p->instance_id); - if (im < 0) - ; // Player will enter the src map for instances - else { - // Changes destiny to the instance map, not the source map - m = im; - mapindex = map_id2index(m); - } - } - - sd->state.changemap = (sd->mapindex != mapindex); - sd->state.warping = 1; - if (sd->state.changemap) { // Misc map-changing settings - int i; - sd->state.pmap = sd->bl.m; - if (sd->sc.count) { // Cancel some map related stuff. - if (sd->sc.data[SC_JAILED]) - return 1; //You may not get out! - status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER); - status_change_end(&sd->bl, SC_WARM, INVALID_TIMER); - status_change_end(&sd->bl, SC_SUN_COMFORT, INVALID_TIMER); - status_change_end(&sd->bl, SC_MOON_COMFORT, INVALID_TIMER); - status_change_end(&sd->bl, SC_STAR_COMFORT, INVALID_TIMER); - status_change_end(&sd->bl, SC_MIRACLE, INVALID_TIMER); - if (sd->sc.data[SC_KNOWLEDGE]) { - struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE]; - if (sce->timer != INVALID_TIMER) - delete_timer(sce->timer, status_change_timer); - sce->timer = add_timer(gettick() + skill_get_time(SG_KNOWLEDGE, sce->val1), status_change_timer, sd->bl.id, SC_KNOWLEDGE); - } - status_change_end(&sd->bl, SC_PROPERTYWALK, INVALID_TIMER); - status_change_end(&sd->bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(&sd->bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - } - for (i = 0; i < EQI_MAX; i++) { - if (sd->equip_index[ i ] >= 0) - if (!pc_isequip(sd , sd->equip_index[ i ])) - pc_unequipitem(sd , sd->equip_index[ i ] , 2); - } - if (battle_config.clear_unit_onwarp&BL_PC) - skill_clear_unitgroup(&sd->bl); - party_send_dot_remove(sd); //minimap dot fix [Kevin] - guild_send_dot_remove(sd); - bg_send_dot_remove(sd); - if (sd->regen.state.gc) - sd->regen.state.gc = 0; - // make sure vending is allowed here - if (sd->state.vending && map[m].flag.novending) { - clif_displaymessage(sd->fd, msg_txt(276)); // "You can't open a shop on this map" - vending_closevending(sd); - } - } - - if (m < 0) { - uint32 ip; - uint16 port; - //if can't find any map-servers, just abort setting position. - if (!sd->mapindex || map_mapname2ipport(mapindex,&ip,&port)) - return 2; - - if (sd->npc_id) - npc_event_dequeue(sd); - npc_script_event(sd, NPCE_LOGOUT); - //remove from map, THEN change x/y coordinates - unit_remove_map_pc(sd,clrtype); - sd->mapindex = mapindex; - sd->bl.x=x; - sd->bl.y=y; - pc_clean_skilltree(sd); - chrif_save(sd,2); - chrif_changemapserver(sd, ip, (short)port); - - //Free session data from this map server [Kevin] - unit_free_pc(sd); - - return 0; - } - - if (x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys) { - ShowError("pc_setpos: attempt to place player %s (%d:%d) on invalid coordinates (%s-%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(mapindex),x,y); - x = y = 0; // make it random - } - - if (x == 0 && y == 0) { - // pick a random walkable cell - do { - x=rnd()%(map[m].xs-2)+1; - y=rnd()%(map[m].ys-2)+1; - } while (map_getcell(m,x,y,CELL_CHKNOPASS)); - } - - if (sd->state.vending && map_getcell(m,x,y,CELL_CHKNOVENDING)) { - clif_displaymessage(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." - vending_closevending(sd); - } - - if (sd->bl.prev != NULL) { - unit_remove_map_pc(sd,clrtype); - clif_changemap(sd,map[m].index,x,y); // [MouseJstr] - } else if (sd->state.active) - //Tag player for rewarping after map-loading is done. [Skotlex] - sd->state.rewarp = 1; - - sd->mapindex = mapindex; - sd->bl.m = m; - sd->bl.x = sd->ud.to_x = x; - sd->bl.y = sd->ud.to_y = y; - - if (sd->status.guild_id > 0 && map[m].flag.gvg_castle) { - // Increased guild castle regen [Valaris] - struct guild_castle *gc = guild_mapindex2gc(sd->mapindex); - if (gc && gc->guild_id == sd->status.guild_id) - sd->regen.state.gc = 1; - } - - if (sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0) { - sd->pd->bl.m = m; - sd->pd->bl.x = sd->pd->ud.to_x = x; - sd->pd->bl.y = sd->pd->ud.to_y = y; - sd->pd->ud.dir = sd->ud.dir; - } - - if (merc_is_hom_active(sd->hd)) { - sd->hd->bl.m = m; - sd->hd->bl.x = sd->hd->ud.to_x = x; - sd->hd->bl.y = sd->hd->ud.to_y = y; - sd->hd->ud.dir = sd->ud.dir; - } - - if (sd->md) { - sd->md->bl.m = m; - sd->md->bl.x = sd->md->ud.to_x = x; - sd->md->bl.y = sd->md->ud.to_y = y; - sd->md->ud.dir = sd->ud.dir; - } - - return 0; +int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype) +{ + struct party_data *p; + int m; + + nullpo_ret(sd); + + if( !mapindex || !mapindex_id2name(mapindex) ) + { + ShowDebug("pc_setpos: Passed mapindex(%d) is invalid!\n", mapindex); + return 1; + } + + if( pc_isdead(sd) ) + { //Revive dead people before warping them + pc_setstand(sd); + pc_setrestartvalue(sd,1); + } + + m = map_mapindex2mapid(mapindex); + if( map[m].flag.src4instance && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) + { + // Request the mapid of this src map into the instance of the party + int im = instance_map2imap(m, p->instance_id); + if( im < 0 ) + ; // Player will enter the src map for instances + else + { // Changes destiny to the instance map, not the source map + m = im; + mapindex = map_id2index(m); + } + } + + sd->state.changemap = (sd->mapindex != mapindex); + sd->state.warping = 1; + if( sd->state.changemap ) { // Misc map-changing settings + int i; + sd->state.pmap = sd->bl.m; + if (sd->sc.count) { // Cancel some map related stuff. + if (sd->sc.data[SC_JAILED]) + return 1; //You may not get out! + status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER); + status_change_end(&sd->bl, SC_WARM, INVALID_TIMER); + status_change_end(&sd->bl, SC_SUN_COMFORT, INVALID_TIMER); + status_change_end(&sd->bl, SC_MOON_COMFORT, INVALID_TIMER); + status_change_end(&sd->bl, SC_STAR_COMFORT, INVALID_TIMER); + status_change_end(&sd->bl, SC_MIRACLE, INVALID_TIMER); + if (sd->sc.data[SC_KNOWLEDGE]) { + struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE]; + if (sce->timer != INVALID_TIMER) + delete_timer(sce->timer, status_change_timer); + sce->timer = add_timer(gettick() + skill_get_time(SG_KNOWLEDGE, sce->val1), status_change_timer, sd->bl.id, SC_KNOWLEDGE); + } + status_change_end(&sd->bl, SC_PROPERTYWALK, INVALID_TIMER); + status_change_end(&sd->bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(&sd->bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + } + for( i = 0; i < EQI_MAX; i++ ) { + if( sd->equip_index[ i ] >= 0 ) + if( !pc_isequip( sd , sd->equip_index[ i ] ) ) + pc_unequipitem( sd , sd->equip_index[ i ] , 2 ); + } + if (battle_config.clear_unit_onwarp&BL_PC) + skill_clear_unitgroup(&sd->bl); + party_send_dot_remove(sd); //minimap dot fix [Kevin] + guild_send_dot_remove(sd); + bg_send_dot_remove(sd); + if (sd->regen.state.gc) + sd->regen.state.gc = 0; + // make sure vending is allowed here + if (sd->state.vending && map[m].flag.novending) { + clif_displaymessage (sd->fd, msg_txt(276)); // "You can't open a shop on this map" + vending_closevending(sd); + } + } + + if( m < 0 ) + { + uint32 ip; + uint16 port; + //if can't find any map-servers, just abort setting position. + if(!sd->mapindex || map_mapname2ipport(mapindex,&ip,&port)) + return 2; + + if (sd->npc_id) + npc_event_dequeue(sd); + npc_script_event(sd, NPCE_LOGOUT); + //remove from map, THEN change x/y coordinates + unit_remove_map_pc(sd,clrtype); + sd->mapindex = mapindex; + sd->bl.x=x; + sd->bl.y=y; + pc_clean_skilltree(sd); + chrif_save(sd,2); + chrif_changemapserver(sd, ip, (short)port); + + //Free session data from this map server [Kevin] + unit_free_pc(sd); + + return 0; + } + + if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) + { + ShowError("pc_setpos: attempt to place player %s (%d:%d) on invalid coordinates (%s-%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(mapindex),x,y); + x = y = 0; // make it random + } + + if( x == 0 && y == 0 ) + {// pick a random walkable cell + do { + x=rnd()%(map[m].xs-2)+1; + y=rnd()%(map[m].ys-2)+1; + } while(map_getcell(m,x,y,CELL_CHKNOPASS)); + } + + if (sd->state.vending && map_getcell(m,x,y,CELL_CHKNOVENDING)) { + clif_displaymessage (sd->fd, msg_txt(204)); // "You can't open a shop on this cell." + vending_closevending(sd); + } + + if(sd->bl.prev != NULL){ + unit_remove_map_pc(sd,clrtype); + clif_changemap(sd,map[m].index,x,y); // [MouseJstr] + } else if(sd->state.active) + //Tag player for rewarping after map-loading is done. [Skotlex] + sd->state.rewarp = 1; + + sd->mapindex = mapindex; + sd->bl.m = m; + sd->bl.x = sd->ud.to_x = x; + sd->bl.y = sd->ud.to_y = y; + + if( sd->status.guild_id > 0 && map[m].flag.gvg_castle ) + { // Increased guild castle regen [Valaris] + struct guild_castle *gc = guild_mapindex2gc(sd->mapindex); + if(gc && gc->guild_id == sd->status.guild_id) + sd->regen.state.gc = 1; + } + + if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 ) + { + sd->pd->bl.m = m; + sd->pd->bl.x = sd->pd->ud.to_x = x; + sd->pd->bl.y = sd->pd->ud.to_y = y; + sd->pd->ud.dir = sd->ud.dir; + } + + if( merc_is_hom_active(sd->hd) ) + { + sd->hd->bl.m = m; + sd->hd->bl.x = sd->hd->ud.to_x = x; + sd->hd->bl.y = sd->hd->ud.to_y = y; + sd->hd->ud.dir = sd->ud.dir; + } + + if( sd->md ) + { + sd->md->bl.m = m; + sd->md->bl.x = sd->md->ud.to_x = x; + sd->md->bl.y = sd->md->ud.to_y = y; + sd->md->ud.dir = sd->ud.dir; + } + + return 0; } /*========================================== * Warp player sd to random location on current map. * May fail if no walkable cell found (1000 attempts). * Return: - * 0 = fail or FIXME success (from pc_setpos) - * x(1|2) = fail + * 0 = fail or FIXME success (from pc_setpos) + * x(1|2) = fail *------------------------------------------*/ int pc_randomwarp(struct map_session_data *sd, clr_type type) { - int x,y,i=0; - int m; + int x,y,i=0; + int m; - nullpo_ret(sd); + nullpo_ret(sd); - m=sd->bl.m; + m=sd->bl.m; - if (map[sd->bl.m].flag.noteleport) //Teleport forbidden - return 0; + if (map[sd->bl.m].flag.noteleport) //Teleport forbidden + return 0; - do { - x=rnd()%(map[m].xs-2)+1; - y=rnd()%(map[m].ys-2)+1; - } while (map_getcell(m,x,y,CELL_CHKNOPASS) && (i++)<1000); + do{ + x=rnd()%(map[m].xs-2)+1; + y=rnd()%(map[m].ys-2)+1; + }while(map_getcell(m,x,y,CELL_CHKNOPASS) && (i++)<1000 ); - if (i < 1000) - return pc_setpos(sd,map[sd->bl.m].index,x,y,type); + if (i < 1000) + return pc_setpos(sd,map[sd->bl.m].index,x,y,type); - return 0; + return 0; } /*========================================== * Records a memo point at sd's current position * pos - entry to replace, (-1: shift oldest entry out) *------------------------------------------*/ -int pc_memo(struct map_session_data *sd, int pos) +int pc_memo(struct map_session_data* sd, int pos) { - int skill; + int skill; - nullpo_ret(sd); + nullpo_ret(sd); - // check mapflags - if (sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_skill_teleportmessage(sd, 1); // "Saved point cannot be memorized." - return 0; - } + // check mapflags + if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) { + clif_skill_teleportmessage(sd, 1); // "Saved point cannot be memorized." + return 0; + } - // check inputs - if (pos < -1 || pos >= MAX_MEMOPOINTS) - return 0; // invalid input + // check inputs + if( pos < -1 || pos >= MAX_MEMOPOINTS ) + return 0; // invalid input - // check required skill level - skill = pc_checkskill(sd, AL_WARP); - if (skill < 1) { - clif_skill_memomessage(sd,2); // "You haven't learned Warp." - return 0; - } - if (skill < 2 || skill - 2 < pos) { - clif_skill_memomessage(sd,1); // "Skill Level is not high enough." - return 0; - } + // check required skill level + skill = pc_checkskill(sd, AL_WARP); + if( skill < 1 ) { + clif_skill_memomessage(sd,2); // "You haven't learned Warp." + return 0; + } + if( skill < 2 || skill - 2 < pos ) { + clif_skill_memomessage(sd,1); // "Skill Level is not high enough." + return 0; + } - if (pos == -1) { - int i; - // prevent memo-ing the same map multiple times - ARR_FIND(0, MAX_MEMOPOINTS, i, sd->status.memo_point[i].map == map_id2index(sd->bl.m)); - memmove(&sd->status.memo_point[1], &sd->status.memo_point[0], (min(i,MAX_MEMOPOINTS-1))*sizeof(struct point)); - pos = 0; - } + if( pos == -1 ) + { + int i; + // prevent memo-ing the same map multiple times + ARR_FIND( 0, MAX_MEMOPOINTS, i, sd->status.memo_point[i].map == map_id2index(sd->bl.m) ); + memmove(&sd->status.memo_point[1], &sd->status.memo_point[0], (min(i,MAX_MEMOPOINTS-1))*sizeof(struct point)); + pos = 0; + } - sd->status.memo_point[pos].map = map_id2index(sd->bl.m); - sd->status.memo_point[pos].x = sd->bl.x; - sd->status.memo_point[pos].y = sd->bl.y; + sd->status.memo_point[pos].map = map_id2index(sd->bl.m); + sd->status.memo_point[pos].x = sd->bl.x; + sd->status.memo_point[pos].y = sd->bl.y; - clif_skill_memomessage(sd, 0); + clif_skill_memomessage(sd, 0); - return 1; + return 1; } // @@ -4733,75 +4877,78 @@ int pc_memo(struct map_session_data *sd, int pos) *------------------------------------------*/ int pc_checkskill(struct map_session_data *sd,int skill_id) { - if (sd == NULL) return 0; - if (skill_id >= GD_SKILLBASE && skill_id < GD_MAX) { - struct guild *g; + if(sd == NULL) return 0; + if( skill_id >= GD_SKILLBASE && skill_id < GD_MAX ) + { + struct guild *g; - if (sd->status.guild_id>0 && (g=guild_search(sd->status.guild_id))!=NULL) - return guild_checkskill(g,skill_id); - return 0; - } else if (skill_id < 0 || skill_id >= ARRAYLENGTH(sd->status.skill)) { - ShowError("pc_checkskill: Invalid skill id %d (char_id=%d).\n", skill_id, sd->status.char_id); - return 0; - } + if( sd->status.guild_id>0 && (g=guild_search(sd->status.guild_id))!=NULL) + return guild_checkskill(g,skill_id); + return 0; + } + else if( skill_id < 0 || skill_id >= ARRAYLENGTH(sd->status.skill) ) + { + ShowError("pc_checkskill: Invalid skill id %d (char_id=%d).\n", skill_id, sd->status.char_id); + return 0; + } - if (sd->status.skill[skill_id].id == skill_id) - return (sd->status.skill[skill_id].lv); + if(sd->status.skill[skill_id].id == skill_id) + return (sd->status.skill[skill_id].lv); - return 0; + return 0; } /*========================================== * Chk if we still have the correct weapon to continue the skill (actually status) * If not ending it * Return - * 0 - No status found or all done + * 0 - No status found or all done *------------------------------------------*/ int pc_checkallowskill(struct map_session_data *sd) { - const enum sc_type scw_list[] = { - SC_TWOHANDQUICKEN, - SC_ONEHAND, - SC_AURABLADE, - SC_PARRYING, - SC_SPEARQUICKEN, - SC_ADRENALINE, - SC_ADRENALINE2, - SC_DANCING, - SC_GATLINGFEVER, - SC_FEARBREEZE - }; - const enum sc_type scs_list[] = { - SC_AUTOGUARD, - SC_DEFENDER, - SC_REFLECTSHIELD, - SC_REFLECTDAMAGE - }; - int i; - nullpo_ret(sd); - - if (!sd->sc.count) - return 0; - - for (i = 0; i < ARRAYLENGTH(scw_list); i++) { - // Skills requiring specific weapon types - if (scw_list[i] == SC_DANCING && !battle_config.dancing_weaponswitch_fix) - continue; - if (sd->sc.data[scw_list[i]] && - !pc_check_weapontype(sd,skill_get_weapontype(status_sc2skill(scw_list[i])))) - status_change_end(&sd->bl, scw_list[i], INVALID_TIMER); - } - - if (sd->sc.data[SC_SPURT] && sd->status.weapon) - // Spurt requires bare hands (feet, in fact xD) - status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER); - - if (sd->status.shield <= 0) { // Skills requiring a shield - for (i = 0; i < ARRAYLENGTH(scs_list); i++) - if (sd->sc.data[scs_list[i]]) - status_change_end(&sd->bl, scs_list[i], INVALID_TIMER); - } - return 0; + const enum sc_type scw_list[] = { + SC_TWOHANDQUICKEN, + SC_ONEHAND, + SC_AURABLADE, + SC_PARRYING, + SC_SPEARQUICKEN, + SC_ADRENALINE, + SC_ADRENALINE2, + SC_DANCING, + SC_GATLINGFEVER, + SC_FEARBREEZE + }; + const enum sc_type scs_list[] = { + SC_AUTOGUARD, + SC_DEFENDER, + SC_REFLECTSHIELD, + SC_REFLECTDAMAGE + }; + int i; + nullpo_ret(sd); + + if(!sd->sc.count) + return 0; + + for (i = 0; i < ARRAYLENGTH(scw_list); i++) + { // Skills requiring specific weapon types + if( scw_list[i] == SC_DANCING && !battle_config.dancing_weaponswitch_fix ) + continue; + if(sd->sc.data[scw_list[i]] && + !pc_check_weapontype(sd,skill_get_weapontype(status_sc2skill(scw_list[i])))) + status_change_end(&sd->bl, scw_list[i], INVALID_TIMER); + } + + if(sd->sc.data[SC_SPURT] && sd->status.weapon) + // Spurt requires bare hands (feet, in fact xD) + status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER); + + if(sd->status.shield <= 0) { // Skills requiring a shield + for (i = 0; i < ARRAYLENGTH(scs_list); i++) + if(sd->sc.data[scs_list[i]]) + status_change_end(&sd->bl, scs_list[i], INVALID_TIMER); + } + return 0; } /*========================================== @@ -4812,16 +4959,16 @@ int pc_checkallowskill(struct map_session_data *sd) *------------------------------------------*/ int pc_checkequip(struct map_session_data *sd,int pos) { - int i; + int i; - nullpo_retr(-1, sd); + nullpo_retr(-1, sd); - for (i=0; i<EQI_MAX; i++) { - if (pos & equip_pos[i]) - return sd->equip_index[i]; - } + for(i=0;i<EQI_MAX;i++){ + if(pos & equip_pos[i]) + return sd->equip_index[i]; + } - return -1; + return -1; } /*========================================== @@ -4830,871 +4977,655 @@ int pc_checkequip(struct map_session_data *sd,int pos) *------------------------------------------*/ int pc_jobid2mapid(unsigned short b_class) { - switch (b_class) { - //Novice And 1-1 Jobs - case JOB_NOVICE: - return MAPID_NOVICE; - case JOB_SWORDMAN: - return MAPID_SWORDMAN; - case JOB_MAGE: - return MAPID_MAGE; - case JOB_ARCHER: - return MAPID_ARCHER; - case JOB_ACOLYTE: - return MAPID_ACOLYTE; - case JOB_MERCHANT: - return MAPID_MERCHANT; - case JOB_THIEF: - return MAPID_THIEF; - case JOB_TAEKWON: - return MAPID_TAEKWON; - case JOB_WEDDING: - return MAPID_WEDDING; - case JOB_GUNSLINGER: - return MAPID_GUNSLINGER; - case JOB_NINJA: - return MAPID_NINJA; - case JOB_XMAS: - return MAPID_XMAS; - case JOB_SUMMER: - return MAPID_SUMMER; - case JOB_GANGSI: - return MAPID_GANGSI; - //2-1 Jobs - case JOB_SUPER_NOVICE: - return MAPID_SUPER_NOVICE; - case JOB_KNIGHT: - return MAPID_KNIGHT; - case JOB_WIZARD: - return MAPID_WIZARD; - case JOB_HUNTER: - return MAPID_HUNTER; - case JOB_PRIEST: - return MAPID_PRIEST; - case JOB_BLACKSMITH: - return MAPID_BLACKSMITH; - case JOB_ASSASSIN: - return MAPID_ASSASSIN; - case JOB_STAR_GLADIATOR: - return MAPID_STAR_GLADIATOR; - case JOB_KAGEROU: - case JOB_OBORO: - return MAPID_KAGEROUOBORO; - case JOB_DEATH_KNIGHT: - return MAPID_DEATH_KNIGHT; - //2-2 Jobs - case JOB_CRUSADER: - return MAPID_CRUSADER; - case JOB_SAGE: - return MAPID_SAGE; - case JOB_BARD: - case JOB_DANCER: - return MAPID_BARDDANCER; - case JOB_MONK: - return MAPID_MONK; - case JOB_ALCHEMIST: - return MAPID_ALCHEMIST; - case JOB_ROGUE: - return MAPID_ROGUE; - case JOB_SOUL_LINKER: - return MAPID_SOUL_LINKER; - case JOB_DARK_COLLECTOR: - return MAPID_DARK_COLLECTOR; - //Trans Novice And Trans 1-1 Jobs - case JOB_NOVICE_HIGH: - return MAPID_NOVICE_HIGH; - case JOB_SWORDMAN_HIGH: - return MAPID_SWORDMAN_HIGH; - case JOB_MAGE_HIGH: - return MAPID_MAGE_HIGH; - case JOB_ARCHER_HIGH: - return MAPID_ARCHER_HIGH; - case JOB_ACOLYTE_HIGH: - return MAPID_ACOLYTE_HIGH; - case JOB_MERCHANT_HIGH: - return MAPID_MERCHANT_HIGH; - case JOB_THIEF_HIGH: - return MAPID_THIEF_HIGH; - //Trans 2-1 Jobs - case JOB_LORD_KNIGHT: - return MAPID_LORD_KNIGHT; - case JOB_HIGH_WIZARD: - return MAPID_HIGH_WIZARD; - case JOB_SNIPER: - return MAPID_SNIPER; - case JOB_HIGH_PRIEST: - return MAPID_HIGH_PRIEST; - case JOB_WHITESMITH: - return MAPID_WHITESMITH; - case JOB_ASSASSIN_CROSS: - return MAPID_ASSASSIN_CROSS; - //Trans 2-2 Jobs - case JOB_PALADIN: - return MAPID_PALADIN; - case JOB_PROFESSOR: - return MAPID_PROFESSOR; - case JOB_CLOWN: - case JOB_GYPSY: - return MAPID_CLOWNGYPSY; - case JOB_CHAMPION: - return MAPID_CHAMPION; - case JOB_CREATOR: - return MAPID_CREATOR; - case JOB_STALKER: - return MAPID_STALKER; - //Baby Novice And Baby 1-1 Jobs - case JOB_BABY: - return MAPID_BABY; - case JOB_BABY_SWORDMAN: - return MAPID_BABY_SWORDMAN; - case JOB_BABY_MAGE: - return MAPID_BABY_MAGE; - case JOB_BABY_ARCHER: - return MAPID_BABY_ARCHER; - case JOB_BABY_ACOLYTE: - return MAPID_BABY_ACOLYTE; - case JOB_BABY_MERCHANT: - return MAPID_BABY_MERCHANT; - case JOB_BABY_THIEF: - return MAPID_BABY_THIEF; - //Baby 2-1 Jobs - case JOB_SUPER_BABY: - return MAPID_SUPER_BABY; - case JOB_BABY_KNIGHT: - return MAPID_BABY_KNIGHT; - case JOB_BABY_WIZARD: - return MAPID_BABY_WIZARD; - case JOB_BABY_HUNTER: - return MAPID_BABY_HUNTER; - case JOB_BABY_PRIEST: - return MAPID_BABY_PRIEST; - case JOB_BABY_BLACKSMITH: - return MAPID_BABY_BLACKSMITH; - case JOB_BABY_ASSASSIN: - return MAPID_BABY_ASSASSIN; - //Baby 2-2 Jobs - case JOB_BABY_CRUSADER: - return MAPID_BABY_CRUSADER; - case JOB_BABY_SAGE: - return MAPID_BABY_SAGE; - case JOB_BABY_BARD: - case JOB_BABY_DANCER: - return MAPID_BABY_BARDDANCER; - case JOB_BABY_MONK: - return MAPID_BABY_MONK; - case JOB_BABY_ALCHEMIST: - return MAPID_BABY_ALCHEMIST; - case JOB_BABY_ROGUE: - return MAPID_BABY_ROGUE; - //3-1 Jobs - case JOB_SUPER_NOVICE_E: - return MAPID_SUPER_NOVICE_E; - case JOB_RUNE_KNIGHT: - return MAPID_RUNE_KNIGHT; - case JOB_WARLOCK: - return MAPID_WARLOCK; - case JOB_RANGER: - return MAPID_RANGER; - case JOB_ARCH_BISHOP: - return MAPID_ARCH_BISHOP; - case JOB_MECHANIC: - return MAPID_MECHANIC; - case JOB_GUILLOTINE_CROSS: - return MAPID_GUILLOTINE_CROSS; - //3-2 Jobs - case JOB_ROYAL_GUARD: - return MAPID_ROYAL_GUARD; - case JOB_SORCERER: - return MAPID_SORCERER; - case JOB_MINSTREL: - case JOB_WANDERER: - return MAPID_MINSTRELWANDERER; - case JOB_SURA: - return MAPID_SURA; - case JOB_GENETIC: - return MAPID_GENETIC; - case JOB_SHADOW_CHASER: - return MAPID_SHADOW_CHASER; - //Trans 3-1 Jobs - case JOB_RUNE_KNIGHT_T: - return MAPID_RUNE_KNIGHT_T; - case JOB_WARLOCK_T: - return MAPID_WARLOCK_T; - case JOB_RANGER_T: - return MAPID_RANGER_T; - case JOB_ARCH_BISHOP_T: - return MAPID_ARCH_BISHOP_T; - case JOB_MECHANIC_T: - return MAPID_MECHANIC_T; - case JOB_GUILLOTINE_CROSS_T: - return MAPID_GUILLOTINE_CROSS_T; - //Trans 3-2 Jobs - case JOB_ROYAL_GUARD_T: - return MAPID_ROYAL_GUARD_T; - case JOB_SORCERER_T: - return MAPID_SORCERER_T; - case JOB_MINSTREL_T: - case JOB_WANDERER_T: - return MAPID_MINSTRELWANDERER_T; - case JOB_SURA_T: - return MAPID_SURA_T; - case JOB_GENETIC_T: - return MAPID_GENETIC_T; - case JOB_SHADOW_CHASER_T: - return MAPID_SHADOW_CHASER_T; - //Baby 3-1 Jobs - case JOB_SUPER_BABY_E: - return MAPID_SUPER_BABY_E; - case JOB_BABY_RUNE: - return MAPID_BABY_RUNE; - case JOB_BABY_WARLOCK: - return MAPID_BABY_WARLOCK; - case JOB_BABY_RANGER: - return MAPID_BABY_RANGER; - case JOB_BABY_BISHOP: - return MAPID_BABY_BISHOP; - case JOB_BABY_MECHANIC: - return MAPID_BABY_MECHANIC; - case JOB_BABY_CROSS: - return MAPID_BABY_CROSS; - //Baby 3-2 Jobs - case JOB_BABY_GUARD: - return MAPID_BABY_GUARD; - case JOB_BABY_SORCERER: - return MAPID_BABY_SORCERER; - case JOB_BABY_MINSTREL: - case JOB_BABY_WANDERER: - return MAPID_BABY_MINSTRELWANDERER; - case JOB_BABY_SURA: - return MAPID_BABY_SURA; - case JOB_BABY_GENETIC: - return MAPID_BABY_GENETIC; - case JOB_BABY_CHASER: - return MAPID_BABY_CHASER; - default: - return -1; - } + switch(b_class) + { + //Novice And 1-1 Jobs + case JOB_NOVICE: return MAPID_NOVICE; + case JOB_SWORDMAN: return MAPID_SWORDMAN; + case JOB_MAGE: return MAPID_MAGE; + case JOB_ARCHER: return MAPID_ARCHER; + case JOB_ACOLYTE: return MAPID_ACOLYTE; + case JOB_MERCHANT: return MAPID_MERCHANT; + case JOB_THIEF: return MAPID_THIEF; + case JOB_TAEKWON: return MAPID_TAEKWON; + case JOB_WEDDING: return MAPID_WEDDING; + case JOB_GUNSLINGER: return MAPID_GUNSLINGER; + case JOB_NINJA: return MAPID_NINJA; + case JOB_XMAS: return MAPID_XMAS; + case JOB_SUMMER: return MAPID_SUMMER; + case JOB_GANGSI: return MAPID_GANGSI; + //2-1 Jobs + case JOB_SUPER_NOVICE: return MAPID_SUPER_NOVICE; + case JOB_KNIGHT: return MAPID_KNIGHT; + case JOB_WIZARD: return MAPID_WIZARD; + case JOB_HUNTER: return MAPID_HUNTER; + case JOB_PRIEST: return MAPID_PRIEST; + case JOB_BLACKSMITH: return MAPID_BLACKSMITH; + case JOB_ASSASSIN: return MAPID_ASSASSIN; + case JOB_STAR_GLADIATOR: return MAPID_STAR_GLADIATOR; + case JOB_KAGEROU: + case JOB_OBORO: return MAPID_KAGEROUOBORO; + case JOB_DEATH_KNIGHT: return MAPID_DEATH_KNIGHT; + //2-2 Jobs + case JOB_CRUSADER: return MAPID_CRUSADER; + case JOB_SAGE: return MAPID_SAGE; + case JOB_BARD: + case JOB_DANCER: return MAPID_BARDDANCER; + case JOB_MONK: return MAPID_MONK; + case JOB_ALCHEMIST: return MAPID_ALCHEMIST; + case JOB_ROGUE: return MAPID_ROGUE; + case JOB_SOUL_LINKER: return MAPID_SOUL_LINKER; + case JOB_DARK_COLLECTOR: return MAPID_DARK_COLLECTOR; + //Trans Novice And Trans 1-1 Jobs + case JOB_NOVICE_HIGH: return MAPID_NOVICE_HIGH; + case JOB_SWORDMAN_HIGH: return MAPID_SWORDMAN_HIGH; + case JOB_MAGE_HIGH: return MAPID_MAGE_HIGH; + case JOB_ARCHER_HIGH: return MAPID_ARCHER_HIGH; + case JOB_ACOLYTE_HIGH: return MAPID_ACOLYTE_HIGH; + case JOB_MERCHANT_HIGH: return MAPID_MERCHANT_HIGH; + case JOB_THIEF_HIGH: return MAPID_THIEF_HIGH; + //Trans 2-1 Jobs + case JOB_LORD_KNIGHT: return MAPID_LORD_KNIGHT; + case JOB_HIGH_WIZARD: return MAPID_HIGH_WIZARD; + case JOB_SNIPER: return MAPID_SNIPER; + case JOB_HIGH_PRIEST: return MAPID_HIGH_PRIEST; + case JOB_WHITESMITH: return MAPID_WHITESMITH; + case JOB_ASSASSIN_CROSS: return MAPID_ASSASSIN_CROSS; + //Trans 2-2 Jobs + case JOB_PALADIN: return MAPID_PALADIN; + case JOB_PROFESSOR: return MAPID_PROFESSOR; + case JOB_CLOWN: + case JOB_GYPSY: return MAPID_CLOWNGYPSY; + case JOB_CHAMPION: return MAPID_CHAMPION; + case JOB_CREATOR: return MAPID_CREATOR; + case JOB_STALKER: return MAPID_STALKER; + //Baby Novice And Baby 1-1 Jobs + case JOB_BABY: return MAPID_BABY; + case JOB_BABY_SWORDMAN: return MAPID_BABY_SWORDMAN; + case JOB_BABY_MAGE: return MAPID_BABY_MAGE; + case JOB_BABY_ARCHER: return MAPID_BABY_ARCHER; + case JOB_BABY_ACOLYTE: return MAPID_BABY_ACOLYTE; + case JOB_BABY_MERCHANT: return MAPID_BABY_MERCHANT; + case JOB_BABY_THIEF: return MAPID_BABY_THIEF; + //Baby 2-1 Jobs + case JOB_SUPER_BABY: return MAPID_SUPER_BABY; + case JOB_BABY_KNIGHT: return MAPID_BABY_KNIGHT; + case JOB_BABY_WIZARD: return MAPID_BABY_WIZARD; + case JOB_BABY_HUNTER: return MAPID_BABY_HUNTER; + case JOB_BABY_PRIEST: return MAPID_BABY_PRIEST; + case JOB_BABY_BLACKSMITH: return MAPID_BABY_BLACKSMITH; + case JOB_BABY_ASSASSIN: return MAPID_BABY_ASSASSIN; + //Baby 2-2 Jobs + case JOB_BABY_CRUSADER: return MAPID_BABY_CRUSADER; + case JOB_BABY_SAGE: return MAPID_BABY_SAGE; + case JOB_BABY_BARD: + case JOB_BABY_DANCER: return MAPID_BABY_BARDDANCER; + case JOB_BABY_MONK: return MAPID_BABY_MONK; + case JOB_BABY_ALCHEMIST: return MAPID_BABY_ALCHEMIST; + case JOB_BABY_ROGUE: return MAPID_BABY_ROGUE; + //3-1 Jobs + case JOB_SUPER_NOVICE_E: return MAPID_SUPER_NOVICE_E; + case JOB_RUNE_KNIGHT: return MAPID_RUNE_KNIGHT; + case JOB_WARLOCK: return MAPID_WARLOCK; + case JOB_RANGER: return MAPID_RANGER; + case JOB_ARCH_BISHOP: return MAPID_ARCH_BISHOP; + case JOB_MECHANIC: return MAPID_MECHANIC; + case JOB_GUILLOTINE_CROSS: return MAPID_GUILLOTINE_CROSS; + //3-2 Jobs + case JOB_ROYAL_GUARD: return MAPID_ROYAL_GUARD; + case JOB_SORCERER: return MAPID_SORCERER; + case JOB_MINSTREL: + case JOB_WANDERER: return MAPID_MINSTRELWANDERER; + case JOB_SURA: return MAPID_SURA; + case JOB_GENETIC: return MAPID_GENETIC; + case JOB_SHADOW_CHASER: return MAPID_SHADOW_CHASER; + //Trans 3-1 Jobs + case JOB_RUNE_KNIGHT_T: return MAPID_RUNE_KNIGHT_T; + case JOB_WARLOCK_T: return MAPID_WARLOCK_T; + case JOB_RANGER_T: return MAPID_RANGER_T; + case JOB_ARCH_BISHOP_T: return MAPID_ARCH_BISHOP_T; + case JOB_MECHANIC_T: return MAPID_MECHANIC_T; + case JOB_GUILLOTINE_CROSS_T: return MAPID_GUILLOTINE_CROSS_T; + //Trans 3-2 Jobs + case JOB_ROYAL_GUARD_T: return MAPID_ROYAL_GUARD_T; + case JOB_SORCERER_T: return MAPID_SORCERER_T; + case JOB_MINSTREL_T: + case JOB_WANDERER_T: return MAPID_MINSTRELWANDERER_T; + case JOB_SURA_T: return MAPID_SURA_T; + case JOB_GENETIC_T: return MAPID_GENETIC_T; + case JOB_SHADOW_CHASER_T: return MAPID_SHADOW_CHASER_T; + //Baby 3-1 Jobs + case JOB_SUPER_BABY_E: return MAPID_SUPER_BABY_E; + case JOB_BABY_RUNE: return MAPID_BABY_RUNE; + case JOB_BABY_WARLOCK: return MAPID_BABY_WARLOCK; + case JOB_BABY_RANGER: return MAPID_BABY_RANGER; + case JOB_BABY_BISHOP: return MAPID_BABY_BISHOP; + case JOB_BABY_MECHANIC: return MAPID_BABY_MECHANIC; + case JOB_BABY_CROSS: return MAPID_BABY_CROSS; + //Baby 3-2 Jobs + case JOB_BABY_GUARD: return MAPID_BABY_GUARD; + case JOB_BABY_SORCERER: return MAPID_BABY_SORCERER; + case JOB_BABY_MINSTREL: + case JOB_BABY_WANDERER: return MAPID_BABY_MINSTRELWANDERER; + case JOB_BABY_SURA: return MAPID_BABY_SURA; + case JOB_BABY_GENETIC: return MAPID_BABY_GENETIC; + case JOB_BABY_CHASER: return MAPID_BABY_CHASER; + default: + return -1; + } } //Reverts the map-style class id to the client-style one. int pc_mapid2jobid(unsigned short class_, int sex) { - switch (class_) { - //Novice And 1-1 Jobs - case MAPID_NOVICE: - return JOB_NOVICE; - case MAPID_SWORDMAN: - return JOB_SWORDMAN; - case MAPID_MAGE: - return JOB_MAGE; - case MAPID_ARCHER: - return JOB_ARCHER; - case MAPID_ACOLYTE: - return JOB_ACOLYTE; - case MAPID_MERCHANT: - return JOB_MERCHANT; - case MAPID_THIEF: - return JOB_THIEF; - case MAPID_TAEKWON: - return JOB_TAEKWON; - case MAPID_WEDDING: - return JOB_WEDDING; - case MAPID_GUNSLINGER: - return JOB_GUNSLINGER; - case MAPID_NINJA: - return JOB_NINJA; - case MAPID_XMAS: - return JOB_XMAS; - case MAPID_SUMMER: - return JOB_SUMMER; - case MAPID_GANGSI: - return JOB_GANGSI; - //2-1 Jobs - case MAPID_SUPER_NOVICE: - return JOB_SUPER_NOVICE; - case MAPID_KNIGHT: - return JOB_KNIGHT; - case MAPID_WIZARD: - return JOB_WIZARD; - case MAPID_HUNTER: - return JOB_HUNTER; - case MAPID_PRIEST: - return JOB_PRIEST; - case MAPID_BLACKSMITH: - return JOB_BLACKSMITH; - case MAPID_ASSASSIN: - return JOB_ASSASSIN; - case MAPID_STAR_GLADIATOR: - return JOB_STAR_GLADIATOR; - case MAPID_KAGEROUOBORO: - return sex?JOB_KAGEROU:JOB_OBORO; - case MAPID_DEATH_KNIGHT: - return JOB_DEATH_KNIGHT; - //2-2 Jobs - case MAPID_CRUSADER: - return JOB_CRUSADER; - case MAPID_SAGE: - return JOB_SAGE; - case MAPID_BARDDANCER: - return sex?JOB_BARD:JOB_DANCER; - case MAPID_MONK: - return JOB_MONK; - case MAPID_ALCHEMIST: - return JOB_ALCHEMIST; - case MAPID_ROGUE: - return JOB_ROGUE; - case MAPID_SOUL_LINKER: - return JOB_SOUL_LINKER; - case MAPID_DARK_COLLECTOR: - return JOB_DARK_COLLECTOR; - //Trans Novice And Trans 2-1 Jobs - case MAPID_NOVICE_HIGH: - return JOB_NOVICE_HIGH; - case MAPID_SWORDMAN_HIGH: - return JOB_SWORDMAN_HIGH; - case MAPID_MAGE_HIGH: - return JOB_MAGE_HIGH; - case MAPID_ARCHER_HIGH: - return JOB_ARCHER_HIGH; - case MAPID_ACOLYTE_HIGH: - return JOB_ACOLYTE_HIGH; - case MAPID_MERCHANT_HIGH: - return JOB_MERCHANT_HIGH; - case MAPID_THIEF_HIGH: - return JOB_THIEF_HIGH; - //Trans 2-1 Jobs - case MAPID_LORD_KNIGHT: - return JOB_LORD_KNIGHT; - case MAPID_HIGH_WIZARD: - return JOB_HIGH_WIZARD; - case MAPID_SNIPER: - return JOB_SNIPER; - case MAPID_HIGH_PRIEST: - return JOB_HIGH_PRIEST; - case MAPID_WHITESMITH: - return JOB_WHITESMITH; - case MAPID_ASSASSIN_CROSS: - return JOB_ASSASSIN_CROSS; - //Trans 2-2 Jobs - case MAPID_PALADIN: - return JOB_PALADIN; - case MAPID_PROFESSOR: - return JOB_PROFESSOR; - case MAPID_CLOWNGYPSY: - return sex?JOB_CLOWN:JOB_GYPSY; - case MAPID_CHAMPION: - return JOB_CHAMPION; - case MAPID_CREATOR: - return JOB_CREATOR; - case MAPID_STALKER: - return JOB_STALKER; - //Baby Novice And Baby 1-1 Jobs - case MAPID_BABY: - return JOB_BABY; - case MAPID_BABY_SWORDMAN: - return JOB_BABY_SWORDMAN; - case MAPID_BABY_MAGE: - return JOB_BABY_MAGE; - case MAPID_BABY_ARCHER: - return JOB_BABY_ARCHER; - case MAPID_BABY_ACOLYTE: - return JOB_BABY_ACOLYTE; - case MAPID_BABY_MERCHANT: - return JOB_BABY_MERCHANT; - case MAPID_BABY_THIEF: - return JOB_BABY_THIEF; - //Baby 2-1 Jobs - case MAPID_SUPER_BABY: - return JOB_SUPER_BABY; - case MAPID_BABY_KNIGHT: - return JOB_BABY_KNIGHT; - case MAPID_BABY_WIZARD: - return JOB_BABY_WIZARD; - case MAPID_BABY_HUNTER: - return JOB_BABY_HUNTER; - case MAPID_BABY_PRIEST: - return JOB_BABY_PRIEST; - case MAPID_BABY_BLACKSMITH: - return JOB_BABY_BLACKSMITH; - case MAPID_BABY_ASSASSIN: - return JOB_BABY_ASSASSIN; - //Baby 2-2 Jobs - case MAPID_BABY_CRUSADER: - return JOB_BABY_CRUSADER; - case MAPID_BABY_SAGE: - return JOB_BABY_SAGE; - case MAPID_BABY_BARDDANCER: - return sex?JOB_BABY_BARD:JOB_BABY_DANCER; - case MAPID_BABY_MONK: - return JOB_BABY_MONK; - case MAPID_BABY_ALCHEMIST: - return JOB_BABY_ALCHEMIST; - case MAPID_BABY_ROGUE: - return JOB_BABY_ROGUE; - //3-1 Jobs - case MAPID_SUPER_NOVICE_E: - return JOB_SUPER_NOVICE_E; - case MAPID_RUNE_KNIGHT: - return JOB_RUNE_KNIGHT; - case MAPID_WARLOCK: - return JOB_WARLOCK; - case MAPID_RANGER: - return JOB_RANGER; - case MAPID_ARCH_BISHOP: - return JOB_ARCH_BISHOP; - case MAPID_MECHANIC: - return JOB_MECHANIC; - case MAPID_GUILLOTINE_CROSS: - return JOB_GUILLOTINE_CROSS; - //3-2 Jobs - case MAPID_ROYAL_GUARD: - return JOB_ROYAL_GUARD; - case MAPID_SORCERER: - return JOB_SORCERER; - case MAPID_MINSTRELWANDERER: - return sex?JOB_MINSTREL:JOB_WANDERER; - case MAPID_SURA: - return JOB_SURA; - case MAPID_GENETIC: - return JOB_GENETIC; - case MAPID_SHADOW_CHASER: - return JOB_SHADOW_CHASER; - //Trans 3-1 Jobs - case MAPID_RUNE_KNIGHT_T: - return JOB_RUNE_KNIGHT_T; - case MAPID_WARLOCK_T: - return JOB_WARLOCK_T; - case MAPID_RANGER_T: - return JOB_RANGER_T; - case MAPID_ARCH_BISHOP_T: - return JOB_ARCH_BISHOP_T; - case MAPID_MECHANIC_T: - return JOB_MECHANIC_T; - case MAPID_GUILLOTINE_CROSS_T: - return JOB_GUILLOTINE_CROSS_T; - //Trans 3-2 Jobs - case MAPID_ROYAL_GUARD_T: - return JOB_ROYAL_GUARD_T; - case MAPID_SORCERER_T: - return JOB_SORCERER_T; - case MAPID_MINSTRELWANDERER_T: - return sex?JOB_MINSTREL_T:JOB_WANDERER_T; - case MAPID_SURA_T: - return JOB_SURA_T; - case MAPID_GENETIC_T: - return JOB_GENETIC_T; - case MAPID_SHADOW_CHASER_T: - return JOB_SHADOW_CHASER_T; - //Baby 3-1 Jobs - case MAPID_SUPER_BABY_E: - return JOB_SUPER_BABY_E; - case MAPID_BABY_RUNE: - return JOB_BABY_RUNE; - case MAPID_BABY_WARLOCK: - return JOB_BABY_WARLOCK; - case MAPID_BABY_RANGER: - return JOB_BABY_RANGER; - case MAPID_BABY_BISHOP: - return JOB_BABY_BISHOP; - case MAPID_BABY_MECHANIC: - return JOB_BABY_MECHANIC; - case MAPID_BABY_CROSS: - return JOB_BABY_CROSS; - //Baby 3-2 Jobs - case MAPID_BABY_GUARD: - return JOB_BABY_GUARD; - case MAPID_BABY_SORCERER: - return JOB_BABY_SORCERER; - case MAPID_BABY_MINSTRELWANDERER: - return sex?JOB_BABY_MINSTREL:JOB_BABY_WANDERER; - case MAPID_BABY_SURA: - return JOB_BABY_SURA; - case MAPID_BABY_GENETIC: - return JOB_BABY_GENETIC; - case MAPID_BABY_CHASER: - return JOB_BABY_CHASER; - default: - return -1; - } + switch(class_) + { + //Novice And 1-1 Jobs + case MAPID_NOVICE: return JOB_NOVICE; + case MAPID_SWORDMAN: return JOB_SWORDMAN; + case MAPID_MAGE: return JOB_MAGE; + case MAPID_ARCHER: return JOB_ARCHER; + case MAPID_ACOLYTE: return JOB_ACOLYTE; + case MAPID_MERCHANT: return JOB_MERCHANT; + case MAPID_THIEF: return JOB_THIEF; + case MAPID_TAEKWON: return JOB_TAEKWON; + case MAPID_WEDDING: return JOB_WEDDING; + case MAPID_GUNSLINGER: return JOB_GUNSLINGER; + case MAPID_NINJA: return JOB_NINJA; + case MAPID_XMAS: return JOB_XMAS; + case MAPID_SUMMER: return JOB_SUMMER; + case MAPID_GANGSI: return JOB_GANGSI; + //2-1 Jobs + case MAPID_SUPER_NOVICE: return JOB_SUPER_NOVICE; + case MAPID_KNIGHT: return JOB_KNIGHT; + case MAPID_WIZARD: return JOB_WIZARD; + case MAPID_HUNTER: return JOB_HUNTER; + case MAPID_PRIEST: return JOB_PRIEST; + case MAPID_BLACKSMITH: return JOB_BLACKSMITH; + case MAPID_ASSASSIN: return JOB_ASSASSIN; + case MAPID_STAR_GLADIATOR: return JOB_STAR_GLADIATOR; + case MAPID_KAGEROUOBORO: return sex?JOB_KAGEROU:JOB_OBORO; + case MAPID_DEATH_KNIGHT: return JOB_DEATH_KNIGHT; + //2-2 Jobs + case MAPID_CRUSADER: return JOB_CRUSADER; + case MAPID_SAGE: return JOB_SAGE; + case MAPID_BARDDANCER: return sex?JOB_BARD:JOB_DANCER; + case MAPID_MONK: return JOB_MONK; + case MAPID_ALCHEMIST: return JOB_ALCHEMIST; + case MAPID_ROGUE: return JOB_ROGUE; + case MAPID_SOUL_LINKER: return JOB_SOUL_LINKER; + case MAPID_DARK_COLLECTOR: return JOB_DARK_COLLECTOR; + //Trans Novice And Trans 2-1 Jobs + case MAPID_NOVICE_HIGH: return JOB_NOVICE_HIGH; + case MAPID_SWORDMAN_HIGH: return JOB_SWORDMAN_HIGH; + case MAPID_MAGE_HIGH: return JOB_MAGE_HIGH; + case MAPID_ARCHER_HIGH: return JOB_ARCHER_HIGH; + case MAPID_ACOLYTE_HIGH: return JOB_ACOLYTE_HIGH; + case MAPID_MERCHANT_HIGH: return JOB_MERCHANT_HIGH; + case MAPID_THIEF_HIGH: return JOB_THIEF_HIGH; + //Trans 2-1 Jobs + case MAPID_LORD_KNIGHT: return JOB_LORD_KNIGHT; + case MAPID_HIGH_WIZARD: return JOB_HIGH_WIZARD; + case MAPID_SNIPER: return JOB_SNIPER; + case MAPID_HIGH_PRIEST: return JOB_HIGH_PRIEST; + case MAPID_WHITESMITH: return JOB_WHITESMITH; + case MAPID_ASSASSIN_CROSS: return JOB_ASSASSIN_CROSS; + //Trans 2-2 Jobs + case MAPID_PALADIN: return JOB_PALADIN; + case MAPID_PROFESSOR: return JOB_PROFESSOR; + case MAPID_CLOWNGYPSY: return sex?JOB_CLOWN:JOB_GYPSY; + case MAPID_CHAMPION: return JOB_CHAMPION; + case MAPID_CREATOR: return JOB_CREATOR; + case MAPID_STALKER: return JOB_STALKER; + //Baby Novice And Baby 1-1 Jobs + case MAPID_BABY: return JOB_BABY; + case MAPID_BABY_SWORDMAN: return JOB_BABY_SWORDMAN; + case MAPID_BABY_MAGE: return JOB_BABY_MAGE; + case MAPID_BABY_ARCHER: return JOB_BABY_ARCHER; + case MAPID_BABY_ACOLYTE: return JOB_BABY_ACOLYTE; + case MAPID_BABY_MERCHANT: return JOB_BABY_MERCHANT; + case MAPID_BABY_THIEF: return JOB_BABY_THIEF; + //Baby 2-1 Jobs + case MAPID_SUPER_BABY: return JOB_SUPER_BABY; + case MAPID_BABY_KNIGHT: return JOB_BABY_KNIGHT; + case MAPID_BABY_WIZARD: return JOB_BABY_WIZARD; + case MAPID_BABY_HUNTER: return JOB_BABY_HUNTER; + case MAPID_BABY_PRIEST: return JOB_BABY_PRIEST; + case MAPID_BABY_BLACKSMITH: return JOB_BABY_BLACKSMITH; + case MAPID_BABY_ASSASSIN: return JOB_BABY_ASSASSIN; + //Baby 2-2 Jobs + case MAPID_BABY_CRUSADER: return JOB_BABY_CRUSADER; + case MAPID_BABY_SAGE: return JOB_BABY_SAGE; + case MAPID_BABY_BARDDANCER: return sex?JOB_BABY_BARD:JOB_BABY_DANCER; + case MAPID_BABY_MONK: return JOB_BABY_MONK; + case MAPID_BABY_ALCHEMIST: return JOB_BABY_ALCHEMIST; + case MAPID_BABY_ROGUE: return JOB_BABY_ROGUE; + //3-1 Jobs + case MAPID_SUPER_NOVICE_E: return JOB_SUPER_NOVICE_E; + case MAPID_RUNE_KNIGHT: return JOB_RUNE_KNIGHT; + case MAPID_WARLOCK: return JOB_WARLOCK; + case MAPID_RANGER: return JOB_RANGER; + case MAPID_ARCH_BISHOP: return JOB_ARCH_BISHOP; + case MAPID_MECHANIC: return JOB_MECHANIC; + case MAPID_GUILLOTINE_CROSS: return JOB_GUILLOTINE_CROSS; + //3-2 Jobs + case MAPID_ROYAL_GUARD: return JOB_ROYAL_GUARD; + case MAPID_SORCERER: return JOB_SORCERER; + case MAPID_MINSTRELWANDERER: return sex?JOB_MINSTREL:JOB_WANDERER; + case MAPID_SURA: return JOB_SURA; + case MAPID_GENETIC: return JOB_GENETIC; + case MAPID_SHADOW_CHASER: return JOB_SHADOW_CHASER; + //Trans 3-1 Jobs + case MAPID_RUNE_KNIGHT_T: return JOB_RUNE_KNIGHT_T; + case MAPID_WARLOCK_T: return JOB_WARLOCK_T; + case MAPID_RANGER_T: return JOB_RANGER_T; + case MAPID_ARCH_BISHOP_T: return JOB_ARCH_BISHOP_T; + case MAPID_MECHANIC_T: return JOB_MECHANIC_T; + case MAPID_GUILLOTINE_CROSS_T: return JOB_GUILLOTINE_CROSS_T; + //Trans 3-2 Jobs + case MAPID_ROYAL_GUARD_T: return JOB_ROYAL_GUARD_T; + case MAPID_SORCERER_T: return JOB_SORCERER_T; + case MAPID_MINSTRELWANDERER_T: return sex?JOB_MINSTREL_T:JOB_WANDERER_T; + case MAPID_SURA_T: return JOB_SURA_T; + case MAPID_GENETIC_T: return JOB_GENETIC_T; + case MAPID_SHADOW_CHASER_T: return JOB_SHADOW_CHASER_T; + //Baby 3-1 Jobs + case MAPID_SUPER_BABY_E: return JOB_SUPER_BABY_E; + case MAPID_BABY_RUNE: return JOB_BABY_RUNE; + case MAPID_BABY_WARLOCK: return JOB_BABY_WARLOCK; + case MAPID_BABY_RANGER: return JOB_BABY_RANGER; + case MAPID_BABY_BISHOP: return JOB_BABY_BISHOP; + case MAPID_BABY_MECHANIC: return JOB_BABY_MECHANIC; + case MAPID_BABY_CROSS: return JOB_BABY_CROSS; + //Baby 3-2 Jobs + case MAPID_BABY_GUARD: return JOB_BABY_GUARD; + case MAPID_BABY_SORCERER: return JOB_BABY_SORCERER; + case MAPID_BABY_MINSTRELWANDERER: return sex?JOB_BABY_MINSTREL:JOB_BABY_WANDERER; + case MAPID_BABY_SURA: return JOB_BABY_SURA; + case MAPID_BABY_GENETIC: return JOB_BABY_GENETIC; + case MAPID_BABY_CHASER: return JOB_BABY_CHASER; + default: + return -1; + } } /*==================================================== * This function return the name of the job (by [Yor]) *----------------------------------------------------*/ -const char *job_name(int class_) -{ - switch (class_) { - case JOB_NOVICE: - case JOB_SWORDMAN: - case JOB_MAGE: - case JOB_ARCHER: - case JOB_ACOLYTE: - case JOB_MERCHANT: - case JOB_THIEF: - return msg_txt(550 - JOB_NOVICE+class_); - - case JOB_KNIGHT: - case JOB_PRIEST: - case JOB_WIZARD: - case JOB_BLACKSMITH: - case JOB_HUNTER: - case JOB_ASSASSIN: - return msg_txt(557 - JOB_KNIGHT+class_); - - case JOB_KNIGHT2: - return msg_txt(557); - - case JOB_CRUSADER: - case JOB_MONK: - case JOB_SAGE: - case JOB_ROGUE: - case JOB_ALCHEMIST: - case JOB_BARD: - case JOB_DANCER: - return msg_txt(563 - JOB_CRUSADER+class_); - - case JOB_CRUSADER2: - return msg_txt(563); - - case JOB_WEDDING: - case JOB_SUPER_NOVICE: - case JOB_GUNSLINGER: - case JOB_NINJA: - case JOB_XMAS: - return msg_txt(570 - JOB_WEDDING+class_); - - case JOB_SUMMER: - return msg_txt(621); - - case JOB_NOVICE_HIGH: - case JOB_SWORDMAN_HIGH: - case JOB_MAGE_HIGH: - case JOB_ARCHER_HIGH: - case JOB_ACOLYTE_HIGH: - case JOB_MERCHANT_HIGH: - case JOB_THIEF_HIGH: - return msg_txt(575 - JOB_NOVICE_HIGH+class_); - - case JOB_LORD_KNIGHT: - case JOB_HIGH_PRIEST: - case JOB_HIGH_WIZARD: - case JOB_WHITESMITH: - case JOB_SNIPER: - case JOB_ASSASSIN_CROSS: - return msg_txt(582 - JOB_LORD_KNIGHT+class_); - - case JOB_LORD_KNIGHT2: - return msg_txt(582); - - case JOB_PALADIN: - case JOB_CHAMPION: - case JOB_PROFESSOR: - case JOB_STALKER: - case JOB_CREATOR: - case JOB_CLOWN: - case JOB_GYPSY: - return msg_txt(588 - JOB_PALADIN + class_); - - case JOB_PALADIN2: - return msg_txt(588); - - case JOB_BABY: - case JOB_BABY_SWORDMAN: - case JOB_BABY_MAGE: - case JOB_BABY_ARCHER: - case JOB_BABY_ACOLYTE: - case JOB_BABY_MERCHANT: - case JOB_BABY_THIEF: - return msg_txt(595 - JOB_BABY + class_); - - case JOB_BABY_KNIGHT: - case JOB_BABY_PRIEST: - case JOB_BABY_WIZARD: - case JOB_BABY_BLACKSMITH: - case JOB_BABY_HUNTER: - case JOB_BABY_ASSASSIN: - return msg_txt(602 - JOB_BABY_KNIGHT + class_); - - case JOB_BABY_KNIGHT2: - return msg_txt(602); - - case JOB_BABY_CRUSADER: - case JOB_BABY_MONK: - case JOB_BABY_SAGE: - case JOB_BABY_ROGUE: - case JOB_BABY_ALCHEMIST: - case JOB_BABY_BARD: - case JOB_BABY_DANCER: - return msg_txt(608 - JOB_BABY_CRUSADER + class_); - - case JOB_BABY_CRUSADER2: - return msg_txt(608); - - case JOB_SUPER_BABY: - return msg_txt(615); - - case JOB_TAEKWON: - return msg_txt(616); - case JOB_STAR_GLADIATOR: - case JOB_STAR_GLADIATOR2: - return msg_txt(617); - case JOB_SOUL_LINKER: - return msg_txt(618); - - case JOB_GANGSI: - case JOB_DEATH_KNIGHT: - case JOB_DARK_COLLECTOR: - return msg_txt(622 - JOB_GANGSI+class_); - - case JOB_RUNE_KNIGHT: - case JOB_WARLOCK: - case JOB_RANGER: - case JOB_ARCH_BISHOP: - case JOB_MECHANIC: - case JOB_GUILLOTINE_CROSS: - return msg_txt(625 - JOB_RUNE_KNIGHT+class_); - - case JOB_RUNE_KNIGHT_T: - case JOB_WARLOCK_T: - case JOB_RANGER_T: - case JOB_ARCH_BISHOP_T: - case JOB_MECHANIC_T: - case JOB_GUILLOTINE_CROSS_T: - return msg_txt(681 - JOB_RUNE_KNIGHT_T+class_); - - case JOB_ROYAL_GUARD: - case JOB_SORCERER: - case JOB_MINSTREL: - case JOB_WANDERER: - case JOB_SURA: - case JOB_GENETIC: - case JOB_SHADOW_CHASER: - return msg_txt(631 - JOB_ROYAL_GUARD+class_); - - case JOB_ROYAL_GUARD_T: - case JOB_SORCERER_T: - case JOB_MINSTREL_T: - case JOB_WANDERER_T: - case JOB_SURA_T: - case JOB_GENETIC_T: - case JOB_SHADOW_CHASER_T: - return msg_txt(687 - JOB_ROYAL_GUARD_T+class_); - - case JOB_RUNE_KNIGHT2: - case JOB_RUNE_KNIGHT_T2: - return msg_txt(625); - - case JOB_ROYAL_GUARD2: - case JOB_ROYAL_GUARD_T2: - return msg_txt(631); - - case JOB_RANGER2: - case JOB_RANGER_T2: - return msg_txt(627); - - case JOB_MECHANIC2: - case JOB_MECHANIC_T2: - return msg_txt(629); - - case JOB_BABY_RUNE: - case JOB_BABY_WARLOCK: - case JOB_BABY_RANGER: - case JOB_BABY_BISHOP: - case JOB_BABY_MECHANIC: - case JOB_BABY_CROSS: - case JOB_BABY_GUARD: - case JOB_BABY_SORCERER: - case JOB_BABY_MINSTREL: - case JOB_BABY_WANDERER: - case JOB_BABY_SURA: - case JOB_BABY_GENETIC: - case JOB_BABY_CHASER: - return msg_txt(638 - JOB_BABY_RUNE+class_); - - case JOB_BABY_RUNE2: - return msg_txt(638); - - case JOB_BABY_GUARD2: - return msg_txt(644); - - case JOB_BABY_RANGER2: - return msg_txt(640); - - case JOB_BABY_MECHANIC2: - return msg_txt(642); - - case JOB_SUPER_NOVICE_E: - case JOB_SUPER_BABY_E: - return msg_txt(651 - JOB_SUPER_NOVICE_E+class_); - - case JOB_KAGEROU: - case JOB_OBORO: - return msg_txt(653 - JOB_KAGEROU+class_); - - default: - return msg_txt(655); - } +const char* job_name(int class_) +{ + switch (class_) { + case JOB_NOVICE: + case JOB_SWORDMAN: + case JOB_MAGE: + case JOB_ARCHER: + case JOB_ACOLYTE: + case JOB_MERCHANT: + case JOB_THIEF: + return msg_txt(550 - JOB_NOVICE+class_); + + case JOB_KNIGHT: + case JOB_PRIEST: + case JOB_WIZARD: + case JOB_BLACKSMITH: + case JOB_HUNTER: + case JOB_ASSASSIN: + return msg_txt(557 - JOB_KNIGHT+class_); + + case JOB_KNIGHT2: + return msg_txt(557); + + case JOB_CRUSADER: + case JOB_MONK: + case JOB_SAGE: + case JOB_ROGUE: + case JOB_ALCHEMIST: + case JOB_BARD: + case JOB_DANCER: + return msg_txt(563 - JOB_CRUSADER+class_); + + case JOB_CRUSADER2: + return msg_txt(563); + + case JOB_WEDDING: + case JOB_SUPER_NOVICE: + case JOB_GUNSLINGER: + case JOB_NINJA: + case JOB_XMAS: + return msg_txt(570 - JOB_WEDDING+class_); + + case JOB_SUMMER: + return msg_txt(621); + + case JOB_NOVICE_HIGH: + case JOB_SWORDMAN_HIGH: + case JOB_MAGE_HIGH: + case JOB_ARCHER_HIGH: + case JOB_ACOLYTE_HIGH: + case JOB_MERCHANT_HIGH: + case JOB_THIEF_HIGH: + return msg_txt(575 - JOB_NOVICE_HIGH+class_); + + case JOB_LORD_KNIGHT: + case JOB_HIGH_PRIEST: + case JOB_HIGH_WIZARD: + case JOB_WHITESMITH: + case JOB_SNIPER: + case JOB_ASSASSIN_CROSS: + return msg_txt(582 - JOB_LORD_KNIGHT+class_); + + case JOB_LORD_KNIGHT2: + return msg_txt(582); + + case JOB_PALADIN: + case JOB_CHAMPION: + case JOB_PROFESSOR: + case JOB_STALKER: + case JOB_CREATOR: + case JOB_CLOWN: + case JOB_GYPSY: + return msg_txt(588 - JOB_PALADIN + class_); + + case JOB_PALADIN2: + return msg_txt(588); + + case JOB_BABY: + case JOB_BABY_SWORDMAN: + case JOB_BABY_MAGE: + case JOB_BABY_ARCHER: + case JOB_BABY_ACOLYTE: + case JOB_BABY_MERCHANT: + case JOB_BABY_THIEF: + return msg_txt(595 - JOB_BABY + class_); + + case JOB_BABY_KNIGHT: + case JOB_BABY_PRIEST: + case JOB_BABY_WIZARD: + case JOB_BABY_BLACKSMITH: + case JOB_BABY_HUNTER: + case JOB_BABY_ASSASSIN: + return msg_txt(602 - JOB_BABY_KNIGHT + class_); + + case JOB_BABY_KNIGHT2: + return msg_txt(602); + + case JOB_BABY_CRUSADER: + case JOB_BABY_MONK: + case JOB_BABY_SAGE: + case JOB_BABY_ROGUE: + case JOB_BABY_ALCHEMIST: + case JOB_BABY_BARD: + case JOB_BABY_DANCER: + return msg_txt(608 - JOB_BABY_CRUSADER + class_); + + case JOB_BABY_CRUSADER2: + return msg_txt(608); + + case JOB_SUPER_BABY: + return msg_txt(615); + + case JOB_TAEKWON: + return msg_txt(616); + case JOB_STAR_GLADIATOR: + case JOB_STAR_GLADIATOR2: + return msg_txt(617); + case JOB_SOUL_LINKER: + return msg_txt(618); + + case JOB_GANGSI: + case JOB_DEATH_KNIGHT: + case JOB_DARK_COLLECTOR: + return msg_txt(622 - JOB_GANGSI+class_); + + case JOB_RUNE_KNIGHT: + case JOB_WARLOCK: + case JOB_RANGER: + case JOB_ARCH_BISHOP: + case JOB_MECHANIC: + case JOB_GUILLOTINE_CROSS: + return msg_txt(625 - JOB_RUNE_KNIGHT+class_); + + case JOB_RUNE_KNIGHT_T: + case JOB_WARLOCK_T: + case JOB_RANGER_T: + case JOB_ARCH_BISHOP_T: + case JOB_MECHANIC_T: + case JOB_GUILLOTINE_CROSS_T: + return msg_txt(625 - JOB_RUNE_KNIGHT_T+class_); + + case JOB_ROYAL_GUARD: + case JOB_SORCERER: + case JOB_MINSTREL: + case JOB_WANDERER: + case JOB_SURA: + case JOB_GENETIC: + case JOB_SHADOW_CHASER: + return msg_txt(631 - JOB_ROYAL_GUARD+class_); + + case JOB_ROYAL_GUARD_T: + case JOB_SORCERER_T: + case JOB_MINSTREL_T: + case JOB_WANDERER_T: + case JOB_SURA_T: + case JOB_GENETIC_T: + case JOB_SHADOW_CHASER_T: + return msg_txt(631 - JOB_ROYAL_GUARD_T+class_); + + case JOB_RUNE_KNIGHT2: + case JOB_RUNE_KNIGHT_T2: + return msg_txt(625); + + case JOB_ROYAL_GUARD2: + case JOB_ROYAL_GUARD_T2: + return msg_txt(631); + + case JOB_RANGER2: + case JOB_RANGER_T2: + return msg_txt(627); + + case JOB_MECHANIC2: + case JOB_MECHANIC_T2: + return msg_txt(629); + + case JOB_BABY_RUNE: + case JOB_BABY_WARLOCK: + case JOB_BABY_RANGER: + case JOB_BABY_BISHOP: + case JOB_BABY_MECHANIC: + case JOB_BABY_CROSS: + case JOB_BABY_GUARD: + case JOB_BABY_SORCERER: + case JOB_BABY_MINSTREL: + case JOB_BABY_WANDERER: + case JOB_BABY_SURA: + case JOB_BABY_GENETIC: + case JOB_BABY_CHASER: + return msg_txt(638 - JOB_BABY_RUNE+class_); + + case JOB_BABY_RUNE2: + return msg_txt(638); + + case JOB_BABY_GUARD2: + return msg_txt(644); + + case JOB_BABY_RANGER2: + return msg_txt(640); + + case JOB_BABY_MECHANIC2: + return msg_txt(642); + + case JOB_SUPER_NOVICE_E: + case JOB_SUPER_BABY_E: + return msg_txt(651 - JOB_SUPER_NOVICE_E+class_); + + case JOB_KAGEROU: + case JOB_OBORO: + return msg_txt(653 - JOB_KAGEROU+class_); + + default: + return msg_txt(655); + } } int pc_follow_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd; - struct block_list *tbl; + struct map_session_data *sd; + struct block_list *tbl; - sd = map_id2sd(id); - nullpo_ret(sd); + sd = map_id2sd(id); + nullpo_ret(sd); - if (sd->followtimer != tid) { - ShowError("pc_follow_timer %d != %d\n",sd->followtimer,tid); - sd->followtimer = INVALID_TIMER; - return 0; - } + if (sd->followtimer != tid){ + ShowError("pc_follow_timer %d != %d\n",sd->followtimer,tid); + sd->followtimer = INVALID_TIMER; + return 0; + } - sd->followtimer = INVALID_TIMER; - tbl = map_id2bl(sd->followtarget); + sd->followtimer = INVALID_TIMER; + tbl = map_id2bl(sd->followtarget); - if (tbl == NULL || pc_isdead(sd) || status_isdead(tbl)) { - pc_stop_following(sd); - return 0; - } + if (tbl == NULL || pc_isdead(sd) || status_isdead(tbl)) + { + pc_stop_following(sd); + return 0; + } - // either player or target is currently detached from map blocks (could be teleporting), - // but still connected to this map, so we'll just increment the timer and check back later - if (sd->bl.prev != NULL && tbl->prev != NULL && - sd->ud.skilltimer == INVALID_TIMER && sd->ud.attacktimer == INVALID_TIMER && sd->ud.walktimer == INVALID_TIMER) { - if ((sd->bl.m == tbl->m) && unit_can_reach_bl(&sd->bl,tbl, AREA_SIZE, 0, NULL, NULL)) { - if (!check_distance_bl(&sd->bl, tbl, 5)) - unit_walktobl(&sd->bl, tbl, 5, 0); - } else - pc_setpos(sd, map_id2index(tbl->m), tbl->x, tbl->y, CLR_TELEPORT); - } - sd->followtimer = add_timer( - tick + 1000, // increase time a bit to loosen up map's load - pc_follow_timer, sd->bl.id, 0); - return 0; + // either player or target is currently detached from map blocks (could be teleporting), + // but still connected to this map, so we'll just increment the timer and check back later + if (sd->bl.prev != NULL && tbl->prev != NULL && + sd->ud.skilltimer == INVALID_TIMER && sd->ud.attacktimer == INVALID_TIMER && sd->ud.walktimer == INVALID_TIMER) + { + if((sd->bl.m == tbl->m) && unit_can_reach_bl(&sd->bl,tbl, AREA_SIZE, 0, NULL, NULL)) { + if (!check_distance_bl(&sd->bl, tbl, 5)) + unit_walktobl(&sd->bl, tbl, 5, 0); + } else + pc_setpos(sd, map_id2index(tbl->m), tbl->x, tbl->y, CLR_TELEPORT); + } + sd->followtimer = add_timer( + tick + 1000, // increase time a bit to loosen up map's load + pc_follow_timer, sd->bl.id, 0); + return 0; } -int pc_stop_following(struct map_session_data *sd) +int pc_stop_following (struct map_session_data *sd) { - nullpo_ret(sd); + nullpo_ret(sd); - if (sd->followtimer != INVALID_TIMER) { - delete_timer(sd->followtimer,pc_follow_timer); - sd->followtimer = INVALID_TIMER; - } - sd->followtarget = -1; + if (sd->followtimer != INVALID_TIMER) { + delete_timer(sd->followtimer,pc_follow_timer); + sd->followtimer = INVALID_TIMER; + } + sd->followtarget = -1; - return 0; + return 0; } int pc_follow(struct map_session_data *sd,int target_id) { - struct block_list *bl = map_id2bl(target_id); - if (bl == NULL /*|| bl->type != BL_PC*/) - return 1; - if (sd->followtimer != INVALID_TIMER) - pc_stop_following(sd); + struct block_list *bl = map_id2bl(target_id); + if (bl == NULL /*|| bl->type != BL_PC*/) + return 1; + if (sd->followtimer != INVALID_TIMER) + pc_stop_following(sd); - sd->followtarget = target_id; - pc_follow_timer(INVALID_TIMER, gettick(), sd->bl.id, 0); + sd->followtarget = target_id; + pc_follow_timer(INVALID_TIMER, gettick(), sd->bl.id, 0); - return 0; + return 0; } -int pc_checkbaselevelup(struct map_session_data *sd) -{ - unsigned int next = pc_nextbaseexp(sd); +int pc_checkbaselevelup(struct map_session_data *sd) { + unsigned int next = pc_nextbaseexp(sd); - if (!next || sd->status.base_exp < next) - return 0; + if (!next || sd->status.base_exp < next) + return 0; - do { - sd->status.base_exp -= next; - //Kyoki pointed out that the max overcarry exp is the exp needed for the previous level -1. [Skotlex] - if (!battle_config.multi_level_up && sd->status.base_exp > next-1) - sd->status.base_exp = next-1; + do { + sd->status.base_exp -= next; + //Kyoki pointed out that the max overcarry exp is the exp needed for the previous level -1. [Skotlex] + if(!battle_config.multi_level_up && sd->status.base_exp > next-1) + sd->status.base_exp = next-1; - next = pc_gets_status_point(sd->status.base_level); - sd->status.base_level ++; - sd->status.status_point += next; + next = pc_gets_status_point(sd->status.base_level); + sd->status.base_level ++; + sd->status.status_point += next; - } while ((next=pc_nextbaseexp(sd)) > 0 && sd->status.base_exp >= next); + } while ((next=pc_nextbaseexp(sd)) > 0 && sd->status.base_exp >= next); - if (battle_config.pet_lv_rate && sd->pd) //<Skotlex> update pet's level - status_calc_pet(sd->pd,0); + if (battle_config.pet_lv_rate && sd->pd) //<Skotlex> update pet's level + status_calc_pet(sd->pd,0); - clif_updatestatus(sd,SP_STATUSPOINT); - clif_updatestatus(sd,SP_BASELEVEL); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_NEXTBASEEXP); - status_calc_pc(sd,0); - status_percent_heal(&sd->bl,100,100); + clif_updatestatus(sd,SP_STATUSPOINT); + clif_updatestatus(sd,SP_BASELEVEL); + clif_updatestatus(sd,SP_BASEEXP); + clif_updatestatus(sd,SP_NEXTBASEEXP); + status_calc_pc(sd,0); + status_percent_heal(&sd->bl,100,100); - if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) { - sc_start(&sd->bl,status_skill2sc(PR_KYRIE),100,1,skill_get_time(PR_KYRIE,1)); - sc_start(&sd->bl,status_skill2sc(PR_IMPOSITIO),100,1,skill_get_time(PR_IMPOSITIO,1)); - sc_start(&sd->bl,status_skill2sc(PR_MAGNIFICAT),100,1,skill_get_time(PR_MAGNIFICAT,1)); - sc_start(&sd->bl,status_skill2sc(PR_GLORIA),100,1,skill_get_time(PR_GLORIA,1)); - sc_start(&sd->bl,status_skill2sc(PR_SUFFRAGIUM),100,1,skill_get_time(PR_SUFFRAGIUM,1)); - if (sd->state.snovice_dead_flag) - sd->state.snovice_dead_flag = 0; //Reenable steelbody resurrection on dead. - } else if ((sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON) { - sc_start(&sd->bl,status_skill2sc(AL_INCAGI),100,10,600000); - sc_start(&sd->bl,status_skill2sc(AL_BLESSING),100,10,600000); - } - clif_misceffect(&sd->bl,0); - npc_script_event(sd, NPCE_BASELVUP); //LORDALFA - LVLUPEVENT + if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) { + sc_start(&sd->bl,status_skill2sc(PR_KYRIE),100,1,skill_get_time(PR_KYRIE,1)); + sc_start(&sd->bl,status_skill2sc(PR_IMPOSITIO),100,1,skill_get_time(PR_IMPOSITIO,1)); + sc_start(&sd->bl,status_skill2sc(PR_MAGNIFICAT),100,1,skill_get_time(PR_MAGNIFICAT,1)); + sc_start(&sd->bl,status_skill2sc(PR_GLORIA),100,1,skill_get_time(PR_GLORIA,1)); + sc_start(&sd->bl,status_skill2sc(PR_SUFFRAGIUM),100,1,skill_get_time(PR_SUFFRAGIUM,1)); + if (sd->state.snovice_dead_flag) + sd->state.snovice_dead_flag = 0; //Reenable steelbody resurrection on dead. + } else if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) { + sc_start(&sd->bl,status_skill2sc(AL_INCAGI),100,10,600000); + sc_start(&sd->bl,status_skill2sc(AL_BLESSING),100,10,600000); + } + clif_misceffect(&sd->bl,0); + npc_script_event(sd, NPCE_BASELVUP); //LORDALFA - LVLUPEVENT - if (sd->status.party_id) - party_send_levelup(sd); + if(sd->status.party_id) + party_send_levelup(sd); - pc_baselevelchanged(sd); - return 1; + pc_baselevelchanged(sd); + return 1; } -void pc_baselevelchanged(struct map_session_data *sd) -{ +void pc_baselevelchanged(struct map_session_data *sd) { #ifdef RENEWAL - int i; - for (i = 0; i < EQI_MAX; i++) { - if (sd->equip_index[i] >= 0) { - if (sd->inventory_data[ sd->equip_index[i] ]->elvmax && sd->status.base_level > (unsigned int)sd->inventory_data[ sd->equip_index[i] ]->elvmax) - pc_unequipitem(sd, sd->equip_index[i], 3); - } - } + int i; + for( i = 0; i < EQI_MAX; i++ ) { + if( sd->equip_index[i] >= 0 ) { + if( sd->inventory_data[ sd->equip_index[i] ]->elvmax && sd->status.base_level > (unsigned int)sd->inventory_data[ sd->equip_index[i] ]->elvmax ) + pc_unequipitem(sd, sd->equip_index[i], 3); + } + } #endif } int pc_checkjoblevelup(struct map_session_data *sd) { - unsigned int next = pc_nextjobexp(sd); + unsigned int next = pc_nextjobexp(sd); - nullpo_ret(sd); - if (!next || sd->status.job_exp < next) - return 0; + nullpo_ret(sd); + if(!next || sd->status.job_exp < next) + return 0; - do { - sd->status.job_exp -= next; - //Kyoki pointed out that the max overcarry exp is the exp needed for the previous level -1. [Skotlex] - if (!battle_config.multi_level_up && sd->status.job_exp > next-1) - sd->status.job_exp = next-1; + do { + sd->status.job_exp -= next; + //Kyoki pointed out that the max overcarry exp is the exp needed for the previous level -1. [Skotlex] + if(!battle_config.multi_level_up && sd->status.job_exp > next-1) + sd->status.job_exp = next-1; - sd->status.job_level ++; - sd->status.skill_point ++; + sd->status.job_level ++; + sd->status.skill_point ++; - } while ((next=pc_nextjobexp(sd)) > 0 && sd->status.job_exp >= next); + } while ((next=pc_nextjobexp(sd)) > 0 && sd->status.job_exp >= next); - clif_updatestatus(sd,SP_JOBLEVEL); - clif_updatestatus(sd,SP_JOBEXP); - clif_updatestatus(sd,SP_NEXTJOBEXP); - clif_updatestatus(sd,SP_SKILLPOINT); - status_calc_pc(sd,0); - clif_misceffect(&sd->bl,1); - if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) - clif_status_change(&sd->bl,SI_DEVIL, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL. + clif_updatestatus(sd,SP_JOBLEVEL); + clif_updatestatus(sd,SP_JOBEXP); + clif_updatestatus(sd,SP_NEXTJOBEXP); + clif_updatestatus(sd,SP_SKILLPOINT); + status_calc_pc(sd,0); + clif_misceffect(&sd->bl,1); + if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) + clif_status_change(&sd->bl,SI_DEVIL, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL. - npc_script_event(sd, NPCE_JOBLVUP); - return 1; + npc_script_event(sd, NPCE_JOBLVUP); + return 1; } /*========================================== @@ -5702,107 +5633,107 @@ int pc_checkjoblevelup(struct map_session_data *sd) *------------------------------------------*/ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src) { - int bonus = 0; - struct status_data *status = status_get_status_data(src); + int bonus = 0; + struct status_data *status = status_get_status_data(src); - if (sd->expaddrace[status->race]) - bonus += sd->expaddrace[status->race]; - bonus += sd->expaddrace[status->mode&MD_BOSS?RC_BOSS:RC_NONBOSS]; + if (sd->expaddrace[status->race]) + bonus += sd->expaddrace[status->race]; + bonus += sd->expaddrace[status->mode&MD_BOSS?RC_BOSS:RC_NONBOSS]; - if (battle_config.pk_mode && - (int)(status_get_lv(src) - sd->status.base_level) >= 20) - bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris] + if (battle_config.pk_mode && + (int)(status_get_lv(src) - sd->status.base_level) >= 20) + bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris] - if (sd->sc.data[SC_EXPBOOST]) - bonus += sd->sc.data[SC_EXPBOOST]->val1; + if (sd->sc.data[SC_EXPBOOST]) + bonus += sd->sc.data[SC_EXPBOOST]->val1; - *base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * bonus/100., 1, UINT_MAX); + *base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * bonus/100., 1, UINT_MAX); - if (sd->sc.data[SC_JEXPBOOST]) - bonus += sd->sc.data[SC_JEXPBOOST]->val1; + if (sd->sc.data[SC_JEXPBOOST]) + bonus += sd->sc.data[SC_JEXPBOOST]->val1; - *job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * bonus/100., 1, UINT_MAX); + *job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * bonus/100., 1, UINT_MAX); - return; + return; } /*========================================== * Give x exp at sd player and calculate remaining exp for next lvl *------------------------------------------*/ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp,unsigned int job_exp,bool quest) { - float nextbp=0, nextjp=0; - unsigned int nextb=0, nextj=0; - nullpo_ret(sd); - - if (sd->bl.prev == NULL || pc_isdead(sd)) - return 0; - - if (!battle_config.pvp_exp && map[sd->bl.m].flag.pvp) // [MouseJstr] - return 0; // no exp on pvp maps - - if (sd->status.guild_id>0) - base_exp-=guild_payexp(sd,base_exp); - - if (src) pc_calcexp(sd, &base_exp, &job_exp, src); - - nextb = pc_nextbaseexp(sd); - nextj = pc_nextjobexp(sd); - - if (sd->state.showexp || battle_config.max_exp_gain_rate) { - if (nextb > 0) - nextbp = (float) base_exp / (float) nextb; - if (nextj > 0) - nextjp = (float) job_exp / (float) nextj; - - if (battle_config.max_exp_gain_rate) { - if (nextbp > battle_config.max_exp_gain_rate/1000.) { - //Note that this value should never be greater than the original - //base_exp, therefore no overflow checks are needed. [Skotlex] - base_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextb); - if (sd->state.showexp) - nextbp = (float) base_exp / (float) nextb; - } - if (nextjp > battle_config.max_exp_gain_rate/1000.) { - job_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextj); - if (sd->state.showexp) - nextjp = (float) job_exp / (float) nextj; - } - } - } - - //Cap exp to the level up requirement of the previous level when you are at max level, otherwise cap at UINT_MAX (this is required for some S. Novice bonuses). [Skotlex] - if (base_exp) { - nextb = nextb?UINT_MAX:pc_thisbaseexp(sd); - if (sd->status.base_exp > nextb - base_exp) - sd->status.base_exp = nextb; - else - sd->status.base_exp += base_exp; - pc_checkbaselevelup(sd); - clif_updatestatus(sd,SP_BASEEXP); - } - - if (job_exp) { - nextj = nextj?UINT_MAX:pc_thisjobexp(sd); - if (sd->status.job_exp > nextj - job_exp) - sd->status.job_exp = nextj; - else - sd->status.job_exp += job_exp; - pc_checkjoblevelup(sd); - clif_updatestatus(sd,SP_JOBEXP); - } - - if (base_exp) - clif_displayexp(sd, base_exp, SP_BASEEXP, quest); - if (job_exp) - clif_displayexp(sd, job_exp, SP_JOBEXP, quest); - if (sd->state.showexp) { - char output[256]; - sprintf(output, - "Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100); - clif_disp_onlyself(sd,output,strlen(output)); - } - - return 1; + float nextbp=0, nextjp=0; + unsigned int nextb=0, nextj=0; + nullpo_ret(sd); + + if(sd->bl.prev == NULL || pc_isdead(sd)) + return 0; + + if(!battle_config.pvp_exp && map[sd->bl.m].flag.pvp) // [MouseJstr] + return 0; // no exp on pvp maps + + if(sd->status.guild_id>0) + base_exp-=guild_payexp(sd,base_exp); + + if(src) pc_calcexp(sd, &base_exp, &job_exp, src); + + nextb = pc_nextbaseexp(sd); + nextj = pc_nextjobexp(sd); + + if(sd->state.showexp || battle_config.max_exp_gain_rate){ + if (nextb > 0) + nextbp = (float) base_exp / (float) nextb; + if (nextj > 0) + nextjp = (float) job_exp / (float) nextj; + + if(battle_config.max_exp_gain_rate) { + if (nextbp > battle_config.max_exp_gain_rate/1000.) { + //Note that this value should never be greater than the original + //base_exp, therefore no overflow checks are needed. [Skotlex] + base_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextb); + if (sd->state.showexp) + nextbp = (float) base_exp / (float) nextb; + } + if (nextjp > battle_config.max_exp_gain_rate/1000.) { + job_exp = (unsigned int)(battle_config.max_exp_gain_rate/1000.*nextj); + if (sd->state.showexp) + nextjp = (float) job_exp / (float) nextj; + } + } + } + + //Cap exp to the level up requirement of the previous level when you are at max level, otherwise cap at UINT_MAX (this is required for some S. Novice bonuses). [Skotlex] + if (base_exp) { + nextb = nextb?UINT_MAX:pc_thisbaseexp(sd); + if(sd->status.base_exp > nextb - base_exp) + sd->status.base_exp = nextb; + else + sd->status.base_exp += base_exp; + pc_checkbaselevelup(sd); + clif_updatestatus(sd,SP_BASEEXP); + } + + if (job_exp) { + nextj = nextj?UINT_MAX:pc_thisjobexp(sd); + if(sd->status.job_exp > nextj - job_exp) + sd->status.job_exp = nextj; + else + sd->status.job_exp += job_exp; + pc_checkjoblevelup(sd); + clif_updatestatus(sd,SP_JOBEXP); + } + + if(base_exp) + clif_displayexp(sd, base_exp, SP_BASEEXP, quest); + if(job_exp) + clif_displayexp(sd, job_exp, SP_JOBEXP, quest); + if(sd->state.showexp) { + char output[256]; + sprintf(output, + "Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100); + clif_disp_onlyself(sd,output,strlen(output)); + } + + return 1; } /*========================================== @@ -5810,12 +5741,12 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int *------------------------------------------*/ unsigned int pc_maxbaselv(struct map_session_data *sd) { - return max_level[pc_class2idx(sd->status.class_)][0]; + return max_level[pc_class2idx(sd->status.class_)][0]; } unsigned int pc_maxjoblv(struct map_session_data *sd) { - return max_level[pc_class2idx(sd->status.class_)][1]; + return max_level[pc_class2idx(sd->status.class_)][1]; } /*========================================== @@ -5825,141 +5756,123 @@ unsigned int pc_maxjoblv(struct map_session_data *sd) //Base exp needed for next level. unsigned int pc_nextbaseexp(struct map_session_data *sd) { - nullpo_ret(sd); + nullpo_ret(sd); - if (sd->status.base_level>=pc_maxbaselv(sd) || sd->status.base_level<=0) - return 0; + if(sd->status.base_level>=pc_maxbaselv(sd) || sd->status.base_level<=0) + return 0; - return exp_table[pc_class2idx(sd->status.class_)][0][sd->status.base_level-1]; + return exp_table[pc_class2idx(sd->status.class_)][0][sd->status.base_level-1]; } //Base exp needed for this level. unsigned int pc_thisbaseexp(struct map_session_data *sd) { - if (sd->status.base_level>pc_maxbaselv(sd) || sd->status.base_level<=1) - return 0; + if(sd->status.base_level>pc_maxbaselv(sd) || sd->status.base_level<=1) + return 0; - return exp_table[pc_class2idx(sd->status.class_)][0][sd->status.base_level-2]; + return exp_table[pc_class2idx(sd->status.class_)][0][sd->status.base_level-2]; } /*========================================== * job level exp lookup * Return: - * 0 = not found - * x = exp for level + * 0 = not found + * x = exp for level *------------------------------------------*/ //Job exp needed for next level. unsigned int pc_nextjobexp(struct map_session_data *sd) { - nullpo_ret(sd); + nullpo_ret(sd); - if (sd->status.job_level>=pc_maxjoblv(sd) || sd->status.job_level<=0) - return 0; - return exp_table[pc_class2idx(sd->status.class_)][1][sd->status.job_level-1]; + if(sd->status.job_level>=pc_maxjoblv(sd) || sd->status.job_level<=0) + return 0; + return exp_table[pc_class2idx(sd->status.class_)][1][sd->status.job_level-1]; } //Job exp needed for this level. unsigned int pc_thisjobexp(struct map_session_data *sd) { - if (sd->status.job_level>pc_maxjoblv(sd) || sd->status.job_level<=1) - return 0; - return exp_table[pc_class2idx(sd->status.class_)][1][sd->status.job_level-2]; + if(sd->status.job_level>pc_maxjoblv(sd) || sd->status.job_level<=1) + return 0; + return exp_table[pc_class2idx(sd->status.class_)][1][sd->status.job_level-2]; } /// Returns the value of the specified stat. -static int pc_getstat(struct map_session_data *sd, int type) -{ - nullpo_retr(-1, sd); - - switch (type) { - case SP_STR: - return sd->status.str; - case SP_AGI: - return sd->status.agi; - case SP_VIT: - return sd->status.vit; - case SP_INT: - return sd->status.int_; - case SP_DEX: - return sd->status.dex; - case SP_LUK: - return sd->status.luk; - default: - return -1; - } +static int pc_getstat(struct map_session_data* sd, int type) +{ + nullpo_retr(-1, sd); + + switch( type ) { + case SP_STR: return sd->status.str; + case SP_AGI: return sd->status.agi; + case SP_VIT: return sd->status.vit; + case SP_INT: return sd->status.int_; + case SP_DEX: return sd->status.dex; + case SP_LUK: return sd->status.luk; + default: + return -1; + } } /// Sets the specified stat to the specified value. /// Returns the new value. -static int pc_setstat(struct map_session_data *sd, int type, int val) -{ - nullpo_retr(-1, sd); - - switch (type) { - case SP_STR: - sd->status.str = val; - break; - case SP_AGI: - sd->status.agi = val; - break; - case SP_VIT: - sd->status.vit = val; - break; - case SP_INT: - sd->status.int_ = val; - break; - case SP_DEX: - sd->status.dex = val; - break; - case SP_LUK: - sd->status.luk = val; - break; - default: - return -1; - } - - return val; +static int pc_setstat(struct map_session_data* sd, int type, int val) +{ + nullpo_retr(-1, sd); + + switch( type ) { + case SP_STR: sd->status.str = val; break; + case SP_AGI: sd->status.agi = val; break; + case SP_VIT: sd->status.vit = val; break; + case SP_INT: sd->status.int_ = val; break; + case SP_DEX: sd->status.dex = val; break; + case SP_LUK: sd->status.luk = val; break; + default: + return -1; + } + + return val; } // Calculates the number of status points PC gets when leveling up (from level to level+1) int pc_gets_status_point(int level) { - if (battle_config.use_statpoint_table) //Use values from "db/statpoint.txt" - return (statp[level+1] - statp[level]); - else //Default increase - return ((level+15) / 5); + if (battle_config.use_statpoint_table) //Use values from "db/statpoint.txt" + return (statp[level+1] - statp[level]); + else //Default increase + return ((level+15) / 5); } /// Returns the number of stat points needed to change the specified stat by val. /// If val is negative, returns the number of stat points that would be needed to /// raise the specified stat from (current value - val) to current value. -int pc_need_status_point(struct map_session_data *sd, int type, int val) +int pc_need_status_point(struct map_session_data* sd, int type, int val) { - int low, high, sp = 0; + int low, high, sp = 0; - if (val == 0) - return 0; + if ( val == 0 ) + return 0; - low = pc_getstat(sd,type); + low = pc_getstat(sd,type); - if (low >= pc_maxparameter(sd) && val > 0) - return 0; // Official servers show '0' when max is reached + if ( low >= pc_maxparameter(sd) && val > 0 ) + return 0; // Official servers show '0' when max is reached - high = low + val; + high = low + val; - if (val < 0) - swap(low, high); + if ( val < 0 ) + swap(low, high); - for (; low < high; low++) + for ( ; low < high; low++ ) #ifdef RENEWAL // renewal status point cost formula - sp += (low < 100) ? (2 + (low - 1) / 10) : (16 + 4 * ((low - 100) / 5)); + sp += (low < 100) ? (2 + (low - 1) / 10) : (16 + 4 * ((low - 100) / 5)); #else - sp += (1 + (low + 9) / 10); + sp += ( 1 + (low + 9) / 10 ); #endif - return sp; + return sp; } /// Raises a stat by 1. @@ -5967,45 +5880,47 @@ int pc_need_status_point(struct map_session_data *sd, int type, int val) /// Subtracts stat points. /// /// @param type The stat to change (see enum _sp) -int pc_statusup(struct map_session_data *sd, int type) +int pc_statusup(struct map_session_data* sd, int type) { - int max, need, val; + int max, need, val; - nullpo_ret(sd); + nullpo_ret(sd); - // check conditions - need = pc_need_status_point(sd,type,1); - if (type < SP_STR || type > SP_LUK || need < 0 || need > sd->status.status_point) { - clif_statusupack(sd,type,0,0); - return 1; - } + // check conditions + need = pc_need_status_point(sd,type,1); + if( type < SP_STR || type > SP_LUK || need < 0 || need > sd->status.status_point ) + { + clif_statusupack(sd,type,0,0); + return 1; + } - // check limits - max = pc_maxparameter(sd); - if (pc_getstat(sd,type) >= max) { - clif_statusupack(sd,type,0,0); - return 1; - } + // check limits + max = pc_maxparameter(sd); + if( pc_getstat(sd,type) >= max ) + { + clif_statusupack(sd,type,0,0); + return 1; + } - // set new values - val = pc_setstat(sd, type, pc_getstat(sd,type) + 1); - sd->status.status_point -= need; + // set new values + val = pc_setstat(sd, type, pc_getstat(sd,type) + 1); + sd->status.status_point -= need; - status_calc_pc(sd,0); + status_calc_pc(sd,0); - // update increase cost indicator - if (need != pc_need_status_point(sd,type,1)) - clif_updatestatus(sd, SP_USTR + type-SP_STR); + // update increase cost indicator + if( need != pc_need_status_point(sd,type,1) ) + clif_updatestatus(sd, SP_USTR + type-SP_STR); - // update statpoint count - clif_updatestatus(sd,SP_STATUSPOINT); + // update statpoint count + clif_updatestatus(sd,SP_STATUSPOINT); - // update stat value - clif_statusupack(sd,type,1,val); // required - if (val > 255) - clif_updatestatus(sd,type); // send after the 'ack' to override the truncated value + // update stat value + clif_statusupack(sd,type,1,val); // required + if( val > 255 ) + clif_updatestatus(sd,type); // send after the 'ack' to override the truncated value - return 0; + return 0; } /// Raises a stat by the specified amount. @@ -6014,34 +5929,35 @@ int pc_statusup(struct map_session_data *sd, int type) /// /// @param type The stat to change (see enum _sp) /// @param val The stat increase amount. -int pc_statusup2(struct map_session_data *sd, int type, int val) +int pc_statusup2(struct map_session_data* sd, int type, int val) { - int max, need; - nullpo_ret(sd); + int max, need; + nullpo_ret(sd); - if (type < SP_STR || type > SP_LUK) { - clif_statusupack(sd,type,0,0); - return 1; - } + if( type < SP_STR || type > SP_LUK ) + { + clif_statusupack(sd,type,0,0); + return 1; + } - need = pc_need_status_point(sd,type,1); + need = pc_need_status_point(sd,type,1); - // set new value - max = pc_maxparameter(sd); - val = pc_setstat(sd, type, cap_value(pc_getstat(sd,type) + val, 1, max)); + // set new value + max = pc_maxparameter(sd); + val = pc_setstat(sd, type, cap_value(pc_getstat(sd,type) + val, 1, max)); - status_calc_pc(sd,0); + status_calc_pc(sd,0); - // update increase cost indicator - if (need != pc_need_status_point(sd,type,1)) - clif_updatestatus(sd, SP_USTR + type-SP_STR); + // update increase cost indicator + if( need != pc_need_status_point(sd,type,1) ) + clif_updatestatus(sd, SP_USTR + type-SP_STR); - // update stat value - clif_statusupack(sd,type,1,val); // required - if (val > 255) - clif_updatestatus(sd,type); // send after the 'ack' to override the truncated value + // update stat value + clif_statusupack(sd,type,1,val); // required + if( val > 255 ) + clif_updatestatus(sd,type); // send after the 'ack' to override the truncated value - return 0; + return 0; } /*========================================== @@ -6050,43 +5966,46 @@ int pc_statusup2(struct map_session_data *sd, int type, int val) *------------------------------------------*/ int pc_skillup(struct map_session_data *sd,int skill_num) { - nullpo_ret(sd); - - if (skill_num >= GD_SKILLBASE && skill_num < GD_SKILLBASE+MAX_GUILDSKILL) { - guild_skillup(sd, skill_num); - return 0; - } - - if (skill_num >= HM_SKILLBASE && skill_num < HM_SKILLBASE+MAX_HOMUNSKILL && sd->hd) { - merc_hom_skillup(sd->hd, skill_num); - return 0; - } - - if (skill_num < 0 || skill_num >= MAX_SKILL) - return 0; - - if (sd->status.skill_point > 0 && - sd->status.skill[skill_num].id && - sd->status.skill[skill_num].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] - 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--; - if (!skill_get_inf(skill_num)) - status_calc_pc(sd,0); // Only recalculate for passive skills. - else if (sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON)) - pc_calc_skilltree(sd); // Required to grant all TK Ranger skills. - else - pc_check_skilltree(sd, skill_num); // Check if a new skill can Lvlup - - clif_skillup(sd,skill_num); - clif_updatestatus(sd,SP_SKILLPOINT); - if (skill_num == GN_REMODELING_CART) /* cart weight info was updated by status_calc_pc */ - clif_updatestatus(sd,SP_CARTINFO); - if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown - clif_skillinfoblock(sd); - } - - return 0; + nullpo_ret(sd); + + if( skill_num >= GD_SKILLBASE && skill_num < GD_SKILLBASE+MAX_GUILDSKILL ) + { + guild_skillup(sd, skill_num); + return 0; + } + + if( skill_num >= HM_SKILLBASE && skill_num < HM_SKILLBASE+MAX_HOMUNSKILL && sd->hd ) + { + merc_hom_skillup(sd->hd, skill_num); + return 0; + } + + if( skill_num < 0 || skill_num >= MAX_SKILL ) + return 0; + + if( sd->status.skill_point > 0 && + sd->status.skill[skill_num].id && + sd->status.skill[skill_num].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] + 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--; + if( !skill_get_inf(skill_num) ) + status_calc_pc(sd,0); // Only recalculate for passive skills. + else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) ) + pc_calc_skilltree(sd); // Required to grant all TK Ranger skills. + else + pc_check_skilltree(sd, skill_num); // Check if a new skill can Lvlup + + clif_skillup(sd,skill_num); + clif_updatestatus(sd,SP_SKILLPOINT); + if( skill_num == GN_REMODELING_CART ) /* cart weight info was updated by status_calc_pc */ + clif_updatestatus(sd,SP_CARTINFO); + if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown + clif_skillinfoblock(sd); + } + + return 0; } /*========================================== @@ -6094,205 +6013,207 @@ int pc_skillup(struct map_session_data *sd,int skill_num) *------------------------------------------*/ int pc_allskillup(struct map_session_data *sd) { - int i,id; - - nullpo_ret(sd); - - for (i=0; i<MAX_SKILL; i++) { - if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) { - sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; - sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; - if (sd->status.skill[i].lv == 0) - sd->status.skill[i].id = 0; - } - } - - if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) { - //Get ALL skills except npc/guild ones. [Skotlex] - //and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage] - for (i=0; i<MAX_SKILL; i++) { - switch (i) { - case SG_DEVIL: - case MO_TRIPLEATTACK: - case RG_SNATCHER: - continue; - default: - if (!(skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL))) - if ((sd->status.skill[i].lv = skill_get_max(i))) //Nonexistant skills should return a max of 0 anyway. - sd->status.skill[i].id = i; - } - } - } else { - int inf2; - for (i=0; i < MAX_SKILL_TREE && (id=skill_tree[pc_class2idx(sd->status.class_)][i].id)>0; i++) { - inf2 = skill_get_inf2(id); - if ( - (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || - (inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) || - id==SG_DEVIL - ) - continue; //Cannot be learned normally. - - sd->status.skill[id].id = id; - sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); // celest - } - } - status_calc_pc(sd,0); - //Required because if you could level up all skills previously, - //the update will not be sent as only the lv variable changes. - clif_skillinfoblock(sd); - return 0; + int i,id; + + nullpo_ret(sd); + + for(i=0;i<MAX_SKILL;i++){ + if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) { + sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; + sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; + if (sd->status.skill[i].lv == 0) + sd->status.skill[i].id = 0; + } + } + + if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) + { //Get ALL skills except npc/guild ones. [Skotlex] + //and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage] + for(i=0;i<MAX_SKILL;i++){ + switch( i ) { + case SG_DEVIL: + case MO_TRIPLEATTACK: + case RG_SNATCHER: + continue; + default: + if( !(skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) ) + if ( ( sd->status.skill[i].lv = skill_get_max(i) ) )//Nonexistant skills should return a max of 0 anyway. + sd->status.skill[i].id = i; + } + } + } else { + int inf2; + for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[pc_class2idx(sd->status.class_)][i].id)>0;i++){ + inf2 = skill_get_inf2(id); + if ( + (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || + (inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) || + id==SG_DEVIL + ) + continue; //Cannot be learned normally. + + sd->status.skill[id].id = id; + sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); // celest + } + } + status_calc_pc(sd,0); + //Required because if you could level up all skills previously, + //the update will not be sent as only the lv variable changes. + clif_skillinfoblock(sd); + return 0; } /*========================================== * /resetlvl *------------------------------------------*/ -int pc_resetlvl(struct map_session_data *sd,int type) -{ - int i; - - nullpo_ret(sd); - - if (type != 3) //Also reset skills - pc_resetskill(sd, 0); - - if (type == 1) { - sd->status.skill_point=0; - sd->status.base_level=1; - sd->status.job_level=1; - sd->status.base_exp=0; - sd->status.job_exp=0; - if (sd->sc.option !=0) - sd->sc.option = 0; - - sd->status.str=1; - sd->status.agi=1; - sd->status.vit=1; - sd->status.int_=1; - sd->status.dex=1; - sd->status.luk=1; - if (sd->status.class_ == JOB_NOVICE_HIGH) { - 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) { - sd->status.skill_point=0; - sd->status.base_level=1; - sd->status.job_level=1; - sd->status.base_exp=0; - sd->status.job_exp=0; - } - if (type == 3) { - sd->status.base_level=1; - sd->status.base_exp=0; - } - if (type == 4) { - sd->status.job_level=1; - sd->status.job_exp=0; - } - - clif_updatestatus(sd,SP_STATUSPOINT); - clif_updatestatus(sd,SP_STR); - clif_updatestatus(sd,SP_AGI); - clif_updatestatus(sd,SP_VIT); - clif_updatestatus(sd,SP_INT); - clif_updatestatus(sd,SP_DEX); - clif_updatestatus(sd,SP_LUK); - clif_updatestatus(sd,SP_BASELEVEL); - clif_updatestatus(sd,SP_JOBLEVEL); - clif_updatestatus(sd,SP_STATUSPOINT); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_JOBEXP); - clif_updatestatus(sd,SP_NEXTBASEEXP); - clif_updatestatus(sd,SP_NEXTJOBEXP); - clif_updatestatus(sd,SP_SKILLPOINT); - - clif_updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris - clif_updatestatus(sd,SP_UAGI); - clif_updatestatus(sd,SP_UVIT); - clif_updatestatus(sd,SP_UINT); - clif_updatestatus(sd,SP_UDEX); - clif_updatestatus(sd,SP_ULUK); // End Addition - - for (i=0; i<EQI_MAX; 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],2); - } - - if ((type == 1 || type == 2 || type == 3) && sd->status.party_id) - party_send_levelup(sd); - - status_calc_pc(sd,0); - clif_skillinfoblock(sd); - - return 0; +int pc_resetlvl(struct map_session_data* sd,int type) +{ + int i; + + nullpo_ret(sd); + + if (type != 3) //Also reset skills + pc_resetskill(sd, 0); + + if(type == 1){ + sd->status.skill_point=0; + sd->status.base_level=1; + sd->status.job_level=1; + sd->status.base_exp=0; + sd->status.job_exp=0; + if(sd->sc.option !=0) + sd->sc.option = 0; + + sd->status.str=1; + sd->status.agi=1; + sd->status.vit=1; + sd->status.int_=1; + sd->status.dex=1; + sd->status.luk=1; + if(sd->status.class_ == JOB_NOVICE_HIGH) { + 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){ + sd->status.skill_point=0; + sd->status.base_level=1; + sd->status.job_level=1; + sd->status.base_exp=0; + sd->status.job_exp=0; + } + if(type == 3){ + sd->status.base_level=1; + sd->status.base_exp=0; + } + if(type == 4){ + sd->status.job_level=1; + sd->status.job_exp=0; + } + + clif_updatestatus(sd,SP_STATUSPOINT); + clif_updatestatus(sd,SP_STR); + clif_updatestatus(sd,SP_AGI); + clif_updatestatus(sd,SP_VIT); + clif_updatestatus(sd,SP_INT); + clif_updatestatus(sd,SP_DEX); + clif_updatestatus(sd,SP_LUK); + clif_updatestatus(sd,SP_BASELEVEL); + clif_updatestatus(sd,SP_JOBLEVEL); + clif_updatestatus(sd,SP_STATUSPOINT); + clif_updatestatus(sd,SP_BASEEXP); + clif_updatestatus(sd,SP_JOBEXP); + clif_updatestatus(sd,SP_NEXTBASEEXP); + clif_updatestatus(sd,SP_NEXTJOBEXP); + clif_updatestatus(sd,SP_SKILLPOINT); + + clif_updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris + clif_updatestatus(sd,SP_UAGI); + clif_updatestatus(sd,SP_UVIT); + clif_updatestatus(sd,SP_UINT); + clif_updatestatus(sd,SP_UDEX); + clif_updatestatus(sd,SP_ULUK); // End Addition + + for(i=0;i<EQI_MAX;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],2); + } + + if ((type == 1 || type == 2 || type == 3) && sd->status.party_id) + party_send_levelup(sd); + + status_calc_pc(sd,0); + clif_skillinfoblock(sd); + + return 0; } /*========================================== * /resetstate *------------------------------------------*/ -int pc_resetstate(struct map_session_data *sd) -{ - nullpo_ret(sd); - - if (battle_config.use_statpoint_table) { - // New statpoint table used here - Dexity - if (sd->status.base_level > MAX_LEVEL) { - //statp[] goes out of bounds, can't reset! - ShowError("pc_resetstate: Can't reset stats of %d:%d, the base level (%d) is greater than the max level supported (%d)\n", - sd->status.account_id, sd->status.char_id, sd->status.base_level, MAX_LEVEL); - return 0; - } - - sd->status.status_point = statp[sd->status.base_level] + (sd->class_&JOBL_UPPER ? 52 : 0); // extra 52+48=100 stat points - } else { - int add=0; - add += pc_need_status_point(sd, SP_STR, 1-pc_getstat(sd, SP_STR)); - add += pc_need_status_point(sd, SP_AGI, 1-pc_getstat(sd, SP_AGI)); - add += pc_need_status_point(sd, SP_VIT, 1-pc_getstat(sd, SP_VIT)); - add += pc_need_status_point(sd, SP_INT, 1-pc_getstat(sd, SP_INT)); - add += pc_need_status_point(sd, SP_DEX, 1-pc_getstat(sd, SP_DEX)); - add += pc_need_status_point(sd, SP_LUK, 1-pc_getstat(sd, SP_LUK)); - - sd->status.status_point+=add; - } - - pc_setstat(sd, SP_STR, 1); - pc_setstat(sd, SP_AGI, 1); - pc_setstat(sd, SP_VIT, 1); - pc_setstat(sd, SP_INT, 1); - pc_setstat(sd, SP_DEX, 1); - pc_setstat(sd, SP_LUK, 1); - - clif_updatestatus(sd,SP_STR); - clif_updatestatus(sd,SP_AGI); - clif_updatestatus(sd,SP_VIT); - clif_updatestatus(sd,SP_INT); - clif_updatestatus(sd,SP_DEX); - clif_updatestatus(sd,SP_LUK); - - clif_updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris - clif_updatestatus(sd,SP_UAGI); - clif_updatestatus(sd,SP_UVIT); - clif_updatestatus(sd,SP_UINT); - clif_updatestatus(sd,SP_UDEX); - clif_updatestatus(sd,SP_ULUK); // End Addition - - clif_updatestatus(sd,SP_STATUSPOINT); - - if (sd->mission_mobid) { //bugreport:2200 - sd->mission_mobid = 0; - sd->mission_count = 0; - pc_setglobalreg(sd,"TK_MISSION_ID", 0); - } - - status_calc_pc(sd,0); - - return 1; +int pc_resetstate(struct map_session_data* sd) +{ + nullpo_ret(sd); + + if (battle_config.use_statpoint_table) + { // New statpoint table used here - Dexity + if (sd->status.base_level > MAX_LEVEL) + { //statp[] goes out of bounds, can't reset! + ShowError("pc_resetstate: Can't reset stats of %d:%d, the base level (%d) is greater than the max level supported (%d)\n", + sd->status.account_id, sd->status.char_id, sd->status.base_level, MAX_LEVEL); + return 0; + } + + sd->status.status_point = statp[sd->status.base_level] + ( sd->class_&JOBL_UPPER ? 52 : 0 ); // extra 52+48=100 stat points + } + else + { + int add=0; + add += pc_need_status_point(sd, SP_STR, 1-pc_getstat(sd, SP_STR)); + add += pc_need_status_point(sd, SP_AGI, 1-pc_getstat(sd, SP_AGI)); + add += pc_need_status_point(sd, SP_VIT, 1-pc_getstat(sd, SP_VIT)); + add += pc_need_status_point(sd, SP_INT, 1-pc_getstat(sd, SP_INT)); + add += pc_need_status_point(sd, SP_DEX, 1-pc_getstat(sd, SP_DEX)); + add += pc_need_status_point(sd, SP_LUK, 1-pc_getstat(sd, SP_LUK)); + + sd->status.status_point+=add; + } + + pc_setstat(sd, SP_STR, 1); + pc_setstat(sd, SP_AGI, 1); + pc_setstat(sd, SP_VIT, 1); + pc_setstat(sd, SP_INT, 1); + pc_setstat(sd, SP_DEX, 1); + pc_setstat(sd, SP_LUK, 1); + + clif_updatestatus(sd,SP_STR); + clif_updatestatus(sd,SP_AGI); + clif_updatestatus(sd,SP_VIT); + clif_updatestatus(sd,SP_INT); + clif_updatestatus(sd,SP_DEX); + clif_updatestatus(sd,SP_LUK); + + clif_updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris + clif_updatestatus(sd,SP_UAGI); + clif_updatestatus(sd,SP_UVIT); + clif_updatestatus(sd,SP_UINT); + clif_updatestatus(sd,SP_UDEX); + clif_updatestatus(sd,SP_ULUK); // End Addition + + clif_updatestatus(sd,SP_STATUSPOINT); + + if( sd->mission_mobid ) { //bugreport:2200 + sd->mission_mobid = 0; + sd->mission_count = 0; + pc_setglobalreg(sd,"TK_MISSION_ID", 0); + } + + status_calc_pc(sd,0); + + return 1; } /*========================================== @@ -6301,215 +6222,210 @@ int pc_resetstate(struct map_session_data *sd) * if flag&2, just count total amount of skill points used by player, do not really reset. * if flag&4, just reset the skills if the player class is a bard/dancer type (for changesex.) *------------------------------------------*/ -int pc_resetskill(struct map_session_data *sd, int flag) -{ - int i, lv, inf2, skill_point=0; - nullpo_ret(sd); - - if (flag&4 && (sd->class_&MAPID_UPPERMASK) != MAPID_BARDDANCER) - return 0; - - if (!(flag&2)) { //Remove stuff lost when resetting skills. - - /** - * It has been confirmed on official server that when you reset skills with a ranked tweakwon your skills are not reset (because you have all of them anyway) - **/ - if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON)) - return 0; - - if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) - clif_status_load(&sd->bl, SI_DEVIL, 0); //Remove perma blindness due to skill-reset. [Skotlex] - i = sd->sc.option; - if (i&OPTION_RIDING && pc_checkskill(sd, KN_RIDING)) - i &= ~OPTION_RIDING; - if (i&OPTION_FALCON && pc_checkskill(sd, HT_FALCON)) - i &= ~OPTION_FALCON; - if (i&OPTION_DRAGON && pc_checkskill(sd, RK_DRAGONTRAINING)) - i &= ~OPTION_DRAGON; - if (i&OPTION_WUG && pc_checkskill(sd, RA_WUGMASTERY)) - i &= ~OPTION_WUG; - if (i&OPTION_WUGRIDER && pc_checkskill(sd, RA_WUGRIDER)) - i &= ~OPTION_WUGRIDER; - if (i&OPTION_MADOGEAR && (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC) - i &= ~OPTION_MADOGEAR; - if (i&OPTION_MOUNTING) - i &= ~OPTION_MOUNTING; +int pc_resetskill(struct map_session_data* sd, int flag) +{ + int i, lv, inf2, skill_point=0; + nullpo_ret(sd); + + if( flag&4 && (sd->class_&MAPID_UPPERMASK) != MAPID_BARDDANCER ) + return 0; + + if( !(flag&2) ) { //Remove stuff lost when resetting skills. + + /** + * It has been confirmed on official server that when you reset skills with a ranked tweakwon your skills are not reset (because you have all of them anyway) + **/ + if( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) ) + return 0; + + if( pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd) ) + clif_status_load(&sd->bl, SI_DEVIL, 0); //Remove perma blindness due to skill-reset. [Skotlex] + i = sd->sc.option; + if( i&OPTION_RIDING && pc_checkskill(sd, KN_RIDING) ) + i &= ~OPTION_RIDING; + if( i&OPTION_FALCON && pc_checkskill(sd, HT_FALCON) ) + i &= ~OPTION_FALCON; + if( i&OPTION_DRAGON && pc_checkskill(sd, RK_DRAGONTRAINING) ) + i &= ~OPTION_DRAGON; + if( i&OPTION_WUG && pc_checkskill(sd, RA_WUGMASTERY) ) + i &= ~OPTION_WUG; + if( i&OPTION_WUGRIDER && pc_checkskill(sd, RA_WUGRIDER) ) + i &= ~OPTION_WUGRIDER; + if( i&OPTION_MADOGEAR && ( sd->class_&MAPID_THIRDMASK ) == MAPID_MECHANIC ) + i &= ~OPTION_MADOGEAR; + if( i&OPTION_MOUNTING ) + i &= ~OPTION_MOUNTING; #ifndef NEW_CARTS - if (i&OPTION_CART && pc_checkskill(sd, MC_PUSHCART)) - i &= ~OPTION_CART; + if( i&OPTION_CART && pc_checkskill(sd, MC_PUSHCART) ) + i &= ~OPTION_CART; #else - if (sd->sc.data[SC_PUSH_CART]) - pc_setcart(sd, 0); + if( sd->sc.data[SC_PUSH_CART] ) + pc_setcart(sd, 0); #endif - if (i != sd->sc.option) - pc_setoption(sd, i); - - if (merc_is_hom_active(sd->hd) && pc_checkskill(sd, AM_CALLHOMUN)) - merc_hom_vaporize(sd, 0); - } - - for (i = 1; i < MAX_SKILL; i++) { - lv = sd->status.skill[i].lv; - if (lv < 1) continue; - - inf2 = skill_get_inf2(i); - - if (inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Avoid reseting wedding/linker skills. - continue; - - // Don't reset trick dead if not a novice/baby - if (i == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE) { - sd->status.skill[i].lv = 0; - sd->status.skill[i].flag = 0; - continue; - } - - // do not reset basic skill - if (i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE) - continue; - - if (flag&4 && !skill_ischangesex(i)) - continue; - - if (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) { - //Only handle quest skills in a special way when you can't learn them manually - if (battle_config.quest_skill_reset && !(flag&2)) { - //Wipe them - sd->status.skill[i].lv = 0; - sd->status.skill[i].flag = 0; - } - continue; - } - if (sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) - skill_point += lv; - else if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) - skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0); - - if (!(flag&2)) { - // reset - sd->status.skill[i].lv = 0; - sd->status.skill[i].flag = 0; - } - } - - if (flag&2 || !skill_point) return skill_point; - - sd->status.skill_point += skill_point; - - if (flag&1) { - clif_updatestatus(sd,SP_SKILLPOINT); - clif_skillinfoblock(sd); - status_calc_pc(sd,0); - } - - return skill_point; + if( i != sd->sc.option ) + pc_setoption(sd, i); + + if( merc_is_hom_active(sd->hd) && pc_checkskill(sd, AM_CALLHOMUN) ) + merc_hom_vaporize(sd, 0); + } + + for( i = 1; i < MAX_SKILL; i++ ) + { + lv = sd->status.skill[i].lv; + if (lv < 1) continue; + + inf2 = skill_get_inf2(i); + + if( inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL) ) //Avoid reseting wedding/linker skills. + continue; + + // Don't reset trick dead if not a novice/baby + if( i == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) + { + sd->status.skill[i].lv = 0; + sd->status.skill[i].flag = 0; + continue; + } + + // do not reset basic skill + if( i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) + continue; + + if( flag&4 && !skill_ischangesex(i) ) + continue; + + if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn ) + { //Only handle quest skills in a special way when you can't learn them manually + if( battle_config.quest_skill_reset && !(flag&2) ) + { //Wipe them + sd->status.skill[i].lv = 0; + sd->status.skill[i].flag = 0; + } + continue; + } + if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT ) + skill_point += lv; + else + if( sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0 ) + skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0); + + if( !(flag&2) ) + {// reset + sd->status.skill[i].lv = 0; + sd->status.skill[i].flag = 0; + } + } + + if( flag&2 || !skill_point ) return skill_point; + + sd->status.skill_point += skill_point; + + if( flag&1 ) + { + clif_updatestatus(sd,SP_SKILLPOINT); + clif_skillinfoblock(sd); + status_calc_pc(sd,0); + } + + return skill_point; } /*========================================== * /resetfeel [Komurka] *------------------------------------------*/ -int pc_resetfeel(struct map_session_data *sd) +int pc_resetfeel(struct map_session_data* sd) { - int i; - nullpo_ret(sd); + int i; + nullpo_ret(sd); - for (i=0; i<MAX_PC_FEELHATE; i++) { - sd->feel_map[i].m = -1; - sd->feel_map[i].index = 0; - pc_setglobalreg(sd,sg_info[i].feel_var,0); - } + for (i=0; i<MAX_PC_FEELHATE; i++) + { + sd->feel_map[i].m = -1; + sd->feel_map[i].index = 0; + pc_setglobalreg(sd,sg_info[i].feel_var,0); + } - return 0; + return 0; } -int pc_resethate(struct map_session_data *sd) +int pc_resethate(struct map_session_data* sd) { - int i; - nullpo_ret(sd); + int i; + nullpo_ret(sd); - for (i=0; i<3; i++) { - sd->hate_mob[i] = -1; - pc_setglobalreg(sd,sg_info[i].hate_var,0); - } - return 0; + for (i=0; i<3; i++) + { + sd->hate_mob[i] = -1; + pc_setglobalreg(sd,sg_info[i].hate_var,0); + } + return 0; } int pc_skillatk_bonus(struct map_session_data *sd, int skill_num) { - int i, bonus = 0; + int i, bonus = 0; - ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == skill_num); - if (i < ARRAYLENGTH(sd->skillatk)) bonus = sd->skillatk[i].val; + ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == skill_num); + if( i < ARRAYLENGTH(sd->skillatk) ) bonus = sd->skillatk[i].val; - return bonus; + return bonus; } -int pc_skillheal_bonus(struct map_session_data *sd, int skill_num) -{ - int i, bonus = sd->bonus.add_heal_rate; +int pc_skillheal_bonus(struct map_session_data *sd, int skill_num) { + int i, bonus = sd->bonus.add_heal_rate; - if (bonus) { - switch (skill_num) { - case AL_HEAL: - if (!(battle_config.skill_add_heal_rate&1)) bonus = 0; - break; - case PR_SANCTUARY: - if (!(battle_config.skill_add_heal_rate&2)) bonus = 0; - break; - case AM_POTIONPITCHER: - if (!(battle_config.skill_add_heal_rate&4)) bonus = 0; - break; - case CR_SLIMPITCHER: - if (!(battle_config.skill_add_heal_rate&8)) bonus = 0; - break; - case BA_APPLEIDUN: - if (!(battle_config.skill_add_heal_rate&16)) bonus = 0; - break; - } - } + if( bonus ) { + switch( skill_num ) { + case AL_HEAL: if( !(battle_config.skill_add_heal_rate&1) ) bonus = 0; break; + case PR_SANCTUARY: if( !(battle_config.skill_add_heal_rate&2) ) bonus = 0; break; + case AM_POTIONPITCHER: if( !(battle_config.skill_add_heal_rate&4) ) bonus = 0; break; + case CR_SLIMPITCHER: if( !(battle_config.skill_add_heal_rate&8) ) bonus = 0; break; + case BA_APPLEIDUN: if( !(battle_config.skill_add_heal_rate&16)) bonus = 0; break; + } + } - ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == skill_num); + ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == skill_num); - if (i < ARRAYLENGTH(sd->skillheal)) - bonus += sd->skillheal[i].val; + if( i < ARRAYLENGTH(sd->skillheal) ) + bonus += sd->skillheal[i].val; - return bonus; + return bonus; } -int pc_skillheal2_bonus(struct map_session_data *sd, int skill_num) -{ - int i, bonus = sd->bonus.add_heal2_rate; +int pc_skillheal2_bonus(struct map_session_data *sd, int skill_num) { + int i, bonus = sd->bonus.add_heal2_rate; - ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == skill_num); + ARR_FIND(0, ARRAYLENGTH(sd->skillheal2), i, sd->skillheal2[i].id == skill_num); - if (i < ARRAYLENGTH(sd->skillheal2)) - bonus += sd->skillheal2[i].val; + if( i < ARRAYLENGTH(sd->skillheal2) ) + bonus += sd->skillheal2[i].val; - return bonus; + return bonus; } -void pc_respawn(struct map_session_data *sd, clr_type clrtype) +void pc_respawn(struct map_session_data* sd, clr_type clrtype) { - if (!pc_isdead(sd)) - return; // not applicable - if (sd->bg_id && bg_member_respawn(sd)) - return; // member revived by battleground + if( !pc_isdead(sd) ) + return; // not applicable + if( sd->bg_id && bg_member_respawn(sd) ) + return; // member revived by battleground - pc_setstand(sd); - pc_setrestartvalue(sd,3); - if (pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype)) - clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet. + pc_setstand(sd); + pc_setrestartvalue(sd,3); + if( pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype) ) + clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet. } static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd = map_id2sd(id); - if (sd != NULL) { - sd->pvp_point=0; - pc_respawn(sd,CLR_OUTSIGHT); - } + struct map_session_data *sd = map_id2sd(id); + if( sd != NULL ) + { + sd->pvp_point=0; + pc_respawn(sd,CLR_OUTSIGHT); + } - return 0; + return 0; } /*========================================== @@ -6517,28 +6433,29 @@ static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int hp, unsigned int sp) { - if (sp) clif_updatestatus(sd,SP_SP); - if (hp) clif_updatestatus(sd,SP_HP); - else return; + if (sp) clif_updatestatus(sd,SP_SP); + if (hp) clif_updatestatus(sd,SP_HP); + else return; - if (!src || src == &sd->bl) - return; + if( !src || src == &sd->bl ) + return; - if (pc_issit(sd)) { - pc_setstand(sd); - skill_sit(sd,0); - } + if( pc_issit(sd) ) + { + pc_setstand(sd); + skill_sit(sd,0); + } - if (sd->progressbar.npc_id) - clif_progressbar_abort(sd); + if( sd->progressbar.npc_id ) + clif_progressbar_abort(sd); - if (sd->status.pet_id > 0 && sd->pd && battle_config.pet_damage_support) - pet_target_check(sd,src,1); + if( sd->status.pet_id > 0 && sd->pd && battle_config.pet_damage_support ) + pet_target_check(sd,src,1); - if (sd->status.ele_id > 0) - elemental_set_target(sd,src); + if( sd->status.ele_id > 0 ) + elemental_set_target(sd,src); - sd->canlog_tick = gettick(); + sd->canlog_tick = gettick(); } /*========================================== @@ -6546,451 +6463,398 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h *------------------------------------------*/ int pc_dead(struct map_session_data *sd,struct block_list *src) { - int i=0,j=0,k=0; - unsigned int tick = gettick(); - - for (k = 0; k < 5; k++) - if (sd->devotion[k]) { - struct map_session_data *devsd = map_id2sd(sd->devotion[k]); - if (devsd) - status_change_end(&devsd->bl, SC_DEVOTION, INVALID_TIMER); - sd->devotion[k] = 0; - } - - if (sd->status.pet_id > 0 && sd->pd) { - struct pet_data *pd = sd->pd; - if (!map[sd->bl.m].flag.noexppenalty) { - pet_set_intimate(pd, pd->pet.intimate - pd->petDB->die); - if (pd->pet.intimate < 0) - pd->pet.intimate = 0; - clif_send_petdata(sd,sd->pd,1,pd->pet.intimate); - } - if (sd->pd->target_id) // Unlock all targets... - pet_unlocktarget(sd->pd); - } - - if (sd->status.hom_id > 0) { - if (battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE]) - merc_hom_vaporize(sd, 0); - } - - if (sd->md) - merc_delete(sd->md, 3); // Your mercenary soldier has ran away. - - if (sd->ed) - elemental_delete(sd->ed, 0); - - // Leave duel if you die [LuzZza] - if (battle_config.duel_autoleave_when_die) { - if (sd->duel_group > 0) - duel_leave(sd->duel_group, sd); - if (sd->duel_invite > 0) - duel_reject(sd->duel_invite, sd); - } - - pc_setglobalreg(sd,"PC_DIE_COUNTER",sd->die_counter+1); - pc_setparam(sd, SP_KILLERRID, src?src->id:0); - - if (sd->bg_id) { - struct battleground_data *bg; - if ((bg = bg_team_search(sd->bg_id)) != NULL && bg->die_event[0]) - npc_event(sd, bg->die_event, 0); - } - - // Clear anything NPC-related when you die and was interacting with one. - if (sd->npc_id) { - if (sd->state.using_fake_npc){ - clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); - sd->state.using_fake_npc = 0; - } - if (sd->state.menu_or_input) - sd->state.menu_or_input = 0; - if (sd->npc_menu) - sd->npc_menu = 0; - sd->npc_id = 0; - if(sd->st && sd->st->state != END) - sd->st->state = END; - } - - npc_script_event(sd,NPCE_DIE); - - /* e.g. not killed thru pc_damage */ - if (pc_issit(sd)) { - clif_status_load(&sd->bl,SI_SIT,0); - } - - pc_setdead(sd); - //Reset menu skills/item skills - if (sd->skillitem) - sd->skillitem = sd->skillitemlv = 0; - if (sd->menuskill_id) - sd->menuskill_id = sd->menuskill_val = 0; - //Reset ticks. - sd->hp_loss.tick = sd->sp_loss.tick = sd->hp_regen.tick = sd->sp_regen.tick = 0; - - if (sd && sd->spiritball) - pc_delspiritball(sd,sd->spiritball,0); - - for (i = 1; i < 5; i++) - pc_del_talisman(sd, sd->talisman[i], i); - - if (src) - switch (src->type) { - case BL_MOB: { - struct mob_data *md=(struct mob_data *)src; - if (md->target_id==sd->bl.id) - mob_unlocktarget(md,tick); - if (battle_config.mobs_level_up && md->status.hp && - (unsigned int)md->level < pc_maxbaselv(sd) && - !md->guardian_data && !md->special_state.ai// Guardians/summons should not level. [Skotlex] - ) { // monster level up [Valaris] - clif_misceffect(&md->bl,0); - md->level++; - status_calc_mob(md, 0); - status_percent_heal(src,10,0); - - if (battle_config.show_mob_info&4) { - // update name with new level - clif_charnameack(0, &md->bl); - } - } - src = battle_get_master(src); // Maybe Player Summon - } - break; - case BL_PET: //Pass on to master... - src = &((TBL_PET *)src)->msd->bl; - break; - case BL_HOM: - src = &((TBL_HOM *)src)->master->bl; - break; - case BL_MER: - src = &((TBL_MER *)src)->master->bl; - break; - } - - if (src && src->type == BL_PC) { - struct map_session_data *ssd = (struct map_session_data *)src; - pc_setparam(ssd, SP_KILLEDRID, sd->bl.id); - npc_script_event(ssd, NPCE_KILLPC); - - if (battle_config.pk_mode&2) { - ssd->status.manner -= 5; - if (ssd->status.manner < 0) - sc_start(src,SC_NOCHAT,100,0,0); + int i=0,j=0,k=0; + unsigned int tick = gettick(); + + for(k = 0; k < 5; k++) + if (sd->devotion[k]){ + struct map_session_data *devsd = map_id2sd(sd->devotion[k]); + if (devsd) + status_change_end(&devsd->bl, SC_DEVOTION, INVALID_TIMER); + sd->devotion[k] = 0; + } + + if(sd->status.pet_id > 0 && sd->pd) { + struct pet_data *pd = sd->pd; + if( !map[sd->bl.m].flag.noexppenalty ) { + pet_set_intimate(pd, pd->pet.intimate - pd->petDB->die); + if( pd->pet.intimate < 0 ) + pd->pet.intimate = 0; + clif_send_petdata(sd,sd->pd,1,pd->pet.intimate); + } + if( sd->pd->target_id ) // Unlock all targets... + pet_unlocktarget(sd->pd); + } + + if (sd->status.hom_id > 0){ + if(battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE]) + merc_hom_vaporize(sd, 0); + } + + if( sd->md ) + merc_delete(sd->md, 3); // Your mercenary soldier has ran away. + + if( sd->ed ) + elemental_delete(sd->ed, 0); + + // Leave duel if you die [LuzZza] + if(battle_config.duel_autoleave_when_die) { + if(sd->duel_group > 0) + duel_leave(sd->duel_group, sd); + if(sd->duel_invite > 0) + duel_reject(sd->duel_invite, sd); + } + + pc_setglobalreg(sd,"PC_DIE_COUNTER",sd->die_counter+1); + pc_setparam(sd, SP_KILLERRID, src?src->id:0); + + if( sd->bg_id ) { + struct battleground_data *bg; + if( (bg = bg_team_search(sd->bg_id)) != NULL && bg->die_event[0] ) + npc_event(sd, bg->die_event, 0); + } + + // Clear anything NPC-related when you die and was interacting with one. + if (sd->npc_id) + { + if (sd->state.using_fake_npc) + sd->state.using_fake_npc = 0; + if (sd->state.menu_or_input) + sd->state.menu_or_input = 0; + if (sd->npc_menu) + sd->npc_menu = 0; + + npc_event_dequeue(sd); + } + + npc_script_event(sd,NPCE_DIE); + + /* e.g. not killed thru pc_damage */ + if( pc_issit(sd) ) { + clif_status_load(&sd->bl,SI_SIT,0); + } + + pc_setdead(sd); + //Reset menu skills/item skills + if (sd->skillitem) + sd->skillitem = sd->skillitemlv = 0; + if (sd->menuskill_id) + sd->menuskill_id = sd->menuskill_val = 0; + //Reset ticks. + sd->hp_loss.tick = sd->sp_loss.tick = sd->hp_regen.tick = sd->sp_regen.tick = 0; + + if ( sd && sd->spiritball ) + pc_delspiritball(sd,sd->spiritball,0); + + for(i = 1; i < 5; i++) + pc_del_talisman(sd, sd->talisman[i], i); + + if (src) + switch (src->type) { + case BL_MOB: + { + struct mob_data *md=(struct mob_data *)src; + if(md->target_id==sd->bl.id) + mob_unlocktarget(md,tick); + if(battle_config.mobs_level_up && md->status.hp && + (unsigned int)md->level < pc_maxbaselv(sd) && + !md->guardian_data && !md->special_state.ai// Guardians/summons should not level. [Skotlex] + ) { // monster level up [Valaris] + clif_misceffect(&md->bl,0); + md->level++; + status_calc_mob(md, 0); + status_percent_heal(src,10,0); + + if( battle_config.show_mob_info&4 ) + {// update name with new level + clif_charnameack(0, &md->bl); + } + } + src = battle_get_master(src); // Maybe Player Summon + } + break; + case BL_PET: //Pass on to master... + src = &((TBL_PET*)src)->msd->bl; + break; + case BL_HOM: + src = &((TBL_HOM*)src)->master->bl; + break; + case BL_MER: + src = &((TBL_MER*)src)->master->bl; + break; + } + + if (src && src->type == BL_PC) + { + struct map_session_data *ssd = (struct map_session_data *)src; + pc_setparam(ssd, SP_KILLEDRID, sd->bl.id); + npc_script_event(ssd, NPCE_KILLPC); + + if (battle_config.pk_mode&2) { + ssd->status.manner -= 5; + if(ssd->status.manner < 0) + sc_start(src,SC_NOCHAT,100,0,0); #if 0 - // PK/Karma system code (not enabled yet) [celest] - // originally from Kade Online, so i don't know if any of these is correct ^^; - // note: karma is measured REVERSE, so more karma = more 'evil' / less honourable, - // karma going down = more 'good' / more honourable. - // The Karma System way... + // PK/Karma system code (not enabled yet) [celest] + // originally from Kade Online, so i don't know if any of these is correct ^^; + // note: karma is measured REVERSE, so more karma = more 'evil' / less honourable, + // karma going down = more 'good' / more honourable. + // The Karma System way... - if (sd->status.karma > ssd->status.karma) { // If player killed was more evil - sd->status.karma--; - ssd->status.karma--; - } else if (sd->status.karma < ssd->status.karma) // If player killed was more good - ssd->status.karma++; + if (sd->status.karma > ssd->status.karma) { // If player killed was more evil + sd->status.karma--; + ssd->status.karma--; + } + else if (sd->status.karma < ssd->status.karma) // If player killed was more good + ssd->status.karma++; - // or the PK System way... + // or the PK System way... - if (sd->status.karma > 0) // player killed is dishonourable? - ssd->status.karma--; // honour points earned - sd->status.karma++; // honour points lost + if (sd->status.karma > 0) // player killed is dishonourable? + ssd->status.karma--; // honour points earned + sd->status.karma++; // honour points lost - // To-do: Receive exp on certain occasions + // To-do: Receive exp on certain occasions #endif - } - } - - if (battle_config.bone_drop==2 - || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp)) { - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid=ITEMID_SKULL_; - item_tmp.identify=1; - item_tmp.card[0]=CARD0_CREATE; - item_tmp.card[1]=0; - item_tmp.card[2]=GetWord(sd->status.char_id,0); // CharId - item_tmp.card[3]=GetWord(sd->status.char_id,1); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - - // activate Steel body if a super novice dies at 99+% exp [celest] - if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && !sd->state.snovice_dead_flag) { - unsigned int next = pc_nextbaseexp(sd); - if (next == 0) next = pc_thisbaseexp(sd); - if (get_percentage(sd->status.base_exp,next) >= 99) { - sd->state.snovice_dead_flag = 1; - pc_setstand(sd); - status_percent_heal(&sd->bl, 100, 100); - clif_resurrection(&sd->bl, 1); - if (battle_config.pc_invincible_time) - pc_setinvincibletimer(sd, battle_config.pc_invincible_time); - sc_start(&sd->bl,status_skill2sc(MO_STEELBODY),100,1,skill_get_time(MO_STEELBODY,1)); - if (map_flag_gvg(sd->bl.m)) - pc_respawn_timer(INVALID_TIMER, gettick(), sd->bl.id, 0); - return 0; - } - } - - // changed penalty options, added death by player if pk_mode [Valaris] - if (battle_config.death_penalty_type - && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty - && !map[sd->bl.m].flag.noexppenalty && !map_flag_gvg(sd->bl.m) - && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_LIFEINSURANCE]) { - unsigned int base_penalty =0; - if (battle_config.death_penalty_base > 0) { - switch (battle_config.death_penalty_type) { - case 1: - base_penalty = (unsigned int)((double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000); - break; - case 2: - base_penalty = (unsigned int)((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000); - break; - } - if (base_penalty) { - if (battle_config.pk_mode && src && src->type==BL_PC) - base_penalty*=2; - sd->status.base_exp -= min(sd->status.base_exp, base_penalty); - clif_updatestatus(sd,SP_BASEEXP); - } - } - if (battle_config.death_penalty_job > 0) { - base_penalty = 0; - switch (battle_config.death_penalty_type) { - case 1: - base_penalty = (unsigned int)((double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000); - break; - case 2: - base_penalty = (unsigned int)((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000); - break; - } - if (base_penalty) { - if (battle_config.pk_mode && src && src->type==BL_PC) - base_penalty*=2; - sd->status.job_exp -= min(sd->status.job_exp, base_penalty); - clif_updatestatus(sd,SP_JOBEXP); - } - } - if (battle_config.zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) { - base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.); - if (base_penalty) - pc_payzeny(sd, base_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL); - } - } - - if (map[sd->bl.m].flag.pvp_nightmaredrop) { - // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker] - for (j=0; j<MAX_DROP_PER_MAP; j++) { - int id = map[sd->bl.m].drop_list[j].drop_id; - int type = map[sd->bl.m].drop_list[j].drop_type; - int per = map[sd->bl.m].drop_list[j].drop_per; - if (id == 0) - continue; - if (id == -1) { - int eq_num=0,eq_n[MAX_INVENTORY]; - memset(eq_n,0,sizeof(eq_n)); - for (i=0; i<MAX_INVENTORY; i++) { - int k; - if ((type == 1 && !sd->status.inventory[i].equip) - || (type == 2 && sd->status.inventory[i].equip) - || type == 3) { - ARR_FIND(0, MAX_INVENTORY, k, eq_n[k] <= 0); - if (k < MAX_INVENTORY) - eq_n[k] = i; - - eq_num++; - } - } - if (eq_num > 0) { - int n = eq_n[rnd()%eq_num]; - if (rnd()%10000 < per) { - if (sd->status.inventory[n].equip) - pc_unequipitem(sd,n,3); - pc_dropitem(sd,n,1); - } - } - } else if (id > 0) { - for (i=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid == id - && rnd()%10000 < per - && ((type == 1 && !sd->status.inventory[i].equip) - || (type == 2 && sd->status.inventory[i].equip) - || type == 3)) { - if (sd->status.inventory[i].equip) - pc_unequipitem(sd,i,3); - pc_dropitem(sd,i,1); - break; - } - } - } - } - } - // pvp - // disable certain pvp functions on pk_mode [Valaris] - if (map[sd->bl.m].flag.pvp && !battle_config.pk_mode && !map[sd->bl.m].flag.pvp_nocalcrank) { - sd->pvp_point -= 5; - sd->pvp_lost++; - if (src && src->type == BL_PC) { - struct map_session_data *ssd = (struct map_session_data *)src; - ssd->pvp_point++; - ssd->pvp_won++; - } - if (sd->pvp_point < 0) { - add_timer(tick+1000, pc_respawn_timer,sd->bl.id,0); - return 1|8; - } - } - //GvG - if (map_flag_gvg(sd->bl.m)) { - add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0); - return 1|8; - } else if (sd->bg_id) { - struct battleground_data *bg = bg_team_search(sd->bg_id); - if (bg && bg->mapindex > 0) { - // Respawn by BG - add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0); - return 1|8; - } - } - - - //Reset "can log out" tick. - if (battle_config.prevent_logout) - sd->canlog_tick = gettick() - battle_config.prevent_logout; - return 1; -} - -void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) -{ - if (hp) clif_updatestatus(sd,SP_HP); - if (sp) clif_updatestatus(sd,SP_SP); - - pc_setstand(sd); - if (battle_config.pc_invincible_time > 0) - pc_setinvincibletimer(sd, battle_config.pc_invincible_time); - - if (sd->state.gmaster_flag) { - guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->state.gmaster_flag,GD_LEADERSHIP)); - guild_guildaura_refresh(sd,GD_GLORYWOUNDS,guild_checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS)); - guild_guildaura_refresh(sd,GD_SOULCOLD,guild_checkskill(sd->state.gmaster_flag,GD_SOULCOLD)); - guild_guildaura_refresh(sd,GD_HAWKEYES,guild_checkskill(sd->state.gmaster_flag,GD_HAWKEYES)); - } + } + } + + if(battle_config.bone_drop==2 + || (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp)) + { + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid=ITEMID_SKULL_; + item_tmp.identify=1; + item_tmp.card[0]=CARD0_CREATE; + item_tmp.card[1]=0; + item_tmp.card[2]=GetWord(sd->status.char_id,0); // CharId + item_tmp.card[3]=GetWord(sd->status.char_id,1); + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + + // activate Steel body if a super novice dies at 99+% exp [celest] + if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && !sd->state.snovice_dead_flag) + { + unsigned int next = pc_nextbaseexp(sd); + if( next == 0 ) next = pc_thisbaseexp(sd); + if( get_percentage(sd->status.base_exp,next) >= 99 ) { + sd->state.snovice_dead_flag = 1; + pc_setstand(sd); + status_percent_heal(&sd->bl, 100, 100); + clif_resurrection(&sd->bl, 1); + if(battle_config.pc_invincible_time) + pc_setinvincibletimer(sd, battle_config.pc_invincible_time); + sc_start(&sd->bl,status_skill2sc(MO_STEELBODY),100,1,skill_get_time(MO_STEELBODY,1)); + if(map_flag_gvg(sd->bl.m)) + pc_respawn_timer(INVALID_TIMER, gettick(), sd->bl.id, 0); + return 0; + } + } + + // changed penalty options, added death by player if pk_mode [Valaris] + if(battle_config.death_penalty_type + && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty + && !map[sd->bl.m].flag.noexppenalty && !map_flag_gvg(sd->bl.m) + && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_LIFEINSURANCE]) + { + unsigned int base_penalty =0; + if (battle_config.death_penalty_base > 0) { + switch (battle_config.death_penalty_type) { + case 1: + base_penalty = (unsigned int) ((double)pc_nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000); + break; + case 2: + base_penalty = (unsigned int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000); + break; + } + if(base_penalty) { + if (battle_config.pk_mode && src && src->type==BL_PC) + base_penalty*=2; + sd->status.base_exp -= min(sd->status.base_exp, base_penalty); + clif_updatestatus(sd,SP_BASEEXP); + } + } + if(battle_config.death_penalty_job > 0) + { + base_penalty = 0; + switch (battle_config.death_penalty_type) { + case 1: + base_penalty = (unsigned int) ((double)pc_nextjobexp(sd) * (double)battle_config.death_penalty_job/10000); + break; + case 2: + base_penalty = (unsigned int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000); + break; + } + if(base_penalty) { + if (battle_config.pk_mode && src && src->type==BL_PC) + base_penalty*=2; + sd->status.job_exp -= min(sd->status.job_exp, base_penalty); + clif_updatestatus(sd,SP_JOBEXP); + } + } + if(battle_config.zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) + { + base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.); + if(base_penalty) + pc_payzeny(sd, base_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL); + } + } + + if(map[sd->bl.m].flag.pvp_nightmaredrop) + { // Moved this outside so it works when PVP isn't enabled and during pk mode [Ancyker] + for(j=0;j<MAX_DROP_PER_MAP;j++){ + int id = map[sd->bl.m].drop_list[j].drop_id; + int type = map[sd->bl.m].drop_list[j].drop_type; + int per = map[sd->bl.m].drop_list[j].drop_per; + if(id == 0) + continue; + if(id == -1){ + int eq_num=0,eq_n[MAX_INVENTORY]; + memset(eq_n,0,sizeof(eq_n)); + for(i=0;i<MAX_INVENTORY;i++){ + int k; + if( (type == 1 && !sd->status.inventory[i].equip) + || (type == 2 && sd->status.inventory[i].equip) + || type == 3) + { + ARR_FIND( 0, MAX_INVENTORY, k, eq_n[k] <= 0 ); + if( k < MAX_INVENTORY ) + eq_n[k] = i; + + eq_num++; + } + } + if(eq_num > 0){ + int n = eq_n[rnd()%eq_num]; + if(rnd()%10000 < per){ + if(sd->status.inventory[n].equip) + pc_unequipitem(sd,n,3); + pc_dropitem(sd,n,1); + } + } + } + else if(id > 0){ + for(i=0;i<MAX_INVENTORY;i++){ + if(sd->status.inventory[i].nameid == id + && rnd()%10000 < per + && ((type == 1 && !sd->status.inventory[i].equip) + || (type == 2 && sd->status.inventory[i].equip) + || type == 3) ){ + if(sd->status.inventory[i].equip) + pc_unequipitem(sd,i,3); + pc_dropitem(sd,i,1); + break; + } + } + } + } + } + // pvp + // disable certain pvp functions on pk_mode [Valaris] + if( map[sd->bl.m].flag.pvp && !battle_config.pk_mode && !map[sd->bl.m].flag.pvp_nocalcrank ) + { + sd->pvp_point -= 5; + sd->pvp_lost++; + if( src && src->type == BL_PC ) + { + struct map_session_data *ssd = (struct map_session_data *)src; + ssd->pvp_point++; + ssd->pvp_won++; + } + if( sd->pvp_point < 0 ) + { + add_timer(tick+1000, pc_respawn_timer,sd->bl.id,0); + return 1|8; + } + } + //GvG + if( map_flag_gvg(sd->bl.m) ) + { + add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0); + return 1|8; + } + else if( sd->bg_id ) + { + struct battleground_data *bg = bg_team_search(sd->bg_id); + if( bg && bg->mapindex > 0 ) + { // Respawn by BG + add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0); + return 1|8; + } + } + + + //Reset "can log out" tick. + if( battle_config.prevent_logout ) + sd->canlog_tick = gettick() - battle_config.prevent_logout; + return 1; +} + +void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) { + if(hp) clif_updatestatus(sd,SP_HP); + if(sp) clif_updatestatus(sd,SP_SP); + + pc_setstand(sd); + if(battle_config.pc_invincible_time > 0) + pc_setinvincibletimer(sd, battle_config.pc_invincible_time); + + if( sd->state.gmaster_flag ) { + guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->state.gmaster_flag,GD_LEADERSHIP)); + guild_guildaura_refresh(sd,GD_GLORYWOUNDS,guild_checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS)); + guild_guildaura_refresh(sd,GD_SOULCOLD,guild_checkskill(sd->state.gmaster_flag,GD_SOULCOLD)); + guild_guildaura_refresh(sd,GD_HAWKEYES,guild_checkskill(sd->state.gmaster_flag,GD_HAWKEYES)); + } } // script // /*========================================== * script reading pc status registry *------------------------------------------*/ -int pc_readparam(struct map_session_data *sd,int type) -{ - int val = 0; - - nullpo_ret(sd); - - switch (type) { - case SP_SKILLPOINT: - val = sd->status.skill_point; - break; - case SP_STATUSPOINT: - val = sd->status.status_point; - break; - case SP_ZENY: - val = sd->status.zeny; - break; - case SP_BASELEVEL: - val = sd->status.base_level; - break; - case SP_JOBLEVEL: - val = sd->status.job_level; - break; - case SP_CLASS: - val = sd->status.class_; - break; - case SP_BASEJOB: - val = pc_mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex); - break; //Base job, extracting upper type. - case SP_UPPER: - val = sd->class_&JOBL_UPPER?1:(sd->class_&JOBL_BABY?2:0); - break; - case SP_BASECLASS: - val = pc_mapid2jobid(sd->class_&MAPID_BASEMASK, sd->status.sex); - break; //Extract base class tree. [Skotlex] - case SP_SEX: - val = sd->status.sex; - break; - case SP_WEIGHT: - val = sd->weight; - break; - case SP_MAXWEIGHT: - val = sd->max_weight; - break; - case SP_BASEEXP: - val = sd->status.base_exp; - break; - case SP_JOBEXP: - val = sd->status.job_exp; - break; - case SP_NEXTBASEEXP: - val = pc_nextbaseexp(sd); - break; - case SP_NEXTJOBEXP: - val = pc_nextjobexp(sd); - break; - case SP_HP: - val = sd->battle_status.hp; - break; - case SP_MAXHP: - val = sd->battle_status.max_hp; - break; - case SP_SP: - val = sd->battle_status.sp; - break; - case SP_MAXSP: - val = sd->battle_status.max_sp; - break; - case SP_STR: - val = sd->status.str; - break; - case SP_AGI: - val = sd->status.agi; - break; - case SP_VIT: - val = sd->status.vit; - break; - case SP_INT: - val = sd->status.int_; - break; - case SP_DEX: - val = sd->status.dex; - break; - case SP_LUK: - val = sd->status.luk; - break; - case SP_KARMA: - val = sd->status.karma; - break; - case SP_MANNER: - val = sd->status.manner; - break; - case SP_FAME: - val = sd->status.fame; - break; - case SP_KILLERRID: - val = sd->killerrid; - break; - case SP_KILLEDRID: - val = sd->killedrid; - break; - case SP_CRITICAL: - val = sd->battle_status.cri/10; - break; - case SP_ASPD: - val = (2000-sd->battle_status.amotion)/10; - break; - } - - return val; +int pc_readparam(struct map_session_data* sd,int type) +{ + int val = 0; + + nullpo_ret(sd); + + switch(type) { + case SP_SKILLPOINT: val = sd->status.skill_point; break; + case SP_STATUSPOINT: val = sd->status.status_point; break; + case SP_ZENY: val = sd->status.zeny; break; + case SP_BASELEVEL: val = sd->status.base_level; break; + case SP_JOBLEVEL: val = sd->status.job_level; break; + case SP_CLASS: val = sd->status.class_; break; + case SP_BASEJOB: val = pc_mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex); break; //Base job, extracting upper type. + case SP_UPPER: val = sd->class_&JOBL_UPPER?1:(sd->class_&JOBL_BABY?2:0); break; + case SP_BASECLASS: val = pc_mapid2jobid(sd->class_&MAPID_BASEMASK, sd->status.sex); break; //Extract base class tree. [Skotlex] + case SP_SEX: val = sd->status.sex; break; + case SP_WEIGHT: val = sd->weight; break; + case SP_MAXWEIGHT: val = sd->max_weight; break; + case SP_BASEEXP: val = sd->status.base_exp; break; + case SP_JOBEXP: val = sd->status.job_exp; break; + case SP_NEXTBASEEXP: val = pc_nextbaseexp(sd); break; + case SP_NEXTJOBEXP: val = pc_nextjobexp(sd); break; + case SP_HP: val = sd->battle_status.hp; break; + case SP_MAXHP: val = sd->battle_status.max_hp; break; + case SP_SP: val = sd->battle_status.sp; break; + case SP_MAXSP: val = sd->battle_status.max_sp; break; + case SP_STR: val = sd->status.str; break; + case SP_AGI: val = sd->status.agi; break; + case SP_VIT: val = sd->status.vit; break; + case SP_INT: val = sd->status.int_; break; + case SP_DEX: val = sd->status.dex; break; + case SP_LUK: val = sd->status.luk; break; + case SP_KARMA: val = sd->status.karma; break; + case SP_MANNER: val = sd->status.manner; break; + case SP_FAME: val = sd->status.fame; break; + case SP_KILLERRID: val = sd->killerrid; break; + case SP_KILLEDRID: val = sd->killedrid; break; + case SP_CRITICAL: val = sd->battle_status.cri/10; break; + case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break; + } + + return val; } /*========================================== @@ -6998,145 +6862,148 @@ int pc_readparam(struct map_session_data *sd,int type) *------------------------------------------*/ int pc_setparam(struct map_session_data *sd,int type,int val) { - int i = 0, statlimit; - - nullpo_ret(sd); - - switch (type) { - case SP_BASELEVEL: - if ((unsigned int)val > pc_maxbaselv(sd)) //Capping to max - val = pc_maxbaselv(sd); - if ((unsigned int)val > sd->status.base_level) { - int stat=0; - for (i = 0; i < (int)((unsigned int)val - sd->status.base_level); i++) - stat += pc_gets_status_point(sd->status.base_level + i); - sd->status.status_point += stat; - } - sd->status.base_level = (unsigned int)val; - sd->status.base_exp = 0; - // clif_updatestatus(sd, SP_BASELEVEL); // Gets updated at the bottom - clif_updatestatus(sd, SP_NEXTBASEEXP); - clif_updatestatus(sd, SP_STATUSPOINT); - clif_updatestatus(sd, SP_BASEEXP); - status_calc_pc(sd, 0); - if (sd->status.party_id) { - party_send_levelup(sd); - } - break; - case SP_JOBLEVEL: - if ((unsigned int)val >= sd->status.job_level) { - if ((unsigned int)val > pc_maxjoblv(sd)) val = pc_maxjoblv(sd); - sd->status.skill_point += val - sd->status.job_level; - clif_updatestatus(sd, SP_SKILLPOINT); - } - sd->status.job_level = (unsigned int)val; - sd->status.job_exp = 0; - // clif_updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom - clif_updatestatus(sd, SP_NEXTJOBEXP); - clif_updatestatus(sd, SP_JOBEXP); - status_calc_pc(sd, 0); - break; - case SP_SKILLPOINT: - sd->status.skill_point = val; - break; - case SP_STATUSPOINT: - sd->status.status_point = val; - break; - case SP_ZENY: - if (val < 0) - return 0;// can't set negative zeny - log_zeny(sd, LOG_TYPE_SCRIPT, sd, -(sd->status.zeny - cap_value(val, 0, MAX_ZENY))); - sd->status.zeny = cap_value(val, 0, MAX_ZENY); - break; - case SP_BASEEXP: - if (pc_nextbaseexp(sd) > 0) { - sd->status.base_exp = val; - pc_checkbaselevelup(sd); - } - break; - case SP_JOBEXP: - if (pc_nextjobexp(sd) > 0) { - sd->status.job_exp = val; - pc_checkjoblevelup(sd); - } - break; - case SP_SEX: - sd->status.sex = val ? SEX_MALE : SEX_FEMALE; - break; - case SP_WEIGHT: - sd->weight = val; - break; - case SP_MAXWEIGHT: - sd->max_weight = val; - break; - case SP_HP: - sd->battle_status.hp = cap_value(val, 1, (int)sd->battle_status.max_hp); - break; - case SP_MAXHP: - sd->battle_status.max_hp = cap_value(val, 1, battle_config.max_hp); - - if (sd->battle_status.max_hp < sd->battle_status.hp) { - sd->battle_status.hp = sd->battle_status.max_hp; - clif_updatestatus(sd, SP_HP); - } - break; - case SP_SP: - sd->battle_status.sp = cap_value(val, 0, (int)sd->battle_status.max_sp); - break; - case SP_MAXSP: - sd->battle_status.max_sp = cap_value(val, 1, battle_config.max_sp); - - if (sd->battle_status.max_sp < sd->battle_status.sp) { - sd->battle_status.sp = sd->battle_status.max_sp; - clif_updatestatus(sd, SP_SP); - } - break; - case SP_STR: - statlimit = pc_maxparameter(sd); - sd->status.str = cap_value(val, 1, statlimit); - break; - case SP_AGI: - statlimit = pc_maxparameter(sd); - sd->status.agi = cap_value(val, 1, statlimit); - break; - case SP_VIT: - statlimit = pc_maxparameter(sd); - sd->status.vit = cap_value(val, 1, statlimit); - break; - case SP_INT: - statlimit = pc_maxparameter(sd); - sd->status.int_ = cap_value(val, 1, statlimit); - break; - case SP_DEX: - statlimit = pc_maxparameter(sd); - sd->status.dex = cap_value(val, 1, statlimit); - break; - case SP_LUK: - statlimit = pc_maxparameter(sd); - sd->status.luk = cap_value(val, 1, statlimit); - break; - case SP_KARMA: - sd->status.karma = val; - break; - case SP_MANNER: - sd->status.manner = val; - break; - case SP_FAME: - sd->status.fame = val; - break; - case SP_KILLERRID: - sd->killerrid = val; - return 1; - case SP_KILLEDRID: - sd->killedrid = val; - return 1; - default: - ShowError("pc_setparam: Attempted to set unknown parameter '%d'.\n", type); - return 0; - } - clif_updatestatus(sd,type); - - return 1; + int i = 0, statlimit; + + nullpo_ret(sd); + + switch(type){ + case SP_BASELEVEL: + if ((unsigned int)val > pc_maxbaselv(sd)) //Capping to max + val = pc_maxbaselv(sd); + if ((unsigned int)val > sd->status.base_level) { + int stat=0; + for (i = 0; i < (int)((unsigned int)val - sd->status.base_level); i++) + stat += pc_gets_status_point(sd->status.base_level + i); + sd->status.status_point += stat; + } + sd->status.base_level = (unsigned int)val; + sd->status.base_exp = 0; + // clif_updatestatus(sd, SP_BASELEVEL); // Gets updated at the bottom + clif_updatestatus(sd, SP_NEXTBASEEXP); + clif_updatestatus(sd, SP_STATUSPOINT); + clif_updatestatus(sd, SP_BASEEXP); + status_calc_pc(sd, 0); + if(sd->status.party_id) + { + party_send_levelup(sd); + } + break; + case SP_JOBLEVEL: + if ((unsigned int)val >= sd->status.job_level) { + if ((unsigned int)val > pc_maxjoblv(sd)) val = pc_maxjoblv(sd); + sd->status.skill_point += val - sd->status.job_level; + clif_updatestatus(sd, SP_SKILLPOINT); + } + sd->status.job_level = (unsigned int)val; + sd->status.job_exp = 0; + // clif_updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom + clif_updatestatus(sd, SP_NEXTJOBEXP); + clif_updatestatus(sd, SP_JOBEXP); + status_calc_pc(sd, 0); + break; + case SP_SKILLPOINT: + sd->status.skill_point = val; + break; + case SP_STATUSPOINT: + sd->status.status_point = val; + break; + case SP_ZENY: + if( val < 0 ) + return 0;// can't set negative zeny + log_zeny(sd, LOG_TYPE_SCRIPT, sd, -(sd->status.zeny - cap_value(val, 0, MAX_ZENY))); + sd->status.zeny = cap_value(val, 0, MAX_ZENY); + break; + case SP_BASEEXP: + if(pc_nextbaseexp(sd) > 0) { + sd->status.base_exp = val; + pc_checkbaselevelup(sd); + } + break; + case SP_JOBEXP: + if(pc_nextjobexp(sd) > 0) { + sd->status.job_exp = val; + pc_checkjoblevelup(sd); + } + break; + case SP_SEX: + sd->status.sex = val ? SEX_MALE : SEX_FEMALE; + break; + case SP_WEIGHT: + sd->weight = val; + break; + case SP_MAXWEIGHT: + sd->max_weight = val; + break; + case SP_HP: + sd->battle_status.hp = cap_value(val, 1, (int)sd->battle_status.max_hp); + break; + case SP_MAXHP: + sd->battle_status.max_hp = cap_value(val, 1, battle_config.max_hp); + + if( sd->battle_status.max_hp < sd->battle_status.hp ) + { + sd->battle_status.hp = sd->battle_status.max_hp; + clif_updatestatus(sd, SP_HP); + } + break; + case SP_SP: + sd->battle_status.sp = cap_value(val, 0, (int)sd->battle_status.max_sp); + break; + case SP_MAXSP: + sd->battle_status.max_sp = cap_value(val, 1, battle_config.max_sp); + + if( sd->battle_status.max_sp < sd->battle_status.sp ) + { + sd->battle_status.sp = sd->battle_status.max_sp; + clif_updatestatus(sd, SP_SP); + } + break; + case SP_STR: + statlimit = pc_maxparameter(sd); + sd->status.str = cap_value(val, 1, statlimit); + break; + case SP_AGI: + statlimit = pc_maxparameter(sd); + sd->status.agi = cap_value(val, 1, statlimit); + break; + case SP_VIT: + statlimit = pc_maxparameter(sd); + sd->status.vit = cap_value(val, 1, statlimit); + break; + case SP_INT: + statlimit = pc_maxparameter(sd); + sd->status.int_ = cap_value(val, 1, statlimit); + break; + case SP_DEX: + statlimit = pc_maxparameter(sd); + sd->status.dex = cap_value(val, 1, statlimit); + break; + case SP_LUK: + statlimit = pc_maxparameter(sd); + sd->status.luk = cap_value(val, 1, statlimit); + break; + case SP_KARMA: + sd->status.karma = val; + break; + case SP_MANNER: + sd->status.manner = val; + break; + case SP_FAME: + sd->status.fame = val; + break; + case SP_KILLERRID: + sd->killerrid = val; + return 1; + case SP_KILLEDRID: + sd->killedrid = val; + return 1; + default: + ShowError("pc_setparam: Attempted to set unknown parameter '%d'.\n", type); + return 0; + } + clif_updatestatus(sd,type); + + return 1; } /*========================================== @@ -7144,18 +7011,18 @@ int pc_setparam(struct map_session_data *sd,int type,int val) *------------------------------------------*/ void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int type) { - if (type) { - if (hp) - clif_heal(sd->fd,SP_HP,hp); - if (sp) - clif_heal(sd->fd,SP_SP,sp); - } else { - if (hp) - clif_updatestatus(sd,SP_HP); - if (sp) - clif_updatestatus(sd,SP_SP); - } - return; + if (type) { + if (hp) + clif_heal(sd->fd,SP_HP,hp); + if (sp) + clif_heal(sd->fd,SP_SP,sp); + } else { + if(hp) + clif_updatestatus(sd,SP_HP); + if(sp) + clif_updatestatus(sd,SP_SP); + } + return; } /*========================================== @@ -7165,64 +7032,65 @@ void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int ty *------------------------------------------*/ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp) { - int i, bonus; - - if (hp) { - bonus = 100 + (sd->battle_status.vit<<1) - + pc_checkskill(sd,SM_RECOVERY)*10 - + pc_checkskill(sd,AM_LEARNINGPOTION)*5; - // A potion produced by an Alchemist in the Fame Top 10 gets +50% effect [DracoRPG] - if (potion_flag > 1) - bonus += bonus*(potion_flag-1)*50/100; - //All item bonuses. - bonus += sd->bonus.itemhealrate2; - //Item Group bonuses - bonus += bonus*itemdb_group_bonus(sd, itemid)/100; - //Individual item bonuses. - for (i = 0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid; i++) { - if (sd->itemhealrate[i].nameid == itemid) { - bonus += bonus*sd->itemhealrate[i].rate/100; - break; - } - } - if (bonus!=100) - hp = hp * bonus / 100; - - // Recovery Potion - if (sd->sc.data[SC_INCHEALRATE]) - hp += (int)(hp * sd->sc.data[SC_INCHEALRATE]->val1/100.); - } - if (sp) { - bonus = 100 + (sd->battle_status.int_<<1) - + pc_checkskill(sd,MG_SRECOVERY)*10 - + pc_checkskill(sd,AM_LEARNINGPOTION)*5; - if (potion_flag > 1) - bonus += bonus*(potion_flag-1)*50/100; - if (bonus != 100) - sp = sp * bonus / 100; - } - if (sd->sc.count) { - if (sd->sc.data[SC_CRITICALWOUND]) { - hp -= hp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100; - sp -= sp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100; - } - - if (sd->sc.data[SC_DEATHHURT]) { - hp -= hp * 20 / 100; - sp -= sp * 20 / 100; - } - - if (sd->sc.data[SC_WATER_INSIGNIA] && sd->sc.data[SC_WATER_INSIGNIA]->val1 == 2) { - hp += hp / 10; - sp += sp / 10; - } + int i, bonus; + + if(hp) { + bonus = 100 + (sd->battle_status.vit<<1) + + pc_checkskill(sd,SM_RECOVERY)*10 + + pc_checkskill(sd,AM_LEARNINGPOTION)*5; + // A potion produced by an Alchemist in the Fame Top 10 gets +50% effect [DracoRPG] + if (potion_flag > 1) + bonus += bonus*(potion_flag-1)*50/100; + //All item bonuses. + bonus += sd->bonus.itemhealrate2; + //Item Group bonuses + bonus += bonus*itemdb_group_bonus(sd, itemid)/100; + //Individual item bonuses. + for(i = 0; i < ARRAYLENGTH(sd->itemhealrate) && sd->itemhealrate[i].nameid; i++) + { + if (sd->itemhealrate[i].nameid == itemid) { + bonus += bonus*sd->itemhealrate[i].rate/100; + break; + } + } + if(bonus!=100) + hp = hp * bonus / 100; + + // Recovery Potion + if( sd->sc.data[SC_INCHEALRATE] ) + hp += (int)(hp * sd->sc.data[SC_INCHEALRATE]->val1/100.); + } + if(sp) { + bonus = 100 + (sd->battle_status.int_<<1) + + pc_checkskill(sd,MG_SRECOVERY)*10 + + pc_checkskill(sd,AM_LEARNINGPOTION)*5; + if (potion_flag > 1) + bonus += bonus*(potion_flag-1)*50/100; + if(bonus != 100) + sp = sp * bonus / 100; + } + if( sd->sc.count ) { + if ( sd->sc.data[SC_CRITICALWOUND] ) { + hp -= hp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100; + sp -= sp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100; + } + + if ( sd->sc.data[SC_DEATHHURT] ) { + hp -= hp * 20 / 100; + sp -= sp * 20 / 100; + } + + if( sd->sc.data[SC_WATER_INSIGNIA] && sd->sc.data[SC_WATER_INSIGNIA]->val1 == 2 ) { + hp += hp / 10; + sp += sp / 10; + } #ifdef RENEWAL - if (sd->sc.data[SC_EXTREMITYFIST2]) - sp = 0; + if( sd->sc.data[SC_EXTREMITYFIST2] ) + sp = 0; #endif - } + } - return status_heal(&sd->bl, hp, sp, 1); + return status_heal(&sd->bl, hp, sp, 1); } /*========================================== @@ -7231,48 +7099,37 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp) *------------------------------------------*/ int pc_percentheal(struct map_session_data *sd,int hp,int sp) { - nullpo_ret(sd); + nullpo_ret(sd); - if (hp > 100) hp = 100; - else if (hp <-100) hp =-100; + if(hp > 100) hp = 100; + else + if(hp <-100) hp =-100; - if (sp > 100) sp = 100; - else if (sp <-100) sp =-100; + if(sp > 100) sp = 100; + else + if(sp <-100) sp =-100; - if (hp >= 0 && sp >= 0) //Heal - return status_percent_heal(&sd->bl, hp, sp); + if(hp >= 0 && sp >= 0) //Heal + return status_percent_heal(&sd->bl, hp, sp); - if (hp <= 0 && sp <= 0) //Damage (negative rates indicate % of max rather than current), and only kill target IF the specified amount is 100% - return status_percent_damage(NULL, &sd->bl, hp, sp, hp==-100); + if(hp <= 0 && sp <= 0) //Damage (negative rates indicate % of max rather than current), and only kill target IF the specified amount is 100% + return status_percent_damage(NULL, &sd->bl, hp, sp, hp==-100); - //Crossed signs - if (hp) { - if (hp > 0) - status_percent_heal(&sd->bl, hp, 0); - else - status_percent_damage(NULL, &sd->bl, hp, 0, hp==-100); - } + //Crossed signs + if(hp) { + if(hp > 0) + status_percent_heal(&sd->bl, hp, 0); + else + status_percent_damage(NULL, &sd->bl, hp, 0, hp==-100); + } - if (sp) { - if (sp > 0) - status_percent_heal(&sd->bl, 0, sp); - else - status_percent_damage(NULL, &sd->bl, 0, sp, false); - } - return 0; -} - -static int jobchange_killclone(struct block_list *bl, va_list ap) -{ - struct mob_data *md; - int flag; - md = (struct mob_data *)bl; - nullpo_ret(md); - flag = va_arg(ap, int); - - if (md->master_id && md->special_state.clone && md->master_id == flag) - status_kill(&md->bl); - return 1; + if(sp) { + if(sp > 0) + status_percent_heal(&sd->bl, 0, sp); + else + status_percent_damage(NULL, &sd->bl, 0, sp, false); + } + return 0; } /*========================================== @@ -7281,168 +7138,161 @@ static int jobchange_killclone(struct block_list *bl, va_list ap) *------------------------------------------*/ int pc_jobchange(struct map_session_data *sd,int job, int upper) { - int i, fame_flag=0; - int b_class; - - nullpo_ret(sd); - - if (job < 0) - return 1; - - //Normalize job. - b_class = pc_jobid2mapid(job); - if (b_class == -1) - return 1; - switch (upper) { - case 1: - b_class|= JOBL_UPPER; - break; - case 2: - b_class|= JOBL_BABY; - break; - } - //This will automatically adjust bard/dancer classes to the correct gender - //That is, if you try to jobchange into dancer, it will turn you to bard. - job = pc_mapid2jobid(b_class, sd->status.sex); - if (job == -1) - return 1; - - if ((unsigned short)b_class == sd->class_) - return 1; //Nothing to change. - - // changing from 1st to 2nd job - if ((b_class&JOBL_2) && !(sd->class_&JOBL_2) && (b_class&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) { - sd->change_level_2nd = sd->status.job_level; - pc_setglobalreg(sd, "jobchange_level", sd->change_level_2nd); - } - // changing from 2nd to 3rd job - else if ((b_class&JOBL_THIRD) && !(sd->class_&JOBL_THIRD)) { - sd->change_level_3rd = sd->status.job_level; - pc_setglobalreg(sd, "jobchange_level_3rd", sd->change_level_3rd); - } - - if (sd->cloneskill_id) { - if (sd->status.skill[sd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED) { - sd->status.skill[sd->cloneskill_id].id = 0; - sd->status.skill[sd->cloneskill_id].lv = 0; - sd->status.skill[sd->cloneskill_id].flag = 0; - clif_deleteskill(sd,sd->cloneskill_id); - } - sd->cloneskill_id = 0; - pc_setglobalreg(sd, "CLONE_SKILL", 0); - pc_setglobalreg(sd, "CLONE_SKILL_LV", 0); - } - - if (sd->reproduceskill_id) { - if (sd->status.skill[sd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED) { - sd->status.skill[sd->reproduceskill_id].id = 0; - sd->status.skill[sd->reproduceskill_id].lv = 0; - sd->status.skill[sd->reproduceskill_id].flag = 0; - clif_deleteskill(sd,sd->reproduceskill_id); - } - sd->reproduceskill_id = 0; - pc_setglobalreg(sd, "REPRODUCE_SKILL",0); - pc_setglobalreg(sd, "REPRODUCE_SKILL_LV",0); - } - - if ((b_class&MAPID_UPPERMASK) != (sd->class_&MAPID_UPPERMASK)) { //Things to remove when changing class tree. - const int class_ = pc_class2idx(sd->status.class_); - short id; - for (i = 0; i < MAX_SKILL_TREE && (id = skill_tree[class_][i].id) > 0; i++) { - //Remove status specific to your current tree skills. - enum sc_type sc = status_skill2sc(id); - if (sc > SC_COMMON_MAX && sd->sc.data[sc]) - status_change_end(&sd->bl, sc, INVALID_TIMER); - } - } - - sd->status.class_ = job; - fame_flag = pc_famerank(sd->status.char_id,sd->class_&MAPID_UPPERMASK); - sd->class_ = (unsigned short)b_class; - sd->status.job_level=1; - sd->status.job_exp=0; - clif_updatestatus(sd,SP_JOBLEVEL); - clif_updatestatus(sd,SP_JOBEXP); - clif_updatestatus(sd,SP_NEXTJOBEXP); - - for (i=0; i<EQI_MAX; i++) { - if (sd->equip_index[i] >= 0) - if (!pc_isequip(sd,sd->equip_index[i])) - pc_unequipitem(sd,sd->equip_index[i],2); // unequip invalid item for class - } - - //Change look, if disguised, you need to undisguise - //to correctly calculate new job sprite without - if (sd->disguise) - pc_disguise(sd, 0); - - status_set_viewdata(&sd->bl, job); - clif_changelook(&sd->bl,LOOK_BASE,sd->vd.class_); // move sprite update to prevent client crashes with incompatible equipment [Valaris] - if (sd->vd.cloth_color) - clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); - - //Update skill tree. - pc_calc_skilltree(sd); - clif_skillinfoblock(sd); - - if (sd->ed) - elemental_delete(sd->ed, 0); - if (sd->state.vending) - vending_closevending(sd); - - map_foreachinmap(jobchange_killclone, sd->bl.m, BL_MOB, sd->bl.id); - - //Remove peco/cart/falcon - i = sd->sc.option; - if (i&OPTION_RIDING && !pc_checkskill(sd, KN_RIDING)) - i&=~OPTION_RIDING; - if (i&OPTION_FALCON && !pc_checkskill(sd, HT_FALCON)) - i&=~OPTION_FALCON; - if (i&OPTION_DRAGON && !pc_checkskill(sd,RK_DRAGONTRAINING)) - i&=~OPTION_DRAGON; - if (i&OPTION_WUGRIDER && !pc_checkskill(sd,RA_WUGMASTERY)) - i&=~OPTION_WUGRIDER; - if (i&OPTION_WUG && !pc_checkskill(sd,RA_WUGMASTERY)) - i&=~OPTION_WUG; - if (i&OPTION_MADOGEAR) //You do not need a skill for this. - i&=~OPTION_MADOGEAR; + int i, fame_flag=0; + int b_class; + + nullpo_ret(sd); + + if (job < 0) + return 1; + + //Normalize job. + b_class = pc_jobid2mapid(job); + if (b_class == -1) + return 1; + switch (upper) { + case 1: + b_class|= JOBL_UPPER; + break; + case 2: + b_class|= JOBL_BABY; + break; + } + //This will automatically adjust bard/dancer classes to the correct gender + //That is, if you try to jobchange into dancer, it will turn you to bard. + job = pc_mapid2jobid(b_class, sd->status.sex); + if (job == -1) + return 1; + + if ((unsigned short)b_class == sd->class_) + return 1; //Nothing to change. + + // changing from 1st to 2nd job + if ((b_class&JOBL_2) && !(sd->class_&JOBL_2) && (b_class&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) { + sd->change_level_2nd = sd->status.job_level; + pc_setglobalreg (sd, "jobchange_level", sd->change_level_2nd); + } + // changing from 2nd to 3rd job + else if((b_class&JOBL_THIRD) && !(sd->class_&JOBL_THIRD)) { + sd->change_level_3rd = sd->status.job_level; + pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd); + } + + if(sd->cloneskill_id) { + if( sd->status.skill[sd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED ) { + sd->status.skill[sd->cloneskill_id].id = 0; + sd->status.skill[sd->cloneskill_id].lv = 0; + sd->status.skill[sd->cloneskill_id].flag = 0; + clif_deleteskill(sd,sd->cloneskill_id); + } + sd->cloneskill_id = 0; + pc_setglobalreg(sd, "CLONE_SKILL", 0); + pc_setglobalreg(sd, "CLONE_SKILL_LV", 0); + } + + if(sd->reproduceskill_id) { + if( sd->status.skill[sd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED ) { + sd->status.skill[sd->reproduceskill_id].id = 0; + sd->status.skill[sd->reproduceskill_id].lv = 0; + sd->status.skill[sd->reproduceskill_id].flag = 0; + clif_deleteskill(sd,sd->reproduceskill_id); + } + sd->reproduceskill_id = 0; + pc_setglobalreg(sd, "REPRODUCE_SKILL",0); + pc_setglobalreg(sd, "REPRODUCE_SKILL_LV",0); + } + + if ( (b_class&MAPID_UPPERMASK) != (sd->class_&MAPID_UPPERMASK) ) { //Things to remove when changing class tree. + const int class_ = pc_class2idx(sd->status.class_); + short id; + for(i = 0; i < MAX_SKILL_TREE && (id = skill_tree[class_][i].id) > 0; i++) { + //Remove status specific to your current tree skills. + enum sc_type sc = status_skill2sc(id); + if (sc > SC_COMMON_MAX && sd->sc.data[sc]) + status_change_end(&sd->bl, sc, INVALID_TIMER); + } + } + + sd->status.class_ = job; + fame_flag = pc_famerank(sd->status.char_id,sd->class_&MAPID_UPPERMASK); + sd->class_ = (unsigned short)b_class; + sd->status.job_level=1; + sd->status.job_exp=0; + clif_updatestatus(sd,SP_JOBLEVEL); + clif_updatestatus(sd,SP_JOBEXP); + clif_updatestatus(sd,SP_NEXTJOBEXP); + + for(i=0;i<EQI_MAX;i++) { + if(sd->equip_index[i] >= 0) + if(!pc_isequip(sd,sd->equip_index[i])) + pc_unequipitem(sd,sd->equip_index[i],2); // unequip invalid item for class + } + + //Change look, if disguised, you need to undisguise + //to correctly calculate new job sprite without + if (sd->disguise) + pc_disguise(sd, 0); + + status_set_viewdata(&sd->bl, job); + clif_changelook(&sd->bl,LOOK_BASE,sd->vd.class_); // move sprite update to prevent client crashes with incompatible equipment [Valaris] + if(sd->vd.cloth_color) + clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); + + //Update skill tree. + pc_calc_skilltree(sd); + clif_skillinfoblock(sd); + + //Remove peco/cart/falcon + i = sd->sc.option; + if( i&OPTION_RIDING && !pc_checkskill(sd, KN_RIDING) ) + i&=~OPTION_RIDING; + if( i&OPTION_FALCON && !pc_checkskill(sd, HT_FALCON) ) + i&=~OPTION_FALCON; + if( i&OPTION_DRAGON && !pc_checkskill(sd,RK_DRAGONTRAINING) ) + i&=~OPTION_DRAGON; + if( i&OPTION_WUGRIDER && !pc_checkskill(sd,RA_WUGMASTERY) ) + i&=~OPTION_WUGRIDER; + if( i&OPTION_WUG && !pc_checkskill(sd,RA_WUGMASTERY) ) + i&=~OPTION_WUG; + if( i&OPTION_MADOGEAR ) //You do not need a skill for this. + i&=~OPTION_MADOGEAR; #ifndef NEW_CARTS - if (i&OPTION_CART && !pc_checkskill(sd, MC_PUSHCART)) - i&=~OPTION_CART; + if( i&OPTION_CART && !pc_checkskill(sd, MC_PUSHCART) ) + i&=~OPTION_CART; #else - if (sd->sc.data[SC_PUSH_CART] && !pc_checkskill(sd, MC_PUSHCART)) - pc_setcart(sd, 0); + if( sd->sc.data[SC_PUSH_CART] && !pc_checkskill(sd, MC_PUSHCART) ) + pc_setcart(sd, 0); #endif - if (i != sd->sc.option) - pc_setoption(sd, i); - - if (merc_is_hom_active(sd->hd) && !pc_checkskill(sd, AM_CALLHOMUN)) - merc_hom_vaporize(sd, 0); - - if (sd->status.manner < 0) - clif_changestatus(sd,SP_MANNER,sd->status.manner); - - status_calc_pc(sd,0); - pc_checkallowskill(sd); - pc_equiplookall(sd); - - //if you were previously famous, not anymore. - if (fame_flag) { - chrif_save(sd,0); - chrif_buildfamelist(); - } else if (sd->status.fame > 0) { - //It may be that now they are famous? - switch (sd->class_&MAPID_UPPERMASK) { - case MAPID_BLACKSMITH: - case MAPID_ALCHEMIST: - case MAPID_TAEKWON: - chrif_save(sd,0); - chrif_buildfamelist(); - break; - } - } - - return 0; + if(i != sd->sc.option) + pc_setoption(sd, i); + + if(merc_is_hom_active(sd->hd) && !pc_checkskill(sd, AM_CALLHOMUN)) + merc_hom_vaporize(sd, 0); + + if(sd->status.manner < 0) + clif_changestatus(sd,SP_MANNER,sd->status.manner); + + status_calc_pc(sd,0); + pc_checkallowskill(sd); + pc_equiplookall(sd); + + //if you were previously famous, not anymore. + if (fame_flag) { + chrif_save(sd,0); + chrif_buildfamelist(); + } else if (sd->status.fame > 0) { + //It may be that now they are famous? + switch (sd->class_&MAPID_UPPERMASK) { + case MAPID_BLACKSMITH: + case MAPID_ALCHEMIST: + case MAPID_TAEKWON: + chrif_save(sd,0); + chrif_buildfamelist(); + break; + } + } + + return 0; } /*========================================== @@ -7450,16 +7300,16 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) *------------------------------------------*/ int pc_equiplookall(struct map_session_data *sd) { - nullpo_ret(sd); + nullpo_ret(sd); - clif_changelook(&sd->bl,LOOK_WEAPON,0); - clif_changelook(&sd->bl,LOOK_SHOES,0); - 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_changelook(&sd->bl, LOOK_ROBE, sd->status.robe); + clif_changelook(&sd->bl,LOOK_WEAPON,0); + clif_changelook(&sd->bl,LOOK_SHOES,0); + 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_changelook(&sd->bl, LOOK_ROBE, sd->status.robe); - return 0; + return 0; } /*========================================== @@ -7467,57 +7317,59 @@ int pc_equiplookall(struct map_session_data *sd) *------------------------------------------*/ int pc_changelook(struct map_session_data *sd,int type,int val) { - nullpo_ret(sd); - - switch (type) { - case LOOK_HAIR: //Use the battle_config limits! [Skotlex] - val = cap_value(val, MIN_HAIR_STYLE, MAX_HAIR_STYLE); - - if (sd->status.hair != val) { - sd->status.hair=val; - if (sd->status.guild_id) //Update Guild Window. [Skotlex] - intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, - GMI_HAIR,&sd->status.hair,sizeof(sd->status.hair)); - } - break; - case LOOK_WEAPON: - sd->status.weapon=val; - break; - case LOOK_HEAD_BOTTOM: - sd->status.head_bottom=val; - break; - case LOOK_HEAD_TOP: - sd->status.head_top=val; - break; - case LOOK_HEAD_MID: - sd->status.head_mid=val; - break; - case LOOK_HAIR_COLOR: //Use the battle_config limits! [Skotlex] - val = cap_value(val, MIN_HAIR_COLOR, MAX_HAIR_COLOR); - - if (sd->status.hair_color != val) { - sd->status.hair_color=val; - if (sd->status.guild_id) //Update Guild Window. [Skotlex] - intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, - GMI_HAIR_COLOR,&sd->status.hair_color,sizeof(sd->status.hair_color)); - } - break; - case LOOK_CLOTHES_COLOR: //Use the battle_config limits! [Skotlex] - val = cap_value(val, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); - - sd->status.clothes_color=val; - break; - case LOOK_SHIELD: - sd->status.shield=val; - break; - case LOOK_SHOES: - break; - case LOOK_ROBE: - sd->status.robe = val; - break; - } - clif_changelook(&sd->bl,type,val); - return 0; + nullpo_ret(sd); + + switch(type){ + case LOOK_HAIR: //Use the battle_config limits! [Skotlex] + val = cap_value(val, MIN_HAIR_STYLE, MAX_HAIR_STYLE); + + if (sd->status.hair != val) + { + sd->status.hair=val; + if (sd->status.guild_id) //Update Guild Window. [Skotlex] + intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, + GMI_HAIR,&sd->status.hair,sizeof(sd->status.hair)); + } + break; + case LOOK_WEAPON: + sd->status.weapon=val; + break; + case LOOK_HEAD_BOTTOM: + sd->status.head_bottom=val; + break; + case LOOK_HEAD_TOP: + sd->status.head_top=val; + break; + case LOOK_HEAD_MID: + sd->status.head_mid=val; + break; + case LOOK_HAIR_COLOR: //Use the battle_config limits! [Skotlex] + val = cap_value(val, MIN_HAIR_COLOR, MAX_HAIR_COLOR); + + if (sd->status.hair_color != val) + { + sd->status.hair_color=val; + if (sd->status.guild_id) //Update Guild Window. [Skotlex] + intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, + GMI_HAIR_COLOR,&sd->status.hair_color,sizeof(sd->status.hair_color)); + } + break; + case LOOK_CLOTHES_COLOR: //Use the battle_config limits! [Skotlex] + val = cap_value(val, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); + + sd->status.clothes_color=val; + break; + case LOOK_SHIELD: + sd->status.shield=val; + break; + case LOOK_SHOES: + break; + case LOOK_ROBE: + sd->status.robe = val; + break; + } + clif_changelook(&sd->bl,type,val); + return 0; } /*========================================== @@ -7525,213 +7377,213 @@ int pc_changelook(struct map_session_data *sd,int type,int val) *------------------------------------------*/ int pc_setoption(struct map_session_data *sd,int type) { - int p_type, new_look=0; - nullpo_ret(sd); - p_type = sd->sc.option; - - //Option has to be changed client-side before the class sprite or it won't always work (eg: Wedding sprite) [Skotlex] - sd->sc.option=type; - clif_changeoption(&sd->bl); - - if ((type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc_checkskill(sd,RK_DRAGONTRAINING) > 0)) { - // Mounting - clif_status_load(&sd->bl,SI_RIDING,1); - status_calc_pc(sd,0); - } else if ((!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON && pc_checkskill(sd,RK_DRAGONTRAINING) > 0)) { - // Dismount - clif_status_load(&sd->bl,SI_RIDING,0); - status_calc_pc(sd,0); - } + int p_type, new_look=0; + nullpo_ret(sd); + p_type = sd->sc.option; + + //Option has to be changed client-side before the class sprite or it won't always work (eg: Wedding sprite) [Skotlex] + sd->sc.option=type; + clif_changeoption(&sd->bl); + + if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) ) + { // Mounting + clif_status_load(&sd->bl,SI_RIDING,1); + status_calc_pc(sd,0); + } + else if( (!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) ) + { // Dismount + clif_status_load(&sd->bl,SI_RIDING,0); + status_calc_pc(sd,0); + } #ifndef NEW_CARTS - if (type&OPTION_CART && !(p_type&OPTION_CART)) { //Cart On - clif_cartlist(sd); - clif_updatestatus(sd, SP_CARTINFO); - if (pc_checkskill(sd, MC_PUSHCART) < 10) - status_calc_pc(sd,0); //Apply speed penalty. - } else if (!(type&OPTION_CART) && p_type&OPTION_CART) { //Cart Off - clif_clearcart(sd->fd); - if (pc_checkskill(sd, MC_PUSHCART) < 10) - status_calc_pc(sd,0); //Remove speed penalty. - } + if( type&OPTION_CART && !( p_type&OPTION_CART ) ) { //Cart On + clif_cartlist(sd); + clif_updatestatus(sd, SP_CARTINFO); + if(pc_checkskill(sd, MC_PUSHCART) < 10) + status_calc_pc(sd,0); //Apply speed penalty. + } else if( !( type&OPTION_CART ) && p_type&OPTION_CART ){ //Cart Off + clif_clearcart(sd->fd); + if(pc_checkskill(sd, MC_PUSHCART) < 10) + status_calc_pc(sd,0); //Remove speed penalty. + } #endif - if (type&OPTION_MOUNTING && !(p_type&OPTION_MOUNTING)) { - clif_status_load_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0); - status_calc_pc(sd,0); - } else if (!(type&OPTION_MOUNTING) && p_type&OPTION_MOUNTING) { - clif_status_load_notick(&sd->bl,SI_ALL_RIDING,0,0,0,0); - status_calc_pc(sd,0); - } - - - if (type&OPTION_FALCON && !(p_type&OPTION_FALCON)) //Falcon ON - clif_status_load(&sd->bl,SI_FALCON,1); - else if (!(type&OPTION_FALCON) && p_type&OPTION_FALCON) //Falcon OFF - clif_status_load(&sd->bl,SI_FALCON,0); - - if ((sd->class_&MAPID_THIRDMASK) == MAPID_RANGER) { - if (type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER)) { // Mounting - clif_status_load(&sd->bl,SI_WUGRIDER,1); - status_calc_pc(sd,0); - } else if (!(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER) { // Dismount - clif_status_load(&sd->bl,SI_WUGRIDER,0); - status_calc_pc(sd,0); - } - } - if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC) { - if (type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR)) { - status_calc_pc(sd, 0); - status_change_end(&sd->bl,SC_MAXIMIZEPOWER,INVALID_TIMER); - status_change_end(&sd->bl,SC_OVERTHRUST,INVALID_TIMER); - status_change_end(&sd->bl,SC_WEAPONPERFECTION,INVALID_TIMER); - status_change_end(&sd->bl,SC_ADRENALINE,INVALID_TIMER); - status_change_end(&sd->bl,SC_CARTBOOST,INVALID_TIMER); - status_change_end(&sd->bl,SC_MELTDOWN,INVALID_TIMER); - status_change_end(&sd->bl,SC_MAXOVERTHRUST,INVALID_TIMER); - } else if (!(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR) { - status_calc_pc(sd, 0); - status_change_end(&sd->bl,SC_SHAPESHIFT,INVALID_TIMER); - status_change_end(&sd->bl,SC_HOVERING,INVALID_TIMER); - status_change_end(&sd->bl,SC_ACCELERATION,INVALID_TIMER); - status_change_end(&sd->bl,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); - status_change_end(&sd->bl,SC_OVERHEAT,INVALID_TIMER); - } - } - - if (type&OPTION_FLYING && !(p_type&OPTION_FLYING)) - new_look = JOB_STAR_GLADIATOR2; - else if (!(type&OPTION_FLYING) && p_type&OPTION_FLYING) - new_look = -1; - - if (type&OPTION_WEDDING && !(p_type&OPTION_WEDDING)) - new_look = JOB_WEDDING; - else if (!(type&OPTION_WEDDING) && p_type&OPTION_WEDDING) - new_look = -1; - - if (type&OPTION_XMAS && !(p_type&OPTION_XMAS)) - new_look = JOB_XMAS; - else if (!(type&OPTION_XMAS) && p_type&OPTION_XMAS) - new_look = -1; - - if (type&OPTION_SUMMER && !(p_type&OPTION_SUMMER)) - new_look = JOB_SUMMER; - else if (!(type&OPTION_SUMMER) && p_type&OPTION_SUMMER) - new_look = -1; - - if (sd->disguise || !new_look) - return 0; //Disguises break sprite changes - - if (new_look < 0) { //Restore normal look. - status_set_viewdata(&sd->bl, sd->status.class_); - new_look = sd->vd.class_; - } - - pc_stop_attack(sd); //Stop attacking on new view change (to prevent wedding/santa attacks. - clif_changelook(&sd->bl,LOOK_BASE,new_look); - if (sd->vd.cloth_color) - clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); - clif_skillinfoblock(sd); // Skill list needs to be updated after base change. - - return 0; + if (type&OPTION_MOUNTING && !(p_type&OPTION_MOUNTING) ) { + clif_status_load_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0); + status_calc_pc(sd,0); + } else if (!(type&OPTION_MOUNTING) && p_type&OPTION_MOUNTING) { + clif_status_load_notick(&sd->bl,SI_ALL_RIDING,0,0,0,0); + status_calc_pc(sd,0); + } + + + if (type&OPTION_FALCON && !(p_type&OPTION_FALCON)) //Falcon ON + clif_status_load(&sd->bl,SI_FALCON,1); + else if (!(type&OPTION_FALCON) && p_type&OPTION_FALCON) //Falcon OFF + clif_status_load(&sd->bl,SI_FALCON,0); + + if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) { + if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting + clif_status_load(&sd->bl,SI_WUGRIDER,1); + status_calc_pc(sd,0); + } else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount + clif_status_load(&sd->bl,SI_WUGRIDER,0); + status_calc_pc(sd,0); + } + } + if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) { + if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) ) { + status_calc_pc(sd, 0); + status_change_end(&sd->bl,SC_MAXIMIZEPOWER,INVALID_TIMER); + status_change_end(&sd->bl,SC_OVERTHRUST,INVALID_TIMER); + status_change_end(&sd->bl,SC_WEAPONPERFECTION,INVALID_TIMER); + status_change_end(&sd->bl,SC_ADRENALINE,INVALID_TIMER); + status_change_end(&sd->bl,SC_CARTBOOST,INVALID_TIMER); + status_change_end(&sd->bl,SC_MELTDOWN,INVALID_TIMER); + status_change_end(&sd->bl,SC_MAXOVERTHRUST,INVALID_TIMER); + } else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR ) { + status_calc_pc(sd, 0); + status_change_end(&sd->bl,SC_SHAPESHIFT,INVALID_TIMER); + status_change_end(&sd->bl,SC_HOVERING,INVALID_TIMER); + status_change_end(&sd->bl,SC_ACCELERATION,INVALID_TIMER); + status_change_end(&sd->bl,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); + status_change_end(&sd->bl,SC_OVERHEAT,INVALID_TIMER); + } + } + + if (type&OPTION_FLYING && !(p_type&OPTION_FLYING)) + new_look = JOB_STAR_GLADIATOR2; + else if (!(type&OPTION_FLYING) && p_type&OPTION_FLYING) + new_look = -1; + + if (type&OPTION_WEDDING && !(p_type&OPTION_WEDDING)) + new_look = JOB_WEDDING; + else if (!(type&OPTION_WEDDING) && p_type&OPTION_WEDDING) + new_look = -1; + + if (type&OPTION_XMAS && !(p_type&OPTION_XMAS)) + new_look = JOB_XMAS; + else if (!(type&OPTION_XMAS) && p_type&OPTION_XMAS) + new_look = -1; + + if (type&OPTION_SUMMER && !(p_type&OPTION_SUMMER)) + new_look = JOB_SUMMER; + else if (!(type&OPTION_SUMMER) && p_type&OPTION_SUMMER) + new_look = -1; + + if (sd->disguise || !new_look) + return 0; //Disguises break sprite changes + + if (new_look < 0) { //Restore normal look. + status_set_viewdata(&sd->bl, sd->status.class_); + new_look = sd->vd.class_; + } + + pc_stop_attack(sd); //Stop attacking on new view change (to prevent wedding/santa attacks. + clif_changelook(&sd->bl,LOOK_BASE,new_look); + if (sd->vd.cloth_color) + clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); + clif_skillinfoblock(sd); // Skill list needs to be updated after base change. + + return 0; } /*========================================== * Give player a cart *------------------------------------------*/ -int pc_setcart(struct map_session_data *sd,int type) -{ +int pc_setcart(struct map_session_data *sd,int type) { #ifndef NEW_CARTS - int cart[6] = {0x0000,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5}; - int option; + int cart[6] = {0x0000,OPTION_CART1,OPTION_CART2,OPTION_CART3,OPTION_CART4,OPTION_CART5}; + int option; #endif - nullpo_ret(sd); + nullpo_ret(sd); - if (type < 0 || type > MAX_CARTS) - return 1;// Never trust the values sent by the client! [Skotlex] + if( type < 0 || type > MAX_CARTS ) + return 1;// Never trust the values sent by the client! [Skotlex] - if (pc_checkskill(sd,MC_PUSHCART) <= 0 && type != 0) - return 1;// Push cart is required + if( pc_checkskill(sd,MC_PUSHCART) <= 0 && type != 0 ) + return 1;// Push cart is required - if (type == 0 && pc_iscarton(sd)) - status_change_end(&sd->bl,SC_GN_CARTBOOST,INVALID_TIMER); + if( type == 0 && pc_iscarton(sd) ) + status_change_end(&sd->bl,SC_GN_CARTBOOST,INVALID_TIMER); #ifdef NEW_CARTS - switch (type) { - case 0: - if (!sd->sc.data[SC_PUSH_CART]) - return 0; - status_change_end(&sd->bl,SC_PUSH_CART,INVALID_TIMER); - clif_clearcart(sd->fd); - break; - default:/* everything else is an allowed ID so we can move on */ - if (!sd->sc.data[SC_PUSH_CART]) /* first time, so fill cart data */ - clif_cartlist(sd); - clif_updatestatus(sd, SP_CARTINFO); - sc_start(&sd->bl, SC_PUSH_CART, 100, type, 0); - clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2 , type, 0, 0); - if (sd->sc.data[SC_PUSH_CART]) /* forcefully update */ - sd->sc.data[SC_PUSH_CART]->val1 = type; - break; - } - - if (pc_checkskill(sd, MC_PUSHCART) < 10) - status_calc_pc(sd,0); //Recalc speed penalty. + switch( type ) { + case 0: + if( !sd->sc.data[SC_PUSH_CART] ) + return 0; + status_change_end(&sd->bl,SC_PUSH_CART,INVALID_TIMER); + clif_clearcart(sd->fd); + break; + default:/* everything else is an allowed ID so we can move on */ + if( !sd->sc.data[SC_PUSH_CART] ) /* first time, so fill cart data */ + clif_cartlist(sd); + clif_updatestatus(sd, SP_CARTINFO); + sc_start(&sd->bl, SC_PUSH_CART, 100, type, 0); + clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2 , type, 0, 0); + if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */ + sd->sc.data[SC_PUSH_CART]->val1 = type; + break; + } + + if(pc_checkskill(sd, MC_PUSHCART) < 10) + status_calc_pc(sd,0); //Recalc speed penalty. #else - // Update option - option = sd->sc.option; - option &= ~OPTION_CART;// clear cart bits - option |= cart[type]; // set cart - pc_setoption(sd, option); + // Update option + option = sd->sc.option; + option &= ~OPTION_CART;// clear cart bits + option |= cart[type]; // set cart + pc_setoption(sd, option); #endif - return 0; + return 0; } /*========================================== * Give player a falcon *------------------------------------------*/ -int pc_setfalcon(TBL_PC *sd, int flag) +int pc_setfalcon(TBL_PC* sd, int flag) { - if (flag) { - if (pc_checkskill(sd,HT_FALCON)>0) // add falcon if he have the skill - pc_setoption(sd,sd->sc.option|OPTION_FALCON); - } else if (pc_isfalcon(sd)) { - pc_setoption(sd,sd->sc.option&~OPTION_FALCON); // remove falcon - } + if( flag ){ + if( pc_checkskill(sd,HT_FALCON)>0 ) // add falcon if he have the skill + pc_setoption(sd,sd->sc.option|OPTION_FALCON); + } else if( pc_isfalcon(sd) ){ + pc_setoption(sd,sd->sc.option&~OPTION_FALCON); // remove falcon + } - return 0; + return 0; } /*========================================== * Set player riding *------------------------------------------*/ -int pc_setriding(TBL_PC *sd, int flag) +int pc_setriding(TBL_PC* sd, int flag) { - if (flag) { - if (pc_checkskill(sd,KN_RIDING) > 0) // add peco - pc_setoption(sd, sd->sc.option|OPTION_RIDING); - } else if (pc_isriding(sd)) { - pc_setoption(sd, sd->sc.option&~OPTION_RIDING); - } + if( flag ){ + if( pc_checkskill(sd,KN_RIDING) > 0 ) // add peco + pc_setoption(sd, sd->sc.option|OPTION_RIDING); + } else if( pc_isriding(sd) ){ + pc_setoption(sd, sd->sc.option&~OPTION_RIDING); + } - return 0; + return 0; } /*========================================== * Give player a mado *------------------------------------------*/ -int pc_setmadogear(TBL_PC *sd, int flag) +int pc_setmadogear(TBL_PC* sd, int flag) { - if (flag) { - if (pc_checkskill(sd,NC_MADOLICENCE) > 0) - pc_setoption(sd, sd->sc.option|OPTION_MADOGEAR); - } else if (pc_ismadogear(sd)) { - pc_setoption(sd, sd->sc.option&~OPTION_MADOGEAR); - } + if( flag ){ + if( pc_checkskill(sd,NC_MADOLICENCE) > 0 ) + pc_setoption(sd, sd->sc.option|OPTION_MADOGEAR); + } else if( pc_ismadogear(sd) ){ + pc_setoption(sd, sd->sc.option&~OPTION_MADOGEAR); + } - return 0; + return 0; } /*========================================== @@ -7739,333 +7591,347 @@ int pc_setmadogear(TBL_PC *sd, int flag) *------------------------------------------*/ int pc_candrop(struct map_session_data *sd, struct item *item) { - if (item && item->expire_time) - return 0; - if (!pc_can_give_items(sd)) //check if this GM level can drop items - return 0; - return (itemdb_isdropable(item, pc_get_group_level(sd))); + if( item && item->expire_time ) + return 0; + if( !pc_can_give_items(sd) ) //check if this GM level can drop items + return 0; + return (itemdb_isdropable(item, pc_get_group_level(sd))); } /*========================================== * Read ram register for player sd * get val (int) from reg for player sd *------------------------------------------*/ -int pc_readreg(struct map_session_data *sd, int reg) +int pc_readreg(struct map_session_data* sd, int reg) { - int i; + int i; - nullpo_ret(sd); + nullpo_ret(sd); - ARR_FIND(0, sd->reg_num, i, sd->reg[i].index == reg); - return (i < sd->reg_num) ? sd->reg[i].data : 0; + ARR_FIND( 0, sd->reg_num, i, sd->reg[i].index == reg ); + return ( i < sd->reg_num ) ? sd->reg[i].data : 0; } /*========================================== * Set ram register for player sd * memo val(int) at reg for player sd *------------------------------------------*/ -int pc_setreg(struct map_session_data *sd, int reg, int val) +int pc_setreg(struct map_session_data* sd, int reg, int val) { - int i; + int i; - nullpo_ret(sd); + nullpo_ret(sd); - ARR_FIND(0, sd->reg_num, i, sd->reg[i].index == reg); - if (i < sd->reg_num) { - // overwrite existing entry - sd->reg[i].data = val; - return 1; - } + ARR_FIND( 0, sd->reg_num, i, sd->reg[i].index == reg ); + if( i < sd->reg_num ) + {// overwrite existing entry + sd->reg[i].data = val; + return 1; + } - ARR_FIND(0, sd->reg_num, i, sd->reg[i].data == 0); - if (i == sd->reg_num) { - // nothing free, increase size - sd->reg_num++; - RECREATE(sd->reg, struct script_reg, sd->reg_num); - } - sd->reg[i].index = reg; - sd->reg[i].data = val; + ARR_FIND( 0, sd->reg_num, i, sd->reg[i].data == 0 ); + if( i == sd->reg_num ) + {// nothing free, increase size + sd->reg_num++; + RECREATE(sd->reg, struct script_reg, sd->reg_num); + } + sd->reg[i].index = reg; + sd->reg[i].data = val; - return 1; + return 1; } /*========================================== * Read ram register for player sd * get val (str) from reg for player sd *------------------------------------------*/ -char *pc_readregstr(struct map_session_data *sd, int reg) +char* pc_readregstr(struct map_session_data* sd, int reg) { - int i; + int i; - nullpo_ret(sd); + nullpo_ret(sd); - ARR_FIND(0, sd->regstr_num, i, sd->regstr[i].index == reg); - return (i < sd->regstr_num) ? sd->regstr[i].data : NULL; + ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].index == reg ); + return ( i < sd->regstr_num ) ? sd->regstr[i].data : NULL; } /*========================================== * Set ram register for player sd * memo val(str) at reg for player sd *------------------------------------------*/ -int pc_setregstr(struct map_session_data *sd, int reg, const char *str) -{ - int i; - - nullpo_ret(sd); - - ARR_FIND(0, sd->regstr_num, i, sd->regstr[i].index == reg); - if (i < sd->regstr_num) { - // found entry, update - if (str == NULL || *str == '\0') { - // empty string - if (sd->regstr[i].data != NULL) - aFree(sd->regstr[i].data); - sd->regstr[i].data = NULL; - } else if (sd->regstr[i].data) { - // recreate - size_t len = strlen(str)+1; - RECREATE(sd->regstr[i].data, char, len); - memcpy(sd->regstr[i].data, str, len*sizeof(char)); - } else { - // create - sd->regstr[i].data = aStrdup(str); - } - return 1; - } - - if (str == NULL || *str == '\0') - return 1;// nothing to add, empty string - - ARR_FIND(0, sd->regstr_num, i, sd->regstr[i].data == NULL); - if (i == sd->regstr_num) { - // nothing free, increase size - sd->regstr_num++; - RECREATE(sd->regstr, struct script_regstr, sd->regstr_num); - } - sd->regstr[i].index = reg; - sd->regstr[i].data = aStrdup(str); - - return 1; +int pc_setregstr(struct map_session_data* sd, int reg, const char* str) +{ + int i; + + nullpo_ret(sd); + + ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].index == reg ); + if( i < sd->regstr_num ) + {// found entry, update + if( str == NULL || *str == '\0' ) + {// empty string + if( sd->regstr[i].data != NULL ) + aFree(sd->regstr[i].data); + sd->regstr[i].data = NULL; + } + else if( sd->regstr[i].data ) + {// recreate + size_t len = strlen(str)+1; + RECREATE(sd->regstr[i].data, char, len); + memcpy(sd->regstr[i].data, str, len*sizeof(char)); + } + else + {// create + sd->regstr[i].data = aStrdup(str); + } + return 1; + } + + if( str == NULL || *str == '\0' ) + return 1;// nothing to add, empty string + + ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].data == NULL ); + if( i == sd->regstr_num ) + {// nothing free, increase size + sd->regstr_num++; + RECREATE(sd->regstr, struct script_regstr, sd->regstr_num); + } + sd->regstr[i].index = reg; + sd->regstr[i].data = aStrdup(str); + + return 1; } int pc_readregistry(struct map_session_data *sd,const char *reg,int type) { - struct global_reg *sd_reg; - int i,max; - - nullpo_ret(sd); - switch (type) { - case 3: //Char reg - sd_reg = sd->save_reg.global; - max = sd->save_reg.global_num; - break; - case 2: //Account reg - sd_reg = sd->save_reg.account; - max = sd->save_reg.account_num; - break; - case 1: //Account2 reg - sd_reg = sd->save_reg.account2; - max = sd->save_reg.account2_num; - break; - default: - return 0; - } - if (max == -1) { - ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type); - //This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again. - intif_request_registry(sd,type==3?4:type); - return 0; - } - - ARR_FIND(0, max, i, strcmp(sd_reg[i].str,reg) == 0); - return (i < max) ? atoi(sd_reg[i].value) : 0; -} - -char *pc_readregistry_str(struct map_session_data *sd,const char *reg,int type) -{ - struct global_reg *sd_reg; - int i,max; - - nullpo_ret(sd); - switch (type) { - case 3: //Char reg - sd_reg = sd->save_reg.global; - max = sd->save_reg.global_num; - break; - case 2: //Account reg - sd_reg = sd->save_reg.account; - max = sd->save_reg.account_num; - break; - case 1: //Account2 reg - sd_reg = sd->save_reg.account2; - max = sd->save_reg.account2_num; - break; - default: - return NULL; - } - if (max == -1) { - ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type); - //This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again. - intif_request_registry(sd,type==3?4:type); - return NULL; - } - - ARR_FIND(0, max, i, strcmp(sd_reg[i].str,reg) == 0); - return (i < max) ? sd_reg[i].value : NULL; + struct global_reg *sd_reg; + int i,max; + + nullpo_ret(sd); + switch (type) { + case 3: //Char reg + sd_reg = sd->save_reg.global; + max = sd->save_reg.global_num; + break; + case 2: //Account reg + sd_reg = sd->save_reg.account; + max = sd->save_reg.account_num; + break; + case 1: //Account2 reg + sd_reg = sd->save_reg.account2; + max = sd->save_reg.account2_num; + break; + default: + return 0; + } + if (max == -1) { + ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type); + //This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again. + intif_request_registry(sd,type==3?4:type); + return 0; + } + + ARR_FIND( 0, max, i, strcmp(sd_reg[i].str,reg) == 0 ); + return ( i < max ) ? atoi(sd_reg[i].value) : 0; +} + +char* pc_readregistry_str(struct map_session_data *sd,const char *reg,int type) +{ + struct global_reg *sd_reg; + int i,max; + + nullpo_ret(sd); + switch (type) { + case 3: //Char reg + sd_reg = sd->save_reg.global; + max = sd->save_reg.global_num; + break; + case 2: //Account reg + sd_reg = sd->save_reg.account; + max = sd->save_reg.account_num; + break; + case 1: //Account2 reg + sd_reg = sd->save_reg.account2; + max = sd->save_reg.account2_num; + break; + default: + return NULL; + } + if (max == -1) { + ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type); + //This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again. + intif_request_registry(sd,type==3?4:type); + return NULL; + } + + ARR_FIND( 0, max, i, strcmp(sd_reg[i].str,reg) == 0 ); + return ( i < max ) ? sd_reg[i].value : NULL; } int pc_setregistry(struct map_session_data *sd,const char *reg,int val,int type) { - struct global_reg *sd_reg; - int i,*max, regmax; - - nullpo_ret(sd); - - switch (type) { - case 3: //Char reg - if (!strcmp(reg,"PC_DIE_COUNTER") && sd->die_counter != val) { - i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE); - sd->die_counter = val; - if (i) - status_calc_pc(sd,0); // Lost the bonus. - } else if (!strcmp(reg,"COOK_MASTERY") && sd->cook_mastery != val) { - val = cap_value(val, 0, 1999); - sd->cook_mastery = val; - } - sd_reg = sd->save_reg.global; - max = &sd->save_reg.global_num; - regmax = GLOBAL_REG_NUM; - break; - case 2: //Account reg - if (!strcmp(reg,"#CASHPOINTS") && sd->cashPoints != val) { - val = cap_value(val, 0, MAX_ZENY); - sd->cashPoints = val; - } else if (!strcmp(reg,"#KAFRAPOINTS") && sd->kafraPoints != val) { - val = cap_value(val, 0, MAX_ZENY); - sd->kafraPoints = val; - } - sd_reg = sd->save_reg.account; - max = &sd->save_reg.account_num; - regmax = ACCOUNT_REG_NUM; - break; - case 1: //Account2 reg - sd_reg = sd->save_reg.account2; - max = &sd->save_reg.account2_num; - regmax = ACCOUNT_REG2_NUM; - break; - default: - return 0; - } - if (*max == -1) { - ShowError("pc_setregistry : refusing to set %s (type %d) until vars are received.\n", reg, type); - return 1; - } - - // delete reg - if (val == 0) { - ARR_FIND(0, *max, i, strcmp(sd_reg[i].str, reg) == 0); - if (i < *max) { - if (i != *max - 1) - memcpy(&sd_reg[i], &sd_reg[*max - 1], sizeof(struct global_reg)); - memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg)); - (*max)--; - sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" - } - return 1; - } - // change value if found - ARR_FIND(0, *max, i, strcmp(sd_reg[i].str, reg) == 0); - if (i < *max) { - safesnprintf(sd_reg[i].value, sizeof(sd_reg[i].value), "%d", val); - sd->state.reg_dirty |= 1<<(type-1); - return 1; - } - - // add value if not found - if (i < regmax) { - memset(&sd_reg[i], 0, sizeof(struct global_reg)); - safestrncpy(sd_reg[i].str, reg, sizeof(sd_reg[i].str)); - safesnprintf(sd_reg[i].value, sizeof(sd_reg[i].value), "%d", val); - (*max)++; - sd->state.reg_dirty |= 1<<(type-1); - return 1; - } - - ShowError("pc_setregistry : couldn't set %s, limit of registries reached (%d)\n", reg, regmax); - - return 0; + struct global_reg *sd_reg; + int i,*max, regmax; + + nullpo_ret(sd); + + switch( type ) + { + case 3: //Char reg + if( !strcmp(reg,"PC_DIE_COUNTER") && sd->die_counter != val ) + { + i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE); + sd->die_counter = val; + if( i ) + status_calc_pc(sd,0); // Lost the bonus. + } + else if( !strcmp(reg,"COOK_MASTERY") && sd->cook_mastery != val ) + { + val = cap_value(val, 0, 1999); + sd->cook_mastery = val; + } + sd_reg = sd->save_reg.global; + max = &sd->save_reg.global_num; + regmax = GLOBAL_REG_NUM; + break; + case 2: //Account reg + if( !strcmp(reg,"#CASHPOINTS") && sd->cashPoints != val ) + { + val = cap_value(val, 0, MAX_ZENY); + sd->cashPoints = val; + } + else if( !strcmp(reg,"#KAFRAPOINTS") && sd->kafraPoints != val ) + { + val = cap_value(val, 0, MAX_ZENY); + sd->kafraPoints = val; + } + sd_reg = sd->save_reg.account; + max = &sd->save_reg.account_num; + regmax = ACCOUNT_REG_NUM; + break; + case 1: //Account2 reg + sd_reg = sd->save_reg.account2; + max = &sd->save_reg.account2_num; + regmax = ACCOUNT_REG2_NUM; + break; + default: + return 0; + } + if (*max == -1) { + ShowError("pc_setregistry : refusing to set %s (type %d) until vars are received.\n", reg, type); + return 1; + } + + // delete reg + if (val == 0) { + ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 ); + if( i < *max ) + { + if (i != *max - 1) + memcpy(&sd_reg[i], &sd_reg[*max - 1], sizeof(struct global_reg)); + memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg)); + (*max)--; + sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" + } + return 1; + } + // change value if found + ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 ); + if( i < *max ) + { + safesnprintf(sd_reg[i].value, sizeof(sd_reg[i].value), "%d", val); + sd->state.reg_dirty |= 1<<(type-1); + return 1; + } + + // add value if not found + if (i < regmax) { + memset(&sd_reg[i], 0, sizeof(struct global_reg)); + safestrncpy(sd_reg[i].str, reg, sizeof(sd_reg[i].str)); + safesnprintf(sd_reg[i].value, sizeof(sd_reg[i].value), "%d", val); + (*max)++; + sd->state.reg_dirty |= 1<<(type-1); + return 1; + } + + ShowError("pc_setregistry : couldn't set %s, limit of registries reached (%d)\n", reg, regmax); + + return 0; } int pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *val,int type) { - struct global_reg *sd_reg; - int i,*max, regmax; - - nullpo_ret(sd); - if (reg[strlen(reg)-1] != '$') { - ShowError("pc_setregistry_str : reg %s must be string (end in '$') to use this!\n", reg); - return 0; - } - - switch (type) { - case 3: //Char reg - sd_reg = sd->save_reg.global; - max = &sd->save_reg.global_num; - regmax = GLOBAL_REG_NUM; - break; - case 2: //Account reg - sd_reg = sd->save_reg.account; - max = &sd->save_reg.account_num; - regmax = ACCOUNT_REG_NUM; - break; - case 1: //Account2 reg - sd_reg = sd->save_reg.account2; - max = &sd->save_reg.account2_num; - regmax = ACCOUNT_REG2_NUM; - break; - default: - return 0; - } - if (*max == -1) { - ShowError("pc_setregistry_str : refusing to set %s (type %d) until vars are received.\n", reg, type); - return 0; - } - - // delete reg - if (!val || strcmp(val,"")==0) { - ARR_FIND(0, *max, i, strcmp(sd_reg[i].str, reg) == 0); - if (i < *max) { - if (i != *max - 1) - memcpy(&sd_reg[i], &sd_reg[*max - 1], sizeof(struct global_reg)); - memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg)); - (*max)--; - sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" - if (type!=3) intif_saveregistry(sd,type); - } - return 1; - } - - // change value if found - ARR_FIND(0, *max, i, strcmp(sd_reg[i].str, reg) == 0); - if (i < *max) { - safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value)); - sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" - if (type!=3) intif_saveregistry(sd,type); - return 1; - } - - // add value if not found - if (i < regmax) { - memset(&sd_reg[i], 0, sizeof(struct global_reg)); - safestrncpy(sd_reg[i].str, reg, sizeof(sd_reg[i].str)); - safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value)); - (*max)++; - sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" - if (type!=3) intif_saveregistry(sd,type); - return 1; - } - - ShowError("pc_setregistry : couldn't set %s, limit of registries reached (%d)\n", reg, regmax); - - return 0; + struct global_reg *sd_reg; + int i,*max, regmax; + + nullpo_ret(sd); + if (reg[strlen(reg)-1] != '$') { + ShowError("pc_setregistry_str : reg %s must be string (end in '$') to use this!\n", reg); + return 0; + } + + switch (type) { + case 3: //Char reg + sd_reg = sd->save_reg.global; + max = &sd->save_reg.global_num; + regmax = GLOBAL_REG_NUM; + break; + case 2: //Account reg + sd_reg = sd->save_reg.account; + max = &sd->save_reg.account_num; + regmax = ACCOUNT_REG_NUM; + break; + case 1: //Account2 reg + sd_reg = sd->save_reg.account2; + max = &sd->save_reg.account2_num; + regmax = ACCOUNT_REG2_NUM; + break; + default: + return 0; + } + if (*max == -1) { + ShowError("pc_setregistry_str : refusing to set %s (type %d) until vars are received.\n", reg, type); + return 0; + } + + // delete reg + if (!val || strcmp(val,"")==0) + { + ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 ); + if( i < *max ) + { + if (i != *max - 1) + memcpy(&sd_reg[i], &sd_reg[*max - 1], sizeof(struct global_reg)); + memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg)); + (*max)--; + sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" + if (type!=3) intif_saveregistry(sd,type); + } + return 1; + } + + // change value if found + ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 ); + if( i < *max ) + { + safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value)); + sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" + if (type!=3) intif_saveregistry(sd,type); + return 1; + } + + // add value if not found + if (i < regmax) { + memset(&sd_reg[i], 0, sizeof(struct global_reg)); + safestrncpy(sd_reg[i].str, reg, sizeof(sd_reg[i].str)); + safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value)); + (*max)++; + sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" + if (type!=3) intif_saveregistry(sd,type); + return 1; + } + + ShowError("pc_setregistry : couldn't set %s, limit of registries reached (%d)\n", reg, regmax); + + return 0; } /*========================================== @@ -8073,22 +7939,24 @@ int pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *v *------------------------------------------*/ static int pc_eventtimer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd=map_id2sd(id); - char *p = (char *)data; - int i; - if (sd==NULL) - return 0; + struct map_session_data *sd=map_id2sd(id); + char *p = (char *)data; + int i; + if(sd==NULL) + return 0; - ARR_FIND(0, MAX_EVENTTIMER, i, sd->eventtimer[i] == tid); - if (i < MAX_EVENTTIMER) { - sd->eventtimer[i] = INVALID_TIMER; - sd->eventcount--; - npc_event(sd,p,0); - } else - ShowError("pc_eventtimer: no such event timer\n"); + ARR_FIND( 0, MAX_EVENTTIMER, i, sd->eventtimer[i] == tid ); + if( i < MAX_EVENTTIMER ) + { + sd->eventtimer[i] = INVALID_TIMER; + sd->eventcount--; + npc_event(sd,p,0); + } + else + ShowError("pc_eventtimer: no such event timer\n"); - if (p) aFree(p); - return 0; + if (p) aFree(p); + return 0; } /*========================================== @@ -8096,17 +7964,17 @@ static int pc_eventtimer(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name) { - int i; - nullpo_ret(sd); + int i; + nullpo_ret(sd); - ARR_FIND(0, MAX_EVENTTIMER, i, sd->eventtimer[i] == INVALID_TIMER); - if (i == MAX_EVENTTIMER) - return 0; + ARR_FIND( 0, MAX_EVENTTIMER, i, sd->eventtimer[i] == INVALID_TIMER ); + if( i == MAX_EVENTTIMER ) + return 0; - sd->eventtimer[i] = add_timer(gettick()+tick, pc_eventtimer, sd->bl.id, (intptr_t)aStrdup(name)); - sd->eventcount++; + sd->eventtimer[i] = add_timer(gettick()+tick, pc_eventtimer, sd->bl.id, (intptr_t)aStrdup(name)); + sd->eventcount++; - return 1; + return 1; } /*========================================== @@ -8114,29 +7982,29 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name) *------------------------------------------*/ int pc_deleventtimer(struct map_session_data *sd,const char *name) { - char *p = NULL; - int i; + char* p = NULL; + int i; - nullpo_ret(sd); + nullpo_ret(sd); - if (sd->eventcount <= 0) - return 0; + if (sd->eventcount <= 0) + return 0; - // find the named event timer - ARR_FIND(0, MAX_EVENTTIMER, i, - sd->eventtimer[i] != INVALID_TIMER && - (p = (char *)(get_timer(sd->eventtimer[i])->data)) != NULL && - strcmp(p, name) == 0 - ); - if (i == MAX_EVENTTIMER) - return 0; // not found + // find the named event timer + ARR_FIND( 0, MAX_EVENTTIMER, i, + sd->eventtimer[i] != INVALID_TIMER && + (p = (char *)(get_timer(sd->eventtimer[i])->data)) != NULL && + strcmp(p, name) == 0 + ); + if( i == MAX_EVENTTIMER ) + return 0; // not found - delete_timer(sd->eventtimer[i],pc_eventtimer); - sd->eventtimer[i] = INVALID_TIMER; - sd->eventcount--; - aFree(p); + delete_timer(sd->eventtimer[i],pc_eventtimer); + sd->eventtimer[i] = INVALID_TIMER; + sd->eventcount--; + aFree(p); - return 1; + return 1; } /*========================================== @@ -8144,18 +8012,18 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name) *------------------------------------------*/ int pc_addeventtimercount(struct map_session_data *sd,const char *name,int tick) { - int i; + int i; - nullpo_ret(sd); + nullpo_ret(sd); - for (i=0; i<MAX_EVENTTIMER; i++) - if (sd->eventtimer[i] != INVALID_TIMER && strcmp( - (char *)(get_timer(sd->eventtimer[i])->data), name)==0) { - addtick_timer(sd->eventtimer[i],tick); - break; - } + for(i=0;i<MAX_EVENTTIMER;i++) + if( sd->eventtimer[i] != INVALID_TIMER && strcmp( + (char *)(get_timer(sd->eventtimer[i])->data), name)==0 ){ + addtick_timer(sd->eventtimer[i],tick); + break; + } - return 0; + return 0; } /*========================================== @@ -8163,369 +8031,373 @@ int pc_addeventtimercount(struct map_session_data *sd,const char *name,int tick) *------------------------------------------*/ int pc_cleareventtimer(struct map_session_data *sd) { - int i; + int i; - nullpo_ret(sd); + nullpo_ret(sd); - if (sd->eventcount <= 0) - return 0; + if (sd->eventcount <= 0) + return 0; - for (i=0; i<MAX_EVENTTIMER; i++) - if (sd->eventtimer[i] != INVALID_TIMER) { - char *p = (char *)(get_timer(sd->eventtimer[i])->data); - delete_timer(sd->eventtimer[i],pc_eventtimer); - sd->eventtimer[i] = INVALID_TIMER; - sd->eventcount--; - if (p) aFree(p); - } - return 0; + for(i=0;i<MAX_EVENTTIMER;i++) + if( sd->eventtimer[i] != INVALID_TIMER ){ + char *p = (char *)(get_timer(sd->eventtimer[i])->data); + delete_timer(sd->eventtimer[i],pc_eventtimer); + sd->eventtimer[i] = INVALID_TIMER; + sd->eventcount--; + if (p) aFree(p); + } + return 0; } /* called when a item with combo is worn */ -int pc_checkcombo(struct map_session_data *sd, struct item_data *data) -{ - int i, j, k, z; - int index, idx, success = 0; +int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) { + int i, j, k, z; + int index, idx, success = 0; - for (i = 0; i < data->combos_count; i++) { + for( i = 0; i < data->combos_count; i++ ) { - /* ensure this isn't a duplicate combo */ - if (sd->combos.bonus != NULL) { - int x; - ARR_FIND(0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id); + /* ensure this isn't a duplicate combo */ + if( sd->combos.bonus != NULL ) { + int x; + ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id ); - /* found a match, skip this combo */ - if (x < sd->combos.count) - continue; - } + /* found a match, skip this combo */ + if( x < sd->combos.count ) + continue; + } - for (j = 0; j < data->combos[i]->count; j++) { - int id = data->combos[i]->nameid[j]; - bool found = false; + for( j = 0; j < data->combos[i]->count; j++ ) { + int id = data->combos[i]->nameid[j]; + bool found = false; - for (k = 0; k < EQI_MAX; k++) { - index = sd->equip_index[k]; - if (index < 0) continue; - if (k == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue; - if (k == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue; - if (k == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue; + for( k = 0; k < EQI_MAX; k++ ) { + index = sd->equip_index[k]; + if( index < 0 ) continue; + if( k == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index ) continue; + if( k == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index ) continue; + if( k == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index) ) continue; - if (!sd->inventory_data[index]) - continue; + if(!sd->inventory_data[index]) + continue; - if (itemdb_type(id) != IT_CARD) { - if (sd->inventory_data[index]->nameid != id) - continue; + if ( itemdb_type(id) != IT_CARD ) { + if ( sd->inventory_data[index]->nameid != id ) + continue; - found = true; - break; - } else { //Cards - if (sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0])) - continue; + found = true; + break; + } else { //Cards + if ( sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0]) ) + continue; - for (z = 0; z < sd->inventory_data[index]->slot; z++) { + for (z = 0; z < sd->inventory_data[index]->slot; z++) { - if (sd->status.inventory[index].card[z] != id) - continue; + if (sd->status.inventory[index].card[z] != id) + continue; - // We have found a match - found = true; - break; - } - } + // We have found a match + found = true; + break; + } + } - } + } - if (!found) - break;/* we haven't found all the ids for this combo, so we can return */ - } + if( !found ) + break;/* we haven't found all the ids for this combo, so we can return */ + } - /* means we broke out of the count loop w/o finding all ids, we can move to the next combo */ - if (j < data->combos[i]->count) - continue; + /* means we broke out of the count loop w/o finding all ids, we can move to the next combo */ + if( j < data->combos[i]->count ) + continue; - /* we got here, means all items in the combo are matching */ + /* we got here, means all items in the combo are matching */ - idx = sd->combos.count; + idx = sd->combos.count; - if (sd->combos.bonus == NULL) { - CREATE(sd->combos.bonus, struct script_code *, 1); - CREATE(sd->combos.id, unsigned short, 1); - sd->combos.count = 1; - } else { - RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count); - RECREATE(sd->combos.id, unsigned short, sd->combos.count); - } + if( sd->combos.bonus == NULL ) { + CREATE(sd->combos.bonus, struct script_code *, 1); + CREATE(sd->combos.id, unsigned short, 1); + sd->combos.count = 1; + } else { + RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count); + RECREATE(sd->combos.id, unsigned short, sd->combos.count); + } - /* we simply copy the pointer */ - sd->combos.bonus[idx] = data->combos[i]->script; - /* save this combo's id */ - sd->combos.id[idx] = data->combos[i]->id; + /* we simply copy the pointer */ + sd->combos.bonus[idx] = data->combos[i]->script; + /* save this combo's id */ + sd->combos.id[idx] = data->combos[i]->id; - success++; - } - return success; + success++; + } + return success; } /* called when a item with combo is removed */ -int pc_removecombo(struct map_session_data *sd, struct item_data *data) -{ - int i, retval = 0; - - if (sd->combos.bonus == NULL) - return 0;/* nothing to do here, player has no combos */ - for (i = 0; i < data->combos_count; i++) { - /* check if this combo exists in this user */ - int x = 0, cursor = 0, j; - ARR_FIND(0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id); - /* no match, skip this combo */ - if (!(x < sd->combos.count)) - continue; - - sd->combos.bonus[x] = NULL; - sd->combos.id[x] = 0; - retval++; - for (j = 0, cursor = 0; j < sd->combos.count; j++) { - if (sd->combos.bonus[j] == NULL) - continue; - - if (cursor != j) { - sd->combos.bonus[cursor] = sd->combos.bonus[j]; - sd->combos.id[cursor] = sd->combos.id[j]; - } - - cursor++; - } - - /* it's empty, we can clear all the memory */ - if ((sd->combos.count = cursor) == 0) { - aFree(sd->combos.bonus); - aFree(sd->combos.id); - sd->combos.bonus = NULL; - sd->combos.id = NULL; - return retval; /* we also can return at this point for we have no more combos to check */ - } - - } - - return retval; -} -int pc_load_combo(struct map_session_data *sd) -{ - int i, ret = 0; - for (i = 0; i < EQI_MAX; i++) { - struct item_data *id = NULL; - int idx = sd->equip_index[i]; - if (sd->equip_index[i] < 0 || !(id = sd->inventory_data[idx])) - continue; - if (id->combos_count) - ret += pc_checkcombo(sd,id); - if (!itemdb_isspecial(sd->status.inventory[idx].card[0])) { - struct item_data *data; - int j; - for (j = 0; j < id->slot; j++) { - if (!sd->status.inventory[idx].card[j]) - continue; - if ((data = itemdb_exists(sd->status.inventory[idx].card[j])) != NULL) { - if (data->combos_count) - ret += pc_checkcombo(sd,data); - } - } - } - } - return ret; +int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { + int i, retval = 0; + + if( sd->combos.bonus == NULL ) + return 0;/* nothing to do here, player has no combos */ + for( i = 0; i < data->combos_count; i++ ) { + /* check if this combo exists in this user */ + int x = 0, cursor = 0, j; + ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id ); + /* no match, skip this combo */ + if( !(x < sd->combos.count) ) + continue; + + sd->combos.bonus[x] = NULL; + sd->combos.id[x] = 0; + retval++; + for( j = 0, cursor = 0; j < sd->combos.count; j++ ) { + if( sd->combos.bonus[j] == NULL ) + continue; + + if( cursor != j ) { + sd->combos.bonus[cursor] = sd->combos.bonus[j]; + sd->combos.id[cursor] = sd->combos.id[j]; + } + + cursor++; + } + + /* it's empty, we can clear all the memory */ + if( (sd->combos.count = cursor) == 0 ) { + aFree(sd->combos.bonus); + aFree(sd->combos.id); + sd->combos.bonus = NULL; + sd->combos.id = NULL; + return retval; /* we also can return at this point for we have no more combos to check */ + } + + } + + return retval; +} +int pc_load_combo(struct map_session_data *sd) { + int i, ret = 0; + for( i = 0; i < EQI_MAX; i++ ) { + struct item_data *id = NULL; + int idx = sd->equip_index[i]; + if( sd->equip_index[i] < 0 || !(id = sd->inventory_data[idx] ) ) + continue; + if( id->combos_count ) + ret += pc_checkcombo(sd,id); + if(!itemdb_isspecial(sd->status.inventory[idx].card[0])) { + struct item_data *data; + int j; + for( j = 0; j < id->slot; j++ ) { + if (!sd->status.inventory[idx].card[j]) + continue; + if ( ( data = itemdb_exists(sd->status.inventory[idx].card[j]) ) != NULL ) { + if( data->combos_count ) + ret += pc_checkcombo(sd,data); + } + } + } + } + return ret; } /*========================================== * Equip item on player sd at req_pos from inventory index n *------------------------------------------*/ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) { - int i,pos,flag=0; - struct item_data *id; - - nullpo_ret(sd); - - if (n < 0 || n >= MAX_INVENTORY) { - clif_equipitemack(sd,0,0,0); - return 0; - } - - if (DIFF_TICK(sd->canequip_tick,gettick()) > 0) { - clif_equipitemack(sd,n,0,0); - return 0; - } - - id = sd->inventory_data[n]; - pos = pc_equippoint(sd,n); //With a few exceptions, item should go in all specified slots. - - if (battle_config.battle_log) - ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos); - if (!pc_isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1) { // [Valaris] - // FIXME: pc_isequip: equip level failure uses 2 instead of 0 - clif_equipitemack(sd,n,0,0); // fail - return 0; - } - - if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST]) { - clif_equipitemack(sd,n,0,0); // fail - return 0; - } - - if (pos == EQP_ACC) { //Accesories should only go in one of the two, - pos = req_pos&EQP_ACC; - if (pos == EQP_ACC) //User specified both slots.. - pos = sd->equip_index[EQI_ACC_R] >= 0 ? EQP_ACC_L : EQP_ACC_R; - } - - if (pos == EQP_ARMS && id->equip == EQP_HAND_R) { - //Dual wield capable weapon. - pos = (req_pos&EQP_ARMS); - if (pos == EQP_ARMS) //User specified both slots, pick one for them. - pos = sd->equip_index[EQI_HAND_R] >= 0 ? EQP_HAND_L : EQP_HAND_R; - } - - if (pos&EQP_HAND_R && battle_config.use_weapon_skill_range&BL_PC) { - //Update skill-block range database when weapon range changes. [Skotlex] - i = sd->equip_index[EQI_HAND_R]; - if (i < 0 || !sd->inventory_data[i]) //No data, or no weapon equipped - flag = 1; - else - flag = id->range != sd->inventory_data[i]->range; - } - - for (i=0; i<EQI_MAX; i++) { - if (pos & equip_pos[i]) { - if (sd->equip_index[i] >= 0) //Slot taken, remove item from there. - pc_unequipitem(sd,sd->equip_index[i],2); - - sd->equip_index[i] = n; - } - } - - if (pos==EQP_AMMO) { - clif_arrowequip(sd,n); - clif_arrow_fail(sd,3); - } else - clif_equipitemack(sd,n,pos,1); - - sd->status.inventory[n].equip=pos; - - if (pos & EQP_HAND_R) { - if (id) - sd->weapontype1 = id->look; - else - sd->weapontype1 = 0; - pc_calcweapontype(sd); - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); - } - if (pos & EQP_HAND_L) { - if (id) { - if (id->type == IT_WEAPON) { - sd->status.shield = 0; - sd->weapontype2 = id->look; - } else if (id->type == IT_ARMOR) { - sd->status.shield = id->look; - sd->weapontype2 = 0; - } - } else - sd->status.shield = sd->weapontype2 = 0; - pc_calcweapontype(sd); - clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); - } - //Added check to prevent sending the same look on multiple slots -> - //causes client to redraw item on top of itself. (suggested by Lupus) - if (pos & EQP_HEAD_LOW && pc_checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1) { - if (id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID))) - sd->status.head_bottom = id->look; - else - sd->status.head_bottom = 0; - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); - } - if (pos & EQP_HEAD_TOP && pc_checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1) { - if (id) - sd->status.head_top = id->look; - else - sd->status.head_top = 0; - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); - } - if (pos & EQP_HEAD_MID && pc_checkequip(sd,EQP_COSTUME_HEAD_MID) == -1) { - if (id && !(pos&EQP_HEAD_TOP)) - sd->status.head_mid = id->look; - else - sd->status.head_mid = 0; - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); - } - if (pos & EQP_COSTUME_HEAD_TOP) { - if (id) { - sd->status.head_top = id->look; - } else - sd->status.head_top = 0; - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); - } - if (pos & EQP_COSTUME_HEAD_MID) { - if (id && !(pos&EQP_HEAD_TOP)) { - sd->status.head_mid = id->look; - } else - sd->status.head_mid = 0; - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); - } - if (pos & EQP_COSTUME_HEAD_LOW) { - if (id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID))) { - sd->status.head_bottom = id->look; - } else - sd->status.head_bottom = 0; - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); - } - if (pos & EQP_SHOES) - clif_changelook(&sd->bl,LOOK_SHOES,0); - if (pos&EQP_GARMENT) { - sd->status.robe = id ? id->look : 0; - clif_changelook(&sd->bl, LOOK_ROBE, sd->status.robe); - } - - pc_checkallowskill(sd); //Check if status changes should be halted. - - /* check for combos (MUST be before status_calc_pc) */ - if (id) { - struct item_data *data; - if (id->combos_count) - pc_checkcombo(sd,id); - if (itemdb_isspecial(sd->status.inventory[n].card[0])) - ; //No cards - else { - for (i = 0; i < id->slot; i++) { - if (!sd->status.inventory[n].card[i]) - continue; - if ((data = itemdb_exists(sd->status.inventory[n].card[i])) != NULL) { - if (data->combos_count) - pc_checkcombo(sd,data); - } - } - } - } - - status_calc_pc(sd,0); - if (flag) //Update skill data - clif_skillinfoblock(sd); - - //OnEquip script [Skotlex] - if (id) { - struct item_data *data; - if (id->equip_script) - run_script(id->equip_script,0,sd->bl.id,fake_nd->bl.id); - if (itemdb_isspecial(sd->status.inventory[n].card[0])) - ; //No cards - else { - for (i = 0; i < id->slot; i++) { - if (!sd->status.inventory[n].card[i]) - continue; - if ((data = itemdb_exists(sd->status.inventory[n].card[i])) != NULL) { - if (data->equip_script) - run_script(data->equip_script,0,sd->bl.id,fake_nd->bl.id); - } - } - } - } - return 0; + int i,pos,flag=0; + struct item_data *id; + + nullpo_ret(sd); + + if( n < 0 || n >= MAX_INVENTORY ) { + clif_equipitemack(sd,0,0,0); + return 0; + } + + if( DIFF_TICK(sd->canequip_tick,gettick()) > 0 ) + { + clif_equipitemack(sd,n,0,0); + return 0; + } + + id = sd->inventory_data[n]; + pos = pc_equippoint(sd,n); //With a few exceptions, item should go in all specified slots. + + if(battle_config.battle_log) + ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos); + if(!pc_isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris] + // FIXME: pc_isequip: equip level failure uses 2 instead of 0 + clif_equipitemack(sd,n,0,0); // fail + return 0; + } + + if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST]) + { + clif_equipitemack(sd,n,0,0); // fail + return 0; + } + + if(pos == EQP_ACC) { //Accesories should only go in one of the two, + pos = req_pos&EQP_ACC; + if (pos == EQP_ACC) //User specified both slots.. + pos = sd->equip_index[EQI_ACC_R] >= 0 ? EQP_ACC_L : EQP_ACC_R; + } + + if(pos == EQP_ARMS && id->equip == EQP_HAND_R) + { //Dual wield capable weapon. + pos = (req_pos&EQP_ARMS); + if (pos == EQP_ARMS) //User specified both slots, pick one for them. + pos = sd->equip_index[EQI_HAND_R] >= 0 ? EQP_HAND_L : EQP_HAND_R; + } + + if (pos&EQP_HAND_R && battle_config.use_weapon_skill_range&BL_PC) + { //Update skill-block range database when weapon range changes. [Skotlex] + i = sd->equip_index[EQI_HAND_R]; + if (i < 0 || !sd->inventory_data[i]) //No data, or no weapon equipped + flag = 1; + else + flag = id->range != sd->inventory_data[i]->range; + } + + for(i=0;i<EQI_MAX;i++) { + if(pos & equip_pos[i]) { + if(sd->equip_index[i] >= 0) //Slot taken, remove item from there. + pc_unequipitem(sd,sd->equip_index[i],2); + + sd->equip_index[i] = n; + } + } + + if(pos==EQP_AMMO){ + clif_arrowequip(sd,n); + clif_arrow_fail(sd,3); + } + else + clif_equipitemack(sd,n,pos,1); + + sd->status.inventory[n].equip=pos; + + if(pos & EQP_HAND_R) { + if(id) + sd->weapontype1 = id->look; + else + sd->weapontype1 = 0; + pc_calcweapontype(sd); + clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); + } + if(pos & EQP_HAND_L) { + if(id) { + if(id->type == IT_WEAPON) { + sd->status.shield = 0; + sd->weapontype2 = id->look; + } + else + if(id->type == IT_ARMOR) { + sd->status.shield = id->look; + sd->weapontype2 = 0; + } + } + else + sd->status.shield = sd->weapontype2 = 0; + pc_calcweapontype(sd); + clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); + } + //Added check to prevent sending the same look on multiple slots -> + //causes client to redraw item on top of itself. (suggested by Lupus) + if(pos & EQP_HEAD_LOW && pc_checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1) { + if(id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID))) + sd->status.head_bottom = id->look; + else + sd->status.head_bottom = 0; + clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + } + if(pos & EQP_HEAD_TOP && pc_checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1) { + if(id) + sd->status.head_top = id->look; + else + sd->status.head_top = 0; + clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + } + if(pos & EQP_HEAD_MID && pc_checkequip(sd,EQP_COSTUME_HEAD_MID) == -1) { + if(id && !(pos&EQP_HEAD_TOP)) + sd->status.head_mid = id->look; + else + sd->status.head_mid = 0; + clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + } + if(pos & EQP_COSTUME_HEAD_TOP) { + if(id){ + sd->status.head_top = id->look; + } else + sd->status.head_top = 0; + clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + } + if(pos & EQP_COSTUME_HEAD_MID) { + if(id && !(pos&EQP_HEAD_TOP)){ + sd->status.head_mid = id->look; + } else + sd->status.head_mid = 0; + clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + } + if(pos & EQP_COSTUME_HEAD_LOW) { + if(id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID))){ + sd->status.head_bottom = id->look; + } else + sd->status.head_bottom = 0; + clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + } + if(pos & EQP_SHOES) + clif_changelook(&sd->bl,LOOK_SHOES,0); + if( pos&EQP_GARMENT ) + { + sd->status.robe = id ? id->look : 0; + clif_changelook(&sd->bl, LOOK_ROBE, sd->status.robe); + } + + pc_checkallowskill(sd); //Check if status changes should be halted. + + /* check for combos (MUST be before status_calc_pc) */ + if ( id ) { + struct item_data *data; + if( id->combos_count ) + pc_checkcombo(sd,id); + if(itemdb_isspecial(sd->status.inventory[n].card[0])) + ; //No cards + else { + for( i = 0; i < id->slot; i++ ) { + if (!sd->status.inventory[n].card[i]) + continue; + if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { + if( data->combos_count ) + pc_checkcombo(sd,data); + } + } + } + } + + status_calc_pc(sd,0); + if (flag) //Update skill data + clif_skillinfoblock(sd); + + //OnEquip script [Skotlex] + if (id) { + struct item_data *data; + if (id->equip_script) + run_script(id->equip_script,0,sd->bl.id,fake_nd->bl.id); + if(itemdb_isspecial(sd->status.inventory[n].card[0])) + ; //No cards + else { + for( i = 0; i < id->slot; i++ ) { + if (!sd->status.inventory[n].card[i]) + continue; + if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { + if( data->equip_script ) + run_script(data->equip_script,0,sd->bl.id,fake_nd->bl.id); + } + } + } + } + return 0; } /*========================================== @@ -8535,159 +8407,160 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) * 1 - calculate status after unequipping * 2 - force unequip *------------------------------------------*/ -int pc_unequipitem(struct map_session_data *sd,int n,int flag) -{ - int i; - bool status_cacl = false; - nullpo_ret(sd); - - if (n < 0 || n >= MAX_INVENTORY) { - clif_unequipitemack(sd,0,0,0); - return 0; - } - - // if player is berserk then cannot unequip - if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST])) { - clif_unequipitemack(sd,n,0,0); - return 0; - } - - if (!(flag&2) && sd->sc.count && sd->sc.data[SC_KYOUGAKU]) { - clif_unequipitemack(sd,n,0,0); - return 0; - } - - if (battle_config.battle_log) - ShowInfo("unequip %d %x:%x\n",n,pc_equippoint(sd,n),sd->status.inventory[n].equip); - - if (!sd->status.inventory[n].equip) { //Nothing to unequip - clif_unequipitemack(sd,n,0,0); - return 0; - } - for (i=0; i<EQI_MAX; i++) { - if (sd->status.inventory[n].equip & equip_pos[i]) - sd->equip_index[i] = -1; - } - - if (sd->status.inventory[n].equip & EQP_HAND_R) { - sd->weapontype1 = 0; - sd->status.weapon = sd->weapontype2; - pc_calcweapontype(sd); - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); - if (!battle_config.dancing_weaponswitch_fix) - status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); // Unequipping => stop dancing. - } - if (sd->status.inventory[n].equip & EQP_HAND_L) { - sd->status.shield = sd->weapontype2 = 0; - pc_calcweapontype(sd); - clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); - } - if (sd->status.inventory[n].equip & EQP_HEAD_LOW && pc_checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1) { - sd->status.head_bottom = 0; - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); - } - if (sd->status.inventory[n].equip & EQP_HEAD_TOP && pc_checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1) { - sd->status.head_top = 0; - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); - } - if (sd->status.inventory[n].equip & EQP_HEAD_MID && pc_checkequip(sd,EQP_COSTUME_HEAD_MID) == -1) { - sd->status.head_mid = 0; - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); - } - - if (sd->status.inventory[n].equip & EQP_COSTUME_HEAD_TOP) { - sd->status.head_top = (pc_checkequip(sd,EQP_HEAD_TOP) >= 0) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_TOP)]->look : 0; - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); - } - - if (sd->status.inventory[n].equip & EQP_COSTUME_HEAD_MID) { - sd->status.head_mid = (pc_checkequip(sd,EQP_HEAD_MID) >= 0) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_MID)]->look : 0; - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); - } - - if (sd->status.inventory[n].equip & EQP_COSTUME_HEAD_LOW) { - sd->status.head_bottom = (pc_checkequip(sd,EQP_HEAD_LOW) >= 0) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_LOW)]->look : 0; - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); - } - - if (sd->status.inventory[n].equip & EQP_SHOES) - clif_changelook(&sd->bl,LOOK_SHOES,0); - if (sd->status.inventory[n].equip&EQP_GARMENT) { - sd->status.robe = 0; - clif_changelook(&sd->bl, LOOK_ROBE, 0); - } - - clif_unequipitemack(sd,n,sd->status.inventory[n].equip,1); - - if ((sd->status.inventory[n].equip & EQP_ARMS) && - sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!) - skill_enchant_elemental_end(&sd->bl,-1); - - if (sd->status.inventory[n].equip & EQP_ARMOR) { - // On Armor Change... - status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER); - status_change_end(&sd->bl, SC_ARMOR_RESIST, INVALID_TIMER); - } - - if (sd->state.autobonus&sd->status.inventory[n].equip) - sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish] - - sd->status.inventory[n].equip=0; - - /* check for combos (MUST be before status_calc_pc) */ - if (sd->inventory_data[n]) { - struct item_data *data; - - if (sd->inventory_data[n]->combos_count) { - if (pc_removecombo(sd,sd->inventory_data[n])) - status_cacl = true; - } - if (itemdb_isspecial(sd->status.inventory[n].card[0])) - ; //No cards - else { - for (i = 0; i < sd->inventory_data[n]->slot; i++) { - if (!sd->status.inventory[n].card[i]) - continue; - if ((data = itemdb_exists(sd->status.inventory[n].card[i])) != NULL) { - if (data->combos_count) { - if (pc_removecombo(sd,data)) - status_cacl = true; - } - } - } - } - } - - if (flag&1 || status_cacl) { - pc_checkallowskill(sd); - status_calc_pc(sd,0); - } - - if (sd->sc.data[SC_SIGNUMCRUCIS] && !battle_check_undead(sd->battle_status.race,sd->battle_status.def_ele)) - status_change_end(&sd->bl, SC_SIGNUMCRUCIS, INVALID_TIMER); - - //OnUnEquip script [Skotlex] - if (sd->inventory_data[n]) { - struct item_data *data; - if (sd->inventory_data[n]->unequip_script) - run_script(sd->inventory_data[n]->unequip_script,0,sd->bl.id,fake_nd->bl.id); - if (itemdb_isspecial(sd->status.inventory[n].card[0])) - ; //No cards - else { - for (i = 0; i < sd->inventory_data[n]->slot; i++) { - if (!sd->status.inventory[n].card[i]) - continue; - - if ((data = itemdb_exists(sd->status.inventory[n].card[i])) != NULL) { - if (data->unequip_script) - run_script(data->unequip_script,0,sd->bl.id,fake_nd->bl.id); - } - - } - } - } - - return 0; +int pc_unequipitem(struct map_session_data *sd,int n,int flag) { + int i; + bool status_cacl = false; + nullpo_ret(sd); + + if( n < 0 || n >= MAX_INVENTORY ) { + clif_unequipitemack(sd,0,0,0); + return 0; + } + + // if player is berserk then cannot unequip + if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST])) + { + clif_unequipitemack(sd,n,0,0); + return 0; + } + + if( !(flag&2) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] ) + { + clif_unequipitemack(sd,n,0,0); + return 0; + } + + if(battle_config.battle_log) + ShowInfo("unequip %d %x:%x\n",n,pc_equippoint(sd,n),sd->status.inventory[n].equip); + + if(!sd->status.inventory[n].equip){ //Nothing to unequip + clif_unequipitemack(sd,n,0,0); + return 0; + } + for(i=0;i<EQI_MAX;i++) { + if(sd->status.inventory[n].equip & equip_pos[i]) + sd->equip_index[i] = -1; + } + + if(sd->status.inventory[n].equip & EQP_HAND_R) { + sd->weapontype1 = 0; + sd->status.weapon = sd->weapontype2; + pc_calcweapontype(sd); + clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); + if( !battle_config.dancing_weaponswitch_fix ) + status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); // Unequipping => stop dancing. + } + if(sd->status.inventory[n].equip & EQP_HAND_L) { + sd->status.shield = sd->weapontype2 = 0; + pc_calcweapontype(sd); + clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); + } + if(sd->status.inventory[n].equip & EQP_HEAD_LOW && pc_checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1 ) { + sd->status.head_bottom = 0; + clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + } + if(sd->status.inventory[n].equip & EQP_HEAD_TOP && pc_checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1 ) { + sd->status.head_top = 0; + clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + } + if(sd->status.inventory[n].equip & EQP_HEAD_MID && pc_checkequip(sd,EQP_COSTUME_HEAD_MID) == -1 ) { + sd->status.head_mid = 0; + clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + } + + if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_TOP) { + sd->status.head_top = ( pc_checkequip(sd,EQP_HEAD_TOP) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_TOP)]->look : 0; + clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + } + + if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_MID) { + sd->status.head_mid = ( pc_checkequip(sd,EQP_HEAD_MID) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_MID)]->look : 0; + clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + } + + if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_LOW) { + sd->status.head_bottom = ( pc_checkequip(sd,EQP_HEAD_LOW) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_LOW)]->look : 0; + clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + } + + if(sd->status.inventory[n].equip & EQP_SHOES) + clif_changelook(&sd->bl,LOOK_SHOES,0); + if( sd->status.inventory[n].equip&EQP_GARMENT ) + { + sd->status.robe = 0; + clif_changelook(&sd->bl, LOOK_ROBE, 0); + } + + clif_unequipitemack(sd,n,sd->status.inventory[n].equip,1); + + if((sd->status.inventory[n].equip & EQP_ARMS) && + sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!) + skill_enchant_elemental_end(&sd->bl,-1); + + if(sd->status.inventory[n].equip & EQP_ARMOR) { + // On Armor Change... + status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER); + status_change_end(&sd->bl, SC_ARMOR_RESIST, INVALID_TIMER); + } + + if( sd->state.autobonus&sd->status.inventory[n].equip ) + sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish] + + sd->status.inventory[n].equip=0; + + /* check for combos (MUST be before status_calc_pc) */ + if ( sd->inventory_data[n] ) { + struct item_data *data; + + if( sd->inventory_data[n]->combos_count ) { + if( pc_removecombo(sd,sd->inventory_data[n]) ) + status_cacl = true; + } if(itemdb_isspecial(sd->status.inventory[n].card[0])) + ; //No cards + else { + for( i = 0; i < sd->inventory_data[n]->slot; i++ ) { + if (!sd->status.inventory[n].card[i]) + continue; + if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { + if( data->combos_count ) { + if( pc_removecombo(sd,data) ) + status_cacl = true; + } + } + } + } + } + + if(flag&1 || status_cacl) { + pc_checkallowskill(sd); + status_calc_pc(sd,0); + } + + if(sd->sc.data[SC_SIGNUMCRUCIS] && !battle_check_undead(sd->battle_status.race,sd->battle_status.def_ele)) + status_change_end(&sd->bl, SC_SIGNUMCRUCIS, INVALID_TIMER); + + //OnUnEquip script [Skotlex] + if (sd->inventory_data[n]) { + struct item_data *data; + if (sd->inventory_data[n]->unequip_script) + run_script(sd->inventory_data[n]->unequip_script,0,sd->bl.id,fake_nd->bl.id); + if(itemdb_isspecial(sd->status.inventory[n].card[0])) + ; //No cards + else { + for( i = 0; i < sd->inventory_data[n]->slot; i++ ) { + if (!sd->status.inventory[n].card[i]) + continue; + + if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { + if( data->unequip_script ) + run_script(data->unequip_script,0,sd->bl.id,fake_nd->bl.id); + } + + } + } + } + + return 0; } /*========================================== @@ -8696,71 +8569,79 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) *------------------------------------------*/ int pc_checkitem(struct map_session_data *sd) { - int i,id,calc_flag = 0; - struct item_data *it=NULL; - - nullpo_ret(sd); - - if (sd->state.vending) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam) - return 0; - - if (battle_config.item_check) { - // check for invalid(ated) items - for (i = 0; i < MAX_INVENTORY; i++) { - id = sd->status.inventory[i].nameid; - - if (id && !itemdb_available(id)) { - ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id); - pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); - } - } - - for (i = 0; i < MAX_CART; i++) { - id = sd->status.cart[i].nameid; - - if (id && !itemdb_available(id)) { - ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id); - pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER); - } - } - } - - for (i = 0; i < MAX_INVENTORY; i++) { - it = sd->inventory_data[i]; - - if (sd->status.inventory[i].nameid == 0) - continue; - - if (!sd->status.inventory[i].equip) - continue; - - if (sd->status.inventory[i].equip&~pc_equippoint(sd,i)) { - pc_unequipitem(sd, i, 2); - calc_flag = 1; - continue; - } - - if (it) { - // check for forbiden items. - int flag = - (map[sd->bl.m].flag.restricted?(8*map[sd->bl.m].zone):0) - | (!map_flag_vs(sd->bl.m)?1:0) - | (map[sd->bl.m].flag.pvp?2:0) - | (map_flag_gvg(sd->bl.m)?4:0) - | (map[sd->bl.m].flag.battleground?8:0); - if (flag && (it->flag.no_equip&flag || !pc_isAllowedCardOn(sd,it->slot,i,flag))) { - pc_unequipitem(sd, i, 2); - calc_flag = 1; - } - } - } - - if (calc_flag && sd->state.active) { - pc_checkallowskill(sd); - status_calc_pc(sd,0); - } - - return 0; + int i,id,calc_flag = 0; + struct item_data *it=NULL; + + nullpo_ret(sd); + + if( sd->state.vending ) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam) + return 0; + + if( battle_config.item_check ) + {// check for invalid(ated) items + for( i = 0; i < MAX_INVENTORY; i++ ) + { + id = sd->status.inventory[i].nameid; + + if( id && !itemdb_available(id) ) + { + ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id); + pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); + } + } + + for( i = 0; i < MAX_CART; i++ ) + { + id = sd->status.cart[i].nameid; + + if( id && !itemdb_available(id) ) + { + ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id); + pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER); + } + } + } + + for( i = 0; i < MAX_INVENTORY; i++) + { + it = sd->inventory_data[i]; + + if( sd->status.inventory[i].nameid == 0 ) + continue; + + if( !sd->status.inventory[i].equip ) + continue; + + if( sd->status.inventory[i].equip&~pc_equippoint(sd,i) ) + { + pc_unequipitem(sd, i, 2); + calc_flag = 1; + continue; + } + + if( it ) + { // check for forbiden items. + int flag = + (map[sd->bl.m].flag.restricted?(8*map[sd->bl.m].zone):0) + | (!map_flag_vs(sd->bl.m)?1:0) + | (map[sd->bl.m].flag.pvp?2:0) + | (map_flag_gvg(sd->bl.m)?4:0) + | (map[sd->bl.m].flag.battleground?8:0); + if( flag && (it->flag.no_equip&flag || !pc_isAllowedCardOn(sd,it->slot,i,flag)) ) + { + pc_unequipitem(sd, i, 2); + calc_flag = 1; + } + } + } + + if( calc_flag && sd->state.active ) + { + pc_checkallowskill(sd); + status_calc_pc(sd,0); + } + + return 0; } /*========================================== @@ -8768,19 +8649,19 @@ int pc_checkitem(struct map_session_data *sd) *------------------------------------------*/ int pc_calc_pvprank_sub(struct block_list *bl,va_list ap) { - struct map_session_data *sd1,*sd2=NULL; + struct map_session_data *sd1,*sd2=NULL; - sd1=(struct map_session_data *)bl; - sd2=va_arg(ap,struct map_session_data *); + sd1=(struct map_session_data *)bl; + sd2=va_arg(ap,struct map_session_data *); - if (sd1->sc.option&OPTION_INVISIBLE || sd2->sc.option&OPTION_INVISIBLE) { - // cannot register pvp rank for hidden GMs - return 0; - } + if( sd1->sc.option&OPTION_INVISIBLE || sd2->sc.option&OPTION_INVISIBLE ) + {// cannot register pvp rank for hidden GMs + return 0; + } - if (sd1->pvp_point > sd2->pvp_point) - sd2->pvp_rank++; - return 0; + if( sd1->pvp_point > sd2->pvp_point ) + sd2->pvp_rank++; + return 0; } /*========================================== * Calculate new rank beetween all present players (map_foreachinarea) @@ -8788,216 +8669,221 @@ int pc_calc_pvprank_sub(struct block_list *bl,va_list ap) *------------------------------------------*/ int pc_calc_pvprank(struct map_session_data *sd) { - int old; - struct map_data *m; - m=&map[sd->bl.m]; - old=sd->pvp_rank; - sd->pvp_rank=1; - map_foreachinmap(pc_calc_pvprank_sub,sd->bl.m,BL_PC,sd); - if (old!=sd->pvp_rank || sd->pvp_lastusers!=m->users_pvp) - clif_pvpset(sd,sd->pvp_rank,sd->pvp_lastusers=m->users_pvp,0); - return sd->pvp_rank; + int old; + struct map_data *m; + m=&map[sd->bl.m]; + old=sd->pvp_rank; + sd->pvp_rank=1; + map_foreachinmap(pc_calc_pvprank_sub,sd->bl.m,BL_PC,sd); + if(old!=sd->pvp_rank || sd->pvp_lastusers!=m->users_pvp) + clif_pvpset(sd,sd->pvp_rank,sd->pvp_lastusers=m->users_pvp,0); + return sd->pvp_rank; } /*========================================== * Calculate next sd ranking calculation from config *------------------------------------------*/ int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd=NULL; + struct map_session_data *sd=NULL; - sd=map_id2sd(id); - if (sd==NULL) - return 0; - sd->pvp_timer = INVALID_TIMER; + sd=map_id2sd(id); + if(sd==NULL) + return 0; + sd->pvp_timer = INVALID_TIMER; - if (sd->sc.option&OPTION_INVISIBLE) { - // do not calculate the pvp rank for a hidden GM - return 0; - } + if( sd->sc.option&OPTION_INVISIBLE ) + {// do not calculate the pvp rank for a hidden GM + return 0; + } - if (pc_calc_pvprank(sd) > 0) - sd->pvp_timer = add_timer(gettick()+PVP_CALCRANK_INTERVAL,pc_calc_pvprank_timer,id,data); - return 0; + if( pc_calc_pvprank(sd) > 0 ) + sd->pvp_timer = add_timer(gettick()+PVP_CALCRANK_INTERVAL,pc_calc_pvprank_timer,id,data); + return 0; } /*========================================== * Checking if sd is married * Return: - * partner_id = yes - * 0 = no + * partner_id = yes + * 0 = no *------------------------------------------*/ int pc_ismarried(struct map_session_data *sd) { - if (sd == NULL) - return -1; - if (sd->status.partner_id > 0) - return sd->status.partner_id; - else - return 0; + if(sd == NULL) + return -1; + if(sd->status.partner_id > 0) + return sd->status.partner_id; + else + return 0; } /*========================================== * Marry player sd to player dstsd * Return: - * -1 = fail - * 0 = success + * -1 = fail + * 0 = success *------------------------------------------*/ 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 || - (sd->class_&JOBL_BABY) || (dstsd->class_&JOBL_BABY)) - return -1; - sd->status.partner_id = dstsd->status.char_id; - dstsd->status.partner_id = sd->status.char_id; - return 0; + if(sd == NULL || dstsd == NULL || + sd->status.partner_id > 0 || dstsd->status.partner_id > 0 || + (sd->class_&JOBL_BABY) || (dstsd->class_&JOBL_BABY)) + return -1; + sd->status.partner_id = dstsd->status.char_id; + dstsd->status.partner_id = sd->status.char_id; + return 0; } /*========================================== * Divorce sd from its partner * Return: - * -1 = fail - * 0 = success + * -1 = fail + * 0 = success *------------------------------------------*/ int pc_divorce(struct map_session_data *sd) { - struct map_session_data *p_sd; - int i; + struct map_session_data *p_sd; + int i; - if (sd == NULL || !pc_ismarried(sd)) - return -1; + if( sd == NULL || !pc_ismarried(sd) ) + return -1; - if (!sd->status.partner_id) - return -1; // Char is not married + if( !sd->status.partner_id ) + return -1; // Char is not married - if ((p_sd = map_charid2sd(sd->status.partner_id)) == NULL) { - // Lets char server do the divorce - if (chrif_divorce(sd->status.char_id, sd->status.partner_id)) - return -1; // No char server connected + if( (p_sd = map_charid2sd(sd->status.partner_id)) == NULL ) + { // Lets char server do the divorce + if( chrif_divorce(sd->status.char_id, sd->status.partner_id) ) + return -1; // No char server connected - return 0; - } + return 0; + } - // Both players online, lets do the divorce manually - sd->status.partner_id = 0; - p_sd->status.partner_id = 0; - for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) - pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); - if (p_sd->status.inventory[i].nameid == WEDDING_RING_M || p_sd->status.inventory[i].nameid == WEDDING_RING_F) - pc_delitem(p_sd, i, 1, 0, 0, LOG_TYPE_OTHER); - } + // Both players online, lets do the divorce manually + sd->status.partner_id = 0; + p_sd->status.partner_id = 0; + for( i = 0; i < MAX_INVENTORY; i++ ) + { + if( sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F ) + pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); + if( p_sd->status.inventory[i].nameid == WEDDING_RING_M || p_sd->status.inventory[i].nameid == WEDDING_RING_F ) + pc_delitem(p_sd, i, 1, 0, 0, LOG_TYPE_OTHER); + } - clif_divorced(sd, p_sd->status.name); - clif_divorced(p_sd, sd->status.name); + clif_divorced(sd, p_sd->status.name); + clif_divorced(p_sd, sd->status.name); - return 0; + return 0; } /*========================================== * Get sd partner charid. (Married partner) *------------------------------------------*/ -struct map_session_data *pc_get_partner(struct map_session_data *sd) { - if (sd && pc_ismarried(sd)) - // charid2sd returns NULL if not found - return map_charid2sd(sd->status.partner_id); +struct map_session_data *pc_get_partner(struct map_session_data *sd) +{ + if (sd && pc_ismarried(sd)) + // charid2sd returns NULL if not found + return map_charid2sd(sd->status.partner_id); - return NULL; + return NULL; } /*========================================== * Get sd father charid. (Need to be baby) *------------------------------------------*/ -struct map_session_data *pc_get_father(struct map_session_data *sd) { - if (sd && sd->class_&JOBL_BABY && sd->status.father > 0) - // charid2sd returns NULL if not found - return map_charid2sd(sd->status.father); +struct map_session_data *pc_get_father (struct map_session_data *sd) +{ + if (sd && sd->class_&JOBL_BABY && sd->status.father > 0) + // charid2sd returns NULL if not found + return map_charid2sd(sd->status.father); - return NULL; + return NULL; } /*========================================== * Get sd mother charid. (Need to be baby) *------------------------------------------*/ -struct map_session_data *pc_get_mother(struct map_session_data *sd) { - if (sd && sd->class_&JOBL_BABY && sd->status.mother > 0) - // charid2sd returns NULL if not found - return map_charid2sd(sd->status.mother); +struct map_session_data *pc_get_mother (struct map_session_data *sd) +{ + if (sd && sd->class_&JOBL_BABY && sd->status.mother > 0) + // charid2sd returns NULL if not found + return map_charid2sd(sd->status.mother); - return NULL; + return NULL; } /*========================================== * Get sd children charid. (Need to be married) *------------------------------------------*/ -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); +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; + return NULL; } /*========================================== * Set player sd to bleed. (losing hp and/or sp each diff_tick) *------------------------------------------*/ -void pc_bleeding(struct map_session_data *sd, unsigned int diff_tick) +void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick) { - int hp = 0, sp = 0; + int hp = 0, sp = 0; - if (pc_isdead(sd)) - return; + if( pc_isdead(sd) ) + return; - if (sd->hp_loss.value) { - sd->hp_loss.tick += diff_tick; - while (sd->hp_loss.tick >= sd->hp_loss.rate) { - hp += sd->hp_loss.value; - sd->hp_loss.tick -= sd->hp_loss.rate; - } - if (hp >= sd->battle_status.hp) - hp = sd->battle_status.hp-1; //Script drains cannot kill you. - } + if (sd->hp_loss.value) { + sd->hp_loss.tick += diff_tick; + while (sd->hp_loss.tick >= sd->hp_loss.rate) { + hp += sd->hp_loss.value; + sd->hp_loss.tick -= sd->hp_loss.rate; + } + if(hp >= sd->battle_status.hp) + hp = sd->battle_status.hp-1; //Script drains cannot kill you. + } - if (sd->sp_loss.value) { - sd->sp_loss.tick += diff_tick; - while (sd->sp_loss.tick >= sd->sp_loss.rate) { - sp += sd->sp_loss.value; - sd->sp_loss.tick -= sd->sp_loss.rate; - } - } + if (sd->sp_loss.value) { + sd->sp_loss.tick += diff_tick; + while (sd->sp_loss.tick >= sd->sp_loss.rate) { + sp += sd->sp_loss.value; + sd->sp_loss.tick -= sd->sp_loss.rate; + } + } - if (hp > 0 || sp > 0) - status_zap(&sd->bl, hp, sp); + if (hp > 0 || sp > 0) + status_zap(&sd->bl, hp, sp); - return; + return; } //Character regen. Flag is used to know which types of regen can take place. //&1: HP regen //&2: SP regen -void pc_regen(struct map_session_data *sd, unsigned int diff_tick) +void pc_regen (struct map_session_data *sd, unsigned int diff_tick) { - int hp = 0, sp = 0; + int hp = 0, sp = 0; - if (sd->hp_regen.value) { - sd->hp_regen.tick += diff_tick; - while (sd->hp_regen.tick >= sd->hp_regen.rate) { - hp += sd->hp_regen.value; - sd->hp_regen.tick -= sd->hp_regen.rate; - } - } + if (sd->hp_regen.value) { + sd->hp_regen.tick += diff_tick; + while (sd->hp_regen.tick >= sd->hp_regen.rate) { + hp += sd->hp_regen.value; + sd->hp_regen.tick -= sd->hp_regen.rate; + } + } - if (sd->sp_regen.value) { - sd->sp_regen.tick += diff_tick; - while (sd->sp_regen.tick >= sd->sp_regen.rate) { - sp += sd->sp_regen.value; - sd->sp_regen.tick -= sd->sp_regen.rate; - } - } + if (sd->sp_regen.value) { + sd->sp_regen.tick += diff_tick; + while (sd->sp_regen.tick >= sd->sp_regen.rate) { + sp += sd->sp_regen.value; + sd->sp_regen.tick -= sd->sp_regen.rate; + } + } - if (hp > 0 || sp > 0) - status_heal(&sd->bl, hp, sp, 0); + if (hp > 0 || sp > 0) + status_heal(&sd->bl, hp, sp, 0); - return; + return; } /*========================================== @@ -9005,13 +8891,13 @@ void pc_regen(struct map_session_data *sd, unsigned int diff_tick) *------------------------------------------*/ int pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y) { - nullpo_ret(sd); + nullpo_ret(sd); - sd->status.save_point.map = mapindex; - sd->status.save_point.x = x; - sd->status.save_point.y = y; + sd->status.save_point.map = mapindex; + sd->status.save_point.x = x; + sd->status.save_point.y = y; - return 0; + return 0; } /*========================================== @@ -9019,52 +8905,53 @@ int pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y) *------------------------------------------*/ int pc_autosave(int tid, unsigned int tick, int id, intptr_t data) { - int interval; - struct s_mapiterator *iter; - struct map_session_data *sd; - static int last_save_id = 0, save_flag = 0; + int interval; + struct s_mapiterator* iter; + struct map_session_data* sd; + static int last_save_id = 0, save_flag = 0; - if (save_flag == 2) //Someone was saved on last call, normal cycle - save_flag = 0; - else - save_flag = 1; //Noone was saved, so save first found char. + if(save_flag == 2) //Someone was saved on last call, normal cycle + save_flag = 0; + else + save_flag = 1; //Noone was saved, so save first found char. - iter = mapit_getallusers(); - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) { - if (sd->bl.id == last_save_id && save_flag != 1) { - save_flag = 1; - continue; - } + iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + { + if(sd->bl.id == last_save_id && save_flag != 1) { + save_flag = 1; + continue; + } - if (save_flag != 1) //Not our turn to save yet. - continue; + if(save_flag != 1) //Not our turn to save yet. + continue; - //Save char. - last_save_id = sd->bl.id; - save_flag = 2; + //Save char. + last_save_id = sd->bl.id; + save_flag = 2; - chrif_save(sd,0); - break; - } - mapit_free(iter); + chrif_save(sd,0); + break; + } + mapit_free(iter); - interval = autosave_interval/(map_usercount()+1); - if (interval < minsave_interval) - interval = minsave_interval; - add_timer(gettick()+interval,pc_autosave,0,0); + interval = autosave_interval/(map_usercount()+1); + if(interval < minsave_interval) + interval = minsave_interval; + add_timer(gettick()+interval,pc_autosave,0,0); - return 0; + return 0; } static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) { - if (sd->state.night != night_flag && map[sd->bl.m].flag.nightenabled) { - //Night/day state does not match. - clif_status_load(&sd->bl, SI_NIGHT, night_flag); //New night effect by dynamix [Skotlex] - sd->state.night = night_flag; - return 1; - } - return 0; + if (sd->state.night != night_flag && map[sd->bl.m].flag.nightenabled) + { //Night/day state does not match. + clif_status_load(&sd->bl, SI_NIGHT, night_flag); //New night effect by dynamix [Skotlex] + sd->state.night = night_flag; + return 1; + } + return 0; } /*================================================ * timer to do the day [Yor] @@ -9072,19 +8959,19 @@ static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) *------------------------------------------------*/ int map_day_timer(int tid, unsigned int tick, int id, intptr_t data) { - char tmp_soutput[1024]; + char tmp_soutput[1024]; - if (data == 0 && battle_config.day_duration <= 0) // if we want a day - return 0; + if (data == 0 && battle_config.day_duration <= 0) // if we want a day + return 0; - if (!night_flag) - return 0; //Already day. + if (!night_flag) + return 0; //Already day. - night_flag = 0; // 0=day, 1=night [Yor] - map_foreachpc(pc_daynight_timer_sub); - strcpy(tmp_soutput, (data == 0) ? msg_txt(502) : msg_txt(60)); // The day has arrived! - intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0); - return 0; + night_flag = 0; // 0=day, 1=night [Yor] + map_foreachpc(pc_daynight_timer_sub); + strcpy(tmp_soutput, (data == 0) ? msg_txt(502) : msg_txt(60)); // The day has arrived! + intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0); + return 0; } /*================================================ @@ -9093,56 +8980,54 @@ int map_day_timer(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------------*/ int map_night_timer(int tid, unsigned int tick, int id, intptr_t data) { - char tmp_soutput[1024]; + char tmp_soutput[1024]; - if (data == 0 && battle_config.night_duration <= 0) // if we want a night - return 0; + if (data == 0 && battle_config.night_duration <= 0) // if we want a night + return 0; - if (night_flag) - return 0; //Already nigth. + if (night_flag) + return 0; //Already nigth. - night_flag = 1; // 0=day, 1=night [Yor] - map_foreachpc(pc_daynight_timer_sub); - strcpy(tmp_soutput, (data == 0) ? msg_txt(503) : msg_txt(59)); // The night has fallen... - intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0); - return 0; + night_flag = 1; // 0=day, 1=night [Yor] + map_foreachpc(pc_daynight_timer_sub); + strcpy(tmp_soutput, (data == 0) ? msg_txt(503) : msg_txt(59)); // The night has fallen... + intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0); + return 0; } -void pc_setstand(struct map_session_data *sd) -{ - nullpo_retv(sd); +void pc_setstand(struct map_session_data *sd){ + nullpo_retv(sd); - status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER); - clif_status_load(&sd->bl,SI_SIT,0); - //Reset sitting tick. - sd->ssregen.tick.hp = sd->ssregen.tick.sp = 0; - sd->state.dead_sit = sd->vd.dead_sit = 0; + status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER); + clif_status_load(&sd->bl,SI_SIT,0); + //Reset sitting tick. + sd->ssregen.tick.hp = sd->ssregen.tick.sp = 0; + sd->state.dead_sit = sd->vd.dead_sit = 0; } /** * Mechanic (MADO GEAR) **/ -void pc_overheat(struct map_session_data *sd, int val) -{ - int heat = val, skill, - limit[] = { 10, 20, 28, 46, 66 }; +void pc_overheat(struct map_session_data *sd, int val) { + int heat = val, skill, + limit[] = { 10, 20, 28, 46, 66 }; - if (!pc_ismadogear(sd) || sd->sc.data[SC_OVERHEAT]) - return; // already burning + if( !pc_ismadogear(sd) || sd->sc.data[SC_OVERHEAT] ) + return; // already burning - skill = cap_value(pc_checkskill(sd,NC_MAINFRAME),0,4); - if (sd->sc.data[SC_OVERHEAT_LIMITPOINT]) { - heat += sd->sc.data[SC_OVERHEAT_LIMITPOINT]->val1; - status_change_end(&sd->bl,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); - } + skill = cap_value(pc_checkskill(sd,NC_MAINFRAME),0,4); + if( sd->sc.data[SC_OVERHEAT_LIMITPOINT] ) { + heat += sd->sc.data[SC_OVERHEAT_LIMITPOINT]->val1; + status_change_end(&sd->bl,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); + } - heat = max(0,heat); // Avoid negative HEAT - if (heat >= limit[skill]) - sc_start(&sd->bl,SC_OVERHEAT,100,0,1000); - else - sc_start(&sd->bl,SC_OVERHEAT_LIMITPOINT,100,heat,30000); + heat = max(0,heat); // Avoid negative HEAT + if( heat >= limit[skill] ) + sc_start(&sd->bl,SC_OVERHEAT,100,0,1000); + else + sc_start(&sd->bl,SC_OVERHEAT_LIMITPOINT,100,heat,30000); - return; + return; } /** @@ -9150,11 +9035,11 @@ void pc_overheat(struct map_session_data *sd, int val) */ bool pc_isautolooting(struct map_session_data *sd, int nameid) { - int i; - if (!sd->state.autolooting) - return false; - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == nameid); - return (i != AUTOLOOTITEM_SIZE); + int i; + if( !sd->state.autolooting ) + return false; + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == nameid); + return (i != AUTOLOOTITEM_SIZE); } /** @@ -9165,7 +9050,7 @@ bool pc_isautolooting(struct map_session_data *sd, int nameid) */ bool pc_can_use_command(struct map_session_data *sd, const char *command, AtCommandType type) { - return pc_group_can_use_command(pc_get_group_id(sd), command, type); + return pc_group_can_use_command(pc_get_group_id(sd), command, type); } /** @@ -9175,104 +9060,107 @@ bool pc_can_use_command(struct map_session_data *sd, const char *command, AtComm */ bool pc_should_log_commands(struct map_session_data *sd) { - return pc_group_should_log_commands(pc_get_group_id(sd)); + return pc_group_should_log_commands(pc_get_group_id(sd)); } static int pc_talisman_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd; - int i, type; + struct map_session_data *sd; + int i, type; - if ((sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC) - return 1; + if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC ) + return 1; - ARR_FIND(1, 5, type, sd->talisman[type] > 0); + ARR_FIND(1, 5, type, sd->talisman[type] > 0); - if (sd->talisman[type] <= 0) { - ShowError("pc_talisman_timer: %d talisman's available. (aid=%d cid=%d tid=%d)\n", sd->talisman[type], sd->status.account_id, sd->status.char_id, tid); - sd->talisman[type] = 0; - return 0; - } + if( sd->talisman[type] <= 0 ) + { + ShowError("pc_talisman_timer: %d talisman's available. (aid=%d cid=%d tid=%d)\n", sd->talisman[type], sd->status.account_id, sd->status.char_id, tid); + sd->talisman[type] = 0; + return 0; + } - ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == tid); - if (i == sd->talisman[type]) { - ShowError("pc_talisman_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid); - return 0; - } + ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == tid); + if( i == sd->talisman[type] ) + { + ShowError("pc_talisman_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid); + return 0; + } - sd->talisman[type]--; - if (i != sd->talisman[type]) - memmove(sd->talisman_timer[type]+i, sd->talisman_timer[type]+i+1, (sd->talisman[type]-i)*sizeof(int)); - sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER; + sd->talisman[type]--; + if( i != sd->talisman[type] ) + memmove(sd->talisman_timer[type]+i, sd->talisman_timer[type]+i+1, (sd->talisman[type]-i)*sizeof(int)); + sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER; - clif_talisman(sd, type); + clif_talisman(sd, type); - return 0; + return 0; } int pc_add_talisman(struct map_session_data *sd,int interval,int max,int type) { - int tid, i; + int tid, i; - nullpo_ret(sd); + nullpo_ret(sd); - if (max > 10) - max = 10; - if (sd->talisman[type] < 0) - sd->talisman[type] = 0; + if(max > 10) + max = 10; + if(sd->talisman[type] < 0) + sd->talisman[type] = 0; - if (sd->talisman[type] && sd->talisman[type] >= max) { - if (sd->talisman_timer[type][0] != INVALID_TIMER) - delete_timer(sd->talisman_timer[type][0],pc_talisman_timer); - sd->talisman[type]--; - if (sd->talisman[type] != 0) - memmove(sd->talisman_timer[type]+0, sd->talisman_timer[type]+1, (sd->talisman[type])*sizeof(int)); - sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER; - } + if( sd->talisman[type] && sd->talisman[type] >= max ) + { + if(sd->talisman_timer[type][0] != INVALID_TIMER) + delete_timer(sd->talisman_timer[type][0],pc_talisman_timer); + sd->talisman[type]--; + if( sd->talisman[type] != 0 ) + memmove(sd->talisman_timer[type]+0, sd->talisman_timer[type]+1, (sd->talisman[type])*sizeof(int)); + sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER; + } - tid = add_timer(gettick()+interval, pc_talisman_timer, sd->bl.id, 0); - ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->talisman_timer[type][i])->tick) < 0); - if (i != sd->talisman[type]) - memmove(sd->talisman_timer[type]+i+1, sd->talisman_timer[type]+i, (sd->talisman[type]-i)*sizeof(int)); - sd->talisman_timer[type][i] = tid; - sd->talisman[type]++; + tid = add_timer(gettick()+interval, pc_talisman_timer, sd->bl.id, 0); + ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->talisman_timer[type][i])->tick) < 0); + if( i != sd->talisman[type] ) + memmove(sd->talisman_timer[type]+i+1, sd->talisman_timer[type]+i, (sd->talisman[type]-i)*sizeof(int)); + sd->talisman_timer[type][i] = tid; + sd->talisman[type]++; - clif_talisman(sd, type); - return 0; + clif_talisman(sd, type); + return 0; } int pc_del_talisman(struct map_session_data *sd,int count,int type) { - int i; - - nullpo_ret(sd); - - if (sd->talisman[type] <= 0) { - sd->talisman[type] = 0; - return 0; - } - - if (count <= 0) - return 0; - if (count > sd->talisman[type]) - count = sd->talisman[type]; - sd->talisman[type] -= count; - if (count > 10) - count = 10; - - for (i = 0; i < count; i++) { - if (sd->talisman_timer[type][i] != INVALID_TIMER) { - delete_timer(sd->talisman_timer[type][i],pc_talisman_timer); - sd->talisman_timer[type][i] = INVALID_TIMER; - } - } - for (i = count; i < 10; i++) { - sd->talisman_timer[type][i-count] = sd->talisman_timer[type][i]; - sd->talisman_timer[type][i] = INVALID_TIMER; - } - - clif_talisman(sd, type); - return 0; + int i; + + nullpo_ret(sd); + + if( sd->talisman[type] <= 0 ) { + sd->talisman[type] = 0; + return 0; + } + + if( count <= 0 ) + return 0; + if( count > sd->talisman[type] ) + count = sd->talisman[type]; + sd->talisman[type] -= count; + if( count > 10 ) + count = 10; + + for(i = 0; i < count; i++) { + if(sd->talisman_timer[type][i] != INVALID_TIMER) { + delete_timer(sd->talisman_timer[type][i],pc_talisman_timer); + sd->talisman_timer[type][i] = INVALID_TIMER; + } + } + for(i = count; i < 10; i++) { + sd->talisman_timer[type][i-count] = sd->talisman_timer[type][i]; + sd->talisman_timer[type][i] = INVALID_TIMER; + } + + clif_talisman(sd, type); + return 0; } #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) /*========================================== @@ -9281,165 +9169,170 @@ int pc_del_talisman(struct map_session_data *sd,int count,int type) *------------------------------------------*/ int pc_level_penalty_mod(struct map_session_data *sd, struct mob_data *md, int type) { - int diff, rate = 100, i; + int diff, rate = 100, i; - nullpo_ret(sd); - nullpo_ret(md); + nullpo_ret(sd); + nullpo_ret(md); - diff = md->level - sd->status.base_level; + diff = md->level - sd->status.base_level; - if (diff < 0) - diff = MAX_LEVEL + (~diff + 1); + if( diff < 0 ) + diff = MAX_LEVEL + ( ~diff + 1 ); - for (i=0; i<RC_MAX; i++) { - int tmp; + for(i=0; i<RC_MAX; i++){ + int tmp; - if (md->status.race != i) { - if (md->status.mode&MD_BOSS && i < RC_BOSS) - i = RC_BOSS; - else if (i <= RC_BOSS) - continue; - } + if( md->status.race != i ){ + if( md->status.mode&MD_BOSS && i < RC_BOSS ) + i = RC_BOSS; + else if( i <= RC_BOSS ) + continue; + } - if ((tmp=level_penalty[type][i][diff]) > 0) { - rate = tmp; - break; - } - } + if( (tmp=level_penalty[type][i][diff]) > 0 ){ + rate = tmp; + break; + } + } - return rate; + return rate; } #endif int pc_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 && i<num-1) //Do not remove a trailing comma. - *str++=0; - } - return i; -} - -int pc_split_atoi(char *str, int *val, char sep, int max) -{ - int i,j; - for (i=0; i<max; i++) { - if (!str) break; - val[i] = atoi(str); - str = strchr(str,sep); - if (str) - *str++=0; - } - //Zero up the remaining. - for (j=i; j < max; j++) - val[j] = 0; - return i; -} - -int pc_split_atoui(char *str, unsigned int *val, char sep, int max) -{ - static int warning=0; - int i,j; - double f; - for (i=0; i<max; i++) { - if (!str) break; - f = atof(str); - if (f < 0) - val[i] = 0; - else if (f > UINT_MAX) { - val[i] = UINT_MAX; - if (!warning) { - warning = 1; - ShowWarning("pc_readdb (exp.txt): Required exp per level is capped to %u\n", UINT_MAX); - } - } else - val[i] = (unsigned int)f; - str = strchr(str,sep); - if (str) - *str++=0; - } - //Zero up the remaining. - for (j=i; j < max; j++) - val[j] = 0; - return i; + int i; + + for (i=0; i<num && str; i++){ + val[i] = str; + str = strchr(str,','); + if (str && i<num-1) //Do not remove a trailing comma. + *str++=0; + } + return i; +} + +int pc_split_atoi(char* str, int* val, char sep, int max) +{ + int i,j; + for (i=0; i<max; i++) { + if (!str) break; + val[i] = atoi(str); + str = strchr(str,sep); + if (str) + *str++=0; + } + //Zero up the remaining. + for(j=i; j < max; j++) + val[j] = 0; + return i; +} + +int pc_split_atoui(char* str, unsigned int* val, char sep, int max) +{ + static int warning=0; + int i,j; + double f; + for (i=0; i<max; i++) { + if (!str) break; + f = atof(str); + if (f < 0) + val[i] = 0; + else if (f > UINT_MAX) { + val[i] = UINT_MAX; + if (!warning) { + warning = 1; + ShowWarning("pc_readdb (exp.txt): Required exp per level is capped to %u\n", UINT_MAX); + } + } else + val[i] = (unsigned int)f; + str = strchr(str,sep); + if (str) + *str++=0; + } + //Zero up the remaining. + for(j=i; j < max; j++) + val[j] = 0; + return i; } /*========================================== * sub DB reading. * Function used to read skill_tree.txt *------------------------------------------*/ -static bool pc_readdb_skilltree(char *fields[], int columns, int current) -{ - unsigned char joblv = 0, skilllv; - unsigned short skillid; - int idx, class_; - unsigned int i, offset = 3, skillidx; - - class_ = atoi(fields[0]); - skillid = (unsigned short)atoi(fields[1]); - skilllv = (unsigned char)atoi(fields[2]); - - if (columns==4+MAX_PC_SKILL_REQUIRE*2) { - // job level requirement extra column - joblv = (unsigned char)atoi(fields[3]); - offset++; - } - - if (!pcdb_checkid(class_)) { - ShowWarning("pc_readdb_skilltree: Invalid job class %d specified.\n", class_); - return false; - } - idx = pc_class2idx(class_); - - //This is to avoid adding two lines for the same skill. [Skotlex] - ARR_FIND(0, MAX_SKILL_TREE, skillidx, skill_tree[idx][skillidx].id == 0 || skill_tree[idx][skillidx].id == skillid); - if (skillidx == MAX_SKILL_TREE) { - ShowWarning("pc_readdb_skilltree: Unable to load skill %hu into job %d's tree. Maximum number of skills per class has been reached.\n", skillid, class_); - return false; - } else if (skill_tree[idx][skillidx].id) { - ShowNotice("pc_readdb_skilltree: Overwriting skill %hu for job class %d.\n", skillid, class_); - } - - skill_tree[idx][skillidx].id = skillid; - skill_tree[idx][skillidx].max = skilllv; - skill_tree[idx][skillidx].joblv = joblv; - - for (i = 0; i < MAX_PC_SKILL_REQUIRE; i++) { - skill_tree[idx][skillidx].need[i].id = atoi(fields[i*2+offset]); - skill_tree[idx][skillidx].need[i].lv = atoi(fields[i*2+offset+1]); - } - return true; +static bool pc_readdb_skilltree(char* fields[], int columns, int current) +{ + unsigned char joblv = 0, skilllv; + unsigned short skillid; + int idx, class_; + unsigned int i, offset = 3, skillidx; + + class_ = atoi(fields[0]); + skillid = (unsigned short)atoi(fields[1]); + skilllv = (unsigned char)atoi(fields[2]); + + if(columns==4+MAX_PC_SKILL_REQUIRE*2) + {// job level requirement extra column + joblv = (unsigned char)atoi(fields[3]); + offset++; + } + + if(!pcdb_checkid(class_)) + { + ShowWarning("pc_readdb_skilltree: Invalid job class %d specified.\n", class_); + return false; + } + idx = pc_class2idx(class_); + + //This is to avoid adding two lines for the same skill. [Skotlex] + ARR_FIND( 0, MAX_SKILL_TREE, skillidx, skill_tree[idx][skillidx].id == 0 || skill_tree[idx][skillidx].id == skillid ); + if( skillidx == MAX_SKILL_TREE ) + { + ShowWarning("pc_readdb_skilltree: Unable to load skill %hu into job %d's tree. Maximum number of skills per class has been reached.\n", skillid, class_); + return false; + } + else if(skill_tree[idx][skillidx].id) + { + ShowNotice("pc_readdb_skilltree: Overwriting skill %hu for job class %d.\n", skillid, class_); + } + + skill_tree[idx][skillidx].id = skillid; + skill_tree[idx][skillidx].max = skilllv; + skill_tree[idx][skillidx].joblv = joblv; + + for(i = 0; i < MAX_PC_SKILL_REQUIRE; i++) + { + skill_tree[idx][skillidx].need[i].id = atoi(fields[i*2+offset]); + skill_tree[idx][skillidx].need[i].lv = atoi(fields[i*2+offset+1]); + } + return true; } #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) -static bool pc_readdb_levelpenalty(char *fields[], int columns, int current) +static bool pc_readdb_levelpenalty(char* fields[], int columns, int current) { - int type, race, diff; + int type, race, diff; - type = atoi(fields[0]); - race = atoi(fields[1]); - diff = atoi(fields[2]); + type = atoi(fields[0]); + race = atoi(fields[1]); + diff = atoi(fields[2]); - if (type != 1 && type != 2) { - ShowWarning("pc_readdb_levelpenalty: Invalid type %d specified.\n", type); - return false; - } + if( type != 1 && type != 2 ){ + ShowWarning("pc_readdb_levelpenalty: Invalid type %d specified.\n", type); + return false; + } - if (race < 0 && race > RC_MAX) { - ShowWarning("pc_readdb_levelpenalty: Invalid race %d specified.\n", race); - return false; - } + if( race < 0 && race > RC_MAX ){ + ShowWarning("pc_readdb_levelpenalty: Invalid race %d specified.\n", race); + return false; + } - diff = min(diff, MAX_LEVEL); + diff = min(diff, MAX_LEVEL); - if (diff < 0) - diff = min(MAX_LEVEL + (~(diff) + 1), MAX_LEVEL*2); + if( diff < 0 ) + diff = min(MAX_LEVEL + ( ~(diff) + 1 ), MAX_LEVEL*2); - level_penalty[type][race][diff] = atoi(fields[3]); + level_penalty[type][race][diff] = atoi(fields[3]); - return true; + return true; } #endif @@ -9451,336 +9344,343 @@ static bool pc_readdb_levelpenalty(char *fields[], int columns, int current) *------------------------------------------*/ int pc_readdb(void) { - int i,j,k,tmp=0; - FILE *fp; - char line[24000],*p; + int i,j,k,tmp=0; + FILE *fp; + char line[24000],*p; //reset - memset(exp_table,0,sizeof(exp_table)); - memset(max_level,0,sizeof(max_level)); - - sprintf(line, "%s/"DBPATH"exp.txt", db_path); - - fp=fopen(line, "r"); - if (fp==NULL) { - ShowError("can't read %s\n", line); - return 1; - } - while (fgets(line, sizeof(line), fp)) { - int jobs[CLASS_COUNT], job_count, job, job_id; - int type; - unsigned int ui,maxlv; - char *split[4]; - if (line[0]=='/' && line[1]=='/') - continue; - if (pc_split_str(line,split,4) < 4) - continue; - - job_count = pc_split_atoi(split[1],jobs,':',CLASS_COUNT); - if (job_count < 1) - continue; - job_id = jobs[0]; - if (!pcdb_checkid(job_id)) { - ShowError("pc_readdb: Invalid job ID %d.\n", job_id); - continue; - } - type = atoi(split[2]); - if (type < 0 || type > 1) { - ShowError("pc_readdb: Invalid type %d (must be 0 for base levels, 1 for job levels).\n", type); - continue; - } - maxlv = atoi(split[0]); - if (maxlv > MAX_LEVEL) { - ShowWarning("pc_readdb: Specified max level %u for job %d is beyond server's limit (%u).\n ", maxlv, job_id, MAX_LEVEL); - maxlv = MAX_LEVEL; - } - - job = jobs[0] = pc_class2idx(job_id); - //We send one less and then one more because the last entry in the exp array should hold 0. - max_level[job][type] = pc_split_atoui(split[3], exp_table[job][type],',',maxlv-1)+1; - //Reverse check in case the array has a bunch of trailing zeros... [Skotlex] - //The reasoning behind the -2 is this... if the max level is 5, then the array - //should look like this: - //0: x, 1: x, 2: x: 3: x 4: 0 <- last valid value is at 3. - while ((ui = max_level[job][type]) >= 2 && exp_table[job][type][ui-2] <= 0) - max_level[job][type]--; - if (max_level[job][type] < maxlv) { - ShowWarning("pc_readdb: Specified max %u for job %d, but that job's exp table only goes up to level %u.\n", maxlv, job_id, max_level[job][type]); - ShowInfo("Filling the missing values with the last exp entry.\n"); - //Fill the requested values with the last entry. - ui = (max_level[job][type] <= 2? 0: max_level[job][type]-2); - for (; ui+2 < maxlv; ui++) - exp_table[job][type][ui] = exp_table[job][type][ui-1]; - max_level[job][type] = maxlv; - } - // ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job_id, max_level[job][type]); - for (i = 1; i < job_count; i++) { - job_id = jobs[i]; - if (!pcdb_checkid(job_id)) { - ShowError("pc_readdb: Invalid job ID %d.\n", job_id); - continue; - } - job = pc_class2idx(job_id); - memcpy(exp_table[job][type], exp_table[jobs[0]][type], sizeof(exp_table[0][0])); - max_level[job][type] = maxlv; - // ShowDebug("%s - Class %d: %u\n", type?"Job":"Base", job_id, max_level[job][type]); - } - } - fclose(fp); - for (i = 0; i < JOB_MAX; i++) { - if (!pcdb_checkid(i)) continue; - if (i == JOB_WEDDING || i == JOB_XMAS || i == JOB_SUMMER) - continue; //Classes that do not need exp tables. - j = pc_class2idx(i); - if (!max_level[j][0]) - ShowWarning("Class %s (%d) does not has a base exp table.\n", job_name(i), i); - if (!max_level[j][1]) - ShowWarning("Class %s (%d) does not has a job exp table.\n", job_name(i), i); - } - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","exp.txt"); - - // Reset and read skilltree - memset(skill_tree,0,sizeof(skill_tree)); - sv_readdb(db_path, DBPATH"skill_tree.txt", ',', 3+MAX_PC_SKILL_REQUIRE*2, 4+MAX_PC_SKILL_REQUIRE*2, -1, &pc_readdb_skilltree); + memset(exp_table,0,sizeof(exp_table)); + memset(max_level,0,sizeof(max_level)); + + sprintf(line, "%s/"DBPATH"exp.txt", db_path); + + fp=fopen(line, "r"); + if(fp==NULL){ + ShowError("can't read %s\n", line); + return 1; + } + while(fgets(line, sizeof(line), fp)) + { + int jobs[CLASS_COUNT], job_count, job, job_id; + int type; + unsigned int ui,maxlv; + char *split[4]; + if(line[0]=='/' && line[1]=='/') + continue; + if (pc_split_str(line,split,4) < 4) + continue; + + job_count = pc_split_atoi(split[1],jobs,':',CLASS_COUNT); + if (job_count < 1) + continue; + job_id = jobs[0]; + if (!pcdb_checkid(job_id)) { + ShowError("pc_readdb: Invalid job ID %d.\n", job_id); + continue; + } + type = atoi(split[2]); + if (type < 0 || type > 1) { + ShowError("pc_readdb: Invalid type %d (must be 0 for base levels, 1 for job levels).\n", type); + continue; + } + maxlv = atoi(split[0]); + if (maxlv > MAX_LEVEL) { + ShowWarning("pc_readdb: Specified max level %u for job %d is beyond server's limit (%u).\n ", maxlv, job_id, MAX_LEVEL); + maxlv = MAX_LEVEL; + } + + job = jobs[0] = pc_class2idx(job_id); + //We send one less and then one more because the last entry in the exp array should hold 0. + max_level[job][type] = pc_split_atoui(split[3], exp_table[job][type],',',maxlv-1)+1; + //Reverse check in case the array has a bunch of trailing zeros... [Skotlex] + //The reasoning behind the -2 is this... if the max level is 5, then the array + //should look like this: + //0: x, 1: x, 2: x: 3: x 4: 0 <- last valid value is at 3. + while ((ui = max_level[job][type]) >= 2 && exp_table[job][type][ui-2] <= 0) + max_level[job][type]--; + if (max_level[job][type] < maxlv) { + ShowWarning("pc_readdb: Specified max %u for job %d, but that job's exp table only goes up to level %u.\n", maxlv, job_id, max_level[job][type]); + ShowInfo("Filling the missing values with the last exp entry.\n"); + //Fill the requested values with the last entry. + ui = (max_level[job][type] <= 2? 0: max_level[job][type]-2); + for (; ui+2 < maxlv; ui++) + exp_table[job][type][ui] = exp_table[job][type][ui-1]; + max_level[job][type] = maxlv; + } +// ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job_id, max_level[job][type]); + for (i = 1; i < job_count; i++) { + job_id = jobs[i]; + if (!pcdb_checkid(job_id)) { + ShowError("pc_readdb: Invalid job ID %d.\n", job_id); + continue; + } + job = pc_class2idx(job_id); + memcpy(exp_table[job][type], exp_table[jobs[0]][type], sizeof(exp_table[0][0])); + max_level[job][type] = maxlv; +// ShowDebug("%s - Class %d: %u\n", type?"Job":"Base", job_id, max_level[job][type]); + } + } + fclose(fp); + for (i = 0; i < JOB_MAX; i++) { + if (!pcdb_checkid(i)) continue; + if (i == JOB_WEDDING || i == JOB_XMAS || i == JOB_SUMMER) + continue; //Classes that do not need exp tables. + j = pc_class2idx(i); + if (!max_level[j][0]) + ShowWarning("Class %s (%d) does not has a base exp table.\n", job_name(i), i); + if (!max_level[j][1]) + ShowWarning("Class %s (%d) does not has a job exp table.\n", job_name(i), i); + } + ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","exp.txt"); + + // Reset and read skilltree + memset(skill_tree,0,sizeof(skill_tree)); + sv_readdb(db_path, DBPATH"skill_tree.txt", ',', 3+MAX_PC_SKILL_REQUIRE*2, 4+MAX_PC_SKILL_REQUIRE*2, -1, &pc_readdb_skilltree); #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) - sv_readdb(db_path, "re/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty); - for (k=1; k < 3; k++) { // fill in the blanks - for (j = 0; j < RC_MAX; j++) { - tmp = 0; - for (i = 0; i < MAX_LEVEL*2; i++) { - if (i == MAX_LEVEL+1) - tmp = level_penalty[k][j][0];// reset - if (level_penalty[k][j][i] > 0) - tmp = level_penalty[k][j][i]; - else - level_penalty[k][j][i] = tmp; - } - } - } + sv_readdb(db_path, "re/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty); + for( k=1; k < 3; k++ ){ // fill in the blanks + for( j = 0; j < RC_MAX; j++ ){ + tmp = 0; + for( i = 0; i < MAX_LEVEL*2; i++ ){ + if( i == MAX_LEVEL+1 ) + tmp = level_penalty[k][j][0];// reset + if( level_penalty[k][j][i] > 0 ) + tmp = level_penalty[k][j][i]; + else + level_penalty[k][j][i] = tmp; + } + } + } #endif - // Reset then read attr_fix - for (i=0; i<4; i++) - for (j=0; j<ELE_MAX; j++) - for (k=0; k<ELE_MAX; k++) - attr_fix_table[i][j][k]=100; - - sprintf(line, "%s/"DBPATH"attr_fix.txt", db_path); - - fp=fopen(line,"r"); - if (fp==NULL) { - ShowError("can't read %s\n", line); - return 1; - } - while (fgets(line, sizeof(line), fp)) { - char *split[10]; - int lv,n; - if (line[0]=='/' && line[1]=='/') - continue; - for (j=0,p=line; j<3 && p; j++) { - split[j]=p; - p=strchr(p,','); - if (p) *p++=0; - } - if (j < 2) - continue; - - lv=atoi(split[0]); - n=atoi(split[1]); - - for (i=0; i<n && i<ELE_MAX;) { - if (!fgets(line, sizeof(line), fp)) - break; - if (line[0]=='/' && line[1]=='/') - continue; - - for (j=0,p=line; j<n && j<ELE_MAX && p; j++) { - while (*p==32 && *p>0) - p++; - attr_fix_table[lv-1][i][j]=atoi(p); - if (battle_config.attr_recover == 0 && attr_fix_table[lv-1][i][j] < 0) - attr_fix_table[lv-1][i][j] = 0; - p=strchr(p,','); - if (p) *p++=0; - } - - i++; - } - } - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","attr_fix.txt"); + // Reset then read attr_fix + for(i=0;i<4;i++) + for(j=0;j<ELE_MAX;j++) + for(k=0;k<ELE_MAX;k++) + attr_fix_table[i][j][k]=100; + + sprintf(line, "%s/"DBPATH"attr_fix.txt", db_path); + + fp=fopen(line,"r"); + if(fp==NULL){ + ShowError("can't read %s\n", line); + return 1; + } + while(fgets(line, sizeof(line), fp)) + { + char *split[10]; + int lv,n; + if(line[0]=='/' && line[1]=='/') + continue; + for(j=0,p=line;j<3 && p;j++){ + split[j]=p; + p=strchr(p,','); + if(p) *p++=0; + } + if( j < 2 ) + continue; + + lv=atoi(split[0]); + n=atoi(split[1]); + + for(i=0;i<n && i<ELE_MAX;){ + if( !fgets(line, sizeof(line), fp) ) + break; + if(line[0]=='/' && line[1]=='/') + continue; + + for(j=0,p=line;j<n && j<ELE_MAX && p;j++){ + while(*p==32 && *p>0) + p++; + attr_fix_table[lv-1][i][j]=atoi(p); + if(battle_config.attr_recover == 0 && attr_fix_table[lv-1][i][j] < 0) + attr_fix_table[lv-1][i][j] = 0; + p=strchr(p,','); + if(p) *p++=0; + } + + i++; + } + } + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","attr_fix.txt"); // reset then read statspoint - memset(statp,0,sizeof(statp)); - i=1; - - sprintf(line, "%s/"DBPATH"statpoint.txt", db_path); - fp=fopen(line,"r"); - if (fp == NULL) { - ShowWarning("Can't read '"CL_WHITE"%s"CL_RESET"'... Generating DB.\n",line); - //return 1; - } else { - while (fgets(line, sizeof(line), fp)) { - int stat; - if (line[0]=='/' && line[1]=='/') - continue; - if ((stat=strtoul(line,NULL,10))<0) - stat=0; - if (i > MAX_LEVEL) - break; - statp[i]=stat; - i++; - } - fclose(fp); - - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","statpoint.txt"); - } - // generate the remaining parts of the db if necessary - k = battle_config.use_statpoint_table; //save setting - battle_config.use_statpoint_table = 0; //temporarily disable to force pc_gets_status_point use default values - statp[0] = 45; // seed value - for (; i <= MAX_LEVEL; i++) - statp[i] = statp[i-1] + pc_gets_status_point(i-1); - battle_config.use_statpoint_table = k; //restore setting - - return 0; + memset(statp,0,sizeof(statp)); + i=1; + + sprintf(line, "%s/"DBPATH"statpoint.txt", db_path); + fp=fopen(line,"r"); + if(fp == NULL){ + ShowWarning("Can't read '"CL_WHITE"%s"CL_RESET"'... Generating DB.\n",line); + //return 1; + } else { + while(fgets(line, sizeof(line), fp)) + { + int stat; + if(line[0]=='/' && line[1]=='/') + continue; + if ((stat=strtoul(line,NULL,10))<0) + stat=0; + if (i > MAX_LEVEL) + break; + statp[i]=stat; + i++; + } + fclose(fp); + + ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","statpoint.txt"); + } + // generate the remaining parts of the db if necessary + k = battle_config.use_statpoint_table; //save setting + battle_config.use_statpoint_table = 0; //temporarily disable to force pc_gets_status_point use default values + statp[0] = 45; // seed value + for (; i <= MAX_LEVEL; i++) + statp[i] = statp[i-1] + pc_gets_status_point(i-1); + battle_config.use_statpoint_table = k; //restore setting + + return 0; } // Read MOTD on startup. [Valaris] int pc_read_motd(void) { - FILE *fp; - - // clear old MOTD - memset(motd_text, 0, sizeof(motd_text)); - - // read current MOTD - if ((fp = fopen(motd_txt, "r")) != NULL) { - char *buf, * ptr; - unsigned int lines = 0, entries = 0; - size_t len; - - while (entries < MOTD_LINE_SIZE && fgets(motd_text[entries], sizeof(motd_text[entries]), fp)) { - lines++; - - buf = motd_text[entries]; - - if (buf[0] == '/' && buf[1] == '/') { - continue; - } - - len = strlen(buf); - - while (len && (buf[len-1] == '\r' || buf[len-1] == '\n')) { - // strip trailing EOL characters - len--; - } - - if (len) { - buf[len] = 0; - - if ((ptr = strstr(buf, " :")) != NULL && ptr-buf >= NAME_LENGTH) { - // crashes newer clients - ShowWarning("Found sequence '"CL_WHITE" :"CL_RESET"' on line '"CL_WHITE"%u"CL_RESET"' in '"CL_WHITE"%s"CL_RESET"'. This can cause newer clients to crash.\n", lines, motd_txt); - } - } else { - // empty line - buf[0] = ' '; - buf[1] = 0; - } - entries++; - } - fclose(fp); - - ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, motd_txt); - } else { - ShowWarning("File '"CL_WHITE"%s"CL_RESET"' not found.\n", motd_txt); - } - - return 0; -} -void pc_itemcd_do(struct map_session_data *sd, bool load) -{ - int i,cursor = 0; - struct item_cd *cd = NULL; - - if (load) { - if (!(cd = idb_get(itemcd_db, sd->status.char_id))) { - // no skill cooldown is associated with this character - return; - } - for (i = 0; i < MAX_ITEMDELAYS; i++) { - if (cd->nameid[i] && DIFF_TICK(gettick(),cd->tick[i]) < 0) { - sd->item_delay[cursor].tick = cd->tick[i]; - sd->item_delay[cursor].nameid = cd->nameid[i]; - cursor++; - } - } - idb_remove(itemcd_db,sd->status.char_id); - } else { - if (!(cd = idb_get(itemcd_db,sd->status.char_id))) { - // create a new skill cooldown object for map storage - CREATE(cd, struct item_cd, 1); - idb_put(itemcd_db, sd->status.char_id, cd); - } - for (i = 0; i < MAX_ITEMDELAYS; i++) { - if (sd->item_delay[i].nameid && DIFF_TICK(gettick(),sd->item_delay[i].tick) < 0) { - cd->tick[cursor] = sd->item_delay[i].tick; - cd->nameid[cursor] = sd->item_delay[i].nameid; - cursor++; - } - } - } - return; + FILE* fp; + + // clear old MOTD + memset(motd_text, 0, sizeof(motd_text)); + + // read current MOTD + if( ( fp = fopen(motd_txt, "r") ) != NULL ) + { + char* buf, * ptr; + unsigned int lines = 0, entries = 0; + size_t len; + + while( entries < MOTD_LINE_SIZE && fgets(motd_text[entries], sizeof(motd_text[entries]), fp) ) + { + lines++; + + buf = motd_text[entries]; + + if( buf[0] == '/' && buf[1] == '/' ) + { + continue; + } + + len = strlen(buf); + + while( len && ( buf[len-1] == '\r' || buf[len-1] == '\n' ) ) + {// strip trailing EOL characters + len--; + } + + if( len ) + { + buf[len] = 0; + + if( ( ptr = strstr(buf, " :") ) != NULL && ptr-buf >= NAME_LENGTH ) + {// crashes newer clients + ShowWarning("Found sequence '"CL_WHITE" :"CL_RESET"' on line '"CL_WHITE"%u"CL_RESET"' in '"CL_WHITE"%s"CL_RESET"'. This can cause newer clients to crash.\n", lines, motd_txt); + } + } + else + {// empty line + buf[0] = ' '; + buf[1] = 0; + } + entries++; + } + fclose(fp); + + ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", entries, motd_txt); + } + else + { + ShowWarning("File '"CL_WHITE"%s"CL_RESET"' not found.\n", motd_txt); + } + + return 0; +} +void pc_itemcd_do(struct map_session_data *sd, bool load) { + int i,cursor = 0; + struct item_cd* cd = NULL; + + if( load ) { + if( !(cd = idb_get(itemcd_db, sd->status.char_id)) ) { + // no skill cooldown is associated with this character + return; + } + for(i = 0; i < MAX_ITEMDELAYS; i++) { + if( cd->nameid[i] && DIFF_TICK(gettick(),cd->tick[i]) < 0 ) { + sd->item_delay[cursor].tick = cd->tick[i]; + sd->item_delay[cursor].nameid = cd->nameid[i]; + cursor++; + } + } + idb_remove(itemcd_db,sd->status.char_id); + } else { + if( !(cd = idb_get(itemcd_db,sd->status.char_id)) ) { + // create a new skill cooldown object for map storage + CREATE( cd, struct item_cd, 1 ); + idb_put( itemcd_db, sd->status.char_id, cd ); + } + for(i = 0; i < MAX_ITEMDELAYS; i++) { + if( sd->item_delay[i].nameid && DIFF_TICK(gettick(),sd->item_delay[i].tick) < 0 ) { + cd->tick[cursor] = sd->item_delay[i].tick; + cd->nameid[cursor] = sd->item_delay[i].nameid; + cursor++; + } + } + } + return; } /*========================================== * pc Init/Terminate *------------------------------------------*/ -void do_final_pc(void) -{ +void do_final_pc(void) { - db_destroy(itemcd_db); + db_destroy(itemcd_db); - do_final_pc_groups(); - return; + do_final_pc_groups(); + return; } -int do_init_pc(void) -{ +int do_init_pc(void) { - itemcd_db = idb_alloc(DB_OPT_RELEASE_DATA); + itemcd_db = idb_alloc(DB_OPT_RELEASE_DATA); - pc_readdb(); - pc_read_motd(); // Read MOTD [Valaris] + pc_readdb(); + pc_read_motd(); // Read MOTD [Valaris] - add_timer_func_list(pc_invincible_timer, "pc_invincible_timer"); - add_timer_func_list(pc_eventtimer, "pc_eventtimer"); - add_timer_func_list(pc_inventory_rental_end, "pc_inventory_rental_end"); - add_timer_func_list(pc_calc_pvprank_timer, "pc_calc_pvprank_timer"); - add_timer_func_list(pc_autosave, "pc_autosave"); - add_timer_func_list(pc_spiritball_timer, "pc_spiritball_timer"); - add_timer_func_list(pc_follow_timer, "pc_follow_timer"); - add_timer_func_list(pc_endautobonus, "pc_endautobonus"); - add_timer_func_list(pc_talisman_timer, "pc_talisman_timer"); + add_timer_func_list(pc_invincible_timer, "pc_invincible_timer"); + add_timer_func_list(pc_eventtimer, "pc_eventtimer"); + add_timer_func_list(pc_inventory_rental_end, "pc_inventory_rental_end"); + add_timer_func_list(pc_calc_pvprank_timer, "pc_calc_pvprank_timer"); + add_timer_func_list(pc_autosave, "pc_autosave"); + add_timer_func_list(pc_spiritball_timer, "pc_spiritball_timer"); + add_timer_func_list(pc_follow_timer, "pc_follow_timer"); + add_timer_func_list(pc_endautobonus, "pc_endautobonus"); + add_timer_func_list(pc_talisman_timer, "pc_talisman_timer"); - add_timer(gettick() + autosave_interval, pc_autosave, 0, 0); + add_timer(gettick() + autosave_interval, pc_autosave, 0, 0); - // 0=day, 1=night [Yor] - night_flag = battle_config.night_at_start ? 1 : 0; + // 0=day, 1=night [Yor] + night_flag = battle_config.night_at_start ? 1 : 0; - 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; - // add night/day timer [Yor] - add_timer_func_list(map_day_timer, "map_day_timer"); - add_timer_func_list(map_night_timer, "map_night_timer"); + 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; + // add night/day timer [Yor] + add_timer_func_list(map_day_timer, "map_day_timer"); + add_timer_func_list(map_night_timer, "map_night_timer"); - day_timer_tid = add_timer_interval(gettick() + (night_flag ? 0 : day_duration) + night_duration, map_day_timer, 0, 0, day_duration + night_duration); - night_timer_tid = add_timer_interval(gettick() + day_duration + (night_flag ? night_duration : 0), map_night_timer, 0, 0, day_duration + night_duration); - } + day_timer_tid = add_timer_interval(gettick() + (night_flag ? 0 : day_duration) + night_duration, map_day_timer, 0, 0, day_duration + night_duration); + night_timer_tid = add_timer_interval(gettick() + day_duration + (night_flag ? night_duration : 0), map_night_timer, 0, 0, day_duration + night_duration); + } - do_init_pc_groups(); + do_init_pc_groups(); - return 0; + return 0; } diff --git a/src/map/pc.h b/src/map/pc.h index 971fce1d2..bc8a76f2a 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -25,456 +25,456 @@ #define MAX_PC_FEELHATE 3 struct weapon_data { - int atkmods[3]; - // all the variables except atkmods get zero'ed in each call of status_calc_pc - // NOTE: if you want to add a non-zeroed variable, you need to update the memset call - // in status_calc_pc as well! All the following are automatically zero'ed. [Skotlex] - int overrefine; - int star; - int ignore_def_ele; - int ignore_def_race; - int def_ratio_atk_ele; - int def_ratio_atk_race; - int addele[ELE_MAX]; - int addrace[RC_MAX]; - int addrace2[RC2_MAX]; - int addsize[3]; - - struct drain_data { - short rate; - short per; - short value; - unsigned type:1; - } hp_drain[RC_MAX], sp_drain[RC_MAX]; - - struct { - short class_, rate; - } add_dmg[MAX_PC_BONUS]; - - struct { - short flag, rate; - unsigned char ele; - } addele2[MAX_PC_BONUS]; + int atkmods[3]; + // all the variables except atkmods get zero'ed in each call of status_calc_pc + // NOTE: if you want to add a non-zeroed variable, you need to update the memset call + // in status_calc_pc as well! All the following are automatically zero'ed. [Skotlex] + int overrefine; + int star; + int ignore_def_ele; + int ignore_def_race; + int def_ratio_atk_ele; + int def_ratio_atk_race; + int addele[ELE_MAX]; + int addrace[RC_MAX]; + int addrace2[RC2_MAX]; + int addsize[3]; + + struct drain_data { + short rate; + short per; + short value; + unsigned type:1; + } hp_drain[RC_MAX], sp_drain[RC_MAX]; + + struct { + short class_, rate; + } add_dmg[MAX_PC_BONUS]; + + struct { + short flag, rate; + unsigned char ele; + } addele2[MAX_PC_BONUS]; }; struct s_autospell { - short id, lv, rate, card_id, flag; - bool lock; // bAutoSpellOnSkill: blocks autospell from triggering again, while being executed + short id, lv, rate, card_id, flag; + bool lock; // bAutoSpellOnSkill: blocks autospell from triggering again, while being executed }; struct s_addeffect { - enum sc_type id; - short rate, arrow_rate; - unsigned char flag; + enum sc_type id; + short rate, arrow_rate; + unsigned char flag; }; struct s_addeffectonskill { - enum sc_type id; - short rate, skill; - unsigned char target; + enum sc_type id; + short rate, skill; + unsigned char target; }; struct s_add_drop { - short id, group; - int race, rate; + short id, group; + int race, rate; }; struct s_autobonus { - short rate,atk_type; - unsigned int duration; - char *bonus_script, *other_script; - int active; - unsigned short pos; + short rate,atk_type; + unsigned int duration; + char *bonus_script, *other_script; + int active; + unsigned short pos; }; struct map_session_data { - struct block_list bl; - struct unit_data ud; - struct view_data vd; - struct status_data base_status, battle_status; - struct status_change sc; - struct regen_data regen; - struct regen_data_sub sregen, ssregen; - //NOTE: When deciding to add a flag to state or special_state, take into consideration that state is preserved in - //status_calc_pc, while special_state is recalculated in each call. [Skotlex] - struct { - unsigned int active : 1; //Marks active player (not active is logging in/out, or changing map servers) - unsigned int menu_or_input : 1;// if a script is waiting for feedback from the player - unsigned int dead_sit : 2; - unsigned int lr_flag : 3;//1: left h. weapon; 2: arrow; 3: shield - unsigned int connect_new : 1; - unsigned int arrow_atk : 1; - unsigned int gangsterparadise : 1; - unsigned int rest : 1; - unsigned int storage_flag : 2; //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex] - unsigned int snovice_dead_flag : 1; //Explosion spirits on death: 0 off, 1 used. - unsigned int abra_flag : 2; // Abracadabra bugfix by Aru - unsigned int autocast : 1; // Autospell flag [Inkfish] - unsigned int autotrade : 1; //By Fantik - unsigned int reg_dirty : 4; //By Skotlex (marks whether registry variables have been saved or not yet) - unsigned int showdelay :1; - unsigned int showexp :1; - unsigned int showzeny :1; - unsigned int mainchat :1; //[LuzZza] - unsigned int noask :1; // [LuzZza] - unsigned int trading :1; //[Skotlex] is 1 only after a trade has started. - unsigned int deal_locked :2; //1: Clicked on OK. 2: Clicked on TRADE - unsigned int monster_ignore :1; // for monsters to ignore a character [Valaris] [zzo] - unsigned int size :2; // for tiny/large types - unsigned int night :1; //Holds whether or not the player currently has the SI_NIGHT effect on. [Skotlex] - unsigned int blockedmove :1; - unsigned int using_fake_npc :1; - unsigned int rewarp :1; //Signals that a player should warp as soon as he is done loading a map. [Skotlex] - unsigned int killer : 1; - unsigned int killable : 1; - unsigned int doridori : 1; - unsigned int ignoreAll : 1; - unsigned int debug_remove_map : 1; // temporary state to track double remove_map's [FlavioJS] - unsigned int buyingstore : 1; - unsigned int lesseffect : 1; - unsigned int vending : 1; - unsigned int noks : 3; // [Zeph Kill Steal Protection] - unsigned int changemap : 1; - unsigned int callshop : 1; // flag to indicate that a script used callshop; on a shop - short pmap; // Previous map on Map Change - unsigned short autoloot; - unsigned short autolootid[AUTOLOOTITEM_SIZE]; // [Zephyrus] - unsigned int autolooting : 1; //performance-saver, autolooting state for @alootid - unsigned short autobonus; //flag to indicate if an autobonus is activated. [Inkfish] - struct guild *gmaster_flag; - unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not. - unsigned int warping : 1;//states whether you're in the middle of a warp processing - } state; - struct { - unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; - unsigned int restart_full_recover : 1; - unsigned int no_castcancel : 1; - unsigned int no_castcancel2 : 1; - unsigned int no_sizefix : 1; - unsigned int no_gemstone : 1; - unsigned int intravision : 1; // Maya Purple Card effect [DracoRPG] - unsigned int perfect_hiding : 1; // [Valaris] - unsigned int no_knockback : 1; - unsigned int bonus_coma : 1; - } special_state; - int login_id1, login_id2; - unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex] - int group_id, group_pos, group_level; - unsigned int permissions;/* group permissions */ - - int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18 - struct mmo_charstatus status; - struct registry save_reg; - - struct item_data *inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups) - short equip_index[14]; - unsigned int weight,max_weight; - int cart_weight,cart_num,cart_weight_max; - int fd; - unsigned short mapindex; - unsigned char head_dir; //0: Look forward. 1: Look right, 2: Look left. - unsigned int client_tick; - int npc_id,areanpc_id,npc_shopid,touching_id; //for script follow scriptoid; ,npcid - int npc_item_flag; //Marks the npc_id with which you can use items during interactions with said npc (see script command enable_itemuse) - int npc_menu; // internal variable, used in npc menu handling - int npc_amount; - struct script_state *st; - char npc_str[CHATBOX_SIZE]; // for passing npc input box text to script engine - int npc_timer_id; //For player attached npc timers. [Skotlex] - unsigned int chatID; - time_t idletime; - - struct { - int npc_id; - unsigned int timeout; - } progressbar; //Progress Bar [Inkfish] - - struct { - char name[NAME_LENGTH]; - } ignore[MAX_IGNORE_LIST]; - - int followtimer; // [MouseJstr] - int followtarget; - - time_t emotionlasttime; // to limit flood with emotion packets - - short skillitem,skillitemlv; - short skillid_old,skilllv_old; - short skillid_dance,skilllv_dance; - short cook_mastery; // range: [0,1999] [Inkfish] - unsigned char blockskill[MAX_SKILL]; - int cloneskill_id, reproduceskill_id; - int menuskill_id, menuskill_val, menuskill_val2; - - int invincible_timer; - unsigned int canlog_tick; - unsigned int canuseitem_tick; // [Skotlex] - unsigned int canusecashfood_tick; - unsigned int canequip_tick; // [Inkfish] - unsigned int cantalk_tick; - unsigned int canskill_tick; // used to prevent abuse from no-delay ACT files - unsigned int cansendmail_tick; // [Mail System Flood Protection] - unsigned int ks_floodprotect_tick; // [Kill Steal Protection] + struct block_list bl; + struct unit_data ud; + struct view_data vd; + struct status_data base_status, battle_status; + struct status_change sc; + struct regen_data regen; + struct regen_data_sub sregen, ssregen; + //NOTE: When deciding to add a flag to state or special_state, take into consideration that state is preserved in + //status_calc_pc, while special_state is recalculated in each call. [Skotlex] + struct { + unsigned int active : 1; //Marks active player (not active is logging in/out, or changing map servers) + unsigned int menu_or_input : 1;// if a script is waiting for feedback from the player + unsigned int dead_sit : 2; + unsigned int lr_flag : 3;//1: left h. weapon; 2: arrow; 3: shield + unsigned int connect_new : 1; + unsigned int arrow_atk : 1; + unsigned int gangsterparadise : 1; + unsigned int rest : 1; + unsigned int storage_flag : 2; //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex] + unsigned int snovice_dead_flag : 1; //Explosion spirits on death: 0 off, 1 used. + unsigned int abra_flag : 2; // Abracadabra bugfix by Aru + unsigned int autocast : 1; // Autospell flag [Inkfish] + unsigned int autotrade : 1; //By Fantik + unsigned int reg_dirty : 4; //By Skotlex (marks whether registry variables have been saved or not yet) + unsigned int showdelay :1; + unsigned int showexp :1; + unsigned int showzeny :1; + unsigned int mainchat :1; //[LuzZza] + unsigned int noask :1; // [LuzZza] + unsigned int trading :1; //[Skotlex] is 1 only after a trade has started. + unsigned int deal_locked :2; //1: Clicked on OK. 2: Clicked on TRADE + unsigned int monster_ignore :1; // for monsters to ignore a character [Valaris] [zzo] + unsigned int size :2; // for tiny/large types + unsigned int night :1; //Holds whether or not the player currently has the SI_NIGHT effect on. [Skotlex] + unsigned int blockedmove :1; + unsigned int using_fake_npc :1; + unsigned int rewarp :1; //Signals that a player should warp as soon as he is done loading a map. [Skotlex] + unsigned int killer : 1; + unsigned int killable : 1; + unsigned int doridori : 1; + unsigned int ignoreAll : 1; + unsigned int debug_remove_map : 1; // temporary state to track double remove_map's [FlavioJS] + unsigned int buyingstore : 1; + unsigned int lesseffect : 1; + unsigned int vending : 1; + unsigned int noks : 3; // [Zeph Kill Steal Protection] + unsigned int changemap : 1; + unsigned int callshop : 1; // flag to indicate that a script used callshop; on a shop + short pmap; // Previous map on Map Change + unsigned short autoloot; + unsigned short autolootid[AUTOLOOTITEM_SIZE]; // [Zephyrus] + unsigned int autolooting : 1; //performance-saver, autolooting state for @alootid + unsigned short autobonus; //flag to indicate if an autobonus is activated. [Inkfish] + struct guild *gmaster_flag; + unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not. + unsigned int warping : 1;//states whether you're in the middle of a warp processing + } state; + struct { + unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; + unsigned int restart_full_recover : 1; + unsigned int no_castcancel : 1; + unsigned int no_castcancel2 : 1; + unsigned int no_sizefix : 1; + unsigned int no_gemstone : 1; + unsigned int intravision : 1; // Maya Purple Card effect [DracoRPG] + unsigned int perfect_hiding : 1; // [Valaris] + unsigned int no_knockback : 1; + unsigned int bonus_coma : 1; + } special_state; + int login_id1, login_id2; + unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex] + int group_id, group_pos, group_level; + unsigned int permissions;/* group permissions */ + + int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18 + struct mmo_charstatus status; + struct registry save_reg; + + struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups) + short equip_index[14]; + unsigned int weight,max_weight; + int cart_weight,cart_num,cart_weight_max; + int fd; + unsigned short mapindex; + unsigned char head_dir; //0: Look forward. 1: Look right, 2: Look left. + unsigned int client_tick; + int npc_id,areanpc_id,npc_shopid,touching_id; //for script follow scriptoid; ,npcid + int npc_item_flag; //Marks the npc_id with which you can use items during interactions with said npc (see script command enable_itemuse) + int npc_menu; // internal variable, used in npc menu handling + int npc_amount; + struct script_state *st; + char npc_str[CHATBOX_SIZE]; // for passing npc input box text to script engine + int npc_timer_id; //For player attached npc timers. [Skotlex] + unsigned int chatID; + time_t idletime; + + struct{ + int npc_id; + unsigned int timeout; + } progressbar; //Progress Bar [Inkfish] + + struct{ + char name[NAME_LENGTH]; + } ignore[MAX_IGNORE_LIST]; + + int followtimer; // [MouseJstr] + int followtarget; + + time_t emotionlasttime; // to limit flood with emotion packets + + short skillitem,skillitemlv; + short skillid_old,skilllv_old; + short skillid_dance,skilllv_dance; + short cook_mastery; // range: [0,1999] [Inkfish] + unsigned char blockskill[MAX_SKILL]; + int cloneskill_id, reproduceskill_id; + int menuskill_id, menuskill_val, menuskill_val2; + + int invincible_timer; + unsigned int canlog_tick; + unsigned int canuseitem_tick; // [Skotlex] + unsigned int canusecashfood_tick; + unsigned int canequip_tick; // [Inkfish] + unsigned int cantalk_tick; + unsigned int canskill_tick; // used to prevent abuse from no-delay ACT files + unsigned int cansendmail_tick; // [Mail System Flood Protection] + unsigned int ks_floodprotect_tick; // [Kill Steal Protection] unsigned int bloodylust_tick; // bloodylust player timer [out/in re full-heal protection] - struct { - short nameid; - unsigned int tick; - } item_delay[MAX_ITEMDELAYS]; // [Paradox924X] - - short weapontype1,weapontype2; - short disguise; // [Valaris] - - struct weapon_data right_weapon, left_weapon; - - // here start arrays to be globally zeroed at the beginning of status_calc_pc() - int param_bonus[6],param_equip[6]; //Stores card/equipment bonuses. - int subele[ELE_MAX]; - int subrace[RC_MAX]; - int subrace2[RC2_MAX]; - int subsize[3]; - int reseff[SC_COMMON_MAX-SC_COMMON_MIN+1]; - int weapon_coma_ele[ELE_MAX]; - int weapon_coma_race[RC_MAX]; - int weapon_atk[16]; - int weapon_atk_rate[16]; - int arrow_addele[ELE_MAX]; - int arrow_addrace[RC_MAX]; - int arrow_addsize[3]; - int magic_addele[ELE_MAX]; - int magic_addrace[RC_MAX]; - int magic_addsize[3]; - int critaddrace[RC_MAX]; - int expaddrace[RC_MAX]; - int ignore_mdef[RC_MAX]; - int ignore_def[RC_MAX]; - int itemgrouphealrate[MAX_ITEMGROUP]; - short sp_gain_race[RC_MAX]; - short sp_gain_race_attack[RC_MAX]; - short hp_gain_race_attack[RC_MAX]; - // zeroed arrays end here. - // zeroed structures start here - struct s_autospell autospell[15], autospell2[15], autospell3[15]; - struct s_addeffect addeff[MAX_PC_BONUS], addeff2[MAX_PC_BONUS]; - struct s_addeffectonskill addeff3[MAX_PC_BONUS]; - - struct { //skillatk raises bonus dmg% of skills, skillheal increases heal%, skillblown increases bonus blewcount for some skills. - unsigned short id; - short val; - } skillatk[MAX_PC_BONUS], skillusesprate[MAX_PC_BONUS], skillusesp[MAX_PC_BONUS], skillheal[5], skillheal2[5], skillblown[MAX_PC_BONUS], skillcast[MAX_PC_BONUS], skillcooldown[MAX_PC_BONUS], skillfixcast[MAX_PC_BONUS], skillvarcast[MAX_PC_BONUS]; - struct { - short value; - int rate; - int tick; - } hp_loss, sp_loss, hp_regen, sp_regen; - struct { - short class_, rate; - } add_def[MAX_PC_BONUS], add_mdef[MAX_PC_BONUS], add_mdmg[MAX_PC_BONUS]; - struct s_add_drop add_drop[MAX_PC_BONUS]; - struct { - int nameid; - int rate; - } itemhealrate[MAX_PC_BONUS]; - struct { - short flag, rate; - unsigned char ele; - } subele2[MAX_PC_BONUS]; - // zeroed structures end here - // manually zeroed structures start here. - struct s_autobonus autobonus[MAX_PC_BONUS], autobonus2[MAX_PC_BONUS], autobonus3[MAX_PC_BONUS]; //Auto script on attack, when attacked, on skill usage - // manually zeroed structures end here. - // zeroed vars start here. - struct { - int atk_rate; - int arrow_atk,arrow_ele,arrow_cri,arrow_hit; - int nsshealhp,nsshealsp; - int critical_def,double_rate; - int long_attack_atk_rate; //Long range atk rate, not weapon based. [Skotlex] - int near_attack_def_rate,long_attack_def_rate,magic_def_rate,misc_def_rate; - int ignore_mdef_ele; - int ignore_mdef_race; - int perfect_hit; - int perfect_hit_add; - int get_zeny_rate; - int get_zeny_num; //Added Get Zeny Rate [Skotlex] - int double_add_rate; - int short_weapon_damage_return,long_weapon_damage_return; - int magic_damage_return; // AppleGirl Was Here - int break_weapon_rate,break_armor_rate; - int crit_atk_rate; - int classchange; // [Valaris] - int speed_rate, speed_add_rate, aspd_add; - int itemhealrate2; // [Epoque] Increase heal rate of all healing items. - int shieldmdef;//royal guard's - unsigned int setitem_hash, setitem_hash2; //Split in 2 because shift operations only work on int ranges. [Skotlex] - - short splash_range, splash_add_range; - short add_steal_rate; - short add_heal_rate, add_heal2_rate; - short sp_gain_value, hp_gain_value, magic_sp_gain_value, magic_hp_gain_value; - short sp_vanish_rate; - short sp_vanish_per; - unsigned short unbreakable; // chance to prevent ANY equipment breaking [celest] - unsigned short unbreakable_equip; //100% break resistance on certain equipment - unsigned short unstripable_equip; - int fixcastrate,varcastrate; - int ematk; // matk bonus from equipment - } bonus; - - // zeroed vars end here. - - int castrate,delayrate,hprate,sprate,dsprate; - int hprecov_rate,sprecov_rate; - int matk_rate; - int critical_rate,hit_rate,flee_rate,flee2_rate,def_rate,def2_rate,mdef_rate,mdef2_rate; - - int itemid; - short itemindex; //Used item's index in sd->inventory [Skotlex] - - short catch_target_class; // pet catching, stores a pet class to catch (short now) [zzo] - - short spiritball, spiritball_old; - int spirit_timer[MAX_SKILL_LEVEL]; - short talisman[ELE_POISON+1]; // There are actually 5 talisman Fire, Ice, Wind, Earth & Poison maybe because its color violet. - int talisman_timer[ELE_POISON+1][10]; - - unsigned char potion_success_counter; //Potion successes in row counter - unsigned char mission_count; //Stores the bounty kill count for TK_MISSION - short mission_mobid; //Stores the target mob_id for TK_MISSION - int die_counter; //Total number of times you've died - int devotion[5]; //Stores the account IDs of chars devoted to. - int reg_num; //Number of registries (type numeric) - int regstr_num; //Number of registries (type string) - - struct script_reg *reg; - struct script_regstr *regstr; - - int trade_partner; - struct { - struct { - short index, amount; - } item[10]; - int zeny, weight; - } deal; - - bool party_creating; // whether the char is requesting party creation - bool party_joining; // whether the char is accepting party invitation - int party_invite, party_invite_account; // for handling party invitation (holds party id and account id) - int adopt_invite; // Adoption - - int guild_invite,guild_invite_account; - int guild_emblem_id,guild_alliance,guild_alliance_account; - short guild_x,guild_y; // For guildmate position display. [Skotlex] should be short [zzo] - int guildspy; // [Syrus22] - int partyspy; // [Syrus22] - - int vended_id; - int vender_id; - int vend_num; - char message[MESSAGE_SIZE]; - struct s_vending vending[MAX_VENDING]; - - unsigned int buyer_id; // uid of open buying store - struct s_buyingstore buyingstore; - - struct s_search_store_info searchstore; - - struct pet_data *pd; - struct homun_data *hd; // [blackhole89] - struct mercenary_data *md; - struct elemental_data *ed; - - struct { - int m; //-1 - none, other: map index corresponding to map name. - unsigned short index; //map index - } feel_map[3]; // 0 - Sun; 1 - Moon; 2 - Stars - short hate_mob[3]; - - int pvp_timer; - short pvp_point; - unsigned short pvp_rank, pvp_lastusers; - unsigned short pvp_won, pvp_lost; - - char eventqueue[MAX_EVENTQUEUE][EVENT_NAME_LENGTH]; - int eventtimer[MAX_EVENTTIMER]; - unsigned short eventcount; // [celest] - - unsigned char change_level_2nd; // job level when changing from 1st to 2nd class [jobchange_level in global_reg_value] - unsigned char change_level_3rd; // job level when changing from 2nd to 3rd class [jobchange_level_3rd in global_reg_value] - - char fakename[NAME_LENGTH]; // fake names [Valaris] - - int duel_group; // duel vars [LuzZza] - int duel_invite; - - int killerrid, killedrid; - - int cashPoints, kafraPoints; - int rental_timer; - - // Auction System [Zephyrus] - struct { - int index, amount; - } auction; - - // Mail System [Zephyrus] - struct { - short nameid; - int index, amount, zeny; - struct mail_data inbox; - bool changed; // if true, should sync with charserver on next mailbox request - } mail; - - //Quest log system [Kevin] [Inkfish] - int num_quests; - int avail_quests; - int quest_index[MAX_QUEST_DB]; - struct quest quest_log[MAX_QUEST_DB]; - bool save_quest; - - // temporary debug [flaviojs] - const char *debug_file; - int debug_line; - const char *debug_func; - - unsigned int bg_id; - unsigned short user_font; - - /** - * For the Secure NPC Timeout option (check config/Secure.h) [RR] - **/ + struct { + short nameid; + unsigned int tick; + } item_delay[MAX_ITEMDELAYS]; // [Paradox924X] + + short weapontype1,weapontype2; + short disguise; // [Valaris] + + struct weapon_data right_weapon, left_weapon; + + // here start arrays to be globally zeroed at the beginning of status_calc_pc() + int param_bonus[6],param_equip[6]; //Stores card/equipment bonuses. + int subele[ELE_MAX]; + int subrace[RC_MAX]; + int subrace2[RC2_MAX]; + int subsize[3]; + int reseff[SC_COMMON_MAX-SC_COMMON_MIN+1]; + int weapon_coma_ele[ELE_MAX]; + int weapon_coma_race[RC_MAX]; + int weapon_atk[16]; + int weapon_atk_rate[16]; + int arrow_addele[ELE_MAX]; + int arrow_addrace[RC_MAX]; + int arrow_addsize[3]; + int magic_addele[ELE_MAX]; + int magic_addrace[RC_MAX]; + int magic_addsize[3]; + int critaddrace[RC_MAX]; + int expaddrace[RC_MAX]; + int ignore_mdef[RC_MAX]; + int ignore_def[RC_MAX]; + int itemgrouphealrate[MAX_ITEMGROUP]; + short sp_gain_race[RC_MAX]; + short sp_gain_race_attack[RC_MAX]; + short hp_gain_race_attack[RC_MAX]; + // zeroed arrays end here. + // zeroed structures start here + struct s_autospell autospell[15], autospell2[15], autospell3[15]; + struct s_addeffect addeff[MAX_PC_BONUS], addeff2[MAX_PC_BONUS]; + struct s_addeffectonskill addeff3[MAX_PC_BONUS]; + + struct { //skillatk raises bonus dmg% of skills, skillheal increases heal%, skillblown increases bonus blewcount for some skills. + unsigned short id; + short val; + } skillatk[MAX_PC_BONUS], skillusesprate[MAX_PC_BONUS], skillusesp[MAX_PC_BONUS], skillheal[5], skillheal2[5], skillblown[MAX_PC_BONUS], skillcast[MAX_PC_BONUS], skillcooldown[MAX_PC_BONUS], skillfixcast[MAX_PC_BONUS], skillvarcast[MAX_PC_BONUS]; + struct { + short value; + int rate; + int tick; + } hp_loss, sp_loss, hp_regen, sp_regen; + struct { + short class_, rate; + } add_def[MAX_PC_BONUS], add_mdef[MAX_PC_BONUS], add_mdmg[MAX_PC_BONUS]; + struct s_add_drop add_drop[MAX_PC_BONUS]; + struct { + int nameid; + int rate; + } itemhealrate[MAX_PC_BONUS]; + struct { + short flag, rate; + unsigned char ele; + } subele2[MAX_PC_BONUS]; + // zeroed structures end here + // manually zeroed structures start here. + struct s_autobonus autobonus[MAX_PC_BONUS], autobonus2[MAX_PC_BONUS], autobonus3[MAX_PC_BONUS]; //Auto script on attack, when attacked, on skill usage + // manually zeroed structures end here. + // zeroed vars start here. + struct { + int atk_rate; + int arrow_atk,arrow_ele,arrow_cri,arrow_hit; + int nsshealhp,nsshealsp; + int critical_def,double_rate; + int long_attack_atk_rate; //Long range atk rate, not weapon based. [Skotlex] + int near_attack_def_rate,long_attack_def_rate,magic_def_rate,misc_def_rate; + int ignore_mdef_ele; + int ignore_mdef_race; + int perfect_hit; + int perfect_hit_add; + int get_zeny_rate; + int get_zeny_num; //Added Get Zeny Rate [Skotlex] + int double_add_rate; + int short_weapon_damage_return,long_weapon_damage_return; + int magic_damage_return; // AppleGirl Was Here + int break_weapon_rate,break_armor_rate; + int crit_atk_rate; + int classchange; // [Valaris] + int speed_rate, speed_add_rate, aspd_add; + int itemhealrate2; // [Epoque] Increase heal rate of all healing items. + int shieldmdef;//royal guard's + unsigned int setitem_hash, setitem_hash2; //Split in 2 because shift operations only work on int ranges. [Skotlex] + + short splash_range, splash_add_range; + short add_steal_rate; + short add_heal_rate, add_heal2_rate; + short sp_gain_value, hp_gain_value, magic_sp_gain_value, magic_hp_gain_value; + short sp_vanish_rate; + short sp_vanish_per; + short sp_weapon_matk,sp_base_matk; + unsigned short unbreakable; // chance to prevent ANY equipment breaking [celest] + unsigned short unbreakable_equip; //100% break resistance on certain equipment + unsigned short unstripable_equip; + int fixcastrate,varcastrate; + } bonus; + + // zeroed vars end here. + + int castrate,delayrate,hprate,sprate,dsprate; + int hprecov_rate,sprecov_rate; + int matk_rate; + int critical_rate,hit_rate,flee_rate,flee2_rate,def_rate,def2_rate,mdef_rate,mdef2_rate; + + int itemid; + short itemindex; //Used item's index in sd->inventory [Skotlex] + + short catch_target_class; // pet catching, stores a pet class to catch (short now) [zzo] + + short spiritball, spiritball_old; + int spirit_timer[MAX_SKILL_LEVEL]; + short talisman[ELE_POISON+1]; // There are actually 5 talisman Fire, Ice, Wind, Earth & Poison maybe because its color violet. + int talisman_timer[ELE_POISON+1][10]; + + unsigned char potion_success_counter; //Potion successes in row counter + unsigned char mission_count; //Stores the bounty kill count for TK_MISSION + short mission_mobid; //Stores the target mob_id for TK_MISSION + int die_counter; //Total number of times you've died + int devotion[5]; //Stores the account IDs of chars devoted to. + int reg_num; //Number of registries (type numeric) + int regstr_num; //Number of registries (type string) + + struct script_reg *reg; + struct script_regstr *regstr; + + int trade_partner; + struct { + struct { + short index, amount; + } item[10]; + int zeny, weight; + } deal; + + bool party_creating; // whether the char is requesting party creation + bool party_joining; // whether the char is accepting party invitation + int party_invite, party_invite_account; // for handling party invitation (holds party id and account id) + int adopt_invite; // Adoption + + int guild_invite,guild_invite_account; + int guild_emblem_id,guild_alliance,guild_alliance_account; + short guild_x,guild_y; // For guildmate position display. [Skotlex] should be short [zzo] + int guildspy; // [Syrus22] + int partyspy; // [Syrus22] + + int vended_id; + int vender_id; + int vend_num; + char message[MESSAGE_SIZE]; + struct s_vending vending[MAX_VENDING]; + + unsigned int buyer_id; // uid of open buying store + struct s_buyingstore buyingstore; + + struct s_search_store_info searchstore; + + struct pet_data *pd; + struct homun_data *hd; // [blackhole89] + struct mercenary_data *md; + struct elemental_data *ed; + + struct{ + int m; //-1 - none, other: map index corresponding to map name. + unsigned short index; //map index + }feel_map[3];// 0 - Sun; 1 - Moon; 2 - Stars + short hate_mob[3]; + + int pvp_timer; + short pvp_point; + unsigned short pvp_rank, pvp_lastusers; + unsigned short pvp_won, pvp_lost; + + char eventqueue[MAX_EVENTQUEUE][EVENT_NAME_LENGTH]; + int eventtimer[MAX_EVENTTIMER]; + unsigned short eventcount; // [celest] + + unsigned char change_level_2nd; // job level when changing from 1st to 2nd class [jobchange_level in global_reg_value] + unsigned char change_level_3rd; // job level when changing from 2nd to 3rd class [jobchange_level_3rd in global_reg_value] + + char fakename[NAME_LENGTH]; // fake names [Valaris] + + int duel_group; // duel vars [LuzZza] + int duel_invite; + + int killerrid, killedrid; + + int cashPoints, kafraPoints; + int rental_timer; + + // Auction System [Zephyrus] + struct { + int index, amount; + } auction; + + // Mail System [Zephyrus] + struct { + short nameid; + int index, amount, zeny; + struct mail_data inbox; + bool changed; // if true, should sync with charserver on next mailbox request + } mail; + + //Quest log system [Kevin] [Inkfish] + int num_quests; + int avail_quests; + int quest_index[MAX_QUEST_DB]; + struct quest quest_log[MAX_QUEST_DB]; + bool save_quest; + + // temporary debug [flaviojs] + const char* debug_file; + int debug_line; + const char* debug_func; + + unsigned int bg_id; + unsigned short user_font; + + /** + * For the Secure NPC Timeout option (check config/Secure.h) [RR] + **/ #if SECURE_NPCTIMEOUT - /** - * ID of the timer - * @info - * - value is -1 (INVALID_TIMER constant) when not being used - * - timer is cancelled upon closure of the current npc's instance - **/ - int npc_idle_timer; - /** - * Tick on the last recorded NPC iteration (next/menu/whatever) - * @info - * - It is updated on every NPC iteration as mentioned above - **/ - unsigned int npc_idle_tick; + /** + * ID of the timer + * @info + * - value is -1 (INVALID_TIMER constant) when not being used + * - timer is cancelled upon closure of the current npc's instance + **/ + int npc_idle_timer; + /** + * Tick on the last recorded NPC iteration (next/menu/whatever) + * @info + * - It is updated on every NPC iteration as mentioned above + **/ + unsigned int npc_idle_tick; #endif - struct { - struct script_code **bonus;/* the script */ - unsigned short *id;/* array of combo ids */ - unsigned char count; - } combos; + struct { + struct script_code **bonus;/* the script */ + unsigned short *id;/* array of combo ids */ + unsigned char count; + } combos; - /** - * Guarantees your friend request is legit (for bugreport:4629) - **/ - int friend_req; + /** + * Guarantees your friend request is legit (for bugreport:4629) + **/ + int friend_req; - int shadowform_id; + int shadowform_id; - // temporary debugging of bug #3504 - const char *delunit_prevfile; - int delunit_prevline; + // temporary debugging of bug #3504 + const char* delunit_prevfile; + int delunit_prevline; }; @@ -485,68 +485,68 @@ struct map_session_data { #define CLASS_COUNT (JOB_MAX - JOB_NOVICE_HIGH + JOB_MAX_BASIC) enum weapon_type { - W_FIST, //Bare hands - W_DAGGER, //1 - W_1HSWORD, //2 - W_2HSWORD, //3 - W_1HSPEAR, //4 - W_2HSPEAR, //5 - W_1HAXE, //6 - W_2HAXE, //7 - W_MACE, //8 - W_2HMACE, //9 (unused) - W_STAFF, //10 - W_BOW, //11 - W_KNUCKLE, //12 - W_MUSICAL, //13 - W_WHIP, //14 - W_BOOK, //15 - W_KATAR, //16 - W_REVOLVER, //17 - W_RIFLE, //18 - W_GATLING, //19 - W_SHOTGUN, //20 - W_GRENADE, //21 - W_HUUMA, //22 - W_2HSTAFF, //23 - MAX_WEAPON_TYPE, - // dual-wield constants - W_DOUBLE_DD, // 2 daggers - W_DOUBLE_SS, // 2 swords - W_DOUBLE_AA, // 2 axes - W_DOUBLE_DS, // dagger + sword - W_DOUBLE_DA, // dagger + axe - W_DOUBLE_SA, // sword + axe + W_FIST, //Bare hands + W_DAGGER, //1 + W_1HSWORD, //2 + W_2HSWORD, //3 + W_1HSPEAR, //4 + W_2HSPEAR, //5 + W_1HAXE, //6 + W_2HAXE, //7 + W_MACE, //8 + W_2HMACE, //9 (unused) + W_STAFF, //10 + W_BOW, //11 + W_KNUCKLE, //12 + W_MUSICAL, //13 + W_WHIP, //14 + W_BOOK, //15 + W_KATAR, //16 + W_REVOLVER, //17 + W_RIFLE, //18 + W_GATLING, //19 + W_SHOTGUN, //20 + W_GRENADE, //21 + W_HUUMA, //22 + W_2HSTAFF, //23 + MAX_WEAPON_TYPE, + // dual-wield constants + W_DOUBLE_DD, // 2 daggers + W_DOUBLE_SS, // 2 swords + W_DOUBLE_AA, // 2 axes + W_DOUBLE_DS, // dagger + sword + W_DOUBLE_DA, // dagger + axe + W_DOUBLE_SA, // sword + axe }; enum ammo_type { - A_ARROW = 1, - A_DAGGER, //2 - A_BULLET, //3 - A_SHELL, //4 - A_GRENADE, //5 - A_SHURIKEN, //6 - A_KUNAI, //7 - A_CANNONBALL, //8 - A_THROWWEAPON //9 + A_ARROW = 1, + A_DAGGER, //2 + A_BULLET, //3 + A_SHELL, //4 + A_GRENADE, //5 + A_SHURIKEN, //6 + A_KUNAI, //7 + A_CANNONBALL, //8 + A_THROWWEAPON //9 }; //Equip position constants enum equip_pos { - EQP_HEAD_LOW = 0x0001, - EQP_HEAD_MID = 0x0200, //512 - EQP_HEAD_TOP = 0x0100, //256 - EQP_HAND_R = 0x0002, - EQP_HAND_L = 0x0020, //32 - EQP_ARMOR = 0x0010, //16 - EQP_SHOES = 0x0040, //64 - EQP_GARMENT = 0x0004, - EQP_ACC_L = 0x0008, - EQP_ACC_R = 0x0080, //128 - EQP_COSTUME_HEAD_TOP = 0x0400, - EQP_COSTUME_HEAD_MID = 0x0800, - EQP_COSTUME_HEAD_LOW = 0x1000, - EQP_AMMO = 0x8000, //32768 + EQP_HEAD_LOW = 0x0001, + EQP_HEAD_MID = 0x0200, //512 + EQP_HEAD_TOP = 0x0100, //256 + EQP_HAND_R = 0x0002, + EQP_HAND_L = 0x0020, //32 + EQP_ARMOR = 0x0010, //16 + EQP_SHOES = 0x0040, //64 + EQP_GARMENT = 0x0004, + EQP_ACC_L = 0x0008, + EQP_ACC_R = 0x0080, //128 + EQP_COSTUME_HEAD_TOP = 0x0400, + EQP_COSTUME_HEAD_MID = 0x0800, + EQP_COSTUME_HEAD_LOW = 0x1000, + EQP_AMMO = 0x8000, //32768 }; #define EQP_WEAPON EQP_HAND_R @@ -558,29 +558,29 @@ enum equip_pos { /// Equip positions that use a visible sprite #if PACKETVER < 20110111 -#define EQP_VISIBLE EQP_HELM + #define EQP_VISIBLE EQP_HELM #else -#define EQP_VISIBLE (EQP_HELM|EQP_GARMENT|EQP_COSTUME) + #define EQP_VISIBLE (EQP_HELM|EQP_GARMENT|EQP_COSTUME) #endif //Equip indexes constants. (eg: sd->equip_index[EQI_AMMO] returns the index //where the arrows are equipped) enum equip_index { - EQI_ACC_L = 0, - EQI_ACC_R, - EQI_SHOES, - EQI_GARMENT, - EQI_HEAD_LOW, - EQI_HEAD_MID, - EQI_HEAD_TOP, - EQI_ARMOR, - EQI_HAND_L, - EQI_HAND_R, - EQI_COSTUME_TOP, - EQI_COSTUME_MID, - EQI_COSTUME_LOW, - EQI_AMMO, - EQI_MAX + EQI_ACC_L = 0, + EQI_ACC_R, + EQI_SHOES, + EQI_GARMENT, + EQI_HEAD_LOW, + EQI_HEAD_MID, + EQI_HEAD_TOP, + EQI_ARMOR, + EQI_HAND_L, + EQI_HAND_R, + EQI_COSTUME_TOP, + EQI_COSTUME_MID, + EQI_COSTUME_LOW, + EQI_AMMO, + EQI_MAX }; #define pc_setdead(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 1 ) @@ -597,9 +597,9 @@ enum equip_index { #define pc_ischasewalk(sd) ( (sd)->sc.option&OPTION_CHASEWALK ) #ifdef NEW_CARTS -#define pc_iscarton(sd) ( (sd)->sc.data[SC_PUSH_CART] ) + #define pc_iscarton(sd) ( (sd)->sc.data[SC_PUSH_CART] ) #else -#define pc_iscarton(sd) ( (sd)->sc.option&OPTION_CART ) + #define pc_iscarton(sd) ( (sd)->sc.option&OPTION_CART ) #endif #define pc_isfalcon(sd) ( (sd)->sc.option&OPTION_FALCON ) @@ -623,49 +623,35 @@ enum equip_index { //Weapon check considering dual wielding. #define pc_check_weapontype(sd, type) ((type)&((sd)->status.weapon < MAX_WEAPON_TYPE? \ - 1<<(sd)->status.weapon:(1<<(sd)->weapontype1)|(1<<(sd)->weapontype2)|(1<<(sd)->status.weapon))) + 1<<(sd)->status.weapon:(1<<(sd)->weapontype1)|(1<<(sd)->weapontype2)|(1<<(sd)->status.weapon))) //Checks if the given class value corresponds to a player class. [Skotlex] //JOB_NOVICE isn't checked for class_ is supposed to be unsigned #define pcdb_checkid_sub(class_) \ - ( \ - ( (class_) < JOB_MAX_BASIC ) \ - || ( (class_) >= JOB_NOVICE_HIGH && (class_) <= JOB_DARK_COLLECTOR ) \ - || ( (class_) >= JOB_RUNE_KNIGHT && (class_) <= JOB_MECHANIC_T2 ) \ - || ( (class_) >= JOB_BABY_RUNE && (class_) <= JOB_BABY_MECHANIC2 ) \ - || ( (class_) >= JOB_SUPER_NOVICE_E && (class_) <= JOB_SUPER_BABY_E ) \ - || ( (class_) >= JOB_KAGEROU && (class_) < JOB_MAX ) \ - ) +( \ + ( (class_) < JOB_MAX_BASIC ) \ +|| ( (class_) >= JOB_NOVICE_HIGH && (class_) <= JOB_DARK_COLLECTOR ) \ +|| ( (class_) >= JOB_RUNE_KNIGHT && (class_) <= JOB_MECHANIC_T2 ) \ +|| ( (class_) >= JOB_BABY_RUNE && (class_) <= JOB_BABY_MECHANIC2 ) \ +|| ( (class_) >= JOB_SUPER_NOVICE_E && (class_) <= JOB_SUPER_BABY_E ) \ +|| ( (class_) >= JOB_KAGEROU && (class_) < JOB_MAX ) \ +) #define pcdb_checkid(class_) pcdb_checkid_sub((unsigned int)class_) // clientside display macros (values to the left/right of the "+") #ifdef RENEWAL -#define pc_leftside_atk(sd) ((sd)->battle_status.batk) -#define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk + (sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2) -#define pc_leftside_def(sd) ((sd)->battle_status.def2) -#define pc_rightside_def(sd) ((sd)->battle_status.def) -#define pc_leftside_mdef(sd) ((sd)->battle_status.mdef2) -#define pc_rightside_mdef(sd) ((sd)->battle_status.mdef) -#define pc_leftside_matk(sd) (status_base_matk(status_get_status_data(&(sd)->bl), (sd)->status.base_level)) -#define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->bonus.ematk) + #define pc_leftside_atk(sd) ((sd)->battle_status.batk) + #define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk + (sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2) + #define pc_leftside_def(sd) ((sd)->battle_status.def2) + #define pc_rightside_def(sd) ((sd)->battle_status.def) + #define pc_leftside_mdef(sd) ((sd)->battle_status.mdef2) + #define pc_rightside_mdef(sd) ((sd)->battle_status.mdef) #else -#define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk) -#define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2) -#define pc_leftside_def(sd) ((sd)->battle_status.def) -#define pc_rightside_def(sd) ((sd)->battle_status.def2) -#define pc_leftside_mdef(sd) ((sd)->battle_status.mdef) -#define pc_rightside_mdef(sd) ( (sd)->battle_status.mdef2 - ((sd)->battle_status.vit>>1) ) -#define pc_leftside_matk(sd) \ - (\ - ((sd)->sc.data[SC_MAGICPOWER] && (sd)->sc.data[SC_MAGICPOWER]->val4) \ - ?((sd)->battle_status.matk_min * 100 + 50) / ((sd)->sc.data[SC_MAGICPOWER]->val3+100) \ - :(sd)->battle_status.matk_min \ - ) -#define pc_rightside_matk(sd) \ - (\ - ((sd)->sc.data[SC_MAGICPOWER] && (sd)->sc.data[SC_MAGICPOWER]->val4) \ - ?((sd)->battle_status.matk_max * 100 + 50) / ((sd)->sc.data[SC_MAGICPOWER]->val3+100) \ - :(sd)->battle_status.matk_max \ - ) + #define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk) + #define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2) + #define pc_leftside_def(sd) ((sd)->battle_status.def) + #define pc_rightside_def(sd) ((sd)->battle_status.def2) + #define pc_leftside_mdef(sd) ((sd)->battle_status.mdef) + #define pc_rightside_mdef(sd) ( (sd)->battle_status.mdef2 - ((sd)->battle_status.vit>>1) ) #endif int pc_class2idx(int class_); @@ -680,8 +666,8 @@ bool pc_should_log_commands(struct map_session_data *sd); int pc_setrestartvalue(struct map_session_data *sd,int type); int pc_makesavestatus(struct map_session_data *); -void pc_respawn(struct map_session_data *sd, clr_type clrtype); -int pc_setnewpc(struct map_session_data *,int,int,int,unsigned int,int,int); +void pc_respawn(struct map_session_data* sd, clr_type clrtype); +int pc_setnewpc(struct map_session_data*,int,int,int,unsigned int,int,int); bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers); void pc_authfail(struct map_session_data *); int pc_reg_received(struct map_session_data *sd); @@ -701,18 +687,18 @@ int pc_clean_skilltree(struct map_session_data *sd); #define pc_checkoverhp(sd) ((sd)->battle_status.hp == (sd)->battle_status.max_hp) #define pc_checkoversp(sd) ((sd)->battle_status.sp == (sd)->battle_status.max_sp) -int pc_setpos(struct map_session_data *sd, unsigned short mapindex, int x, int y, clr_type clrtype); -int pc_setsavepoint(struct map_session_data *,short,int,int); +int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype); +int pc_setsavepoint(struct map_session_data*,short,int,int); int pc_randomwarp(struct map_session_data *sd,clr_type type); -int pc_memo(struct map_session_data *sd, int pos); +int pc_memo(struct map_session_data* sd, int pos); -int pc_checkadditem(struct map_session_data *,int,int); -int pc_inventoryblank(struct map_session_data *); +int pc_checkadditem(struct map_session_data*,int,int); +int pc_inventoryblank(struct map_session_data*); int pc_search_inventory(struct map_session_data *sd,int item_id); -int pc_payzeny(struct map_session_data *,int, enum e_log_pick_type type, struct map_session_data *); -int pc_additem(struct map_session_data *,struct item *,int,e_log_pick_type); -int pc_getzeny(struct map_session_data *,int, enum e_log_pick_type, struct map_session_data *); -int pc_delitem(struct map_session_data *,int,int,int,short,e_log_pick_type); +int pc_payzeny(struct map_session_data*,int, enum e_log_pick_type type, struct map_session_data*); +int pc_additem(struct map_session_data*,struct item*,int,e_log_pick_type); +int pc_getzeny(struct map_session_data*,int, enum e_log_pick_type, struct map_session_data*); +int pc_delitem(struct map_session_data*,int,int,int,short,e_log_pick_type); // Special Shop System int pc_paycash(struct map_session_data *sd, int price, int points); @@ -724,62 +710,62 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount); int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount); int pc_cartitem_amount(struct map_session_data *sd,int idx,int amount); -int pc_takeitem(struct map_session_data *,struct flooritem_data *); -int pc_dropitem(struct map_session_data *,int,int); +int pc_takeitem(struct map_session_data*,struct flooritem_data*); +int pc_dropitem(struct map_session_data*,int,int); bool pc_isequipped(struct map_session_data *sd, int nameid); -bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd); +bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd ); bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd); int pc_updateweightstatus(struct map_session_data *sd); int pc_addautobonus(struct s_autobonus *bonus,char max,const char *script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned short pos,bool onskill); -int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *bonus); +int pc_exeautobonus(struct map_session_data* sd,struct s_autobonus *bonus); int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data); -int pc_delautobonus(struct map_session_data *sd,struct s_autobonus *bonus,char max,bool restore); +int pc_delautobonus(struct map_session_data* sd,struct s_autobonus *bonus,char max,bool restore); -int pc_bonus(struct map_session_data *,int,int); +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_bonus5(struct map_session_data *sd,int,int,int,int,int,int); -int pc_skill(struct map_session_data *sd, int id, int level, int flag); +int pc_skill(struct map_session_data* sd, int id, int level, int flag); int pc_insert_card(struct map_session_data *sd,int idx_card,int idx_equip); int pc_steal_item(struct map_session_data *sd,struct block_list *bl, int skilllv); int pc_steal_coin(struct map_session_data *sd,struct block_list *bl); -int pc_modifybuyvalue(struct map_session_data *,int); -int pc_modifysellvalue(struct map_session_data *,int); +int pc_modifybuyvalue(struct map_session_data*,int); +int pc_modifysellvalue(struct map_session_data*,int); -int pc_follow(struct map_session_data *, int); // [MouseJstr] -int pc_stop_following(struct map_session_data *); +int pc_follow(struct map_session_data*, int); // [MouseJstr] +int pc_stop_following(struct map_session_data*); unsigned int pc_maxbaselv(struct map_session_data *sd); unsigned int pc_maxjoblv(struct map_session_data *sd); int pc_checkbaselevelup(struct map_session_data *sd); int pc_checkjoblevelup(struct map_session_data *sd); -int pc_gainexp(struct map_session_data *,struct block_list *,unsigned int,unsigned int, bool); +int pc_gainexp(struct map_session_data*,struct block_list*,unsigned int,unsigned int, bool); unsigned int pc_nextbaseexp(struct map_session_data *); unsigned int pc_thisbaseexp(struct map_session_data *); unsigned int pc_nextjobexp(struct map_session_data *); unsigned int pc_thisjobexp(struct map_session_data *); int pc_gets_status_point(int); int pc_need_status_point(struct map_session_data *,int,int); -int pc_statusup(struct map_session_data *,int); -int pc_statusup2(struct map_session_data *,int,int); -int pc_skillup(struct map_session_data *,int); -int pc_allskillup(struct map_session_data *); -int pc_resetlvl(struct map_session_data *,int type); -int pc_resetstate(struct map_session_data *); -int pc_resetskill(struct map_session_data *, int); -int pc_resetfeel(struct map_session_data *); -int pc_resethate(struct map_session_data *); -int pc_equipitem(struct map_session_data *,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); +int pc_statusup(struct map_session_data*,int); +int pc_statusup2(struct map_session_data*,int,int); +int pc_skillup(struct map_session_data*,int); +int pc_allskillup(struct map_session_data*); +int pc_resetlvl(struct map_session_data*,int type); +int pc_resetstate(struct map_session_data*); +int pc_resetskill(struct map_session_data*, int); +int pc_resetfeel(struct map_session_data*); +int pc_resethate(struct map_session_data*); +int pc_equipitem(struct map_session_data*,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); int pc_skillatk_bonus(struct map_session_data *sd, int skill_num); int pc_skillheal_bonus(struct map_session_data *sd, int skill_num); @@ -793,17 +779,17 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp); int pc_percentheal(struct map_session_data *sd,int,int); int pc_jobchange(struct map_session_data *,int, int); int pc_setoption(struct map_session_data *,int); -int pc_setcart(struct map_session_data *sd, int type); -int pc_setfalcon(struct map_session_data *sd, int flag); -int pc_setriding(struct map_session_data *sd, int flag); -int pc_setmadogear(struct map_session_data *sd, int flag); +int pc_setcart(struct map_session_data* sd, int type); +int pc_setfalcon(struct map_session_data* sd, int flag); +int pc_setriding(struct map_session_data* sd, int flag); +int pc_setmadogear(struct map_session_data* sd, int flag); int pc_changelook(struct map_session_data *,int,int); int pc_equiplookall(struct map_session_data *sd); -int pc_readparam(struct map_session_data *,int); -int pc_setparam(struct map_session_data *,int,int); -int pc_readreg(struct map_session_data *,int); -int pc_setreg(struct map_session_data *,int,int); +int pc_readparam(struct map_session_data*,int); +int pc_setparam(struct map_session_data*,int,int); +int pc_readreg(struct map_session_data*,int); +int pc_setreg(struct map_session_data*,int,int); char *pc_readregstr(struct map_session_data *sd,int reg); int pc_setregstr(struct map_session_data *sd,int reg,const char *str); @@ -819,10 +805,10 @@ int pc_setregstr(struct map_session_data *sd,int reg,const char *str); #define pc_setaccountreg2(sd,reg,val) pc_setregistry(sd,reg,val,1) #define pc_readaccountreg2str(sd,reg) pc_readregistry_str(sd,reg,1) #define pc_setaccountreg2str(sd,reg,val) pc_setregistry_str(sd,reg,val,1) -int pc_readregistry(struct map_session_data *,const char *,int); -int pc_setregistry(struct map_session_data *,const char *,int,int); -char *pc_readregistry_str(struct map_session_data *,const char *,int); -int pc_setregistry_str(struct map_session_data *,const char *,const char *,int); +int pc_readregistry(struct map_session_data*,const char*,int); +int pc_setregistry(struct map_session_data*,const char*,int,int); +char *pc_readregistry_str(struct map_session_data*,const char*,int); +int pc_setregistry_str(struct map_session_data*,const char*,const char*,int); int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name); int pc_deleventtimer(struct map_session_data *sd,const char *name); @@ -840,40 +826,40 @@ 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); -void pc_bleeding(struct map_session_data *sd, unsigned int diff_tick); -void pc_regen(struct map_session_data *sd, unsigned int diff_tick); +void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick); +void pc_regen (struct map_session_data *sd, unsigned int diff_tick); void pc_setstand(struct map_session_data *sd); int pc_candrop(struct map_session_data *sd,struct item *item); -int pc_jobid2mapid(unsigned short b_class); // Skotlex -int pc_mapid2jobid(unsigned short class_, int sex); // Skotlex +int pc_jobid2mapid(unsigned short b_class); // Skotlex +int pc_mapid2jobid(unsigned short class_, int sex); // Skotlex -const char *job_name(int class_); +const char * job_name(int class_); struct skill_tree_entry { - short id; - unsigned char max; - unsigned char joblv; - struct { - short id; - unsigned char lv; - } need[MAX_PC_SKILL_REQUIRE]; + short id; + unsigned char max; + unsigned char joblv; + struct { + short id; + unsigned char lv; + } need[MAX_PC_SKILL_REQUIRE]; }; // Celest extern struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE]; struct sg_data { - short anger_id; - short bless_id; - short comfort_id; - char feel_var[NAME_LENGTH]; - char hate_var[NAME_LENGTH]; - int (*day_func)(void); + short anger_id; + short bless_id; + short comfort_id; + char feel_var[NAME_LENGTH]; + char hate_var[NAME_LENGTH]; + int (*day_func)(void); }; extern const struct sg_data sg_info[MAX_PC_FEELHATE]; -void pc_setinvincibletimer(struct map_session_data *sd, int val); -void pc_delinvincibletimer(struct map_session_data *sd); +void pc_setinvincibletimer(struct map_session_data* sd, int val); +void 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); @@ -920,6 +906,6 @@ int pc_del_talisman(struct map_session_data *sd,int count,int type); void pc_baselevelchanged(struct map_session_data *sd); #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) -int pc_level_penalty_mod(struct map_session_data *sd, struct mob_data *md, int type); +int pc_level_penalty_mod(struct map_session_data *sd, struct mob_data * md, int type); #endif #endif /* _PC_H_ */ diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 76335532d..3111e2788 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -18,42 +18,42 @@ typedef struct GroupSettings GroupSettings; // Cached config settings/pointers for quick lookup struct GroupSettings { - unsigned int id; // groups.[].id - int level; // groups.[].level - const char *name; // groups.[].name - config_setting_t *commands; // groups.[].commands - unsigned int e_permissions; // packed groups.[].permissions - bool log_commands; // groups.[].log_commands - /// Following are used only during config reading - config_setting_t *permissions; // groups.[].permissions - config_setting_t *inherit; // groups.[].inherit - bool inheritance_done; // have all inheritance rules been evaluated? - config_setting_t *root; // groups.[] - int group_pos;/* pos on load */ + unsigned int id; // groups.[].id + int level; // groups.[].level + const char *name; // groups.[].name + config_setting_t *commands; // groups.[].commands + unsigned int e_permissions; // packed groups.[].permissions + bool log_commands; // groups.[].log_commands + /// Following are used only during config reading + config_setting_t *permissions; // groups.[].permissions + config_setting_t *inherit; // groups.[].inherit + bool inheritance_done; // have all inheritance rules been evaluated? + config_setting_t *root; // groups.[] + int group_pos;/* pos on load */ }; int pc_group_max; /* known number of groups */ static config_t pc_group_config; -static DBMap *pc_group_db; // id -> GroupSettings -static DBMap *pc_groupname_db; // name -> GroupSettings +static DBMap* pc_group_db; // id -> GroupSettings +static DBMap* pc_groupname_db; // name -> GroupSettings /** * @retval NULL if not found * @private */ -static inline GroupSettings *id2group(int group_id) +static inline GroupSettings* id2group(int group_id) { - return (GroupSettings *)idb_get(pc_group_db, group_id); + return (GroupSettings*)idb_get(pc_group_db, group_id); } /** * @retval NULL if not found * @private */ -static inline GroupSettings *name2group(const char *group_name) +static inline GroupSettings* name2group(const char* group_name) { - return (GroupSettings *)strdb_get(pc_groupname_db, group_name); + return (GroupSettings*)strdb_get(pc_groupname_db, group_name); } /** @@ -62,234 +62,234 @@ static inline GroupSettings *name2group(const char *group_name) */ static void read_config(void) { - config_setting_t *groups = NULL; - const char *config_filename = "conf/groups.conf"; // FIXME hardcoded name - int group_count = 0; - - if (conf_read_file(&pc_group_config, config_filename)) - return; - - groups = config_lookup(&pc_group_config, "groups"); - - if (groups != NULL) { - GroupSettings *group_settings = NULL; - DBIterator *iter = NULL; - int i, loop = 0; - - group_count = config_setting_length(groups); - for (i = 0; i < group_count; ++i) { - int id = 0, level = 0; - const char *groupname = NULL; - int log_commands = 0; - config_setting_t *group = config_setting_get_elem(groups, i); - - if (!config_setting_lookup_int(group, "id", &id)) { - ShowConfigWarning(group, "pc_groups:read_config: \"groups\" list member #%d has undefined id, removing...", i); - config_setting_remove_elem(groups, i); - --i; - --group_count; - continue; - } - - if (id2group(id) != NULL) { - ShowConfigWarning(group, "pc_groups:read_config: duplicate group id %d, removing...", i); - config_setting_remove_elem(groups, i); - --i; - --group_count; - continue; - } - - config_setting_lookup_int(group, "level", &level); - config_setting_lookup_bool(group, "log_commands", &log_commands); - - if (!config_setting_lookup_string(group, "name", &groupname)) { - char temp[20]; - config_setting_t *name = NULL; - snprintf(temp, sizeof(temp), "Group %d", id); - if ((name = config_setting_add(group, "name", CONFIG_TYPE_STRING)) == NULL || - !config_setting_set_string(name, temp)) { - ShowError("pc_groups:read_config: failed to set missing group name, id=%d, skipping... (%s:%d)\n", - id, config_setting_source_file(group), config_setting_source_line(group)); - continue; - } - config_setting_lookup_string(group, "name", &groupname); // Retrieve the pointer - } - - if (name2group(groupname) != NULL) { - ShowConfigWarning(group, "pc_groups:read_config: duplicate group name %s, removing...", groupname); - config_setting_remove_elem(groups, i); - --i; - --group_count; - continue; - } - - CREATE(group_settings, GroupSettings, 1); - group_settings->id = id; - group_settings->level = level; - group_settings->name = groupname; - group_settings->log_commands = (bool)log_commands; - group_settings->inherit = config_setting_get_member(group, "inherit"); - group_settings->commands = config_setting_get_member(group, "commands"); - group_settings->permissions = config_setting_get_member(group, "permissions"); - group_settings->inheritance_done = false; - group_settings->root = group; - group_settings->group_pos = i; - - strdb_put(pc_groupname_db, groupname, group_settings); - idb_put(pc_group_db, id, group_settings); - - } - group_count = config_setting_length(groups); // Save number of groups - - // Check if all commands and permissions exist - iter = db_iterator(pc_group_db); - for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { - config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions; - int count = 0, i; - - // Make sure there is "commands" group - if (commands == NULL) - commands = group_settings->commands = config_setting_add(group_settings->root, "commands", CONFIG_TYPE_GROUP); - count = config_setting_length(commands); - - for (i = 0; i < count; ++i) { - config_setting_t *command = config_setting_get_elem(commands, i); - const char *name = config_setting_name(command); - if (!atcommand_exists(name)) { - ShowConfigWarning(command, "pc_groups:read_config: non-existent command name '%s', removing...", name); - config_setting_remove(commands, name); - --i; - --count; - } - } - - // Make sure there is "permissions" group - if (permissions == NULL) - permissions = group_settings->permissions = config_setting_add(group_settings->root, "permissions", CONFIG_TYPE_GROUP); - count = config_setting_length(permissions); - - for (i = 0; i < count; ++i) { - config_setting_t *permission = config_setting_get_elem(permissions, i); - const char *name = config_setting_name(permission); - int j; - - ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0); - if (j == ARRAYLENGTH(pc_g_permission_name)) { - ShowConfigWarning(permission, "pc_groups:read_config: non-existent permission name '%s', removing...", name); - config_setting_remove(permissions, name); - --i; - --count; - } - } - } - dbi_destroy(iter); - - // Apply inheritance - i = 0; // counter for processed groups - while (i < group_count) { - iter = db_iterator(pc_group_db); - for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { - config_setting_t *inherit = NULL, - *commands = group_settings->commands, - *permissions = group_settings->permissions; - int j, inherit_count = 0, done = 0; - - if (group_settings->inheritance_done) // group already processed - continue; - - if ((inherit = group_settings->inherit) == NULL || - (inherit_count = config_setting_length(inherit)) <= 0) { // this group does not inherit from others - ++i; - group_settings->inheritance_done = true; - continue; - } - - for (j = 0; j < inherit_count; ++j) { - GroupSettings *inherited_group = NULL; - const char *groupname = config_setting_get_string_elem(inherit, j); - - if (groupname == NULL) { - ShowConfigWarning(inherit, "pc_groups:read_config: \"inherit\" array member #%d is not a name, removing...", j); - config_setting_remove_elem(inherit,j); - continue; - } - if ((inherited_group = name2group(groupname)) == NULL) { - ShowConfigWarning(inherit, "pc_groups:read_config: non-existent group name \"%s\", removing...", groupname); - config_setting_remove_elem(inherit,j); - continue; - } - if (!inherited_group->inheritance_done) - continue; // we need to do that group first - - // Copy settings (commands/permissions) that are not defined yet - if (inherited_group->commands != NULL) { - int i = 0, commands_count = config_setting_length(inherited_group->commands); - for (i = 0; i < commands_count; ++i) - config_setting_copy(commands, config_setting_get_elem(inherited_group->commands, i)); - } - - if (inherited_group->permissions != NULL) { - int i = 0, permissions_count = config_setting_length(inherited_group->permissions); - for (i = 0; i < permissions_count; ++i) - config_setting_copy(permissions, config_setting_get_elem(inherited_group->permissions, i)); - } - - ++done; // copied commands and permissions from one of inherited groups - } - - if (done == inherit_count) { // copied commands from all of inherited groups - ++i; - group_settings->inheritance_done = true; // we're done with this group - } - } - dbi_destroy(iter); - - if (++loop > group_count) { - ShowWarning("pc_groups:read_config: Could not process inheritance rules, check your config '%s' for cycles...\n", - config_filename); - break; - } - } // while(i < group_count) - - // Pack permissions into GroupSettings.e_permissions for faster checking - iter = db_iterator(pc_group_db); - for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { - config_setting_t *permissions = group_settings->permissions; - int i, count = config_setting_length(permissions); - - for (i = 0; i < count; ++i) { - config_setting_t *perm = config_setting_get_elem(permissions, i); - const char *name = config_setting_name(perm); - int val = config_setting_get_bool(perm); - int j; - - if (val == 0) // does not have this permission - continue; - ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0); - group_settings->e_permissions |= pc_g_permission_name[j].permission; - } - } - dbi_destroy(iter); - } - - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' groups in '"CL_WHITE"%s"CL_RESET"'.\n", group_count, config_filename); - - - if ((pc_group_max = group_count)) { - DBIterator *iter = db_iterator(pc_group_db); - GroupSettings *group_settings = NULL; - int *group_ids = aMalloc(pc_group_max * sizeof(int)); - int i = 0; - for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { - group_ids[i++] = group_settings->id; - } - - atcommand_db_load_groups(group_ids); - - aFree(group_ids); - - dbi_destroy(iter); - } + config_setting_t *groups = NULL; + const char *config_filename = "conf/groups.conf"; // FIXME hardcoded name + int group_count = 0; + + if (conf_read_file(&pc_group_config, config_filename)) + return; + + groups = config_lookup(&pc_group_config, "groups"); + + if (groups != NULL) { + GroupSettings *group_settings = NULL; + DBIterator *iter = NULL; + int i, loop = 0; + + group_count = config_setting_length(groups); + for (i = 0; i < group_count; ++i) { + int id = 0, level = 0; + const char *groupname = NULL; + int log_commands = 0; + config_setting_t *group = config_setting_get_elem(groups, i); + + if (!config_setting_lookup_int(group, "id", &id)) { + ShowConfigWarning(group, "pc_groups:read_config: \"groups\" list member #%d has undefined id, removing...", i); + config_setting_remove_elem(groups, i); + --i; + --group_count; + continue; + } + + if (id2group(id) != NULL) { + ShowConfigWarning(group, "pc_groups:read_config: duplicate group id %d, removing...", i); + config_setting_remove_elem(groups, i); + --i; + --group_count; + continue; + } + + config_setting_lookup_int(group, "level", &level); + config_setting_lookup_bool(group, "log_commands", &log_commands); + + if (!config_setting_lookup_string(group, "name", &groupname)) { + char temp[20]; + config_setting_t *name = NULL; + snprintf(temp, sizeof(temp), "Group %d", id); + if ((name = config_setting_add(group, "name", CONFIG_TYPE_STRING)) == NULL || + !config_setting_set_string(name, temp)) { + ShowError("pc_groups:read_config: failed to set missing group name, id=%d, skipping... (%s:%d)\n", + id, config_setting_source_file(group), config_setting_source_line(group)); + continue; + } + config_setting_lookup_string(group, "name", &groupname); // Retrieve the pointer + } + + if (name2group(groupname) != NULL) { + ShowConfigWarning(group, "pc_groups:read_config: duplicate group name %s, removing...", groupname); + config_setting_remove_elem(groups, i); + --i; + --group_count; + continue; + } + + CREATE(group_settings, GroupSettings, 1); + group_settings->id = id; + group_settings->level = level; + group_settings->name = groupname; + group_settings->log_commands = (bool)log_commands; + group_settings->inherit = config_setting_get_member(group, "inherit"); + group_settings->commands = config_setting_get_member(group, "commands"); + group_settings->permissions = config_setting_get_member(group, "permissions"); + group_settings->inheritance_done = false; + group_settings->root = group; + group_settings->group_pos = i; + + strdb_put(pc_groupname_db, groupname, group_settings); + idb_put(pc_group_db, id, group_settings); + + } + group_count = config_setting_length(groups); // Save number of groups + + // Check if all commands and permissions exist + iter = db_iterator(pc_group_db); + for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { + config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions; + int count = 0, i; + + // Make sure there is "commands" group + if (commands == NULL) + commands = group_settings->commands = config_setting_add(group_settings->root, "commands", CONFIG_TYPE_GROUP); + count = config_setting_length(commands); + + for (i = 0; i < count; ++i) { + config_setting_t *command = config_setting_get_elem(commands, i); + const char *name = config_setting_name(command); + if (!atcommand_exists(name)) { + ShowConfigWarning(command, "pc_groups:read_config: non-existent command name '%s', removing...", name); + config_setting_remove(commands, name); + --i; + --count; + } + } + + // Make sure there is "permissions" group + if (permissions == NULL) + permissions = group_settings->permissions = config_setting_add(group_settings->root, "permissions", CONFIG_TYPE_GROUP); + count = config_setting_length(permissions); + + for(i = 0; i < count; ++i) { + config_setting_t *permission = config_setting_get_elem(permissions, i); + const char *name = config_setting_name(permission); + int j; + + ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0); + if (j == ARRAYLENGTH(pc_g_permission_name)) { + ShowConfigWarning(permission, "pc_groups:read_config: non-existent permission name '%s', removing...", name); + config_setting_remove(permissions, name); + --i; + --count; + } + } + } + dbi_destroy(iter); + + // Apply inheritance + i = 0; // counter for processed groups + while (i < group_count) { + iter = db_iterator(pc_group_db); + for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { + config_setting_t *inherit = NULL, + *commands = group_settings->commands, + *permissions = group_settings->permissions; + int j, inherit_count = 0, done = 0; + + if (group_settings->inheritance_done) // group already processed + continue; + + if ((inherit = group_settings->inherit) == NULL || + (inherit_count = config_setting_length(inherit)) <= 0) { // this group does not inherit from others + ++i; + group_settings->inheritance_done = true; + continue; + } + + for (j = 0; j < inherit_count; ++j) { + GroupSettings *inherited_group = NULL; + const char *groupname = config_setting_get_string_elem(inherit, j); + + if (groupname == NULL) { + ShowConfigWarning(inherit, "pc_groups:read_config: \"inherit\" array member #%d is not a name, removing...", j); + config_setting_remove_elem(inherit,j); + continue; + } + if ((inherited_group = name2group(groupname)) == NULL) { + ShowConfigWarning(inherit, "pc_groups:read_config: non-existent group name \"%s\", removing...", groupname); + config_setting_remove_elem(inherit,j); + continue; + } + if (!inherited_group->inheritance_done) + continue; // we need to do that group first + + // Copy settings (commands/permissions) that are not defined yet + if (inherited_group->commands != NULL) { + int i = 0, commands_count = config_setting_length(inherited_group->commands); + for (i = 0; i < commands_count; ++i) + config_setting_copy(commands, config_setting_get_elem(inherited_group->commands, i)); + } + + if (inherited_group->permissions != NULL) { + int i = 0, permissions_count = config_setting_length(inherited_group->permissions); + for (i = 0; i < permissions_count; ++i) + config_setting_copy(permissions, config_setting_get_elem(inherited_group->permissions, i)); + } + + ++done; // copied commands and permissions from one of inherited groups + } + + if (done == inherit_count) { // copied commands from all of inherited groups + ++i; + group_settings->inheritance_done = true; // we're done with this group + } + } + dbi_destroy(iter); + + if (++loop > group_count) { + ShowWarning("pc_groups:read_config: Could not process inheritance rules, check your config '%s' for cycles...\n", + config_filename); + break; + } + } // while(i < group_count) + + // Pack permissions into GroupSettings.e_permissions for faster checking + iter = db_iterator(pc_group_db); + for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { + config_setting_t *permissions = group_settings->permissions; + int i, count = config_setting_length(permissions); + + for (i = 0; i < count; ++i) { + config_setting_t *perm = config_setting_get_elem(permissions, i); + const char *name = config_setting_name(perm); + int val = config_setting_get_bool(perm); + int j; + + if (val == 0) // does not have this permission + continue; + ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0); + group_settings->e_permissions |= pc_g_permission_name[j].permission; + } + } + dbi_destroy(iter); + } + + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' groups in '"CL_WHITE"%s"CL_RESET"'.\n", group_count, config_filename); + + + if( ( pc_group_max = group_count ) ) { + DBIterator *iter = db_iterator(pc_group_db); + GroupSettings *group_settings = NULL; + int* group_ids = aMalloc( pc_group_max * sizeof(int) ); + int i = 0; + for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { + group_ids[i++] = group_settings->id; + } + + atcommand_db_load_groups(group_ids); + + aFree(group_ids); + + dbi_destroy(iter); + } } /** @@ -298,7 +298,7 @@ static void read_config(void) */ static void destroy_config(void) { - config_destroy(&pc_group_config); + config_destroy(&pc_group_config); } /** @@ -309,10 +309,7 @@ static void destroy_config(void) * COMMAND_ATCOMMAND (1) being index 0, COMMAND_CHARCOMMAND (2) being index 1. * @private */ -static inline int AtCommandType2idx(AtCommandType type) -{ - return (type-1); -} +static inline int AtCommandType2idx(AtCommandType type) { return (type-1); } /** * Checks if player group can use @/#command @@ -322,45 +319,44 @@ static inline int AtCommandType2idx(AtCommandType type) */ bool pc_group_can_use_command(int group_id, const char *command, AtCommandType type) { - int result = 0; - config_setting_t *commands = NULL; - GroupSettings *group = NULL; - - if (pc_group_has_permission(group_id, PC_PERM_USE_ALL_COMMANDS)) - return true; - - if ((group = id2group(group_id)) == NULL) - return false; - - commands = group->commands; - if (commands != NULL) { - config_setting_t *cmd = NULL; - - // <commandname> : <bool> (only atcommand) - if (type == COMMAND_ATCOMMAND && config_setting_lookup_bool(commands, command, &result)) - return (bool)result; - - // <commandname> : [ <bool>, <bool> ] ([ atcommand, charcommand ]) - if ((cmd = config_setting_get_member(commands, command)) != NULL && - config_setting_is_aggregate(cmd) && config_setting_length(cmd) == 2) - return (bool)config_setting_get_bool_elem(cmd, AtCommandType2idx(type)); - } - return false; + int result = 0; + config_setting_t *commands = NULL; + GroupSettings *group = NULL; + + if (pc_group_has_permission(group_id, PC_PERM_USE_ALL_COMMANDS)) + return true; + + if ((group = id2group(group_id)) == NULL) + return false; + + commands = group->commands; + if (commands != NULL) { + config_setting_t *cmd = NULL; + + // <commandname> : <bool> (only atcommand) + if (type == COMMAND_ATCOMMAND && config_setting_lookup_bool(commands, command, &result)) + return (bool)result; + + // <commandname> : [ <bool>, <bool> ] ([ atcommand, charcommand ]) + if ((cmd = config_setting_get_member(commands, command)) != NULL && + config_setting_is_aggregate(cmd) && config_setting_length(cmd) == 2) + return (bool)config_setting_get_bool_elem(cmd, AtCommandType2idx(type)); + } + return false; } -void pc_group_pc_load(struct map_session_data *sd) -{ - GroupSettings *group = NULL; - if ((group = id2group(sd->group_id)) == NULL) { - ShowWarning("pc_group_pc_load: %s (AID:%d) logged in with unknown group id (%d)! kicking...\n", - sd->status.name, - sd->status.account_id, - sd->group_id); - set_eof(sd->fd); - return; - } - sd->permissions = group->e_permissions; - sd->group_pos = group->group_pos; - sd->group_level = group->level; +void pc_group_pc_load(struct map_session_data * sd) { + GroupSettings *group = NULL; + if ((group = id2group(sd->group_id)) == NULL) { + ShowWarning("pc_group_pc_load: %s (AID:%d) logged in with unknown group id (%d)! kicking...\n", + sd->status.name, + sd->status.account_id, + sd->group_id); + set_eof(sd->fd); + return; + } + sd->permissions = group->e_permissions; + sd->group_pos = group->group_pos; + sd->group_level = group->level; } /** * Checks if player group has a permission @@ -369,10 +365,10 @@ void pc_group_pc_load(struct map_session_data *sd) */ bool pc_group_has_permission(int group_id, int permission) { - GroupSettings *group = NULL; - if ((group = id2group(group_id)) == NULL) - return false; - return ((group->e_permissions&permission) != 0); + GroupSettings *group = NULL; + if ((group = id2group(group_id)) == NULL) + return false; + return ((group->e_permissions&permission) != 0); } /** @@ -381,10 +377,10 @@ bool pc_group_has_permission(int group_id, int permission) */ bool pc_group_should_log_commands(int group_id) { - GroupSettings *group = NULL; - if ((group = id2group(group_id)) == NULL) - return false; - return group->log_commands; + GroupSettings *group = NULL; + if ((group = id2group(group_id)) == NULL) + return false; + return group->log_commands; } /** @@ -394,7 +390,7 @@ bool pc_group_should_log_commands(int group_id) */ bool pc_group_exists(int group_id) { - return idb_exists(pc_group_db, group_id); + return idb_exists(pc_group_db, group_id); } /** @@ -403,12 +399,12 @@ bool pc_group_exists(int group_id) * @return group name * @public */ -const char *pc_group_id2name(int group_id) +const char* pc_group_id2name(int group_id) { - GroupSettings *group = id2group(group_id); - if (group == NULL) - return "Non-existent group!"; - return group->name; + GroupSettings *group = id2group(group_id); + if (group == NULL) + return "Non-existent group!"; + return group->name; } /** @@ -419,10 +415,10 @@ const char *pc_group_id2name(int group_id) */ int pc_group_id2level(int group_id) { - GroupSettings *group = id2group(group_id); - if (group == NULL) - return 0; - return group->level; + GroupSettings *group = id2group(group_id); + if (group == NULL) + return 0; + return group->level; } /** @@ -431,9 +427,9 @@ int pc_group_id2level(int group_id) */ void do_init_pc_groups(void) { - pc_group_db = idb_alloc(DB_OPT_RELEASE_DATA); - pc_groupname_db = stridb_alloc(DB_OPT_DUP_KEY, 0); - read_config(); + pc_group_db = idb_alloc(DB_OPT_RELEASE_DATA); + pc_groupname_db = stridb_alloc(DB_OPT_DUP_KEY, 0); + read_config(); } /** @@ -442,11 +438,11 @@ void do_init_pc_groups(void) */ void do_final_pc_groups(void) { - if (pc_group_db != NULL) - db_destroy(pc_group_db); - if (pc_groupname_db != NULL) - db_destroy(pc_groupname_db); - destroy_config(); + if (pc_group_db != NULL) + db_destroy(pc_group_db); + if (pc_groupname_db != NULL ) + db_destroy(pc_groupname_db); + destroy_config(); } /** @@ -454,20 +450,19 @@ void do_final_pc_groups(void) * Used in @reloadatcommand * @public */ -void pc_groups_reload(void) -{ - struct map_session_data *sd = NULL; - struct s_mapiterator *iter = NULL; - - do_final_pc_groups(); - do_init_pc_groups(); - - /* refresh online users permissions */ - iter = mapit_getallusers(); - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) { - pc_group_pc_load(sd); - } - mapit_free(iter); - - +void pc_groups_reload(void) { + struct map_session_data* sd = NULL; + struct s_mapiterator* iter = NULL; + + do_final_pc_groups(); + do_init_pc_groups(); + + /* refresh online users permissions */ + iter = mapit_getallusers(); + for (sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) { + pc_group_pc_load(sd); + } + mapit_free(iter); + + } diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h index 6bce4fbf8..65c48935a 100644 --- a/src/map/pc_groups.h +++ b/src/map/pc_groups.h @@ -12,7 +12,7 @@ bool pc_group_exists(int group_id); bool pc_group_can_use_command(int group_id, const char *command, AtCommandType type); bool pc_group_has_permission(int group_id, int permission); bool pc_group_should_log_commands(int group_id); -const char *pc_group_id2name(int group_id); +const char* pc_group_id2name(int group_id); int pc_group_id2level(int group_id); void pc_group_pc_load(struct map_session_data *); @@ -21,55 +21,55 @@ void do_final_pc_groups(void); void pc_groups_reload(void); enum e_pc_permission { - PC_PERM_NONE = 0, - PC_PERM_TRADE = 0x000001, - PC_PERM_PARTY = 0x000002, - PC_PERM_ALL_SKILL = 0x000004, - PC_PERM_USE_ALL_EQUIPMENT = 0x000008, - PC_PERM_SKILL_UNCONDITIONAL = 0x000010, - PC_PERM_JOIN_ALL_CHAT = 0x000020, - PC_PERM_NO_CHAT_KICK = 0x000040, - PC_PERM_HIDE_SESSION = 0x000080, - PC_PERM_WHO_DISPLAY_AID = 0x000100, - PC_PERM_RECEIVE_HACK_INFO = 0x000200, - PC_PERM_WARP_ANYWHERE = 0x000400, - PC_PERM_VIEW_HPMETER = 0x000800, - PC_PERM_VIEW_EQUIPMENT = 0x001000, - PC_PERM_USE_CHECK = 0x002000, - PC_PERM_USE_CHANGEMAPTYPE = 0x004000, - PC_PERM_USE_ALL_COMMANDS = 0x008000, - PC_PERM_RECEIVE_REQUESTS = 0x010000, - PC_PERM_SHOW_BOSS = 0x020000, - PC_PERM_DISABLE_PVM = 0x040000, - PC_PERM_DISABLE_PVP = 0x080000, - PC_PERM_DISABLE_CMD_DEAD = 0x100000, + PC_PERM_NONE = 0, + PC_PERM_TRADE = 0x000001, + PC_PERM_PARTY = 0x000002, + PC_PERM_ALL_SKILL = 0x000004, + PC_PERM_USE_ALL_EQUIPMENT = 0x000008, + PC_PERM_SKILL_UNCONDITIONAL = 0x000010, + PC_PERM_JOIN_ALL_CHAT = 0x000020, + PC_PERM_NO_CHAT_KICK = 0x000040, + PC_PERM_HIDE_SESSION = 0x000080, + PC_PERM_WHO_DISPLAY_AID = 0x000100, + PC_PERM_RECEIVE_HACK_INFO = 0x000200, + PC_PERM_WARP_ANYWHERE = 0x000400, + PC_PERM_VIEW_HPMETER = 0x000800, + PC_PERM_VIEW_EQUIPMENT = 0x001000, + PC_PERM_USE_CHECK = 0x002000, + PC_PERM_USE_CHANGEMAPTYPE = 0x004000, + PC_PERM_USE_ALL_COMMANDS = 0x008000, + PC_PERM_RECEIVE_REQUESTS = 0x010000, + PC_PERM_SHOW_BOSS = 0x020000, + PC_PERM_DISABLE_PVM = 0x040000, + PC_PERM_DISABLE_PVP = 0x080000, + PC_PERM_DISABLE_CMD_DEAD = 0x100000, }; static const struct { - const char *name; - unsigned int permission; + const char *name; + unsigned int permission; } pc_g_permission_name[] = { - { "can_trade", PC_PERM_TRADE }, - { "can_party", PC_PERM_PARTY }, - { "all_skill", PC_PERM_ALL_SKILL }, - { "all_equipment", PC_PERM_USE_ALL_EQUIPMENT }, - { "skill_unconditional", PC_PERM_SKILL_UNCONDITIONAL }, - { "join_chat", PC_PERM_JOIN_ALL_CHAT }, - { "kick_chat", PC_PERM_NO_CHAT_KICK }, - { "hide_session", PC_PERM_HIDE_SESSION }, - { "who_display_aid", PC_PERM_WHO_DISPLAY_AID }, - { "hack_info", PC_PERM_RECEIVE_HACK_INFO }, - { "any_warp", PC_PERM_WARP_ANYWHERE }, - { "view_hpmeter", PC_PERM_VIEW_HPMETER }, - { "view_equipment", PC_PERM_VIEW_EQUIPMENT }, - { "use_check", PC_PERM_USE_CHECK }, - { "use_changemaptype", PC_PERM_USE_CHANGEMAPTYPE }, - { "all_commands", PC_PERM_USE_ALL_COMMANDS }, - { "receive_requests", PC_PERM_RECEIVE_REQUESTS }, - { "show_bossmobs", PC_PERM_SHOW_BOSS }, - { "disable_pvm", PC_PERM_DISABLE_PVM }, - { "disable_pvp", PC_PERM_DISABLE_PVP }, - { "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD }, + { "can_trade", PC_PERM_TRADE }, + { "can_party", PC_PERM_PARTY }, + { "all_skill", PC_PERM_ALL_SKILL }, + { "all_equipment", PC_PERM_USE_ALL_EQUIPMENT }, + { "skill_unconditional", PC_PERM_SKILL_UNCONDITIONAL }, + { "join_chat", PC_PERM_JOIN_ALL_CHAT }, + { "kick_chat", PC_PERM_NO_CHAT_KICK }, + { "hide_session", PC_PERM_HIDE_SESSION }, + { "who_display_aid", PC_PERM_WHO_DISPLAY_AID }, + { "hack_info", PC_PERM_RECEIVE_HACK_INFO }, + { "any_warp", PC_PERM_WARP_ANYWHERE }, + { "view_hpmeter", PC_PERM_VIEW_HPMETER }, + { "view_equipment", PC_PERM_VIEW_EQUIPMENT }, + { "use_check", PC_PERM_USE_CHECK }, + { "use_changemaptype", PC_PERM_USE_CHANGEMAPTYPE }, + { "all_commands", PC_PERM_USE_ALL_COMMANDS }, + { "receive_requests", PC_PERM_RECEIVE_REQUESTS }, + { "show_bossmobs", PC_PERM_SHOW_BOSS }, + { "disable_pvm", PC_PERM_DISABLE_PVM }, + { "disable_pvp", PC_PERM_DISABLE_PVP }, + { "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD }, }; #endif // _PC_GROUPS_H_ diff --git a/src/map/pet.c b/src/map/pet.c index daee6600a..5c7f15151 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -43,56 +43,56 @@ static struct eri *item_drop_list_ers; int pet_hungry_val(struct pet_data *pd) { - nullpo_ret(pd); - - if (pd->pet.hungry > 90) - return 4; - else if (pd->pet.hungry > 75) - return 3; - else if (pd->pet.hungry > 25) - return 2; - else if (pd->pet.hungry > 10) - return 1; - else - return 0; + nullpo_ret(pd); + + if(pd->pet.hungry > 90) + return 4; + else if(pd->pet.hungry > 75) + return 3; + else if(pd->pet.hungry > 25) + return 2; + else if(pd->pet.hungry > 10) + return 1; + else + return 0; } void pet_set_intimate(struct pet_data *pd, int value) { - int intimate; - struct map_session_data *sd; + int intimate; + struct map_session_data *sd; - nullpo_retv(pd); - intimate = pd->pet.intimate; - sd = pd->msd; + nullpo_retv(pd); + intimate = pd->pet.intimate; + sd = pd->msd; - pd->pet.intimate = value; - if ((intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly)) - status_calc_pc(sd,0); + pd->pet.intimate = value; + if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) ) + status_calc_pc(sd,0); } int pet_create_egg(struct map_session_data *sd, int item_id) { - int pet_id = search_petDB_index(item_id, PET_EGG); - if (pet_id < 0) return 0; //No pet egg here. - sd->catch_target_class = pet_db[pet_id].class_; - intif_create_pet(sd->status.account_id, 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); - return 1; + int pet_id = search_petDB_index(item_id, PET_EGG); + if (pet_id < 0) return 0; //No pet egg here. + sd->catch_target_class = pet_db[pet_id].class_; + intif_create_pet(sd->status.account_id, 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); + return 1; } int pet_unlocktarget(struct pet_data *pd) { - nullpo_ret(pd); + nullpo_ret(pd); - pd->target_id=0; - pet_stop_attack(pd); - pet_stop_walking(pd,1); - return 0; + pd->target_id=0; + pet_stop_attack(pd); + pet_stop_walking(pd,1); + return 0; } /*========================================== @@ -100,484 +100,480 @@ int pet_unlocktarget(struct pet_data *pd) *------------------------------------------*/ int pet_attackskill(struct pet_data *pd, int target_id) { - struct block_list *bl; - - if (!battle_config.pet_status_support || !pd->a_skill || - (battle_config.pet_equip_required && !pd->pet.equip)) - return 0; - - if (DIFF_TICK(pd->ud.canact_tick, gettick()) > 0) - return 0; - - if (rnd()%100 < (pd->a_skill->rate +pd->pet.intimate*pd->a_skill->bonusrate/1000)) { - //Skotlex: Use pet's skill - int inf; - - bl=map_id2bl(target_id); - if (bl == NULL || pd->bl.m != bl->m || bl->prev == NULL || status_isdead(bl) || - !check_distance_bl(&pd->bl, bl, pd->db->range3)) - return 0; - - inf = skill_get_inf(pd->a_skill->id); - if (inf & INF_GROUND_SKILL) - unit_skilluse_pos(&pd->bl, bl->x, bl->y, pd->a_skill->id, pd->a_skill->lv); - else //Offensive self skill? Could be stuff like GX. - unit_skilluse_id(&pd->bl,(inf&INF_SELF_SKILL?pd->bl.id:bl->id), pd->a_skill->id, pd->a_skill->lv); - return 1; //Skill invoked. - } - return 0; + struct block_list *bl; + + if (!battle_config.pet_status_support || !pd->a_skill || + (battle_config.pet_equip_required && !pd->pet.equip)) + return 0; + + if (DIFF_TICK(pd->ud.canact_tick, gettick()) > 0) + return 0; + + if (rnd()%100 < (pd->a_skill->rate +pd->pet.intimate*pd->a_skill->bonusrate/1000)) + { //Skotlex: Use pet's skill + int inf; + + bl=map_id2bl(target_id); + if(bl == NULL || pd->bl.m != bl->m || bl->prev == NULL || status_isdead(bl) || + !check_distance_bl(&pd->bl, bl, pd->db->range3)) + return 0; + + inf = skill_get_inf(pd->a_skill->id); + if (inf & INF_GROUND_SKILL) + unit_skilluse_pos(&pd->bl, bl->x, bl->y, pd->a_skill->id, pd->a_skill->lv); + else //Offensive self skill? Could be stuff like GX. + unit_skilluse_id(&pd->bl,(inf&INF_SELF_SKILL?pd->bl.id:bl->id), pd->a_skill->id, pd->a_skill->lv); + return 1; //Skill invoked. + } + return 0; } int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type) { - struct pet_data *pd; - int rate; - - pd = sd->pd; - - Assert((pd->msd == 0) || (pd->msd->pd == pd)); - - if (bl == NULL || bl->type != BL_MOB || bl->prev == NULL || - pd->pet.intimate < battle_config.pet_support_min_friendly || - pd->pet.hungry < 1 || - pd->pet.class_ == status_get_class(bl)) - return 0; - - if (pd->bl.m != bl->m || - !check_distance_bl(&pd->bl, bl, pd->db->range2)) - return 0; - - if (!status_check_skilluse(&pd->bl, bl, 0, 0)) - return 0; - - if (!type) { - rate = pd->petDB->attack_rate; - rate = rate * pd->rate_fix/1000; - if (pd->petDB->attack_rate > 0 && rate <= 0) - rate = 1; - } else { - rate = pd->petDB->defence_attack_rate; - rate = rate * pd->rate_fix/1000; - if (pd->petDB->defence_attack_rate > 0 && rate <= 0) - rate = 1; - } - if (rnd()%10000 < rate) { - if (pd->target_id == 0 || rnd()%10000 < pd->petDB->change_target_rate) - pd->target_id = bl->id; - } - - return 0; + struct pet_data *pd; + int rate; + + pd = sd->pd; + + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + + if(bl == NULL || bl->type != BL_MOB || bl->prev == NULL || + pd->pet.intimate < battle_config.pet_support_min_friendly || + pd->pet.hungry < 1 || + pd->pet.class_ == status_get_class(bl)) + return 0; + + if(pd->bl.m != bl->m || + !check_distance_bl(&pd->bl, bl, pd->db->range2)) + return 0; + + if (!status_check_skilluse(&pd->bl, bl, 0, 0)) + return 0; + + if(!type) { + rate = pd->petDB->attack_rate; + rate = rate * pd->rate_fix/1000; + if(pd->petDB->attack_rate > 0 && rate <= 0) + rate = 1; + } else { + rate = pd->petDB->defence_attack_rate; + rate = rate * pd->rate_fix/1000; + if(pd->petDB->defence_attack_rate > 0 && rate <= 0) + rate = 1; + } + if(rnd()%10000 < rate) + { + if(pd->target_id == 0 || rnd()%10000 < pd->petDB->change_target_rate) + pd->target_id = bl->id; + } + + return 0; } /*========================================== * Pet SC Check [Skotlex] *------------------------------------------*/ int pet_sc_check(struct map_session_data *sd, int type) { - struct pet_data *pd; + struct pet_data *pd; - nullpo_ret(sd); - pd = sd->pd; + nullpo_ret(sd); + pd = sd->pd; - if (pd == NULL - || (battle_config.pet_equip_required && pd->pet.equip == 0) - || pd->recovery == NULL - || pd->recovery->timer != INVALID_TIMER - || pd->recovery->type != type) - return 1; + if( pd == NULL + || (battle_config.pet_equip_required && pd->pet.equip == 0) + || pd->recovery == NULL + || pd->recovery->timer != INVALID_TIMER + || pd->recovery->type != type ) + return 1; - pd->recovery->timer = add_timer(gettick()+pd->recovery->delay*1000,pet_recovery_timer,sd->bl.id,0); - - return 0; + pd->recovery->timer = add_timer(gettick()+pd->recovery->delay*1000,pet_recovery_timer,sd->bl.id,0); + + return 0; } static int pet_hungry(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd; - struct pet_data *pd; - int interval; - - sd=map_id2sd(id); - if (!sd) - return 1; - - if (!sd->status.pet_id || !sd->pd) - return 1; - - pd = sd->pd; - if (pd->pet_hungry_timer != tid) { - ShowError("pet_hungry_timer %d != %d\n",pd->pet_hungry_timer,tid); - return 0; - } - pd->pet_hungry_timer = INVALID_TIMER; - - if (pd->pet.intimate <= 0) - return 1; //You lost the pet already, the rest is irrelevant. - - pd->pet.hungry--; - if (pd->pet.hungry < 0) { - pet_stop_attack(pd); - pd->pet.hungry = 0; - pet_set_intimate(pd, pd->pet.intimate - battle_config.pet_hungry_friendly_decrease); - if (pd->pet.intimate <= 0) { - pd->pet.intimate = 0; - pd->status.speed = pd->db->status.speed; - } - status_calc_pet(pd, 0); - clif_send_petdata(sd,pd,1,pd->pet.intimate); - } - clif_send_petdata(sd,pd,2,pd->pet.hungry); - - if (battle_config.pet_hungry_delay_rate != 100) - interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100; - else - interval = pd->petDB->hungry_delay; - if (interval <= 0) - interval = 1; - pd->pet_hungry_timer = add_timer(tick+interval,pet_hungry,sd->bl.id,0); - - return 0; + struct map_session_data *sd; + struct pet_data *pd; + int interval; + + sd=map_id2sd(id); + if(!sd) + return 1; + + if(!sd->status.pet_id || !sd->pd) + return 1; + + pd = sd->pd; + if(pd->pet_hungry_timer != tid){ + ShowError("pet_hungry_timer %d != %d\n",pd->pet_hungry_timer,tid); + return 0; + } + pd->pet_hungry_timer = INVALID_TIMER; + + if (pd->pet.intimate <= 0) + return 1; //You lost the pet already, the rest is irrelevant. + + pd->pet.hungry--; + if( pd->pet.hungry < 0 ) + { + pet_stop_attack(pd); + pd->pet.hungry = 0; + pet_set_intimate(pd, pd->pet.intimate - battle_config.pet_hungry_friendly_decrease); + if( pd->pet.intimate <= 0 ) + { + pd->pet.intimate = 0; + pd->status.speed = pd->db->status.speed; + } + status_calc_pet(pd, 0); + clif_send_petdata(sd,pd,1,pd->pet.intimate); + } + clif_send_petdata(sd,pd,2,pd->pet.hungry); + + if(battle_config.pet_hungry_delay_rate != 100) + interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100; + else + interval = pd->petDB->hungry_delay; + if(interval <= 0) + interval = 1; + pd->pet_hungry_timer = add_timer(tick+interval,pet_hungry,sd->bl.id,0); + + return 0; } int search_petDB_index(int key,int type) { - int i; - - for (i = 0; i < MAX_PET_DB; i++) { - if (pet_db[i].class_ <= 0) - continue; - switch (type) { - case PET_CLASS: - if (pet_db[i].class_ == key) return i; - break; - case PET_CATCH: - if (pet_db[i].itemID == key) return i; - break; - case PET_EGG: - if (pet_db[i].EggID == key) return i; - break; - case PET_EQUIP: - if (pet_db[i].AcceID == key) return i; - break; - case PET_FOOD: - if (pet_db[i].FoodID == key) return i; - break; - default: - return -1; - } - } - return -1; + int i; + + for( i = 0; i < MAX_PET_DB; i++ ) + { + if(pet_db[i].class_ <= 0) + continue; + switch(type) { + case PET_CLASS: if(pet_db[i].class_ == key) return i; break; + case PET_CATCH: if(pet_db[i].itemID == key) return i; break; + case PET_EGG: if(pet_db[i].EggID == key) return i; break; + case PET_EQUIP: if(pet_db[i].AcceID == key) return i; break; + case PET_FOOD: if(pet_db[i].FoodID == key) return i; break; + default: + return -1; + } + } + return -1; } int pet_hungry_timer_delete(struct pet_data *pd) { - nullpo_ret(pd); - if (pd->pet_hungry_timer != INVALID_TIMER) { - delete_timer(pd->pet_hungry_timer,pet_hungry); - pd->pet_hungry_timer = INVALID_TIMER; - } + nullpo_ret(pd); + if(pd->pet_hungry_timer != INVALID_TIMER) { + delete_timer(pd->pet_hungry_timer,pet_hungry); + pd->pet_hungry_timer = INVALID_TIMER; + } - return 1; + return 1; } static int pet_performance(struct map_session_data *sd, struct pet_data *pd) { - int val; - - if (pd->pet.intimate > 900) - val = (pd->petDB->s_perfor > 0)? 4:3; - else if (pd->pet.intimate > 750) //TODO: this is way too high - val = 2; - else - val = 1; - - pet_stop_walking(pd,2000<<8); - clif_pet_performance(pd, rnd()%val + 1); - pet_lootitem_drop(pd,NULL); - return 1; + int val; + + if (pd->pet.intimate > 900) + val = (pd->petDB->s_perfor > 0)? 4:3; + else if(pd->pet.intimate > 750) //TODO: this is way too high + val = 2; + else + val = 1; + + pet_stop_walking(pd,2000<<8); + clif_pet_performance(pd, rnd()%val + 1); + pet_lootitem_drop(pd,NULL); + return 1; } static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd) { - struct item tmp_item; - int flag; - - pet_lootitem_drop(pd,sd); - memset(&tmp_item,0,sizeof(tmp_item)); - tmp_item.nameid = pd->petDB->EggID; - tmp_item.identify = 1; - tmp_item.card[0] = CARD0_PET; - tmp_item.card[1] = GetWord(pd->pet.pet_id,0); - tmp_item.card[2] = GetWord(pd->pet.pet_id,1); - tmp_item.card[3] = pd->pet.rename_flag; - if ((flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) { - clif_additem(sd,0,0,flag); - map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - pd->pet.incuvate = 1; - unit_free(&pd->bl,CLR_OUTSIGHT); - - status_calc_pc(sd,0); - sd->status.pet_id = 0; - - return 1; + struct item tmp_item; + int flag; + + pet_lootitem_drop(pd,sd); + memset(&tmp_item,0,sizeof(tmp_item)); + tmp_item.nameid = pd->petDB->EggID; + tmp_item.identify = 1; + tmp_item.card[0] = CARD0_PET; + tmp_item.card[1] = GetWord(pd->pet.pet_id,0); + tmp_item.card[2] = GetWord(pd->pet.pet_id,1); + tmp_item.card[3] = pd->pet.rename_flag; + if((flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) { + clif_additem(sd,0,0,flag); + map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + pd->pet.incuvate = 1; + unit_free(&pd->bl,CLR_OUTSIGHT); + + status_calc_pc(sd,0); + sd->status.pet_id = 0; + + return 1; } int pet_data_init(struct map_session_data *sd, struct s_pet *pet) { - struct pet_data *pd; - int i=0,interval=0; - - nullpo_retr(1, sd); - - Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); - - if (sd->status.account_id != pet->account_id || sd->status.char_id != pet->char_id) { - sd->status.pet_id = 0; - return 1; - } - if (sd->status.pet_id != pet->pet_id) { - if (sd->status.pet_id) { - //Wrong pet?? Set incuvate to no and send it back for saving. - pet->incuvate = 1; - intif_save_petdata(sd->status.account_id,pet); - sd->status.pet_id = 0; - return 1; - } - //The pet_id value was lost? odd... restore it. - sd->status.pet_id = pet->pet_id; - } - - i = search_petDB_index(pet->class_,PET_CLASS); - if (i < 0) { - sd->status.pet_id = 0; - return 1; - } - sd->pd = pd = (struct pet_data *)aCalloc(1,sizeof(struct pet_data)); - pd->bl.type = BL_PET; - pd->bl.id = npc_get_new_npc_id(); - - pd->msd = sd; - pd->petDB = &pet_db[i]; - pd->db = mob_db(pet->class_); - memcpy(&pd->pet, pet, sizeof(struct s_pet)); - status_set_viewdata(&pd->bl, pet->class_); - unit_dataset(&pd->bl); - pd->ud.dir = sd->ud.dir; - - pd->bl.m = sd->bl.m; - pd->bl.x = sd->bl.x; - pd->bl.y = sd->bl.y; - unit_calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir); - pd->bl.x = pd->ud.to_x; - pd->bl.y = pd->ud.to_y; - - map_addiddb(&pd->bl); - status_calc_pet(pd,1); - - pd->last_thinktime = gettick(); - pd->state.skillbonus = 0; - if (battle_config.pet_status_support) - run_script(pet_db[i].pet_script,0,sd->bl.id,0); - if (pd->petDB && pd->petDB->equip_script) - status_calc_pc(sd,0); - - if (battle_config.pet_hungry_delay_rate != 100) - interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100; - else - interval = pd->petDB->hungry_delay; - if (interval <= 0) - interval = 1; - pd->pet_hungry_timer = add_timer(gettick() + interval, pet_hungry, sd->bl.id, 0); - return 0; + struct pet_data *pd; + int i=0,interval=0; + + nullpo_retr(1, sd); + + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + + if(sd->status.account_id != pet->account_id || sd->status.char_id != pet->char_id) { + sd->status.pet_id = 0; + return 1; + } + if (sd->status.pet_id != pet->pet_id) { + if (sd->status.pet_id) { + //Wrong pet?? Set incuvate to no and send it back for saving. + pet->incuvate = 1; + intif_save_petdata(sd->status.account_id,pet); + sd->status.pet_id = 0; + return 1; + } + //The pet_id value was lost? odd... restore it. + sd->status.pet_id = pet->pet_id; + } + + i = search_petDB_index(pet->class_,PET_CLASS); + if(i < 0) { + sd->status.pet_id = 0; + return 1; + } + sd->pd = pd = (struct pet_data *)aCalloc(1,sizeof(struct pet_data)); + pd->bl.type = BL_PET; + pd->bl.id = npc_get_new_npc_id(); + + pd->msd = sd; + pd->petDB = &pet_db[i]; + pd->db = mob_db(pet->class_); + memcpy(&pd->pet, pet, sizeof(struct s_pet)); + status_set_viewdata(&pd->bl, pet->class_); + unit_dataset(&pd->bl); + pd->ud.dir = sd->ud.dir; + + pd->bl.m = sd->bl.m; + pd->bl.x = sd->bl.x; + pd->bl.y = sd->bl.y; + unit_calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir); + pd->bl.x = pd->ud.to_x; + pd->bl.y = pd->ud.to_y; + + map_addiddb(&pd->bl); + status_calc_pet(pd,1); + + pd->last_thinktime = gettick(); + pd->state.skillbonus = 0; + if( battle_config.pet_status_support ) + run_script(pet_db[i].pet_script,0,sd->bl.id,0); + if( pd->petDB && pd->petDB->equip_script ) + status_calc_pc(sd,0); + + if( battle_config.pet_hungry_delay_rate != 100 ) + interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100; + else + interval = pd->petDB->hungry_delay; + if( interval <= 0 ) + interval = 1; + pd->pet_hungry_timer = add_timer(gettick() + interval, pet_hungry, sd->bl.id, 0); + return 0; } int pet_birth_process(struct map_session_data *sd, struct s_pet *pet) { - nullpo_retr(1, sd); - - Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); - - if (sd->status.pet_id && pet->incuvate == 1) { - sd->status.pet_id = 0; - return 1; - } - - pet->incuvate = 0; - pet->account_id = sd->status.account_id; - pet->char_id = sd->status.char_id; - sd->status.pet_id = pet->pet_id; - if (pet_data_init(sd, pet)) { - sd->status.pet_id = 0; - return 1; - } - - intif_save_petdata(sd->status.account_id,pet); - if (save_settings&8) - chrif_save(sd,0); //is it REALLY Needed to save the char for hatching a pet? [Skotlex] - - if (sd->bl.prev != NULL) { - map_addblock(&sd->pd->bl); - clif_spawn(&sd->pd->bl); - clif_send_petdata(sd,sd->pd, 0,0); - clif_send_petdata(sd,sd->pd, 5,battle_config.pet_hair_style); - clif_pet_equip_area(sd->pd); - clif_send_petstatus(sd); - } - Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); - - return 0; + nullpo_retr(1, sd); + + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + + if(sd->status.pet_id && pet->incuvate == 1) { + sd->status.pet_id = 0; + return 1; + } + + pet->incuvate = 0; + pet->account_id = sd->status.account_id; + pet->char_id = sd->status.char_id; + sd->status.pet_id = pet->pet_id; + if(pet_data_init(sd, pet)) { + sd->status.pet_id = 0; + return 1; + } + + intif_save_petdata(sd->status.account_id,pet); + if (save_settings&8) + chrif_save(sd,0); //is it REALLY Needed to save the char for hatching a pet? [Skotlex] + + if(sd->bl.prev != NULL) { + map_addblock(&sd->pd->bl); + clif_spawn(&sd->pd->bl); + clif_send_petdata(sd,sd->pd, 0,0); + clif_send_petdata(sd,sd->pd, 5,battle_config.pet_hair_style); + clif_pet_equip_area(sd->pd); + clif_send_petstatus(sd); + } + Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); + + return 0; } int pet_recv_petdata(int account_id,struct s_pet *p,int flag) { - struct map_session_data *sd; - - sd = map_id2sd(account_id); - if (sd == NULL) - return 1; - if (flag == 1) { - sd->status.pet_id = 0; - return 1; - } - if (p->incuvate == 1) { - int i; - //Delete egg from inventory. [Skotlex] - for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].card[0] == CARD0_PET && - p->pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])) - break; - } - if (i >= MAX_INVENTORY) { - ShowError("pet_recv_petdata: Hatching pet (%d:%s) aborted, couldn't find egg in inventory for removal!\n",p->pet_id, p->name); - sd->status.pet_id = 0; - return 1; - } - if (!pet_birth_process(sd,p)) //Pet hatched. Delete egg. - pc_delitem(sd,i,1,0,0,LOG_TYPE_OTHER); - } else { - pet_data_init(sd,p); - if (sd->pd && sd->bl.prev != NULL) { - map_addblock(&sd->pd->bl); - clif_spawn(&sd->pd->bl); - clif_send_petdata(sd,sd->pd,0,0); - clif_send_petdata(sd,sd->pd,5,battle_config.pet_hair_style); - clif_pet_equip_area(sd->pd); - clif_send_petstatus(sd); - } - } - - return 0; + struct map_session_data *sd; + + sd = map_id2sd(account_id); + if(sd == NULL) + return 1; + if(flag == 1) { + sd->status.pet_id = 0; + return 1; + } + if(p->incuvate == 1) { + int i; + //Delete egg from inventory. [Skotlex] + for (i = 0; i < MAX_INVENTORY; i++) { + if(sd->status.inventory[i].card[0] == CARD0_PET && + p->pet_id == MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])) + break; + } + if(i >= MAX_INVENTORY) { + ShowError("pet_recv_petdata: Hatching pet (%d:%s) aborted, couldn't find egg in inventory for removal!\n",p->pet_id, p->name); + sd->status.pet_id = 0; + return 1; + } + if (!pet_birth_process(sd,p)) //Pet hatched. Delete egg. + pc_delitem(sd,i,1,0,0,LOG_TYPE_OTHER); + } else { + pet_data_init(sd,p); + if(sd->pd && sd->bl.prev != NULL) { + map_addblock(&sd->pd->bl); + clif_spawn(&sd->pd->bl); + clif_send_petdata(sd,sd->pd,0,0); + clif_send_petdata(sd,sd->pd,5,battle_config.pet_hair_style); + clif_pet_equip_area(sd->pd); + clif_send_petstatus(sd); + } + } + + return 0; } int pet_select_egg(struct map_session_data *sd,short egg_index) { - nullpo_ret(sd); + nullpo_ret(sd); - if (egg_index < 0 || egg_index >= MAX_INVENTORY) - return 0; //Forged packet! + if(egg_index < 0 || egg_index >= MAX_INVENTORY) + return 0; //Forged packet! - if (sd->status.inventory[egg_index].card[0] == CARD0_PET) - intif_request_petdata(sd->status.account_id, sd->status.char_id, MakeDWord(sd->status.inventory[egg_index].card[1], sd->status.inventory[egg_index].card[2])); - else - ShowError("wrong egg item inventory %d\n",egg_index); + if(sd->status.inventory[egg_index].card[0] == CARD0_PET) + intif_request_petdata(sd->status.account_id, sd->status.char_id, MakeDWord(sd->status.inventory[egg_index].card[1], sd->status.inventory[egg_index].card[2]) ); + else + ShowError("wrong egg item inventory %d\n",egg_index); - return 0; + return 0; } int pet_catch_process1(struct map_session_data *sd,int target_class) { - nullpo_ret(sd); + nullpo_ret(sd); - sd->catch_target_class = target_class; - clif_catch_process(sd); + sd->catch_target_class = target_class; + clif_catch_process(sd); - return 0; + return 0; } -int pet_catch_process2(struct map_session_data *sd, int target_id) +int pet_catch_process2(struct map_session_data* sd, int target_id) { - struct mob_data *md; - int i = 0, pet_catch_rate = 0; - - nullpo_retr(1, sd); - - md = (struct mob_data *)map_id2bl(target_id); - if (!md || md->bl.type != BL_MOB || md->bl.prev == NULL) { - // Invalid inputs/state, abort capture. - clif_pet_roulette(sd,0); - sd->catch_target_class = -1; - sd->itemid = sd->itemindex = -1; - return 1; - } - - //FIXME: delete taming item here, if this was an item-invoked capture and the item was flagged as delay-consume [ultramage] - - i = search_petDB_index(md->class_,PET_CLASS); - //catch_target_class == 0 is used for universal lures (except bosses for now). [Skotlex] - if (sd->catch_target_class == 0 && !(md->status.mode&MD_BOSS)) - sd->catch_target_class = md->class_; - if (i < 0 || sd->catch_target_class != md->class_) { - clif_emotion(&md->bl, E_AG); //mob will do /ag if wrong lure is used on them. - clif_pet_roulette(sd,0); - sd->catch_target_class = -1; - return 1; - } - - pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - md->level)*30 + sd->battle_status.luk*20)*(200 - get_percentage(md->status.hp, md->status.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 (rnd()%10000 < pet_catch_rate) { - unit_remove_map(&md->bl,CLR_OUTSIGHT); - status_kill(&md->bl); - clif_pet_roulette(sd,1); - 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 { - clif_pet_roulette(sd,0); - sd->catch_target_class = -1; - } - - return 0; + struct mob_data* md; + int i = 0, pet_catch_rate = 0; + + nullpo_retr(1, sd); + + md = (struct mob_data*)map_id2bl(target_id); + if(!md || md->bl.type != BL_MOB || md->bl.prev == NULL) + { // Invalid inputs/state, abort capture. + clif_pet_roulette(sd,0); + sd->catch_target_class = -1; + sd->itemid = sd->itemindex = -1; + return 1; + } + + //FIXME: delete taming item here, if this was an item-invoked capture and the item was flagged as delay-consume [ultramage] + + i = search_petDB_index(md->class_,PET_CLASS); + //catch_target_class == 0 is used for universal lures (except bosses for now). [Skotlex] + if (sd->catch_target_class == 0 && !(md->status.mode&MD_BOSS)) + sd->catch_target_class = md->class_; + if(i < 0 || sd->catch_target_class != md->class_) { + clif_emotion(&md->bl, E_AG); //mob will do /ag if wrong lure is used on them. + clif_pet_roulette(sd,0); + sd->catch_target_class = -1; + return 1; + } + + pet_catch_rate = (pet_db[i].capture + (sd->status.base_level - md->level)*30 + sd->battle_status.luk*20)*(200 - get_percentage(md->status.hp, md->status.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(rnd()%10000 < pet_catch_rate) + { + unit_remove_map(&md->bl,CLR_OUTSIGHT); + status_kill(&md->bl); + clif_pet_roulette(sd,1); + 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 + { + clif_pet_roulette(sd,0); + sd->catch_target_class = -1; + } + + return 0; } int pet_get_egg(int account_id,int pet_id,int flag) -{ - //This function is invoked when a new pet has been created, and at no other time! - struct map_session_data *sd; - struct item tmp_item; - int i=0,ret=0; - - if (flag) - return 0; - - sd = map_id2sd(account_id); - if (sd == NULL) - return 0; - - i = search_petDB_index(sd->catch_target_class,PET_CLASS); - sd->catch_target_class = -1; - - if (i < 0) { - intif_delete_petdata(pet_id); - return 0; - } - - memset(&tmp_item,0,sizeof(tmp_item)); - tmp_item.nameid = pet_db[i].EggID; - tmp_item.identify = 1; - tmp_item.card[0] = CARD0_PET; - tmp_item.card[1] = GetWord(pet_id,0); - tmp_item.card[2] = GetWord(pet_id,1); - tmp_item.card[3] = 0; //New pets are not named. - if ((ret = pc_additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER))) { - clif_additem(sd,0,0,ret); - map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - - return 1; +{ //This function is invoked when a new pet has been created, and at no other time! + struct map_session_data *sd; + struct item tmp_item; + int i=0,ret=0; + + if(flag) + return 0; + + sd = map_id2sd(account_id); + if(sd == NULL) + return 0; + + i = search_petDB_index(sd->catch_target_class,PET_CLASS); + sd->catch_target_class = -1; + + if(i < 0) { + intif_delete_petdata(pet_id); + return 0; + } + + memset(&tmp_item,0,sizeof(tmp_item)); + tmp_item.nameid = pet_db[i].EggID; + tmp_item.identify = 1; + tmp_item.card[0] = CARD0_PET; + tmp_item.card[1] = GetWord(pet_id,0); + tmp_item.card[2] = GetWord(pet_id,1); + tmp_item.card[3] = 0; //New pets are not named. + if((ret = pc_additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER))) { + clif_additem(sd,0,0,ret); + map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + + return 1; } static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd); @@ -586,743 +582,766 @@ static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap); int pet_menu(struct map_session_data *sd,int menunum) { - nullpo_ret(sd); - if (sd->pd == NULL) - return 1; - - //You lost the pet already. - if (!sd->status.pet_id || sd->pd->pet.intimate <= 0 || sd->pd->pet.incuvate) - return 1; - - switch (menunum) { - case 0: - clif_send_petstatus(sd); - break; - case 1: - pet_food(sd, sd->pd); - break; - case 2: - pet_performance(sd, sd->pd); - break; - case 3: - pet_return_egg(sd, sd->pd); - break; - case 4: - pet_unequipitem(sd, sd->pd); - break; - } - return 0; + nullpo_ret(sd); + if (sd->pd == NULL) + return 1; + + //You lost the pet already. + if(!sd->status.pet_id || sd->pd->pet.intimate <= 0 || sd->pd->pet.incuvate) + return 1; + + switch(menunum) { + case 0: + clif_send_petstatus(sd); + break; + case 1: + pet_food(sd, sd->pd); + break; + case 2: + pet_performance(sd, sd->pd); + break; + case 3: + pet_return_egg(sd, sd->pd); + break; + case 4: + pet_unequipitem(sd, sd->pd); + break; + } + return 0; } int pet_change_name(struct map_session_data *sd,char *name) { - int i; - struct pet_data *pd; - nullpo_retr(1, sd); + int i; + struct pet_data *pd; + nullpo_retr(1, sd); - pd = sd->pd; - if ((pd == NULL) || (pd->pet.rename_flag == 1 && !battle_config.pet_rename)) - return 1; + pd = sd->pd; + if((pd == NULL) || (pd->pet.rename_flag == 1 && !battle_config.pet_rename)) + return 1; - for (i=0; i<NAME_LENGTH && name[i]; i++) { - if (!(name[i]&0xe0) || name[i]==0x7f) - return 1; - } + for(i=0;i<NAME_LENGTH && name[i];i++){ + if( !(name[i]&0xe0) || name[i]==0x7f) + return 1; + } - return intif_rename_pet(sd, name); + return intif_rename_pet(sd, name); } -int pet_change_name_ack(struct map_session_data *sd, char *name, int flag) +int pet_change_name_ack(struct map_session_data *sd, char* name, int flag) { - struct pet_data *pd = sd->pd; - if (!pd) return 0; - - normalize_name(name," ");//bugreport:3032 - - if (!flag || !strlen(name)) { - clif_displaymessage(sd->fd, msg_txt(280)); // You cannot use this name for your pet. - clif_send_petstatus(sd); //Send status so client knows oet name change got rejected. - return 0; - } - memcpy(pd->pet.name, name, NAME_LENGTH); - clif_charnameack(0,&pd->bl); - pd->pet.rename_flag = 1; - clif_pet_equip_area(pd); - clif_send_petstatus(sd); - return 1; + struct pet_data *pd = sd->pd; + if (!pd) return 0; + + normalize_name(name," ");//bugreport:3032 + + if ( !flag || !strlen(name) ) { + clif_displaymessage(sd->fd, msg_txt(280)); // You cannot use this name for your pet. + clif_send_petstatus(sd); //Send status so client knows oet name change got rejected. + return 0; + } + memcpy(pd->pet.name, name, NAME_LENGTH); + clif_charnameack (0,&pd->bl); + pd->pet.rename_flag = 1; + clif_pet_equip_area(pd); + clif_send_petstatus(sd); + return 1; } int pet_equipitem(struct map_session_data *sd,int index) { - struct pet_data *pd; - int nameid; - - nullpo_retr(1, sd); - pd = sd->pd; - if (!pd) return 1; - - nameid = sd->status.inventory[index].nameid; - - if (pd->petDB->AcceID == 0 || nameid != pd->petDB->AcceID || pd->pet.equip != 0) { - clif_equipitemack(sd,0,0,0); - return 1; - } - - pc_delitem(sd,index,1,0,0,LOG_TYPE_OTHER); - pd->pet.equip = nameid; - status_set_viewdata(&pd->bl, pd->pet.class_); //Updates view_data. - clif_pet_equip_area(pd); - if (battle_config.pet_equip_required) { - //Skotlex: start support timers if need - unsigned int tick = gettick(); - if (pd->s_skill && pd->s_skill->timer == INVALID_TIMER) { - if (pd->s_skill->id) - pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000, pet_skill_support_timer, sd->bl.id, 0); - else - pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000, pet_heal_timer, sd->bl.id, 0); - } - if (pd->bonus && pd->bonus->timer == INVALID_TIMER) - pd->bonus->timer=add_timer(tick+pd->bonus->delay*1000, pet_skill_bonus_timer, sd->bl.id, 0); - } - - return 0; + struct pet_data *pd; + int nameid; + + nullpo_retr(1, sd); + pd = sd->pd; + if (!pd) return 1; + + nameid = sd->status.inventory[index].nameid; + + if(pd->petDB->AcceID == 0 || nameid != pd->petDB->AcceID || pd->pet.equip != 0) { + clif_equipitemack(sd,0,0,0); + return 1; + } + + pc_delitem(sd,index,1,0,0,LOG_TYPE_OTHER); + pd->pet.equip = nameid; + status_set_viewdata(&pd->bl, pd->pet.class_); //Updates view_data. + clif_pet_equip_area(pd); + if (battle_config.pet_equip_required) + { //Skotlex: start support timers if need + unsigned int tick = gettick(); + if (pd->s_skill && pd->s_skill->timer == INVALID_TIMER) + { + if (pd->s_skill->id) + pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000, pet_skill_support_timer, sd->bl.id, 0); + else + pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000, pet_heal_timer, sd->bl.id, 0); + } + if (pd->bonus && pd->bonus->timer == INVALID_TIMER) + pd->bonus->timer=add_timer(tick+pd->bonus->delay*1000, pet_skill_bonus_timer, sd->bl.id, 0); + } + + return 0; } static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) { - struct item tmp_item; - int nameid,flag; - - if (pd->pet.equip == 0) - return 1; - - nameid = pd->pet.equip; - pd->pet.equip = 0; - status_set_viewdata(&pd->bl, pd->pet.class_); - clif_pet_equip_area(pd); - memset(&tmp_item,0,sizeof(tmp_item)); - tmp_item.nameid = nameid; - tmp_item.identify = 1; - if ((flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) { - clif_additem(sd,0,0,flag); - map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - if (battle_config.pet_equip_required) { - // Skotlex: halt support timers if needed - if (pd->state.skillbonus) { - pd->state.skillbonus = 0; - status_calc_pc(sd,0); - } - if (pd->s_skill && pd->s_skill->timer != INVALID_TIMER) { - if (pd->s_skill->id) - delete_timer(pd->s_skill->timer, pet_skill_support_timer); - else - delete_timer(pd->s_skill->timer, pet_heal_timer); - pd->s_skill->timer = INVALID_TIMER; - } - if (pd->bonus && pd->bonus->timer != INVALID_TIMER) { - delete_timer(pd->bonus->timer, pet_skill_bonus_timer); - pd->bonus->timer = INVALID_TIMER; - } - } - - return 0; + struct item tmp_item; + int nameid,flag; + + if(pd->pet.equip == 0) + return 1; + + nameid = pd->pet.equip; + pd->pet.equip = 0; + status_set_viewdata(&pd->bl, pd->pet.class_); + clif_pet_equip_area(pd); + memset(&tmp_item,0,sizeof(tmp_item)); + tmp_item.nameid = nameid; + tmp_item.identify = 1; + if((flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) { + clif_additem(sd,0,0,flag); + map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + if( battle_config.pet_equip_required ) + { // Skotlex: halt support timers if needed + if( pd->state.skillbonus ) + { + pd->state.skillbonus = 0; + status_calc_pc(sd,0); + } + if( pd->s_skill && pd->s_skill->timer != INVALID_TIMER ) + { + if( pd->s_skill->id ) + delete_timer(pd->s_skill->timer, pet_skill_support_timer); + else + delete_timer(pd->s_skill->timer, pet_heal_timer); + pd->s_skill->timer = INVALID_TIMER; + } + if( pd->bonus && pd->bonus->timer != INVALID_TIMER ) + { + delete_timer(pd->bonus->timer, pet_skill_bonus_timer); + pd->bonus->timer = INVALID_TIMER; + } + } + + return 0; } static int pet_food(struct map_session_data *sd, struct pet_data *pd) { - int i,k; - - k=pd->petDB->FoodID; - i=pc_search_inventory(sd,k); - if (i < 0) { - clif_pet_food(sd,k,0); - return 1; - } - pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); - - if (pd->pet.hungry > 90) - pet_set_intimate(pd, pd->pet.intimate - pd->petDB->r_full); - else { - if (battle_config.pet_friendly_rate != 100) - k = (pd->petDB->r_hungry * battle_config.pet_friendly_rate)/100; - else - k = pd->petDB->r_hungry; - if (pd->pet.hungry > 75) { - k = k >> 1; - if (k <= 0) - k = 1; - } - pet_set_intimate(pd, pd->pet.intimate + k); - } - if (pd->pet.intimate <= 0) { - pd->pet.intimate = 0; - pet_stop_attack(pd); - pd->status.speed = pd->db->status.speed; - } else if (pd->pet.intimate > 1000) - pd->pet.intimate = 1000; - status_calc_pet(pd, 0); - pd->pet.hungry += pd->petDB->fullness; - if (pd->pet.hungry > 100) - pd->pet.hungry = 100; - - clif_send_petdata(sd,pd,2,pd->pet.hungry); - clif_send_petdata(sd,pd,1,pd->pet.intimate); - clif_pet_food(sd,pd->petDB->FoodID,1); - - return 0; + int i,k; + + k=pd->petDB->FoodID; + i=pc_search_inventory(sd,k); + if(i < 0) { + clif_pet_food(sd,k,0); + return 1; + } + pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); + + if( pd->pet.hungry > 90 ) + pet_set_intimate(pd, pd->pet.intimate - pd->petDB->r_full); + else + { + if( battle_config.pet_friendly_rate != 100 ) + k = (pd->petDB->r_hungry * battle_config.pet_friendly_rate)/100; + else + k = pd->petDB->r_hungry; + if( pd->pet.hungry > 75 ) + { + k = k >> 1; + if( k <= 0 ) + k = 1; + } + pet_set_intimate(pd, pd->pet.intimate + k); + } + if( pd->pet.intimate <= 0 ) + { + pd->pet.intimate = 0; + pet_stop_attack(pd); + pd->status.speed = pd->db->status.speed; + } + else if( pd->pet.intimate > 1000 ) + pd->pet.intimate = 1000; + status_calc_pet(pd, 0); + pd->pet.hungry += pd->petDB->fullness; + if( pd->pet.hungry > 100 ) + pd->pet.hungry = 100; + + clif_send_petdata(sd,pd,2,pd->pet.hungry); + clif_send_petdata(sd,pd,1,pd->pet.intimate); + clif_pet_food(sd,pd->petDB->FoodID,1); + + return 0; } static int pet_randomwalk(struct pet_data *pd,unsigned int tick) { - const int retrycount=20; - - nullpo_ret(pd); - - Assert((pd->msd == 0) || (pd->msd->pd == pd)); - - if (DIFF_TICK(pd->next_walktime,tick) < 0 && unit_can_move(&pd->bl)) { - int i,x,y,c,d=12-pd->move_fail_count; - if (d<5) d=5; - for (i=0; i<retrycount; i++) { - int r=rnd(); - x=pd->bl.x+r%(d*2+1)-d; - y=pd->bl.y+r/(d*2+1)%(d*2+1)-d; - if (map_getcell(pd->bl.m,x,y,CELL_CHKPASS) && unit_walktoxy(&pd->bl,x,y,0)) { - pd->move_fail_count=0; - break; - } - if (i+1>=retrycount) { - pd->move_fail_count++; - if (pd->move_fail_count>1000) { - ShowWarning("PET can't move. hold position %d, class = %d\n",pd->bl.id,pd->pet.class_); - pd->move_fail_count=0; - pd->ud.canmove_tick = tick + 60000; - return 0; - } - } - } - for (i=c=0; i<pd->ud.walkpath.path_len; i++) { - if (pd->ud.walkpath.path[i]&1) - c+=pd->status.speed*14/10; - else - c+=pd->status.speed; - } - pd->next_walktime = tick+rnd()%3000+3000+c; - - return 1; - } - return 0; + const int retrycount=20; + + nullpo_ret(pd); + + Assert((pd->msd == 0) || (pd->msd->pd == pd)); + + if(DIFF_TICK(pd->next_walktime,tick) < 0 && unit_can_move(&pd->bl)) { + int i,x,y,c,d=12-pd->move_fail_count; + if(d<5) d=5; + for(i=0;i<retrycount;i++){ + int r=rnd(); + x=pd->bl.x+r%(d*2+1)-d; + y=pd->bl.y+r/(d*2+1)%(d*2+1)-d; + if(map_getcell(pd->bl.m,x,y,CELL_CHKPASS) && unit_walktoxy(&pd->bl,x,y,0)){ + pd->move_fail_count=0; + break; + } + if(i+1>=retrycount){ + pd->move_fail_count++; + if(pd->move_fail_count>1000){ + ShowWarning("PET can't move. hold position %d, class = %d\n",pd->bl.id,pd->pet.class_); + pd->move_fail_count=0; + pd->ud.canmove_tick = tick + 60000; + return 0; + } + } + } + for(i=c=0;i<pd->ud.walkpath.path_len;i++){ + if(pd->ud.walkpath.path[i]&1) + c+=pd->status.speed*14/10; + else + c+=pd->status.speed; + } + pd->next_walktime = tick+rnd()%3000+3000+c; + + return 1; + } + return 0; } static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, unsigned int tick) { - struct block_list *target = NULL; - - if (pd->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL) - return 0; - - if (DIFF_TICK(tick,pd->last_thinktime) < MIN_PETTHINKTIME) - return 0; - pd->last_thinktime=tick; - - if (pd->ud.attacktimer != INVALID_TIMER || pd->ud.skilltimer != INVALID_TIMER || pd->bl.m != sd->bl.m) - return 0; - - if (pd->ud.walktimer != INVALID_TIMER && pd->ud.walkpath.path_pos <= 2) - return 0; //No thinking when you just started to walk. - - if (pd->pet.intimate <= 0) { - //Pet should just... well, random walk. - pet_randomwalk(pd,tick); - return 0; - } - - if (!check_distance_bl(&sd->bl, &pd->bl, pd->db->range3)) { - //Master too far, chase. - if (pd->target_id) - pet_unlocktarget(pd); - if (pd->ud.walktimer != INVALID_TIMER && pd->ud.target == sd->bl.id) - return 0; //Already walking to him - if (DIFF_TICK(tick, pd->ud.canmove_tick) < 0) - return 0; //Can't move yet. - pd->status.speed = (sd->battle_status.speed>>1); - if (pd->status.speed <= 0) - pd->status.speed = 1; - if (!unit_walktobl(&pd->bl, &sd->bl, 3, 0)) - pet_randomwalk(pd,tick); - return 0; - } - - //Return speed to normal. - if (pd->status.speed != pd->petDB->speed) { - if (pd->ud.walktimer != INVALID_TIMER) - return 0; //Wait until the pet finishes walking back to master. - pd->status.speed = pd->petDB->speed; - pd->ud.state.change_walk_target = pd->ud.state.speed_changed = 1; - } - - if (pd->target_id) { - target= map_id2bl(pd->target_id); - if (!target || pd->bl.m != target->m || status_isdead(target) || - !check_distance_bl(&pd->bl, target, pd->db->range3)) { - target = NULL; - pet_unlocktarget(pd); - } - } - - if (!target && pd->loot && pd->loot->count < pd->loot->max && DIFF_TICK(tick,pd->ud.canact_tick)>0) { - //Use half the pet's range of sight. - map_foreachinrange(pet_ai_sub_hard_lootsearch,&pd->bl, - pd->db->range2/2, BL_ITEM,pd,&target); - } - - if (!target) { - //Just walk around. - if (check_distance_bl(&sd->bl, &pd->bl, 3)) - return 0; //Already next to master. - - if (pd->ud.walktimer != INVALID_TIMER && check_distance_blxy(&sd->bl, pd->ud.to_x,pd->ud.to_y, 3)) - return 0; //Already walking to him - - unit_calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir); - if (!unit_walktoxy(&pd->bl,pd->ud.to_x,pd->ud.to_y,0)) - pet_randomwalk(pd,tick); - - return 0; - } - - if (pd->ud.target == target->id && - (pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER)) - return 0; //Target already locked. - - if (target->type != BL_ITEM) { - //enemy targetted - if (!battle_check_range(&pd->bl,target,pd->status.rhw.range)) { - //Chase - if (!unit_walktobl(&pd->bl, target, pd->status.rhw.range, 2)) - pet_unlocktarget(pd); //Unreachable target. - return 0; - } - //Continuous attack. - unit_attack(&pd->bl, pd->target_id, 1); - } else { //Item Targeted, attempt loot - if (!check_distance_bl(&pd->bl, target, 1)) { - //Out of range - if (!unit_walktobl(&pd->bl, target, 1, 1)) //Unreachable target. - pet_unlocktarget(pd); - return 0; - } else { - struct flooritem_data *fitem = (struct flooritem_data *)target; - if (pd->loot->count < pd->loot->max) { - memcpy(&pd->loot->item[pd->loot->count++],&fitem->item_data,sizeof(pd->loot->item[0])); - pd->loot->weight += itemdb_weight(fitem->item_data.nameid)*fitem->item_data.amount; - map_clearflooritem(target); - } - //Target is unlocked regardless of whether it was picked or not. - pet_unlocktarget(pd); - } - } - return 0; + struct block_list *target = NULL; + + if(pd->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL) + return 0; + + if(DIFF_TICK(tick,pd->last_thinktime) < MIN_PETTHINKTIME) + return 0; + pd->last_thinktime=tick; + + if(pd->ud.attacktimer != INVALID_TIMER || pd->ud.skilltimer != INVALID_TIMER || pd->bl.m != sd->bl.m) + return 0; + + if(pd->ud.walktimer != INVALID_TIMER && pd->ud.walkpath.path_pos <= 2) + return 0; //No thinking when you just started to walk. + + if(pd->pet.intimate <= 0) { + //Pet should just... well, random walk. + pet_randomwalk(pd,tick); + return 0; + } + + if (!check_distance_bl(&sd->bl, &pd->bl, pd->db->range3)) { + //Master too far, chase. + if(pd->target_id) + pet_unlocktarget(pd); + if(pd->ud.walktimer != INVALID_TIMER && pd->ud.target == sd->bl.id) + return 0; //Already walking to him + if (DIFF_TICK(tick, pd->ud.canmove_tick) < 0) + return 0; //Can't move yet. + pd->status.speed = (sd->battle_status.speed>>1); + if(pd->status.speed <= 0) + pd->status.speed = 1; + if (!unit_walktobl(&pd->bl, &sd->bl, 3, 0)) + pet_randomwalk(pd,tick); + return 0; + } + + //Return speed to normal. + if (pd->status.speed != pd->petDB->speed) { + if (pd->ud.walktimer != INVALID_TIMER) + return 0; //Wait until the pet finishes walking back to master. + pd->status.speed = pd->petDB->speed; + pd->ud.state.change_walk_target = pd->ud.state.speed_changed = 1; + } + + if (pd->target_id) { + target= map_id2bl(pd->target_id); + if (!target || pd->bl.m != target->m || status_isdead(target) || + !check_distance_bl(&pd->bl, target, pd->db->range3)) + { + target = NULL; + pet_unlocktarget(pd); + } + } + + if(!target && pd->loot && pd->loot->count < pd->loot->max && DIFF_TICK(tick,pd->ud.canact_tick)>0) { + //Use half the pet's range of sight. + map_foreachinrange(pet_ai_sub_hard_lootsearch,&pd->bl, + pd->db->range2/2, BL_ITEM,pd,&target); + } + + if (!target) { + //Just walk around. + if (check_distance_bl(&sd->bl, &pd->bl, 3)) + return 0; //Already next to master. + + if(pd->ud.walktimer != INVALID_TIMER && check_distance_blxy(&sd->bl, pd->ud.to_x,pd->ud.to_y, 3)) + return 0; //Already walking to him + + unit_calc_pos(&pd->bl, sd->bl.x, sd->bl.y, sd->ud.dir); + if(!unit_walktoxy(&pd->bl,pd->ud.to_x,pd->ud.to_y,0)) + pet_randomwalk(pd,tick); + + return 0; + } + + if(pd->ud.target == target->id && + (pd->ud.attacktimer != INVALID_TIMER || pd->ud.walktimer != INVALID_TIMER)) + return 0; //Target already locked. + + if (target->type != BL_ITEM) + { //enemy targetted + if(!battle_check_range(&pd->bl,target,pd->status.rhw.range)) + { //Chase + if(!unit_walktobl(&pd->bl, target, pd->status.rhw.range, 2)) + pet_unlocktarget(pd); //Unreachable target. + return 0; + } + //Continuous attack. + unit_attack(&pd->bl, pd->target_id, 1); + } else { //Item Targeted, attempt loot + if (!check_distance_bl(&pd->bl, target, 1)) + { //Out of range + if(!unit_walktobl(&pd->bl, target, 1, 1)) //Unreachable target. + pet_unlocktarget(pd); + return 0; + } else{ + struct flooritem_data *fitem = (struct flooritem_data *)target; + if(pd->loot->count < pd->loot->max){ + memcpy(&pd->loot->item[pd->loot->count++],&fitem->item_data,sizeof(pd->loot->item[0])); + pd->loot->weight += itemdb_weight(fitem->item_data.nameid)*fitem->item_data.amount; + map_clearflooritem(target); + } + //Target is unlocked regardless of whether it was picked or not. + pet_unlocktarget(pd); + } + } + return 0; } static int pet_ai_sub_foreachclient(struct map_session_data *sd,va_list ap) { - unsigned int tick = va_arg(ap,unsigned int); - if (sd->status.pet_id && sd->pd) - pet_ai_sub_hard(sd->pd,sd,tick); + unsigned int tick = va_arg(ap,unsigned int); + if(sd->status.pet_id && sd->pd) + pet_ai_sub_hard(sd->pd,sd,tick); - return 0; + return 0; } static int pet_ai_hard(int tid, unsigned int tick, int id, intptr_t data) { - map_foreachpc(pet_ai_sub_foreachclient,tick); + map_foreachpc(pet_ai_sub_foreachclient,tick); - return 0; + return 0; } static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap) { - struct pet_data *pd; - struct flooritem_data *fitem = (struct flooritem_data *)bl; - struct block_list **target; - int sd_charid =0; - - pd=va_arg(ap,struct pet_data *); - target=va_arg(ap,struct block_list **); - - sd_charid = fitem->first_get_charid; - - if (sd_charid && sd_charid != pd->msd->status.char_id) - return 0; - - if (unit_can_reach_bl(&pd->bl,bl, pd->db->range2, 1, NULL, NULL) && - ((*target) == NULL || //New target closer than previous one. - !check_distance_bl(&pd->bl, *target, distance_bl(&pd->bl, bl)))) { - (*target) = bl; - pd->target_id = bl->id; - return 1; - } - - return 0; + struct pet_data* pd; + struct flooritem_data *fitem = (struct flooritem_data *)bl; + struct block_list **target; + int sd_charid =0; + + pd=va_arg(ap,struct pet_data *); + target=va_arg(ap,struct block_list**); + + sd_charid = fitem->first_get_charid; + + if(sd_charid && sd_charid != pd->msd->status.char_id) + return 0; + + if(unit_can_reach_bl(&pd->bl,bl, pd->db->range2, 1, NULL, NULL) && + ((*target) == NULL || //New target closer than previous one. + !check_distance_bl(&pd->bl, *target, distance_bl(&pd->bl, bl)))) + { + (*target) = bl; + pd->target_id = bl->id; + return 1; + } + + return 0; } static int pet_delay_item_drop(int tid, unsigned int tick, int id, intptr_t data) { - struct item_drop_list *list; - struct item_drop *ditem, *ditem_prev; - list=(struct item_drop_list *)data; - ditem = list->item; - while (ditem) { - map_addflooritem(&ditem->item_data,ditem->item_data.amount, - list->m,list->x,list->y, - list->first_charid,list->second_charid,list->third_charid,0); - ditem_prev = ditem; - ditem = ditem->next; - ers_free(item_drop_ers, ditem_prev); - } - ers_free(item_drop_list_ers, list); - return 0; + struct item_drop_list *list; + struct item_drop *ditem, *ditem_prev; + list=(struct item_drop_list *)data; + ditem = list->item; + while (ditem) { + map_addflooritem(&ditem->item_data,ditem->item_data.amount, + list->m,list->x,list->y, + list->first_charid,list->second_charid,list->third_charid,0); + ditem_prev = ditem; + ditem = ditem->next; + ers_free(item_drop_ers, ditem_prev); + } + ers_free(item_drop_list_ers, list); + return 0; } int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd) { - int i,flag=0; - struct item_drop_list *dlist; - struct item_drop *ditem; - struct item *it; - if (!pd || !pd->loot || !pd->loot->count) - return 0; - dlist = ers_alloc(item_drop_list_ers, struct item_drop_list); - dlist->m = pd->bl.m; - dlist->x = pd->bl.x; - dlist->y = pd->bl.y; - dlist->first_charid = 0; - dlist->second_charid = 0; - dlist->third_charid = 0; - dlist->item = NULL; - - for (i=0; i<pd->loot->count; i++) { - it = &pd->loot->item[i]; - if (sd) { - if ((flag = pc_additem(sd,it,it->amount,LOG_TYPE_PICKDROP_PLAYER))) { - clif_additem(sd,0,0,flag); - ditem = ers_alloc(item_drop_ers, struct item_drop); - memcpy(&ditem->item_data, it, sizeof(struct item)); - ditem->next = dlist->item; - dlist->item = ditem; - } - } else { - ditem = ers_alloc(item_drop_ers, struct item_drop); - memcpy(&ditem->item_data, it, sizeof(struct item)); - ditem->next = dlist->item; - dlist->item = ditem; - } - } - //The smart thing to do is use pd->loot->max (thanks for pointing it out, Shinomori) - memset(pd->loot->item,0,pd->loot->max * sizeof(struct item)); - pd->loot->count = 0; - pd->loot->weight = 0; - pd->ud.canact_tick = gettick()+10000; //prevent picked up during 10*1000ms - - if (dlist->item) - add_timer(gettick()+540,pet_delay_item_drop,0,(intptr_t)dlist); - else - ers_free(item_drop_list_ers, dlist); - return 1; + int i,flag=0; + struct item_drop_list *dlist; + struct item_drop *ditem; + struct item *it; + if(!pd || !pd->loot || !pd->loot->count) + return 0; + dlist = ers_alloc(item_drop_list_ers, struct item_drop_list); + dlist->m = pd->bl.m; + dlist->x = pd->bl.x; + dlist->y = pd->bl.y; + dlist->first_charid = 0; + dlist->second_charid = 0; + dlist->third_charid = 0; + dlist->item = NULL; + + for(i=0;i<pd->loot->count;i++) { + it = &pd->loot->item[i]; + if(sd){ + if((flag = pc_additem(sd,it,it->amount,LOG_TYPE_PICKDROP_PLAYER))){ + clif_additem(sd,0,0,flag); + ditem = ers_alloc(item_drop_ers, struct item_drop); + memcpy(&ditem->item_data, it, sizeof(struct item)); + ditem->next = dlist->item; + dlist->item = ditem; + } + } + else { + ditem = ers_alloc(item_drop_ers, struct item_drop); + memcpy(&ditem->item_data, it, sizeof(struct item)); + ditem->next = dlist->item; + dlist->item = ditem; + } + } + //The smart thing to do is use pd->loot->max (thanks for pointing it out, Shinomori) + memset(pd->loot->item,0,pd->loot->max * sizeof(struct item)); + pd->loot->count = 0; + pd->loot->weight = 0; + pd->ud.canact_tick = gettick()+10000; //prevent picked up during 10*1000ms + + if (dlist->item) + add_timer(gettick()+540,pet_delay_item_drop,0,(intptr_t)dlist); + else + ers_free(item_drop_list_ers, dlist); + return 1; } /*========================================== * pet bonus giving skills [Valaris] / Rewritten by [Skotlex] - *------------------------------------------*/ + *------------------------------------------*/ int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd=map_id2sd(id); - struct pet_data *pd; - int bonus; - int timer = 0; - - if (sd == NULL || sd->pd==NULL || sd->pd->bonus == NULL) - return 1; - - pd=sd->pd; - - if (pd->bonus->timer != tid) { - ShowError("pet_skill_bonus_timer %d != %d\n",pd->bonus->timer,tid); - pd->bonus->timer = INVALID_TIMER; - return 0; - } - - // determine the time for the next timer - if (pd->state.skillbonus && pd->bonus->delay > 0) { - bonus = 0; - timer = pd->bonus->delay*1000; // the duration until pet bonuses will be reactivated again - } else if (pd->pet.intimate) { - bonus = 1; - timer = pd->bonus->duration*1000; // the duration for pet bonuses to be in effect - } else { //Lost pet... - pd->bonus->timer = INVALID_TIMER; - return 0; - } - - if (pd->state.skillbonus != bonus) { - pd->state.skillbonus = bonus; - status_calc_pc(sd, 0); - } - // wait for the next timer - pd->bonus->timer=add_timer(tick+timer,pet_skill_bonus_timer,sd->bl.id,0); - return 0; + struct map_session_data *sd=map_id2sd(id); + struct pet_data *pd; + int bonus; + int timer = 0; + + if(sd == NULL || sd->pd==NULL || sd->pd->bonus == NULL) + return 1; + + pd=sd->pd; + + if(pd->bonus->timer != tid) { + ShowError("pet_skill_bonus_timer %d != %d\n",pd->bonus->timer,tid); + pd->bonus->timer = INVALID_TIMER; + return 0; + } + + // determine the time for the next timer + if (pd->state.skillbonus && pd->bonus->delay > 0) { + bonus = 0; + timer = pd->bonus->delay*1000; // the duration until pet bonuses will be reactivated again + } else if (pd->pet.intimate) { + bonus = 1; + timer = pd->bonus->duration*1000; // the duration for pet bonuses to be in effect + } else { //Lost pet... + pd->bonus->timer = INVALID_TIMER; + return 0; + } + + if (pd->state.skillbonus != bonus) { + pd->state.skillbonus = bonus; + status_calc_pc(sd, 0); + } + // wait for the next timer + pd->bonus->timer=add_timer(tick+timer,pet_skill_bonus_timer,sd->bl.id,0); + return 0; } /*========================================== * pet recovery skills [Valaris] / Rewritten by [Skotlex] - *------------------------------------------*/ + *------------------------------------------*/ int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd=map_id2sd(id); - struct pet_data *pd; - - if (sd==NULL || sd->pd == NULL || sd->pd->recovery == NULL) - return 1; - - pd=sd->pd; - - if (pd->recovery->timer != tid) { - ShowError("pet_recovery_timer %d != %d\n",pd->recovery->timer,tid); - return 0; - } - - if (sd->sc.data[pd->recovery->type]) { - //Display a heal animation? - //Detoxify is chosen for now. - clif_skill_nodamage(&pd->bl,&sd->bl,TF_DETOXIFY,1,1); - status_change_end(&sd->bl, pd->recovery->type, INVALID_TIMER); - clif_emotion(&pd->bl, E_OK); - } - - pd->recovery->timer = INVALID_TIMER; - - return 0; + struct map_session_data *sd=map_id2sd(id); + struct pet_data *pd; + + if(sd==NULL || sd->pd == NULL || sd->pd->recovery == NULL) + return 1; + + pd=sd->pd; + + if(pd->recovery->timer != tid) { + ShowError("pet_recovery_timer %d != %d\n",pd->recovery->timer,tid); + return 0; + } + + if(sd->sc.data[pd->recovery->type]) + { //Display a heal animation? + //Detoxify is chosen for now. + clif_skill_nodamage(&pd->bl,&sd->bl,TF_DETOXIFY,1,1); + status_change_end(&sd->bl, pd->recovery->type, INVALID_TIMER); + clif_emotion(&pd->bl, E_OK); + } + + pd->recovery->timer = INVALID_TIMER; + + return 0; } int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd=map_id2sd(id); - struct status_data *status; - struct pet_data *pd; - unsigned int rate = 100; - - if (sd==NULL || sd->pd == NULL || sd->pd->s_skill == NULL) - return 1; - - pd=sd->pd; - - if (pd->s_skill->timer != tid) { - ShowError("pet_heal_timer %d != %d\n",pd->s_skill->timer,tid); - return 0; - } - - status = status_get_status_data(&sd->bl); - - if (pc_isdead(sd) || - (rate = get_percentage(status->sp, status->max_sp)) > pd->s_skill->sp || - (rate = get_percentage(status->hp, status->max_hp)) > pd->s_skill->hp || - (rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect - ) { //Wait (how long? 1 sec for every 10% of remaining) - pd->s_skill->timer=add_timer(gettick()+(rate>10?rate:10)*100,pet_heal_timer,sd->bl.id,0); - return 0; - } - pet_stop_attack(pd); - pet_stop_walking(pd,1); - clif_skill_nodamage(&pd->bl,&sd->bl,AL_HEAL,pd->s_skill->lv,1); - status_heal(&sd->bl, pd->s_skill->lv,0, 0); - pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000,pet_heal_timer,sd->bl.id,0); - return 0; + struct map_session_data *sd=map_id2sd(id); + struct status_data *status; + struct pet_data *pd; + unsigned int rate = 100; + + if(sd==NULL || sd->pd == NULL || sd->pd->s_skill == NULL) + return 1; + + pd=sd->pd; + + if(pd->s_skill->timer != tid) { + ShowError("pet_heal_timer %d != %d\n",pd->s_skill->timer,tid); + return 0; + } + + status = status_get_status_data(&sd->bl); + + if(pc_isdead(sd) || + (rate = get_percentage(status->sp, status->max_sp)) > pd->s_skill->sp || + (rate = get_percentage(status->hp, status->max_hp)) > pd->s_skill->hp || + (rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect + ) { //Wait (how long? 1 sec for every 10% of remaining) + pd->s_skill->timer=add_timer(gettick()+(rate>10?rate:10)*100,pet_heal_timer,sd->bl.id,0); + return 0; + } + pet_stop_attack(pd); + pet_stop_walking(pd,1); + clif_skill_nodamage(&pd->bl,&sd->bl,AL_HEAL,pd->s_skill->lv,1); + status_heal(&sd->bl, pd->s_skill->lv,0, 0); + pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000,pet_heal_timer,sd->bl.id,0); + return 0; } /*========================================== * pet support skills [Skotlex] - *------------------------------------------*/ + *------------------------------------------*/ int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd=map_id2sd(id); - struct pet_data *pd; - struct status_data *status; - short rate = 100; - if (sd==NULL || sd->pd == NULL || sd->pd->s_skill == NULL) - return 1; - - pd=sd->pd; - - if (pd->s_skill->timer != tid) { - ShowError("pet_skill_support_timer %d != %d\n",pd->s_skill->timer,tid); - return 0; - } - - status = status_get_status_data(&sd->bl); - - if (DIFF_TICK(pd->ud.canact_tick, tick) > 0) { - //Wait until the pet can act again. - pd->s_skill->timer=add_timer(pd->ud.canact_tick,pet_skill_support_timer,sd->bl.id,0); - return 0; - } - - if (pc_isdead(sd) || - (rate = get_percentage(status->sp, status->max_sp)) > pd->s_skill->sp || - (rate = get_percentage(status->hp, status->max_hp)) > pd->s_skill->hp || - (rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect - ) { //Wait (how long? 1 sec for every 10% of remaining) - pd->s_skill->timer=add_timer(tick+(rate>10?rate:10)*100,pet_skill_support_timer,sd->bl.id,0); - return 0; - } - - pet_stop_attack(pd); - pet_stop_walking(pd,1); - pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000,pet_skill_support_timer,sd->bl.id,0); - if (skill_get_inf(pd->s_skill->id) & INF_GROUND_SKILL) - unit_skilluse_pos(&pd->bl, sd->bl.x, sd->bl.y, pd->s_skill->id, pd->s_skill->lv); - else - unit_skilluse_id(&pd->bl, sd->bl.id, pd->s_skill->id, pd->s_skill->lv); - return 0; + struct map_session_data *sd=map_id2sd(id); + struct pet_data *pd; + struct status_data *status; + short rate = 100; + if(sd==NULL || sd->pd == NULL || sd->pd->s_skill == NULL) + return 1; + + pd=sd->pd; + + if(pd->s_skill->timer != tid) { + ShowError("pet_skill_support_timer %d != %d\n",pd->s_skill->timer,tid); + return 0; + } + + status = status_get_status_data(&sd->bl); + + if (DIFF_TICK(pd->ud.canact_tick, tick) > 0) + { //Wait until the pet can act again. + pd->s_skill->timer=add_timer(pd->ud.canact_tick,pet_skill_support_timer,sd->bl.id,0); + return 0; + } + + if(pc_isdead(sd) || + (rate = get_percentage(status->sp, status->max_sp)) > pd->s_skill->sp || + (rate = get_percentage(status->hp, status->max_hp)) > pd->s_skill->hp || + (rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect + ) { //Wait (how long? 1 sec for every 10% of remaining) + pd->s_skill->timer=add_timer(tick+(rate>10?rate:10)*100,pet_skill_support_timer,sd->bl.id,0); + return 0; + } + + pet_stop_attack(pd); + pet_stop_walking(pd,1); + pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000,pet_skill_support_timer,sd->bl.id,0); + if (skill_get_inf(pd->s_skill->id) & INF_GROUND_SKILL) + unit_skilluse_pos(&pd->bl, sd->bl.x, sd->bl.y, pd->s_skill->id, pd->s_skill->lv); + else + unit_skilluse_id(&pd->bl, sd->bl.id, pd->s_skill->id, pd->s_skill->lv); + return 0; } /*========================================== * Pet read db data * pet_db.txt * pet_db2.txt - *------------------------------------------*/ + *------------------------------------------*/ int read_petdb() { - char *filename[] = {"pet_db.txt","pet_db2.txt"}; - FILE *fp; - int nameid,i,j,k; - - // Remove any previous scripts in case reloaddb was invoked. - for (j = 0; j < MAX_PET_DB; j++) { - if (pet_db[j].pet_script) { - script_free_code(pet_db[j].pet_script); - pet_db[j].pet_script = NULL; - } - if (pet_db[j].equip_script) { - script_free_code(pet_db[j].equip_script); - pet_db[j].pet_script = NULL; - } - } - - // clear database - memset(pet_db,0,sizeof(pet_db)); - - j = 0; // entry counter - for (i = 0; i < ARRAYLENGTH(filename); i++) { - char line[1024]; - int lines, entries; - - sprintf(line, "%s/%s", db_path, filename[i]); - fp=fopen(line,"r"); - if (fp == NULL) { - if (i == 0) - ShowError("can't read %s\n",line); - continue; - } - - lines = entries = 0; - while (fgets(line, sizeof(line), fp) && j < MAX_PET_DB) { - char *str[22], *p; - lines++; - - if (line[0] == '/' && line[1] == '/') - continue; - memset(str, 0, sizeof(str)); - p = line; - while (ISSPACE(*p)) - ++p; - if (*p == '\0') - continue; // empty line - for (k = 0; k < 20; ++k) { - str[k] = p; - p = strchr(p,','); - if (p == NULL) - break; // comma not found - *p = '\0'; - ++p; - } - - if (p == NULL) { - ShowError("read_petdb: Insufficient columns in line %d, skipping.\n", lines); - continue; - } - - // Pet Script - if (*p != '{') { - ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines); - continue; - } - - str[20] = p; - p = strstr(p+1,"},"); - if (p == NULL) { - ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines); - continue; - } - p[1] = '\0'; - p += 2; - - // Equip Script - if (*p != '{') { - ShowError("read_petdb: Invalid format (Equip Script column) in line %d, skipping.\n", lines); - continue; - } - str[21] = p; - - if ((nameid = atoi(str[0])) <= 0) - continue; - - if (!mobdb_checkid(nameid)) { - ShowWarning("pet_db reading: Invalid mob-class %d, pet not read.\n", nameid); - continue; - } - - pet_db[j].class_ = nameid; - safestrncpy(pet_db[j].name,str[1],NAME_LENGTH); - safestrncpy(pet_db[j].jname,str[2],NAME_LENGTH); - pet_db[j].itemID=atoi(str[3]); - pet_db[j].EggID=atoi(str[4]); - pet_db[j].AcceID=atoi(str[5]); - pet_db[j].FoodID=atoi(str[6]); - pet_db[j].fullness=atoi(str[7]); - pet_db[j].hungry_delay=atoi(str[8])*1000; - pet_db[j].r_hungry=atoi(str[9]); - if (pet_db[j].r_hungry <= 0) - pet_db[j].r_hungry=1; - pet_db[j].r_full=atoi(str[10]); - pet_db[j].intimate=atoi(str[11]); - pet_db[j].die=atoi(str[12]); - pet_db[j].capture=atoi(str[13]); - pet_db[j].speed=atoi(str[14]); - pet_db[j].s_perfor=(char)atoi(str[15]); - pet_db[j].talk_convert_class=atoi(str[16]); - pet_db[j].attack_rate=atoi(str[17]); - pet_db[j].defence_attack_rate=atoi(str[18]); - pet_db[j].change_target_rate=atoi(str[19]); - pet_db[j].pet_script = NULL; - pet_db[j].equip_script = NULL; - - if (*str[20]) - pet_db[j].pet_script = parse_script(str[20], filename[i], lines, 0); - if (*str[21]) - pet_db[j].equip_script = parse_script(str[21], filename[i], lines, 0); - - j++; - entries++; - } - - if (j >= MAX_PET_DB) - ShowWarning("read_petdb: Reached max number of pets [%d]. Remaining pets were not read.\n ", MAX_PET_DB); - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n", entries, filename[i]); - } - return 0; + char* filename[] = {"pet_db.txt","pet_db2.txt"}; + FILE *fp; + int nameid,i,j,k; + + // Remove any previous scripts in case reloaddb was invoked. + for( j = 0; j < MAX_PET_DB; j++ ) + { + if( pet_db[j].pet_script ) + { + script_free_code(pet_db[j].pet_script); + pet_db[j].pet_script = NULL; + } + if( pet_db[j].equip_script ) + { + script_free_code(pet_db[j].equip_script); + pet_db[j].pet_script = NULL; + } + } + + // clear database + memset(pet_db,0,sizeof(pet_db)); + + j = 0; // entry counter + for( i = 0; i < ARRAYLENGTH(filename); i++ ) + { + char line[1024]; + int lines, entries; + + sprintf(line, "%s/%s", db_path, filename[i]); + fp=fopen(line,"r"); + if( fp == NULL ) + { + if( i == 0 ) + ShowError("can't read %s\n",line); + continue; + } + + lines = entries = 0; + while( fgets(line, sizeof(line), fp) && j < MAX_PET_DB ) + { + char *str[22], *p; + lines++; + + if(line[0] == '/' && line[1] == '/') + continue; + memset(str, 0, sizeof(str)); + p = line; + while( ISSPACE(*p) ) + ++p; + if( *p == '\0' ) + continue; // empty line + for( k = 0; k < 20; ++k ) + { + str[k] = p; + p = strchr(p,','); + if( p == NULL ) + break; // comma not found + *p = '\0'; + ++p; + } + + if( p == NULL ) + { + ShowError("read_petdb: Insufficient columns in line %d, skipping.\n", lines); + continue; + } + + // Pet Script + if( *p != '{' ) + { + ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines); + continue; + } + + str[20] = p; + p = strstr(p+1,"},"); + if( p == NULL ) + { + ShowError("read_petdb: Invalid format (Pet Script column) in line %d, skipping.\n", lines); + continue; + } + p[1] = '\0'; + p += 2; + + // Equip Script + if( *p != '{' ) + { + ShowError("read_petdb: Invalid format (Equip Script column) in line %d, skipping.\n", lines); + continue; + } + str[21] = p; + + if( (nameid = atoi(str[0])) <= 0 ) + continue; + + if( !mobdb_checkid(nameid) ) + { + ShowWarning("pet_db reading: Invalid mob-class %d, pet not read.\n", nameid); + continue; + } + + pet_db[j].class_ = nameid; + safestrncpy(pet_db[j].name,str[1],NAME_LENGTH); + safestrncpy(pet_db[j].jname,str[2],NAME_LENGTH); + pet_db[j].itemID=atoi(str[3]); + pet_db[j].EggID=atoi(str[4]); + pet_db[j].AcceID=atoi(str[5]); + pet_db[j].FoodID=atoi(str[6]); + pet_db[j].fullness=atoi(str[7]); + pet_db[j].hungry_delay=atoi(str[8])*1000; + pet_db[j].r_hungry=atoi(str[9]); + if( pet_db[j].r_hungry <= 0 ) + pet_db[j].r_hungry=1; + pet_db[j].r_full=atoi(str[10]); + pet_db[j].intimate=atoi(str[11]); + pet_db[j].die=atoi(str[12]); + pet_db[j].capture=atoi(str[13]); + pet_db[j].speed=atoi(str[14]); + pet_db[j].s_perfor=(char)atoi(str[15]); + pet_db[j].talk_convert_class=atoi(str[16]); + pet_db[j].attack_rate=atoi(str[17]); + pet_db[j].defence_attack_rate=atoi(str[18]); + pet_db[j].change_target_rate=atoi(str[19]); + pet_db[j].pet_script = NULL; + pet_db[j].equip_script = NULL; + + if( *str[20] ) + pet_db[j].pet_script = parse_script(str[20], filename[i], lines, 0); + if( *str[21] ) + pet_db[j].equip_script = parse_script(str[21], filename[i], lines, 0); + + j++; + entries++; + } + + if( j >= MAX_PET_DB ) + ShowWarning("read_petdb: Reached max number of pets [%d]. Remaining pets were not read.\n ", MAX_PET_DB); + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n", entries, filename[i]); + } + return 0; } /*========================================== @@ -1330,37 +1349,40 @@ int read_petdb() *------------------------------------------*/ int do_init_pet(void) { - read_petdb(); - - item_drop_ers = ers_new(sizeof(struct item_drop),"pet.c::item_drop_ers",ERS_OPT_NONE); - item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"pet.c::item_drop_list_ers",ERS_OPT_NONE); - - 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_delay_item_drop,"pet_delay_item_drop"); - add_timer_func_list(pet_skill_support_timer, "pet_skill_support_timer"); // [Skotlex] - add_timer_func_list(pet_recovery_timer,"pet_recovery_timer"); // [Valaris] - add_timer_func_list(pet_heal_timer,"pet_heal_timer"); // [Valaris] - add_timer_interval(gettick()+MIN_PETTHINKTIME,pet_ai_hard,0,0,MIN_PETTHINKTIME); - - return 0; + read_petdb(); + + item_drop_ers = ers_new(sizeof(struct item_drop),"pet.c::item_drop_ers",ERS_OPT_NONE); + item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"pet.c::item_drop_list_ers",ERS_OPT_NONE); + + 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_delay_item_drop,"pet_delay_item_drop"); + add_timer_func_list(pet_skill_support_timer, "pet_skill_support_timer"); // [Skotlex] + add_timer_func_list(pet_recovery_timer,"pet_recovery_timer"); // [Valaris] + add_timer_func_list(pet_heal_timer,"pet_heal_timer"); // [Valaris] + add_timer_interval(gettick()+MIN_PETTHINKTIME,pet_ai_hard,0,0,MIN_PETTHINKTIME); + + return 0; } int do_final_pet(void) { - int i; - for (i = 0; i < MAX_PET_DB; i++) { - if (pet_db[i].pet_script) { - script_free_code(pet_db[i].pet_script); - pet_db[i].pet_script = NULL; - } - if (pet_db[i].equip_script) { - script_free_code(pet_db[i].equip_script); - pet_db[i].equip_script = NULL; - } - } - ers_destroy(item_drop_ers); - ers_destroy(item_drop_list_ers); - return 0; + int i; + for( i = 0; i < MAX_PET_DB; i++ ) + { + if( pet_db[i].pet_script ) + { + script_free_code(pet_db[i].pet_script); + pet_db[i].pet_script = NULL; + } + if( pet_db[i].equip_script ) + { + script_free_code(pet_db[i].equip_script); + pet_db[i].equip_script = NULL; + } + } + ers_destroy(item_drop_ers); + ers_destroy(item_drop_list_ers); + return 0; } diff --git a/src/map/pet.h b/src/map/pet.h index 3ac849111..b46f55229 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -4,98 +4,98 @@ #ifndef _PET_H_ #define _PET_H_ -#define MAX_PET_DB 300 -#define MAX_PETLOOT_SIZE 30 +#define MAX_PET_DB 300 +#define MAX_PETLOOT_SIZE 30 struct s_pet_db { - short class_; - char name[NAME_LENGTH],jname[NAME_LENGTH]; - short itemID; - short EggID; - short AcceID; - short FoodID; - int fullness; - int hungry_delay; - int r_hungry; - int r_full; - int intimate; - int die; - int capture; - int speed; - char s_perfor; - int talk_convert_class; - int attack_rate; - int defence_attack_rate; - int change_target_rate; - struct script_code *equip_script; - struct script_code *pet_script; + short class_; + char name[NAME_LENGTH],jname[NAME_LENGTH]; + short itemID; + short EggID; + short AcceID; + short FoodID; + int fullness; + int hungry_delay; + int r_hungry; + int r_full; + int intimate; + int die; + int capture; + int speed; + char s_perfor; + int talk_convert_class; + int attack_rate; + int defence_attack_rate; + int change_target_rate; + struct script_code *equip_script; + struct script_code *pet_script; }; extern struct s_pet_db pet_db[MAX_PET_DB]; enum { PET_CLASS,PET_CATCH,PET_EGG,PET_EQUIP,PET_FOOD }; struct pet_recovery { //Stat recovery - enum sc_type type; //Status Change id - unsigned short delay; //How long before curing (secs). - int timer; + enum sc_type type; //Status Change id + unsigned short delay; //How long before curing (secs). + int timer; }; struct pet_bonus { - unsigned short type; //bStr, bVit? - unsigned short val; //Qty - unsigned short duration; //in secs - unsigned short delay; //Time before RENEWAL_CAST (secs) - int timer; + unsigned short type; //bStr, bVit? + unsigned short val; //Qty + unsigned short duration; //in secs + unsigned short delay; //Time before RENEWAL_CAST (secs) + int timer; }; struct pet_skill_attack { //Attack Skill - unsigned short id; - unsigned short lv; - unsigned short div_; //0 = Normal skill. >0 = Fixed damage (lv), fixed div_. - unsigned short rate; //Base chance of skill ocurrance (10 = 10% of attacks) - unsigned short bonusrate; //How being 100% loyal affects cast rate (10 = At 1000 intimacy->rate+10% + unsigned short id; + unsigned short lv; + unsigned short div_; //0 = Normal skill. >0 = Fixed damage (lv), fixed div_. + unsigned short rate; //Base chance of skill ocurrance (10 = 10% of attacks) + unsigned short bonusrate; //How being 100% loyal affects cast rate (10 = At 1000 intimacy->rate+10% }; struct pet_skill_support { //Support Skill - unsigned short id; - unsigned short lv; - unsigned short hp; //Max HP% for skill to trigger (50 -> 50% for Magnificat) - unsigned short sp; //Max SP% for skill to trigger (100 = no check) - unsigned short delay; //Time (secs) between being able to recast. - int timer; + unsigned short id; + unsigned short lv; + unsigned short hp; //Max HP% for skill to trigger (50 -> 50% for Magnificat) + unsigned short sp; //Max SP% for skill to trigger (100 = no check) + unsigned short delay; //Time (secs) between being able to recast. + int timer; }; struct pet_loot { - struct item *item; - unsigned short count; - unsigned short weight; - unsigned short max; + struct item *item; + unsigned short count; + unsigned short weight; + unsigned short max; }; struct pet_data { - struct block_list bl; - struct unit_data ud; - struct view_data vd; - struct s_pet pet; - struct status_data status; - struct mob_db *db; - struct s_pet_db *petDB; - int pet_hungry_timer; - int target_id; - struct { - unsigned skillbonus : 1; - } state; - int move_fail_count; - unsigned int next_walktime,last_thinktime; - short rate_fix; //Support rate as modified by intimacy (1000 = 100%) [Skotlex] - - struct pet_recovery *recovery; - struct pet_bonus *bonus; - struct pet_skill_attack *a_skill; - struct pet_skill_support *s_skill; - struct pet_loot *loot; - - struct map_session_data *msd; + struct block_list bl; + struct unit_data ud; + struct view_data vd; + struct s_pet pet; + struct status_data status; + struct mob_db *db; + struct s_pet_db *petDB; + int pet_hungry_timer; + int target_id; + struct { + unsigned skillbonus : 1; + } state; + int move_fail_count; + unsigned int next_walktime,last_thinktime; + short rate_fix; //Support rate as modified by intimacy (1000 = 100%) [Skotlex] + + struct pet_recovery* recovery; + struct pet_bonus* bonus; + struct pet_skill_attack* a_skill; + struct pet_skill_support* s_skill; + struct pet_loot* loot; + + struct map_session_data *msd; }; @@ -117,7 +117,7 @@ int pet_catch_process2(struct map_session_data *sd,int target_id); int pet_get_egg(int account_id,int pet_id,int flag); int pet_menu(struct map_session_data *sd,int menunum); int pet_change_name(struct map_session_data *sd,char *name); -int pet_change_name_ack(struct map_session_data *sd, char *name, int flag); +int pet_change_name_ack(struct map_session_data *sd, char* name, int flag); int pet_equipitem(struct map_session_data *sd,int index); int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd); int pet_attackskill(struct pet_data *pd, int target_id); diff --git a/src/map/quest.c b/src/map/quest.c index 07c3097a8..c7ca06514 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -38,317 +38,321 @@ struct s_quest_db quest_db[MAX_QUEST_DB]; int quest_search_db(int quest_id) { - int i; + int i; - ARR_FIND(0, MAX_QUEST_DB,i,quest_id == quest_db[i].id); - if (i == MAX_QUEST_DB) - return -1; + ARR_FIND(0, MAX_QUEST_DB,i,quest_id == quest_db[i].id); + if( i == MAX_QUEST_DB ) + return -1; - return i; + return i; } //Send quest info on login -int quest_pc_login(TBL_PC *sd) +int quest_pc_login(TBL_PC * sd) { - if (sd->avail_quests == 0) - return 1; + if(sd->avail_quests == 0) + return 1; - clif_quest_send_list(sd); - clif_quest_send_mission(sd); + clif_quest_send_list(sd); + clif_quest_send_mission(sd); - return 0; + return 0; } -int quest_add(TBL_PC *sd, int quest_id) +int quest_add(TBL_PC * sd, int quest_id) { - int i, j; + int i, j; - if (sd->num_quests >= MAX_QUEST_DB) { - ShowError("quest_add: Character %d has got all the quests.(max quests: %d)\n", sd->status.char_id, MAX_QUEST_DB); - return 1; - } + if( sd->num_quests >= MAX_QUEST_DB ) + { + ShowError("quest_add: Character %d has got all the quests.(max quests: %d)\n", sd->status.char_id, MAX_QUEST_DB); + return 1; + } - if (quest_check(sd, quest_id, HAVEQUEST) >= 0) { - ShowError("quest_add: Character %d already has quest %d.\n", sd->status.char_id, quest_id); - return -1; - } + if( quest_check(sd, quest_id, HAVEQUEST) >= 0 ) + { + ShowError("quest_add: Character %d already has quest %d.\n", sd->status.char_id, quest_id); + return -1; + } - if ((j = quest_search_db(quest_id)) < 0) { - ShowError("quest_add: quest %d not found in DB.\n", quest_id); - return -1; - } + if( (j = quest_search_db(quest_id)) < 0 ) + { + ShowError("quest_add: quest %d not found in DB.\n", quest_id); + return -1; + } - i = sd->avail_quests; - memmove(&sd->quest_log[i+1], &sd->quest_log[i], sizeof(struct quest)*(sd->num_quests-sd->avail_quests)); - memmove(sd->quest_index+i+1, sd->quest_index+i, sizeof(int)*(sd->num_quests-sd->avail_quests)); + i = sd->avail_quests; + memmove(&sd->quest_log[i+1], &sd->quest_log[i], sizeof(struct quest)*(sd->num_quests-sd->avail_quests)); + memmove(sd->quest_index+i+1, sd->quest_index+i, sizeof(int)*(sd->num_quests-sd->avail_quests)); - memset(&sd->quest_log[i], 0, sizeof(struct quest)); - sd->quest_log[i].quest_id = quest_db[j].id; - if (quest_db[j].time) - sd->quest_log[i].time = (unsigned int)(time(NULL) + quest_db[j].time); - sd->quest_log[i].state = Q_ACTIVE; + memset(&sd->quest_log[i], 0, sizeof(struct quest)); + sd->quest_log[i].quest_id = quest_db[j].id; + if( quest_db[j].time ) + sd->quest_log[i].time = (unsigned int)(time(NULL) + quest_db[j].time); + sd->quest_log[i].state = Q_ACTIVE; - sd->quest_index[i] = j; - sd->num_quests++; - sd->avail_quests++; - sd->save_quest = true; + sd->quest_index[i] = j; + sd->num_quests++; + sd->avail_quests++; + sd->save_quest = true; - clif_quest_add(sd, &sd->quest_log[i], sd->quest_index[i]); + clif_quest_add(sd, &sd->quest_log[i], sd->quest_index[i]); - if (save_settings&64) - chrif_save(sd,0); + if( save_settings&64 ) + chrif_save(sd,0); - return 0; + return 0; } -int quest_change(TBL_PC *sd, int qid1, int qid2) +int quest_change(TBL_PC * sd, int qid1, int qid2) { - int i, j; - - if (quest_check(sd, qid2, HAVEQUEST) >= 0) { - ShowError("quest_change: Character %d already has quest %d.\n", sd->status.char_id, qid2); - return -1; - } - - if (quest_check(sd, qid1, HAVEQUEST) < 0) { - ShowError("quest_change: Character %d doesn't have quest %d.\n", sd->status.char_id, qid1); - return -1; - } - - if ((j = quest_search_db(qid2)) < 0) { - ShowError("quest_change: quest %d not found in DB.\n",qid2); - return -1; - } - - ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == qid1); - if (i == sd->avail_quests) { - ShowError("quest_change: Character %d has completed quests %d.\n", sd->status.char_id, qid1); - return -1; - } - - memset(&sd->quest_log[i], 0, sizeof(struct quest)); - sd->quest_log[i].quest_id = quest_db[j].id; - if (quest_db[j].time) - sd->quest_log[i].time = (unsigned int)(time(NULL) + quest_db[j].time); - sd->quest_log[i].state = Q_ACTIVE; - - sd->quest_index[i] = j; - sd->save_quest = true; - - clif_quest_delete(sd, qid1); - clif_quest_add(sd, &sd->quest_log[i], sd->quest_index[i]); - - if (save_settings&64) - chrif_save(sd,0); - - return 0; + int i, j; + + if( quest_check(sd, qid2, HAVEQUEST) >= 0 ) + { + ShowError("quest_change: Character %d already has quest %d.\n", sd->status.char_id, qid2); + return -1; + } + + if( quest_check(sd, qid1, HAVEQUEST) < 0 ) + { + ShowError("quest_change: Character %d doesn't have quest %d.\n", sd->status.char_id, qid1); + return -1; + } + + if( (j = quest_search_db(qid2)) < 0 ) + { + ShowError("quest_change: quest %d not found in DB.\n",qid2); + return -1; + } + + ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == qid1); + if(i == sd->avail_quests) + { + ShowError("quest_change: Character %d has completed quests %d.\n", sd->status.char_id, qid1); + return -1; + } + + memset(&sd->quest_log[i], 0, sizeof(struct quest)); + sd->quest_log[i].quest_id = quest_db[j].id; + if( quest_db[j].time ) + sd->quest_log[i].time = (unsigned int)(time(NULL) + quest_db[j].time); + sd->quest_log[i].state = Q_ACTIVE; + + sd->quest_index[i] = j; + sd->save_quest = true; + + clif_quest_delete(sd, qid1); + clif_quest_add(sd, &sd->quest_log[i], sd->quest_index[i]); + + if( save_settings&64 ) + chrif_save(sd,0); + + return 0; } -int quest_delete(TBL_PC *sd, int quest_id) +int quest_delete(TBL_PC * sd, int quest_id) { - int i; - - //Search for quest - ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id); - if (i == sd->num_quests) { - ShowError("quest_delete: Character %d doesn't have quest %d.\n", sd->status.char_id, quest_id); - return -1; - } - - if (sd->quest_log[i].state != Q_COMPLETE) - sd->avail_quests--; - if (sd->num_quests-- < MAX_QUEST_DB && sd->quest_log[i+1].quest_id) { - memmove(&sd->quest_log[i], &sd->quest_log[i+1], sizeof(struct quest)*(sd->num_quests-i)); - memmove(sd->quest_index+i, sd->quest_index+i+1, sizeof(int)*(sd->num_quests-i)); - } - memset(&sd->quest_log[sd->num_quests], 0, sizeof(struct quest)); - sd->quest_index[sd->num_quests] = 0; - sd->save_quest = true; - - clif_quest_delete(sd, quest_id); - - if (save_settings&64) - chrif_save(sd,0); - - return 0; + int i; + + //Search for quest + ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id); + if(i == sd->num_quests) + { + ShowError("quest_delete: Character %d doesn't have quest %d.\n", sd->status.char_id, quest_id); + return -1; + } + + if( sd->quest_log[i].state != Q_COMPLETE ) + sd->avail_quests--; + if( sd->num_quests-- < MAX_QUEST_DB && sd->quest_log[i+1].quest_id ) + { + memmove(&sd->quest_log[i], &sd->quest_log[i+1], sizeof(struct quest)*(sd->num_quests-i)); + memmove(sd->quest_index+i, sd->quest_index+i+1, sizeof(int)*(sd->num_quests-i)); + } + memset(&sd->quest_log[sd->num_quests], 0, sizeof(struct quest)); + sd->quest_index[sd->num_quests] = 0; + sd->save_quest = true; + + clif_quest_delete(sd, quest_id); + + if( save_settings&64 ) + chrif_save(sd,0); + + return 0; } int quest_update_objective_sub(struct block_list *bl, va_list ap) { - struct map_session_data *sd; - int mob, party; + struct map_session_data * sd; + int mob, party; - nullpo_ret(bl); - nullpo_ret(sd = (struct map_session_data *)bl); + nullpo_ret(bl); + nullpo_ret(sd = (struct map_session_data *)bl); - party = va_arg(ap,int); - mob = va_arg(ap,int); + party = va_arg(ap,int); + mob = va_arg(ap,int); - if (!sd->avail_quests) - return 0; - if (sd->status.party_id != party) - return 0; + if( !sd->avail_quests ) + return 0; + if( sd->status.party_id != party ) + return 0; - quest_update_objective(sd, mob); + quest_update_objective(sd, mob); - return 1; + return 1; } -void quest_update_objective(TBL_PC *sd, int mob) -{ - int i,j; - - for (i = 0; i < sd->avail_quests; i++) { - if (sd->quest_log[i].state != Q_ACTIVE) - continue; - - for (j = 0; j < MAX_QUEST_OBJECTIVES; j++) - if (quest_db[sd->quest_index[i]].mob[j] == mob && sd->quest_log[i].count[j] < quest_db[sd->quest_index[i]].count[j]) { - sd->quest_log[i].count[j]++; - sd->save_quest = true; - clif_quest_update_objective(sd,&sd->quest_log[i],sd->quest_index[i]); - } - } +void quest_update_objective(TBL_PC * sd, int mob) { + int i,j; + + for( i = 0; i < sd->avail_quests; i++ ) { + if( sd->quest_log[i].state != Q_ACTIVE ) + continue; + + for( j = 0; j < MAX_QUEST_OBJECTIVES; j++ ) + if( quest_db[sd->quest_index[i]].mob[j] == mob && sd->quest_log[i].count[j] < quest_db[sd->quest_index[i]].count[j] ) { + sd->quest_log[i].count[j]++; + sd->save_quest = true; + clif_quest_update_objective(sd,&sd->quest_log[i],sd->quest_index[i]); + } + } } -int quest_update_status(TBL_PC *sd, int quest_id, quest_state status) -{ - int i; +int quest_update_status(TBL_PC * sd, int quest_id, quest_state status) { + int i; - //Only status of active and inactive quests can be updated. Completed quests can't (for now). [Inkfish] - ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == quest_id); - if (i == sd->avail_quests) { - ShowError("quest_update_status: Character %d doesn't have quest %d.\n", sd->status.char_id, quest_id); - return -1; - } + //Only status of active and inactive quests can be updated. Completed quests can't (for now). [Inkfish] + ARR_FIND(0, sd->avail_quests, i, sd->quest_log[i].quest_id == quest_id); + if(i == sd->avail_quests) { + ShowError("quest_update_status: Character %d doesn't have quest %d.\n", sd->status.char_id, quest_id); + return -1; + } - sd->quest_log[i].state = status; - sd->save_quest = true; + sd->quest_log[i].state = status; + sd->save_quest = true; - if (status < Q_COMPLETE) { - clif_quest_update_status(sd, quest_id, (bool)status); - return 0; - } + if( status < Q_COMPLETE ) { + clif_quest_update_status(sd, quest_id, (bool)status); + return 0; + } - if (i != (--sd->avail_quests)) { - struct quest tmp_quest; - memcpy(&tmp_quest, &sd->quest_log[i],sizeof(struct quest)); - memcpy(&sd->quest_log[i], &sd->quest_log[sd->avail_quests],sizeof(struct quest)); - memcpy(&sd->quest_log[sd->avail_quests], &tmp_quest,sizeof(struct quest)); - } + if( i != (--sd->avail_quests) ) { + struct quest tmp_quest; + memcpy(&tmp_quest, &sd->quest_log[i],sizeof(struct quest)); + memcpy(&sd->quest_log[i], &sd->quest_log[sd->avail_quests],sizeof(struct quest)); + memcpy(&sd->quest_log[sd->avail_quests], &tmp_quest,sizeof(struct quest)); + } - clif_quest_delete(sd, quest_id); + clif_quest_delete(sd, quest_id); - if (save_settings&64) - chrif_save(sd,0); + if( save_settings&64 ) + chrif_save(sd,0); - return 0; + return 0; } -int quest_check(TBL_PC *sd, int quest_id, quest_check_type type) -{ - int i; - - ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id); - if (i == sd->num_quests) - return -1; - - switch (type) { - case HAVEQUEST: - return sd->quest_log[i].state; - case PLAYTIME: - return (sd->quest_log[i].time < (unsigned int)time(NULL) ? 2 : sd->quest_log[i].state == Q_COMPLETE ? 1 : 0); - case HUNTING: { - if (sd->quest_log[i].state == 0 || sd->quest_log[i].state == 1) { - int j; - ARR_FIND(0, MAX_QUEST_OBJECTIVES, j, sd->quest_log[i].count[j] < quest_db[sd->quest_index[i]].count[j]); - if (j == MAX_QUEST_OBJECTIVES) - return 2; - if (sd->quest_log[i].time < (unsigned int)time(NULL)) - return 1; - return 0; - } else - return 0; - } - default: - ShowError("quest_check_quest: Unknown parameter %d",type); - break; - } - - return -1; +int quest_check(TBL_PC * sd, int quest_id, quest_check_type type) { + int i; + + ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id); + if( i == sd->num_quests ) + return -1; + + switch( type ) { + case HAVEQUEST: + return sd->quest_log[i].state; + case PLAYTIME: + return (sd->quest_log[i].time < (unsigned int)time(NULL) ? 2 : sd->quest_log[i].state == Q_COMPLETE ? 1 : 0); + case HUNTING: { + if( sd->quest_log[i].state == 0 || sd->quest_log[i].state == 1 ) { + int j; + ARR_FIND(0, MAX_QUEST_OBJECTIVES, j, sd->quest_log[i].count[j] < quest_db[sd->quest_index[i]].count[j]); + if( j == MAX_QUEST_OBJECTIVES ) + return 2; + if( sd->quest_log[i].time < (unsigned int)time(NULL) ) + return 1; + return 0; + } else + return 0; + } + default: + ShowError("quest_check_quest: Unknown parameter %d",type); + break; + } + + return -1; } -int quest_read_db(void) -{ - FILE *fp; - char line[1024]; - int i,j,k = 0; - char *str[20],*p,*np; - - sprintf(line, "%s/quest_db.txt", db_path); - if ((fp=fopen(line,"r"))==NULL) { - ShowError("can't read %s\n", line); - return -1; - } - - while (fgets(line, sizeof(line), fp)) { - - if (k == MAX_QUEST_DB) { - ShowError("quest_read_db: Too many entries specified in %s/quest_db.txt!\n", db_path); - break; - } - - if (line[0]=='/' && line[1]=='/') - continue; - memset(str,0,sizeof(str)); - - for (j = 0, p = line; j < 8; j++) { - if ((np = strchr(p,',')) != NULL) { - str[j] = p; - *np = 0; - p = np + 1; - } else if (str[0] == NULL) - continue; - else { - ShowError("quest_read_db: insufficient columns in line %s\n", line); - continue; - } - } - if (str[0]==NULL) - continue; - - memset(&quest_db[k], 0, sizeof(quest_db[0])); - - quest_db[k].id = atoi(str[0]); - quest_db[k].time = atoi(str[1]); - - for (i = 0; i < MAX_QUEST_OBJECTIVES; i++) { - quest_db[k].mob[i] = atoi(str[2*i+2]); - quest_db[k].count[i] = atoi(str[2*i+3]); - - if (!quest_db[k].mob[i] || !quest_db[k].count[i]) - break; - } - - quest_db[k].num_objectives = i; - - k++; - } - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", k, "quest_db.txt"); - return 0; +int quest_read_db(void) { + FILE *fp; + char line[1024]; + int i,j,k = 0; + char *str[20],*p,*np; + + sprintf(line, "%s/quest_db.txt", db_path); + if( (fp=fopen(line,"r"))==NULL ){ + ShowError("can't read %s\n", line); + return -1; + } + + while(fgets(line, sizeof(line), fp)) { + + if (k == MAX_QUEST_DB) { + ShowError("quest_read_db: Too many entries specified in %s/quest_db.txt!\n", db_path); + break; + } + + if(line[0]=='/' && line[1]=='/') + continue; + memset(str,0,sizeof(str)); + + for( j = 0, p = line; j < 8; j++ ) { + if( ( np = strchr(p,',') ) != NULL ) { + str[j] = p; + *np = 0; + p = np + 1; + } + else if (str[0] == NULL) + continue; + else { + ShowError("quest_read_db: insufficient columns in line %s\n", line); + continue; + } + } + if(str[0]==NULL) + continue; + + memset(&quest_db[k], 0, sizeof(quest_db[0])); + + quest_db[k].id = atoi(str[0]); + quest_db[k].time = atoi(str[1]); + + for( i = 0; i < MAX_QUEST_OBJECTIVES; i++ ) { + quest_db[k].mob[i] = atoi(str[2*i+2]); + quest_db[k].count[i] = atoi(str[2*i+3]); + + if( !quest_db[k].mob[i] || !quest_db[k].count[i] ) + break; + } + + quest_db[k].num_objectives = i; + + k++; + } + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", k, "quest_db.txt"); + return 0; } -void do_init_quest(void) -{ - quest_read_db(); +void do_init_quest(void) { + quest_read_db(); } -void do_reload_quest(void) -{ - memset(&quest_db, 0, sizeof(quest_db)); - quest_read_db(); +void do_reload_quest(void) { + memset(&quest_db, 0, sizeof(quest_db)); + quest_read_db(); } diff --git a/src/map/quest.h b/src/map/quest.h index 239b9f593..7f638a54c 100644 --- a/src/map/quest.h +++ b/src/map/quest.h @@ -5,26 +5,26 @@ #define _QUEST_H_ struct s_quest_db { - int id; - unsigned int time; - int mob[MAX_QUEST_OBJECTIVES]; - int count[MAX_QUEST_OBJECTIVES]; - int num_objectives; - //char name[NAME_LENGTH]; + int id; + unsigned int time; + int mob[MAX_QUEST_OBJECTIVES]; + int count[MAX_QUEST_OBJECTIVES]; + int num_objectives; + //char name[NAME_LENGTH]; }; extern struct s_quest_db quest_db[MAX_QUEST_DB]; typedef enum quest_check_type { HAVEQUEST, PLAYTIME, HUNTING } quest_check_type; -int quest_pc_login(TBL_PC *sd); +int quest_pc_login(TBL_PC * sd); -int quest_add(TBL_PC *sd, int quest_id); -int quest_delete(TBL_PC *sd, int quest_id); -int quest_change(TBL_PC *sd, int qid1, int qid2); +int quest_add(TBL_PC * sd, int quest_id); +int quest_delete(TBL_PC * sd, int quest_id); +int quest_change(TBL_PC * sd, int qid1, int qid2); int quest_update_objective_sub(struct block_list *bl, va_list ap); -void quest_update_objective(TBL_PC *sd, int mob); -int quest_update_status(TBL_PC *sd, int quest_id, quest_state status); -int quest_check(TBL_PC *sd, int quest_id, quest_check_type type); +void quest_update_objective(TBL_PC * sd, int mob); +int quest_update_status(TBL_PC * sd, int quest_id, quest_state status); +int quest_check(TBL_PC * sd, int quest_id, quest_check_type type); int quest_search_db(int quest_id); diff --git a/src/map/script.c b/src/map/script.c index 8ff244538..f1a422b7e 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -13,7 +13,7 @@ #include "../common/nullpo.h" #include "../common/random.h" #include "../common/showmsg.h" -#include "../common/socket.h" // usage: getcharip +#include "../common/socket.h" // usage: getcharip #include "../common/strlib.h" #include "../common/timer.h" #include "../common/utils.h" @@ -55,17 +55,17 @@ #include <string.h> #include <math.h> #ifndef WIN32 -#include <sys/time.h> + #include <sys/time.h> #endif #include <time.h> #include <setjmp.h> #include <errno.h> #ifdef BETA_THREAD_TEST -#include "../common/atomic.h" -#include "../common/spinlock.h" -#include "../common/thread.h" -#include "../common/mutex.h" + #include "../common/atomic.h" + #include "../common/spinlock.h" + #include "../common/thread.h" + #include "../common/mutex.h" #endif @@ -166,8 +166,8 @@ #define is_string_variable(name) ( (name)[strlen(name) - 1] == '$' ) #define FETCH(n, t) \ - if( script_hasdata(st,n) ) \ - (t)=script_getnum(st,n); + if( script_hasdata(st,n) ) \ + (t)=script_getnum(st,n); /// Maximum amount of elements in script arrays #define SCRIPT_MAX_ARRAYSIZE 128 @@ -177,30 +177,30 @@ enum { LABEL_NEXTLINE=1,LABEL_START }; /// temporary buffer for passing around compiled bytecode /// @see add_scriptb, set_label, parse_script -static unsigned char *script_buf = NULL; +static unsigned char* script_buf = NULL; static int script_pos = 0, script_size = 0; -static inline int GETVALUE(const unsigned char *buf, int i) +static inline int GETVALUE(const unsigned char* buf, int i) { - return (int)MakeDWord(MakeWord(buf[i], buf[i+1]), MakeWord(buf[i+2], 0)); + return (int)MakeDWord(MakeWord(buf[i], buf[i+1]), MakeWord(buf[i+2], 0)); } -static inline void SETVALUE(unsigned char *buf, int i, int n) +static inline void SETVALUE(unsigned char* buf, int i, int n) { - buf[i] = GetByte(n, 0); - buf[i+1] = GetByte(n, 1); - buf[i+2] = GetByte(n, 2); + buf[i] = GetByte(n, 0); + buf[i+1] = GetByte(n, 1); + buf[i+2] = GetByte(n, 2); } // String buffer structures. // str_data stores string information static struct str_data_struct { - enum c_op type; - int str; - int backpatch; - int label; - int (*func)(struct script_state *st); - int val; - int next; + enum c_op type; + int str; + int backpatch; + int label; + int (*func)(struct script_state *st); + int val; + int next; } *str_data = NULL; static int str_data_size = 0; // size of the data static int str_num = LABEL_START; // next id to be assigned @@ -219,17 +219,11 @@ int str_hash[SCRIPT_HASH_SIZE]; //#define SCRIPT_HASH_SDBM #define SCRIPT_HASH_ELF -static DBMap *scriptlabel_db=NULL; // const char* label_name -> int script_pos -static DBMap *userfunc_db=NULL; // const char* func_name -> struct script_code* +static DBMap* scriptlabel_db=NULL; // const char* label_name -> int script_pos +static DBMap* userfunc_db=NULL; // const char* func_name -> struct script_code* static int parse_options=0; -DBMap *script_get_label_db(void) -{ - return scriptlabel_db; -} -DBMap *script_get_userfunc_db(void) -{ - return userfunc_db; -} +DBMap* script_get_label_db(void){ return scriptlabel_db; } +DBMap* script_get_userfunc_db(void){ return userfunc_db; } // important buildin function references for usage in scripts static int buildin_set_ref = 0; @@ -239,64 +233,65 @@ static int buildin_getelementofarray_ref = 0; // Caches compiled autoscript item code. // Note: This is not cleared when reloading itemdb. -static DBMap *autobonus_db=NULL; // char* script -> char* bytecode +static DBMap* autobonus_db=NULL; // char* script -> char* bytecode struct Script_Config script_config = { - 1, // warn_func_mismatch_argtypes - 1, 65535, 2048, //warn_func_mismatch_paramnum/check_cmdcount/check_gotocount - 0, INT_MAX, // input_min_value/input_max_value - "OnPCDieEvent", //die_event_name - "OnPCKillEvent", //kill_pc_event_name - "OnNPCKillEvent", //kill_mob_event_name - "OnPCLoginEvent", //login_event_name - "OnPCLogoutEvent", //logout_event_name - "OnPCLoadMapEvent", //loadmap_event_name - "OnPCBaseLvUpEvent", //baselvup_event_name - "OnPCJobLvUpEvent", //joblvup_event_name - "OnTouch_", //ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves) - "OnTouch", //ontouch2_name (run whenever a char walks into the OnTouch area) + 1, // warn_func_mismatch_argtypes + 1, 65535, 2048, //warn_func_mismatch_paramnum/check_cmdcount/check_gotocount + 0, INT_MAX, // input_min_value/input_max_value + "OnPCDieEvent", //die_event_name + "OnPCKillEvent", //kill_pc_event_name + "OnNPCKillEvent", //kill_mob_event_name + "OnPCLoginEvent", //login_event_name + "OnPCLogoutEvent", //logout_event_name + "OnPCLoadMapEvent", //loadmap_event_name + "OnPCBaseLvUpEvent", //baselvup_event_name + "OnPCJobLvUpEvent", //joblvup_event_name + "OnTouch_", //ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves) + "OnTouch", //ontouch2_name (run whenever a char walks into the OnTouch area) }; static jmp_buf error_jump; -static char *error_msg; -static const char *error_pos; +static char* error_msg; +static const char* error_pos; static int error_report; // if the error should produce output // for advanced scripting support ( nested if, switch, while, for, do-while, function, etc ) // [Eoe / jA 1080, 1081, 1094, 1164] enum curly_type { - TYPE_NULL = 0, - TYPE_IF, - TYPE_SWITCH, - TYPE_WHILE, - TYPE_FOR, - TYPE_DO, - TYPE_USERFUNC, - TYPE_ARGLIST // function argument list + TYPE_NULL = 0, + TYPE_IF, + TYPE_SWITCH, + TYPE_WHILE, + TYPE_FOR, + TYPE_DO, + TYPE_USERFUNC, + TYPE_ARGLIST // function argument list }; -enum e_arglist { - ARGLIST_UNDEFINED = 0, - ARGLIST_NO_PAREN = 1, - ARGLIST_PAREN = 2, +enum e_arglist +{ + ARGLIST_UNDEFINED = 0, + ARGLIST_NO_PAREN = 1, + ARGLIST_PAREN = 2, }; static struct { - struct { - enum curly_type type; - int index; - int count; - int flag; - struct linkdb_node *case_label; - } curly[256]; // Information right parenthesis - int curly_count; // The number of right brackets - int index; // Number of the syntax used in the script + struct { + enum curly_type type; + int index; + int count; + int flag; + struct linkdb_node *case_label; + } curly[256]; // Information right parenthesis + int curly_count; // The number of right brackets + int index; // Number of the syntax used in the script } syntax; -const char *parse_curly_close(const char *p); -const char *parse_syntax_close(const char *p); -const char *parse_syntax_close_sub(const char *p,int *flag); -const char *parse_syntax(const char *p); +const char* parse_curly_close(const char* p); +const char* parse_syntax_close(const char* p); +const char* parse_syntax_close_sub(const char* p,int* flag); +const char* parse_syntax(const char* p); static int parse_syntax_for_flag = 0; extern int current_equip_item_index; //for New CARDS Scripts. It contains Inventory Index of the EQUIP_SCRIPT caller item. [Lupus] @@ -309,14 +304,14 @@ c_op get_com(unsigned char *script,int *pos); int get_num(unsigned char *script,int *pos); typedef struct script_function { - int (*func)(struct script_state *st); - const char *name; - const char *arg; + int (*func)(struct script_state *st); + const char *name; + const char *arg; } script_function; extern script_function buildin_func[]; -static struct linkdb_node *sleep_db;// int oid -> struct script_state* +static struct linkdb_node* sleep_db;// int oid -> struct script_state* #ifdef BETA_THREAD_TEST /** @@ -324,285 +319,301 @@ static struct linkdb_node *sleep_db;// int oid -> struct script_state* **/ static SPIN_LOCK queryThreadLock; static rAthread queryThread = NULL; -static ramutex queryThreadMutex = NULL; -static racond queryThreadCond = NULL; +static ramutex queryThreadMutex = NULL; +static racond queryThreadCond = NULL; static volatile int32 queryThreadTerminate = 0; struct queryThreadEntry { - bool ok; - bool type; /* main db or log db? */ - struct script_state *st; + bool ok; + bool type; /* main db or log db? */ + struct script_state *st; }; /* Ladies and Gentleman the Manager! */ struct { - struct queryThreadEntry **entry;/* array of structs */ - int count; - int timer;/* used to receive processed entries */ + struct queryThreadEntry **entry;/* array of structs */ + int count; + int timer;/* used to receive processed entries */ } queryThreadData; #endif /*========================================== * (Only those needed) local declaration prototype *------------------------------------------*/ -const char *parse_subexpr(const char *p,int limit); +const char* parse_subexpr(const char* p,int limit); int run_func(struct script_state *st); enum { - MF_NOMEMO, //0 - MF_NOTELEPORT, - MF_NOSAVE, - MF_NOBRANCH, - MF_NOPENALTY, - MF_NOZENYPENALTY, - MF_PVP, - MF_PVP_NOPARTY, - MF_PVP_NOGUILD, - MF_GVG, - MF_GVG_NOPARTY, //10 - MF_NOTRADE, - MF_NOSKILL, - MF_NOWARP, - MF_PARTYLOCK, - MF_NOICEWALL, - MF_SNOW, - MF_FOG, - MF_SAKURA, - MF_LEAVES, - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //MF_RAIN, //20 - // 21 free - MF_NOGO = 22, - MF_CLOUDS, - MF_CLOUDS2, - MF_FIREWORKS, - MF_GVG_CASTLE, - MF_GVG_DUNGEON, - MF_NIGHTENABLED, - MF_NOBASEEXP, - MF_NOJOBEXP, //30 - MF_NOMOBLOOT, - MF_NOMVPLOOT, - MF_NORETURN, - MF_NOWARPTO, - MF_NIGHTMAREDROP, - MF_RESTRICTED, - MF_NOCOMMAND, - MF_NODROP, - MF_JEXP, - MF_BEXP, //40 - MF_NOVENDING, - MF_LOADEVENT, - MF_NOCHAT, - MF_NOEXPPENALTY, - MF_GUILDLOCK, - MF_TOWN, - MF_AUTOTRADE, - MF_ALLOWKS, - MF_MONSTER_NOTELEPORT, - MF_PVP_NOCALCRANK, //50 - MF_BATTLEGROUND, - MF_RESET + MF_NOMEMO, //0 + MF_NOTELEPORT, + MF_NOSAVE, + MF_NOBRANCH, + MF_NOPENALTY, + MF_NOZENYPENALTY, + MF_PVP, + MF_PVP_NOPARTY, + MF_PVP_NOGUILD, + MF_GVG, + MF_GVG_NOPARTY, //10 + MF_NOTRADE, + MF_NOSKILL, + MF_NOWARP, + MF_PARTYLOCK, + MF_NOICEWALL, + MF_SNOW, + MF_FOG, + MF_SAKURA, + MF_LEAVES, + /** + * No longer available, keeping here just in case it's back someday. [Ind] + **/ + //MF_RAIN, //20 + // 21 free + MF_NOGO = 22, + MF_CLOUDS, + MF_CLOUDS2, + MF_FIREWORKS, + MF_GVG_CASTLE, + MF_GVG_DUNGEON, + MF_NIGHTENABLED, + MF_NOBASEEXP, + MF_NOJOBEXP, //30 + MF_NOMOBLOOT, + MF_NOMVPLOOT, + MF_NORETURN, + MF_NOWARPTO, + MF_NIGHTMAREDROP, + MF_RESTRICTED, + MF_NOCOMMAND, + MF_NODROP, + MF_JEXP, + MF_BEXP, //40 + MF_NOVENDING, + MF_LOADEVENT, + MF_NOCHAT, + MF_NOEXPPENALTY, + MF_GUILDLOCK, + MF_TOWN, + MF_AUTOTRADE, + MF_ALLOWKS, + MF_MONSTER_NOTELEPORT, + MF_PVP_NOCALCRANK, //50 + MF_BATTLEGROUND, + MF_RESET }; -const char *script_op2name(int op) +const char* script_op2name(int op) { #define RETURN_OP_NAME(type) case type: return #type - switch (op) { - RETURN_OP_NAME(C_NOP); - RETURN_OP_NAME(C_POS); - RETURN_OP_NAME(C_INT); - RETURN_OP_NAME(C_PARAM); - RETURN_OP_NAME(C_FUNC); - RETURN_OP_NAME(C_STR); - RETURN_OP_NAME(C_CONSTSTR); - RETURN_OP_NAME(C_ARG); - RETURN_OP_NAME(C_NAME); - RETURN_OP_NAME(C_EOL); - RETURN_OP_NAME(C_RETINFO); - RETURN_OP_NAME(C_USERFUNC); - RETURN_OP_NAME(C_USERFUNC_POS); - - // operators - RETURN_OP_NAME(C_OP3); - RETURN_OP_NAME(C_LOR); - RETURN_OP_NAME(C_LAND); - RETURN_OP_NAME(C_LE); - RETURN_OP_NAME(C_LT); - RETURN_OP_NAME(C_GE); - RETURN_OP_NAME(C_GT); - RETURN_OP_NAME(C_EQ); - RETURN_OP_NAME(C_NE); - RETURN_OP_NAME(C_XOR); - RETURN_OP_NAME(C_OR); - RETURN_OP_NAME(C_AND); - RETURN_OP_NAME(C_ADD); - RETURN_OP_NAME(C_SUB); - RETURN_OP_NAME(C_MUL); - RETURN_OP_NAME(C_DIV); - RETURN_OP_NAME(C_MOD); - RETURN_OP_NAME(C_NEG); - RETURN_OP_NAME(C_LNOT); - RETURN_OP_NAME(C_NOT); - RETURN_OP_NAME(C_R_SHIFT); - RETURN_OP_NAME(C_L_SHIFT); - - default: - ShowDebug("script_op2name: unexpected op=%d\n", op); - return "???"; - } + switch( op ) + { + RETURN_OP_NAME(C_NOP); + RETURN_OP_NAME(C_POS); + RETURN_OP_NAME(C_INT); + RETURN_OP_NAME(C_PARAM); + RETURN_OP_NAME(C_FUNC); + RETURN_OP_NAME(C_STR); + RETURN_OP_NAME(C_CONSTSTR); + RETURN_OP_NAME(C_ARG); + RETURN_OP_NAME(C_NAME); + RETURN_OP_NAME(C_EOL); + RETURN_OP_NAME(C_RETINFO); + RETURN_OP_NAME(C_USERFUNC); + RETURN_OP_NAME(C_USERFUNC_POS); + + // operators + RETURN_OP_NAME(C_OP3); + RETURN_OP_NAME(C_LOR); + RETURN_OP_NAME(C_LAND); + RETURN_OP_NAME(C_LE); + RETURN_OP_NAME(C_LT); + RETURN_OP_NAME(C_GE); + RETURN_OP_NAME(C_GT); + RETURN_OP_NAME(C_EQ); + RETURN_OP_NAME(C_NE); + RETURN_OP_NAME(C_XOR); + RETURN_OP_NAME(C_OR); + RETURN_OP_NAME(C_AND); + RETURN_OP_NAME(C_ADD); + RETURN_OP_NAME(C_SUB); + RETURN_OP_NAME(C_MUL); + RETURN_OP_NAME(C_DIV); + RETURN_OP_NAME(C_MOD); + RETURN_OP_NAME(C_NEG); + RETURN_OP_NAME(C_LNOT); + RETURN_OP_NAME(C_NOT); + RETURN_OP_NAME(C_R_SHIFT); + RETURN_OP_NAME(C_L_SHIFT); + + default: + ShowDebug("script_op2name: unexpected op=%d\n", op); + return "???"; + } #undef RETURN_OP_NAME } #ifdef DEBUG_DUMP_STACK -static void script_dump_stack(struct script_state *st) -{ - int i; - ShowMessage("\tstart = %d\n", st->start); - ShowMessage("\tend = %d\n", st->end); - ShowMessage("\tdefsp = %d\n", st->stack->defsp); - ShowMessage("\tsp = %d\n", st->stack->sp); - for (i = 0; i < st->stack->sp; ++i) { - struct script_data *data = &st->stack->stack_data[i]; - ShowMessage("\t[%d] %s", i, script_op2name(data->type)); - switch (data->type) { - case C_INT: - case C_POS: - ShowMessage(" %d\n", data->u.num); - break; - - case C_STR: - case C_CONSTSTR: - ShowMessage(" \"%s\"\n", data->u.str); - break; - - case C_NAME: - ShowMessage(" \"%s\" (id=%d ref=%p subtype=%s)\n", reference_getname(data), data->u.num, data->ref, script_op2name(str_data[data->u.num].type)); - break; - - case C_RETINFO: { - struct script_retinfo *ri = data->u.ri; - ShowMessage(" %p {var_function=%p, script=%p, pos=%d, nargs=%d, defsp=%d}\n", ri, ri->var_function, ri->script, ri->pos, ri->nargs, ri->defsp); - } - break; - default: - ShowMessage("\n"); - break; - } - } +static void script_dump_stack(struct script_state* st) +{ + int i; + ShowMessage("\tstart = %d\n", st->start); + ShowMessage("\tend = %d\n", st->end); + ShowMessage("\tdefsp = %d\n", st->stack->defsp); + ShowMessage("\tsp = %d\n", st->stack->sp); + for( i = 0; i < st->stack->sp; ++i ) + { + struct script_data* data = &st->stack->stack_data[i]; + ShowMessage("\t[%d] %s", i, script_op2name(data->type)); + switch( data->type ) + { + case C_INT: + case C_POS: + ShowMessage(" %d\n", data->u.num); + break; + + case C_STR: + case C_CONSTSTR: + ShowMessage(" \"%s\"\n", data->u.str); + break; + + case C_NAME: + ShowMessage(" \"%s\" (id=%d ref=%p subtype=%s)\n", reference_getname(data), data->u.num, data->ref, script_op2name(str_data[data->u.num].type)); + break; + + case C_RETINFO: + { + struct script_retinfo* ri = data->u.ri; + ShowMessage(" %p {var_function=%p, script=%p, pos=%d, nargs=%d, defsp=%d}\n", ri, ri->var_function, ri->script, ri->pos, ri->nargs, ri->defsp); + } + break; + default: + ShowMessage("\n"); + break; + } + } } #endif /// Reports on the console the src of a script error. static void script_reportsrc(struct script_state *st) { - struct block_list *bl; - - if (st->oid == 0) - return; //Can't report source. - - bl = map_id2bl(st->oid); - if (bl == NULL) - return; - - switch (bl->type) { - case BL_NPC: - if (bl->m >= 0) - ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, map[bl->m].name, bl->x, bl->y); - else - ShowDebug("Source (NPC): %s (invisible/not on a map)\n", ((struct npc_data *)bl)->name); - break; - default: - if (bl->m >= 0) - ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status_get_name(bl), map[bl->m].name, bl->x, bl->y); - else - ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status_get_name(bl)); - break; - } + struct block_list* bl; + + if( st->oid == 0 ) + return; //Can't report source. + + bl = map_id2bl(st->oid); + if( bl == NULL ) + return; + + switch( bl->type ) + { + case BL_NPC: + if( bl->m >= 0 ) + ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, map[bl->m].name, bl->x, bl->y); + else + ShowDebug("Source (NPC): %s (invisible/not on a map)\n", ((struct npc_data *)bl)->name); + break; + default: + if( bl->m >= 0 ) + ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status_get_name(bl), map[bl->m].name, bl->x, bl->y); + else + ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status_get_name(bl)); + break; + } } /// Reports on the console information about the script data. -static void script_reportdata(struct script_data *data) -{ - if (data == NULL) - return; - switch (data->type) { - case C_NOP:// no value - ShowDebug("Data: nothing (nil)\n"); - break; - case C_INT:// number - ShowDebug("Data: number value=%d\n", data->u.num); - break; - case C_STR: - case C_CONSTSTR:// string - if (data->u.str) { - ShowDebug("Data: string value=\"%s\"\n", data->u.str); - } else { - ShowDebug("Data: string value=NULL\n"); - } - break; - case C_NAME:// reference - if (reference_tovariable(data)) { - // variable - const char *name = reference_getname(data); - if (not_array_variable(*name)) - ShowDebug("Data: variable name='%s'\n", name); - else - ShowDebug("Data: variable name='%s' index=%d\n", name, reference_getindex(data)); - } else if (reference_toconstant(data)) { - // constant - ShowDebug("Data: constant name='%s' value=%d\n", reference_getname(data), reference_getconstant(data)); - } else if (reference_toparam(data)) { - // param - ShowDebug("Data: param name='%s' type=%d\n", reference_getname(data), reference_getparamtype(data)); - } else { - // ??? - ShowDebug("Data: reference name='%s' type=%s\n", reference_getname(data), script_op2name(data->type)); - ShowDebug("Please report this!!! - str_data.type=%s\n", script_op2name(str_data[reference_getid(data)].type)); - } - break; - case C_POS:// label - ShowDebug("Data: label pos=%d\n", data->u.num); - break; - default: - ShowDebug("Data: %s\n", script_op2name(data->type)); - break; - } +static void script_reportdata(struct script_data* data) +{ + if( data == NULL ) + return; + switch( data->type ) + { + case C_NOP:// no value + ShowDebug("Data: nothing (nil)\n"); + break; + case C_INT:// number + ShowDebug("Data: number value=%d\n", data->u.num); + break; + case C_STR: + case C_CONSTSTR:// string + if( data->u.str ) + { + ShowDebug("Data: string value=\"%s\"\n", data->u.str); + } + else + { + ShowDebug("Data: string value=NULL\n"); + } + break; + case C_NAME:// reference + if( reference_tovariable(data) ) + {// variable + const char* name = reference_getname(data); + if( not_array_variable(*name) ) + ShowDebug("Data: variable name='%s'\n", name); + else + ShowDebug("Data: variable name='%s' index=%d\n", name, reference_getindex(data)); + } + else if( reference_toconstant(data) ) + {// constant + ShowDebug("Data: constant name='%s' value=%d\n", reference_getname(data), reference_getconstant(data)); + } + else if( reference_toparam(data) ) + {// param + ShowDebug("Data: param name='%s' type=%d\n", reference_getname(data), reference_getparamtype(data)); + } + else + {// ??? + ShowDebug("Data: reference name='%s' type=%s\n", reference_getname(data), script_op2name(data->type)); + ShowDebug("Please report this!!! - str_data.type=%s\n", script_op2name(str_data[reference_getid(data)].type)); + } + break; + case C_POS:// label + ShowDebug("Data: label pos=%d\n", data->u.num); + break; + default: + ShowDebug("Data: %s\n", script_op2name(data->type)); + break; + } } /// Reports on the console information about the current built-in function. -static void script_reportfunc(struct script_state *st) +static void script_reportfunc(struct script_state* st) { - int i, params, id; - struct script_data *data; + int i, params, id; + struct script_data* data; - if (!script_hasdata(st,0)) { - // no stack - return; - } + if( !script_hasdata(st,0) ) + {// no stack + return; + } - data = script_getdata(st,0); + data = script_getdata(st,0); - if (!data_isreference(data) || str_data[reference_getid(data)].type != C_FUNC) { - // script currently not executing a built-in function or corrupt stack - return; - } + if( !data_isreference(data) || str_data[reference_getid(data)].type != C_FUNC ) + {// script currently not executing a built-in function or corrupt stack + return; + } - id = reference_getid(data); - params = script_lastdata(st)-1; + id = reference_getid(data); + params = script_lastdata(st)-1; - if (params > 0) { - ShowDebug("Function: %s (%d parameter%s):\n", get_str(id), params, (params == 1) ? "" : "s"); + if( params > 0 ) + { + ShowDebug("Function: %s (%d parameter%s):\n", get_str(id), params, ( params == 1 ) ? "" : "s"); - for (i = 2; i <= script_lastdata(st); i++) { - script_reportdata(script_getdata(st,i)); - } - } else { - ShowDebug("Function: %s (no parameters)\n", get_str(id)); - } + for( i = 2; i <= script_lastdata(st); i++ ) + { + script_reportdata(script_getdata(st,i)); + } + } + else + { + ShowDebug("Function: %s (no parameters)\n", get_str(id)); + } } @@ -611,55 +622,57 @@ static void script_reportfunc(struct script_state *st) *------------------------------------------*/ static void disp_error_message2(const char *mes,const char *pos,int report) { - error_msg = aStrdup(mes); - error_pos = pos; - error_report = report; - longjmp(error_jump, 1); + error_msg = aStrdup(mes); + error_pos = pos; + error_report = report; + longjmp( error_jump, 1 ); } #define disp_error_message(mes,pos) disp_error_message2(mes,pos,1) /// Checks event parameter validity static void check_event(struct script_state *st, const char *evt) { - if (evt && evt[0] && !stristr(evt, "::On")) { - ShowWarning("NPC event parameter deprecated! Please use 'NPCNAME::OnEVENT' instead of '%s'.\n", evt); - script_reportsrc(st); - } + if( evt && evt[0] && !stristr(evt, "::On") ) + { + ShowWarning("NPC event parameter deprecated! Please use 'NPCNAME::OnEVENT' instead of '%s'.\n", evt); + script_reportsrc(st); + } } /*========================================== * Hashes the input string *------------------------------------------*/ -static unsigned int calc_hash(const char *p) +static unsigned int calc_hash(const char* p) { - unsigned int h; + unsigned int h; #if defined(SCRIPT_HASH_DJB2) - h = 5381; - while (*p) // hash*33 + c - h = (h << 5) + h + ((unsigned char)TOLOWER(*p++)); + h = 5381; + while( *p ) // hash*33 + c + h = ( h << 5 ) + h + ((unsigned char)TOLOWER(*p++)); #elif defined(SCRIPT_HASH_SDBM) - h = 0; - while (*p) // hash*65599 + c - h = (h << 6) + (h << 16) - h + ((unsigned char)TOLOWER(*p++)); + h = 0; + while( *p ) // hash*65599 + c + h = ( h << 6 ) + ( h << 16 ) - h + ((unsigned char)TOLOWER(*p++)); #elif defined(SCRIPT_HASH_ELF) // UNIX ELF hash - h = 0; - while (*p) { - unsigned int g; - h = (h << 4) + ((unsigned char)TOLOWER(*p++)); - g = h & 0xF0000000; - if (g) { - h ^= g >> 24; - h &= ~g; - } - } + h = 0; + while( *p ){ + unsigned int g; + h = ( h << 4 ) + ((unsigned char)TOLOWER(*p++)); + g = h & 0xF0000000; + if( g ) + { + h ^= g >> 24; + h &= ~g; + } + } #else // athena hash - h = 0; - while (*p) - h = (h << 1) + (h >> 3) + (h >> 5) + (h >> 8) + (unsigned char)TOLOWER(*p++); + h = 0; + while( *p ) + h = ( h << 1 ) + ( h >> 3 ) + ( h >> 5 ) + ( h >> 8 ) + (unsigned char)TOLOWER(*p++); #endif - return h % SCRIPT_HASH_SIZE; + return h % SCRIPT_HASH_SIZE; } @@ -668,86 +681,91 @@ static unsigned int calc_hash(const char *p) *------------------------------------------*/ /// Looks up string using the provided id. -const char *get_str(int id) +const char* get_str(int id) { - Assert(id >= LABEL_START && id < str_size); - return str_buf+str_data[id].str; + Assert( id >= LABEL_START && id < str_size ); + return str_buf+str_data[id].str; } /// Returns the uid of the string, or -1. -static int search_str(const char *p) +static int search_str(const char* p) { - int i; + int i; - for (i = str_hash[calc_hash(p)]; i != 0; i = str_data[i].next) - if (strcasecmp(get_str(i),p) == 0) - return i; + for( i = str_hash[calc_hash(p)]; i != 0; i = str_data[i].next ) + if( strcasecmp(get_str(i),p) == 0 ) + return i; - return -1; + return -1; } /// Stores a copy of the string and returns its id. /// If an identical string is already present, returns its id instead. -int add_str(const char *p) -{ - int i, h; - int len; - - h = calc_hash(p); - - if (str_hash[h] == 0) { - // empty bucket, add new node here - str_hash[h] = str_num; - } else { - // scan for end of list, or occurence of identical string - for (i = str_hash[h]; ; i = str_data[i].next) { - if (strcasecmp(get_str(i),p) == 0) - return i; // string already in list - if (str_data[i].next == 0) - break; // reached the end - } - - // append node to end of list - str_data[i].next = str_num; - } - - // grow list if neccessary - if (str_num >= str_data_size) { - str_data_size += 128; - RECREATE(str_data,struct str_data_struct,str_data_size); - memset(str_data + (str_data_size - 128), '\0', 128); - } - - len=(int)strlen(p); - - // grow string buffer if neccessary - while (str_pos+len+1 >= str_size) { - str_size += 256; - RECREATE(str_buf,char,str_size); - memset(str_buf + (str_size - 256), '\0', 256); - } - - safestrncpy(str_buf+str_pos, p, len+1); - 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 += len+1; - - return str_num++; +int add_str(const char* p) +{ + int i, h; + int len; + + h = calc_hash(p); + + if( str_hash[h] == 0 ) + {// empty bucket, add new node here + str_hash[h] = str_num; + } + else + {// scan for end of list, or occurence of identical string + for( i = str_hash[h]; ; i = str_data[i].next ) + { + if( strcasecmp(get_str(i),p) == 0 ) + return i; // string already in list + if( str_data[i].next == 0 ) + break; // reached the end + } + + // append node to end of list + str_data[i].next = str_num; + } + + // grow list if neccessary + if( str_num >= str_data_size ) + { + str_data_size += 128; + RECREATE(str_data,struct str_data_struct,str_data_size); + memset(str_data + (str_data_size - 128), '\0', 128); + } + + len=(int)strlen(p); + + // grow string buffer if neccessary + while( str_pos+len+1 >= str_size ) + { + str_size += 256; + RECREATE(str_buf,char,str_size); + memset(str_buf + (str_size - 256), '\0', 256); + } + + safestrncpy(str_buf+str_pos, p, len+1); + 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 += len+1; + + return str_num++; } /// Appends 1 byte to the script buffer. static void add_scriptb(int a) { - if (script_pos+1 >= script_size) { - script_size += SCRIPT_BLOCK_SIZE; - RECREATE(script_buf,unsigned char,script_size); - } - script_buf[script_pos++] = (uint8)(a); + if( script_pos+1 >= script_size ) + { + script_size += SCRIPT_BLOCK_SIZE; + RECREATE(script_buf,unsigned char,script_size); + } + script_buf[script_pos++] = (uint8)(a); } /// Appends a c_op value to the script buffer. @@ -756,12 +774,13 @@ static void add_scriptb(int a) /// All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries). static void add_scriptc(int a) { - while (a >= 0x40) { - add_scriptb((a&0x3f)|0x40); - a = (a - 0x40) >> 6; - } + while( a >= 0x40 ) + { + add_scriptb((a&0x3f)|0x40); + a = (a - 0x40) >> 6; + } - add_scriptb(a); + add_scriptb(a); } /// Appends an integer value to the script buffer. @@ -770,11 +789,12 @@ static void add_scriptc(int a) /// All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries). static void add_scripti(int a) { - while (a >= 0x40) { - add_scriptb((a&0x3f)|0xc0); - a = (a - 0x40) >> 6; - } - add_scriptb(a|0x80); + while( a >= 0x40 ) + { + add_scriptb((a&0x3f)|0xc0); + a = (a - 0x40) >> 6; + } + add_scriptb(a|0x80); } /// Appends a str_data object (label/function/variable/integer) to the script buffer. @@ -784,1319 +804,1321 @@ static void add_scripti(int a) // Maximum up to 16M static void add_scriptl(int l) { - int backpatch = str_data[l].backpatch; - - switch (str_data[l].type) { - case C_POS: - case C_USERFUNC_POS: - add_scriptc(C_POS); - add_scriptb(str_data[l].label); - add_scriptb(str_data[l].label>>8); - add_scriptb(str_data[l].label>>16); - break; - case C_NOP: - case C_USERFUNC: - // Embedded data backpatch there is a possibility of label - add_scriptc(C_NAME); - str_data[l].backpatch = script_pos; - add_scriptb(backpatch); - add_scriptb(backpatch>>8); - add_scriptb(backpatch>>16); - break; - case C_INT: - add_scripti(abs(str_data[l].val)); - if (str_data[l].val < 0) //Notice that this is negative, from jA (Rayce) - add_scriptc(C_NEG); - break; - default: // assume C_NAME - add_scriptc(C_NAME); - add_scriptb(l); - add_scriptb(l>>8); - add_scriptb(l>>16); - break; - } + int backpatch = str_data[l].backpatch; + + switch(str_data[l].type){ + case C_POS: + case C_USERFUNC_POS: + add_scriptc(C_POS); + add_scriptb(str_data[l].label); + add_scriptb(str_data[l].label>>8); + add_scriptb(str_data[l].label>>16); + break; + case C_NOP: + case C_USERFUNC: + // Embedded data backpatch there is a possibility of label + add_scriptc(C_NAME); + str_data[l].backpatch = script_pos; + add_scriptb(backpatch); + add_scriptb(backpatch>>8); + add_scriptb(backpatch>>16); + break; + case C_INT: + add_scripti(abs(str_data[l].val)); + if( str_data[l].val < 0 ) //Notice that this is negative, from jA (Rayce) + add_scriptc(C_NEG); + break; + default: // assume C_NAME + add_scriptc(C_NAME); + add_scriptb(l); + add_scriptb(l>>8); + add_scriptb(l>>16); + break; + } } /*========================================== * Resolve the label *------------------------------------------*/ -void set_label(int l,int pos, const char *script_pos) -{ - int i,next; - - if (str_data[l].type==C_INT || str_data[l].type==C_PARAM || str_data[l].type==C_FUNC) { - //Prevent overwriting constants values, parameters and built-in functions [Skotlex] - disp_error_message("set_label: invalid label name",script_pos); - return; - } - if (str_data[l].label!=-1) { - disp_error_message("set_label: dup label ",script_pos); - return; - } - str_data[l].type=(str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS); - str_data[l].label=pos; - for (i=str_data[l].backpatch; i>=0 && i!=0x00ffffff;) { - next=GETVALUE(script_buf,i); - script_buf[i-1]=(str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS); - SETVALUE(script_buf,i,pos); - i=next; - } +void set_label(int l,int pos, const char* script_pos) +{ + int i,next; + + if(str_data[l].type==C_INT || str_data[l].type==C_PARAM || str_data[l].type==C_FUNC) + { //Prevent overwriting constants values, parameters and built-in functions [Skotlex] + disp_error_message("set_label: invalid label name",script_pos); + return; + } + if(str_data[l].label!=-1){ + disp_error_message("set_label: dup label ",script_pos); + return; + } + str_data[l].type=(str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS); + str_data[l].label=pos; + for(i=str_data[l].backpatch;i>=0 && i!=0x00ffffff;){ + next=GETVALUE(script_buf,i); + script_buf[i-1]=(str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS); + SETVALUE(script_buf,i,pos); + i=next; + } } /// Skips spaces and/or comments. -const char *skip_space(const char *p) -{ - if (p == NULL) - return NULL; - for (;;) { - while (ISSPACE(*p)) - ++p; - if (*p == '/' && p[1] == '/') { - // line comment - while (*p && *p!='\n') - ++p; - } else if (*p == '/' && p[1] == '*') { - // block comment - p += 2; - for (;;) { - if (*p == '\0') - return p;//disp_error_message("script:skip_space: end of file while parsing block comment. expected "CL_BOLD"*/"CL_NORM, p); - if (*p == '*' && p[1] == '/') { - // end of block comment - p += 2; - break; - } - ++p; - } - } else - break; - } - return p; +const char* skip_space(const char* p) +{ + if( p == NULL ) + return NULL; + for(;;) + { + while( ISSPACE(*p) ) + ++p; + if( *p == '/' && p[1] == '/' ) + {// line comment + while(*p && *p!='\n') + ++p; + } + else if( *p == '/' && p[1] == '*' ) + {// block comment + p += 2; + for(;;) + { + if( *p == '\0' ) + return p;//disp_error_message("script:skip_space: end of file while parsing block comment. expected "CL_BOLD"*/"CL_NORM, p); + if( *p == '*' && p[1] == '/' ) + {// end of block comment + p += 2; + break; + } + ++p; + } + } + else + break; + } + return p; } /// Skips a word. /// A word consists of undercores and/or alfanumeric characters, /// and valid variable prefixes/postfixes. static -const char *skip_word(const char *p) -{ - // prefix - switch (*p) { - case '@':// temporary char variable - ++p; - break; - case '#':// account variable - p += (p[1] == '#' ? 2 : 1); - break; - case '\'':// instance variable - ++p; - break; - case '.':// npc variable - p += (p[1] == '@' ? 2 : 1); - break; - case '$':// global variable - p += (p[1] == '@' ? 2 : 1); - break; - } +const char* skip_word(const char* p) +{ + // prefix + switch( *p ) + { + case '@':// temporary char variable + ++p; break; + case '#':// account variable + p += ( p[1] == '#' ? 2 : 1 ); break; + case '\'':// instance variable + ++p; break; + case '.':// npc variable + p += ( p[1] == '@' ? 2 : 1 ); break; + case '$':// global variable + p += ( p[1] == '@' ? 2 : 1 ); break; + } - while (ISALNUM(*p) || *p == '_') - ++p; + while( ISALNUM(*p) || *p == '_' ) + ++p; - // postfix - if (*p == '$') // string - p++; + // postfix + if( *p == '$' )// string + p++; - return p; + return p; } /// Adds a word to str_data. /// @see skip_word /// @see add_str static -int add_word(const char *p) +int add_word(const char* p) { - char *word; - int len; - int i; + char* word; + int len; + int i; - // Check for a word - len = skip_word(p) - p; - if (len == 0) - disp_error_message("script:add_word: invalid word. A word consists of undercores and/or alfanumeric characters, and valid variable prefixes/postfixes.", p); + // Check for a word + len = skip_word(p) - p; + if( len == 0 ) + disp_error_message("script:add_word: invalid word. A word consists of undercores and/or alfanumeric characters, and valid variable prefixes/postfixes.", p); - // Duplicate the word - word = (char *)aMalloc(len+1); - memcpy(word, p, len); - word[len] = 0; + // Duplicate the word + word = (char*)aMalloc(len+1); + memcpy(word, p, len); + word[len] = 0; - // add the word - i = add_str(word); - aFree(word); - return i; + // add the word + i = add_str(word); + aFree(word); + return i; } /// Parses a function call. /// The argument list can have parenthesis or not. /// The number of arguments is checked. static -const char *parse_callfunc(const char *p, int require_paren, int is_custom) -{ - const char *p2; - const char *arg=NULL; - int func; - - func = add_word(p); - if (str_data[func].type == C_FUNC) { - // buildin function - add_scriptl(func); - add_scriptc(C_ARG); - arg = buildin_func[str_data[func].val].arg; - } else if (str_data[func].type == C_USERFUNC || str_data[func].type == C_USERFUNC_POS) { - // script defined function - add_scriptl(buildin_callsub_ref); - add_scriptc(C_ARG); - add_scriptl(func); - arg = buildin_func[str_data[buildin_callsub_ref].val].arg; - if (*arg == 0) - disp_error_message("parse_callfunc: callsub has no arguments, please review it's definition",p); - if (*arg != '*') - ++arg; // count func as argument - } else { +const char* parse_callfunc(const char* p, int require_paren, int is_custom) +{ + const char* p2; + const char* arg=NULL; + int func; + + func = add_word(p); + if( str_data[func].type == C_FUNC ){ + // buildin function + add_scriptl(func); + add_scriptc(C_ARG); + arg = buildin_func[str_data[func].val].arg; + } else if( str_data[func].type == C_USERFUNC || str_data[func].type == C_USERFUNC_POS ){ + // script defined function + add_scriptl(buildin_callsub_ref); + add_scriptc(C_ARG); + add_scriptl(func); + arg = buildin_func[str_data[buildin_callsub_ref].val].arg; + if( *arg == 0 ) + disp_error_message("parse_callfunc: callsub has no arguments, please review it's definition",p); + if( *arg != '*' ) + ++arg; // count func as argument + } else { #ifdef SCRIPT_CALLFUNC_CHECK - const char *name = get_str(func); - if (!is_custom && strdb_get(userfunc_db, name) == NULL) { + const char* name = get_str(func); + if( !is_custom && strdb_get(userfunc_db, name) == NULL ) { #endif - disp_error_message("parse_line: expect command, missing function name or calling undeclared function",p); + disp_error_message("parse_line: expect command, missing function name or calling undeclared function",p); #ifdef SCRIPT_CALLFUNC_CHECK - } else { - ; - add_scriptl(buildin_callfunc_ref); - add_scriptc(C_ARG); - add_scriptc(C_STR); - while (*name) add_scriptb(*name ++); - add_scriptb(0); - arg = buildin_func[str_data[buildin_callfunc_ref].val].arg; - if (*arg != '*') ++ arg; - } + } else {; + add_scriptl(buildin_callfunc_ref); + add_scriptc(C_ARG); + add_scriptc(C_STR); + while( *name ) add_scriptb(*name ++); + add_scriptb(0); + arg = buildin_func[str_data[buildin_callfunc_ref].val].arg; + if( *arg != '*' ) ++ arg; + } #endif - } - - p = skip_word(p); - p = skip_space(p); - syntax.curly[syntax.curly_count].type = TYPE_ARGLIST; - syntax.curly[syntax.curly_count].count = 0; - if (*p == ';') { - // <func name> ';' - syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN; - } else if (*p == '(' && *(p2=skip_space(p+1)) == ')') { - // <func name> '(' ')' - syntax.curly[syntax.curly_count].flag = ARGLIST_PAREN; - p = p2; - /* - } else if( 0 && require_paren && *p != '(' ) - {// <func name> - syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN; - */ - } else { - // <func name> <arg list> - if (require_paren) { - if (*p != '(') - disp_error_message("need '('",p); - ++p; // skip '(' - syntax.curly[syntax.curly_count].flag = ARGLIST_PAREN; - } else if (*p == '(') { - syntax.curly[syntax.curly_count].flag = ARGLIST_UNDEFINED; - } else { - syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN; - } - ++syntax.curly_count; - while (*arg) { - p2=parse_subexpr(p,-1); - if (p == p2) - break; // not an argument - if (*arg != '*') - ++arg; // next argument - - p=skip_space(p2); - if (*arg == 0 || *p != ',') - break; // no more arguments - ++p; // skip comma - } - --syntax.curly_count; - } - if (*arg && *arg != '?' && *arg != '*') - disp_error_message2("parse_callfunc: not enough arguments, expected ','", p, script_config.warn_func_mismatch_paramnum); - if (syntax.curly[syntax.curly_count].type != TYPE_ARGLIST) - disp_error_message("parse_callfunc: DEBUG last curly is not an argument list",p); - if (syntax.curly[syntax.curly_count].flag == ARGLIST_PAREN) { - if (*p != ')') - disp_error_message("parse_callfunc: expected ')' to close argument list",p); - ++p; - } - add_scriptc(C_FUNC); - return p; + } + + p = skip_word(p); + p = skip_space(p); + syntax.curly[syntax.curly_count].type = TYPE_ARGLIST; + syntax.curly[syntax.curly_count].count = 0; + if( *p == ';' ) + {// <func name> ';' + syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN; + } else if( *p == '(' && *(p2=skip_space(p+1)) == ')' ) + {// <func name> '(' ')' + syntax.curly[syntax.curly_count].flag = ARGLIST_PAREN; + p = p2; + /* + } else if( 0 && require_paren && *p != '(' ) + {// <func name> + syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN; + */ + } else + {// <func name> <arg list> + if( require_paren ){ + if( *p != '(' ) + disp_error_message("need '('",p); + ++p; // skip '(' + syntax.curly[syntax.curly_count].flag = ARGLIST_PAREN; + } else if( *p == '(' ){ + syntax.curly[syntax.curly_count].flag = ARGLIST_UNDEFINED; + } else { + syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN; + } + ++syntax.curly_count; + while( *arg ) { + p2=parse_subexpr(p,-1); + if( p == p2 ) + break; // not an argument + if( *arg != '*' ) + ++arg; // next argument + + p=skip_space(p2); + if( *arg == 0 || *p != ',' ) + break; // no more arguments + ++p; // skip comma + } + --syntax.curly_count; + } + if( *arg && *arg != '?' && *arg != '*' ) + disp_error_message2("parse_callfunc: not enough arguments, expected ','", p, script_config.warn_func_mismatch_paramnum); + if( syntax.curly[syntax.curly_count].type != TYPE_ARGLIST ) + disp_error_message("parse_callfunc: DEBUG last curly is not an argument list",p); + if( syntax.curly[syntax.curly_count].flag == ARGLIST_PAREN ){ + if( *p != ')' ) + disp_error_message("parse_callfunc: expected ')' to close argument list",p); + ++p; + } + add_scriptc(C_FUNC); + return p; } /// Processes end of logical script line. /// @param first When true, only fix up scheduling data is initialized /// @param p Script position for error reporting in set_label -static void parse_nextline(bool first, const char *p) +static void parse_nextline(bool first, const char* p) { - if (!first) { - add_scriptc(C_EOL); // mark end of line for stack cleanup - set_label(LABEL_NEXTLINE, script_pos, p); // fix up '-' labels - } + if( !first ) + { + add_scriptc(C_EOL); // mark end of line for stack cleanup + set_label(LABEL_NEXTLINE, script_pos, p); // fix up '-' labels + } - // initialize data for new '-' label fix up scheduling - str_data[LABEL_NEXTLINE].type = C_NOP; - str_data[LABEL_NEXTLINE].backpatch = -1; - str_data[LABEL_NEXTLINE].label = -1; + // initialize data for new '-' label fix up scheduling + str_data[LABEL_NEXTLINE].type = C_NOP; + str_data[LABEL_NEXTLINE].backpatch = -1; + str_data[LABEL_NEXTLINE].label = -1; } /// Parse a variable assignment using the direct equals operator /// @param p script position where the function should run from /// @return NULL if not a variable assignment, the new position otherwise -const char *parse_variable(const char *p) -{ - int i, j, word; - c_op type = C_NOP; - const char *p2 = NULL; - const char *var = p; - - // skip the variable where applicable - p = skip_word(p); - p = skip_space(p); - - if (p == NULL) { // end of the line or invalid buffer - return NULL; - } - - if (*p == '[') { // array variable so process the array as appropriate - for (p2 = p, i = 0, j = 1; p; ++ i) { - if (*p ++ == ']' && --(j) == 0) break; - if (*p == '[') ++ j; - } - - if (!(p = skip_space(p))) { // end of line or invalid characters remaining - disp_error_message("Missing right expression or closing bracket for variable.", p); - } - } - - if (type == C_NOP && - !((p[0] == '=' && p[1] != '=' && (type = C_EQ)) // = - || (p[0] == '+' && p[1] == '=' && (type = C_ADD)) // += - || (p[0] == '-' && p[1] == '=' && (type = C_SUB)) // -= - || (p[0] == '^' && p[1] == '=' && (type = C_XOR)) // ^= - || (p[0] == '|' && p[1] == '=' && (type = C_OR)) // |= - || (p[0] == '&' && p[1] == '=' && (type = C_AND)) // &= - || (p[0] == '*' && p[1] == '=' && (type = C_MUL)) // *= - || (p[0] == '/' && p[1] == '=' && (type = C_DIV)) // /= - || (p[0] == '%' && p[1] == '=' && (type = C_MOD)) // %= - || (p[0] == '~' && p[1] == '=' && (type = C_NOT)) // ~= - || (p[0] == '+' && p[1] == '+' && (type = C_ADD_PP)) // ++ - || (p[0] == '-' && p[1] == '-' && (type = C_SUB_PP)) // -- - || (p[0] == '<' && p[1] == '<' && p[2] == '=' && (type = C_L_SHIFT)) // <<= - || (p[0] == '>' && p[1] == '>' && p[2] == '=' && (type = C_R_SHIFT)) // >>= - )) { - // failed to find a matching operator combination so invalid - return NULL; - } - - switch (type) { - case C_EQ: {// incremental modifier - p = skip_space(&p[1]); - } - break; - - case C_L_SHIFT: - case C_R_SHIFT: {// left or right shift modifier - p = skip_space(&p[3]); - } - break; - - default: {// normal incremental command - p = skip_space(&p[2]); - } - } - - if (p == NULL) { // end of line or invalid buffer - return NULL; - } - - // push the set function onto the stack - add_scriptl(buildin_set_ref); - add_scriptc(C_ARG); - - // always append parenthesis to avoid errors - syntax.curly[syntax.curly_count].type = TYPE_ARGLIST; - syntax.curly[syntax.curly_count].count = 0; - syntax.curly[syntax.curly_count].flag = ARGLIST_PAREN; - - // increment the total curly count for the position in the script - ++ syntax.curly_count; - - // parse the variable currently being modified - word = add_word(var); - - if (str_data[word].type == C_FUNC || str_data[word].type == C_USERFUNC || str_data[word].type == C_USERFUNC_POS) { - // cannot assign a variable which exists as a function or label - disp_error_message("Cannot modify a variable which has the same name as a function or label.", p); - } - - if (p2) { // process the variable index - const char *p3 = NULL; - - // push the getelementofarray method into the stack - add_scriptl(buildin_getelementofarray_ref); - add_scriptc(C_ARG); - add_scriptl(word); - - // process the sub-expression for this assignment - p3 = parse_subexpr(p2 + 1, 1); - p3 = skip_space(p3); - - if (*p3 != ']') { // closing parenthesis is required for this script - disp_error_message("Missing closing ']' parenthesis for the variable assignment.", p3); - } - - // push the closing function stack operator onto the stack - add_scriptc(C_FUNC); - p3 ++; - } else {// simply push the variable or value onto the stack - add_scriptl(word); - } - - if (type != C_EQ) - add_scriptc(C_REF); - - if (type == C_ADD_PP || type == C_SUB_PP) { // incremental operator for the method - add_scripti(1); - add_scriptc(type == C_ADD_PP ? C_ADD : C_SUB); - } else {// process the value as an expression - p = parse_subexpr(p, -1); - - if (type != C_EQ) { - // push the type of modifier onto the stack - add_scriptc(type); - } - } - - // decrement the curly count for the position within the script - -- syntax.curly_count; - - // close the script by appending the function operator - add_scriptc(C_FUNC); - - // push the buffer from the method - return p; +const char* parse_variable(const char* p) { + int i, j, word; + c_op type = C_NOP; + const char *p2 = NULL; + const char *var = p; + + // skip the variable where applicable + p = skip_word(p); + p = skip_space(p); + + if( p == NULL ) {// end of the line or invalid buffer + return NULL; + } + + if( *p == '[' ) {// array variable so process the array as appropriate + for( p2 = p, i = 0, j = 1; p; ++ i ) { + if( *p ++ == ']' && --(j) == 0 ) break; + if( *p == '[' ) ++ j; + } + + if( !(p = skip_space(p)) ) {// end of line or invalid characters remaining + disp_error_message("Missing right expression or closing bracket for variable.", p); + } + } + + if( type == C_NOP && + !( ( p[0] == '=' && p[1] != '=' && (type = C_EQ) ) // = + || ( p[0] == '+' && p[1] == '=' && (type = C_ADD) ) // += + || ( p[0] == '-' && p[1] == '=' && (type = C_SUB) ) // -= + || ( p[0] == '^' && p[1] == '=' && (type = C_XOR) ) // ^= + || ( p[0] == '|' && p[1] == '=' && (type = C_OR ) ) // |= + || ( p[0] == '&' && p[1] == '=' && (type = C_AND) ) // &= + || ( p[0] == '*' && p[1] == '=' && (type = C_MUL) ) // *= + || ( p[0] == '/' && p[1] == '=' && (type = C_DIV) ) // /= + || ( p[0] == '%' && p[1] == '=' && (type = C_MOD) ) // %= + || ( p[0] == '~' && p[1] == '=' && (type = C_NOT) ) // ~= + || ( p[0] == '+' && p[1] == '+' && (type = C_ADD_PP) ) // ++ + || ( p[0] == '-' && p[1] == '-' && (type = C_SUB_PP) ) // -- + || ( p[0] == '<' && p[1] == '<' && p[2] == '=' && (type = C_L_SHIFT) ) // <<= + || ( p[0] == '>' && p[1] == '>' && p[2] == '=' && (type = C_R_SHIFT) ) // >>= + ) ) + {// failed to find a matching operator combination so invalid + return NULL; + } + + switch( type ) { + case C_EQ: {// incremental modifier + p = skip_space( &p[1] ); + } + break; + + case C_L_SHIFT: + case C_R_SHIFT: {// left or right shift modifier + p = skip_space( &p[3] ); + } + break; + + default: {// normal incremental command + p = skip_space( &p[2] ); + } + } + + if( p == NULL ) {// end of line or invalid buffer + return NULL; + } + + // push the set function onto the stack + add_scriptl(buildin_set_ref); + add_scriptc(C_ARG); + + // always append parenthesis to avoid errors + syntax.curly[syntax.curly_count].type = TYPE_ARGLIST; + syntax.curly[syntax.curly_count].count = 0; + syntax.curly[syntax.curly_count].flag = ARGLIST_PAREN; + + // increment the total curly count for the position in the script + ++ syntax.curly_count; + + // parse the variable currently being modified + word = add_word(var); + + if( str_data[word].type == C_FUNC || str_data[word].type == C_USERFUNC || str_data[word].type == C_USERFUNC_POS ) + {// cannot assign a variable which exists as a function or label + disp_error_message("Cannot modify a variable which has the same name as a function or label.", p); + } + + if( p2 ) {// process the variable index + const char* p3 = NULL; + + // push the getelementofarray method into the stack + add_scriptl(buildin_getelementofarray_ref); + add_scriptc(C_ARG); + add_scriptl(word); + + // process the sub-expression for this assignment + p3 = parse_subexpr(p2 + 1, 1); + p3 = skip_space(p3); + + if( *p3 != ']' ) {// closing parenthesis is required for this script + disp_error_message("Missing closing ']' parenthesis for the variable assignment.", p3); + } + + // push the closing function stack operator onto the stack + add_scriptc(C_FUNC); + p3 ++; + } else {// simply push the variable or value onto the stack + add_scriptl(word); + } + + if( type != C_EQ ) + add_scriptc(C_REF); + + if( type == C_ADD_PP || type == C_SUB_PP ) {// incremental operator for the method + add_scripti(1); + add_scriptc(type == C_ADD_PP ? C_ADD : C_SUB); + } else {// process the value as an expression + p = parse_subexpr(p, -1); + + if( type != C_EQ ) + {// push the type of modifier onto the stack + add_scriptc(type); + } + } + + // decrement the curly count for the position within the script + -- syntax.curly_count; + + // close the script by appending the function operator + add_scriptc(C_FUNC); + + // push the buffer from the method + return p; } /*========================================== * Analysis section *------------------------------------------*/ -const char *parse_simpleexpr(const char *p) -{ - int i; - p=skip_space(p); - - if (*p==';' || *p==',') - disp_error_message("parse_simpleexpr: unexpected expr end",p); - if (*p=='(') { - if ((i=syntax.curly_count-1) >= 0 && syntax.curly[i].type == TYPE_ARGLIST) - ++syntax.curly[i].count; - p=parse_subexpr(p+1,-1); - p=skip_space(p); - if ((i=syntax.curly_count-1) >= 0 && syntax.curly[i].type == TYPE_ARGLIST && - syntax.curly[i].flag == ARGLIST_UNDEFINED && --syntax.curly[i].count == 0 - ) { - if (*p == ',') { - syntax.curly[i].flag = ARGLIST_PAREN; - return p; - } else - syntax.curly[i].flag = ARGLIST_NO_PAREN; - } - if (*p != ')') - disp_error_message("parse_simpleexpr: unmatch ')'",p); - ++p; - } else if (ISDIGIT(*p) || ((*p=='-' || *p=='+') && ISDIGIT(p[1]))) { - char *np; - while (*p == '0' && ISDIGIT(p[1])) p++; - i=strtoul(p,&np,0); - add_scripti(i); - p=np; - } else if (*p=='"') { - add_scriptc(C_STR); - p++; - while (*p && *p != '"') { - if ((unsigned char)p[-1] <= 0x7e && *p == '\\') { - char buf[8]; - size_t len = skip_escaped_c(p) - p; - size_t n = sv_unescape_c(buf, p, len); - if (n != 1) - ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf); - p += len; - add_scriptb(*buf); - continue; - } else if (*p == '\n') - disp_error_message("parse_simpleexpr: unexpected newline @ string",p); - add_scriptb(*p++); - } - if (!*p) - disp_error_message("parse_simpleexpr: unexpected eof @ string",p); - add_scriptb(0); - p++; //'"' - } else { - int l; - const char *pv; - - // label , register , function etc - if (skip_word(p)==p) - disp_error_message("parse_simpleexpr: unexpected character",p); - - l=add_word(p); - if (str_data[l].type == C_FUNC || str_data[l].type == C_USERFUNC || str_data[l].type == C_USERFUNC_POS) - return parse_callfunc(p,1,0); +const char* parse_simpleexpr(const char *p) +{ + int i; + p=skip_space(p); + + if(*p==';' || *p==',') + disp_error_message("parse_simpleexpr: unexpected expr end",p); + if(*p=='('){ + if( (i=syntax.curly_count-1) >= 0 && syntax.curly[i].type == TYPE_ARGLIST ) + ++syntax.curly[i].count; + p=parse_subexpr(p+1,-1); + p=skip_space(p); + if( (i=syntax.curly_count-1) >= 0 && syntax.curly[i].type == TYPE_ARGLIST && + syntax.curly[i].flag == ARGLIST_UNDEFINED && --syntax.curly[i].count == 0 + ){ + if( *p == ',' ){ + syntax.curly[i].flag = ARGLIST_PAREN; + return p; + } else + syntax.curly[i].flag = ARGLIST_NO_PAREN; + } + if( *p != ')' ) + disp_error_message("parse_simpleexpr: unmatch ')'",p); + ++p; + } else if(ISDIGIT(*p) || ((*p=='-' || *p=='+') && ISDIGIT(p[1]))){ + char *np; + while(*p == '0' && ISDIGIT(p[1])) p++; + i=strtoul(p,&np,0); + add_scripti(i); + p=np; + } else if(*p=='"'){ + add_scriptc(C_STR); + p++; + while( *p && *p != '"' ){ + if( (unsigned char)p[-1] <= 0x7e && *p == '\\' ) + { + char buf[8]; + size_t len = skip_escaped_c(p) - p; + size_t n = sv_unescape_c(buf, p, len); + if( n != 1 ) + ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf); + p += len; + add_scriptb(*buf); + continue; + } + else if( *p == '\n' ) + disp_error_message("parse_simpleexpr: unexpected newline @ string",p); + add_scriptb(*p++); + } + if(!*p) + disp_error_message("parse_simpleexpr: unexpected eof @ string",p); + add_scriptb(0); + p++; //'"' + } else { + int l; + const char* pv; + + // label , register , function etc + if(skip_word(p)==p) + disp_error_message("parse_simpleexpr: unexpected character",p); + + l=add_word(p); + if( str_data[l].type == C_FUNC || str_data[l].type == C_USERFUNC || str_data[l].type == C_USERFUNC_POS) + return parse_callfunc(p,1,0); #ifdef SCRIPT_CALLFUNC_CHECK - else { - const char *name = get_str(l); - if (strdb_get(userfunc_db,name) != NULL) { - return parse_callfunc(p,1,1); - } - } + else { + const char* name = get_str(l); + if( strdb_get(userfunc_db,name) != NULL ) { + return parse_callfunc(p,1,1); + } + } #endif - if ((pv = parse_variable(p))) { - // successfully processed a variable assignment - return pv; - } + if( (pv = parse_variable(p)) ) + {// successfully processed a variable assignment + return pv; + } - p=skip_word(p); - if (*p == '[') { - // array(name[i] => getelementofarray(name,i) ) - add_scriptl(buildin_getelementofarray_ref); - add_scriptc(C_ARG); - add_scriptl(l); - - p=parse_subexpr(p+1,-1); - p=skip_space(p); - if (*p != ']') - disp_error_message("parse_simpleexpr: unmatch ']'",p); - ++p; - add_scriptc(C_FUNC); - } else - add_scriptl(l); + p=skip_word(p); + if( *p == '[' ){ + // array(name[i] => getelementofarray(name,i) ) + add_scriptl(buildin_getelementofarray_ref); + add_scriptc(C_ARG); + add_scriptl(l); - } + p=parse_subexpr(p+1,-1); + p=skip_space(p); + if( *p != ']' ) + disp_error_message("parse_simpleexpr: unmatch ']'",p); + ++p; + add_scriptc(C_FUNC); + }else + add_scriptl(l); - return p; + } + + return p; } /*========================================== * Analysis of the expression *------------------------------------------*/ -const char *parse_subexpr(const char *p,int limit) -{ - int op,opl,len; - const char *tmpp; - - p=skip_space(p); - - if (*p == '-') { - tmpp = skip_space(p+1); - if (*tmpp == ';' || *tmpp == ',') { - add_scriptl(LABEL_NEXTLINE); - p++; - return p; - } - } - - if ((op=C_NEG,*p=='-') || (op=C_LNOT,*p=='!') || (op=C_NOT,*p=='~')) { - p=parse_subexpr(p+1,10); - add_scriptc(op); - } else - p=parse_simpleexpr(p); - p=skip_space(p); - while (( - (op=C_OP3,opl=0,len=1,*p=='?') || - (op=C_ADD,opl=8,len=1,*p=='+') || - (op=C_SUB,opl=8,len=1,*p=='-') || - (op=C_MUL,opl=9,len=1,*p=='*') || - (op=C_DIV,opl=9,len=1,*p=='/') || - (op=C_MOD,opl=9,len=1,*p=='%') || - (op=C_LAND,opl=2,len=2,*p=='&' && p[1]=='&') || - (op=C_AND,opl=6,len=1,*p=='&') || - (op=C_LOR,opl=1,len=2,*p=='|' && p[1]=='|') || - (op=C_OR,opl=5,len=1,*p=='|') || - (op=C_XOR,opl=4,len=1,*p=='^') || - (op=C_EQ,opl=3,len=2,*p=='=' && p[1]=='=') || - (op=C_NE,opl=3,len=2,*p=='!' && p[1]=='=') || - (op=C_R_SHIFT,opl=7,len=2,*p=='>' && p[1]=='>') || - (op=C_GE,opl=3,len=2,*p=='>' && p[1]=='=') || - (op=C_GT,opl=3,len=1,*p=='>') || - (op=C_L_SHIFT,opl=7,len=2,*p=='<' && p[1]=='<') || - (op=C_LE,opl=3,len=2,*p=='<' && p[1]=='=') || - (op=C_LT,opl=3,len=1,*p=='<')) && opl>limit) { - p+=len; - if (op == C_OP3) { - p=parse_subexpr(p,-1); - p=skip_space(p); - if (*(p++) != ':') - disp_error_message("parse_subexpr: need ':'", p-1); - p=parse_subexpr(p,-1); - } else { - p=parse_subexpr(p,opl); - } - add_scriptc(op); - p=skip_space(p); - } - - return p; /* return first untreated operator */ +const char* parse_subexpr(const char* p,int limit) +{ + int op,opl,len; + const char* tmpp; + + p=skip_space(p); + + if( *p == '-' ){ + tmpp = skip_space(p+1); + if( *tmpp == ';' || *tmpp == ',' ){ + add_scriptl(LABEL_NEXTLINE); + p++; + return p; + } + } + + if((op=C_NEG,*p=='-') || (op=C_LNOT,*p=='!') || (op=C_NOT,*p=='~')){ + p=parse_subexpr(p+1,10); + add_scriptc(op); + } else + p=parse_simpleexpr(p); + p=skip_space(p); + while(( + (op=C_OP3,opl=0,len=1,*p=='?') || + (op=C_ADD,opl=8,len=1,*p=='+') || + (op=C_SUB,opl=8,len=1,*p=='-') || + (op=C_MUL,opl=9,len=1,*p=='*') || + (op=C_DIV,opl=9,len=1,*p=='/') || + (op=C_MOD,opl=9,len=1,*p=='%') || + (op=C_LAND,opl=2,len=2,*p=='&' && p[1]=='&') || + (op=C_AND,opl=6,len=1,*p=='&') || + (op=C_LOR,opl=1,len=2,*p=='|' && p[1]=='|') || + (op=C_OR,opl=5,len=1,*p=='|') || + (op=C_XOR,opl=4,len=1,*p=='^') || + (op=C_EQ,opl=3,len=2,*p=='=' && p[1]=='=') || + (op=C_NE,opl=3,len=2,*p=='!' && p[1]=='=') || + (op=C_R_SHIFT,opl=7,len=2,*p=='>' && p[1]=='>') || + (op=C_GE,opl=3,len=2,*p=='>' && p[1]=='=') || + (op=C_GT,opl=3,len=1,*p=='>') || + (op=C_L_SHIFT,opl=7,len=2,*p=='<' && p[1]=='<') || + (op=C_LE,opl=3,len=2,*p=='<' && p[1]=='=') || + (op=C_LT,opl=3,len=1,*p=='<')) && opl>limit){ + p+=len; + if(op == C_OP3) { + p=parse_subexpr(p,-1); + p=skip_space(p); + if( *(p++) != ':') + disp_error_message("parse_subexpr: need ':'", p-1); + p=parse_subexpr(p,-1); + } else { + p=parse_subexpr(p,opl); + } + add_scriptc(op); + p=skip_space(p); + } + + return p; /* return first untreated operator */ } /*========================================== * Evaluation of the expression *------------------------------------------*/ -const char *parse_expr(const char *p) -{ - switch (*p) { - case ')': - case ';': - case ':': - case '[': - case ']': - case '}': - disp_error_message("parse_expr: unexpected char",p); - } - p=parse_subexpr(p,-1); - return p; +const char* parse_expr(const char *p) +{ + switch(*p){ + case ')': case ';': case ':': case '[': case ']': + case '}': + disp_error_message("parse_expr: unexpected char",p); + } + p=parse_subexpr(p,-1); + return p; } /*========================================== * Analysis of the line *------------------------------------------*/ -const char *parse_line(const char *p) -{ - const char *p2; - - p=skip_space(p); - if (*p==';') { - //Close decision for if(); for(); while(); - p = parse_syntax_close(p + 1); - return p; - } - if (*p==')' && parse_syntax_for_flag) - return p+1; - - p = skip_space(p); - if (p[0] == '{') { - syntax.curly[syntax.curly_count].type = TYPE_NULL; - syntax.curly[syntax.curly_count].count = -1; - syntax.curly[syntax.curly_count].index = -1; - syntax.curly_count++; - return p + 1; - } else if (p[0] == '}') { - return parse_curly_close(p); - } - - // Syntax-related processing - p2 = parse_syntax(p); - if (p2 != NULL) - return p2; - - // attempt to process a variable assignment - p2 = parse_variable(p); - - if (p2 != NULL) { - // variable assignment processed so leave the method - return parse_syntax_close(p2 + 1); - } - - p = parse_callfunc(p,0,0); - p = skip_space(p); - - if (parse_syntax_for_flag) { - if (*p != ')') - disp_error_message("parse_line: need ')'",p); - } else { - if (*p != ';') - disp_error_message("parse_line: need ';'",p); - } - - //Binding decision for if(), for(), while() - p = parse_syntax_close(p+1); - - return p; +const char* parse_line(const char* p) +{ + const char* p2; + + p=skip_space(p); + if(*p==';') { + //Close decision for if(); for(); while(); + p = parse_syntax_close(p + 1); + return p; + } + if(*p==')' && parse_syntax_for_flag) + return p+1; + + p = skip_space(p); + if(p[0] == '{') { + syntax.curly[syntax.curly_count].type = TYPE_NULL; + syntax.curly[syntax.curly_count].count = -1; + syntax.curly[syntax.curly_count].index = -1; + syntax.curly_count++; + return p + 1; + } else if(p[0] == '}') { + return parse_curly_close(p); + } + + // Syntax-related processing + p2 = parse_syntax(p); + if(p2 != NULL) + return p2; + + // attempt to process a variable assignment + p2 = parse_variable(p); + + if( p2 != NULL ) + {// variable assignment processed so leave the method + return parse_syntax_close(p2 + 1); + } + + p = parse_callfunc(p,0,0); + p = skip_space(p); + + if(parse_syntax_for_flag) { + if( *p != ')' ) + disp_error_message("parse_line: need ')'",p); + } else { + if( *p != ';' ) + disp_error_message("parse_line: need ';'",p); + } + + //Binding decision for if(), for(), while() + p = parse_syntax_close(p+1); + + return p; } // { ... } Closing process -const char *parse_curly_close(const char *p) -{ - if (syntax.curly_count <= 0) { - disp_error_message("parse_curly_close: unexpected string",p); - return p + 1; - } else if (syntax.curly[syntax.curly_count-1].type == TYPE_NULL) { - syntax.curly_count--; - //Close decision if, for , while - p = parse_syntax_close(p + 1); - return p; - } else if (syntax.curly[syntax.curly_count-1].type == TYPE_SWITCH) { - //Closing switch() - int pos = syntax.curly_count-1; - char label[256]; - int l; - // Remove temporary variables - sprintf(label,"set $@__SW%x_VAL,0;",syntax.curly[pos].index); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // Go to the end pointer unconditionally - sprintf(label,"goto __SW%x_FIN;",syntax.curly[pos].index); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // You are here labeled - sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count); - l=add_str(label); - set_label(l,script_pos, p); - - if (syntax.curly[pos].flag) { - //Exists default - sprintf(label,"goto __SW%x_DEF;",syntax.curly[pos].index); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - } - - // Label end - sprintf(label,"__SW%x_FIN",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos, p); - linkdb_final(&syntax.curly[pos].case_label); // free the list of case label - syntax.curly_count--; - //Closing decision if, for , while - p = parse_syntax_close(p + 1); - return p; - } else { - disp_error_message("parse_curly_close: unexpected string",p); - return p + 1; - } +const char* parse_curly_close(const char* p) +{ + if(syntax.curly_count <= 0) { + disp_error_message("parse_curly_close: unexpected string",p); + return p + 1; + } else if(syntax.curly[syntax.curly_count-1].type == TYPE_NULL) { + syntax.curly_count--; + //Close decision if, for , while + p = parse_syntax_close(p + 1); + return p; + } else if(syntax.curly[syntax.curly_count-1].type == TYPE_SWITCH) { + //Closing switch() + int pos = syntax.curly_count-1; + char label[256]; + int l; + // Remove temporary variables + sprintf(label,"set $@__SW%x_VAL,0;",syntax.curly[pos].index); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // Go to the end pointer unconditionally + sprintf(label,"goto __SW%x_FIN;",syntax.curly[pos].index); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // You are here labeled + sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count); + l=add_str(label); + set_label(l,script_pos, p); + + if(syntax.curly[pos].flag) { + //Exists default + sprintf(label,"goto __SW%x_DEF;",syntax.curly[pos].index); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + } + + // Label end + sprintf(label,"__SW%x_FIN",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos, p); + linkdb_final(&syntax.curly[pos].case_label); // free the list of case label + syntax.curly_count--; + //Closing decision if, for , while + p = parse_syntax_close(p + 1); + return p; + } else { + disp_error_message("parse_curly_close: unexpected string",p); + return p + 1; + } } // Syntax-related processing -// break, case, continue, default, do, for, function, -// if, switch, while ? will handle this internally. -const char *parse_syntax(const char *p) -{ - const char *p2 = skip_word(p); - - switch (*p) { - case 'B': - case 'b': - if (p2 - p == 5 && !strncasecmp(p,"break",5)) { - // break Processing - char label[256]; - int pos = syntax.curly_count - 1; - while (pos >= 0) { - if (syntax.curly[pos].type == TYPE_DO) { - sprintf(label,"goto __DO%x_FIN;",syntax.curly[pos].index); - break; - } else if (syntax.curly[pos].type == TYPE_FOR) { - sprintf(label,"goto __FR%x_FIN;",syntax.curly[pos].index); - break; - } else if (syntax.curly[pos].type == TYPE_WHILE) { - sprintf(label,"goto __WL%x_FIN;",syntax.curly[pos].index); - break; - } else if (syntax.curly[pos].type == TYPE_SWITCH) { - sprintf(label,"goto __SW%x_FIN;",syntax.curly[pos].index); - break; - } - pos--; - } - if (pos < 0) { - disp_error_message("parse_syntax: unexpected 'break'",p); - } else { - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - } - p = skip_space(p2); - if (*p != ';') - disp_error_message("parse_syntax: need ';'",p); - // Closing decision if, for , while - p = parse_syntax_close(p + 1); - return p; - } - break; - case 'c': - case 'C': - if (p2 - p == 4 && !strncasecmp(p,"case",4)) { - //Processing case - int pos = syntax.curly_count-1; - if (pos < 0 || syntax.curly[pos].type != TYPE_SWITCH) { - disp_error_message("parse_syntax: unexpected 'case' ",p); - return p+1; - } else { - char label[256]; - int l,v; - char *np; - if (syntax.curly[pos].count != 1) { - //Jump for FALLTHRU - sprintf(label,"goto __SW%x_%xJ;",syntax.curly[pos].index,syntax.curly[pos].count); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // You are here labeled - sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count); - l=add_str(label); - set_label(l,script_pos, p); - } - //Decision statement switch - p = skip_space(p2); - if (p == p2) { - disp_error_message("parse_syntax: expect space ' '",p); - } - // check whether case label is integer or not - v = strtol(p,&np,0); - if (np == p) { //Check for constants - p2 = skip_word(p); - v = p2-p; // length of word at p2 - memcpy(label,p,v); - label[v]='\0'; - if (!script_get_constant(label, &v)) - disp_error_message("parse_syntax: 'case' label not integer",p); - p = skip_word(p); - } else { //Numeric value - if ((*p == '-' || *p == '+') && ISDIGIT(p[1])) // pre-skip because '-' can not skip_word - p++; - p = skip_word(p); - if (np != p) - disp_error_message("parse_syntax: 'case' label not integer",np); - } - p = skip_space(p); - if (*p != ':') - disp_error_message("parse_syntax: expect ':'",p); - sprintf(label,"if(%d != $@__SW%x_VAL) goto __SW%x_%x;", - v,syntax.curly[pos].index,syntax.curly[pos].index,syntax.curly[pos].count+1); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - // Bad I do not parse twice - p2 = parse_line(label); - parse_line(p2); - syntax.curly_count--; - if (syntax.curly[pos].count != 1) { - // Label after the completion of FALLTHRU - sprintf(label,"__SW%x_%xJ",syntax.curly[pos].index,syntax.curly[pos].count); - l=add_str(label); - set_label(l,script_pos,p); - } - // check duplication of case label [Rayce] - if (linkdb_search(&syntax.curly[pos].case_label, (void *)__64BPRTSIZE(v)) != NULL) - disp_error_message("parse_syntax: dup 'case'",p); - linkdb_insert(&syntax.curly[pos].case_label, (void *)__64BPRTSIZE(v), (void *)1); - - sprintf(label,"set $@__SW%x_VAL,0;",syntax.curly[pos].index); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - - parse_line(label); - syntax.curly_count--; - syntax.curly[pos].count++; - } - return p + 1; - } else if (p2 - p == 8 && !strncasecmp(p,"continue",8)) { - // Processing continue - char label[256]; - int pos = syntax.curly_count - 1; - while (pos >= 0) { - if (syntax.curly[pos].type == TYPE_DO) { - sprintf(label,"goto __DO%x_NXT;",syntax.curly[pos].index); - syntax.curly[pos].flag = 1; //Flag put the link for continue - break; - } else if (syntax.curly[pos].type == TYPE_FOR) { - sprintf(label,"goto __FR%x_NXT;",syntax.curly[pos].index); - break; - } else if (syntax.curly[pos].type == TYPE_WHILE) { - sprintf(label,"goto __WL%x_NXT;",syntax.curly[pos].index); - break; - } - pos--; - } - if (pos < 0) { - disp_error_message("parse_syntax: unexpected 'continue'",p); - } else { - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - } - p = skip_space(p2); - if (*p != ';') - disp_error_message("parse_syntax: need ';'",p); - //Closing decision if, for , while - p = parse_syntax_close(p + 1); - return p; - } - break; - case 'd': - case 'D': - if (p2 - p == 7 && !strncasecmp(p,"default",7)) { - // Switch - default processing - int pos = syntax.curly_count-1; - if (pos < 0 || syntax.curly[pos].type != TYPE_SWITCH) { - disp_error_message("parse_syntax: unexpected 'default'",p); - } else if (syntax.curly[pos].flag) { - disp_error_message("parse_syntax: dup 'default'",p); - } else { - char label[256]; - int l; - // Put the label location - p = skip_space(p2); - if (*p != ':') { - disp_error_message("parse_syntax: need ':'",p); - } - sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count); - l=add_str(label); - set_label(l,script_pos,p); - - // Skip to the next link w/o condition - sprintf(label,"goto __SW%x_%x;",syntax.curly[pos].index,syntax.curly[pos].count+1); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // The default label - sprintf(label,"__SW%x_DEF",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos,p); - - syntax.curly[syntax.curly_count - 1].flag = 1; - syntax.curly[pos].count++; - } - return p + 1; - } else if (p2 - p == 2 && !strncasecmp(p,"do",2)) { - int l; - char label[256]; - p=skip_space(p2); - - syntax.curly[syntax.curly_count].type = TYPE_DO; - syntax.curly[syntax.curly_count].count = 1; - syntax.curly[syntax.curly_count].index = syntax.index++; - syntax.curly[syntax.curly_count].flag = 0; - // Label of the (do) form here - sprintf(label,"__DO%x_BGN",syntax.curly[syntax.curly_count].index); - l=add_str(label); - set_label(l,script_pos,p); - syntax.curly_count++; - return p; - } - break; - case 'f': - case 'F': - if (p2 - p == 3 && !strncasecmp(p,"for",3)) { - int l; - char label[256]; - int pos = syntax.curly_count; - syntax.curly[syntax.curly_count].type = TYPE_FOR; - syntax.curly[syntax.curly_count].count = 1; - syntax.curly[syntax.curly_count].index = syntax.index++; - syntax.curly[syntax.curly_count].flag = 0; - syntax.curly_count++; - - p=skip_space(p2); - - if (*p != '(') - disp_error_message("parse_syntax: need '('",p); - p++; - - // Execute the initialization statement - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - p=parse_line(p); - syntax.curly_count--; - - // Form the start of label decision - sprintf(label,"__FR%x_J",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos,p); - - p=skip_space(p); - if (*p == ';') { - // For (; Because the pattern of always true ;) - ; - } else { - // Skip to the end point if the condition is false - sprintf(label,"__FR%x_FIN",syntax.curly[pos].index); - add_scriptl(add_str("jump_zero")); - add_scriptc(C_ARG); - p=parse_expr(p); - p=skip_space(p); - add_scriptl(add_str(label)); - add_scriptc(C_FUNC); - } - if (*p != ';') - disp_error_message("parse_syntax: need ';'",p); - p++; - - // Skip to the beginning of the loop - sprintf(label,"goto __FR%x_BGN;",syntax.curly[pos].index); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // Labels to form the next loop - sprintf(label,"__FR%x_NXT",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos,p); - - // Process the next time you enter the loop - // A ')' last for; flag to be treated as' - parse_syntax_for_flag = 1; - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - p=parse_line(p); - syntax.curly_count--; - parse_syntax_for_flag = 0; - - // Skip to the determination process conditions - sprintf(label,"goto __FR%x_J;",syntax.curly[pos].index); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // Loop start labeling - sprintf(label,"__FR%x_BGN",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos,p); - return p; - } else if (p2 - p == 8 && strncasecmp(p,"function",8) == 0) { - // internal script function - const char *func_name; - - func_name = skip_space(p2); - p = skip_word(func_name); - if (p == func_name) - disp_error_message("parse_syntax:function: function name is missing or invalid", p); - p2 = skip_space(p); - if (*p2 == ';') { - // function <name> ; - // function declaration - just register the name - int l; - l = add_word(func_name); - if (str_data[l].type == C_NOP) // register only, if the name was not used by something else - str_data[l].type = C_USERFUNC; - else if (str_data[l].type == C_USERFUNC) - ; // already registered - else - disp_error_message("parse_syntax:function: function name is invalid", func_name); - - // Close condition of if, for, while - p = parse_syntax_close(p2 + 1); - return p; - } else if (*p2 == '{') { - // function <name> <line/block of code> - char label[256]; - int l; - - syntax.curly[syntax.curly_count].type = TYPE_USERFUNC; - syntax.curly[syntax.curly_count].count = 1; - syntax.curly[syntax.curly_count].index = syntax.index++; - syntax.curly[syntax.curly_count].flag = 0; - ++syntax.curly_count; - - // Jump over the function code - sprintf(label, "goto __FN%x_FIN;", syntax.curly[syntax.curly_count-1].index); - syntax.curly[syntax.curly_count].type = TYPE_NULL; - ++syntax.curly_count; - parse_line(label); - --syntax.curly_count; - - // Set the position of the function (label) - l=add_word(func_name); - if (str_data[l].type == C_NOP || str_data[l].type == C_USERFUNC) { // register only, if the name was not used by something else - str_data[l].type = C_USERFUNC; - set_label(l, script_pos, p); - if (parse_options&SCRIPT_USE_LABEL_DB) - strdb_iput(scriptlabel_db, get_str(l), script_pos); - } else - disp_error_message("parse_syntax:function: function name is invalid", func_name); - - return skip_space(p); - } else { - disp_error_message("expect ';' or '{' at function syntax",p); - } - } - break; - case 'i': - case 'I': - if (p2 - p == 2 && !strncasecmp(p,"if",2)) { - // If process - char label[256]; - p=skip_space(p2); - if (*p != '(') { //Prevent if this {} non-c syntax. from Rayce (jA) - disp_error_message("need '('",p); - } - syntax.curly[syntax.curly_count].type = TYPE_IF; - syntax.curly[syntax.curly_count].count = 1; - syntax.curly[syntax.curly_count].index = syntax.index++; - syntax.curly[syntax.curly_count].flag = 0; - sprintf(label,"__IF%x_%x",syntax.curly[syntax.curly_count].index,syntax.curly[syntax.curly_count].count); - syntax.curly_count++; - add_scriptl(add_str("jump_zero")); - add_scriptc(C_ARG); - p=parse_expr(p); - p=skip_space(p); - add_scriptl(add_str(label)); - add_scriptc(C_FUNC); - return p; - } - break; - case 's': - case 'S': - if (p2 - p == 6 && !strncasecmp(p,"switch",6)) { - // Processing of switch () - char label[256]; - p=skip_space(p2); - if (*p != '(') { - disp_error_message("need '('",p); - } - syntax.curly[syntax.curly_count].type = TYPE_SWITCH; - syntax.curly[syntax.curly_count].count = 1; - syntax.curly[syntax.curly_count].index = syntax.index++; - syntax.curly[syntax.curly_count].flag = 0; - sprintf(label,"$@__SW%x_VAL",syntax.curly[syntax.curly_count].index); - syntax.curly_count++; - add_scriptl(add_str("set")); - add_scriptc(C_ARG); - add_scriptl(add_str(label)); - p=parse_expr(p); - p=skip_space(p); - if (*p != '{') { - disp_error_message("parse_syntax: need '{'",p); - } - add_scriptc(C_FUNC); - return p + 1; - } - break; - case 'w': - case 'W': - if (p2 - p == 5 && !strncasecmp(p,"while",5)) { - int l; - char label[256]; - p=skip_space(p2); - if (*p != '(') { - disp_error_message("need '('",p); - } - syntax.curly[syntax.curly_count].type = TYPE_WHILE; - syntax.curly[syntax.curly_count].count = 1; - syntax.curly[syntax.curly_count].index = syntax.index++; - syntax.curly[syntax.curly_count].flag = 0; - // Form the start of label decision - sprintf(label,"__WL%x_NXT",syntax.curly[syntax.curly_count].index); - l=add_str(label); - set_label(l,script_pos,p); - - // Skip to the end point if the condition is false - sprintf(label,"__WL%x_FIN",syntax.curly[syntax.curly_count].index); - syntax.curly_count++; - add_scriptl(add_str("jump_zero")); - add_scriptc(C_ARG); - p=parse_expr(p); - p=skip_space(p); - add_scriptl(add_str(label)); - add_scriptc(C_FUNC); - return p; - } - break; - } - return NULL; -} - -const char *parse_syntax_close(const char *p) -{ - // If (...) for (...) hoge (); as to make sure closed closed once again - int flag; - - do { - p = parse_syntax_close_sub(p,&flag); - } while (flag); - return p; +// break, case, continue, default, do, for, function, +// if, switch, while ? will handle this internally. +const char* parse_syntax(const char* p) +{ + const char *p2 = skip_word(p); + + switch(*p) { + case 'B': + case 'b': + if(p2 - p == 5 && !strncasecmp(p,"break",5)) { + // break Processing + char label[256]; + int pos = syntax.curly_count - 1; + while(pos >= 0) { + if(syntax.curly[pos].type == TYPE_DO) { + sprintf(label,"goto __DO%x_FIN;",syntax.curly[pos].index); + break; + } else if(syntax.curly[pos].type == TYPE_FOR) { + sprintf(label,"goto __FR%x_FIN;",syntax.curly[pos].index); + break; + } else if(syntax.curly[pos].type == TYPE_WHILE) { + sprintf(label,"goto __WL%x_FIN;",syntax.curly[pos].index); + break; + } else if(syntax.curly[pos].type == TYPE_SWITCH) { + sprintf(label,"goto __SW%x_FIN;",syntax.curly[pos].index); + break; + } + pos--; + } + if(pos < 0) { + disp_error_message("parse_syntax: unexpected 'break'",p); + } else { + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + } + p = skip_space(p2); + if(*p != ';') + disp_error_message("parse_syntax: need ';'",p); + // Closing decision if, for , while + p = parse_syntax_close(p + 1); + return p; + } + break; + case 'c': + case 'C': + if(p2 - p == 4 && !strncasecmp(p,"case",4)) { + //Processing case + int pos = syntax.curly_count-1; + if(pos < 0 || syntax.curly[pos].type != TYPE_SWITCH) { + disp_error_message("parse_syntax: unexpected 'case' ",p); + return p+1; + } else { + char label[256]; + int l,v; + char *np; + if(syntax.curly[pos].count != 1) { + //Jump for FALLTHRU + sprintf(label,"goto __SW%x_%xJ;",syntax.curly[pos].index,syntax.curly[pos].count); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // You are here labeled + sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count); + l=add_str(label); + set_label(l,script_pos, p); + } + //Decision statement switch + p = skip_space(p2); + if(p == p2) { + disp_error_message("parse_syntax: expect space ' '",p); + } + // check whether case label is integer or not + v = strtol(p,&np,0); + if(np == p) { //Check for constants + p2 = skip_word(p); + v = p2-p; // length of word at p2 + memcpy(label,p,v); + label[v]='\0'; + if( !script_get_constant(label, &v) ) + disp_error_message("parse_syntax: 'case' label not integer",p); + p = skip_word(p); + } else { //Numeric value + if((*p == '-' || *p == '+') && ISDIGIT(p[1])) // pre-skip because '-' can not skip_word + p++; + p = skip_word(p); + if(np != p) + disp_error_message("parse_syntax: 'case' label not integer",np); + } + p = skip_space(p); + if(*p != ':') + disp_error_message("parse_syntax: expect ':'",p); + sprintf(label,"if(%d != $@__SW%x_VAL) goto __SW%x_%x;", + v,syntax.curly[pos].index,syntax.curly[pos].index,syntax.curly[pos].count+1); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + // Bad I do not parse twice + p2 = parse_line(label); + parse_line(p2); + syntax.curly_count--; + if(syntax.curly[pos].count != 1) { + // Label after the completion of FALLTHRU + sprintf(label,"__SW%x_%xJ",syntax.curly[pos].index,syntax.curly[pos].count); + l=add_str(label); + set_label(l,script_pos,p); + } + // check duplication of case label [Rayce] + if(linkdb_search(&syntax.curly[pos].case_label, (void*)__64BPRTSIZE(v)) != NULL) + disp_error_message("parse_syntax: dup 'case'",p); + linkdb_insert(&syntax.curly[pos].case_label, (void*)__64BPRTSIZE(v), (void*)1); + + sprintf(label,"set $@__SW%x_VAL,0;",syntax.curly[pos].index); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + + parse_line(label); + syntax.curly_count--; + syntax.curly[pos].count++; + } + return p + 1; + } else if(p2 - p == 8 && !strncasecmp(p,"continue",8)) { + // Processing continue + char label[256]; + int pos = syntax.curly_count - 1; + while(pos >= 0) { + if(syntax.curly[pos].type == TYPE_DO) { + sprintf(label,"goto __DO%x_NXT;",syntax.curly[pos].index); + syntax.curly[pos].flag = 1; //Flag put the link for continue + break; + } else if(syntax.curly[pos].type == TYPE_FOR) { + sprintf(label,"goto __FR%x_NXT;",syntax.curly[pos].index); + break; + } else if(syntax.curly[pos].type == TYPE_WHILE) { + sprintf(label,"goto __WL%x_NXT;",syntax.curly[pos].index); + break; + } + pos--; + } + if(pos < 0) { + disp_error_message("parse_syntax: unexpected 'continue'",p); + } else { + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + } + p = skip_space(p2); + if(*p != ';') + disp_error_message("parse_syntax: need ';'",p); + //Closing decision if, for , while + p = parse_syntax_close(p + 1); + return p; + } + break; + case 'd': + case 'D': + if(p2 - p == 7 && !strncasecmp(p,"default",7)) { + // Switch - default processing + int pos = syntax.curly_count-1; + if(pos < 0 || syntax.curly[pos].type != TYPE_SWITCH) { + disp_error_message("parse_syntax: unexpected 'default'",p); + } else if(syntax.curly[pos].flag) { + disp_error_message("parse_syntax: dup 'default'",p); + } else { + char label[256]; + int l; + // Put the label location + p = skip_space(p2); + if(*p != ':') { + disp_error_message("parse_syntax: need ':'",p); + } + sprintf(label,"__SW%x_%x",syntax.curly[pos].index,syntax.curly[pos].count); + l=add_str(label); + set_label(l,script_pos,p); + + // Skip to the next link w/o condition + sprintf(label,"goto __SW%x_%x;",syntax.curly[pos].index,syntax.curly[pos].count+1); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // The default label + sprintf(label,"__SW%x_DEF",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos,p); + + syntax.curly[syntax.curly_count - 1].flag = 1; + syntax.curly[pos].count++; + } + return p + 1; + } else if(p2 - p == 2 && !strncasecmp(p,"do",2)) { + int l; + char label[256]; + p=skip_space(p2); + + syntax.curly[syntax.curly_count].type = TYPE_DO; + syntax.curly[syntax.curly_count].count = 1; + syntax.curly[syntax.curly_count].index = syntax.index++; + syntax.curly[syntax.curly_count].flag = 0; + // Label of the (do) form here + sprintf(label,"__DO%x_BGN",syntax.curly[syntax.curly_count].index); + l=add_str(label); + set_label(l,script_pos,p); + syntax.curly_count++; + return p; + } + break; + case 'f': + case 'F': + if(p2 - p == 3 && !strncasecmp(p,"for",3)) { + int l; + char label[256]; + int pos = syntax.curly_count; + syntax.curly[syntax.curly_count].type = TYPE_FOR; + syntax.curly[syntax.curly_count].count = 1; + syntax.curly[syntax.curly_count].index = syntax.index++; + syntax.curly[syntax.curly_count].flag = 0; + syntax.curly_count++; + + p=skip_space(p2); + + if(*p != '(') + disp_error_message("parse_syntax: need '('",p); + p++; + + // Execute the initialization statement + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + p=parse_line(p); + syntax.curly_count--; + + // Form the start of label decision + sprintf(label,"__FR%x_J",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos,p); + + p=skip_space(p); + if(*p == ';') { + // For (; Because the pattern of always true ;) + ; + } else { + // Skip to the end point if the condition is false + sprintf(label,"__FR%x_FIN",syntax.curly[pos].index); + add_scriptl(add_str("jump_zero")); + add_scriptc(C_ARG); + p=parse_expr(p); + p=skip_space(p); + add_scriptl(add_str(label)); + add_scriptc(C_FUNC); + } + if(*p != ';') + disp_error_message("parse_syntax: need ';'",p); + p++; + + // Skip to the beginning of the loop + sprintf(label,"goto __FR%x_BGN;",syntax.curly[pos].index); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // Labels to form the next loop + sprintf(label,"__FR%x_NXT",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos,p); + + // Process the next time you enter the loop + // A ')' last for; flag to be treated as' + parse_syntax_for_flag = 1; + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + p=parse_line(p); + syntax.curly_count--; + parse_syntax_for_flag = 0; + + // Skip to the determination process conditions + sprintf(label,"goto __FR%x_J;",syntax.curly[pos].index); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // Loop start labeling + sprintf(label,"__FR%x_BGN",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos,p); + return p; + } + else if( p2 - p == 8 && strncasecmp(p,"function",8) == 0 ) + {// internal script function + const char *func_name; + + func_name = skip_space(p2); + p = skip_word(func_name); + if( p == func_name ) + disp_error_message("parse_syntax:function: function name is missing or invalid", p); + p2 = skip_space(p); + if( *p2 == ';' ) + {// function <name> ; + // function declaration - just register the name + int l; + l = add_word(func_name); + if( str_data[l].type == C_NOP )// register only, if the name was not used by something else + str_data[l].type = C_USERFUNC; + else if( str_data[l].type == C_USERFUNC ) + ; // already registered + else + disp_error_message("parse_syntax:function: function name is invalid", func_name); + + // Close condition of if, for, while + p = parse_syntax_close(p2 + 1); + return p; + } + else if(*p2 == '{') + {// function <name> <line/block of code> + char label[256]; + int l; + + syntax.curly[syntax.curly_count].type = TYPE_USERFUNC; + syntax.curly[syntax.curly_count].count = 1; + syntax.curly[syntax.curly_count].index = syntax.index++; + syntax.curly[syntax.curly_count].flag = 0; + ++syntax.curly_count; + + // Jump over the function code + sprintf(label, "goto __FN%x_FIN;", syntax.curly[syntax.curly_count-1].index); + syntax.curly[syntax.curly_count].type = TYPE_NULL; + ++syntax.curly_count; + parse_line(label); + --syntax.curly_count; + + // Set the position of the function (label) + l=add_word(func_name); + if( str_data[l].type == C_NOP || str_data[l].type == C_USERFUNC )// register only, if the name was not used by something else + { + str_data[l].type = C_USERFUNC; + set_label(l, script_pos, p); + if( parse_options&SCRIPT_USE_LABEL_DB ) + strdb_iput(scriptlabel_db, get_str(l), script_pos); + } + else + disp_error_message("parse_syntax:function: function name is invalid", func_name); + + return skip_space(p); + } + else + { + disp_error_message("expect ';' or '{' at function syntax",p); + } + } + break; + case 'i': + case 'I': + if(p2 - p == 2 && !strncasecmp(p,"if",2)) { + // If process + char label[256]; + p=skip_space(p2); + if(*p != '(') { //Prevent if this {} non-c syntax. from Rayce (jA) + disp_error_message("need '('",p); + } + syntax.curly[syntax.curly_count].type = TYPE_IF; + syntax.curly[syntax.curly_count].count = 1; + syntax.curly[syntax.curly_count].index = syntax.index++; + syntax.curly[syntax.curly_count].flag = 0; + sprintf(label,"__IF%x_%x",syntax.curly[syntax.curly_count].index,syntax.curly[syntax.curly_count].count); + syntax.curly_count++; + add_scriptl(add_str("jump_zero")); + add_scriptc(C_ARG); + p=parse_expr(p); + p=skip_space(p); + add_scriptl(add_str(label)); + add_scriptc(C_FUNC); + return p; + } + break; + case 's': + case 'S': + if(p2 - p == 6 && !strncasecmp(p,"switch",6)) { + // Processing of switch () + char label[256]; + p=skip_space(p2); + if(*p != '(') { + disp_error_message("need '('",p); + } + syntax.curly[syntax.curly_count].type = TYPE_SWITCH; + syntax.curly[syntax.curly_count].count = 1; + syntax.curly[syntax.curly_count].index = syntax.index++; + syntax.curly[syntax.curly_count].flag = 0; + sprintf(label,"$@__SW%x_VAL",syntax.curly[syntax.curly_count].index); + syntax.curly_count++; + add_scriptl(add_str("set")); + add_scriptc(C_ARG); + add_scriptl(add_str(label)); + p=parse_expr(p); + p=skip_space(p); + if(*p != '{') { + disp_error_message("parse_syntax: need '{'",p); + } + add_scriptc(C_FUNC); + return p + 1; + } + break; + case 'w': + case 'W': + if(p2 - p == 5 && !strncasecmp(p,"while",5)) { + int l; + char label[256]; + p=skip_space(p2); + if(*p != '(') { + disp_error_message("need '('",p); + } + syntax.curly[syntax.curly_count].type = TYPE_WHILE; + syntax.curly[syntax.curly_count].count = 1; + syntax.curly[syntax.curly_count].index = syntax.index++; + syntax.curly[syntax.curly_count].flag = 0; + // Form the start of label decision + sprintf(label,"__WL%x_NXT",syntax.curly[syntax.curly_count].index); + l=add_str(label); + set_label(l,script_pos,p); + + // Skip to the end point if the condition is false + sprintf(label,"__WL%x_FIN",syntax.curly[syntax.curly_count].index); + syntax.curly_count++; + add_scriptl(add_str("jump_zero")); + add_scriptc(C_ARG); + p=parse_expr(p); + p=skip_space(p); + add_scriptl(add_str(label)); + add_scriptc(C_FUNC); + return p; + } + break; + } + return NULL; +} + +const char* parse_syntax_close(const char *p) { + // If (...) for (...) hoge (); as to make sure closed closed once again + int flag; + + do { + p = parse_syntax_close_sub(p,&flag); + } while(flag); + return p; } // Close judgment if, for, while, of do -// flag == 1 : closed -// flag == 0 : not closed -const char *parse_syntax_close_sub(const char *p,int *flag) -{ - char label[256]; - int pos = syntax.curly_count - 1; - int l; - *flag = 1; - - if (syntax.curly_count <= 0) { - *flag = 0; - return p; - } else if (syntax.curly[pos].type == TYPE_IF) { - const char *bp = p; - const char *p2; - - // if-block and else-block end is a new line - parse_nextline(false, p); - - // Skip to the last location if - sprintf(label,"goto __IF%x_FIN;",syntax.curly[pos].index); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // Put the label of the location - sprintf(label,"__IF%x_%x",syntax.curly[pos].index,syntax.curly[pos].count); - l=add_str(label); - set_label(l,script_pos,p); - - syntax.curly[pos].count++; - p = skip_space(p); - p2 = skip_word(p); - if (!syntax.curly[pos].flag && p2 - p == 4 && !strncasecmp(p,"else",4)) { - // else or else - if - p = skip_space(p2); - p2 = skip_word(p); - if (p2 - p == 2 && !strncasecmp(p,"if",2)) { - // else - if - p=skip_space(p2); - if (*p != '(') { - disp_error_message("need '('",p); - } - sprintf(label,"__IF%x_%x",syntax.curly[pos].index,syntax.curly[pos].count); - add_scriptl(add_str("jump_zero")); - add_scriptc(C_ARG); - p=parse_expr(p); - p=skip_space(p); - add_scriptl(add_str(label)); - add_scriptc(C_FUNC); - *flag = 0; - return p; - } else { - // else - if (!syntax.curly[pos].flag) { - syntax.curly[pos].flag = 1; - *flag = 0; - return p; - } - } - } - // Close if - syntax.curly_count--; - // Put the label of the final location - sprintf(label,"__IF%x_FIN",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos,p); - if (syntax.curly[pos].flag == 1) { - // Because the position of the pointer is the same if not else for this - return bp; - } - return p; - } else if (syntax.curly[pos].type == TYPE_DO) { - int l; - char label[256]; - const char *p2; - - if (syntax.curly[pos].flag) { - // (Come here continue) to form the label here - sprintf(label,"__DO%x_NXT",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos,p); - } - - // Skip to the end point if the condition is false - p = skip_space(p); - p2 = skip_word(p); - if (p2 - p != 5 || strncasecmp(p,"while",5)) - disp_error_message("parse_syntax: need 'while'",p); - - p = skip_space(p2); - if (*p != '(') { - disp_error_message("need '('",p); - } - - // do-block end is a new line - parse_nextline(false, p); - - sprintf(label,"__DO%x_FIN",syntax.curly[pos].index); - add_scriptl(add_str("jump_zero")); - add_scriptc(C_ARG); - p=parse_expr(p); - p=skip_space(p); - add_scriptl(add_str(label)); - add_scriptc(C_FUNC); - - // Skip to the starting point - sprintf(label,"goto __DO%x_BGN;",syntax.curly[pos].index); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // Form label of the end point conditions - sprintf(label,"__DO%x_FIN",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos,p); - p = skip_space(p); - if (*p != ';') { - disp_error_message("parse_syntax: need ';'",p); - return p+1; - } - p++; - syntax.curly_count--; - return p; - } else if (syntax.curly[pos].type == TYPE_FOR) { - // for-block end is a new line - parse_nextline(false, p); - - // Skip to the next loop - sprintf(label,"goto __FR%x_NXT;",syntax.curly[pos].index); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // End for labeling - sprintf(label,"__FR%x_FIN",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos,p); - syntax.curly_count--; - return p; - } else if (syntax.curly[pos].type == TYPE_WHILE) { - // while-block end is a new line - parse_nextline(false, p); - - // Skip to the decision while - sprintf(label,"goto __WL%x_NXT;",syntax.curly[pos].index); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // End while labeling - sprintf(label,"__WL%x_FIN",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos,p); - syntax.curly_count--; - return p; - } else if (syntax.curly[syntax.curly_count-1].type == TYPE_USERFUNC) { - int pos = syntax.curly_count-1; - char label[256]; - int l; - // Back - sprintf(label,"return;"); - syntax.curly[syntax.curly_count++].type = TYPE_NULL; - parse_line(label); - syntax.curly_count--; - - // Put the label of the location - sprintf(label,"__FN%x_FIN",syntax.curly[pos].index); - l=add_str(label); - set_label(l,script_pos,p); - syntax.curly_count--; - return p; - } else { - *flag = 0; - return p; - } +// flag == 1 : closed +// flag == 0 : not closed +const char* parse_syntax_close_sub(const char* p,int* flag) +{ + char label[256]; + int pos = syntax.curly_count - 1; + int l; + *flag = 1; + + if(syntax.curly_count <= 0) { + *flag = 0; + return p; + } else if(syntax.curly[pos].type == TYPE_IF) { + const char *bp = p; + const char *p2; + + // if-block and else-block end is a new line + parse_nextline(false, p); + + // Skip to the last location if + sprintf(label,"goto __IF%x_FIN;",syntax.curly[pos].index); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // Put the label of the location + sprintf(label,"__IF%x_%x",syntax.curly[pos].index,syntax.curly[pos].count); + l=add_str(label); + set_label(l,script_pos,p); + + syntax.curly[pos].count++; + p = skip_space(p); + p2 = skip_word(p); + if(!syntax.curly[pos].flag && p2 - p == 4 && !strncasecmp(p,"else",4)) { + // else or else - if + p = skip_space(p2); + p2 = skip_word(p); + if(p2 - p == 2 && !strncasecmp(p,"if",2)) { + // else - if + p=skip_space(p2); + if(*p != '(') { + disp_error_message("need '('",p); + } + sprintf(label,"__IF%x_%x",syntax.curly[pos].index,syntax.curly[pos].count); + add_scriptl(add_str("jump_zero")); + add_scriptc(C_ARG); + p=parse_expr(p); + p=skip_space(p); + add_scriptl(add_str(label)); + add_scriptc(C_FUNC); + *flag = 0; + return p; + } else { + // else + if(!syntax.curly[pos].flag) { + syntax.curly[pos].flag = 1; + *flag = 0; + return p; + } + } + } + // Close if + syntax.curly_count--; + // Put the label of the final location + sprintf(label,"__IF%x_FIN",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos,p); + if(syntax.curly[pos].flag == 1) { + // Because the position of the pointer is the same if not else for this + return bp; + } + return p; + } else if(syntax.curly[pos].type == TYPE_DO) { + int l; + char label[256]; + const char *p2; + + if(syntax.curly[pos].flag) { + // (Come here continue) to form the label here + sprintf(label,"__DO%x_NXT",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos,p); + } + + // Skip to the end point if the condition is false + p = skip_space(p); + p2 = skip_word(p); + if(p2 - p != 5 || strncasecmp(p,"while",5)) + disp_error_message("parse_syntax: need 'while'",p); + + p = skip_space(p2); + if(*p != '(') { + disp_error_message("need '('",p); + } + + // do-block end is a new line + parse_nextline(false, p); + + sprintf(label,"__DO%x_FIN",syntax.curly[pos].index); + add_scriptl(add_str("jump_zero")); + add_scriptc(C_ARG); + p=parse_expr(p); + p=skip_space(p); + add_scriptl(add_str(label)); + add_scriptc(C_FUNC); + + // Skip to the starting point + sprintf(label,"goto __DO%x_BGN;",syntax.curly[pos].index); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // Form label of the end point conditions + sprintf(label,"__DO%x_FIN",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos,p); + p = skip_space(p); + if(*p != ';') { + disp_error_message("parse_syntax: need ';'",p); + return p+1; + } + p++; + syntax.curly_count--; + return p; + } else if(syntax.curly[pos].type == TYPE_FOR) { + // for-block end is a new line + parse_nextline(false, p); + + // Skip to the next loop + sprintf(label,"goto __FR%x_NXT;",syntax.curly[pos].index); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // End for labeling + sprintf(label,"__FR%x_FIN",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos,p); + syntax.curly_count--; + return p; + } else if(syntax.curly[pos].type == TYPE_WHILE) { + // while-block end is a new line + parse_nextline(false, p); + + // Skip to the decision while + sprintf(label,"goto __WL%x_NXT;",syntax.curly[pos].index); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // End while labeling + sprintf(label,"__WL%x_FIN",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos,p); + syntax.curly_count--; + return p; + } else if(syntax.curly[syntax.curly_count-1].type == TYPE_USERFUNC) { + int pos = syntax.curly_count-1; + char label[256]; + int l; + // Back + sprintf(label,"return;"); + syntax.curly[syntax.curly_count++].type = TYPE_NULL; + parse_line(label); + syntax.curly_count--; + + // Put the label of the location + sprintf(label,"__FN%x_FIN",syntax.curly[pos].index); + l=add_str(label); + set_label(l,script_pos,p); + syntax.curly_count--; + return p; + } else { + *flag = 0; + return p; + } } /*========================================== @@ -2104,69 +2126,72 @@ const char *parse_syntax_close_sub(const char *p,int *flag) *------------------------------------------*/ static void add_buildin_func(void) { - int i,n; - const char *p; - for (i = 0; buildin_func[i].func; i++) { - // arg must follow the pattern: (v|s|i|r|l)*\?*\*? - // 'v' - value (either string or int or reference) - // 's' - string - // 'i' - int - // 'r' - reference (of a variable) - // 'l' - label - // '?' - one optional parameter - // '*' - unknown number of optional parameters - p = buildin_func[i].arg; - while (*p == 'v' || *p == 's' || *p == 'i' || *p == 'r' || *p == 'l') ++p; - while (*p == '?') ++p; - if (*p == '*') ++p; - if (*p != 0) { - ShowWarning("add_buildin_func: ignoring function \"%s\" with invalid arg \"%s\".\n", buildin_func[i].name, buildin_func[i].arg); - } else if (*skip_word(buildin_func[i].name) != 0) { - ShowWarning("add_buildin_func: ignoring function with invalid name \"%s\" (must be a word).\n", buildin_func[i].name); - } else { - n = add_str(buildin_func[i].name); - str_data[n].type = C_FUNC; - str_data[n].val = i; - str_data[n].func = buildin_func[i].func; + int i,n; + const char* p; + for( i = 0; buildin_func[i].func; i++ ) + { + // arg must follow the pattern: (v|s|i|r|l)*\?*\*? + // 'v' - value (either string or int or reference) + // 's' - string + // 'i' - int + // 'r' - reference (of a variable) + // 'l' - label + // '?' - one optional parameter + // '*' - unknown number of optional parameters + p = buildin_func[i].arg; + while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'r' || *p == 'l' ) ++p; + while( *p == '?' ) ++p; + if( *p == '*' ) ++p; + if( *p != 0){ + ShowWarning("add_buildin_func: ignoring function \"%s\" with invalid arg \"%s\".\n", buildin_func[i].name, buildin_func[i].arg); + } else if( *skip_word(buildin_func[i].name) != 0 ){ + ShowWarning("add_buildin_func: ignoring function with invalid name \"%s\" (must be a word).\n", buildin_func[i].name); + } else { + n = add_str(buildin_func[i].name); + str_data[n].type = C_FUNC; + str_data[n].val = i; + str_data[n].func = buildin_func[i].func; if (!strcmp(buildin_func[i].name, "set")) buildin_set_ref = n; else if (!strcmp(buildin_func[i].name, "callsub")) buildin_callsub_ref = n; else if (!strcmp(buildin_func[i].name, "callfunc")) buildin_callfunc_ref = n; - else if (!strcmp(buildin_func[i].name, "getelementofarray")) buildin_getelementofarray_ref = n; - } - } + else if( !strcmp(buildin_func[i].name, "getelementofarray") ) buildin_getelementofarray_ref = n; + } + } } /// Retrieves the value of a constant. -bool script_get_constant(const char *name, int *value) +bool script_get_constant(const char* name, int* value) { - int n = search_str(name); + int n = search_str(name); - if (n == -1 || str_data[n].type != C_INT) { - // not found or not a constant - return false; - } - value[0] = str_data[n].val; + if( n == -1 || str_data[n].type != C_INT ) + {// not found or not a constant + return false; + } + value[0] = str_data[n].val; - return true; + return true; } /// Creates new constant or parameter with given value. -void script_set_constant(const char *name, int value, bool isparameter) -{ - int n = add_str(name); - - if (str_data[n].type == C_NOP) { - // new - str_data[n].type = isparameter ? C_PARAM : C_INT; - str_data[n].val = value; - } else if (str_data[n].type == C_PARAM || str_data[n].type == C_INT) { - // existing parameter or constant - ShowError("script_set_constant: Attempted to overwrite existing %s '%s' (old value=%d, new value=%d).\n", (str_data[n].type == C_PARAM) ? "parameter" : "constant", name, str_data[n].val, value); - } else { - // existing name - ShowError("script_set_constant: Invalid name for %s '%s' (already defined as %s).\n", isparameter ? "parameter" : "constant", name, script_op2name(str_data[n].type)); - } +void script_set_constant(const char* name, int value, bool isparameter) +{ + int n = add_str(name); + + if( str_data[n].type == C_NOP ) + {// new + str_data[n].type = isparameter ? C_PARAM : C_INT; + str_data[n].val = value; + } + else if( str_data[n].type == C_PARAM || str_data[n].type == C_INT ) + {// existing parameter or constant + ShowError("script_set_constant: Attempted to overwrite existing %s '%s' (old value=%d, new value=%d).\n", ( str_data[n].type == C_PARAM ) ? "parameter" : "constant", name, str_data[n].val, value); + } + else + {// existing name + ShowError("script_set_constant: Invalid name for %s '%s' (already defined as %s).\n", isparameter ? "parameter" : "constant", name, script_op2name(str_data[n].type)); + } } /*========================================== @@ -2175,615 +2200,647 @@ void script_set_constant(const char *name, int value, bool isparameter) *------------------------------------------*/ static void read_constdb(void) { - FILE *fp; - char line[1024],name[1024],val[1024]; - int type; - - sprintf(line, "%s/const.txt", db_path); - fp=fopen(line, "r"); - if (fp==NULL) { - ShowError("can't read %s\n", line); - return ; - } - while (fgets(line, sizeof(line), fp)) { - if (line[0]=='/' && line[1]=='/') - continue; - type=0; - if (sscanf(line,"%[A-Za-z0-9_],%[-0-9xXA-Fa-f],%d",name,val,&type)>=2 || - sscanf(line,"%[A-Za-z0-9_] %[-0-9xXA-Fa-f] %d",name,val,&type)>=2) { - script_set_constant(name, (int)strtol(val, NULL, 0), (bool)type); - } - } - fclose(fp); + FILE *fp; + char line[1024],name[1024],val[1024]; + int type; + + sprintf(line, "%s/const.txt", db_path); + fp=fopen(line, "r"); + if(fp==NULL){ + ShowError("can't read %s\n", line); + return ; + } + while(fgets(line, sizeof(line), fp)) + { + if(line[0]=='/' && line[1]=='/') + continue; + type=0; + if(sscanf(line,"%[A-Za-z0-9_],%[-0-9xXA-Fa-f],%d",name,val,&type)>=2 || + sscanf(line,"%[A-Za-z0-9_] %[-0-9xXA-Fa-f] %d",name,val,&type)>=2){ + script_set_constant(name, (int)strtol(val, NULL, 0), (bool)type); + } + } + fclose(fp); } /*========================================== * Display emplacement line of script *------------------------------------------*/ -static const char *script_print_line(StringBuf *buf, const char *p, const char *mark, int line) -{ - int i; - if (p == NULL || !p[0]) return NULL; - if (line < 0) - StringBuf_Printf(buf, "*% 5d : ", -line); - else - StringBuf_Printf(buf, " % 5d : ", line); - for (i=0; p[i] && p[i] != '\n'; i++) { - if (p + i != mark) - StringBuf_Printf(buf, "%c", p[i]); - else - StringBuf_Printf(buf, "\'%c\'", p[i]); - } - StringBuf_AppendStr(buf, "\n"); - return p+i+(p[i] == '\n' ? 1 : 0); -} - -void script_error(const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos) -{ - // Find the line where the error occurred - int j; - int line = start_line; - const char *p; - const char *linestart[5] = { NULL, NULL, NULL, NULL, NULL }; - StringBuf buf; - - for (p=src; p && *p; line++) { - const char *lineend=strchr(p,'\n'); - if (lineend==NULL || error_pos<lineend) { - break; - } - for (j = 0; j < 4; j++) { - linestart[j] = linestart[j+1]; - } - linestart[4] = p; - p=lineend+1; - } - - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "\a\n"); - StringBuf_Printf(&buf, "script error on %s line %d\n", file, line); - StringBuf_Printf(&buf, " %s\n", error_msg); - for (j = 0; j < 5; j++) { - script_print_line(&buf, linestart[j], NULL, line + j - 5); - } - p = script_print_line(&buf, p, error_pos, -line); - for (j = 0; j < 5; j++) { - p = script_print_line(&buf, p, NULL, line + j + 1); - } - ShowError("%s", StringBuf_Value(&buf)); - StringBuf_Destroy(&buf); +static const char* script_print_line(StringBuf* buf, const char* p, const char* mark, int line) +{ + int i; + if( p == NULL || !p[0] ) return NULL; + if( line < 0 ) + StringBuf_Printf(buf, "*% 5d : ", -line); + else + StringBuf_Printf(buf, " % 5d : ", line); + for(i=0;p[i] && p[i] != '\n';i++){ + if(p + i != mark) + StringBuf_Printf(buf, "%c", p[i]); + else + StringBuf_Printf(buf, "\'%c\'", p[i]); + } + StringBuf_AppendStr(buf, "\n"); + return p+i+(p[i] == '\n' ? 1 : 0); +} + +void script_error(const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) +{ + // Find the line where the error occurred + int j; + int line = start_line; + const char *p; + const char *linestart[5] = { NULL, NULL, NULL, NULL, NULL }; + StringBuf buf; + + for(p=src;p && *p;line++){ + const char *lineend=strchr(p,'\n'); + if(lineend==NULL || error_pos<lineend){ + break; + } + for( j = 0; j < 4; j++ ) { + linestart[j] = linestart[j+1]; + } + linestart[4] = p; + p=lineend+1; + } + + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, "\a\n"); + StringBuf_Printf(&buf, "script error on %s line %d\n", file, line); + StringBuf_Printf(&buf, " %s\n", error_msg); + for(j = 0; j < 5; j++ ) { + script_print_line(&buf, linestart[j], NULL, line + j - 5); + } + p = script_print_line(&buf, p, error_pos, -line); + for(j = 0; j < 5; j++) { + p = script_print_line(&buf, p, NULL, line + j + 1 ); + } + ShowError("%s", StringBuf_Value(&buf)); + StringBuf_Destroy(&buf); } /*========================================== * Analysis of the script *------------------------------------------*/ -struct script_code *parse_script(const char *src,const char *file,int line,int options) { - const char *p,*tmpp; - int i; - struct script_code *code = NULL; - static int first=1; - char end; - bool unresolved_names = false; - - if (src == NULL) - return NULL;// empty script - - memset(&syntax,0,sizeof(syntax)); - if (first) { - add_buildin_func(); - read_constdb(); - first=0; - } - - script_buf=(unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE *sizeof(unsigned char)); - script_pos=0; - script_size=SCRIPT_BLOCK_SIZE; - parse_nextline(true, NULL); - - // who called parse_script is responsible for clearing the database after using it, but just in case... lets clear it here - if (options &SCRIPT_USE_LABEL_DB) - db_clear(scriptlabel_db); - parse_options = options; - - if (setjmp(error_jump) != 0) { - //Restore program state when script has problems. [from jA] - int i; - const int size = ARRAYLENGTH(syntax.curly); - if (error_report) - script_error(src,file,line,error_msg,error_pos); - aFree(error_msg); - aFree(script_buf); - script_pos = 0; - script_size = 0; - script_buf = NULL; - for (i=LABEL_START; i<str_num; i++) - if (str_data[i].type == C_NOP) str_data[i].type = C_NAME; - for (i=0; i<size; i++) - linkdb_final(&syntax.curly[i].case_label); - return NULL; - } - - parse_syntax_for_flag=0; - p=src; - p=skip_space(p); - if (options &SCRIPT_IGNORE_EXTERNAL_BRACKETS) { - // does not require brackets around the script - if (*p == '\0' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT)) { - // empty script and can return NULL - aFree(script_buf); - script_pos = 0; - script_size = 0; - script_buf = NULL; - return NULL; - } - end = '\0'; - } else { - // requires brackets around the script - if (*p != '{') - disp_error_message("not found '{'",p); - p = skip_space(p+1); - if (*p == '}' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT)) { - // empty script and can return NULL - aFree(script_buf); - script_pos = 0; - script_size = 0; - script_buf = NULL; - return NULL; - } - end = '}'; - } - - // clear references of labels, variables and internal functions - for (i=LABEL_START; i<str_num; i++) { - if ( - str_data[i].type==C_POS || str_data[i].type==C_NAME || - str_data[i].type==C_USERFUNC || str_data[i].type == C_USERFUNC_POS - ) { - str_data[i].type=C_NOP; - str_data[i].backpatch=-1; - str_data[i].label=-1; - } - } - - while (syntax.curly_count != 0 || *p != end) { - if (*p == '\0') - disp_error_message("unexpected end of script",p); - // Special handling only label - tmpp=skip_space(skip_word(p)); - if (*tmpp==':' && !(!strncasecmp(p,"default:",8) && p + 7 == tmpp)) { - i=add_word(p); - set_label(i,script_pos,p); - if (parse_options&SCRIPT_USE_LABEL_DB) - strdb_iput(scriptlabel_db, get_str(i), script_pos); - p=tmpp+1; - p=skip_space(p); - continue; - } - - // All other lumped - p=parse_line(p); - p=skip_space(p); - - parse_nextline(false, p); - } - - add_scriptc(C_NOP); - - // trim code to size - script_size = script_pos; - RECREATE(script_buf,unsigned char,script_pos); - - // default unknown references to variables - for (i=LABEL_START; i<str_num; i++) { - if (str_data[i].type==C_NOP) { - int j,next; - str_data[i].type=C_NAME; - str_data[i].label=i; - for (j=str_data[i].backpatch; j>=0 && j!=0x00ffffff;) { - next=GETVALUE(script_buf,j); - SETVALUE(script_buf,j,i); - j=next; - } - } else if (str_data[i].type == C_USERFUNC) { - // 'function name;' without follow-up code - ShowError("parse_script: function '%s' declared but not defined.\n", str_buf+str_data[i].str); - unresolved_names = true; - } - } - - if (unresolved_names) { - disp_error_message("parse_script: unresolved function references", p); - } +struct script_code* parse_script(const char *src,const char *file,int line,int options) +{ + const char *p,*tmpp; + int i; + struct script_code* code = NULL; + static int first=1; + char end; + bool unresolved_names = false; + + if( src == NULL ) + return NULL;// empty script + + memset(&syntax,0,sizeof(syntax)); + if(first){ + add_buildin_func(); + read_constdb(); + first=0; + } + + script_buf=(unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char)); + script_pos=0; + script_size=SCRIPT_BLOCK_SIZE; + parse_nextline(true, NULL); + + // who called parse_script is responsible for clearing the database after using it, but just in case... lets clear it here + if( options&SCRIPT_USE_LABEL_DB ) + db_clear(scriptlabel_db); + parse_options = options; + + if( setjmp( error_jump ) != 0 ) { + //Restore program state when script has problems. [from jA] + int i; + const int size = ARRAYLENGTH(syntax.curly); + if( error_report ) + script_error(src,file,line,error_msg,error_pos); + aFree( error_msg ); + aFree( script_buf ); + script_pos = 0; + script_size = 0; + script_buf = NULL; + for(i=LABEL_START;i<str_num;i++) + if(str_data[i].type == C_NOP) str_data[i].type = C_NAME; + for(i=0; i<size; i++) + linkdb_final(&syntax.curly[i].case_label); + return NULL; + } + + parse_syntax_for_flag=0; + p=src; + p=skip_space(p); + if( options&SCRIPT_IGNORE_EXTERNAL_BRACKETS ) + {// does not require brackets around the script + if( *p == '\0' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) ) + {// empty script and can return NULL + aFree( script_buf ); + script_pos = 0; + script_size = 0; + script_buf = NULL; + return NULL; + } + end = '\0'; + } + else + {// requires brackets around the script + if( *p != '{' ) + disp_error_message("not found '{'",p); + p = skip_space(p+1); + if( *p == '}' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) ) + {// empty script and can return NULL + aFree( script_buf ); + script_pos = 0; + script_size = 0; + script_buf = NULL; + return NULL; + } + end = '}'; + } + + // clear references of labels, variables and internal functions + for(i=LABEL_START;i<str_num;i++){ + if( + str_data[i].type==C_POS || str_data[i].type==C_NAME || + str_data[i].type==C_USERFUNC || str_data[i].type == C_USERFUNC_POS + ){ + str_data[i].type=C_NOP; + str_data[i].backpatch=-1; + str_data[i].label=-1; + } + } + + while( syntax.curly_count != 0 || *p != end ) + { + if( *p == '\0' ) + disp_error_message("unexpected end of script",p); + // Special handling only label + tmpp=skip_space(skip_word(p)); + if(*tmpp==':' && !(!strncasecmp(p,"default:",8) && p + 7 == tmpp)){ + i=add_word(p); + set_label(i,script_pos,p); + if( parse_options&SCRIPT_USE_LABEL_DB ) + strdb_iput(scriptlabel_db, get_str(i), script_pos); + p=tmpp+1; + p=skip_space(p); + continue; + } + + // All other lumped + p=parse_line(p); + p=skip_space(p); + + parse_nextline(false, p); + } + + add_scriptc(C_NOP); + + // trim code to size + script_size = script_pos; + RECREATE(script_buf,unsigned char,script_pos); + + // default unknown references to variables + for(i=LABEL_START;i<str_num;i++){ + if(str_data[i].type==C_NOP){ + int j,next; + str_data[i].type=C_NAME; + str_data[i].label=i; + for(j=str_data[i].backpatch;j>=0 && j!=0x00ffffff;){ + next=GETVALUE(script_buf,j); + SETVALUE(script_buf,j,i); + j=next; + } + } + else if( str_data[i].type == C_USERFUNC ) + {// 'function name;' without follow-up code + ShowError("parse_script: function '%s' declared but not defined.\n", str_buf+str_data[i].str); + unresolved_names = true; + } + } + + if( unresolved_names ) + { + disp_error_message("parse_script: unresolved function references", p); + } #ifdef DEBUG_DISP - for (i=0; i<script_pos; i++) { - if ((i&15)==0) ShowMessage("%04x : ",i); - ShowMessage("%02x ",script_buf[i]); - if ((i&15)==15) ShowMessage("\n"); - } - ShowMessage("\n"); + for(i=0;i<script_pos;i++){ + if((i&15)==0) ShowMessage("%04x : ",i); + ShowMessage("%02x ",script_buf[i]); + if((i&15)==15) ShowMessage("\n"); + } + ShowMessage("\n"); #endif #ifdef DEBUG_DISASM - { - int i = 0,j; - while (i < script_pos) { - c_op op = get_com(script_buf,&i); - - ShowMessage("%06x %s", i, script_op2name(op)); - j = i; - switch (op) { - case C_INT: - ShowMessage(" %d", get_num(script_buf,&i)); - break; - case C_POS: - ShowMessage(" 0x%06x", *(int *)(script_buf+i)&0xffffff); - i += 3; - break; - case C_NAME: - j = (*(int *)(script_buf+i)&0xffffff); - ShowMessage(" %s", (j == 0xffffff) ? "?? unknown ??" : get_str(j)); - i += 3; - break; - case C_STR: - j = strlen(script_buf + i); - ShowMessage(" %s", script_buf + i); - i += j+1; - break; - } - ShowMessage(CL_CLL"\n"); - } - } + { + int i = 0,j; + while(i < script_pos) { + c_op op = get_com(script_buf,&i); + + ShowMessage("%06x %s", i, script_op2name(op)); + j = i; + switch(op) { + case C_INT: + ShowMessage(" %d", get_num(script_buf,&i)); + break; + case C_POS: + ShowMessage(" 0x%06x", *(int*)(script_buf+i)&0xffffff); + i += 3; + break; + case C_NAME: + j = (*(int*)(script_buf+i)&0xffffff); + ShowMessage(" %s", ( j == 0xffffff ) ? "?? unknown ??" : get_str(j)); + i += 3; + break; + case C_STR: + j = strlen(script_buf + i); + ShowMessage(" %s", script_buf + i); + i += j+1; + break; + } + ShowMessage(CL_CLL"\n"); + } + } #endif - CREATE(code,struct script_code,1); - code->script_buf = script_buf; - code->script_size = script_size; - code->script_vars = idb_alloc(DB_OPT_RELEASE_DATA); - return code; + CREATE(code,struct script_code,1); + code->script_buf = script_buf; + code->script_size = script_size; + code->script_vars = idb_alloc(DB_OPT_RELEASE_DATA); + return code; } /// Returns the player attached to this script, identified by the rid. /// If there is no player attached, the script is terminated. TBL_PC *script_rid2sd(struct script_state *st) { - TBL_PC *sd=map_id2sd(st->rid); - if (!sd) { - ShowError("script_rid2sd: fatal error ! player not attached!\n"); - script_reportfunc(st); - script_reportsrc(st); - st->state = END; - } - return sd; + TBL_PC *sd=map_id2sd(st->rid); + if(!sd){ + ShowError("script_rid2sd: fatal error ! player not attached!\n"); + script_reportfunc(st); + script_reportsrc(st); + st->state = END; + } + return sd; } /// Dereferences a variable/constant, replacing it with a copy of the value. /// /// @param st Script state /// @param data Variable/constant -void get_val(struct script_state *st, struct script_data *data) -{ - const char *name; - char prefix; - char postfix; - TBL_PC *sd = NULL; - - if (!data_isreference(data)) - return;// not a variable/constant - - name = reference_getname(data); - prefix = name[0]; - postfix = name[strlen(name) - 1]; - - //##TODO use reference_tovariable(data) when it's confirmed that it works [FlavioJS] - if (!reference_toconstant(data) && not_server_variable(prefix)) { - sd = script_rid2sd(st); - if (sd == NULL) { - // needs player attached - if (postfix == '$') { - // string variable - ShowWarning("script:get_val: cannot access player variable '%s', defaulting to \"\"\n", name); - data->type = C_CONSTSTR; - data->u.str = ""; - } else { - // integer variable - ShowWarning("script:get_val: cannot access player variable '%s', defaulting to 0\n", name); - data->type = C_INT; - data->u.num = 0; - } - return; - } - } - - if (postfix == '$') { - // string variable - - switch (prefix) { - case '@': - data->u.str = pc_readregstr(sd, data->u.num); - break; - case '$': - data->u.str = mapreg_readregstr(data->u.num); - break; - case '#': - if (name[1] == '#') - data->u.str = pc_readaccountreg2str(sd, name);// global - else - data->u.str = pc_readaccountregstr(sd, name);// local - break; - case '.': { - struct DBMap *n = - data->ref ? *data->ref: - name[1] == '@' ? st->stack->var_function:// instance/scope variable - st->script->script_vars;// npc variable - if (n) - data->u.str = (char *)idb_get(n,reference_getuid(data)); - else - data->u.str = NULL; - } - break; - case '\'': - if (st->instance_id) { - data->u.str = (char *)idb_get(instance[st->instance_id].vars,reference_getuid(data)); - } else { - ShowWarning("script:get_val: cannot access instance variable '%s', defaulting to \"\"\n", name); - data->u.str = NULL; - } - break; - default: - data->u.str = pc_readglobalreg_str(sd, name); - break; - } - - if (data->u.str == NULL || data->u.str[0] == '\0') { - // empty string - data->type = C_CONSTSTR; - data->u.str = ""; - } else { - // duplicate string - data->type = C_STR; - data->u.str = aStrdup(data->u.str); - } - - } else { - // integer variable - - data->type = C_INT; - - if (reference_toconstant(data)) { - data->u.num = reference_getconstant(data); - } else if (reference_toparam(data)) { - data->u.num = pc_readparam(sd, reference_getparamtype(data)); - } else - switch (prefix) { - case '@': - data->u.num = pc_readreg(sd, data->u.num); - break; - case '$': - data->u.num = mapreg_readreg(data->u.num); - break; - case '#': - if (name[1] == '#') - data->u.num = pc_readaccountreg2(sd, name);// global - else - data->u.num = pc_readaccountreg(sd, name);// local - break; - case '.': { - struct DBMap *n = - data->ref ? *data->ref: - name[1] == '@' ? st->stack->var_function:// instance/scope variable - st->script->script_vars;// npc variable - if (n) - data->u.num = (int)idb_iget(n,reference_getuid(data)); - else - data->u.num = 0; - } - break; - case '\'': - if (st->instance_id) - data->u.num = (int)idb_iget(instance[st->instance_id].vars,reference_getuid(data)); - else { - ShowWarning("script:get_val: cannot access instance variable '%s', defaulting to 0\n", name); - data->u.num = 0; - } - break; - default: - data->u.num = pc_readglobalreg(sd, name); - break; - } - - } - - return; -} - -struct script_data *push_val2(struct script_stack *stack, enum c_op type, int val, struct DBMap **ref); +void get_val(struct script_state* st, struct script_data* data) +{ + const char* name; + char prefix; + char postfix; + TBL_PC* sd = NULL; + + if( !data_isreference(data) ) + return;// not a variable/constant + + name = reference_getname(data); + prefix = name[0]; + postfix = name[strlen(name) - 1]; + + //##TODO use reference_tovariable(data) when it's confirmed that it works [FlavioJS] + if( !reference_toconstant(data) && not_server_variable(prefix) ) + { + sd = script_rid2sd(st); + if( sd == NULL ) + {// needs player attached + if( postfix == '$' ) + {// string variable + ShowWarning("script:get_val: cannot access player variable '%s', defaulting to \"\"\n", name); + data->type = C_CONSTSTR; + data->u.str = ""; + } + else + {// integer variable + ShowWarning("script:get_val: cannot access player variable '%s', defaulting to 0\n", name); + data->type = C_INT; + data->u.num = 0; + } + return; + } + } + + if( postfix == '$' ) + {// string variable + + switch( prefix ) + { + case '@': + data->u.str = pc_readregstr(sd, data->u.num); + break; + case '$': + data->u.str = mapreg_readregstr(data->u.num); + break; + case '#': + if( name[1] == '#' ) + data->u.str = pc_readaccountreg2str(sd, name);// global + else + data->u.str = pc_readaccountregstr(sd, name);// local + break; + case '.': + { + struct DBMap* n = + data->ref ? *data->ref: + name[1] == '@' ? st->stack->var_function:// instance/scope variable + st->script->script_vars;// npc variable + if( n ) + data->u.str = (char*)idb_get(n,reference_getuid(data)); + else + data->u.str = NULL; + } + break; + case '\'': + if (st->instance_id) { + data->u.str = (char*)idb_get(instance[st->instance_id].vars,reference_getuid(data)); + } else { + ShowWarning("script:get_val: cannot access instance variable '%s', defaulting to \"\"\n", name); + data->u.str = NULL; + } + break; + default: + data->u.str = pc_readglobalreg_str(sd, name); + break; + } + + if( data->u.str == NULL || data->u.str[0] == '\0' ) + {// empty string + data->type = C_CONSTSTR; + data->u.str = ""; + } + else + {// duplicate string + data->type = C_STR; + data->u.str = aStrdup(data->u.str); + } + + } + else + {// integer variable + + data->type = C_INT; + + if( reference_toconstant(data) ) + { + data->u.num = reference_getconstant(data); + } + else if( reference_toparam(data) ) + { + data->u.num = pc_readparam(sd, reference_getparamtype(data)); + } + else + switch( prefix ) + { + case '@': + data->u.num = pc_readreg(sd, data->u.num); + break; + case '$': + data->u.num = mapreg_readreg(data->u.num); + break; + case '#': + if( name[1] == '#' ) + data->u.num = pc_readaccountreg2(sd, name);// global + else + data->u.num = pc_readaccountreg(sd, name);// local + break; + case '.': + { + struct DBMap* n = + data->ref ? *data->ref: + name[1] == '@' ? st->stack->var_function:// instance/scope variable + st->script->script_vars;// npc variable + if( n ) + data->u.num = (int)idb_iget(n,reference_getuid(data)); + else + data->u.num = 0; + } + break; + case '\'': + if( st->instance_id ) + data->u.num = (int)idb_iget(instance[st->instance_id].vars,reference_getuid(data)); + else { + ShowWarning("script:get_val: cannot access instance variable '%s', defaulting to 0\n", name); + data->u.num = 0; + } + break; + default: + data->u.num = pc_readglobalreg(sd, name); + break; + } + + } + + return; +} + +struct script_data* push_val2(struct script_stack* stack, enum c_op type, int val, struct DBMap** ref); /// Retrieves the value of a reference identified by uid (variable, constant, param) /// The value is left in the top of the stack and needs to be removed manually. -void *get_val2(struct script_state *st, int uid, struct DBMap **ref) +void* get_val2(struct script_state* st, int uid, struct DBMap** ref) { - struct script_data *data; - push_val2(st->stack, C_NAME, uid, ref); - data = script_getdatatop(st, -1); - get_val(st, data); - return (data->type == C_INT ? (void *)__64BPRTSIZE(data->u.num) : (void *)__64BPRTSIZE(data->u.str)); + struct script_data* data; + push_val2(st->stack, C_NAME, uid, ref); + data = script_getdatatop(st, -1); + get_val(st, data); + return (data->type == C_INT ? (void*)__64BPRTSIZE(data->u.num) : (void*)__64BPRTSIZE(data->u.str)); } /*========================================== * Stores the value of a script variable * Return value is 0 on fail, 1 on success. *------------------------------------------*/ -static int set_reg(struct script_state *st, TBL_PC *sd, int num, const char *name, const void *value, struct DBMap **ref) -{ - char prefix = name[0]; - - if (is_string_variable(name)) { - // string variable - const char *str = (const char *)value; - switch (prefix) { - case '@': - return pc_setregstr(sd, num, str); - case '$': - return mapreg_setregstr(num, str); - case '#': - return (name[1] == '#') ? - pc_setaccountreg2str(sd, name, str) : - pc_setaccountregstr(sd, name, str); - case '.': { - struct DBMap *n; - n = (ref) ? *ref : (name[1] == '@') ? st->stack->var_function : st->script->script_vars; - if (n) { - idb_remove(n, num); - if (str[0]) idb_put(n, num, aStrdup(str)); - } - } - return 1; - case '\'': - if (st->instance_id) { - idb_remove(instance[st->instance_id].vars, num); - if (str[0]) idb_put(instance[st->instance_id].vars, num, aStrdup(str)); - } - return 1; - default: - return pc_setglobalreg_str(sd, name, str); - } - } else { - // integer variable - int val = (int)__64BPRTSIZE(value); - if (str_data[num&0x00ffffff].type == C_PARAM) { - if (pc_setparam(sd, str_data[num&0x00ffffff].val, val) == 0) { - if (st != NULL) { - ShowError("script:set_reg: failed to set param '%s' to %d.\n", name, val); - script_reportsrc(st); - st->state = END; - } - return 0; - } - return 1; - } - - switch (prefix) { - case '@': - return pc_setreg(sd, num, val); - case '$': - return mapreg_setreg(num, val); - case '#': - return (name[1] == '#') ? - pc_setaccountreg2(sd, name, val) : - pc_setaccountreg(sd, name, val); - case '.': { - struct DBMap *n; - n = (ref) ? *ref : (name[1] == '@') ? st->stack->var_function : st->script->script_vars; - if (n) { - idb_remove(n, num); - if (val != 0) - idb_iput(n, num, val); - } - } - return 1; - case '\'': - if (st->instance_id) { - idb_remove(instance[st->instance_id].vars, num); - if (val != 0) - idb_iput(instance[st->instance_id].vars, num, val); - } - return 1; - default: - return pc_setglobalreg(sd, name, val); - } - } -} - -int set_var(TBL_PC *sd, char *name, void *val) +static int set_reg(struct script_state* st, TBL_PC* sd, int num, const char* name, const void* value, struct DBMap** ref) +{ + char prefix = name[0]; + + if( is_string_variable(name) ) + {// string variable + const char* str = (const char*)value; + switch (prefix) { + case '@': + return pc_setregstr(sd, num, str); + case '$': + return mapreg_setregstr(num, str); + case '#': + return (name[1] == '#') ? + pc_setaccountreg2str(sd, name, str) : + pc_setaccountregstr(sd, name, str); + case '.': + { + struct DBMap* n; + n = (ref) ? *ref : (name[1] == '@') ? st->stack->var_function : st->script->script_vars; + if( n ) { + idb_remove(n, num); + if (str[0]) idb_put(n, num, aStrdup(str)); + } + } + return 1; + case '\'': + if( st->instance_id ) { + idb_remove(instance[st->instance_id].vars, num); + if( str[0] ) idb_put(instance[st->instance_id].vars, num, aStrdup(str)); + } + return 1; + default: + return pc_setglobalreg_str(sd, name, str); + } + } + else + {// integer variable + int val = (int)__64BPRTSIZE(value); + if(str_data[num&0x00ffffff].type == C_PARAM) + { + if( pc_setparam(sd, str_data[num&0x00ffffff].val, val) == 0 ) + { + if( st != NULL ) + { + ShowError("script:set_reg: failed to set param '%s' to %d.\n", name, val); + script_reportsrc(st); + st->state = END; + } + return 0; + } + return 1; + } + + switch (prefix) { + case '@': + return pc_setreg(sd, num, val); + case '$': + return mapreg_setreg(num, val); + case '#': + return (name[1] == '#') ? + pc_setaccountreg2(sd, name, val) : + pc_setaccountreg(sd, name, val); + case '.': + { + struct DBMap* n; + n = (ref) ? *ref : (name[1] == '@') ? st->stack->var_function : st->script->script_vars; + if( n ) { + idb_remove(n, num); + if( val != 0 ) + idb_iput(n, num, val); + } + } + return 1; + case '\'': + if( st->instance_id ) { + idb_remove(instance[st->instance_id].vars, num); + if( val != 0 ) + idb_iput(instance[st->instance_id].vars, num, val); + } + return 1; + default: + return pc_setglobalreg(sd, name, val); + } + } +} + +int set_var(TBL_PC* sd, char* name, void* val) { return set_reg(NULL, sd, reference_uid(add_str(name),0), name, val, NULL); } void setd_sub(struct script_state *st, TBL_PC *sd, const char *varname, int elem, void *value, struct DBMap **ref) { - set_reg(st, sd, reference_uid(add_str(varname),elem), varname, value, ref); + set_reg(st, sd, reference_uid(add_str(varname),elem), varname, value, ref); } /// Converts the data to a string -const char *conv_str(struct script_state *st, struct script_data *data) -{ - char *p; - - get_val(st, data); - if (data_isstring(data)) { - // nothing to convert - } else if (data_isint(data)) { - // int -> string - CREATE(p, char, ITEM_NAME_LENGTH); - snprintf(p, ITEM_NAME_LENGTH, "%d", data->u.num); - p[ITEM_NAME_LENGTH-1] = '\0'; - data->type = C_STR; - data->u.str = p; - } else if (data_isreference(data)) { - // reference -> string - //##TODO when does this happen (check get_val) [FlavioJS] - data->type = C_CONSTSTR; - data->u.str = reference_getname(data); - } else { - // unsupported data type - ShowError("script:conv_str: cannot convert to string, defaulting to \"\"\n"); - script_reportdata(data); - script_reportsrc(st); - data->type = C_CONSTSTR; - data->u.str = ""; - } - return data->u.str; +const char* conv_str(struct script_state* st, struct script_data* data) +{ + char* p; + + get_val(st, data); + if( data_isstring(data) ) + {// nothing to convert + } + else if( data_isint(data) ) + {// int -> string + CREATE(p, char, ITEM_NAME_LENGTH); + snprintf(p, ITEM_NAME_LENGTH, "%d", data->u.num); + p[ITEM_NAME_LENGTH-1] = '\0'; + data->type = C_STR; + data->u.str = p; + } + else if( data_isreference(data) ) + {// reference -> string + //##TODO when does this happen (check get_val) [FlavioJS] + data->type = C_CONSTSTR; + data->u.str = reference_getname(data); + } + else + {// unsupported data type + ShowError("script:conv_str: cannot convert to string, defaulting to \"\"\n"); + script_reportdata(data); + script_reportsrc(st); + data->type = C_CONSTSTR; + data->u.str = ""; + } + return data->u.str; } /// Converts the data to an int -int conv_num(struct script_state *st, struct script_data *data) -{ - char *p; - long num; - - get_val(st, data); - if (data_isint(data)) { - // nothing to convert - } else if (data_isstring(data)) { - // string -> int - // the result does not overflow or underflow, it is capped instead - // ex: 999999999999 is capped to INT_MAX (2147483647) - p = data->u.str; - errno = 0; - num = strtol(data->u.str, NULL, 10);// change radix to 0 to support octal numbers "o377" and hex numbers "0xFF" - if (errno == ERANGE +int conv_num(struct script_state* st, struct script_data* data) +{ + char* p; + long num; + + get_val(st, data); + if( data_isint(data) ) + {// nothing to convert + } + else if( data_isstring(data) ) + {// string -> int + // the result does not overflow or underflow, it is capped instead + // ex: 999999999999 is capped to INT_MAX (2147483647) + p = data->u.str; + errno = 0; + num = strtol(data->u.str, NULL, 10);// change radix to 0 to support octal numbers "o377" and hex numbers "0xFF" + if( errno == ERANGE #if LONG_MAX > INT_MAX - || num < INT_MIN || num > INT_MAX + || num < INT_MIN || num > INT_MAX #endif - ) { - if (num <= INT_MIN) { - num = INT_MIN; - ShowError("script:conv_num: underflow detected, capping to %ld\n", num); - } else { //if( num >= INT_MAX ) - num = INT_MAX; - ShowError("script:conv_num: overflow detected, capping to %ld\n", num); - } - script_reportdata(data); - script_reportsrc(st); - } - if (data->type == C_STR) - aFree(p); - data->type = C_INT; - data->u.num = (int)num; - } + ) + { + if( num <= INT_MIN ) + { + num = INT_MIN; + ShowError("script:conv_num: underflow detected, capping to %ld\n", num); + } + else//if( num >= INT_MAX ) + { + num = INT_MAX; + ShowError("script:conv_num: overflow detected, capping to %ld\n", num); + } + script_reportdata(data); + script_reportsrc(st); + } + if( data->type == C_STR ) + aFree(p); + data->type = C_INT; + data->u.num = (int)num; + } #if 0 - // FIXME this function is being used to retrieve the position of labels and - // probably other stuff [FlavioJS] - else { - // unsupported data type - ShowError("script:conv_num: cannot convert to number, defaulting to 0\n"); - script_reportdata(data); - script_reportsrc(st); - data->type = C_INT; - data->u.num = 0; - } + // FIXME this function is being used to retrieve the position of labels and + // probably other stuff [FlavioJS] + else + {// unsupported data type + ShowError("script:conv_num: cannot convert to number, defaulting to 0\n"); + script_reportdata(data); + script_reportsrc(st); + data->type = C_INT; + data->u.num = 0; + } #endif - return data->u.num; + return data->u.num; } // @@ -2791,118 +2848,126 @@ int conv_num(struct script_state *st, struct script_data *data) // /// Increases the size of the stack -void stack_expand(struct script_stack *stack) +void stack_expand(struct script_stack* stack) { - stack->sp_max += 64; - stack->stack_data = (struct script_data *)aRealloc(stack->stack_data, - stack->sp_max * sizeof(stack->stack_data[0])); - memset(stack->stack_data + (stack->sp_max - 64), 0, - 64 * sizeof(stack->stack_data[0])); + stack->sp_max += 64; + stack->stack_data = (struct script_data*)aRealloc(stack->stack_data, + stack->sp_max * sizeof(stack->stack_data[0]) ); + memset(stack->stack_data + (stack->sp_max - 64), 0, + 64 * sizeof(stack->stack_data[0]) ); } /// Pushes a value into the stack #define push_val(stack,type,val) push_val2(stack, type, val, NULL) /// Pushes a value into the stack (with reference) -struct script_data *push_val2(struct script_stack *stack, enum c_op type, int val, struct DBMap **ref) { - if (stack->sp >= stack->sp_max) - stack_expand(stack); - stack->stack_data[stack->sp].type = type; - stack->stack_data[stack->sp].u.num = val; - stack->stack_data[stack->sp].ref = ref; - stack->sp++; - return &stack->stack_data[stack->sp-1]; +struct script_data* push_val2(struct script_stack* stack, enum c_op type, int val, struct DBMap** ref) +{ + if( stack->sp >= stack->sp_max ) + stack_expand(stack); + stack->stack_data[stack->sp].type = type; + stack->stack_data[stack->sp].u.num = val; + stack->stack_data[stack->sp].ref = ref; + stack->sp++; + return &stack->stack_data[stack->sp-1]; } /// Pushes a string into the stack -struct script_data *push_str(struct script_stack *stack, enum c_op type, char *str) { - if (stack->sp >= stack->sp_max) - stack_expand(stack); - stack->stack_data[stack->sp].type = type; - stack->stack_data[stack->sp].u.str = str; - stack->stack_data[stack->sp].ref = NULL; - stack->sp++; - return &stack->stack_data[stack->sp-1]; +struct script_data* push_str(struct script_stack* stack, enum c_op type, char* str) +{ + if( stack->sp >= stack->sp_max ) + stack_expand(stack); + stack->stack_data[stack->sp].type = type; + stack->stack_data[stack->sp].u.str = str; + stack->stack_data[stack->sp].ref = NULL; + stack->sp++; + return &stack->stack_data[stack->sp-1]; } /// Pushes a retinfo into the stack -struct script_data *push_retinfo(struct script_stack *stack, struct script_retinfo *ri, DBMap **ref) { - if (stack->sp >= stack->sp_max) - stack_expand(stack); - stack->stack_data[stack->sp].type = C_RETINFO; - stack->stack_data[stack->sp].u.ri = ri; - stack->stack_data[stack->sp].ref = ref; - stack->sp++; - return &stack->stack_data[stack->sp-1]; +struct script_data* push_retinfo(struct script_stack* stack, struct script_retinfo* ri, DBMap **ref) +{ + if( stack->sp >= stack->sp_max ) + stack_expand(stack); + stack->stack_data[stack->sp].type = C_RETINFO; + stack->stack_data[stack->sp].u.ri = ri; + stack->stack_data[stack->sp].ref = ref; + stack->sp++; + return &stack->stack_data[stack->sp-1]; } /// Pushes a copy of the target position into the stack -struct script_data *push_copy(struct script_stack *stack, int pos) { - switch (stack->stack_data[pos].type) { - case C_CONSTSTR: - return push_str(stack, C_CONSTSTR, stack->stack_data[pos].u.str); - break; - case C_STR: - return push_str(stack, C_STR, aStrdup(stack->stack_data[pos].u.str)); - break; - case C_RETINFO: - ShowFatalError("script:push_copy: can't create copies of C_RETINFO. Exiting...\n"); - exit(1); - break; - default: - return push_val2( - stack,stack->stack_data[pos].type, - stack->stack_data[pos].u.num, - stack->stack_data[pos].ref - ); - break; - } +struct script_data* push_copy(struct script_stack* stack, int pos) +{ + switch( stack->stack_data[pos].type ) + { + case C_CONSTSTR: + return push_str(stack, C_CONSTSTR, stack->stack_data[pos].u.str); + break; + case C_STR: + return push_str(stack, C_STR, aStrdup(stack->stack_data[pos].u.str)); + break; + case C_RETINFO: + ShowFatalError("script:push_copy: can't create copies of C_RETINFO. Exiting...\n"); + exit(1); + break; + default: + return push_val2( + stack,stack->stack_data[pos].type, + stack->stack_data[pos].u.num, + stack->stack_data[pos].ref + ); + break; + } } /// Removes the values in indexes [start,end[ from the stack. /// Adjusts all stack pointers. -void pop_stack(struct script_state *st, int start, int end) -{ - struct script_stack *stack = st->stack; - struct script_data *data; - int i; - - if (start < 0) - start = 0; - if (end > stack->sp) - end = stack->sp; - if (start >= end) - return;// nothing to pop - - // free stack elements - for (i = start; i < end; i++) { - data = &stack->stack_data[i]; - if (data->type == C_STR) - aFree(data->u.str); - if (data->type == C_RETINFO) { - struct script_retinfo *ri = data->u.ri; - if (ri->var_function) - script_free_vars(ri->var_function); - if (data->ref) - aFree(data->ref); - aFree(ri); - } - data->type = C_NOP; - } - // move the rest of the elements - if (stack->sp > end) { - memmove(&stack->stack_data[start], &stack->stack_data[end], sizeof(stack->stack_data[0])*(stack->sp - end)); - for (i = start + stack->sp - end; i < stack->sp; ++i) - stack->stack_data[i].type = C_NOP; - } - // adjust stack pointers - if (st->start > end) st->start -= end - start; - else if (st->start > start) st->start = start; - if (st->end > end) st->end -= end - start; - else if (st->end > start) st->end = start; - if (stack->defsp > end) stack->defsp -= end - start; - else if (stack->defsp > start) stack->defsp = start; - stack->sp -= end - start; +void pop_stack(struct script_state* st, int start, int end) +{ + struct script_stack* stack = st->stack; + struct script_data* data; + int i; + + if( start < 0 ) + start = 0; + if( end > stack->sp ) + end = stack->sp; + if( start >= end ) + return;// nothing to pop + + // free stack elements + for( i = start; i < end; i++ ) + { + data = &stack->stack_data[i]; + if( data->type == C_STR ) + aFree(data->u.str); + if( data->type == C_RETINFO ) + { + struct script_retinfo* ri = data->u.ri; + if( ri->var_function ) + script_free_vars(ri->var_function); + if( data->ref ) + aFree(data->ref); + aFree(ri); + } + data->type = C_NOP; + } + // move the rest of the elements + if( stack->sp > end ) + { + memmove(&stack->stack_data[start], &stack->stack_data[end], sizeof(stack->stack_data[0])*(stack->sp - end)); + for( i = start + stack->sp - end; i < stack->sp; ++i ) + stack->stack_data[i].type = C_NOP; + } + // adjust stack pointers + if( st->start > end ) st->start -= end - start; + else if( st->start > start ) st->start = start; + if( st->end > end ) st->end -= end - start; + else if( st->end > start ) st->end = start; + if( stack->defsp > end ) stack->defsp -= end - start; + else if( stack->defsp > start ) stack->defsp = start; + stack->sp -= end - start; } /// @@ -2912,19 +2977,19 @@ void pop_stack(struct script_state *st, int start, int end) /*========================================== * Release script dependent variable, dependent variable of function *------------------------------------------*/ -void script_free_vars(struct DBMap *storage) +void script_free_vars(struct DBMap* storage) { - if (storage) { - // destroy the storage construct containing the variables - db_destroy(storage); - } + if( storage ) + {// destroy the storage construct containing the variables + db_destroy(storage); + } } -void script_free_code(struct script_code *code) +void script_free_code(struct script_code* code) { - script_free_vars(code->script_vars); - aFree(code->script_buf); - aFree(code); + script_free_vars( code->script_vars ); + aFree( code->script_buf ); + aFree( code ); } /// Creates a new script state. @@ -2934,43 +2999,44 @@ void script_free_code(struct script_code *code) /// @param rid Who is running the script (attached player) /// @param oid Where the code is being run (npc 'object') /// @return Script state -struct script_state *script_alloc_state(struct script_code *script, int pos, int rid, int oid) { - struct script_state *st; - CREATE(st, struct script_state, 1); - st->stack = (struct script_stack *)aMalloc(sizeof(struct script_stack)); - st->stack->sp = 0; - st->stack->sp_max = 64; - CREATE(st->stack->stack_data, struct script_data, st->stack->sp_max); - st->stack->defsp = st->stack->sp; - st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA); - st->state = RUN; - st->script = script; - //st->scriptroot = script; - st->pos = pos; - st->rid = rid; - st->oid = oid; - st->sleep.timer = INVALID_TIMER; - return st; +struct script_state* script_alloc_state(struct script_code* script, int pos, int rid, int oid) +{ + struct script_state* st; + CREATE(st, struct script_state, 1); + st->stack = (struct script_stack*)aMalloc(sizeof(struct script_stack)); + st->stack->sp = 0; + st->stack->sp_max = 64; + CREATE(st->stack->stack_data, struct script_data, st->stack->sp_max); + st->stack->defsp = st->stack->sp; + st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA); + st->state = RUN; + st->script = script; + //st->scriptroot = script; + st->pos = pos; + st->rid = rid; + st->oid = oid; + st->sleep.timer = INVALID_TIMER; + return st; } /// Frees a script state. /// /// @param st Script state -void script_free_state(struct script_state *st) -{ - if (st->bk_st) { - // backup was not restored - ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); - } - if (st->sleep.timer != INVALID_TIMER) - delete_timer(st->sleep.timer, run_script_timer); - script_free_vars(st->stack->var_function); - pop_stack(st, 0, st->stack->sp); - aFree(st->stack->stack_data); - aFree(st->stack); - st->stack = NULL; - st->pos = -1; - aFree(st); +void script_free_state(struct script_state* st) +{ + if(st->bk_st) + {// backup was not restored + ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); + } + if( st->sleep.timer != INVALID_TIMER ) + delete_timer(st->sleep.timer, run_script_timer); + script_free_vars(st->stack->var_function); + pop_stack(st, 0, st->stack->sp); + aFree(st->stack->stack_data); + aFree(st->stack); + st->stack = NULL; + st->pos = -1; + aFree(st); } // @@ -2981,16 +3047,16 @@ void script_free_state(struct script_state *st) *------------------------------------------*/ c_op get_com(unsigned char *script,int *pos) { - int i = 0, j = 0; + int i = 0, j = 0; - if (script[*pos]>=0x80) { - return C_INT; - } - while (script[*pos]>=0x40) { - i=script[(*pos)++]<<j; - j+=6; - } - return (c_op)(i+(script[(*pos)++]<<j)); + if(script[*pos]>=0x80){ + return C_INT; + } + while(script[*pos]>=0x40){ + i=script[(*pos)++]<<j; + j+=6; + } + return (c_op)(i+(script[(*pos)++]<<j)); } /*========================================== @@ -2998,57 +3064,57 @@ c_op get_com(unsigned char *script,int *pos) *------------------------------------------*/ int get_num(unsigned char *script,int *pos) { - int i,j; - i=0; - j=0; - while (script[*pos]>=0xc0) { - i+=(script[(*pos)++]&0x7f)<<j; - j+=6; - } - return i+((script[(*pos)++]&0x7f)<<j); + int i,j; + i=0; j=0; + while(script[*pos]>=0xc0){ + i+=(script[(*pos)++]&0x7f)<<j; + j+=6; + } + return i+((script[(*pos)++]&0x7f)<<j); } /*========================================== * Remove the value from the stack *------------------------------------------*/ -int pop_val(struct script_state *st) +int pop_val(struct script_state* st) { - if (st->stack->sp<=0) - return 0; - st->stack->sp--; - get_val(st,&(st->stack->stack_data[st->stack->sp])); - if (st->stack->stack_data[st->stack->sp].type==C_INT) - return st->stack->stack_data[st->stack->sp].u.num; - return 0; + if(st->stack->sp<=0) + return 0; + st->stack->sp--; + get_val(st,&(st->stack->stack_data[st->stack->sp])); + if(st->stack->stack_data[st->stack->sp].type==C_INT) + return st->stack->stack_data[st->stack->sp].u.num; + return 0; } /// Ternary operators /// test ? if_true : if_false -void op_3(struct script_state *st, int op) -{ - struct script_data *data; - int flag = 0; - - data = script_getdatatop(st, -3); - get_val(st, data); - - if (data_isstring(data)) - flag = data->u.str[0];// "" -> false - else if (data_isint(data)) - flag = data->u.num;// 0 -> false - else { - ShowError("script:op_3: invalid data for the ternary operator test\n"); - script_reportdata(data); - script_reportsrc(st); - script_removetop(st, -3, 0); - script_pushnil(st); - return; - } - if (flag) - script_pushcopytop(st, -2); - else - script_pushcopytop(st, -1); - script_removetop(st, -4, -1); +void op_3(struct script_state* st, int op) +{ + struct script_data* data; + int flag = 0; + + data = script_getdatatop(st, -3); + get_val(st, data); + + if( data_isstring(data) ) + flag = data->u.str[0];// "" -> false + else if( data_isint(data) ) + flag = data->u.num;// 0 -> false + else + { + ShowError("script:op_3: invalid data for the ternary operator test\n"); + script_reportdata(data); + script_reportsrc(st); + script_removetop(st, -3, 0); + script_pushnil(st); + return; + } + if( flag ) + script_pushcopytop(st, -2); + else + script_pushcopytop(st, -1); + script_removetop(st, -4, -1); } /// Binary string operators @@ -3059,249 +3125,209 @@ void op_3(struct script_state *st, int op) /// s1 LT s2 -> i /// s1 LE s2 -> i /// s1 ADD s2 -> s -void op_2str(struct script_state *st, int op, const char *s1, const char *s2) -{ - int a = 0; - - switch (op) { - case C_EQ: - a = (strcmp(s1,s2) == 0); - break; - case C_NE: - a = (strcmp(s1,s2) != 0); - break; - case C_GT: - a = (strcmp(s1,s2) > 0); - break; - case C_GE: - a = (strcmp(s1,s2) >= 0); - break; - case C_LT: - a = (strcmp(s1,s2) < 0); - break; - case C_LE: - a = (strcmp(s1,s2) <= 0); - break; - case C_ADD: { - char *buf = (char *)aMalloc((strlen(s1)+strlen(s2)+1)*sizeof(char)); - strcpy(buf, s1); - strcat(buf, s2); - script_pushstr(st, buf); - return; - } - default: - ShowError("script:op2_str: unexpected string operator %s\n", script_op2name(op)); - script_reportsrc(st); - script_pushnil(st); - st->state = END; - return; - } - - script_pushint(st,a); +void op_2str(struct script_state* st, int op, const char* s1, const char* s2) +{ + int a = 0; + + switch(op){ + case C_EQ: a = (strcmp(s1,s2) == 0); break; + case C_NE: a = (strcmp(s1,s2) != 0); break; + case C_GT: a = (strcmp(s1,s2) > 0); break; + case C_GE: a = (strcmp(s1,s2) >= 0); break; + case C_LT: a = (strcmp(s1,s2) < 0); break; + case C_LE: a = (strcmp(s1,s2) <= 0); break; + case C_ADD: + { + char* buf = (char *)aMalloc((strlen(s1)+strlen(s2)+1)*sizeof(char)); + strcpy(buf, s1); + strcat(buf, s2); + script_pushstr(st, buf); + return; + } + default: + ShowError("script:op2_str: unexpected string operator %s\n", script_op2name(op)); + script_reportsrc(st); + script_pushnil(st); + st->state = END; + return; + } + + script_pushint(st,a); } /// Binary number operators /// i OP i -> i -void op_2num(struct script_state *st, int op, int i1, int i2) -{ - int ret; - double ret_double; - - switch (op) { - case C_AND: - ret = i1 & i2; - break; - case C_OR: - ret = i1 | i2; - break; - case C_XOR: - ret = i1 ^ i2; - break; - case C_LAND: - ret = (i1 && i2); - break; - case C_LOR: - ret = (i1 || i2); - break; - case C_EQ: - ret = (i1 == i2); - break; - case C_NE: - ret = (i1 != i2); - break; - case C_GT: - ret = (i1 > i2); - break; - case C_GE: - ret = (i1 >= i2); - break; - case C_LT: - ret = (i1 < i2); - break; - case C_LE: - ret = (i1 <= i2); - break; - case C_R_SHIFT: - ret = i1>>i2; - break; - case C_L_SHIFT: - ret = i1<<i2; - break; - case C_DIV: - case C_MOD: - if (i2 == 0) { - ShowError("script:op_2num: division by zero detected op=%s i1=%d i2=%d\n", script_op2name(op), i1, i2); - script_reportsrc(st); - script_pushnil(st); - st->state = END; - return; - } else if (op == C_DIV) - ret = i1 / i2; - else//if( op == C_MOD ) - ret = i1 % i2; - break; - default: - switch (op) { - // operators that can overflow/underflow - case C_ADD: - ret = i1 + i2; - ret_double = (double)i1 + (double)i2; - break; - case C_SUB: - ret = i1 - i2; - ret_double = (double)i1 - (double)i2; - break; - case C_MUL: - ret = i1 * i2; - ret_double = (double)i1 * (double)i2; - break; - default: - ShowError("script:op_2num: unexpected number operator %s i1=%d i2=%d\n", script_op2name(op), i1, i2); - script_reportsrc(st); - script_pushnil(st); - return; - } - if (ret_double < (double)INT_MIN) { - ShowWarning("script:op_2num: underflow detected op=%s i1=%d i2=%d\n", script_op2name(op), i1, i2); - script_reportsrc(st); - ret = INT_MIN; - } else if (ret_double > (double)INT_MAX) { - ShowWarning("script:op_2num: overflow detected op=%s i1=%d i2=%d\n", script_op2name(op), i1, i2); - script_reportsrc(st); - ret = INT_MAX; - } - } - script_pushint(st, ret); +void op_2num(struct script_state* st, int op, int i1, int i2) +{ + int ret; + double ret_double; + + switch( op ) + { + case C_AND: ret = i1 & i2; break; + case C_OR: ret = i1 | i2; break; + case C_XOR: ret = i1 ^ i2; break; + case C_LAND: ret = (i1 && i2); break; + case C_LOR: ret = (i1 || i2); break; + case C_EQ: ret = (i1 == i2); break; + case C_NE: ret = (i1 != i2); break; + case C_GT: ret = (i1 > i2); break; + case C_GE: ret = (i1 >= i2); break; + case C_LT: ret = (i1 < i2); break; + case C_LE: ret = (i1 <= i2); break; + case C_R_SHIFT: ret = i1>>i2; break; + case C_L_SHIFT: ret = i1<<i2; break; + case C_DIV: + case C_MOD: + if( i2 == 0 ) + { + ShowError("script:op_2num: division by zero detected op=%s i1=%d i2=%d\n", script_op2name(op), i1, i2); + script_reportsrc(st); + script_pushnil(st); + st->state = END; + return; + } + else if( op == C_DIV ) + ret = i1 / i2; + else//if( op == C_MOD ) + ret = i1 % i2; + break; + default: + switch( op ) + {// operators that can overflow/underflow + case C_ADD: ret = i1 + i2; ret_double = (double)i1 + (double)i2; break; + case C_SUB: ret = i1 - i2; ret_double = (double)i1 - (double)i2; break; + case C_MUL: ret = i1 * i2; ret_double = (double)i1 * (double)i2; break; + default: + ShowError("script:op_2num: unexpected number operator %s i1=%d i2=%d\n", script_op2name(op), i1, i2); + script_reportsrc(st); + script_pushnil(st); + return; + } + if( ret_double < (double)INT_MIN ) + { + ShowWarning("script:op_2num: underflow detected op=%s i1=%d i2=%d\n", script_op2name(op), i1, i2); + script_reportsrc(st); + ret = INT_MIN; + } + else if( ret_double > (double)INT_MAX ) + { + ShowWarning("script:op_2num: overflow detected op=%s i1=%d i2=%d\n", script_op2name(op), i1, i2); + script_reportsrc(st); + ret = INT_MAX; + } + } + script_pushint(st, ret); } /// Binary operators void op_2(struct script_state *st, int op) { - struct script_data *left, leftref; - struct script_data *right; - - leftref.type = C_NOP; - - left = script_getdatatop(st, -2); - right = script_getdatatop(st, -1); - - if (st->op2ref) { - if (data_isreference(left)) { - leftref = *left; - } - - st->op2ref = 0; - } - - get_val(st, left); - get_val(st, right); - - // automatic conversions - switch (op) { - case C_ADD: - if (data_isint(left) && data_isstring(right)) { - // convert int-string to string-string - conv_str(st, left); - } else if (data_isstring(left) && data_isint(right)) { - // convert string-int to string-string - conv_str(st, right); - } - break; - } - - if (data_isstring(left) && data_isstring(right)) { - // ss => op_2str - op_2str(st, op, left->u.str, right->u.str); - script_removetop(st, leftref.type == C_NOP ? -3 : -2, -1);// pop the two values before the top one - - if (leftref.type != C_NOP) { - aFree(left->u.str); - *left = leftref; - } - } else if (data_isint(left) && data_isint(right)) { - // ii => op_2num - int i1 = left->u.num; - int i2 = right->u.num; - - script_removetop(st, leftref.type == C_NOP ? -2 : -1, 0); - op_2num(st, op, i1, i2); - - if (leftref.type != C_NOP) - *left = leftref; - } else { - // invalid argument - ShowError("script:op_2: invalid data for operator %s\n", script_op2name(op)); - script_reportdata(left); - script_reportdata(right); - script_reportsrc(st); - script_removetop(st, -2, 0); - script_pushnil(st); - st->state = END; - } + struct script_data* left, leftref; + struct script_data* right; + + leftref.type = C_NOP; + + left = script_getdatatop(st, -2); + right = script_getdatatop(st, -1); + + if (st->op2ref) { + if (data_isreference(left)) { + leftref = *left; + } + + st->op2ref = 0; + } + + get_val(st, left); + get_val(st, right); + + // automatic conversions + switch( op ) + { + case C_ADD: + if( data_isint(left) && data_isstring(right) ) + {// convert int-string to string-string + conv_str(st, left); + } + else if( data_isstring(left) && data_isint(right) ) + {// convert string-int to string-string + conv_str(st, right); + } + break; + } + + if( data_isstring(left) && data_isstring(right) ) + {// ss => op_2str + op_2str(st, op, left->u.str, right->u.str); + script_removetop(st, leftref.type == C_NOP ? -3 : -2, -1);// pop the two values before the top one + + if (leftref.type != C_NOP) + { + aFree(left->u.str); + *left = leftref; + } + } + else if( data_isint(left) && data_isint(right) ) + {// ii => op_2num + int i1 = left->u.num; + int i2 = right->u.num; + + script_removetop(st, leftref.type == C_NOP ? -2 : -1, 0); + op_2num(st, op, i1, i2); + + if (leftref.type != C_NOP) + *left = leftref; + } + else + {// invalid argument + ShowError("script:op_2: invalid data for operator %s\n", script_op2name(op)); + script_reportdata(left); + script_reportdata(right); + script_reportsrc(st); + script_removetop(st, -2, 0); + script_pushnil(st); + st->state = END; + } } /// Unary operators /// NEG i -> i /// NOT i -> i /// LNOT i -> i -void op_1(struct script_state *st, int op) -{ - struct script_data *data; - int i1; - - data = script_getdatatop(st, -1); - get_val(st, data); - - if (!data_isint(data)) { - // not a number - ShowError("script:op_1: argument is not a number (op=%s)\n", script_op2name(op)); - script_reportdata(data); - script_reportsrc(st); - script_pushnil(st); - st->state = END; - return; - } - - i1 = data->u.num; - script_removetop(st, -1, 0); - switch (op) { - case C_NEG: - i1 = -i1; - break; - case C_NOT: - i1 = ~i1; - break; - case C_LNOT: - i1 = !i1; - break; - default: - ShowError("script:op_1: unexpected operator %s i1=%d\n", script_op2name(op), i1); - script_reportsrc(st); - script_pushnil(st); - st->state = END; - return; - } - script_pushint(st, i1); +void op_1(struct script_state* st, int op) +{ + struct script_data* data; + int i1; + + data = script_getdatatop(st, -1); + get_val(st, data); + + if( !data_isint(data) ) + {// not a number + ShowError("script:op_1: argument is not a number (op=%s)\n", script_op2name(op)); + script_reportdata(data); + script_reportsrc(st); + script_pushnil(st); + st->state = END; + return; + } + + i1 = data->u.num; + script_removetop(st, -1, 0); + switch( op ) + { + case C_NEG: i1 = -i1; break; + case C_NOT: i1 = ~i1; break; + case C_LNOT: i1 = !i1; break; + default: + ShowError("script:op_1: unexpected operator %s i1=%d\n", script_op2name(op), i1); + script_reportsrc(st); + script_pushnil(st); + st->state = END; + return; + } + script_pushint(st, i1); } @@ -3309,82 +3335,88 @@ void op_1(struct script_state *st, int op) /// /// @param st Script state whose stack arguments should be inspected. /// @param func Built-in function for which the arguments are intended. -static void script_check_buildin_argtype(struct script_state *st, int func) -{ - char type; - int idx, invalid = 0; - script_function *sf = &buildin_func[str_data[func].val]; - - for (idx = 2; script_hasdata(st, idx); idx++) { - struct script_data *data = script_getdata(st, idx); - - type = sf->arg[idx-2]; - - if (type == '?' || type == '*') { - // optional argument or unknown number of optional parameters ( no types are after this ) - break; - } else if (type == 0) { - // more arguments than necessary ( should not happen, as it is checked before ) - ShowWarning("Found more arguments than necessary. unexpected arg type %s\n",script_op2name(data->type)); - invalid++; - break; - } else { - const char *name = NULL; - - if (data_isreference(data)) { - // get name for variables to determine the type they refer to - name = reference_getname(data); - } - - switch (type) { - case 'v': - if (!data_isstring(data) && !data_isint(data) && !data_isreference(data)) { - // variant - ShowWarning("Unexpected type for argument %d. Expected string, number or variable.\n", idx-1); - script_reportdata(data); - invalid++; - } - break; - case 's': - if (!data_isstring(data) && !(data_isreference(data) && is_string_variable(name))) { - // string - ShowWarning("Unexpected type for argument %d. Expected string.\n", idx-1); - script_reportdata(data); - invalid++; - } - break; - case 'i': - if (!data_isint(data) && !(data_isreference(data) && (reference_toparam(data) || reference_toconstant(data) || !is_string_variable(name)))) { - // int ( params and constants are always int ) - ShowWarning("Unexpected type for argument %d. Expected number.\n", idx-1); - script_reportdata(data); - invalid++; - } - break; - case 'r': - if (!data_isreference(data)) { - // variables - ShowWarning("Unexpected type for argument %d. Expected variable, got %s.\n", idx-1,script_op2name(data->type)); - script_reportdata(data); - invalid++; - } - break; - case 'l': - if (!data_islabel(data) && !data_isfunclabel(data)) { - // label - ShowWarning("Unexpected type for argument %d. Expected label, got %s\n", idx-1,script_op2name(data->type)); - script_reportdata(data); - invalid++; - } - break; - } - } - } - - if (invalid) { - ShowDebug("Function: %s\n", get_str(func)); - script_reportsrc(st); - } +static void script_check_buildin_argtype(struct script_state* st, int func) +{ + char type; + int idx, invalid = 0; + script_function* sf = &buildin_func[str_data[func].val]; + + for( idx = 2; script_hasdata(st, idx); idx++ ) + { + struct script_data* data = script_getdata(st, idx); + + type = sf->arg[idx-2]; + + if( type == '?' || type == '*' ) + {// optional argument or unknown number of optional parameters ( no types are after this ) + break; + } + else if( type == 0 ) + {// more arguments than necessary ( should not happen, as it is checked before ) + ShowWarning("Found more arguments than necessary. unexpected arg type %s\n",script_op2name(data->type)); + invalid++; + break; + } + else + { + const char* name = NULL; + + if( data_isreference(data) ) + {// get name for variables to determine the type they refer to + name = reference_getname(data); + } + + switch( type ) + { + case 'v': + if( !data_isstring(data) && !data_isint(data) && !data_isreference(data) ) + {// variant + ShowWarning("Unexpected type for argument %d. Expected string, number or variable.\n", idx-1); + script_reportdata(data); + invalid++; + } + break; + case 's': + if( !data_isstring(data) && !( data_isreference(data) && is_string_variable(name) ) ) + {// string + ShowWarning("Unexpected type for argument %d. Expected string.\n", idx-1); + script_reportdata(data); + invalid++; + } + break; + case 'i': + if( !data_isint(data) && !( data_isreference(data) && ( reference_toparam(data) || reference_toconstant(data) || !is_string_variable(name) ) ) ) + {// int ( params and constants are always int ) + ShowWarning("Unexpected type for argument %d. Expected number.\n", idx-1); + script_reportdata(data); + invalid++; + } + break; + case 'r': + if( !data_isreference(data) ) + {// variables + ShowWarning("Unexpected type for argument %d. Expected variable, got %s.\n", idx-1,script_op2name(data->type)); + script_reportdata(data); + invalid++; + } + break; + case 'l': + if( !data_islabel(data) && !data_isfunclabel(data) ) + {// label + ShowWarning("Unexpected type for argument %d. Expected label, got %s\n", idx-1,script_op2name(data->type)); + script_reportdata(data); + invalid++; + } + break; + } + } + } + + if(invalid) + { + ShowDebug("Function: %s\n", get_str(func)); + script_reportsrc(st); + } } @@ -3392,81 +3424,85 @@ static void script_check_buildin_argtype(struct script_state *st, int func) /// Stack: C_NAME(<command>) C_ARG <arg0> <arg1> ... <argN> int run_func(struct script_state *st) { - struct script_data *data; - int i,start_sp,end_sp,func; - - end_sp = st->stack->sp;// position after the last argument - for (i = end_sp-1; i > 0 ; --i) - if (st->stack->stack_data[i].type == C_ARG) - break; - if (i == 0) { - ShowError("script:run_func: C_ARG not found. please report this!!!\n"); - st->state = END; - script_reportsrc(st); - return 1; - } - start_sp = i-1;// C_NAME of the command - st->start = start_sp; - st->end = end_sp; - - data = &st->stack->stack_data[st->start]; - if (data->type == C_NAME && str_data[data->u.num].type == C_FUNC) - func = data->u.num; - else { - ShowError("script:run_func: not a buildin command.\n"); - script_reportdata(data); - script_reportsrc(st); - st->state = END; - return 1; - } - - if (script_config.warn_func_mismatch_argtypes) { - script_check_buildin_argtype(st, func); - } - - if (str_data[func].func) { - if (str_data[func].func(st)) //Report error - script_reportsrc(st); - } else { - ShowError("script:run_func: '%s' (id=%d type=%s) has no C function. please report this!!!\n", get_str(func), func, script_op2name(str_data[func].type)); - script_reportsrc(st); - st->state = END; - } - - // Stack's datum are used when re-running functions [Eoe] - if (st->state == RERUNLINE) - return 0; - - pop_stack(st, st->start, st->end); - if (st->state == RETFUNC) { - // return from a user-defined function - struct script_retinfo *ri; - int olddefsp = st->stack->defsp; - int nargs; - - pop_stack(st, st->stack->defsp, st->start);// pop distractions from the stack - if (st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp-1].type != C_RETINFO) { - ShowWarning("script:run_func: return without callfunc or callsub!\n"); - script_reportsrc(st); - st->state = END; - return 1; - } - script_free_vars(st->stack->var_function); - - ri = st->stack->stack_data[st->stack->defsp-1].u.ri; - nargs = ri->nargs; - st->pos = ri->pos; - st->script = ri->script; - st->stack->var_function = ri->var_function; - st->stack->defsp = ri->defsp; - memset(ri, 0, sizeof(struct script_retinfo)); - - pop_stack(st, olddefsp-nargs-1, olddefsp);// pop arguments and retinfo - - st->state = GOTO; - } - - return 0; + struct script_data* data; + int i,start_sp,end_sp,func; + + end_sp = st->stack->sp;// position after the last argument + for( i = end_sp-1; i > 0 ; --i ) + if( st->stack->stack_data[i].type == C_ARG ) + break; + if( i == 0 ) + { + ShowError("script:run_func: C_ARG not found. please report this!!!\n"); + st->state = END; + script_reportsrc(st); + return 1; + } + start_sp = i-1;// C_NAME of the command + st->start = start_sp; + st->end = end_sp; + + data = &st->stack->stack_data[st->start]; + if( data->type == C_NAME && str_data[data->u.num].type == C_FUNC ) + func = data->u.num; + else + { + ShowError("script:run_func: not a buildin command.\n"); + script_reportdata(data); + script_reportsrc(st); + st->state = END; + return 1; + } + + if( script_config.warn_func_mismatch_argtypes ) + { + script_check_buildin_argtype(st, func); + } + + if(str_data[func].func){ + if (str_data[func].func(st)) //Report error + script_reportsrc(st); + } else { + ShowError("script:run_func: '%s' (id=%d type=%s) has no C function. please report this!!!\n", get_str(func), func, script_op2name(str_data[func].type)); + script_reportsrc(st); + st->state = END; + } + + // Stack's datum are used when re-running functions [Eoe] + if( st->state == RERUNLINE ) + return 0; + + pop_stack(st, st->start, st->end); + if( st->state == RETFUNC ) + {// return from a user-defined function + struct script_retinfo* ri; + int olddefsp = st->stack->defsp; + int nargs; + + pop_stack(st, st->stack->defsp, st->start);// pop distractions from the stack + if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp-1].type != C_RETINFO ) + { + ShowWarning("script:run_func: return without callfunc or callsub!\n"); + script_reportsrc(st); + st->state = END; + return 1; + } + script_free_vars( st->stack->var_function ); + + ri = st->stack->stack_data[st->stack->defsp-1].u.ri; + nargs = ri->nargs; + st->pos = ri->pos; + st->script = ri->script; + st->stack->var_function = ri->var_function; + st->stack->defsp = ri->defsp; + memset(ri, 0, sizeof(struct script_retinfo)); + + pop_stack(st, olddefsp-nargs-1, olddefsp);// pop arguments and retinfo + + st->state = GOTO; + } + + return 0; } /*========================================== @@ -3474,46 +3510,48 @@ int run_func(struct script_state *st) *------------------------------------------*/ void run_script(struct script_code *rootscript,int pos,int rid,int oid) { - struct script_state *st; + struct script_state *st; - if (rootscript == NULL || pos < 0) - return; + if( rootscript == NULL || pos < 0 ) + return; - // TODO In jAthena, this function can take over the pending script in the player. [FlavioJS] - // It is unclear how that can be triggered, so it needs the be traced/checked in more detail. - // NOTE At the time of this change, this function wasn't capable of taking over the script state because st->scriptroot was never set. - st = script_alloc_state(rootscript, pos, rid, oid); - run_script_main(st); + // TODO In jAthena, this function can take over the pending script in the player. [FlavioJS] + // It is unclear how that can be triggered, so it needs the be traced/checked in more detail. + // NOTE At the time of this change, this function wasn't capable of taking over the script state because st->scriptroot was never set. + st = script_alloc_state(rootscript, pos, rid, oid); + run_script_main(st); } void script_stop_sleeptimers(int id) { - struct script_state *st; - for (;;) { - st = (struct script_state *)linkdb_erase(&sleep_db,(void *)__64BPRTSIZE(id)); - if (st == NULL) - break; // no more sleep timers - script_free_state(st); - } + struct script_state* st; + for(;;) + { + st = (struct script_state*)linkdb_erase(&sleep_db,(void*)__64BPRTSIZE(id)); + if( st == NULL ) + break; // no more sleep timers + script_free_state(st); + } } /*========================================== * Delete the specified node from sleep_db *------------------------------------------*/ -struct linkdb_node *script_erase_sleepdb(struct linkdb_node *n) { - struct linkdb_node *retnode; - - if (n == NULL) - return NULL; - if (n->prev == NULL) - sleep_db = n->next; - else - n->prev->next = n->next; - if (n->next) - n->next->prev = n->prev; - retnode = n->next; - aFree(n); - return retnode; // The following; return retnode +struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n) +{ + struct linkdb_node *retnode; + + if( n == NULL) + return NULL; + if( n->prev == NULL ) + sleep_db = n->next; + else + n->prev->next = n->next; + if( n->next ) + n->next->prev = n->prev; + retnode = n->next; + aFree( n ); + return retnode; // The following; return retnode } /*========================================== @@ -3521,96 +3559,103 @@ struct linkdb_node *script_erase_sleepdb(struct linkdb_node *n) { *------------------------------------------*/ int run_script_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct script_state *st = (struct script_state *)data; - struct linkdb_node *node = (struct linkdb_node *)sleep_db; - TBL_PC *sd = map_id2sd(st->rid); - - if ((sd && sd->status.char_id != id) || (st->rid && !sd)) { - //Character mismatch. Cancel execution. - st->rid = 0; - st->state = END; - } - while (node && st->sleep.timer != INVALID_TIMER) { - if ((int)__64BPRTSIZE(node->key) == st->oid && ((struct script_state *)node->data)->sleep.timer == st->sleep.timer) { - script_erase_sleepdb(node); - st->sleep.timer = INVALID_TIMER; - break; - } - node = node->next; - } - if (st->state != RERUNLINE) - st->sleep.tick = 0; - run_script_main(st); - return 0; + struct script_state *st = (struct script_state *)data; + struct linkdb_node *node = (struct linkdb_node *)sleep_db; + TBL_PC *sd = map_id2sd(st->rid); + + if((sd && sd->status.char_id != id) || (st->rid && !sd)) + { //Character mismatch. Cancel execution. + st->rid = 0; + st->state = END; + } + while( node && st->sleep.timer != INVALID_TIMER ) { + if( (int)__64BPRTSIZE(node->key) == st->oid && ((struct script_state *)node->data)->sleep.timer == st->sleep.timer ) { + script_erase_sleepdb(node); + st->sleep.timer = INVALID_TIMER; + break; + } + node = node->next; + } + if(st->state != RERUNLINE) + st->sleep.tick = 0; + run_script_main(st); + return 0; } /// Detaches script state from possibly attached character and restores it's previous script if any. /// /// @param st Script state to detach. /// @param dequeue_event Whether to schedule any queued events, when there was no previous script. -static void script_detach_state(struct script_state *st, bool dequeue_event) -{ - struct map_session_data *sd; - - if (st->rid && (sd = map_id2sd(st->rid))!=NULL) { - sd->st = st->bk_st; - sd->npc_id = st->bk_npcid; - /** - * For the Secure NPC Timeout option (check config/Secure.h) [RR] - **/ -#if SECURE_NPCTIMEOUT - /** - * We're done with this NPC session, so we cancel the timer (if existent) and move on - **/ - if (sd->npc_idle_timer != INVALID_TIMER) { - delete_timer(sd->npc_idle_timer,npc_rr_secure_timeout_timer); - sd->npc_idle_timer = INVALID_TIMER; - } -#endif - if (st->bk_st) { - //Remove tag for removal. - st->bk_st = NULL; - st->bk_npcid = 0; - } else if (dequeue_event) { - npc_event_dequeue(sd); - } - } else if (st->bk_st) { - // rid was set to 0, before detaching the script state - ShowError("script_detach_state: Found previous script state without attached player (rid=%d, oid=%d, state=%d, bk_npcid=%d)\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); - script_reportsrc(st->bk_st); - - script_free_state(st->bk_st); - st->bk_st = NULL; - } +static void script_detach_state(struct script_state* st, bool dequeue_event) +{ + struct map_session_data* sd; + + if(st->rid && (sd = map_id2sd(st->rid))!=NULL) + { + sd->st = st->bk_st; + sd->npc_id = st->bk_npcid; + /** + * For the Secure NPC Timeout option (check config/Secure.h) [RR] + **/ + #if SECURE_NPCTIMEOUT + /** + * We're done with this NPC session, so we cancel the timer (if existent) and move on + **/ + if( sd->npc_idle_timer != INVALID_TIMER ) { + delete_timer(sd->npc_idle_timer,npc_rr_secure_timeout_timer); + sd->npc_idle_timer = INVALID_TIMER; + } + #endif + if(st->bk_st) + { + //Remove tag for removal. + st->bk_st = NULL; + st->bk_npcid = 0; + } + else if(dequeue_event) + { + npc_event_dequeue(sd); + } + } + else if(st->bk_st) + {// rid was set to 0, before detaching the script state + ShowError("script_detach_state: Found previous script state without attached player (rid=%d, oid=%d, state=%d, bk_npcid=%d)\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); + script_reportsrc(st->bk_st); + + script_free_state(st->bk_st); + st->bk_st = NULL; + } } /// Attaches script state to possibly attached character and backups it's previous script, if any. /// /// @param st Script state to attach. -static void script_attach_state(struct script_state *st) -{ - struct map_session_data *sd; - - if (st->rid && (sd = map_id2sd(st->rid))!=NULL) { - if (st!=sd->st) { - if (st->bk_st) { - // there is already a backup - ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); - } - st->bk_st = sd->st; - st->bk_npcid = sd->npc_id; - } - sd->st = st; - sd->npc_id = st->oid; - /** - * For the Secure NPC Timeout option (check config/Secure.h) [RR] - **/ +static void script_attach_state(struct script_state* st) +{ + struct map_session_data* sd; + + if(st->rid && (sd = map_id2sd(st->rid))!=NULL) + { + if(st!=sd->st) + { + if(st->bk_st) + {// there is already a backup + ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); + } + st->bk_st = sd->st; + st->bk_npcid = sd->npc_id; + } + sd->st = st; + sd->npc_id = st->oid; +/** + * For the Secure NPC Timeout option (check config/Secure.h) [RR] + **/ #if SECURE_NPCTIMEOUT - if (sd->npc_idle_timer == INVALID_TIMER) - sd->npc_idle_timer = add_timer(gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc_rr_secure_timeout_timer,sd->bl.id,0); - sd->npc_idle_tick = gettick(); + if( sd->npc_idle_timer == INVALID_TIMER ) + sd->npc_idle_timer = add_timer(gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc_rr_secure_timeout_timer,sd->bl.id,0); + sd->npc_idle_tick = gettick(); #endif - } + } } /*========================================== @@ -3618,194 +3663,204 @@ static void script_attach_state(struct script_state *st) *------------------------------------------*/ void run_script_main(struct script_state *st) { - int cmdcount = script_config.check_cmdcount; - int gotocount = script_config.check_gotocount; - TBL_PC *sd; - struct script_stack *stack=st->stack; - struct npc_data *nd; - - script_attach_state(st); - - nd = map_id2nd(st->oid); - if (nd && map[nd->bl.m].instance_id > 0) - st->instance_id = map[nd->bl.m].instance_id; - - if (st->state == RERUNLINE) { - run_func(st); - if (st->state == GOTO) - st->state = RUN; - } else if (st->state != END) - st->state = RUN; - - while (st->state == RUN) { - enum c_op c = get_com(st->script->script_buf,&st->pos); - switch (c) { - case C_EOL: - if (stack->defsp > stack->sp) - ShowError("script:run_script_main: unexpected stack position (defsp=%d sp=%d). please report this!!!\n", stack->defsp, stack->sp); - else - pop_stack(st, stack->defsp, stack->sp);// pop unused stack data. (unused return value) - break; - case C_INT: - push_val(stack,C_INT,get_num(st->script->script_buf,&st->pos)); - break; - case C_POS: - case C_NAME: - push_val(stack,c,GETVALUE(st->script->script_buf,st->pos)); - st->pos+=3; - break; - case C_ARG: - push_val(stack,c,0); - break; - case C_STR: - push_str(stack,C_CONSTSTR,(char *)(st->script->script_buf+st->pos)); - while (st->script->script_buf[st->pos++]); - break; - case C_FUNC: - run_func(st); - if (st->state==GOTO) { - st->state = RUN; - if (!st->freeloop && gotocount>0 && (--gotocount)<=0) { - ShowError("run_script: infinity loop !\n"); - script_reportsrc(st); - st->state=END; - } - } - break; - - case C_REF: - st->op2ref = 1; - break; - - case C_NEG: - case C_NOT: - case C_LNOT: - op_1(st ,c); - break; - - case C_ADD: - case C_SUB: - case C_MUL: - case C_DIV: - case C_MOD: - case C_EQ: - case C_NE: - case C_GT: - case C_GE: - case C_LT: - case C_LE: - case C_AND: - case C_OR: - case C_XOR: - case C_LAND: - case C_LOR: - case C_R_SHIFT: - case C_L_SHIFT: - op_2(st, c); - break; - - case C_OP3: - op_3(st, c); - break; - - case C_NOP: - st->state=END; - break; - - default: - ShowError("unknown command : %d @ %d\n",c,st->pos); - st->state=END; - break; - } - if (!st->freeloop && cmdcount>0 && (--cmdcount)<=0) { - ShowError("run_script: infinity loop !\n"); - script_reportsrc(st); - st->state=END; - } - } - - if (st->sleep.tick > 0) { - //Restore previous script - script_detach_state(st, false); - //Delay execution - sd = map_id2sd(st->rid); // Get sd since script might have attached someone while running. [Inkfish] - st->sleep.charid = sd?sd->status.char_id:0; - st->sleep.timer = add_timer(gettick()+st->sleep.tick, - run_script_timer, st->sleep.charid, (intptr_t)st); - linkdb_insert(&sleep_db, (void *)__64BPRTSIZE(st->oid), st); - } else if (st->state != END && st->rid) { - //Resume later (st is already attached to player). - if (st->bk_st) { - ShowWarning("Unable to restore stack! Double continuation!\n"); - //Report BOTH scripts to see if that can help somehow. - ShowDebug("Previous script (lost):\n"); - script_reportsrc(st->bk_st); - ShowDebug("Current script:\n"); - script_reportsrc(st); - - script_free_state(st->bk_st); - st->bk_st = NULL; - } - } else { - //Dispose of script. - if ((sd = map_id2sd(st->rid))!=NULL) { - //Restore previous stack and save char. - if (sd->state.using_fake_npc) { - clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); - sd->state.using_fake_npc = 0; - } - //Restore previous script if any. - script_detach_state(st, true); - if (sd->state.reg_dirty&2) - intif_saveregistry(sd,2); - if (sd->state.reg_dirty&1) - intif_saveregistry(sd,1); - } - script_free_state(st); - st = NULL; - } + int cmdcount = script_config.check_cmdcount; + int gotocount = script_config.check_gotocount; + TBL_PC *sd; + struct script_stack *stack=st->stack; + struct npc_data *nd; + + script_attach_state(st); + + nd = map_id2nd(st->oid); + if( nd && map[nd->bl.m].instance_id > 0 ) + st->instance_id = map[nd->bl.m].instance_id; + + if(st->state == RERUNLINE) { + run_func(st); + if(st->state == GOTO) + st->state = RUN; + } else if(st->state != END) + st->state = RUN; + + while(st->state == RUN) + { + enum c_op c = get_com(st->script->script_buf,&st->pos); + switch(c){ + case C_EOL: + if( stack->defsp > stack->sp ) + ShowError("script:run_script_main: unexpected stack position (defsp=%d sp=%d). please report this!!!\n", stack->defsp, stack->sp); + else + pop_stack(st, stack->defsp, stack->sp);// pop unused stack data. (unused return value) + break; + case C_INT: + push_val(stack,C_INT,get_num(st->script->script_buf,&st->pos)); + break; + case C_POS: + case C_NAME: + push_val(stack,c,GETVALUE(st->script->script_buf,st->pos)); + st->pos+=3; + break; + case C_ARG: + push_val(stack,c,0); + break; + case C_STR: + push_str(stack,C_CONSTSTR,(char*)(st->script->script_buf+st->pos)); + while(st->script->script_buf[st->pos++]); + break; + case C_FUNC: + run_func(st); + if(st->state==GOTO){ + st->state = RUN; + if( !st->freeloop && gotocount>0 && (--gotocount)<=0 ){ + ShowError("run_script: infinity loop !\n"); + script_reportsrc(st); + st->state=END; + } + } + break; + + case C_REF: + st->op2ref = 1; + break; + + case C_NEG: + case C_NOT: + case C_LNOT: + op_1(st ,c); + break; + + case C_ADD: + case C_SUB: + case C_MUL: + case C_DIV: + case C_MOD: + case C_EQ: + case C_NE: + case C_GT: + case C_GE: + case C_LT: + case C_LE: + case C_AND: + case C_OR: + case C_XOR: + case C_LAND: + case C_LOR: + case C_R_SHIFT: + case C_L_SHIFT: + op_2(st, c); + break; + + case C_OP3: + op_3(st, c); + break; + + case C_NOP: + st->state=END; + break; + + default: + ShowError("unknown command : %d @ %d\n",c,st->pos); + st->state=END; + break; + } + if( !st->freeloop && cmdcount>0 && (--cmdcount)<=0 ){ + ShowError("run_script: infinity loop !\n"); + script_reportsrc(st); + st->state=END; + } + } + + if(st->sleep.tick > 0) { + //Restore previous script + script_detach_state(st, false); + //Delay execution + sd = map_id2sd(st->rid); // Get sd since script might have attached someone while running. [Inkfish] + st->sleep.charid = sd?sd->status.char_id:0; + st->sleep.timer = add_timer(gettick()+st->sleep.tick, + run_script_timer, st->sleep.charid, (intptr_t)st); + linkdb_insert(&sleep_db, (void*)__64BPRTSIZE(st->oid), st); + } + else if(st->state != END && st->rid){ + //Resume later (st is already attached to player). + if(st->bk_st) { + ShowWarning("Unable to restore stack! Double continuation!\n"); + //Report BOTH scripts to see if that can help somehow. + ShowDebug("Previous script (lost):\n"); + script_reportsrc(st->bk_st); + ShowDebug("Current script:\n"); + script_reportsrc(st); + + script_free_state(st->bk_st); + st->bk_st = NULL; + } + } else { + //Dispose of script. + if ((sd = map_id2sd(st->rid))!=NULL) + { //Restore previous stack and save char. + if(sd->state.using_fake_npc){ + clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); + sd->state.using_fake_npc = 0; + } + //Restore previous script if any. + script_detach_state(st, true); + if (sd->state.reg_dirty&2) + intif_saveregistry(sd,2); + if (sd->state.reg_dirty&1) + intif_saveregistry(sd,1); + } + script_free_state(st); + st = NULL; + } } int script_config_read(char *cfgName) { - int i; - char line[1024],w1[1024],w2[1024]; - FILE *fp; - - - fp=fopen(cfgName,"r"); - if (fp==NULL) { - ShowError("File not found: %s\n", cfgName); - return 1; - } - while (fgets(line, sizeof(line), fp)) { - if (line[0] == '/' && line[1] == '/') - continue; - i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2); - if (i!=2) - continue; - - if (strcmpi(w1,"warn_func_mismatch_paramnum")==0) { - script_config.warn_func_mismatch_paramnum = config_switch(w2); - } else if (strcmpi(w1,"check_cmdcount")==0) { - script_config.check_cmdcount = config_switch(w2); - } else if (strcmpi(w1,"check_gotocount")==0) { - script_config.check_gotocount = config_switch(w2); - } else if (strcmpi(w1,"input_min_value")==0) { - script_config.input_min_value = config_switch(w2); - } else if (strcmpi(w1,"input_max_value")==0) { - script_config.input_max_value = config_switch(w2); - } else if (strcmpi(w1,"warn_func_mismatch_argtypes")==0) { - script_config.warn_func_mismatch_argtypes = config_switch(w2); - } else if (strcmpi(w1,"import")==0) { - script_config_read(w2); - } else { - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); - } - } - fclose(fp); - - return 0; + int i; + char line[1024],w1[1024],w2[1024]; + FILE *fp; + + + fp=fopen(cfgName,"r"); + if(fp==NULL){ + ShowError("File not found: %s\n", cfgName); + return 1; + } + while(fgets(line, sizeof(line), fp)) + { + if(line[0] == '/' && line[1] == '/') + continue; + i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2); + if(i!=2) + continue; + + if(strcmpi(w1,"warn_func_mismatch_paramnum")==0) { + script_config.warn_func_mismatch_paramnum = config_switch(w2); + } + else if(strcmpi(w1,"check_cmdcount")==0) { + script_config.check_cmdcount = config_switch(w2); + } + else if(strcmpi(w1,"check_gotocount")==0) { + script_config.check_gotocount = config_switch(w2); + } + else if(strcmpi(w1,"input_min_value")==0) { + script_config.input_min_value = config_switch(w2); + } + else if(strcmpi(w1,"input_max_value")==0) { + script_config.input_max_value = config_switch(w2); + } + else if(strcmpi(w1,"warn_func_mismatch_argtypes")==0) { + script_config.warn_func_mismatch_argtypes = config_switch(w2); + } + else if(strcmpi(w1,"import")==0){ + script_config_read(w2); + } + else { + ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); + } + } + fclose(fp); + + return 0; } /** @@ -3813,454 +3868,462 @@ int script_config_read(char *cfgName) */ static int db_script_free_code_sub(DBKey key, DBData *data, va_list ap) { - struct script_code *code = db_data2ptr(data); - if (code) - script_free_code(code); - return 0; + struct script_code *code = db_data2ptr(data); + if (code) + script_free_code(code); + return 0; } void script_run_autobonus(const char *autobonus, int id, int pos) { - struct script_code *script = (struct script_code *)strdb_get(autobonus_db, autobonus); + struct script_code *script = (struct script_code *)strdb_get(autobonus_db, autobonus); - if (script) { - current_equip_item_index = pos; - run_script(script,0,id,0); - } + if( script ) + { + current_equip_item_index = pos; + run_script(script,0,id,0); + } } void script_add_autobonus(const char *autobonus) { - if (strdb_get(autobonus_db, autobonus) == NULL) { - struct script_code *script = parse_script(autobonus, "autobonus", 0, 0); + if( strdb_get(autobonus_db, autobonus) == NULL ) + { + struct script_code *script = parse_script(autobonus, "autobonus", 0, 0); - if (script) - strdb_put(autobonus_db, autobonus, script); - } + if( script ) + strdb_put(autobonus_db, autobonus, script); + } } /// resets a temporary character array variable to given value -void script_cleararray_pc(struct map_session_data *sd, const char *varname, void *value) +void script_cleararray_pc(struct map_session_data* sd, const char* varname, void* value) { - int key; - uint8 idx; + int key; + uint8 idx; - if (not_array_variable(varname[0]) || !not_server_variable(varname[0])) { - ShowError("script_cleararray_pc: Variable '%s' has invalid scope (char_id=%d).\n", varname, sd->status.char_id); - return; - } + if( not_array_variable(varname[0]) || !not_server_variable(varname[0]) ) + { + ShowError("script_cleararray_pc: Variable '%s' has invalid scope (char_id=%d).\n", varname, sd->status.char_id); + return; + } - key = add_str(varname); + key = add_str(varname); - if (is_string_variable(varname)) { - for (idx = 0; idx < SCRIPT_MAX_ARRAYSIZE; idx++) { - pc_setregstr(sd, reference_uid(key, idx), (const char *)value); - } - } else { - for (idx = 0; idx < SCRIPT_MAX_ARRAYSIZE; idx++) { - pc_setreg(sd, reference_uid(key, idx), (int)__64BPRTSIZE(value)); - } - } + if( is_string_variable(varname) ) + { + for( idx = 0; idx < SCRIPT_MAX_ARRAYSIZE; idx++ ) + { + pc_setregstr(sd, reference_uid(key, idx), (const char*)value); + } + } + else + { + for( idx = 0; idx < SCRIPT_MAX_ARRAYSIZE; idx++ ) + { + pc_setreg(sd, reference_uid(key, idx), (int)__64BPRTSIZE(value)); + } + } } /// sets a temporary character array variable element idx to given value /// @param refcache Pointer to an int variable, which keeps a copy of the reference to varname and must be initialized to 0. Can be NULL if only one element is set. -void script_setarray_pc(struct map_session_data *sd, const char *varname, uint8 idx, void *value, int *refcache) -{ - int key; - - if (not_array_variable(varname[0]) || !not_server_variable(varname[0])) { - ShowError("script_setarray_pc: Variable '%s' has invalid scope (char_id=%d).\n", varname, sd->status.char_id); - return; - } - - if (idx >= SCRIPT_MAX_ARRAYSIZE) { - ShowError("script_setarray_pc: Variable '%s' has invalid index '%d' (char_id=%d).\n", varname, (int)idx, sd->status.char_id); - return; - } - - key = (refcache && refcache[0]) ? refcache[0] : add_str(varname); - - if (is_string_variable(varname)) { - pc_setregstr(sd, reference_uid(key, idx), (const char *)value); - } else { - pc_setreg(sd, reference_uid(key, idx), (int)__64BPRTSIZE(value)); - } - - if (refcache) { - // save to avoid repeated add_str calls - refcache[0] = key; - } +void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 idx, void* value, int* refcache) +{ + int key; + + if( not_array_variable(varname[0]) || !not_server_variable(varname[0]) ) + { + ShowError("script_setarray_pc: Variable '%s' has invalid scope (char_id=%d).\n", varname, sd->status.char_id); + return; + } + + if( idx >= SCRIPT_MAX_ARRAYSIZE ) + { + ShowError("script_setarray_pc: Variable '%s' has invalid index '%d' (char_id=%d).\n", varname, (int)idx, sd->status.char_id); + return; + } + + key = ( refcache && refcache[0] ) ? refcache[0] : add_str(varname); + + if( is_string_variable(varname) ) + { + pc_setregstr(sd, reference_uid(key, idx), (const char*)value); + } + else + { + pc_setreg(sd, reference_uid(key, idx), (int)__64BPRTSIZE(value)); + } + + if( refcache ) + {// save to avoid repeated add_str calls + refcache[0] = key; + } } #ifdef BETA_THREAD_TEST -int buildin_query_sql_sub(struct script_state *st, Sql *handle); +int buildin_query_sql_sub(struct script_state* st, Sql* handle); /* used to receive items the queryThread has already processed */ -int queryThread_timer(int tid, unsigned int tick, int id, intptr_t data) -{ - int i, cursor = 0; - bool allOk = true; +int queryThread_timer(int tid, unsigned int tick, int id, intptr_t data) { + int i, cursor = 0; + bool allOk = true; - EnterSpinLock(&queryThreadLock); + EnterSpinLock(&queryThreadLock); - for (i = 0; i < queryThreadData.count; i++) { - struct queryThreadEntry *entry = queryThreadData.entry[i]; + for( i = 0; i < queryThreadData.count; i++ ) { + struct queryThreadEntry *entry = queryThreadData.entry[i]; - if (!entry->ok) { - allOk = false; - continue; - } + if( !entry->ok ) { + allOk = false; + continue; + } - run_script_main(entry->st); + run_script_main(entry->st); - entry->st = NULL;/* empty entries */ - aFree(entry); - queryThreadData.entry[i] = NULL; - } + entry->st = NULL;/* empty entries */ + aFree(entry); + queryThreadData.entry[i] = NULL; + } - if (allOk) { - /* cancel the repeating timer -- it'll re-create itself when necessary, dont need to remain looping */ - delete_timer(queryThreadData.timer, queryThread_timer); - queryThreadData.timer = INVALID_TIMER; - } + if( allOk ) { + /* cancel the repeating timer -- it'll re-create itself when necessary, dont need to remain looping */ + delete_timer(queryThreadData.timer, queryThread_timer); + queryThreadData.timer = INVALID_TIMER; + } - /* now lets clear the mess. */ - for (i = 0; i < queryThreadData.count; i++) { - struct queryThreadEntry *entry = queryThreadData.entry[i]; - if (entry == NULL) - continue;/* entry on hold */ + /* now lets clear the mess. */ + for( i = 0; i < queryThreadData.count; i++ ) { + struct queryThreadEntry *entry = queryThreadData.entry[i]; + if( entry == NULL ) + continue;/* entry on hold */ - /* move */ - memmove(&queryThreadData.entry[cursor], &queryThreadData.entry[i], sizeof(struct queryThreadEntry *)); + /* move */ + memmove(&queryThreadData.entry[cursor], &queryThreadData.entry[i], sizeof(struct queryThreadEntry*)); - cursor++; - } + cursor++; + } - queryThreadData.count = cursor; + queryThreadData.count = cursor; - LeaveSpinLock(&queryThreadLock); + LeaveSpinLock(&queryThreadLock); - return 0; + return 0; } -void queryThread_add(struct script_state *st, bool type) -{ - int idx = 0; - struct queryThreadEntry *entry = NULL; +void queryThread_add(struct script_state *st, bool type) { + int idx = 0; + struct queryThreadEntry* entry = NULL; - EnterSpinLock(&queryThreadLock); + EnterSpinLock(&queryThreadLock); - if (queryThreadData.count++ != 0) - RECREATE(queryThreadData.entry, struct queryThreadEntry * , queryThreadData.count); + if( queryThreadData.count++ != 0 ) + RECREATE(queryThreadData.entry, struct queryThreadEntry* , queryThreadData.count); - idx = queryThreadData.count-1; + idx = queryThreadData.count-1; - CREATE(queryThreadData.entry[idx],struct queryThreadEntry,1); + CREATE(queryThreadData.entry[idx],struct queryThreadEntry,1); - entry = queryThreadData.entry[idx]; + entry = queryThreadData.entry[idx]; - entry->st = st; - entry->ok = false; - entry->type = type; - if (queryThreadData.timer == INVALID_TIMER) { /* start the receiver timer */ - queryThreadData.timer = add_timer_interval(gettick() + 100, queryThread_timer, 0, 0, 100); - } + entry->st = st; + entry->ok = false; + entry->type = type; + if( queryThreadData.timer == INVALID_TIMER ) { /* start the receiver timer */ + queryThreadData.timer = add_timer_interval(gettick() + 100, queryThread_timer, 0, 0, 100); + } - LeaveSpinLock(&queryThreadLock); + LeaveSpinLock(&queryThreadLock); - /* unlock the queryThread */ - racond_signal(queryThreadCond); + /* unlock the queryThread */ + racond_signal(queryThreadCond); } /* adds a new log to the queue */ -void queryThread_log(char *entry, int length) -{ - int idx = logThreadData.count; +void queryThread_log(char * entry, int length) { + int idx = logThreadData.count; - EnterSpinLock(&queryThreadLock); + EnterSpinLock(&queryThreadLock); - if (logThreadData.count++ != 0) - RECREATE(logThreadData.entry, char * , logThreadData.count); + if( logThreadData.count++ != 0 ) + RECREATE(logThreadData.entry, char* , logThreadData.count); - CREATE(logThreadData.entry[idx], char, length + 1); - safestrncpy(logThreadData.entry[idx], entry, length + 1); + CREATE(logThreadData.entry[idx], char, length + 1 ); + safestrncpy(logThreadData.entry[idx], entry, length + 1 ); - LeaveSpinLock(&queryThreadLock); + LeaveSpinLock(&queryThreadLock); - /* unlock the queryThread */ - racond_signal(queryThreadCond); + /* unlock the queryThread */ + racond_signal(queryThreadCond); } /* queryThread_main */ -static void *queryThread_main(void *x) -{ - Sql *queryThread_handle = Sql_Malloc(); - int i; +static void *queryThread_main(void *x) { + Sql *queryThread_handle = Sql_Malloc(); + int i; - if (SQL_ERROR == Sql_Connect(queryThread_handle, map_server_id, map_server_pw, map_server_ip, map_server_port, map_server_db)) - exit(EXIT_FAILURE); + if ( SQL_ERROR == Sql_Connect(queryThread_handle, map_server_id, map_server_pw, map_server_ip, map_server_port, map_server_db) ) + exit(EXIT_FAILURE); - if (strlen(default_codepage) > 0) - if (SQL_ERROR == Sql_SetEncoding(queryThread_handle, default_codepage)) - Sql_ShowDebug(queryThread_handle); + if( strlen(default_codepage) > 0 ) + if ( SQL_ERROR == Sql_SetEncoding(queryThread_handle, default_codepage) ) + Sql_ShowDebug(queryThread_handle); - if (log_config.sql_logs) { - logmysql_handle = Sql_Malloc(); + if( log_config.sql_logs ) { + logmysql_handle = Sql_Malloc(); - if (SQL_ERROR == Sql_Connect(logmysql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db_db)) - exit(EXIT_FAILURE); + if ( SQL_ERROR == Sql_Connect(logmysql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db_db) ) + exit(EXIT_FAILURE); - if (strlen(default_codepage) > 0) - if (SQL_ERROR == Sql_SetEncoding(logmysql_handle, default_codepage)) - Sql_ShowDebug(logmysql_handle); - } + if( strlen(default_codepage) > 0 ) + if ( SQL_ERROR == Sql_SetEncoding(logmysql_handle, default_codepage) ) + Sql_ShowDebug(logmysql_handle); + } - while (1) { + while( 1 ) { - if (queryThreadTerminate > 0) - break; + if(queryThreadTerminate > 0) + break; - EnterSpinLock(&queryThreadLock); + EnterSpinLock(&queryThreadLock); - /* mess with queryThreadData within the lock */ - for (i = 0; i < queryThreadData.count; i++) { - struct queryThreadEntry *entry = queryThreadData.entry[i]; + /* mess with queryThreadData within the lock */ + for( i = 0; i < queryThreadData.count; i++ ) { + struct queryThreadEntry *entry = queryThreadData.entry[i]; - if (entry->ok) - continue; - else if (!entry->st || !entry->st->stack) { - entry->ok = true;/* dispose */ - continue; - } + if( entry->ok ) + continue; + else if ( !entry->st || !entry->st->stack ) { + entry->ok = true;/* dispose */ + continue; + } - buildin_query_sql_sub(entry->st, entry->type ? logmysql_handle : queryThread_handle); + buildin_query_sql_sub(entry->st, entry->type ? logmysql_handle : queryThread_handle); - entry->ok = true;/* we're done with this */ - } + entry->ok = true;/* we're done with this */ + } - /* also check for any logs in need to be sent */ - if (log_config.sql_logs) { - for (i = 0; i < logThreadData.count; i++) { - if (SQL_ERROR == Sql_Query(logmysql_handle, logThreadData.entry[i])) - Sql_ShowDebug(logmysql_handle); - aFree(logThreadData.entry[i]); - } - logThreadData.count = 0; - } + /* also check for any logs in need to be sent */ + if( log_config.sql_logs ) { + for( i = 0; i < logThreadData.count; i++ ) { + if( SQL_ERROR == Sql_Query(logmysql_handle, logThreadData.entry[i]) ) + Sql_ShowDebug(logmysql_handle); + aFree(logThreadData.entry[i]); + } + logThreadData.count = 0; + } - LeaveSpinLock(&queryThreadLock); + LeaveSpinLock(&queryThreadLock); - ramutex_lock(queryThreadMutex); - racond_wait(queryThreadCond, queryThreadMutex, -1); - ramutex_unlock(queryThreadMutex); + ramutex_lock( queryThreadMutex ); + racond_wait( queryThreadCond, queryThreadMutex, -1 ); + ramutex_unlock( queryThreadMutex ); - } + } - Sql_Free(queryThread_handle); + Sql_Free(queryThread_handle); - if (log_config.sql_logs) { - Sql_Free(logmysql_handle); - } + if( log_config.sql_logs ) { + Sql_Free(logmysql_handle); + } - return NULL; + return NULL; } #endif /*========================================== * Destructor *------------------------------------------*/ -int do_final_script() -{ - int i; +int do_final_script() { + int i; #ifdef DEBUG_HASH - if (battle_config.etc_log) { - FILE *fp = fopen("hash_dump.txt","wt"); - if (fp) { - int count[SCRIPT_HASH_SIZE]; - int count2[SCRIPT_HASH_SIZE]; // number of buckets with a certain number of items - int n=0; - int min=INT_MAX,max=0,zero=0; - double mean=0.0f; - double median=0.0f; - - ShowNotice("Dumping script str hash information to hash_dump.txt\n"); - memset(count, 0, sizeof(count)); - fprintf(fp,"num : hash : data_name\n"); - fprintf(fp,"---------------------------------------------------------------\n"); - for (i=LABEL_START; i<str_num; i++) { - unsigned int h = calc_hash(get_str(i)); - fprintf(fp,"%04d : %4u : %s\n",i,h, get_str(i)); - ++count[h]; - } - fprintf(fp,"--------------------\n\n"); - memset(count2, 0, sizeof(count2)); - for (i=0; i<SCRIPT_HASH_SIZE; i++) { - fprintf(fp," hash %3d = %d\n",i,count[i]); - if (min > count[i]) - min = count[i]; // minimun count of collision - if (max < count[i]) - max = count[i]; // maximun count of collision - if (count[i] == 0) - zero++; - ++count2[count[i]]; - } - fprintf(fp,"\n--------------------\n items : buckets\n--------------------\n"); - for (i=min; i <= max; ++i) { - fprintf(fp," %5d : %7d\n",i,count2[i]); - mean += 1.0f*i*count2[i]/SCRIPT_HASH_SIZE; // Note: this will always result in <nr labels>/<nr buckets> - } - for (i=min; i <= max; ++i) { - n += count2[i]; - if (n*2 >= SCRIPT_HASH_SIZE) { - if (SCRIPT_HASH_SIZE%2 == 0 && SCRIPT_HASH_SIZE/2 == n) - median = (i+i+1)/2.0f; - else - median = i; - break; - } - } - fprintf(fp,"--------------------\n min = %d, max = %d, zero = %d\n mean = %lf, median = %lf\n",min,max,zero,mean,median); - fclose(fp); - } - } + if (battle_config.etc_log) + { + FILE *fp = fopen("hash_dump.txt","wt"); + if(fp) { + int count[SCRIPT_HASH_SIZE]; + int count2[SCRIPT_HASH_SIZE]; // number of buckets with a certain number of items + int n=0; + int min=INT_MAX,max=0,zero=0; + double mean=0.0f; + double median=0.0f; + + ShowNotice("Dumping script str hash information to hash_dump.txt\n"); + memset(count, 0, sizeof(count)); + fprintf(fp,"num : hash : data_name\n"); + fprintf(fp,"---------------------------------------------------------------\n"); + for(i=LABEL_START; i<str_num; i++) { + unsigned int h = calc_hash(get_str(i)); + fprintf(fp,"%04d : %4u : %s\n",i,h, get_str(i)); + ++count[h]; + } + fprintf(fp,"--------------------\n\n"); + memset(count2, 0, sizeof(count2)); + for(i=0; i<SCRIPT_HASH_SIZE; i++) { + fprintf(fp," hash %3d = %d\n",i,count[i]); + if(min > count[i]) + min = count[i]; // minimun count of collision + if(max < count[i]) + max = count[i]; // maximun count of collision + if(count[i] == 0) + zero++; + ++count2[count[i]]; + } + fprintf(fp,"\n--------------------\n items : buckets\n--------------------\n"); + for( i=min; i <= max; ++i ){ + fprintf(fp," %5d : %7d\n",i,count2[i]); + mean += 1.0f*i*count2[i]/SCRIPT_HASH_SIZE; // Note: this will always result in <nr labels>/<nr buckets> + } + for( i=min; i <= max; ++i ){ + n += count2[i]; + if( n*2 >= SCRIPT_HASH_SIZE ) + { + if( SCRIPT_HASH_SIZE%2 == 0 && SCRIPT_HASH_SIZE/2 == n ) + median = (i+i+1)/2.0f; + else + median = i; + break; + } + } + fprintf(fp,"--------------------\n min = %d, max = %d, zero = %d\n mean = %lf, median = %lf\n",min,max,zero,mean,median); + fclose(fp); + } + } #endif - mapreg_final(); - - db_destroy(scriptlabel_db); - userfunc_db->destroy(userfunc_db, db_script_free_code_sub); - autobonus_db->destroy(autobonus_db, db_script_free_code_sub); - if (sleep_db) { - struct linkdb_node *n = (struct linkdb_node *)sleep_db; - while (n) { - struct script_state *st = (struct script_state *)n->data; - script_free_state(st); - n = n->next; - } - linkdb_final(&sleep_db); - } + mapreg_final(); + + db_destroy(scriptlabel_db); + userfunc_db->destroy(userfunc_db, db_script_free_code_sub); + autobonus_db->destroy(autobonus_db, db_script_free_code_sub); + if(sleep_db) { + struct linkdb_node *n = (struct linkdb_node *)sleep_db; + while(n) { + struct script_state *st = (struct script_state *)n->data; + script_free_state(st); + n = n->next; + } + linkdb_final(&sleep_db); + } + + if (str_data) + aFree(str_data); + if (str_buf) + aFree(str_buf); + + for( i = 0; i < atcmd_binding_count; i++ ) { + aFree(atcmd_binding[i]); + } + + if( atcmd_binding_count != 0 ) + aFree(atcmd_binding); +#ifdef BETA_THREAD_TEST + /* QueryThread */ + InterlockedIncrement(&queryThreadTerminate); + racond_signal(queryThreadCond); + rathread_wait(queryThread, NULL); - if (str_data) - aFree(str_data); - if (str_buf) - aFree(str_buf); + // Destroy cond var and mutex. + racond_destroy( queryThreadCond ); + ramutex_destroy( queryThreadMutex ); - for (i = 0; i < atcmd_binding_count; i++) { - aFree(atcmd_binding[i]); - } - - if (atcmd_binding_count != 0) - aFree(atcmd_binding); -#ifdef BETA_THREAD_TEST - /* QueryThread */ - InterlockedIncrement(&queryThreadTerminate); - racond_signal(queryThreadCond); - rathread_wait(queryThread, NULL); - - // Destroy cond var and mutex. - racond_destroy(queryThreadCond); - ramutex_destroy(queryThreadMutex); - - /* Clear missing vars */ - for (i = 0; i < queryThreadData.count; i++) { - aFree(queryThreadData.entry[i]); - } + /* Clear missing vars */ + for( i = 0; i < queryThreadData.count; i++ ) { + aFree(queryThreadData.entry[i]); + } - aFree(queryThreadData.entry); + aFree(queryThreadData.entry); - for (i = 0; i < logThreadData.count; i++) { - aFree(logThreadData.entry[i]); - } + for( i = 0; i < logThreadData.count; i++ ) { + aFree(logThreadData.entry[i]); + } - aFree(logThreadData.entry); + aFree(logThreadData.entry); #endif - return 0; + return 0; } /*========================================== * Initialization *------------------------------------------*/ -int do_init_script() -{ - userfunc_db=strdb_alloc(DB_OPT_DUP_KEY,0); - scriptlabel_db=strdb_alloc(DB_OPT_DUP_KEY,50); - autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0); +int do_init_script() { + userfunc_db=strdb_alloc(DB_OPT_DUP_KEY,0); + scriptlabel_db=strdb_alloc(DB_OPT_DUP_KEY,50); + autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0); - mapreg_init(); + mapreg_init(); #ifdef BETA_THREAD_TEST - CREATE(queryThreadData.entry, struct queryThreadEntry *, 1); - queryThreadData.count = 0; - CREATE(logThreadData.entry, char *, 1); - logThreadData.count = 0; - /* QueryThread Start */ + CREATE(queryThreadData.entry, struct queryThreadEntry*, 1); + queryThreadData.count = 0; + CREATE(logThreadData.entry, char *, 1); + logThreadData.count = 0; + /* QueryThread Start */ - InitializeSpinLock(&queryThreadLock); + InitializeSpinLock(&queryThreadLock); - queryThreadData.timer = INVALID_TIMER; - queryThreadTerminate = 0; - queryThreadMutex = ramutex_create(); - queryThreadCond = racond_create(); + queryThreadData.timer = INVALID_TIMER; + queryThreadTerminate = 0; + queryThreadMutex = ramutex_create(); + queryThreadCond = racond_create(); - queryThread = rathread_create(queryThread_main, NULL); + queryThread = rathread_create(queryThread_main, NULL); - if (queryThread == NULL) { - ShowFatalError("do_init_script: cannot spawn Query Thread.\n"); - exit(EXIT_FAILURE); - } + if(queryThread == NULL){ + ShowFatalError("do_init_script: cannot spawn Query Thread.\n"); + exit(EXIT_FAILURE); + } - add_timer_func_list(queryThread_timer, "queryThread_timer"); + add_timer_func_list(queryThread_timer, "queryThread_timer"); #endif - return 0; + return 0; } -int script_reload() -{ - int i; +int script_reload() { + int i; #ifdef BETA_THREAD_TEST - /* we're reloading so any queries undergoing should be...exterminated. */ - EnterSpinLock(&queryThreadLock); + /* we're reloading so any queries undergoing should be...exterminated. */ + EnterSpinLock(&queryThreadLock); - for (i = 0; i < queryThreadData.count; i++) { - aFree(queryThreadData.entry[i]); - } - queryThreadData.count = 0; + for( i = 0; i < queryThreadData.count; i++ ) { + aFree(queryThreadData.entry[i]); + } + queryThreadData.count = 0; - if (queryThreadData.timer != INVALID_TIMER) { - delete_timer(queryThreadData.timer, queryThread_timer); - queryThreadData.timer = INVALID_TIMER; - } + if( queryThreadData.timer != INVALID_TIMER ) { + delete_timer(queryThreadData.timer, queryThread_timer); + queryThreadData.timer = INVALID_TIMER; + } - LeaveSpinLock(&queryThreadLock); + LeaveSpinLock(&queryThreadLock); #endif - userfunc_db->clear(userfunc_db, db_script_free_code_sub); - db_clear(scriptlabel_db); + userfunc_db->clear(userfunc_db, db_script_free_code_sub); + db_clear(scriptlabel_db); - // @commands (script based) - // Clear bindings - for (i = 0; i < atcmd_binding_count; i++) { - aFree(atcmd_binding[i]); - } + // @commands (script based) + // Clear bindings + for( i = 0; i < atcmd_binding_count; i++ ) { + aFree(atcmd_binding[i]); + } - if (atcmd_binding_count != 0) - aFree(atcmd_binding); + if( atcmd_binding_count != 0 ) + aFree(atcmd_binding); - atcmd_binding_count = 0; + atcmd_binding_count = 0; - if (sleep_db) { - struct linkdb_node *n = (struct linkdb_node *)sleep_db; - while (n) { - struct script_state *st = (struct script_state *)n->data; - script_free_state(st); - n = n->next; - } - linkdb_final(&sleep_db); - } - mapreg_reload(); - return 0; + if(sleep_db) { + struct linkdb_node *n = (struct linkdb_node *)sleep_db; + while(n) { + struct script_state *st = (struct script_state *)n->data; + script_free_state(st); + n = n->next; + } + linkdb_final(&sleep_db); + } + mapreg_reload(); + return 0; } //----------------------------------------------------------------------------- @@ -4281,24 +4344,26 @@ int script_reload() /// mes "<message>"; BUILDIN_FUNC(mes) { - TBL_PC *sd = script_rid2sd(st); - if (sd == NULL) - return 0; + TBL_PC* sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - if (!script_hasdata(st, 3)) { - // only a single line detected in the script - clif_scriptmes(sd, st->oid, script_getstr(st, 2)); - } else { - // parse multiple lines as they exist - int i; + if( !script_hasdata(st, 3) ) + {// only a single line detected in the script + clif_scriptmes(sd, st->oid, script_getstr(st, 2)); + } + else + {// parse multiple lines as they exist + int i; - for (i = 2; script_hasdata(st, i); i++) { - // send the message to the client - clif_scriptmes(sd, st->oid, script_getstr(st, i)); - } - } + for( i = 2; script_hasdata(st, i); i++ ) + { + // send the message to the client + clif_scriptmes(sd, st->oid, script_getstr(st, i)); + } + } - return 0; + return 0; } /// Displays the button 'next' in the npc dialog. @@ -4307,15 +4372,15 @@ BUILDIN_FUNC(mes) /// next; BUILDIN_FUNC(next) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - st->state = STOP; - clif_scriptnext(sd, st->oid); - return 0; + st->state = STOP; + clif_scriptnext(sd, st->oid); + return 0; } /// Ends the script and displays the button 'close' on the npc dialog. @@ -4324,15 +4389,15 @@ BUILDIN_FUNC(next) /// close; BUILDIN_FUNC(close) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - st->state = END; - clif_scriptclose(sd, st->oid); - return 0; + st->state = END; + clif_scriptclose(sd, st->oid); + return 0; } /// Displays the button 'close' on the npc dialog. @@ -4341,48 +4406,51 @@ BUILDIN_FUNC(close) /// close2; BUILDIN_FUNC(close2) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - st->state = STOP; - clif_scriptclose(sd, st->oid); - return 0; + st->state = STOP; + clif_scriptclose(sd, st->oid); + return 0; } /// Counts the number of valid and total number of options in 'str' /// If max_count > 0 the counting stops when that valid option is reached /// total is incremented for each option (NULL is supported) -static int menu_countoptions(const char *str, int max_count, int *total) -{ - int count = 0; - int bogus_total; - - if (total == NULL) - total = &bogus_total; - ++(*total); - - // initial empty options - while (*str == ':') { - ++str; - ++(*total); - } - // count menu options - while (*str != '\0') { - ++count; - --max_count; - if (max_count == 0) - break; - while (*str != ':' && *str != '\0') - ++str; - while (*str == ':') { - ++str; - ++(*total); - } - } - return count; +static int menu_countoptions(const char* str, int max_count, int* total) +{ + int count = 0; + int bogus_total; + + if( total == NULL ) + total = &bogus_total; + ++(*total); + + // initial empty options + while( *str == ':' ) + { + ++str; + ++(*total); + } + // count menu options + while( *str != '\0' ) + { + ++count; + --max_count; + if( max_count == 0 ) + break; + while( *str != ':' && *str != '\0' ) + ++str; + while( *str == ':' ) + { + ++str; + ++(*total); + } + } + return count; } /// Displays a menu with options and goes to the target label. @@ -4403,115 +4471,121 @@ static int menu_countoptions(const char *str, int max_count, int *total) /// menu "<option_text>",<target_label>{,"<option_text>",<target_label>,...}; BUILDIN_FUNC(menu) { - int i; - const char *text; - TBL_PC *sd; - - sd = script_rid2sd(st); - if (sd == NULL) - return 0; - - // TODO detect multiple scripts waiting for input at the same time, and what to do when that happens - if (sd->state.menu_or_input == 0) { - struct StringBuf buf; - struct script_data *data; - - if (script_lastdata(st) % 2 == 0) { - // argument count is not even (1st argument is at index 2) - ShowError("script:menu: illegal number of arguments (%d).\n", (script_lastdata(st) - 1)); - st->state = END; - return 1; - } - - StringBuf_Init(&buf); - sd->npc_menu = 0; - for (i = 2; i < script_lastdata(st); i += 2) { - // menu options - text = script_getstr(st, i); - - // target label - data = script_getdata(st, i+1); - if (!data_islabel(data)) { - // not a label - StringBuf_Destroy(&buf); - ShowError("script:menu: argument #%d (from 1) is not a label or label not found.\n", i); - script_reportdata(data); - st->state = END; - return 1; - } - - // append option(s) - if (text[0] == '\0') - continue;// empty string, ignore - if (sd->npc_menu > 0) - StringBuf_AppendStr(&buf, ":"); - StringBuf_AppendStr(&buf, text); - sd->npc_menu += menu_countoptions(text, 0, NULL); - } - st->state = RERUNLINE; - sd->state.menu_or_input = 1; - - /** - * menus beyond this length crash the client (see bugreport:6402) - **/ - if (StringBuf_Length(&buf) >= 2047) { - struct npc_data *nd = map_id2nd(st->oid); - char *menu; - CREATE(menu, char, 2048); - safestrncpy(menu, StringBuf_Value(&buf), 2047); - ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf)); - clif_scriptmenu(sd, st->oid, menu); - aFree(menu); - } else - clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf)); - - StringBuf_Destroy(&buf); - - if (sd->npc_menu >= 0xff) { - // client supports only up to 254 entries; 0 is not used and 255 is reserved for cancel; excess entries are displayed but cause 'uint8' overflow - ShowWarning("buildin_menu: Too many options specified (current=%d, max=254).\n", sd->npc_menu); - script_reportsrc(st); - } - } else if (sd->npc_menu == 0xff) { - // Cancel was pressed - sd->state.menu_or_input = 0; - st->state = END; - } else { - // goto target label - int menu = 0; - - sd->state.menu_or_input = 0; - if (sd->npc_menu <= 0) { - ShowDebug("script:menu: unexpected selection (%d)\n", sd->npc_menu); - st->state = END; - return 1; - } - - // get target label - for (i = 2; i < script_lastdata(st); i += 2) { - text = script_getstr(st, i); - sd->npc_menu -= menu_countoptions(text, sd->npc_menu, &menu); - if (sd->npc_menu <= 0) - break;// entry found - } - if (sd->npc_menu > 0) { - // Invalid selection - ShowDebug("script:menu: selection is out of range (%d pairs are missing?) - please report this\n", sd->npc_menu); - st->state = END; - return 1; - } - if (!data_islabel(script_getdata(st, i + 1))) { - // TODO remove this temporary crash-prevention code (fallback for multiple scripts requesting user input) - ShowError("script:menu: unexpected data in label argument\n"); - script_reportdata(script_getdata(st, i + 1)); - st->state = END; - return 1; - } - pc_setreg(sd, add_str("@menu"), menu); - st->pos = script_getnum(st, i + 1); - st->state = GOTO; - } - return 0; + int i; + const char* text; + TBL_PC* sd; + + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; + + // TODO detect multiple scripts waiting for input at the same time, and what to do when that happens + if( sd->state.menu_or_input == 0 ) + { + struct StringBuf buf; + struct script_data* data; + + if( script_lastdata(st) % 2 == 0 ) + {// argument count is not even (1st argument is at index 2) + ShowError("script:menu: illegal number of arguments (%d).\n", (script_lastdata(st) - 1)); + st->state = END; + return 1; + } + + StringBuf_Init(&buf); + sd->npc_menu = 0; + for( i = 2; i < script_lastdata(st); i += 2 ) + { + // menu options + text = script_getstr(st, i); + + // target label + data = script_getdata(st, i+1); + if( !data_islabel(data) ) + {// not a label + StringBuf_Destroy(&buf); + ShowError("script:menu: argument #%d (from 1) is not a label or label not found.\n", i); + script_reportdata(data); + st->state = END; + return 1; + } + + // append option(s) + if( text[0] == '\0' ) + continue;// empty string, ignore + if( sd->npc_menu > 0 ) + StringBuf_AppendStr(&buf, ":"); + StringBuf_AppendStr(&buf, text); + sd->npc_menu += menu_countoptions(text, 0, NULL); + } + st->state = RERUNLINE; + sd->state.menu_or_input = 1; + + /** + * menus beyond this length crash the client (see bugreport:6402) + **/ + if( StringBuf_Length(&buf) >= 2047 ) { + struct npc_data * nd = map_id2nd(st->oid); + char* menu; + CREATE(menu, char, 2048); + safestrncpy(menu, StringBuf_Value(&buf), 2047); + ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf)); + clif_scriptmenu(sd, st->oid, menu); + aFree(menu); + } else + clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf)); + + StringBuf_Destroy(&buf); + + if( sd->npc_menu >= 0xff ) + {// client supports only up to 254 entries; 0 is not used and 255 is reserved for cancel; excess entries are displayed but cause 'uint8' overflow + ShowWarning("buildin_menu: Too many options specified (current=%d, max=254).\n", sd->npc_menu); + script_reportsrc(st); + } + } + else if( sd->npc_menu == 0xff ) + {// Cancel was pressed + sd->state.menu_or_input = 0; + st->state = END; + } + else + {// goto target label + int menu = 0; + + sd->state.menu_or_input = 0; + if( sd->npc_menu <= 0 ) + { + ShowDebug("script:menu: unexpected selection (%d)\n", sd->npc_menu); + st->state = END; + return 1; + } + + // get target label + for( i = 2; i < script_lastdata(st); i += 2 ) + { + text = script_getstr(st, i); + sd->npc_menu -= menu_countoptions(text, sd->npc_menu, &menu); + if( sd->npc_menu <= 0 ) + break;// entry found + } + if( sd->npc_menu > 0 ) + {// Invalid selection + ShowDebug("script:menu: selection is out of range (%d pairs are missing?) - please report this\n", sd->npc_menu); + st->state = END; + return 1; + } + if( !data_islabel(script_getdata(st, i + 1)) ) + {// TODO remove this temporary crash-prevention code (fallback for multiple scripts requesting user input) + ShowError("script:menu: unexpected data in label argument\n"); + script_reportdata(script_getdata(st, i + 1)); + st->state = END; + return 1; + } + pc_setreg(sd, add_str("@menu"), menu); + st->pos = script_getnum(st, i + 1); + st->state = GOTO; + } + return 0; } /// Displays a menu with options and returns the selected option. @@ -4522,69 +4596,69 @@ BUILDIN_FUNC(menu) /// @see menu BUILDIN_FUNC(select) { - int i; - const char *text; - TBL_PC *sd; - - sd = script_rid2sd(st); - if (sd == NULL) - return 0; - - if (sd->state.menu_or_input == 0) { - struct StringBuf buf; - - StringBuf_Init(&buf); - sd->npc_menu = 0; - for (i = 2; i <= script_lastdata(st); ++i) { - text = script_getstr(st, i); - - if (sd->npc_menu > 0) - StringBuf_AppendStr(&buf, ":"); - - StringBuf_AppendStr(&buf, text); - sd->npc_menu += menu_countoptions(text, 0, NULL); - } - - st->state = RERUNLINE; - sd->state.menu_or_input = 1; - - /** - * menus beyond this length crash the client (see bugreport:6402) - **/ - if (StringBuf_Length(&buf) >= 2047) { - struct npc_data *nd = map_id2nd(st->oid); - char *menu; - CREATE(menu, char, 2048); - safestrncpy(menu, StringBuf_Value(&buf), 2047); - ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf)); - clif_scriptmenu(sd, st->oid, menu); - aFree(menu); - } else - clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf)); - StringBuf_Destroy(&buf); - - if (sd->npc_menu >= 0xff) { - ShowWarning("buildin_select: Too many options specified (current=%d, max=254).\n", sd->npc_menu); - script_reportsrc(st); - } - } else if (sd->npc_menu == 0xff) { // Cancel was pressed - sd->state.menu_or_input = 0; - st->state = END; - } else {// return selected option - int menu = 0; - - sd->state.menu_or_input = 0; - for (i = 2; i <= script_lastdata(st); ++i) { - text = script_getstr(st, i); - sd->npc_menu -= menu_countoptions(text, sd->npc_menu, &menu); - if (sd->npc_menu <= 0) - break;// entry found - } - pc_setreg(sd, add_str("@menu"), menu); - script_pushint(st, menu); - st->state = RUN; - } - return 0; + int i; + const char* text; + TBL_PC* sd; + + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; + + if( sd->state.menu_or_input == 0 ) { + struct StringBuf buf; + + StringBuf_Init(&buf); + sd->npc_menu = 0; + for( i = 2; i <= script_lastdata(st); ++i ) { + text = script_getstr(st, i); + + if( sd->npc_menu > 0 ) + StringBuf_AppendStr(&buf, ":"); + + StringBuf_AppendStr(&buf, text); + sd->npc_menu += menu_countoptions(text, 0, NULL); + } + + st->state = RERUNLINE; + sd->state.menu_or_input = 1; + + /** + * menus beyond this length crash the client (see bugreport:6402) + **/ + if( StringBuf_Length(&buf) >= 2047 ) { + struct npc_data * nd = map_id2nd(st->oid); + char* menu; + CREATE(menu, char, 2048); + safestrncpy(menu, StringBuf_Value(&buf), 2047); + ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf)); + clif_scriptmenu(sd, st->oid, menu); + aFree(menu); + } else + clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf)); + StringBuf_Destroy(&buf); + + if( sd->npc_menu >= 0xff ) { + ShowWarning("buildin_select: Too many options specified (current=%d, max=254).\n", sd->npc_menu); + script_reportsrc(st); + } + } else if( sd->npc_menu == 0xff ) {// Cancel was pressed + sd->state.menu_or_input = 0; + st->state = END; + } else {// return selected option + int menu = 0; + + sd->state.menu_or_input = 0; + for( i = 2; i <= script_lastdata(st); ++i ) { + text = script_getstr(st, i); + sd->npc_menu -= menu_countoptions(text, sd->npc_menu, &menu); + if( sd->npc_menu <= 0 ) + break;// entry found + } + pc_setreg(sd, add_str("@menu"), menu); + script_pushint(st, menu); + st->state = RUN; + } + return 0; } /// Displays a menu with options and returns the selected option. @@ -4597,71 +4671,77 @@ BUILDIN_FUNC(select) /// @see menu BUILDIN_FUNC(prompt) { - int i; - const char *text; - TBL_PC *sd; - - sd = script_rid2sd(st); - if (sd == NULL) - return 0; - - if (sd->state.menu_or_input == 0) { - struct StringBuf buf; - - StringBuf_Init(&buf); - sd->npc_menu = 0; - for (i = 2; i <= script_lastdata(st); ++i) { - text = script_getstr(st, i); - if (sd->npc_menu > 0) - StringBuf_AppendStr(&buf, ":"); - StringBuf_AppendStr(&buf, text); - sd->npc_menu += menu_countoptions(text, 0, NULL); - } - - st->state = RERUNLINE; - sd->state.menu_or_input = 1; - - /** - * menus beyond this length crash the client (see bugreport:6402) - **/ - if (StringBuf_Length(&buf) >= 2047) { - struct npc_data *nd = map_id2nd(st->oid); - char *menu; - CREATE(menu, char, 2048); - safestrncpy(menu, StringBuf_Value(&buf), 2047); - ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf)); - clif_scriptmenu(sd, st->oid, menu); - aFree(menu); - } else - clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf)); - StringBuf_Destroy(&buf); - - if (sd->npc_menu >= 0xff) { - ShowWarning("buildin_prompt: Too many options specified (current=%d, max=254).\n", sd->npc_menu); - script_reportsrc(st); - } - } else if (sd->npc_menu == 0xff) { - // Cancel was pressed - sd->state.menu_or_input = 0; - pc_setreg(sd, add_str("@menu"), 0xff); - script_pushint(st, 0xff); - st->state = RUN; - } else { - // return selected option - int menu = 0; - - sd->state.menu_or_input = 0; - for (i = 2; i <= script_lastdata(st); ++i) { - text = script_getstr(st, i); - sd->npc_menu -= menu_countoptions(text, sd->npc_menu, &menu); - if (sd->npc_menu <= 0) - break;// entry found - } - pc_setreg(sd, add_str("@menu"), menu); - script_pushint(st, menu); - st->state = RUN; - } - return 0; + int i; + const char *text; + TBL_PC* sd; + + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; + + if( sd->state.menu_or_input == 0 ) + { + struct StringBuf buf; + + StringBuf_Init(&buf); + sd->npc_menu = 0; + for( i = 2; i <= script_lastdata(st); ++i ) + { + text = script_getstr(st, i); + if( sd->npc_menu > 0 ) + StringBuf_AppendStr(&buf, ":"); + StringBuf_AppendStr(&buf, text); + sd->npc_menu += menu_countoptions(text, 0, NULL); + } + + st->state = RERUNLINE; + sd->state.menu_or_input = 1; + + /** + * menus beyond this length crash the client (see bugreport:6402) + **/ + if( StringBuf_Length(&buf) >= 2047 ) { + struct npc_data * nd = map_id2nd(st->oid); + char* menu; + CREATE(menu, char, 2048); + safestrncpy(menu, StringBuf_Value(&buf), 2047); + ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf)); + clif_scriptmenu(sd, st->oid, menu); + aFree(menu); + } else + clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf)); + StringBuf_Destroy(&buf); + + if( sd->npc_menu >= 0xff ) + { + ShowWarning("buildin_prompt: Too many options specified (current=%d, max=254).\n", sd->npc_menu); + script_reportsrc(st); + } + } + else if( sd->npc_menu == 0xff ) + {// Cancel was pressed + sd->state.menu_or_input = 0; + pc_setreg(sd, add_str("@menu"), 0xff); + script_pushint(st, 0xff); + st->state = RUN; + } + else + {// return selected option + int menu = 0; + + sd->state.menu_or_input = 0; + for( i = 2; i <= script_lastdata(st); ++i ) + { + text = script_getstr(st, i); + sd->npc_menu -= menu_countoptions(text, sd->npc_menu, &menu); + if( sd->npc_menu <= 0 ) + break;// entry found + } + pc_setreg(sd, add_str("@menu"), menu); + script_pushint(st, menu); + st->state = RUN; + } + return 0; } ///////////////////////////////////////////////////////////////////// @@ -4673,16 +4753,17 @@ BUILDIN_FUNC(prompt) /// goto <label>; BUILDIN_FUNC(goto) { - if (!data_islabel(script_getdata(st,2))) { - ShowError("script:goto: not a label\n"); - script_reportdata(script_getdata(st,2)); - st->state = END; - return 1; - } + if( !data_islabel(script_getdata(st,2)) ) + { + ShowError("script:goto: not a label\n"); + script_reportdata(script_getdata(st,2)); + st->state = END; + return 1; + } - st->pos = script_getnum(st,2); - st->state = GOTO; - return 0; + st->pos = script_getnum(st,2); + st->state = GOTO; + return 0; } /*========================================== @@ -4690,94 +4771,100 @@ BUILDIN_FUNC(goto) *------------------------------------------*/ BUILDIN_FUNC(callfunc) { - int i, j; - struct script_retinfo *ri; - struct script_code *scr; - const char *str = script_getstr(st,2); - DBMap **ref = NULL; - - scr = (struct script_code *)strdb_get(userfunc_db, str); - if (!scr) { - ShowError("script:callfunc: function not found! [%s]\n", str); - st->state = END; - return 1; - } - - for (i = st->start+3, j = 0; i < st->end; i++, j++) { - struct script_data *data = push_copy(st->stack,i); - if (data_isreference(data) && !data->ref) { - const char *name = reference_getname(data); - if (name[0] == '.') { - if (!ref) { - ref = (struct DBMap **)aCalloc(sizeof(struct DBMap *), 1); - ref[0] = (name[1] == '@' ? st->stack->var_function : st->script->script_vars); - } - data->ref = ref; - } - } - } - - CREATE(ri, struct script_retinfo, 1); - ri->script = st->script;// script code - ri->var_function = st->stack->var_function;// scope variables - ri->pos = st->pos;// script location - ri->nargs = j;// argument count - ri->defsp = st->stack->defsp;// default stack pointer - push_retinfo(st->stack, ri, ref); - - st->pos = 0; - st->script = scr; - st->stack->defsp = st->stack->sp; - st->state = GOTO; - st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA); - - return 0; + int i, j; + struct script_retinfo* ri; + struct script_code* scr; + const char* str = script_getstr(st,2); + DBMap **ref = NULL; + + scr = (struct script_code*)strdb_get(userfunc_db, str); + if( !scr ) + { + ShowError("script:callfunc: function not found! [%s]\n", str); + st->state = END; + return 1; + } + + for( i = st->start+3, j = 0; i < st->end; i++, j++ ) + { + struct script_data* data = push_copy(st->stack,i); + if( data_isreference(data) && !data->ref ) + { + const char* name = reference_getname(data); + if( name[0] == '.' ) { + if ( !ref ) { + ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 1); + ref[0] = (name[1] == '@' ? st->stack->var_function : st->script->script_vars); + } + data->ref = ref; + } + } + } + + CREATE(ri, struct script_retinfo, 1); + ri->script = st->script;// script code + ri->var_function = st->stack->var_function;// scope variables + ri->pos = st->pos;// script location + ri->nargs = j;// argument count + ri->defsp = st->stack->defsp;// default stack pointer + push_retinfo(st->stack, ri, ref); + + st->pos = 0; + st->script = scr; + st->stack->defsp = st->stack->sp; + st->state = GOTO; + st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA); + + return 0; } /*========================================== * subroutine call *------------------------------------------*/ BUILDIN_FUNC(callsub) { - int i,j; - struct script_retinfo *ri; - int pos = script_getnum(st,2); - DBMap **ref = NULL; - - if (!data_islabel(script_getdata(st,2)) && !data_isfunclabel(script_getdata(st,2))) { - ShowError("script:callsub: argument is not a label\n"); - script_reportdata(script_getdata(st,2)); - st->state = END; - return 1; - } - - for (i = st->start+3, j = 0; i < st->end; i++, j++) { - struct script_data *data = push_copy(st->stack,i); - if (data_isreference(data) && !data->ref) { - const char *name = reference_getname(data); - if (name[0] == '.' && name[1] == '@') { - if (!ref) { - ref = (struct DBMap **)aCalloc(sizeof(struct DBMap *), 1); - ref[0] = st->stack->var_function; - } - data->ref = ref; - } - } - } - - CREATE(ri, struct script_retinfo, 1); - ri->script = st->script;// script code - ri->var_function = st->stack->var_function;// scope variables - ri->pos = st->pos;// script location - ri->nargs = j;// argument count - ri->defsp = st->stack->defsp;// default stack pointer - push_retinfo(st->stack, ri, ref); - - st->pos = pos; - st->stack->defsp = st->stack->sp; - st->state = GOTO; - st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA); - - return 0; + int i,j; + struct script_retinfo* ri; + int pos = script_getnum(st,2); + DBMap **ref = NULL; + + if( !data_islabel(script_getdata(st,2)) && !data_isfunclabel(script_getdata(st,2)) ) + { + ShowError("script:callsub: argument is not a label\n"); + script_reportdata(script_getdata(st,2)); + st->state = END; + return 1; + } + + for( i = st->start+3, j = 0; i < st->end; i++, j++ ) + { + struct script_data* data = push_copy(st->stack,i); + if( data_isreference(data) && !data->ref ) + { + const char* name = reference_getname(data); + if( name[0] == '.' && name[1] == '@' ) { + if ( !ref ) { + ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 1); + ref[0] = st->stack->var_function; + } + data->ref = ref; + } + } + } + + CREATE(ri, struct script_retinfo, 1); + ri->script = st->script;// script code + ri->var_function = st->stack->var_function;// scope variables + ri->pos = st->pos;// script location + ri->nargs = j;// argument count + ri->defsp = st->stack->defsp;// default stack pointer + push_retinfo(st->stack, ri, ref); + + st->pos = pos; + st->stack->defsp = st->stack->sp; + st->state = GOTO; + st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA); + + return 0; } /// Retrieves an argument provided to callfunc/callsub. @@ -4786,29 +4873,31 @@ BUILDIN_FUNC(callsub) /// getarg(<index>{,<default_value>}) -> <value> BUILDIN_FUNC(getarg) { - struct script_retinfo *ri; - int idx; + struct script_retinfo* ri; + int idx; - if (st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO) { - ShowError("script:getarg: no callfunc or callsub!\n"); - st->state = END; - return 1; - } - ri = st->stack->stack_data[st->stack->defsp - 1].u.ri; - - idx = script_getnum(st,2); - - if (idx >= 0 && idx < ri->nargs) - push_copy(st->stack, st->stack->defsp - 1 - ri->nargs + idx); - else if (script_hasdata(st,3)) - script_pushcopy(st, 3); - else { - ShowError("script:getarg: index (idx=%d) out of range (nargs=%d) and no default value found\n", idx, ri->nargs); - st->state = END; - return 1; - } + if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO ) + { + ShowError("script:getarg: no callfunc or callsub!\n"); + st->state = END; + return 1; + } + ri = st->stack->stack_data[st->stack->defsp - 1].u.ri; - return 0; + idx = script_getnum(st,2); + + if( idx >= 0 && idx < ri->nargs ) + push_copy(st->stack, st->stack->defsp - 1 - ri->nargs + idx); + else if( script_hasdata(st,3) ) + script_pushcopy(st, 3); + else + { + ShowError("script:getarg: index (idx=%d) out of range (nargs=%d) and no default value found\n", idx, ri->nargs); + st->state = END; + return 1; + } + + return 0; } /// Returns from the current function, optionaly returning a value from the functions. @@ -4818,28 +4907,31 @@ BUILDIN_FUNC(getarg) /// return <value>; BUILDIN_FUNC(return) { - if (script_hasdata(st,2)) { - // return value - struct script_data *data; - script_pushcopy(st, 2); - data = script_getdatatop(st, -1); - if (data_isreference(data)) { - const char *name = reference_getname(data); - if (name[0] == '.' && name[1] == '@') { - // scope variable - if (!data->ref || data->ref == (DBMap **)&st->stack->var_function) - get_val(st, data);// current scope, convert to value - } else if (name[0] == '.' && !data->ref) { - // script variable, link to current script - data->ref = &st->script->script_vars; - } - } - } else { - // no return value - script_pushnil(st); - } - st->state = RETFUNC; - return 0; + if( script_hasdata(st,2) ) + {// return value + struct script_data* data; + script_pushcopy(st, 2); + data = script_getdatatop(st, -1); + if( data_isreference(data) ) + { + const char* name = reference_getname(data); + if( name[0] == '.' && name[1] == '@' ) + {// scope variable + if( !data->ref || data->ref == (DBMap**)&st->stack->var_function ) + get_val(st, data);// current scope, convert to value + } + else if( name[0] == '.' && !data->ref ) + {// script variable, link to current script + data->ref = &st->script->script_vars; + } + } + } + else + {// no return value + script_pushnil(st); + } + st->state = RETFUNC; + return 0; } /// Returns a random number from 0 to <range>-1. @@ -4849,28 +4941,29 @@ BUILDIN_FUNC(return) /// rand(<min>,<max>) -> <int> BUILDIN_FUNC(rand) { - int range; - int min; - int max; - - if (script_hasdata(st,3)) { - // min,max - min = script_getnum(st,2); - max = script_getnum(st,3); - if (max < min) - swap(min, max); - range = max - min + 1; - } else { - // range - min = 0; - range = script_getnum(st,2); - } - if (range <= 1) - script_pushint(st, min); - else - script_pushint(st, rnd()%range + min); - - return 0; + int range; + int min; + int max; + + if( script_hasdata(st,3) ) + {// min,max + min = script_getnum(st,2); + max = script_getnum(st,3); + if( max < min ) + swap(min, max); + range = max - min + 1; + } + else + {// range + min = 0; + range = script_getnum(st,2); + } + if( range <= 1 ) + script_pushint(st, min); + else + script_pushint(st, rnd()%range + min); + + return 0; } /*========================================== @@ -4878,105 +4971,106 @@ BUILDIN_FUNC(rand) *------------------------------------------*/ BUILDIN_FUNC(warp) { - int ret; - int x,y; - const char *str; - TBL_PC *sd; + int ret; + int x,y; + const char* str; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - str = script_getstr(st,2); - x = script_getnum(st,3); - y = script_getnum(st,4); + str = script_getstr(st,2); + x = script_getnum(st,3); + y = script_getnum(st,4); - if (strcmp(str,"Random")==0) - ret = pc_randomwarp(sd,CLR_TELEPORT); - else if (strcmp(str,"SavePoint")==0 || strcmp(str,"Save")==0) - ret = pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - else - ret = pc_setpos(sd,mapindex_name2id(str),x,y,CLR_OUTSIGHT); + if(strcmp(str,"Random")==0) + ret = pc_randomwarp(sd,CLR_TELEPORT); + else if(strcmp(str,"SavePoint")==0 || strcmp(str,"Save")==0) + ret = pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + else + ret = pc_setpos(sd,mapindex_name2id(str),x,y,CLR_OUTSIGHT); - if (ret) { - ShowError("buildin_warp: moving player '%s' to \"%s\",%d,%d failed.\n", sd->status.name, str, x, y); - script_reportsrc(st); - } + if( ret ) { + ShowError("buildin_warp: moving player '%s' to \"%s\",%d,%d failed.\n", sd->status.name, str, x, y); + script_reportsrc(st); + } - return 0; + return 0; } /*========================================== * Warp a specified area *------------------------------------------*/ static int buildin_areawarp_sub(struct block_list *bl,va_list ap) { - int x2,y2,x3,y3; - unsigned int index; - - index = va_arg(ap,unsigned int); - x2 = va_arg(ap,int); - y2 = va_arg(ap,int); - x3 = va_arg(ap,int); - y3 = va_arg(ap,int); - - if (index == 0) - pc_randomwarp((TBL_PC *)bl,CLR_TELEPORT); - else if (x3 && y3) { - int max, tx, ty, j = 0; - - // choose a suitable max number of attempts - if ((max = (y3-y2+1)*(x3-x2+1)*3) > 1000) - max = 1000; - - // find a suitable map cell - do { - tx = rnd()%(x3-x2+1)+x2; - ty = rnd()%(y3-y2+1)+y2; - j++; - } while (map_getcell(index,tx,ty,CELL_CHKNOPASS) && j < max); - - pc_setpos((TBL_PC *)bl,index,tx,ty,CLR_OUTSIGHT); - } else - pc_setpos((TBL_PC *)bl,index,x2,y2,CLR_OUTSIGHT); - return 0; + int x2,y2,x3,y3; + unsigned int index; + + index = va_arg(ap,unsigned int); + x2 = va_arg(ap,int); + y2 = va_arg(ap,int); + x3 = va_arg(ap,int); + y3 = va_arg(ap,int); + + if(index == 0) + pc_randomwarp((TBL_PC *)bl,CLR_TELEPORT); + else if(x3 && y3) { + int max, tx, ty, j = 0; + + // choose a suitable max number of attempts + if( (max = (y3-y2+1)*(x3-x2+1)*3) > 1000 ) + max = 1000; + + // find a suitable map cell + do { + tx = rnd()%(x3-x2+1)+x2; + ty = rnd()%(y3-y2+1)+y2; + j++; + } while( map_getcell(index,tx,ty,CELL_CHKNOPASS) && j < max ); + + pc_setpos((TBL_PC *)bl,index,tx,ty,CLR_OUTSIGHT); + } + else + pc_setpos((TBL_PC *)bl,index,x2,y2,CLR_OUTSIGHT); + return 0; } BUILDIN_FUNC(areawarp) { - int m, x0,y0,x1,y1, x2,y2,x3=0,y3=0; - unsigned int index; - const char *str; - const char *mapname; - - mapname = script_getstr(st,2); - x0 = script_getnum(st,3); - y0 = script_getnum(st,4); - x1 = script_getnum(st,5); - y1 = script_getnum(st,6); - str = script_getstr(st,7); - x2 = script_getnum(st,8); - y2 = script_getnum(st,9); - - if (script_hasdata(st,10) && script_hasdata(st,11)) { // Warp area to area - if ((x3 = script_getnum(st,10)) < 0 || (y3 = script_getnum(st,11)) < 0) { - x3 = 0; - y3 = 0; - } else if (x3 && y3) { - // normalize x3/y3 coordinates - if (x3 < x2) swap(x3,x2); - if (y3 < y2) swap(y3,y2); - } - } - - if ((m = map_mapname2mapid(mapname)) < 0) - return 0; - - if (strcmp(str,"Random") == 0) - index = 0; - else if (!(index=mapindex_name2id(str))) - return 0; - - map_foreachinarea(buildin_areawarp_sub, m,x0,y0,x1,y1, BL_PC, index,x2,y2,x3,y3); - return 0; + int m, x0,y0,x1,y1, x2,y2,x3=0,y3=0; + unsigned int index; + const char *str; + const char *mapname; + + mapname = script_getstr(st,2); + x0 = script_getnum(st,3); + y0 = script_getnum(st,4); + x1 = script_getnum(st,5); + y1 = script_getnum(st,6); + str = script_getstr(st,7); + x2 = script_getnum(st,8); + y2 = script_getnum(st,9); + + if( script_hasdata(st,10) && script_hasdata(st,11) ) { // Warp area to area + if( (x3 = script_getnum(st,10)) < 0 || (y3 = script_getnum(st,11)) < 0 ){ + x3 = 0; + y3 = 0; + } else if( x3 && y3 ) { + // normalize x3/y3 coordinates + if( x3 < x2 ) swap(x3,x2); + if( y3 < y2 ) swap(y3,y2); + } + } + + if( (m = map_mapname2mapid(mapname)) < 0 ) + return 0; + + if( strcmp(str,"Random") == 0 ) + index = 0; + else if( !(index=mapindex_name2id(str)) ) + return 0; + + map_foreachinarea(buildin_areawarp_sub, m,x0,y0,x1,y1, BL_PC, index,x2,y2,x3,y3); + return 0; } /*========================================== @@ -4984,31 +5078,31 @@ BUILDIN_FUNC(areawarp) *------------------------------------------*/ static int buildin_areapercentheal_sub(struct block_list *bl,va_list ap) { - int hp, sp; - hp = va_arg(ap, int); - sp = va_arg(ap, int); - pc_percentheal((TBL_PC *)bl,hp,sp); - return 0; + int hp, sp; + hp = va_arg(ap, int); + sp = va_arg(ap, int); + pc_percentheal((TBL_PC *)bl,hp,sp); + return 0; } BUILDIN_FUNC(areapercentheal) { - int hp,sp,m; - const char *mapname; - int x0,y0,x1,y1; + int hp,sp,m; + const char *mapname; + int x0,y0,x1,y1; - mapname=script_getstr(st,2); - x0=script_getnum(st,3); - y0=script_getnum(st,4); - x1=script_getnum(st,5); - y1=script_getnum(st,6); - hp=script_getnum(st,7); - sp=script_getnum(st,8); + mapname=script_getstr(st,2); + x0=script_getnum(st,3); + y0=script_getnum(st,4); + x1=script_getnum(st,5); + y1=script_getnum(st,6); + hp=script_getnum(st,7); + sp=script_getnum(st,8); - if ((m=map_mapname2mapid(mapname))< 0) - return 0; + if( (m=map_mapname2mapid(mapname))< 0) + return 0; - map_foreachinarea(buildin_areapercentheal_sub,m,x0,y0,x1,y1,BL_PC,hp,sp); - return 0; + map_foreachinarea(buildin_areapercentheal_sub,m,x0,y0,x1,y1,BL_PC,hp,sp); + return 0; } /*========================================== @@ -5019,27 +5113,28 @@ BUILDIN_FUNC(areapercentheal) *------------------------------------------*/ BUILDIN_FUNC(warpchar) { - int x,y,a; - const char *str; - TBL_PC *sd; + int x,y,a; + const char *str; + TBL_PC *sd; - str=script_getstr(st,2); - x=script_getnum(st,3); - y=script_getnum(st,4); - a=script_getnum(st,5); + str=script_getstr(st,2); + x=script_getnum(st,3); + y=script_getnum(st,4); + a=script_getnum(st,5); - sd = map_charid2sd(a); - if (sd == NULL) - return 0; + sd = map_charid2sd(a); + if( sd == NULL ) + return 0; - if (strcmp(str, "Random") == 0) - pc_randomwarp(sd, CLR_TELEPORT); - else if (strcmp(str, "SavePoint") == 0) - pc_setpos(sd, sd->status.save_point.map,sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); - else - pc_setpos(sd, mapindex_name2id(str), x, y, CLR_TELEPORT); + if(strcmp(str, "Random") == 0) + pc_randomwarp(sd, CLR_TELEPORT); + else + if(strcmp(str, "SavePoint") == 0) + pc_setpos(sd, sd->status.save_point.map,sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); + else + pc_setpos(sd, mapindex_name2id(str), x, y, CLR_TELEPORT); - return 0; + return 0; } /*========================================== * Warpparty - [Fredzilla] [Paradox924X] @@ -5048,85 +5143,88 @@ BUILDIN_FUNC(warpchar) *------------------------------------------*/ BUILDIN_FUNC(warpparty) { - TBL_PC *sd = NULL; - TBL_PC *pl_sd; - struct party_data *p; - int type; - int mapindex; - int i; - - const char *str = script_getstr(st,2); - int x = script_getnum(st,3); - int y = script_getnum(st,4); - int p_id = script_getnum(st,5); - const char *str2 = NULL; - if (script_hasdata(st,6)) - str2 = script_getstr(st,6); - - p = party_search(p_id); - if (!p) - return 0; - - type = (strcmp(str,"Random")==0) ? 0 - : (strcmp(str,"SavePointAll")==0) ? 1 - : (strcmp(str,"SavePoint")==0) ? 2 - : (strcmp(str,"Leader")==0) ? 3 - : 4; - - switch (type) { - case 3: - for (i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++); - if (i == MAX_PARTY || !p->data[i].sd) //Leader not found / not online - return 0; - pl_sd = p->data[i].sd; - mapindex = pl_sd->mapindex; - x = pl_sd->bl.x; - y = pl_sd->bl.y; - break; - case 4: - mapindex = mapindex_name2id(str); - break; - case 2: - //"SavePoint" uses save point of the currently attached player - if ((sd = script_rid2sd(st)) == NULL) - return 0; - default: - mapindex = 0; - break; - } - - for (i = 0; i < MAX_PARTY; i++) { - if (!(pl_sd = p->data[i].sd) || pl_sd->status.party_id != p_id) - continue; - - if (str2 && strcmp(str2, map[pl_sd->bl.m].name) != 0) - continue; - - if (pc_isdead(pl_sd)) - continue; - - switch (type) { - case 0: // Random - if (!map[pl_sd->bl.m].flag.nowarp) - pc_randomwarp(pl_sd,CLR_TELEPORT); - break; - case 1: // SavePointAll - if (!map[pl_sd->bl.m].flag.noreturn) - pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT); - break; - case 2: // SavePoint - if (!map[pl_sd->bl.m].flag.noreturn) - pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - break; - case 3: // Leader - case 4: // m,x,y - if (!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp) - pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT); - break; - } - } - - return 0; + TBL_PC *sd = NULL; + TBL_PC *pl_sd; + struct party_data* p; + int type; + int mapindex; + int i; + + const char* str = script_getstr(st,2); + int x = script_getnum(st,3); + int y = script_getnum(st,4); + int p_id = script_getnum(st,5); + const char* str2 = NULL; + if ( script_hasdata(st,6) ) + str2 = script_getstr(st,6); + + p = party_search(p_id); + if(!p) + return 0; + + type = ( strcmp(str,"Random")==0 ) ? 0 + : ( strcmp(str,"SavePointAll")==0 ) ? 1 + : ( strcmp(str,"SavePoint")==0 ) ? 2 + : ( strcmp(str,"Leader")==0 ) ? 3 + : 4; + + switch (type) + { + case 3: + for(i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++); + if (i == MAX_PARTY || !p->data[i].sd) //Leader not found / not online + return 0; + pl_sd = p->data[i].sd; + mapindex = pl_sd->mapindex; + x = pl_sd->bl.x; + y = pl_sd->bl.y; + break; + case 4: + mapindex = mapindex_name2id(str); + break; + case 2: + //"SavePoint" uses save point of the currently attached player + if (( sd = script_rid2sd(st) ) == NULL ) + return 0; + default: + mapindex = 0; + break; + } + + for (i = 0; i < MAX_PARTY; i++) + { + if( !(pl_sd = p->data[i].sd) || pl_sd->status.party_id != p_id ) + continue; + + if( str2 && strcmp(str2, map[pl_sd->bl.m].name) != 0 ) + continue; + + if( pc_isdead(pl_sd) ) + continue; + + switch( type ) + { + case 0: // Random + if(!map[pl_sd->bl.m].flag.nowarp) + pc_randomwarp(pl_sd,CLR_TELEPORT); + break; + case 1: // SavePointAll + if(!map[pl_sd->bl.m].flag.noreturn) + pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT); + break; + case 2: // SavePoint + if(!map[pl_sd->bl.m].flag.noreturn) + pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + break; + case 3: // Leader + case 4: // m,x,y + if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp) + pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT); + break; + } + } + + return 0; } /*========================================== * Warpguild - [Fredzilla] @@ -5134,123 +5232,125 @@ BUILDIN_FUNC(warpparty) *------------------------------------------*/ BUILDIN_FUNC(warpguild) { - TBL_PC *sd = NULL; - TBL_PC *pl_sd; - struct guild *g; - struct s_mapiterator *iter; - int type; - - const char *str = script_getstr(st,2); - int x = script_getnum(st,3); - int y = script_getnum(st,4); - int gid = script_getnum(st,5); - - g = guild_search(gid); - if (g == NULL) - return 0; - - type = (strcmp(str,"Random")==0) ? 0 - : (strcmp(str,"SavePointAll")==0) ? 1 - : (strcmp(str,"SavePoint")==0) ? 2 - : 3; - - if (type == 2 && (sd = script_rid2sd(st)) == NULL) { - // "SavePoint" uses save point of the currently attached player - return 0; - } - - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (pl_sd->status.guild_id != gid) - continue; - - switch (type) { - case 0: // Random - if (!map[pl_sd->bl.m].flag.nowarp) - pc_randomwarp(pl_sd,CLR_TELEPORT); - break; - case 1: // SavePointAll - if (!map[pl_sd->bl.m].flag.noreturn) - pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT); - break; - case 2: // SavePoint - if (!map[pl_sd->bl.m].flag.noreturn) - pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - break; - case 3: // m,x,y - if (!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp) - pc_setpos(pl_sd,mapindex_name2id(str),x,y,CLR_TELEPORT); - break; - } - } - mapit_free(iter); - - return 0; + TBL_PC *sd = NULL; + TBL_PC *pl_sd; + struct guild* g; + struct s_mapiterator* iter; + int type; + + const char* str = script_getstr(st,2); + int x = script_getnum(st,3); + int y = script_getnum(st,4); + int gid = script_getnum(st,5); + + g = guild_search(gid); + if( g == NULL ) + return 0; + + type = ( strcmp(str,"Random")==0 ) ? 0 + : ( strcmp(str,"SavePointAll")==0 ) ? 1 + : ( strcmp(str,"SavePoint")==0 ) ? 2 + : 3; + + if( type == 2 && ( sd = script_rid2sd(st) ) == NULL ) + {// "SavePoint" uses save point of the currently attached player + return 0; + } + + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + if( pl_sd->status.guild_id != gid ) + continue; + + switch( type ) + { + case 0: // Random + if(!map[pl_sd->bl.m].flag.nowarp) + pc_randomwarp(pl_sd,CLR_TELEPORT); + break; + case 1: // SavePointAll + if(!map[pl_sd->bl.m].flag.noreturn) + pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT); + break; + case 2: // SavePoint + if(!map[pl_sd->bl.m].flag.noreturn) + pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + break; + case 3: // m,x,y + if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp) + pc_setpos(pl_sd,mapindex_name2id(str),x,y,CLR_TELEPORT); + break; + } + } + mapit_free(iter); + + return 0; } /*========================================== * Force Heal a player (hp and sp) *------------------------------------------*/ BUILDIN_FUNC(heal) { - TBL_PC *sd; - int hp,sp; + TBL_PC *sd; + int hp,sp; - sd = script_rid2sd(st); - if (!sd) return 0; + sd = script_rid2sd(st); + if (!sd) return 0; - hp=script_getnum(st,2); - sp=script_getnum(st,3); - status_heal(&sd->bl, hp, sp, 1); - return 0; + hp=script_getnum(st,2); + sp=script_getnum(st,3); + status_heal(&sd->bl, hp, sp, 1); + return 0; } /*========================================== * Heal a player by item (get vit bonus etc) *------------------------------------------*/ BUILDIN_FUNC(itemheal) { - TBL_PC *sd; - int hp,sp; + TBL_PC *sd; + int hp,sp; - hp=script_getnum(st,2); - sp=script_getnum(st,3); + hp=script_getnum(st,2); + sp=script_getnum(st,3); - if (potion_flag==1) { - potion_hp = hp; - potion_sp = sp; - return 0; - } + if(potion_flag==1) { + potion_hp = hp; + potion_sp = sp; + return 0; + } - sd = script_rid2sd(st); - if (!sd) return 0; - pc_itemheal(sd,sd->itemid,hp,sp); - return 0; + sd = script_rid2sd(st); + if (!sd) return 0; + pc_itemheal(sd,sd->itemid,hp,sp); + return 0; } /*========================================== * *------------------------------------------*/ BUILDIN_FUNC(percentheal) { - int hp,sp; - TBL_PC *sd; + int hp,sp; + TBL_PC* sd; - hp=script_getnum(st,2); - sp=script_getnum(st,3); + hp=script_getnum(st,2); + sp=script_getnum(st,3); - if (potion_flag==1) { - potion_per_hp = hp; - potion_per_sp = sp; - return 0; - } + if(potion_flag==1) { + potion_per_hp = hp; + potion_per_sp = sp; + return 0; + } - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; #ifdef RENEWAL - if (sd->sc.data[SC_EXTREMITYFIST2]) - sp = 0; + if( sd->sc.data[SC_EXTREMITYFIST2] ) + sp = 0; #endif - pc_percentheal(sd,hp,sp); - return 0; + pc_percentheal(sd,hp,sp); + return 0; } /*========================================== @@ -5258,23 +5358,24 @@ BUILDIN_FUNC(percentheal) *------------------------------------------*/ BUILDIN_FUNC(jobchange) { - int job, upper=-1; + int job, upper=-1; - job=script_getnum(st,2); - if (script_hasdata(st,3)) - upper=script_getnum(st,3); + job=script_getnum(st,2); + if( script_hasdata(st,3) ) + upper=script_getnum(st,3); - if (pcdb_checkid(job)) { - TBL_PC *sd; + if (pcdb_checkid(job)) + { + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - pc_jobchange(sd, job, upper); - } + pc_jobchange(sd, job, upper); + } - return 0; + return 0; } /*========================================== @@ -5282,9 +5383,9 @@ BUILDIN_FUNC(jobchange) *------------------------------------------*/ BUILDIN_FUNC(jobname) { - int class_=script_getnum(st,2); - script_pushconststr(st, (char *)job_name(class_)); - return 0; + int class_=script_getnum(st,2); + script_pushconststr(st, (char*)job_name(class_)); + return 0; } /// Get input from the player. @@ -5296,52 +5397,56 @@ BUILDIN_FUNC(jobname) /// input(<var>{,<min>{,<max>}}) -> <int> BUILDIN_FUNC(input) { - TBL_PC *sd; - struct script_data *data; - int uid; - const char *name; - int min; - int max; - - sd = script_rid2sd(st); - if (sd == NULL) - return 0; - - data = script_getdata(st,2); - if (!data_isreference(data)) { - ShowError("script:input: not a variable\n"); - script_reportdata(data); - st->state = END; - return 1; - } - uid = reference_getuid(data); - name = reference_getname(data); - min = (script_hasdata(st,3) ? script_getnum(st,3) : script_config.input_min_value); - max = (script_hasdata(st,4) ? script_getnum(st,4) : script_config.input_max_value); - - if (!sd->state.menu_or_input) { - // first invocation, display npc input box - sd->state.menu_or_input = 1; - st->state = RERUNLINE; - if (is_string_variable(name)) - clif_scriptinputstr(sd,st->oid); - else - clif_scriptinput(sd,st->oid); - } else { - // take received text/value and store it in the designated variable - sd->state.menu_or_input = 0; - if (is_string_variable(name)) { - int len = (int)strlen(sd->npc_str); - set_reg(st, sd, uid, name, (void *)sd->npc_str, script_getref(st,2)); - script_pushint(st, (len > max ? 1 : len < min ? -1 : 0)); - } else { - int amount = sd->npc_amount; - set_reg(st, sd, uid, name, (void *)__64BPRTSIZE(cap_value(amount,min,max)), script_getref(st,2)); - script_pushint(st, (amount > max ? 1 : amount < min ? -1 : 0)); - } - st->state = RUN; - } - return 0; + TBL_PC* sd; + struct script_data* data; + int uid; + const char* name; + int min; + int max; + + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; + + data = script_getdata(st,2); + if( !data_isreference(data) ){ + ShowError("script:input: not a variable\n"); + script_reportdata(data); + st->state = END; + return 1; + } + uid = reference_getuid(data); + name = reference_getname(data); + min = (script_hasdata(st,3) ? script_getnum(st,3) : script_config.input_min_value); + max = (script_hasdata(st,4) ? script_getnum(st,4) : script_config.input_max_value); + + if( !sd->state.menu_or_input ) + { // first invocation, display npc input box + sd->state.menu_or_input = 1; + st->state = RERUNLINE; + if( is_string_variable(name) ) + clif_scriptinputstr(sd,st->oid); + else + clif_scriptinput(sd,st->oid); + } + else + { // take received text/value and store it in the designated variable + sd->state.menu_or_input = 0; + if( is_string_variable(name) ) + { + int len = (int)strlen(sd->npc_str); + set_reg(st, sd, uid, name, (void*)sd->npc_str, script_getref(st,2)); + script_pushint(st, (len > max ? 1 : len < min ? -1 : 0)); + } + else + { + int amount = sd->npc_amount; + set_reg(st, sd, uid, name, (void*)__64BPRTSIZE(cap_value(amount,min,max)), script_getref(st,2)); + script_pushint(st, (amount > max ? 1 : amount < min ? -1 : 0)); + } + st->state = RUN; + } + return 0; } // declare the copyarray method here for future reference @@ -5353,71 +5458,74 @@ BUILDIN_FUNC(copyarray); /// set(<variable>,<value>) -> <variable> BUILDIN_FUNC(set) { - TBL_PC *sd = NULL; - struct script_data *data; - //struct script_data* datavalue; - int num; - const char *name; - char prefix; - - data = script_getdata(st,2); - //datavalue = script_getdata(st,3); - if (!data_isreference(data)) { - ShowError("script:set: not a variable\n"); - script_reportdata(script_getdata(st,2)); - st->state = END; - return 1; - } - - num = reference_getuid(data); - name = reference_getname(data); - prefix = *name; - - if (not_server_variable(prefix)) { - sd = script_rid2sd(st); - if (sd == NULL) { - ShowError("script:set: no player attached for player variable '%s'\n", name); - return 0; - } - } + TBL_PC* sd = NULL; + struct script_data* data; + //struct script_data* datavalue; + int num; + const char* name; + char prefix; + + data = script_getdata(st,2); + //datavalue = script_getdata(st,3); + if( !data_isreference(data) ) + { + ShowError("script:set: not a variable\n"); + script_reportdata(script_getdata(st,2)); + st->state = END; + return 1; + } + + num = reference_getuid(data); + name = reference_getname(data); + prefix = *name; + + if( not_server_variable(prefix) ) + { + sd = script_rid2sd(st); + if( sd == NULL ) + { + ShowError("script:set: no player attached for player variable '%s'\n", name); + return 0; + } + } #if 0 - if (data_isreference(datavalue)) { - // the value being referenced is a variable - const char *namevalue = reference_getname(datavalue); - - if (!not_array_variable(*namevalue)) { - // array variable being copied into another array variable - if (sd == NULL && not_server_variable(*namevalue) && !(sd = script_rid2sd(st))) { - // player must be attached in order to copy a player variable - ShowError("script:set: no player attached for player variable '%s'\n", namevalue); - return 0; - } - - if (is_string_variable(namevalue) != is_string_variable(name)) { - // non-matching array value types - ShowWarning("script:set: two array variables do not match in type.\n"); - return 0; - } - - // push the maximum number of array values to the stack - push_val(st->stack, C_INT, SCRIPT_MAX_ARRAYSIZE); - - // call the copy array method directly - return buildin_copyarray(st); - } - } + if( data_isreference(datavalue) ) + {// the value being referenced is a variable + const char* namevalue = reference_getname(datavalue); + + if( !not_array_variable(*namevalue) ) + {// array variable being copied into another array variable + if( sd == NULL && not_server_variable(*namevalue) && !(sd = script_rid2sd(st)) ) + {// player must be attached in order to copy a player variable + ShowError("script:set: no player attached for player variable '%s'\n", namevalue); + return 0; + } + + if( is_string_variable(namevalue) != is_string_variable(name) ) + {// non-matching array value types + ShowWarning("script:set: two array variables do not match in type.\n"); + return 0; + } + + // push the maximum number of array values to the stack + push_val(st->stack, C_INT, SCRIPT_MAX_ARRAYSIZE); + + // call the copy array method directly + return buildin_copyarray(st); + } + } #endif - if (is_string_variable(name)) - set_reg(st,sd,num,name,(void *)script_getstr(st,3),script_getref(st,2)); - else - set_reg(st,sd,num,name,(void *)__64BPRTSIZE(script_getnum(st,3)),script_getref(st,2)); + if( is_string_variable(name) ) + set_reg(st,sd,num,name,(void*)script_getstr(st,3),script_getref(st,2)); + else + set_reg(st,sd,num,name,(void*)__64BPRTSIZE(script_getnum(st,3)),script_getref(st,2)); - // return a copy of the variable reference - script_pushcopy(st,2); + // return a copy of the variable reference + script_pushcopy(st,2); - return 0; + return 0; } ///////////////////////////////////////////////////////////////////// @@ -5425,26 +5533,31 @@ BUILDIN_FUNC(set) /// /// Returns the size of the specified array -static int32 getarraysize(struct script_state *st, int32 id, int32 idx, int isstring, struct DBMap **ref) -{ - int32 ret = idx; - - if (isstring) { - for (; idx < SCRIPT_MAX_ARRAYSIZE; ++idx) { - char *str = (char *)get_val2(st, reference_uid(id, idx), ref); - if (str && *str) - ret = idx + 1; - script_removetop(st, -1, 0); - } - } else { - for (; idx < SCRIPT_MAX_ARRAYSIZE; ++idx) { - int32 num = (int32)__64BPRTSIZE(get_val2(st, reference_uid(id, idx), ref)); - if (num) - ret = idx + 1; - script_removetop(st, -1, 0); - } - } - return ret; +static int32 getarraysize(struct script_state* st, int32 id, int32 idx, int isstring, struct DBMap** ref) +{ + int32 ret = idx; + + if( isstring ) + { + for( ; idx < SCRIPT_MAX_ARRAYSIZE; ++idx ) + { + char* str = (char*)get_val2(st, reference_uid(id, idx), ref); + if( str && *str ) + ret = idx + 1; + script_removetop(st, -1, 0); + } + } + else + { + for( ; idx < SCRIPT_MAX_ARRAYSIZE; ++idx ) + { + int32 num = (int32)__64BPRTSIZE(get_val2(st, reference_uid(id, idx), ref)); + if( num ) + ret = idx + 1; + script_removetop(st, -1, 0); + } + } + return ret; } /// Sets values of an array, from the starting index. @@ -5453,52 +5566,56 @@ static int32 getarraysize(struct script_state *st, int32 id, int32 idx, int isst /// setarray <array variable>,<value1>{,<value2>...}; BUILDIN_FUNC(setarray) { - struct script_data *data; - const char *name; - int32 start; - int32 end; - int32 id; - int32 i; - TBL_PC *sd = NULL; - - data = script_getdata(st, 2); - if (!data_isreference(data)) { - ShowError("script:setarray: not a variable\n"); - script_reportdata(data); - st->state = END; - return 1;// not a variable - } - - id = reference_getid(data); - start = reference_getindex(data); - name = reference_getname(data); - if (not_array_variable(*name)) { - ShowError("script:setarray: illegal scope\n"); - script_reportdata(data); - st->state = END; - return 1;// not supported - } - - if (not_server_variable(*name)) { - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached - } - - end = start + script_lastdata(st) - 2; - if (end > SCRIPT_MAX_ARRAYSIZE) - end = SCRIPT_MAX_ARRAYSIZE; - - if (is_string_variable(name)) { - // string array - for (i = 3; start < end; ++start, ++i) - set_reg(st, sd, reference_uid(id, start), name, (void *)script_getstr(st,i), reference_getref(data)); - } else { - // int array - for (i = 3; start < end; ++start, ++i) - set_reg(st, sd, reference_uid(id, start), name, (void *)__64BPRTSIZE(script_getnum(st,i)), reference_getref(data)); - } - return 0; + struct script_data* data; + const char* name; + int32 start; + int32 end; + int32 id; + int32 i; + TBL_PC* sd = NULL; + + data = script_getdata(st, 2); + if( !data_isreference(data) ) + { + ShowError("script:setarray: not a variable\n"); + script_reportdata(data); + st->state = END; + return 1;// not a variable + } + + id = reference_getid(data); + start = reference_getindex(data); + name = reference_getname(data); + if( not_array_variable(*name) ) + { + ShowError("script:setarray: illegal scope\n"); + script_reportdata(data); + st->state = END; + return 1;// not supported + } + + if( not_server_variable(*name) ) + { + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached + } + + end = start + script_lastdata(st) - 2; + if( end > SCRIPT_MAX_ARRAYSIZE ) + end = SCRIPT_MAX_ARRAYSIZE; + + if( is_string_variable(name) ) + {// string array + for( i = 3; start < end; ++start, ++i ) + set_reg(st, sd, reference_uid(id, start), name, (void*)script_getstr(st,i), reference_getref(data)); + } + else + {// int array + for( i = 3; start < end; ++start, ++i ) + set_reg(st, sd, reference_uid(id, start), name, (void*)__64BPRTSIZE(script_getnum(st,i)), reference_getref(data)); + } + return 0; } /// Sets count values of an array, from the starting index. @@ -5507,50 +5624,53 @@ BUILDIN_FUNC(setarray) /// cleararray <array variable>,<value>,<count>; BUILDIN_FUNC(cleararray) { - struct script_data *data; - const char *name; - int32 start; - int32 end; - int32 id; - void *v; - TBL_PC *sd = NULL; - - data = script_getdata(st, 2); - if (!data_isreference(data)) { - ShowError("script:cleararray: not a variable\n"); - script_reportdata(data); - st->state = END; - return 1;// not a variable - } - - id = reference_getid(data); - start = reference_getindex(data); - name = reference_getname(data); - if (not_array_variable(*name)) { - ShowError("script:cleararray: illegal scope\n"); - script_reportdata(data); - st->state = END; - return 1;// not supported - } - - if (not_server_variable(*name)) { - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached - } - - if (is_string_variable(name)) - v = (void *)script_getstr(st, 3); - else - v = (void *)__64BPRTSIZE(script_getnum(st, 3)); - - end = start + script_getnum(st, 4); - if (end > SCRIPT_MAX_ARRAYSIZE) - end = SCRIPT_MAX_ARRAYSIZE; - - for (; start < end; ++start) - set_reg(st, sd, reference_uid(id, start), name, v, script_getref(st,2)); - return 0; + struct script_data* data; + const char* name; + int32 start; + int32 end; + int32 id; + void* v; + TBL_PC* sd = NULL; + + data = script_getdata(st, 2); + if( !data_isreference(data) ) + { + ShowError("script:cleararray: not a variable\n"); + script_reportdata(data); + st->state = END; + return 1;// not a variable + } + + id = reference_getid(data); + start = reference_getindex(data); + name = reference_getname(data); + if( not_array_variable(*name) ) + { + ShowError("script:cleararray: illegal scope\n"); + script_reportdata(data); + st->state = END; + return 1;// not supported + } + + if( not_server_variable(*name) ) + { + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached + } + + if( is_string_variable(name) ) + v = (void*)script_getstr(st, 3); + else + v = (void*)__64BPRTSIZE(script_getnum(st, 3)); + + end = start + script_getnum(st, 4); + if( end > SCRIPT_MAX_ARRAYSIZE ) + end = SCRIPT_MAX_ARRAYSIZE; + + for( ; start < end; ++start ) + set_reg(st, sd, reference_uid(id, start), name, v, script_getref(st,2)); + return 0; } /// Copies data from one array to another. @@ -5559,82 +5679,91 @@ BUILDIN_FUNC(cleararray) /// copyarray <destination array variable>,<source array variable>,<count>; BUILDIN_FUNC(copyarray) { - struct script_data *data1; - struct script_data *data2; - const char *name1; - const char *name2; - int32 idx1; - int32 idx2; - int32 id1; - int32 id2; - void *v; - int32 i; - int32 count; - TBL_PC *sd = NULL; - - data1 = script_getdata(st, 2); - data2 = script_getdata(st, 3); - if (!data_isreference(data1) || !data_isreference(data2)) { - ShowError("script:copyarray: not a variable\n"); - script_reportdata(data1); - script_reportdata(data2); - st->state = END; - return 1;// not a variable - } - - id1 = reference_getid(data1); - id2 = reference_getid(data2); - idx1 = reference_getindex(data1); - idx2 = reference_getindex(data2); - name1 = reference_getname(data1); - name2 = reference_getname(data2); - if (not_array_variable(*name1) || not_array_variable(*name2)) { - ShowError("script:copyarray: illegal scope\n"); - script_reportdata(data1); - script_reportdata(data2); - st->state = END; - return 1;// not supported - } - - if (is_string_variable(name1) != is_string_variable(name2)) { - ShowError("script:copyarray: type mismatch\n"); - script_reportdata(data1); - script_reportdata(data2); - st->state = END; - return 1;// data type mismatch - } - - if (not_server_variable(*name1) || not_server_variable(*name2)) { - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached - } - - count = script_getnum(st, 4); - if (count > SCRIPT_MAX_ARRAYSIZE - idx1) - count = SCRIPT_MAX_ARRAYSIZE - idx1; - if (count <= 0 || (id1 == id2 && idx1 == idx2)) - return 0;// nothing to copy - - if (id1 == id2 && idx1 > idx2) { - // destination might be overlapping the source - copy in reverse order - for (i = count - 1; i >= 0; --i) { - v = get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2)); - set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1)); - script_removetop(st, -1, 0); - } - } else { - // normal copy - for (i = 0; i < count; ++i) { - if (idx2 + i < SCRIPT_MAX_ARRAYSIZE) { - v = get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2)); - set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1)); - script_removetop(st, -1, 0); - } else // out of range - assume ""/0 - set_reg(st, sd, reference_uid(id1, idx1 + i), name1, (is_string_variable(name1)?(void *)"":(void *)0), reference_getref(data1)); - } - } - return 0; + struct script_data* data1; + struct script_data* data2; + const char* name1; + const char* name2; + int32 idx1; + int32 idx2; + int32 id1; + int32 id2; + void* v; + int32 i; + int32 count; + TBL_PC* sd = NULL; + + data1 = script_getdata(st, 2); + data2 = script_getdata(st, 3); + if( !data_isreference(data1) || !data_isreference(data2) ) + { + ShowError("script:copyarray: not a variable\n"); + script_reportdata(data1); + script_reportdata(data2); + st->state = END; + return 1;// not a variable + } + + id1 = reference_getid(data1); + id2 = reference_getid(data2); + idx1 = reference_getindex(data1); + idx2 = reference_getindex(data2); + name1 = reference_getname(data1); + name2 = reference_getname(data2); + if( not_array_variable(*name1) || not_array_variable(*name2) ) + { + ShowError("script:copyarray: illegal scope\n"); + script_reportdata(data1); + script_reportdata(data2); + st->state = END; + return 1;// not supported + } + + if( is_string_variable(name1) != is_string_variable(name2) ) + { + ShowError("script:copyarray: type mismatch\n"); + script_reportdata(data1); + script_reportdata(data2); + st->state = END; + return 1;// data type mismatch + } + + if( not_server_variable(*name1) || not_server_variable(*name2) ) + { + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached + } + + count = script_getnum(st, 4); + if( count > SCRIPT_MAX_ARRAYSIZE - idx1 ) + count = SCRIPT_MAX_ARRAYSIZE - idx1; + if( count <= 0 || (id1 == id2 && idx1 == idx2) ) + return 0;// nothing to copy + + if( id1 == id2 && idx1 > idx2 ) + {// destination might be overlapping the source - copy in reverse order + for( i = count - 1; i >= 0; --i ) + { + v = get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2)); + set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1)); + script_removetop(st, -1, 0); + } + } + else + {// normal copy + for( i = 0; i < count; ++i ) + { + if( idx2 + i < SCRIPT_MAX_ARRAYSIZE ) + { + v = get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2)); + set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1)); + script_removetop(st, -1, 0); + } + else// out of range - assume ""/0 + set_reg(st, sd, reference_uid(id1, idx1 + i), name1, (is_string_variable(name1)?(void*)"":(void*)0), reference_getref(data1)); + } + } + return 0; } /// Returns the size of the array. @@ -5644,29 +5773,31 @@ BUILDIN_FUNC(copyarray) /// getarraysize(<array variable>) -> <int> BUILDIN_FUNC(getarraysize) { - struct script_data *data; - const char *name; - - data = script_getdata(st, 2); - if (!data_isreference(data)) { - ShowError("script:getarraysize: not a variable\n"); - script_reportdata(data); - script_pushnil(st); - st->state = END; - return 1;// not a variable - } - - name = reference_getname(data); - if (not_array_variable(*name)) { - ShowError("script:getarraysize: illegal scope\n"); - script_reportdata(data); - script_pushnil(st); - st->state = END; - return 1;// not supported - } - - script_pushint(st, getarraysize(st, reference_getid(data), reference_getindex(data), is_string_variable(name), reference_getref(data))); - return 0; + struct script_data* data; + const char* name; + + data = script_getdata(st, 2); + if( !data_isreference(data) ) + { + ShowError("script:getarraysize: not a variable\n"); + script_reportdata(data); + script_pushnil(st); + st->state = END; + return 1;// not a variable + } + + name = reference_getname(data); + if( not_array_variable(*name) ) + { + ShowError("script:getarraysize: illegal scope\n"); + script_reportdata(data); + script_pushnil(st); + st->state = END; + return 1;// not supported + } + + script_pushint(st, getarraysize(st, reference_getid(data), reference_getindex(data), is_string_variable(name), reference_getref(data))); + return 0; } /// Deletes count or all the elements in an array, from the starting index. @@ -5676,66 +5807,74 @@ BUILDIN_FUNC(getarraysize) /// deletearray <array variable>,<count>; BUILDIN_FUNC(deletearray) { - struct script_data *data; - const char *name; - int start; - int end; - int id; - TBL_PC *sd = NULL; - - data = script_getdata(st, 2); - if (!data_isreference(data)) { - ShowError("script:deletearray: not a variable\n"); - script_reportdata(data); - st->state = END; - return 1;// not a variable - } - - id = reference_getid(data); - start = reference_getindex(data); - name = reference_getname(data); - if (not_array_variable(*name)) { - ShowError("script:deletearray: illegal scope\n"); - script_reportdata(data); - st->state = END; - return 1;// not supported - } - - if (not_server_variable(*name)) { - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached - } - - end = SCRIPT_MAX_ARRAYSIZE; - - if (start >= end) - return 0;// nothing to free - - if (script_hasdata(st,3)) { - int count = script_getnum(st, 3); - if (count > end - start) - count = end - start; - if (count <= 0) - return 0;// nothing to free - - // move rest of the elements backward - for (; start + count < end; ++start) { - void *v = get_val2(st, reference_uid(id, start + count), reference_getref(data)); - set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data)); - script_removetop(st, -1, 0); - } - } - - // clear the rest of the array - if (is_string_variable(name)) { - for (; start < end; ++start) - set_reg(st, sd, reference_uid(id, start), name, (void *)"", reference_getref(data)); - } else { - for (; start < end; ++start) - set_reg(st, sd, reference_uid(id, start), name, (void *)0, reference_getref(data)); - } - return 0; + struct script_data* data; + const char* name; + int start; + int end; + int id; + TBL_PC *sd = NULL; + + data = script_getdata(st, 2); + if( !data_isreference(data) ) + { + ShowError("script:deletearray: not a variable\n"); + script_reportdata(data); + st->state = END; + return 1;// not a variable + } + + id = reference_getid(data); + start = reference_getindex(data); + name = reference_getname(data); + if( not_array_variable(*name) ) + { + ShowError("script:deletearray: illegal scope\n"); + script_reportdata(data); + st->state = END; + return 1;// not supported + } + + if( not_server_variable(*name) ) + { + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached + } + + end = SCRIPT_MAX_ARRAYSIZE; + + if( start >= end ) + return 0;// nothing to free + + if( script_hasdata(st,3) ) + { + int count = script_getnum(st, 3); + if( count > end - start ) + count = end - start; + if( count <= 0 ) + return 0;// nothing to free + + // move rest of the elements backward + for( ; start + count < end; ++start ) + { + void* v = get_val2(st, reference_uid(id, start + count), reference_getref(data)); + set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data)); + script_removetop(st, -1, 0); + } + } + + // clear the rest of the array + if( is_string_variable(name) ) + { + for( ; start < end; ++start ) + set_reg(st, sd, reference_uid(id, start), name, (void *)"", reference_getref(data)); + } + else + { + for( ; start < end; ++start ) + set_reg(st, sd, reference_uid(id, start), name, (void*)0, reference_getref(data)); + } + return 0; } /// Returns a reference to the target index of the array variable. @@ -5744,41 +5883,44 @@ BUILDIN_FUNC(deletearray) /// getelementofarray(<array variable>,<index>) -> <variable reference> BUILDIN_FUNC(getelementofarray) { - struct script_data *data; - const char *name; - int32 id; - int i; - - data = script_getdata(st, 2); - if (!data_isreference(data)) { - ShowError("script:getelementofarray: not a variable\n"); - script_reportdata(data); - script_pushnil(st); - st->state = END; - return 1;// not a variable - } - - id = reference_getid(data); - name = reference_getname(data); - if (not_array_variable(*name)) { - ShowError("script:getelementofarray: illegal scope\n"); - script_reportdata(data); - script_pushnil(st); - st->state = END; - return 1;// not supported - } - - i = script_getnum(st, 3); - if (i < 0 || i >= SCRIPT_MAX_ARRAYSIZE) { - ShowWarning("script:getelementofarray: index out of range (%d)\n", i); - script_reportdata(data); - script_pushnil(st); - st->state = END; - return 1;// out of range - } - - push_val2(st->stack, C_NAME, reference_uid(id, i), reference_getref(data)); - return 0; + struct script_data* data; + const char* name; + int32 id; + int i; + + data = script_getdata(st, 2); + if( !data_isreference(data) ) + { + ShowError("script:getelementofarray: not a variable\n"); + script_reportdata(data); + script_pushnil(st); + st->state = END; + return 1;// not a variable + } + + id = reference_getid(data); + name = reference_getname(data); + if( not_array_variable(*name) ) + { + ShowError("script:getelementofarray: illegal scope\n"); + script_reportdata(data); + script_pushnil(st); + st->state = END; + return 1;// not supported + } + + i = script_getnum(st, 3); + if( i < 0 || i >= SCRIPT_MAX_ARRAYSIZE ) + { + ShowWarning("script:getelementofarray: index out of range (%d)\n", i); + script_reportdata(data); + script_pushnil(st); + st->state = END; + return 1;// out of range + } + + push_val2(st->stack, C_NAME, reference_uid(id, i), reference_getref(data)); + return 0; } ///////////////////////////////////////////////////////////////////// @@ -5790,37 +5932,36 @@ BUILDIN_FUNC(getelementofarray) *------------------------------------------*/ BUILDIN_FUNC(setlook) { - int type,val; - TBL_PC *sd; + int type,val; + TBL_PC* sd; - type=script_getnum(st,2); - val=script_getnum(st,3); + type=script_getnum(st,2); + val=script_getnum(st,3); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - pc_changelook(sd,type,val); + pc_changelook(sd,type,val); - return 0; + return 0; } BUILDIN_FUNC(changelook) -{ - // As setlook but only client side - int type,val; - TBL_PC *sd; +{ // As setlook but only client side + int type,val; + TBL_PC* sd; - type=script_getnum(st,2); - val=script_getnum(st,3); + type=script_getnum(st,2); + val=script_getnum(st,3); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - clif_changelook(&sd->bl,type,val); + clif_changelook(&sd->bl,type,val); - return 0; + return 0; } /*========================================== @@ -5828,14 +5969,14 @@ BUILDIN_FUNC(changelook) *------------------------------------------*/ BUILDIN_FUNC(cutin) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - clif_cutin(sd,script_getstr(st,2),script_getnum(st,3)); - return 0; + clif_cutin(sd,script_getstr(st,2),script_getnum(st,3)); + return 0; } /*========================================== @@ -5843,22 +5984,22 @@ BUILDIN_FUNC(cutin) *------------------------------------------*/ BUILDIN_FUNC(viewpoint) { - int type,x,y,id,color; - TBL_PC *sd; + int type,x,y,id,color; + TBL_PC* sd; - type=script_getnum(st,2); - x=script_getnum(st,3); - y=script_getnum(st,4); - id=script_getnum(st,5); - color=script_getnum(st,6); + type=script_getnum(st,2); + x=script_getnum(st,3); + y=script_getnum(st,4); + id=script_getnum(st,5); + color=script_getnum(st,6); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - clif_viewpoint(sd,st->oid,type,x,y,id,color); + clif_viewpoint(sd,st->oid,type,x,y,id,color); - return 0; + return 0; } /*========================================== @@ -5866,282 +6007,291 @@ BUILDIN_FUNC(viewpoint) *------------------------------------------*/ BUILDIN_FUNC(countitem) { - int nameid, i; - int count = 0; - struct item_data *id = NULL; - struct script_data *data; + int nameid, i; + int count = 0; + struct item_data* id = NULL; + struct script_data* data; - TBL_PC *sd = script_rid2sd(st); - if (!sd) { - script_pushint(st,0); - return 0; - } + TBL_PC* sd = script_rid2sd(st); + if (!sd) { + script_pushint(st,0); + return 0; + } - data = script_getdata(st,2); - get_val(st, data); // convert into value in case of a variable + data = script_getdata(st,2); + get_val(st, data); // convert into value in case of a variable - if (data_isstring(data)) { - // item name - id = itemdb_searchname(conv_str(st, data)); - } else { - // item id - id = itemdb_exists(conv_num(st, data)); - } + if( data_isstring(data) ) + {// item name + id = itemdb_searchname(conv_str(st, data)); + } + else + {// item id + id = itemdb_exists(conv_num(st, data)); + } - if (id == NULL) { - ShowError("buildin_countitem: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was - script_pushint(st,0); - return 1; - } + if( id == NULL ) + { + ShowError("buildin_countitem: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was + script_pushint(st,0); + return 1; + } - nameid = id->nameid; + nameid = id->nameid; - for (i = 0; i < MAX_INVENTORY; i++) - if (sd->status.inventory[i].nameid == nameid) - count += sd->status.inventory[i].amount; + for(i = 0; i < MAX_INVENTORY; i++) + if(sd->status.inventory[i].nameid == nameid) + count += sd->status.inventory[i].amount; - script_pushint(st,count); - return 0; + script_pushint(st,count); + return 0; } /*========================================== - * countitem2(nameID,Identified,Refine,Attribute,Card0,Card1,Card2,Card3) [Lupus] - * returns number of items that meet the conditions + * countitem2(nameID,Identified,Refine,Attribute,Card0,Card1,Card2,Card3) [Lupus] + * returns number of items that meet the conditions *------------------------------------------*/ BUILDIN_FUNC(countitem2) { - int nameid, iden, ref, attr, c1, c2, c3, c4; - int count = 0; - int i; - struct item_data *id = NULL; - struct script_data *data; - - TBL_PC *sd = script_rid2sd(st); - if (!sd) { - script_pushint(st,0); - return 0; - } - - data = script_getdata(st,2); - get_val(st, data); // convert into value in case of a variable - - if (data_isstring(data)) { - // item name - id = itemdb_searchname(conv_str(st, data)); - } else { - // item id - id = itemdb_exists(conv_num(st, data)); - } - - if (id == NULL) { - ShowError("buildin_countitem2: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was - script_pushint(st,0); - return 1; - } - - nameid = id->nameid; - iden = script_getnum(st,3); - ref = script_getnum(st,4); - attr = script_getnum(st,5); - c1 = (short)script_getnum(st,6); - c2 = (short)script_getnum(st,7); - c3 = (short)script_getnum(st,8); - c4 = (short)script_getnum(st,9); - - for (i = 0; i < MAX_INVENTORY; i++) - if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] != NULL && - sd->status.inventory[i].amount > 0 && sd->status.inventory[i].nameid == nameid && - sd->status.inventory[i].identify == iden && sd->status.inventory[i].refine == ref && - sd->status.inventory[i].attribute == attr && sd->status.inventory[i].card[0] == c1 && - sd->status.inventory[i].card[1] == c2 && sd->status.inventory[i].card[2] == c3 && - sd->status.inventory[i].card[3] == c4 - ) - count += sd->status.inventory[i].amount; - - script_pushint(st,count); - return 0; + int nameid, iden, ref, attr, c1, c2, c3, c4; + int count = 0; + int i; + struct item_data* id = NULL; + struct script_data* data; + + TBL_PC* sd = script_rid2sd(st); + if (!sd) { + script_pushint(st,0); + return 0; + } + + data = script_getdata(st,2); + get_val(st, data); // convert into value in case of a variable + + if( data_isstring(data) ) + {// item name + id = itemdb_searchname(conv_str(st, data)); + } + else + {// item id + id = itemdb_exists(conv_num(st, data)); + } + + if( id == NULL ) + { + ShowError("buildin_countitem2: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was + script_pushint(st,0); + return 1; + } + + nameid = id->nameid; + iden = script_getnum(st,3); + ref = script_getnum(st,4); + attr = script_getnum(st,5); + c1 = (short)script_getnum(st,6); + c2 = (short)script_getnum(st,7); + c3 = (short)script_getnum(st,8); + c4 = (short)script_getnum(st,9); + + for(i = 0; i < MAX_INVENTORY; i++) + if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] != NULL && + sd->status.inventory[i].amount > 0 && sd->status.inventory[i].nameid == nameid && + sd->status.inventory[i].identify == iden && sd->status.inventory[i].refine == ref && + sd->status.inventory[i].attribute == attr && sd->status.inventory[i].card[0] == c1 && + sd->status.inventory[i].card[1] == c2 && sd->status.inventory[i].card[2] == c3 && + sd->status.inventory[i].card[3] == c4 + ) + count += sd->status.inventory[i].amount; + + script_pushint(st,count); + return 0; } /*========================================== * Check if item with this amount can fit in inventory * Checking : weight, stack amount >32k, slots amount >(MAX_INVENTORY) * Return - * 0 : fail - * 1 : success (npc side only) + * 0 : fail + * 1 : success (npc side only) *------------------------------------------*/ BUILDIN_FUNC(checkweight) { - int nameid, amount, slots, amount2=0; - unsigned int weight=0, i, nbargs; - struct item_data *id = NULL; - struct map_session_data *sd; - struct script_data *data; - - if ((sd = script_rid2sd(st)) == NULL) { - return 0; - } - nbargs = script_lastdata(st)+1; - if (nbargs%2) { - ShowError("buildin_checkweight: Invalid nb of args should be a multiple of 2.\n"); - script_pushint(st,0); - return 1; - } - slots = pc_inventoryblank(sd); //nb of empty slot - - for (i=2; i<nbargs; i=i+2) { - data = script_getdata(st,i); - get_val(st, data); // convert into value in case of a variable - if (data_isstring(data)) {// item name - id = itemdb_searchname(conv_str(st, data)); - } else {// item id - id = itemdb_exists(conv_num(st, data)); - } - if (id == NULL) { - ShowError("buildin_checkweight: Invalid item '%s'.\n", script_getstr(st,i)); // returns string, regardless of what it was - script_pushint(st,0); - return 1; - } - nameid = id->nameid; - - amount = script_getnum(st,i+1); - if (amount < 1) { - ShowError("buildin_checkweight: Invalid amount '%d'.\n", amount); - script_pushint(st,0); - return 1; - } - - weight += itemdb_weight(nameid)*amount; //total weight for all chk - if (weight + sd->weight > sd->max_weight) { - // too heavy - script_pushint(st,0); - return 0; - } - - switch (pc_checkadditem(sd, nameid, amount)) { - case ADDITEM_EXIST: - // item is already in inventory, but there is still space for the requested amount - break; - case ADDITEM_NEW: - if (itemdb_isstackable(nameid)) { // stackable - amount2++; - if (slots < amount2) { - script_pushint(st,0); - return 0; - } - } else { // non-stackable - amount2 += amount; - if (slots < amount2) { - script_pushint(st,0); - return 0; - } - } - break; - case ADDITEM_OVERAMOUNT: - script_pushint(st,0); - return 0; - } - } - script_pushint(st,1); - return 0; + int nameid, amount, slots, amount2=0; + unsigned int weight=0, i, nbargs; + struct item_data* id = NULL; + struct map_session_data* sd; + struct script_data* data; + + if( ( sd = script_rid2sd(st) ) == NULL ){ + return 0; + } + nbargs = script_lastdata(st)+1; + if(nbargs%2){ + ShowError("buildin_checkweight: Invalid nb of args should be a multiple of 2.\n"); + script_pushint(st,0); + return 1; + } + slots = pc_inventoryblank(sd); //nb of empty slot + + for(i=2; i<nbargs; i=i+2){ + data = script_getdata(st,i); + get_val(st, data); // convert into value in case of a variable + if( data_isstring(data) ){// item name + id = itemdb_searchname(conv_str(st, data)); + } else {// item id + id = itemdb_exists(conv_num(st, data)); + } + if( id == NULL ) { + ShowError("buildin_checkweight: Invalid item '%s'.\n", script_getstr(st,i)); // returns string, regardless of what it was + script_pushint(st,0); + return 1; + } + nameid = id->nameid; + + amount = script_getnum(st,i+1); + if( amount < 1 ) { + ShowError("buildin_checkweight: Invalid amount '%d'.\n", amount); + script_pushint(st,0); + return 1; + } + + weight += itemdb_weight(nameid)*amount; //total weight for all chk + if( weight + sd->weight > sd->max_weight ) + {// too heavy + script_pushint(st,0); + return 0; + } + + switch( pc_checkadditem(sd, nameid, amount) ) + { + case ADDITEM_EXIST: + // item is already in inventory, but there is still space for the requested amount + break; + case ADDITEM_NEW: + if( itemdb_isstackable(nameid) ) {// stackable + amount2++; + if( slots < amount2 ) { + script_pushint(st,0); + return 0; + } + } + else {// non-stackable + amount2 += amount; + if( slots < amount2){ + script_pushint(st,0); + return 0; + } + } + break; + case ADDITEM_OVERAMOUNT: + script_pushint(st,0); + return 0; + } + } + script_pushint(st,1); + return 0; } BUILDIN_FUNC(checkweight2) { - //variable sub checkweight - int32 nameid=-1, amount=-1; - int i=0, amount2=0, slots=0, weight=0; - short fail=0; + //variable sub checkweight + int32 nameid=-1, amount=-1; + int i=0, amount2=0, slots=0, weight=0; + short fail=0; - //variable for array parsing - struct script_data *data_it; - struct script_data *data_nb; - const char *name_it; - const char *name_nb; - int32 id_it, id_nb; - int32 idx_it, idx_nb; - int nb_it, nb_nb; //array size + //variable for array parsing + struct script_data* data_it; + struct script_data* data_nb; + const char* name_it; + const char* name_nb; + int32 id_it, id_nb; + int32 idx_it, idx_nb; + int nb_it, nb_nb; //array size - TBL_PC *sd = script_rid2sd(st); - nullpo_retr(1,sd); + TBL_PC *sd = script_rid2sd(st); + nullpo_retr(1,sd); - data_it = script_getdata(st, 2); - data_nb = script_getdata(st, 3); + data_it = script_getdata(st, 2); + data_nb = script_getdata(st, 3); - if (!data_isreference(data_it) || !data_isreference(data_nb)) { - ShowError("script:checkweight2: parameter not a variable\n"); - script_pushint(st,0); - return 1;// not a variable - } - id_it = reference_getid(data_it); - id_nb = reference_getid(data_nb); - idx_it = reference_getindex(data_it); - idx_nb = reference_getindex(data_nb); - name_it = reference_getname(data_it); - name_nb = reference_getname(data_nb); - - if (not_array_variable(*name_it) || not_array_variable(*name_nb)) { - ShowError("script:checkweight2: illegal scope\n"); - script_pushint(st,0); - return 1;// not supported - } - if (is_string_variable(name_it) || is_string_variable(name_nb)) { - ShowError("script:checkweight2: illegal type, need int\n"); - script_pushint(st,0); - return 1;// not supported - } - nb_it = getarraysize(st, id_it, idx_it, 0, reference_getref(data_it)); - nb_nb = getarraysize(st, id_nb, idx_nb, 0, reference_getref(data_nb)); - if (nb_it != nb_nb) { - ShowError("Size mistmatch: nb_it=%d, nb_nb=%d\n",nb_it,nb_nb); - fail = 1; - } - - slots = pc_inventoryblank(sd); - for (i=0; i<nb_it; i++) { - nameid = (int32)__64BPRTSIZE(get_val2(st,reference_uid(id_it,idx_it+i),reference_getref(data_it))); - script_removetop(st, -1, 0); - amount = (int32)__64BPRTSIZE(get_val2(st,reference_uid(id_nb,idx_nb+i),reference_getref(data_nb))); - script_removetop(st, -1, 0); - if (fail) continue; //cpntonie to depop rest - - if (itemdb_exists(nameid) == NULL) { - ShowError("buildin_checkweight2: Invalid item '%d'.\n", nameid); - fail=1; - continue; + if( !data_isreference(data_it) || !data_isreference(data_nb)) + { + ShowError("script:checkweight2: parameter not a variable\n"); + script_pushint(st,0); + return 1;// not a variable } - if (amount < 0) { - ShowError("buildin_checkweight2: Invalid amount '%d'.\n", amount); - fail = 1; - continue; + id_it = reference_getid(data_it); + id_nb = reference_getid(data_nb); + idx_it = reference_getindex(data_it); + idx_nb = reference_getindex(data_nb); + name_it = reference_getname(data_it); + name_nb = reference_getname(data_nb); + + if( not_array_variable(*name_it) || not_array_variable(*name_nb)) + { + ShowError("script:checkweight2: illegal scope\n"); + script_pushint(st,0); + return 1;// not supported } - weight += itemdb_weight(nameid)*amount; - if (weight + sd->weight > sd->max_weight) { - fail = 1; - continue; + if(is_string_variable(name_it) || is_string_variable(name_nb)){ + ShowError("script:checkweight2: illegal type, need int\n"); + script_pushint(st,0); + return 1;// not supported + } + nb_it = getarraysize(st, id_it, idx_it, 0, reference_getref(data_it)); + nb_nb = getarraysize(st, id_nb, idx_nb, 0, reference_getref(data_nb)); + if(nb_it != nb_nb){ + ShowError("Size mistmatch: nb_it=%d, nb_nb=%d\n",nb_it,nb_nb); + fail = 1; } - switch (pc_checkadditem(sd, nameid, amount)) { - case ADDITEM_EXIST: - // item is already in inventory, but there is still space for the requested amount - break; - case ADDITEM_NEW: - if (itemdb_isstackable(nameid)) {// stackable - amount2++; - if (slots < amount2) - fail = 1; - } else { // non-stackable - amount2 += amount; - if (slots < amount2) { - fail = 1; - } - } - break; - case ADDITEM_OVERAMOUNT: - fail = 1; - } //end switch - } //end loop DO NOT break it prematurly we need to depop all stack - fail?script_pushint(st,0):script_pushint(st,1); - return 0; + slots = pc_inventoryblank(sd); + for(i=0; i<nb_it; i++){ + nameid = (int32)__64BPRTSIZE(get_val2(st,reference_uid(id_it,idx_it+i),reference_getref(data_it))); + script_removetop(st, -1, 0); + amount = (int32)__64BPRTSIZE(get_val2(st,reference_uid(id_nb,idx_nb+i),reference_getref(data_nb))); + script_removetop(st, -1, 0); + if(fail) continue; //cpntonie to depop rest + + if(itemdb_exists(nameid) == NULL ){ + ShowError("buildin_checkweight2: Invalid item '%d'.\n", nameid); + fail=1; + continue; + } + if(amount < 0 ){ + ShowError("buildin_checkweight2: Invalid amount '%d'.\n", amount); + fail = 1; + continue; + } + weight += itemdb_weight(nameid)*amount; + if( weight + sd->weight > sd->max_weight ){ + fail = 1; + continue; + } + switch( pc_checkadditem(sd, nameid, amount) ) { + case ADDITEM_EXIST: + // item is already in inventory, but there is still space for the requested amount + break; + case ADDITEM_NEW: + if( itemdb_isstackable(nameid) ){// stackable + amount2++; + if( slots < amount2 ) + fail = 1; + } + else {// non-stackable + amount2 += amount; + if( slots < amount2 ){ + fail = 1; + } + } + break; + case ADDITEM_OVERAMOUNT: + fail = 1; + } //end switch + } //end loop DO NOT break it prematurly we need to depop all stack + + fail?script_pushint(st,0):script_pushint(st,1); + return 0; } /*========================================== @@ -6150,76 +6300,79 @@ BUILDIN_FUNC(checkweight2) *------------------------------------------*/ BUILDIN_FUNC(getitem) { - int nameid,amount,get_count,i,flag = 0; - struct item it; - TBL_PC *sd; - struct script_data *data; - - data=script_getdata(st,2); - get_val(st,data); - if (data_isstring(data)) { - // "<item name>" - const char *name=conv_str(st,data); - struct item_data *item_data = itemdb_searchname(name); - if (item_data == NULL) { - ShowError("buildin_getitem: Nonexistant item %s requested.\n", name); - return 1; //No item created. - } - nameid=item_data->nameid; - } else if (data_isint(data)) { - // <item id> - nameid=conv_num(st,data); - //Violet Box, Blue Box, etc - random item pick - if (nameid < 0) { - nameid = -nameid; - flag = 1; - } - if (nameid <= 0 || !itemdb_exists(nameid)) { - ShowError("buildin_getitem: Nonexistant item %d requested.\n", nameid); - return 1; //No item created. - } - } else { - ShowError("buildin_getitem: invalid data type for argument #1 (%d).", data->type); - return 1; - } - - // <amount> - if ((amount=script_getnum(st,3)) <= 0) - return 0; //return if amount <=0, skip the useles iteration - - memset(&it,0,sizeof(it)); - it.nameid=nameid; - if (!flag) - it.identify=1; - else - it.identify=itemdb_isidentified(nameid); - - if (script_hasdata(st,4)) - sd=map_id2sd(script_getnum(st,4)); // <Account ID> - else - sd=script_rid2sd(st); // Attached player - - if (sd == NULL) // no target - return 0; - - //Check if it's stackable. - if (!itemdb_isstackable(nameid)) - get_count = 1; - else - get_count = amount; - - for (i = 0; i < amount; i += get_count) { - // if not pet egg - if (!pet_create_egg(sd, nameid)) { - if ((flag = pc_additem(sd, &it, get_count, LOG_TYPE_SCRIPT))) { - clif_additem(sd, 0, 0, flag); - if (pc_candrop(sd,&it)) - map_addflooritem(&it,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - } - - return 0; + int nameid,amount,get_count,i,flag = 0; + struct item it; + TBL_PC *sd; + struct script_data *data; + + data=script_getdata(st,2); + get_val(st,data); + if( data_isstring(data) ) + {// "<item name>" + const char *name=conv_str(st,data); + struct item_data *item_data = itemdb_searchname(name); + if( item_data == NULL ){ + ShowError("buildin_getitem: Nonexistant item %s requested.\n", name); + return 1; //No item created. + } + nameid=item_data->nameid; + } else if( data_isint(data) ) + {// <item id> + nameid=conv_num(st,data); + //Violet Box, Blue Box, etc - random item pick + if( nameid < 0 ) { + nameid = -nameid; + flag = 1; + } + if( nameid <= 0 || !itemdb_exists(nameid) ){ + ShowError("buildin_getitem: Nonexistant item %d requested.\n", nameid); + return 1; //No item created. + } + } else { + ShowError("buildin_getitem: invalid data type for argument #1 (%d).", data->type); + return 1; + } + + // <amount> + if( (amount=script_getnum(st,3)) <= 0) + return 0; //return if amount <=0, skip the useles iteration + + memset(&it,0,sizeof(it)); + it.nameid=nameid; + if(!flag) + it.identify=1; + else + it.identify=itemdb_isidentified(nameid); + + if( script_hasdata(st,4) ) + sd=map_id2sd(script_getnum(st,4)); // <Account ID> + else + sd=script_rid2sd(st); // Attached player + + if( sd == NULL ) // no target + return 0; + + //Check if it's stackable. + if (!itemdb_isstackable(nameid)) + get_count = 1; + else + get_count = amount; + + for (i = 0; i < amount; i += get_count) + { + // if not pet egg + if (!pet_create_egg(sd, nameid)) + { + if ((flag = pc_additem(sd, &it, get_count, LOG_TYPE_SCRIPT))) + { + clif_additem(sd, 0, 0, flag); + if( pc_candrop(sd,&it) ) + map_addflooritem(&it,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + } + + return 0; } /*========================================== @@ -6227,93 +6380,98 @@ BUILDIN_FUNC(getitem) *------------------------------------------*/ BUILDIN_FUNC(getitem2) { - int nameid,amount,get_count,i,flag = 0; - int iden,ref,attr,c1,c2,c3,c4; - struct item_data *item_data; - struct item item_tmp; - TBL_PC *sd; - struct script_data *data; - - if (script_hasdata(st,11)) - sd=map_id2sd(script_getnum(st,11)); // <Account ID> - else - sd=script_rid2sd(st); // Attached player - - if (sd == NULL) // no target - return 0; - - data=script_getdata(st,2); - get_val(st,data); - if (data_isstring(data)) { - const char *name=conv_str(st,data); - struct item_data *item_data = itemdb_searchname(name); - if (item_data) - nameid=item_data->nameid; - else - nameid=UNKNOWN_ITEM_ID; - } else - nameid=conv_num(st,data); - - amount=script_getnum(st,3); - iden=script_getnum(st,4); - ref=script_getnum(st,5); - attr=script_getnum(st,6); - c1=(short)script_getnum(st,7); - c2=(short)script_getnum(st,8); - c3=(short)script_getnum(st,9); - c4=(short)script_getnum(st,10); - - if (nameid<0) { // Invalide nameid - nameid = -nameid; - flag = 1; - } - - if (nameid > 0) { - memset(&item_tmp,0,sizeof(item_tmp)); - item_data=itemdb_exists(nameid); - if (item_data == NULL) - return -1; - if (item_data->type==IT_WEAPON || item_data->type==IT_ARMOR) { - if (ref > MAX_REFINE) ref = MAX_REFINE; - } else if (item_data->type==IT_PETEGG) { - iden = 1; - ref = 0; - } else { - iden = 1; - ref = attr = 0; - } - - item_tmp.nameid=nameid; - if (!flag) - item_tmp.identify=iden; - else if (item_data->type==IT_WEAPON || item_data->type==IT_ARMOR) - item_tmp.identify=0; - item_tmp.refine=ref; - item_tmp.attribute=attr; - item_tmp.card[0]=(short)c1; - item_tmp.card[1]=(short)c2; - item_tmp.card[2]=(short)c3; - item_tmp.card[3]=(short)c4; - - //Check if it's stackable. - if (!itemdb_isstackable(nameid)) - get_count = 1; - else - get_count = amount; - - for (i = 0; i < amount; i += get_count) { - // if not pet egg - if (!pet_create_egg(sd, nameid)) { - if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) { - clif_additem(sd, 0, 0, flag); - if (pc_candrop(sd,&item_tmp)) - map_addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - } - } - - return 0; + int nameid,amount,get_count,i,flag = 0; + int iden,ref,attr,c1,c2,c3,c4; + struct item_data *item_data; + struct item item_tmp; + TBL_PC *sd; + struct script_data *data; + + if( script_hasdata(st,11) ) + sd=map_id2sd(script_getnum(st,11)); // <Account ID> + else + sd=script_rid2sd(st); // Attached player + + if( sd == NULL ) // no target + return 0; + + data=script_getdata(st,2); + get_val(st,data); + if( data_isstring(data) ){ + const char *name=conv_str(st,data); + struct item_data *item_data = itemdb_searchname(name); + if( item_data ) + nameid=item_data->nameid; + else + nameid=UNKNOWN_ITEM_ID; + }else + nameid=conv_num(st,data); + + amount=script_getnum(st,3); + iden=script_getnum(st,4); + ref=script_getnum(st,5); + attr=script_getnum(st,6); + c1=(short)script_getnum(st,7); + c2=(short)script_getnum(st,8); + c3=(short)script_getnum(st,9); + c4=(short)script_getnum(st,10); + + if(nameid<0) { // Invalide nameid + nameid = -nameid; + flag = 1; + } + + if(nameid > 0) { + memset(&item_tmp,0,sizeof(item_tmp)); + item_data=itemdb_exists(nameid); + if (item_data == NULL) + return -1; + if(item_data->type==IT_WEAPON || item_data->type==IT_ARMOR){ + if(ref > MAX_REFINE) ref = MAX_REFINE; + } + else if(item_data->type==IT_PETEGG) { + iden = 1; + ref = 0; + } + else { + iden = 1; + ref = attr = 0; + } + + item_tmp.nameid=nameid; + if(!flag) + item_tmp.identify=iden; + else if(item_data->type==IT_WEAPON || item_data->type==IT_ARMOR) + item_tmp.identify=0; + item_tmp.refine=ref; + item_tmp.attribute=attr; + item_tmp.card[0]=(short)c1; + item_tmp.card[1]=(short)c2; + item_tmp.card[2]=(short)c3; + item_tmp.card[3]=(short)c4; + + //Check if it's stackable. + if (!itemdb_isstackable(nameid)) + get_count = 1; + else + get_count = amount; + + for (i = 0; i < amount; i += get_count) + { + // if not pet egg + if (!pet_create_egg(sd, nameid)) + { + if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) + { + clif_additem(sd, 0, 0, flag); + if( pc_candrop(sd,&item_tmp) ) + map_addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + } + } + + return 0; } /*========================================== @@ -6322,49 +6480,57 @@ BUILDIN_FUNC(getitem2) *------------------------------------------*/ BUILDIN_FUNC(rentitem) { - struct map_session_data *sd; - struct script_data *data; - struct item it; - int seconds; - int nameid = 0, flag; - - data = script_getdata(st,2); - get_val(st,data); - - if ((sd = script_rid2sd(st)) == NULL) - return 0; - - if (data_isstring(data)) { - const char *name = conv_str(st,data); - struct item_data *itd = itemdb_searchname(name); - if (itd == NULL) { - ShowError("buildin_rentitem: Nonexistant item %s requested.\n", name); - return 1; - } - nameid = itd->nameid; - } else if (data_isint(data)) { - nameid = conv_num(st,data); - if (nameid <= 0 || !itemdb_exists(nameid)) { - ShowError("buildin_rentitem: Nonexistant item %d requested.\n", nameid); - return 1; - } - } else { - ShowError("buildin_rentitem: invalid data type for argument #1 (%d).\n", data->type); - return 1; - } - - seconds = script_getnum(st,3); - memset(&it, 0, sizeof(it)); - it.nameid = nameid; - it.identify = 1; - it.expire_time = (unsigned int)(time(NULL) + seconds); - - if ((flag = pc_additem(sd, &it, 1, LOG_TYPE_SCRIPT))) { - clif_additem(sd, 0, 0, flag); - return 1; - } - - return 0; + struct map_session_data *sd; + struct script_data *data; + struct item it; + int seconds; + int nameid = 0, flag; + + data = script_getdata(st,2); + get_val(st,data); + + if( (sd = script_rid2sd(st)) == NULL ) + return 0; + + if( data_isstring(data) ) + { + const char *name = conv_str(st,data); + struct item_data *itd = itemdb_searchname(name); + if( itd == NULL ) + { + ShowError("buildin_rentitem: Nonexistant item %s requested.\n", name); + return 1; + } + nameid = itd->nameid; + } + else if( data_isint(data) ) + { + nameid = conv_num(st,data); + if( nameid <= 0 || !itemdb_exists(nameid) ) + { + ShowError("buildin_rentitem: Nonexistant item %d requested.\n", nameid); + return 1; + } + } + else + { + ShowError("buildin_rentitem: invalid data type for argument #1 (%d).\n", data->type); + return 1; + } + + seconds = script_getnum(st,3); + memset(&it, 0, sizeof(it)); + it.nameid = nameid; + it.identify = 1; + it.expire_time = (unsigned int)(time(NULL) + seconds); + + if( (flag = pc_additem(sd, &it, 1, LOG_TYPE_SCRIPT)) ) + { + clif_additem(sd, 0, 0, flag); + return 1; + } + + return 0; } /*========================================== @@ -6375,65 +6541,65 @@ BUILDIN_FUNC(rentitem) *------------------------------------------*/ BUILDIN_FUNC(getnameditem) { - int nameid; - struct item item_tmp; - TBL_PC *sd, *tsd; - struct script_data *data; - - sd = script_rid2sd(st); - if (sd == NULL) { - //Player not attached! - script_pushint(st,0); - return 0; - } - - data=script_getdata(st,2); - get_val(st,data); - if (data_isstring(data)) { - const char *name=conv_str(st,data); - struct item_data *item_data = itemdb_searchname(name); - if (item_data == NULL) { - //Failed - script_pushint(st,0); - return 0; - } - nameid = item_data->nameid; - } else - nameid = conv_num(st,data); - - if (!itemdb_exists(nameid)/* || itemdb_isstackable(nameid)*/) { - //Even though named stackable items "could" be risky, they are required for certain quests. - script_pushint(st,0); - return 0; - } - - data=script_getdata(st,3); - get_val(st,data); - if (data_isstring(data)) //Char Name - tsd=map_nick2sd(conv_str(st,data)); - else //Char Id was given - tsd=map_charid2sd(conv_num(st,data)); - - if (tsd == NULL) { - //Failed - script_pushint(st,0); - return 0; - } - - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid=nameid; - item_tmp.amount=1; - item_tmp.identify=1; - item_tmp.card[0]=CARD0_CREATE; //we don't use 255! because for example SIGNED WEAPON shouldn't get TOP10 BS Fame bonus [Lupus] - item_tmp.card[2]=tsd->status.char_id; - item_tmp.card[3]=tsd->status.char_id >> 16; - if (pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT)) { - script_pushint(st,0); - return 0; //Failed to add item, we will not drop if they don't fit - } - - script_pushint(st,1); - return 0; + int nameid; + struct item item_tmp; + TBL_PC *sd, *tsd; + struct script_data *data; + + sd = script_rid2sd(st); + if (sd == NULL) + { //Player not attached! + script_pushint(st,0); + return 0; + } + + data=script_getdata(st,2); + get_val(st,data); + if( data_isstring(data) ){ + const char *name=conv_str(st,data); + struct item_data *item_data = itemdb_searchname(name); + if( item_data == NULL) + { //Failed + script_pushint(st,0); + return 0; + } + nameid = item_data->nameid; + }else + nameid = conv_num(st,data); + + if(!itemdb_exists(nameid)/* || itemdb_isstackable(nameid)*/) + { //Even though named stackable items "could" be risky, they are required for certain quests. + script_pushint(st,0); + return 0; + } + + data=script_getdata(st,3); + get_val(st,data); + if( data_isstring(data) ) //Char Name + tsd=map_nick2sd(conv_str(st,data)); + else //Char Id was given + tsd=map_charid2sd(conv_num(st,data)); + + if( tsd == NULL ) + { //Failed + script_pushint(st,0); + return 0; + } + + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid=nameid; + item_tmp.amount=1; + item_tmp.identify=1; + item_tmp.card[0]=CARD0_CREATE; //we don't use 255! because for example SIGNED WEAPON shouldn't get TOP10 BS Fame bonus [Lupus] + item_tmp.card[2]=tsd->status.char_id; + item_tmp.card[3]=tsd->status.char_id >> 16; + if(pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT)) { + script_pushint(st,0); + return 0; //Failed to add item, we will not drop if they don't fit + } + + script_pushint(st,1); + return 0; } /*========================================== @@ -6442,11 +6608,11 @@ BUILDIN_FUNC(getnameditem) *------------------------------------------*/ BUILDIN_FUNC(grouprandomitem) { - int group; + int group; - group = script_getnum(st,2); - script_pushint(st,itemdb_searchrandomid(group)); - return 0; + group = script_getnum(st,2); + script_pushint(st,itemdb_searchrandomid(group)); + return 0; } /*========================================== @@ -6454,76 +6620,78 @@ BUILDIN_FUNC(grouprandomitem) *------------------------------------------*/ BUILDIN_FUNC(makeitem) { - int nameid,amount,flag = 0; - int x,y,m; - const char *mapname; - struct item item_tmp; - struct script_data *data; - - data=script_getdata(st,2); - get_val(st,data); - if (data_isstring(data)) { - const char *name=conv_str(st,data); - struct item_data *item_data = itemdb_searchname(name); - if (item_data) - nameid=item_data->nameid; - else - nameid=UNKNOWN_ITEM_ID; - } else - nameid=conv_num(st,data); - - amount=script_getnum(st,3); - mapname =script_getstr(st,4); - x =script_getnum(st,5); - y =script_getnum(st,6); - - if (strcmp(mapname,"this")==0) { - TBL_PC *sd; - sd = script_rid2sd(st); - if (!sd) return 0; //Failed... - m=sd->bl.m; - } else - m=map_mapname2mapid(mapname); - - if (nameid<0) { - nameid = -nameid; - flag = 1; - } - - if (nameid > 0) { - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid=nameid; - if (!flag) - item_tmp.identify=1; - else - item_tmp.identify=itemdb_isidentified(nameid); - - map_addflooritem(&item_tmp,amount,m,x,y,0,0,0,0); - } - - return 0; + int nameid,amount,flag = 0; + int x,y,m; + const char *mapname; + struct item item_tmp; + struct script_data *data; + + data=script_getdata(st,2); + get_val(st,data); + if( data_isstring(data) ){ + const char *name=conv_str(st,data); + struct item_data *item_data = itemdb_searchname(name); + if( item_data ) + nameid=item_data->nameid; + else + nameid=UNKNOWN_ITEM_ID; + }else + nameid=conv_num(st,data); + + amount=script_getnum(st,3); + mapname =script_getstr(st,4); + x =script_getnum(st,5); + y =script_getnum(st,6); + + if(strcmp(mapname,"this")==0) + { + TBL_PC *sd; + sd = script_rid2sd(st); + if (!sd) return 0; //Failed... + m=sd->bl.m; + } else + m=map_mapname2mapid(mapname); + + if(nameid<0) { + nameid = -nameid; + flag = 1; + } + + if(nameid > 0) { + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid=nameid; + if(!flag) + item_tmp.identify=1; + else + item_tmp.identify=itemdb_isidentified(nameid); + + map_addflooritem(&item_tmp,amount,m,x,y,0,0,0,0); + } + + return 0; } /// Counts / deletes the current item given by idx. /// Used by buildin_delitem_search /// Relies on all input data being already fully valid. -static void buildin_delitem_delete(struct map_session_data *sd, int idx, int *amount, bool delete_items) +static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* amount, bool delete_items) { - int delamount; - struct item *inv = &sd->status.inventory[idx]; + int delamount; + struct item* inv = &sd->status.inventory[idx]; - delamount = (amount[0] < inv->amount) ? amount[0] : inv->amount; + delamount = ( amount[0] < inv->amount ) ? amount[0] : inv->amount; - if (delete_items) { - if (sd->inventory_data[idx]->type == IT_PETEGG && inv->card[0] == CARD0_PET) { - // delete associated pet - intif_delete_petdata(MakeDWord(inv->card[1], inv->card[2])); - } - pc_delitem(sd, idx, delamount, 0, 0, LOG_TYPE_SCRIPT); - } + if( delete_items ) + { + if( sd->inventory_data[idx]->type == IT_PETEGG && inv->card[0] == CARD0_PET ) + {// delete associated pet + intif_delete_petdata(MakeDWord(inv->card[1], inv->card[2])); + } + pc_delitem(sd, idx, delamount, 0, 0, LOG_TYPE_SCRIPT); + } - amount[0]-= delamount; + amount[0]-= delamount; } @@ -6532,103 +6700,116 @@ static void buildin_delitem_delete(struct map_session_data *sd, int idx, int *am /// Relies on all input data being already fully valid. /// @param exact_match will also match item attributes and cards, not just name id /// @return true when all items could be deleted, false when there were not enough items to delete -static bool buildin_delitem_search(struct map_session_data *sd, struct item *it, bool exact_match) -{ - bool delete_items = false; - int i, amount, important; - struct item *inv; - - // prefer always non-equipped items - it->equip = 0; - - // when searching for nameid only, prefer additionally - if (!exact_match) { - // non-refined items - it->refine = 0; - // card-less items - memset(it->card, 0, sizeof(it->card)); - } - - for (;;) { - amount = it->amount; - important = 0; - - // 1st pass -- less important items / exact match - for (i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++) { - inv = &sd->status.inventory[i]; - - if (!inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid) { - // wrong/invalid item - continue; - } - - if (inv->equip != it->equip || inv->refine != it->refine) { - // not matching attributes - important++; - continue; - } - - if (exact_match) { - if (inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card))) { - // not matching exact attributes - continue; - } - } else { - if (sd->inventory_data[i]->type == IT_PETEGG) { - if (inv->card[0] == CARD0_PET && CheckForCharServer()) { - // pet which cannot be deleted - continue; - } - } else if (memcmp(inv->card, it->card, sizeof(inv->card))) { - // named/carded item - important++; - continue; - } - } - - // count / delete item - buildin_delitem_delete(sd, i, &amount, delete_items); - } - - // 2nd pass -- any matching item - if (amount == 0 || important == 0) { - // either everything was already consumed or no items were skipped - ; - } else for (i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++) { - inv = &sd->status.inventory[i]; - - if (!inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid) { - // wrong/invalid item - continue; - } - - if (sd->inventory_data[i]->type == IT_PETEGG && inv->card[0] == CARD0_PET && CheckForCharServer()) { - // pet which cannot be deleted - continue; - } - - if (exact_match) { - if (inv->refine != it->refine || inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card))) { - // not matching attributes - continue; - } - } - - // count / delete item - buildin_delitem_delete(sd, i, &amount, delete_items); - } - - if (amount) { - // not enough items - return false; - } else if (delete_items) { - // we are done with the work - return true; - } else { - // get rid of the items now - delete_items = true; - } - } +static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, bool exact_match) +{ + bool delete_items = false; + int i, amount, important; + struct item* inv; + + // prefer always non-equipped items + it->equip = 0; + + // when searching for nameid only, prefer additionally + if( !exact_match ) + { + // non-refined items + it->refine = 0; + // card-less items + memset(it->card, 0, sizeof(it->card)); + } + + for(;;) + { + amount = it->amount; + important = 0; + + // 1st pass -- less important items / exact match + for( i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++ ) + { + inv = &sd->status.inventory[i]; + + if( !inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid ) + {// wrong/invalid item + continue; + } + + if( inv->equip != it->equip || inv->refine != it->refine ) + {// not matching attributes + important++; + continue; + } + + if( exact_match ) + { + if( inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card)) ) + {// not matching exact attributes + continue; + } + } + else + { + if( sd->inventory_data[i]->type == IT_PETEGG ) + { + if( inv->card[0] == CARD0_PET && CheckForCharServer() ) + {// pet which cannot be deleted + continue; + } + } + else if( memcmp(inv->card, it->card, sizeof(inv->card)) ) + {// named/carded item + important++; + continue; + } + } + + // count / delete item + buildin_delitem_delete(sd, i, &amount, delete_items); + } + + // 2nd pass -- any matching item + if( amount == 0 || important == 0 ) + {// either everything was already consumed or no items were skipped + ; + } + else for( i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++ ) + { + inv = &sd->status.inventory[i]; + + if( !inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid ) + {// wrong/invalid item + continue; + } + + if( sd->inventory_data[i]->type == IT_PETEGG && inv->card[0] == CARD0_PET && CheckForCharServer() ) + {// pet which cannot be deleted + continue; + } + + if( exact_match ) + { + if( inv->refine != it->refine || inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card)) ) + {// not matching attributes + continue; + } + } + + // count / delete item + buildin_delitem_delete(sd, i, &amount, delete_items); + } + + if( amount ) + {// not enough items + return false; + } + else if( delete_items ) + {// we are done with the work + return true; + } + else + {// get rid of the items now + delete_items = true; + } + } } @@ -6639,58 +6820,67 @@ static bool buildin_delitem_search(struct map_session_data *sd, struct item *it, /// delitem "<item name>",<amount>{,<account id>} BUILDIN_FUNC(delitem) { - TBL_PC *sd; - struct item it; - struct script_data *data; - - if (script_hasdata(st,4)) { - int account_id = script_getnum(st,4); - sd = map_id2sd(account_id); // <account id> - if (sd == NULL) { - ShowError("script:delitem: player not found (AID=%d).\n", account_id); - st->state = END; - return 1; - } - } else { - sd = script_rid2sd(st);// attached player - if (sd == NULL) - return 0; - } - - data = script_getdata(st,2); - get_val(st,data); - if (data_isstring(data)) { - const char *item_name = conv_str(st,data); - struct item_data *id = itemdb_searchname(item_name); - if (id == NULL) { - ShowError("script:delitem: unknown item \"%s\".\n", item_name); - st->state = END; - return 1; - } - it.nameid = id->nameid;// "<item name>" - } else { - it.nameid = conv_num(st,data);// <item id> - if (!itemdb_exists(it.nameid)) { - ShowError("script:delitem: unknown item \"%d\".\n", it.nameid); - st->state = END; - return 1; - } - } - - it.amount=script_getnum(st,3); - - if (it.amount <= 0) - return 0;// nothing to do - - if (buildin_delitem_search(sd, &it, false)) { - // success - return 0; - } - - ShowError("script:delitem: failed to delete %d items (AID=%d item_id=%d).\n", it.amount, sd->status.account_id, it.nameid); - st->state = END; - clif_scriptclose(sd, st->oid); - return 1; + TBL_PC *sd; + struct item it; + struct script_data *data; + + if( script_hasdata(st,4) ) + { + int account_id = script_getnum(st,4); + sd = map_id2sd(account_id); // <account id> + if( sd == NULL ) + { + ShowError("script:delitem: player not found (AID=%d).\n", account_id); + st->state = END; + return 1; + } + } + else + { + sd = script_rid2sd(st);// attached player + if( sd == NULL ) + return 0; + } + + data = script_getdata(st,2); + get_val(st,data); + if( data_isstring(data) ) + { + const char* item_name = conv_str(st,data); + struct item_data* id = itemdb_searchname(item_name); + if( id == NULL ) + { + ShowError("script:delitem: unknown item \"%s\".\n", item_name); + st->state = END; + return 1; + } + it.nameid = id->nameid;// "<item name>" + } + else + { + it.nameid = conv_num(st,data);// <item id> + if( !itemdb_exists( it.nameid ) ) + { + ShowError("script:delitem: unknown item \"%d\".\n", it.nameid); + st->state = END; + return 1; + } + } + + it.amount=script_getnum(st,3); + + if( it.amount <= 0 ) + return 0;// nothing to do + + if( buildin_delitem_search(sd, &it, false) ) + {// success + return 0; + } + + ShowError("script:delitem: failed to delete %d items (AID=%d item_id=%d).\n", it.amount, sd->status.account_id, it.nameid); + st->state = END; + clif_scriptclose(sd, st->oid); + return 1; } /// Deletes items from the target/attached player. @@ -6699,65 +6889,74 @@ BUILDIN_FUNC(delitem) /// delitem2 "<Item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>} BUILDIN_FUNC(delitem2) { - TBL_PC *sd; - struct item it; - struct script_data *data; - - if (script_hasdata(st,11)) { - int account_id = script_getnum(st,11); - sd = map_id2sd(account_id); // <account id> - if (sd == NULL) { - ShowError("script:delitem2: player not found (AID=%d).\n", account_id); - st->state = END; - return 1; - } - } else { - sd = script_rid2sd(st);// attached player - if (sd == NULL) - return 0; - } - - data = script_getdata(st,2); - get_val(st,data); - if (data_isstring(data)) { - const char *item_name = conv_str(st,data); - struct item_data *id = itemdb_searchname(item_name); - if (id == NULL) { - ShowError("script:delitem2: unknown item \"%s\".\n", item_name); - st->state = END; - return 1; - } - it.nameid = id->nameid;// "<item name>" - } else { - it.nameid = conv_num(st,data);// <item id> - if (!itemdb_exists(it.nameid)) { - ShowError("script:delitem: unknown item \"%d\".\n", it.nameid); - st->state = END; - return 1; - } - } - - it.amount=script_getnum(st,3); - it.identify=script_getnum(st,4); - it.refine=script_getnum(st,5); - it.attribute=script_getnum(st,6); - it.card[0]=(short)script_getnum(st,7); - it.card[1]=(short)script_getnum(st,8); - it.card[2]=(short)script_getnum(st,9); - it.card[3]=(short)script_getnum(st,10); - - if (it.amount <= 0) - return 0;// nothing to do - - if (buildin_delitem_search(sd, &it, true)) { - // success - return 0; - } - - ShowError("script:delitem2: failed to delete %d items (AID=%d item_id=%d).\n", it.amount, sd->status.account_id, it.nameid); - st->state = END; - clif_scriptclose(sd, st->oid); - return 1; + TBL_PC *sd; + struct item it; + struct script_data *data; + + if( script_hasdata(st,11) ) + { + int account_id = script_getnum(st,11); + sd = map_id2sd(account_id); // <account id> + if( sd == NULL ) + { + ShowError("script:delitem2: player not found (AID=%d).\n", account_id); + st->state = END; + return 1; + } + } + else + { + sd = script_rid2sd(st);// attached player + if( sd == NULL ) + return 0; + } + + data = script_getdata(st,2); + get_val(st,data); + if( data_isstring(data) ) + { + const char* item_name = conv_str(st,data); + struct item_data* id = itemdb_searchname(item_name); + if( id == NULL ) + { + ShowError("script:delitem2: unknown item \"%s\".\n", item_name); + st->state = END; + return 1; + } + it.nameid = id->nameid;// "<item name>" + } + else + { + it.nameid = conv_num(st,data);// <item id> + if( !itemdb_exists( it.nameid ) ) + { + ShowError("script:delitem: unknown item \"%d\".\n", it.nameid); + st->state = END; + return 1; + } + } + + it.amount=script_getnum(st,3); + it.identify=script_getnum(st,4); + it.refine=script_getnum(st,5); + it.attribute=script_getnum(st,6); + it.card[0]=(short)script_getnum(st,7); + it.card[1]=(short)script_getnum(st,8); + it.card[2]=(short)script_getnum(st,9); + it.card[3]=(short)script_getnum(st,10); + + if( it.amount <= 0 ) + return 0;// nothing to do + + if( buildin_delitem_search(sd, &it, true) ) + {// success + return 0; + } + + ShowError("script:delitem2: failed to delete %d items (AID=%d item_id=%d).\n", it.amount, sd->status.account_id, it.nameid); + st->state = END; + clif_scriptclose(sd, st->oid); + return 1; } /*========================================== @@ -6765,20 +6964,20 @@ BUILDIN_FUNC(delitem2) *------------------------------------------*/ BUILDIN_FUNC(enableitemuse) { - TBL_PC *sd; - sd=script_rid2sd(st); - if (sd) - sd->npc_item_flag = st->oid; - return 0; + TBL_PC *sd; + sd=script_rid2sd(st); + if (sd) + sd->npc_item_flag = st->oid; + return 0; } BUILDIN_FUNC(disableitemuse) { - TBL_PC *sd; - sd=script_rid2sd(st); - if (sd) - sd->npc_item_flag = 0; - return 0; + TBL_PC *sd; + sd=script_rid2sd(st); + if (sd) + sd->npc_item_flag = 0; + return 0; } /*========================================== @@ -6787,102 +6986,93 @@ BUILDIN_FUNC(disableitemuse) *------------------------------------------*/ BUILDIN_FUNC(readparam) { - int type; - TBL_PC *sd; + int type; + TBL_PC *sd; - type=script_getnum(st,2); - if (script_hasdata(st,3)) - sd=map_nick2sd(script_getstr(st,3)); - else - sd=script_rid2sd(st); + type=script_getnum(st,2); + if( script_hasdata(st,3) ) + sd=map_nick2sd(script_getstr(st,3)); + else + sd=script_rid2sd(st); - if (sd==NULL) { - script_pushint(st,-1); - return 0; - } + if(sd==NULL){ + script_pushint(st,-1); + return 0; + } - script_pushint(st,pc_readparam(sd,type)); + script_pushint(st,pc_readparam(sd,type)); - return 0; + return 0; } /*========================================== * Return charid identification * return by @num : - * 0 : char_id - * 1 : party_id - * 2 : guild_id - * 3 : account_id - * 4 : bg_id + * 0 : char_id + * 1 : party_id + * 2 : guild_id + * 3 : account_id + * 4 : bg_id *------------------------------------------*/ BUILDIN_FUNC(getcharid) { - int num; - TBL_PC *sd; - - num = script_getnum(st,2); - if (script_hasdata(st,3)) - sd=map_nick2sd(script_getstr(st,3)); - else - sd=script_rid2sd(st); - - if (sd==NULL) { - script_pushint(st,0); //return 0, according docs - return 0; - } - - switch (num) { - case 0: - script_pushint(st,sd->status.char_id); - break; - case 1: - script_pushint(st,sd->status.party_id); - break; - case 2: - script_pushint(st,sd->status.guild_id); - break; - case 3: - script_pushint(st,sd->status.account_id); - break; - case 4: - script_pushint(st,sd->bg_id); - break; - default: - ShowError("buildin_getcharid: invalid parameter (%d).\n", num); - script_pushint(st,0); - break; - } - - return 0; + int num; + TBL_PC *sd; + + num = script_getnum(st,2); + if( script_hasdata(st,3) ) + sd=map_nick2sd(script_getstr(st,3)); + else + sd=script_rid2sd(st); + + if(sd==NULL){ + script_pushint(st,0); //return 0, according docs + return 0; + } + + switch( num ) { + case 0: script_pushint(st,sd->status.char_id); break; + case 1: script_pushint(st,sd->status.party_id); break; + case 2: script_pushint(st,sd->status.guild_id); break; + case 3: script_pushint(st,sd->status.account_id); break; + case 4: script_pushint(st,sd->bg_id); break; + default: + ShowError("buildin_getcharid: invalid parameter (%d).\n", num); + script_pushint(st,0); + break; + } + + return 0; } /*========================================== * returns the GID of an NPC *------------------------------------------*/ BUILDIN_FUNC(getnpcid) { - int num = script_getnum(st,2); - struct npc_data *nd = NULL; + int num = script_getnum(st,2); + struct npc_data* nd = NULL; - if (script_hasdata(st,3)) { - // unique npc name - if ((nd = npc_name2id(script_getstr(st,3))) == NULL) { - ShowError("buildin_getnpcid: No such NPC '%s'.\n", script_getstr(st,3)); - script_pushint(st,0); - return 1; - } - } + if( script_hasdata(st,3) ) + {// unique npc name + if( ( nd = npc_name2id(script_getstr(st,3)) ) == NULL ) + { + ShowError("buildin_getnpcid: No such NPC '%s'.\n", script_getstr(st,3)); + script_pushint(st,0); + return 1; + } + } - switch (num) { - case 0: - script_pushint(st,nd ? nd->bl.id : st->oid); - break; - default: - ShowError("buildin_getnpcid: invalid parameter (%d).\n", num); - script_pushint(st,0); - return 1; - } + switch (num) { + case 0: + script_pushint(st,nd ? nd->bl.id : st->oid); + break; + default: + ShowError("buildin_getnpcid: invalid parameter (%d).\n", num); + script_pushint(st,0); + return 1; + } - return 0; + return 0; } /*========================================== @@ -6891,57 +7081,60 @@ BUILDIN_FUNC(getnpcid) *------------------------------------------*/ BUILDIN_FUNC(getpartyname) { - int party_id; - struct party_data *p; + int party_id; + struct party_data* p; - party_id = script_getnum(st,2); + party_id = script_getnum(st,2); - if ((p = party_search(party_id)) != NULL) { - script_pushstrcopy(st,p->party.name); - } else { - script_pushconststr(st,"null"); - } - return 0; + if( ( p = party_search(party_id) ) != NULL ) + { + script_pushstrcopy(st,p->party.name); + } + else + { + script_pushconststr(st,"null"); + } + return 0; } /*========================================== * Get the information of the members of a party by type * @party_id, @type * return by @type : - * - : nom des membres - * 1 : char_id des membres - * 2 : account_id des membres + * - : nom des membres + * 1 : char_id des membres + * 2 : account_id des membres *------------------------------------------*/ BUILDIN_FUNC(getpartymember) { - struct party_data *p; - int i,j=0,type=0; - - p=party_search(script_getnum(st,2)); - - if (script_hasdata(st,3)) - type=script_getnum(st,3); - - if (p!=NULL) { - for (i=0; i<MAX_PARTY; i++) { - if (p->party.member[i].account_id) { - switch (type) { - case 2: - mapreg_setreg(reference_uid(add_str("$@partymemberaid"), j),p->party.member[i].account_id); - break; - case 1: - mapreg_setreg(reference_uid(add_str("$@partymembercid"), j),p->party.member[i].char_id); - break; - default: - mapreg_setregstr(reference_uid(add_str("$@partymembername$"), j),p->party.member[i].name); - } - j++; - } - } - } - mapreg_setreg(add_str("$@partymembercount"),j); + struct party_data *p; + int i,j=0,type=0; - return 0; + p=party_search(script_getnum(st,2)); + + if( script_hasdata(st,3) ) + type=script_getnum(st,3); + + if(p!=NULL){ + for(i=0;i<MAX_PARTY;i++){ + if(p->party.member[i].account_id){ + switch (type) { + case 2: + mapreg_setreg(reference_uid(add_str("$@partymemberaid"), j),p->party.member[i].account_id); + break; + case 1: + mapreg_setreg(reference_uid(add_str("$@partymembercid"), j),p->party.member[i].char_id); + break; + default: + mapreg_setregstr(reference_uid(add_str("$@partymembername$"), j),p->party.member[i].name); + } + j++; + } + } + } + mapreg_setreg(add_str("$@partymembercount"),j); + + return 0; } /*========================================== @@ -6950,47 +7143,35 @@ BUILDIN_FUNC(getpartymember) *------------------------------------------*/ BUILDIN_FUNC(getpartyleader) { - int party_id, type = 0, i=0; - struct party_data *p; + int party_id, type = 0, i=0; + struct party_data *p; - party_id=script_getnum(st,2); - if (script_hasdata(st,3)) - type=script_getnum(st,3); + party_id=script_getnum(st,2); + if( script_hasdata(st,3) ) + type=script_getnum(st,3); - p=party_search(party_id); + p=party_search(party_id); - if (p) //Search leader - for (i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++); + if (p) //Search leader + for(i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++); - if (!p || i == MAX_PARTY) { //leader not found - if (type) - script_pushint(st,-1); - else - script_pushconststr(st,"null"); - return 0; - } + if (!p || i == MAX_PARTY) { //leader not found + if (type) + script_pushint(st,-1); + else + script_pushconststr(st,"null"); + return 0; + } - switch (type) { - case 1: - script_pushint(st,p->party.member[i].account_id); - break; - case 2: - script_pushint(st,p->party.member[i].char_id); - break; - case 3: - script_pushint(st,p->party.member[i].class_); - break; - case 4: - script_pushstrcopy(st,mapindex_id2name(p->party.member[i].map)); - break; - case 5: - script_pushint(st,p->party.member[i].lv); - break; - default: - script_pushstrcopy(st,p->party.member[i].name); - break; - } - return 0; + switch (type) { + case 1: script_pushint(st,p->party.member[i].account_id); break; + case 2: script_pushint(st,p->party.member[i].char_id); break; + case 3: script_pushint(st,p->party.member[i].class_); break; + case 4: script_pushstrcopy(st,mapindex_id2name(p->party.member[i].map)); break; + case 5: script_pushint(st,p->party.member[i].lv); break; + default: script_pushstrcopy(st,p->party.member[i].name); break; + } + return 0; } /*========================================== @@ -6999,17 +7180,20 @@ BUILDIN_FUNC(getpartyleader) *------------------------------------------*/ BUILDIN_FUNC(getguildname) { - int guild_id; - struct guild *g; + int guild_id; + struct guild* g; - guild_id = script_getnum(st,2); + guild_id = script_getnum(st,2); - if ((g = guild_search(guild_id)) != NULL) { - script_pushstrcopy(st,g->name); - } else { - script_pushconststr(st,"null"); - } - return 0; + if( ( g = guild_search(guild_id) ) != NULL ) + { + script_pushstrcopy(st,g->name); + } + else + { + script_pushconststr(st,"null"); + } + return 0; } /*========================================== @@ -7018,137 +7202,150 @@ BUILDIN_FUNC(getguildname) *------------------------------------------*/ BUILDIN_FUNC(getguildmaster) { - int guild_id; - struct guild *g; + int guild_id; + struct guild* g; - guild_id = script_getnum(st,2); + guild_id = script_getnum(st,2); - if ((g = guild_search(guild_id)) != NULL) { - script_pushstrcopy(st,g->member[0].name); - } else { - script_pushconststr(st,"null"); - } - return 0; + if( ( g = guild_search(guild_id) ) != NULL ) + { + script_pushstrcopy(st,g->member[0].name); + } + else + { + script_pushconststr(st,"null"); + } + return 0; } BUILDIN_FUNC(getguildmasterid) { - int guild_id; - struct guild *g; + int guild_id; + struct guild* g; - guild_id = script_getnum(st,2); + guild_id = script_getnum(st,2); - if ((g = guild_search(guild_id)) != NULL) { - script_pushint(st,g->member[0].char_id); - } else { - script_pushint(st,0); - } - return 0; + if( ( g = guild_search(guild_id) ) != NULL ) + { + script_pushint(st,g->member[0].char_id); + } + else + { + script_pushint(st,0); + } + return 0; } /*========================================== * Get char string information by type : * Return by @type : - * 0 : char_name - * 1 : party_name or "" - * 2 : guild_name or "" - * 3 : map_name - * - : "" + * 0 : char_name + * 1 : party_name or "" + * 2 : guild_name or "" + * 3 : map_name + * - : "" *------------------------------------------*/ BUILDIN_FUNC(strcharinfo) { - TBL_PC *sd; - int num; - struct guild *g; - struct party_data *p; - - sd=script_rid2sd(st); - if (!sd) { //Avoid crashing.... - script_pushconststr(st,""); - return 0; - } - num=script_getnum(st,2); - switch (num) { - case 0: - script_pushstrcopy(st,sd->status.name); - break; - case 1: - if ((p = party_search(sd->status.party_id)) != NULL) { - script_pushstrcopy(st,p->party.name); - } else { - script_pushconststr(st,""); - } - break; - case 2: - if ((g = guild_search(sd->status.guild_id)) != NULL) { - script_pushstrcopy(st,g->name); - } else { - script_pushconststr(st,""); - } - break; - case 3: - script_pushconststr(st,map[sd->bl.m].name); - break; - default: - ShowWarning("buildin_strcharinfo: unknown parameter.\n"); - script_pushconststr(st,""); - break; - } - - return 0; + TBL_PC *sd; + int num; + struct guild* g; + struct party_data* p; + + sd=script_rid2sd(st); + if (!sd) { //Avoid crashing.... + script_pushconststr(st,""); + return 0; + } + num=script_getnum(st,2); + switch(num){ + case 0: + script_pushstrcopy(st,sd->status.name); + break; + case 1: + if( ( p = party_search(sd->status.party_id) ) != NULL ) + { + script_pushstrcopy(st,p->party.name); + } + else + { + script_pushconststr(st,""); + } + break; + case 2: + if( ( g = guild_search(sd->status.guild_id) ) != NULL ) + { + script_pushstrcopy(st,g->name); + } + else + { + script_pushconststr(st,""); + } + break; + case 3: + script_pushconststr(st,map[sd->bl.m].name); + break; + default: + ShowWarning("buildin_strcharinfo: unknown parameter.\n"); + script_pushconststr(st,""); + break; + } + + return 0; } /*========================================== * Get npc string information by type * return by @type: - * 0 : name - * 1 : str# - * 2 : #str - * 3 : ::str - * 4 : map name + * 0 : name + * 1 : str# + * 2 : #str + * 3 : ::str + * 4 : map name *------------------------------------------*/ BUILDIN_FUNC(strnpcinfo) { - TBL_NPC *nd; - int num; - char *buf,*name=NULL; - - nd = map_id2nd(st->oid); - if (!nd) { - script_pushconststr(st, ""); - return 0; - } - - num = script_getnum(st,2); - switch (num) { - case 0: // display name - name = aStrdup(nd->name); - break; - case 1: // visible part of display name - if ((buf = strchr(nd->name,'#')) != NULL) { - name = aStrdup(nd->name); - name[buf - nd->name] = 0; - } else // Return the name, there is no '#' present - name = aStrdup(nd->name); - break; - case 2: // # fragment - if ((buf = strchr(nd->name,'#')) != NULL) - name = aStrdup(buf+1); - break; - case 3: // unique name - name = aStrdup(nd->exname); - break; - case 4: // map name - name = aStrdup(map[nd->bl.m].name); - break; - } - - if (name) - script_pushstr(st, name); - else - script_pushconststr(st, ""); - - return 0; + TBL_NPC* nd; + int num; + char *buf,*name=NULL; + + nd = map_id2nd(st->oid); + if (!nd) { + script_pushconststr(st, ""); + return 0; + } + + num = script_getnum(st,2); + switch(num){ + case 0: // display name + name = aStrdup(nd->name); + break; + case 1: // visible part of display name + if((buf = strchr(nd->name,'#')) != NULL) + { + name = aStrdup(nd->name); + name[buf - nd->name] = 0; + } else // Return the name, there is no '#' present + name = aStrdup(nd->name); + break; + case 2: // # fragment + if((buf = strchr(nd->name,'#')) != NULL) + name = aStrdup(buf+1); + break; + case 3: // unique name + name = aStrdup(nd->exname); + break; + case 4: // map name + name = aStrdup(map[nd->bl.m].name); + break; + } + + if(name) + script_pushstr(st, name); + else + script_pushconststr(st, ""); + + return 0; } @@ -7160,34 +7357,36 @@ static unsigned int equip[] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_ *------------------------------------------*/ BUILDIN_FUNC(getequipid) { - int i, num; - TBL_PC *sd; - struct item_data *item; + int i, num; + TBL_PC* sd; + struct item_data* item; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - num = script_getnum(st,2) - 1; - if (num < 0 || num >= ARRAYLENGTH(equip)) { - script_pushint(st,-1); - return 0; - } + num = script_getnum(st,2) - 1; + if( num < 0 || num >= ARRAYLENGTH(equip) ) + { + script_pushint(st,-1); + return 0; + } - // get inventory position of item - i = pc_checkequip(sd,equip[num]); - if (i < 0) { - script_pushint(st,-1); - return 0; - } + // get inventory position of item + i = pc_checkequip(sd,equip[num]); + if( i < 0 ) + { + script_pushint(st,-1); + return 0; + } - item = sd->inventory_data[i]; - if (item != 0) - script_pushint(st,item->nameid); - else - script_pushint(st,0); + item = sd->inventory_data[i]; + if( item != 0 ) + script_pushint(st,item->nameid); + else + script_pushint(st,0); - return 0; + return 0; } /*========================================== @@ -7196,34 +7395,36 @@ BUILDIN_FUNC(getequipid) *------------------------------------------*/ BUILDIN_FUNC(getequipname) { - int i, num; - TBL_PC *sd; - struct item_data *item; + int i, num; + TBL_PC* sd; + struct item_data* item; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - num = script_getnum(st,2) - 1; - if (num < 0 || num >= ARRAYLENGTH(equip)) { - script_pushconststr(st,""); - return 0; - } + num = script_getnum(st,2) - 1; + if( num < 0 || num >= ARRAYLENGTH(equip) ) + { + script_pushconststr(st,""); + return 0; + } - // get inventory position of item - i = pc_checkequip(sd,equip[num]); - if (i < 0) { - script_pushint(st,-1); - return 0; - } + // get inventory position of item + i = pc_checkequip(sd,equip[num]); + if( i < 0 ) + { + script_pushint(st,-1); + return 0; + } - item = sd->inventory_data[i]; - if (item != 0) - script_pushstrcopy(st,item->jname); - else - script_pushconststr(st,""); + item = sd->inventory_data[i]; + if( item != 0 ) + script_pushstrcopy(st,item->jname); + else + script_pushconststr(st,""); - return 0; + return 0; } /*========================================== @@ -7231,27 +7432,27 @@ BUILDIN_FUNC(getequipname) *------------------------------------------*/ BUILDIN_FUNC(getbrokenid) { - int i,num,id=0,brokencounter=0; - TBL_PC *sd; + int i,num,id=0,brokencounter=0; + TBL_PC *sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - num=script_getnum(st,2); - for (i=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].attribute) { - brokencounter++; - if (num==brokencounter) { - id=sd->status.inventory[i].nameid; - break; - } - } - } + num=script_getnum(st,2); + for(i=0; i<MAX_INVENTORY; i++) { + if(sd->status.inventory[i].attribute){ + brokencounter++; + if(num==brokencounter){ + id=sd->status.inventory[i].nameid; + break; + } + } + } - script_pushint(st,id); + script_pushint(st,id); - return 0; + return 0; } /*========================================== @@ -7259,29 +7460,29 @@ BUILDIN_FUNC(getbrokenid) *------------------------------------------*/ BUILDIN_FUNC(repair) { - int i,num; - int repaircounter=0; - TBL_PC *sd; + int i,num; + int repaircounter=0; + TBL_PC *sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - num=script_getnum(st,2); - for (i=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].attribute) { - repaircounter++; - if (num==repaircounter) { - sd->status.inventory[i].attribute=0; - clif_equiplist(sd); - clif_produceeffect(sd, 0, sd->status.inventory[i].nameid); - clif_misceffect(&sd->bl, 3); - break; - } - } - } + num=script_getnum(st,2); + for(i=0; i<MAX_INVENTORY; i++) { + if(sd->status.inventory[i].attribute){ + repaircounter++; + if(num==repaircounter){ + sd->status.inventory[i].attribute=0; + clif_equiplist(sd); + clif_produceeffect(sd, 0, sd->status.inventory[i].nameid); + clif_misceffect(&sd->bl, 3); + break; + } + } + } - return 0; + return 0; } /*========================================== @@ -7289,27 +7490,30 @@ BUILDIN_FUNC(repair) *------------------------------------------*/ BUILDIN_FUNC(repairall) { - int i, repaircounter = 0; - TBL_PC *sd; + int i, repaircounter = 0; + TBL_PC *sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if(sd == NULL) + return 0; - for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid && sd->status.inventory[i].attribute) { - sd->status.inventory[i].attribute = 0; - clif_produceeffect(sd,0,sd->status.inventory[i].nameid); - repaircounter++; - } - } + for(i = 0; i < MAX_INVENTORY; i++) + { + if(sd->status.inventory[i].nameid && sd->status.inventory[i].attribute) + { + sd->status.inventory[i].attribute = 0; + clif_produceeffect(sd,0,sd->status.inventory[i].nameid); + repaircounter++; + } + } - if (repaircounter) { - clif_misceffect(&sd->bl, 3); - clif_equiplist(sd); - } + if(repaircounter) + { + clif_misceffect(&sd->bl, 3); + clif_equiplist(sd); + } - return 0; + return 0; } /*========================================== @@ -7317,154 +7521,154 @@ BUILDIN_FUNC(repairall) *------------------------------------------*/ BUILDIN_FUNC(getequipisequiped) { - int i = -1,num; - TBL_PC *sd; + int i = -1,num; + TBL_PC *sd; - num = script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); - if (i >= 0) - script_pushint(st,1); - else - script_pushint(st,0); - return 0; + if(i >= 0) + script_pushint(st,1); + else + script_pushint(st,0); + return 0; } /*========================================== * Chk if the player have something equiped at pos * if so chk if this item ain't marked not refinable or rental * return (npc) - * 1 : true - * 0 : false + * 1 : true + * 0 : false *------------------------------------------*/ BUILDIN_FUNC(getequipisenableref) { - int i = -1,num; - TBL_PC *sd; + int i = -1,num; + TBL_PC *sd; - num = script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - if (num > 0 && num <= ARRAYLENGTH(equip)) - i = pc_checkequip(sd,equip[num-1]); - if (i >= 0 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine && !sd->status.inventory[i].expire_time) - script_pushint(st,1); - else - script_pushint(st,0); + if( num > 0 && num <= ARRAYLENGTH(equip) ) + i = pc_checkequip(sd,equip[num-1]); + if( i >= 0 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine && !sd->status.inventory[i].expire_time ) + script_pushint(st,1); + else + script_pushint(st,0); - return 0; + return 0; } /*========================================== * Chk if the item equiped at pos is identify (huh ?) * return (npc) - * 1 : true - * 0 : false + * 1 : true + * 0 : false *------------------------------------------*/ BUILDIN_FUNC(getequipisidentify) { - int i = -1,num; - TBL_PC *sd; + int i = -1,num; + TBL_PC *sd; - num = script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); - if (i >= 0) - script_pushint(st,sd->status.inventory[i].identify); - else - script_pushint(st,0); + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); + if(i >= 0) + script_pushint(st,sd->status.inventory[i].identify); + else + script_pushint(st,0); - return 0; + return 0; } /*========================================== * Get the item refined value at pos * return (npc) - * x : refine amount - * 0 : false (not refined) + * x : refine amount + * 0 : false (not refined) *------------------------------------------*/ BUILDIN_FUNC(getequiprefinerycnt) { - int i = -1,num; - TBL_PC *sd; + int i = -1,num; + TBL_PC *sd; - num = script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); - if (i >= 0) - script_pushint(st,sd->status.inventory[i].refine); - else - script_pushint(st,0); + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); + if(i >= 0) + script_pushint(st,sd->status.inventory[i].refine); + else + script_pushint(st,0); - return 0; + return 0; } /*========================================== * Get the weapon level value at pos * (pos should normally only be EQI_HAND_L or EQI_HAND_R) * return (npc) - * x : weapon level - * 0 : false + * x : weapon level + * 0 : false *------------------------------------------*/ BUILDIN_FUNC(getequipweaponlv) { - int i = -1,num; - TBL_PC *sd; + int i = -1,num; + TBL_PC *sd; - num = script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); - if (i >= 0 && sd->inventory_data[i]) - script_pushint(st,sd->inventory_data[i]->wlv); - else - script_pushint(st,0); + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); + if(i >= 0 && sd->inventory_data[i]) + script_pushint(st,sd->inventory_data[i]->wlv); + else + script_pushint(st,0); - return 0; + return 0; } /*========================================== * Get the item refine chance (from refine.txt) for item at pos * return (npc) - * x : refine chance - * 0 : false (max refine level or unequip..) + * x : refine chance + * 0 : false (max refine level or unequip..) *------------------------------------------*/ BUILDIN_FUNC(getequippercentrefinery) { - int i = -1,num; - TBL_PC *sd; + int i = -1,num; + TBL_PC *sd; - num = script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); - if (i >= 0 && sd->status.inventory[i].nameid && sd->status.inventory[i].refine < MAX_REFINE) - script_pushint(st,status_get_refine_chance(itemdb_wlv(sd->status.inventory[i].nameid), (int)sd->status.inventory[i].refine)); - else - script_pushint(st,0); + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); + if(i >= 0 && sd->status.inventory[i].nameid && sd->status.inventory[i].refine < MAX_REFINE) + script_pushint(st,status_get_refine_chance(itemdb_wlv(sd->status.inventory[i].nameid), (int)sd->status.inventory[i].refine)); + else + script_pushint(st,0); - return 0; + return 0; } /*========================================== @@ -7472,53 +7676,53 @@ BUILDIN_FUNC(getequippercentrefinery) *------------------------------------------*/ BUILDIN_FUNC(successrefitem) { - int i=-1,num,ep; - TBL_PC *sd; - - num = script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; - - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); - if (i >= 0) { - ep=sd->status.inventory[i].equip; - - //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i]); - - sd->status.inventory[i].refine++; - pc_unequipitem(sd,i,2); // status calc will happen in pc_equipitem() below - - clif_refine(sd->fd,0,i,sd->status.inventory[i].refine); - clif_delitem(sd,i,1,3); - - //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i]); - - clif_additem(sd,i,1,0); - pc_equipitem(sd,i,ep); - clif_misceffect(&sd->bl,3); - if (sd->status.inventory[i].refine == MAX_REFINE && - sd->status.inventory[i].card[0] == CARD0_FORGE && - sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3]) - ) { // Fame point system [DracoRPG] - switch (sd->inventory_data[i]->wlv) { - case 1: - pc_addfame(sd,1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point - break; - case 2: - pc_addfame(sd,25); // Success to refine to +10 a lv2 weapon you forged = +25 fame point - break; - case 3: - pc_addfame(sd,1000); // Success to refine to +10 a lv3 weapon you forged = +1000 fame point - break; - } - } - } - - return 0; + int i=-1,num,ep; + TBL_PC *sd; + + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; + + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); + if(i >= 0) { + ep=sd->status.inventory[i].equip; + + //Logs items, got from (N)PC scripts [Lupus] + log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i]); + + sd->status.inventory[i].refine++; + pc_unequipitem(sd,i,2); // status calc will happen in pc_equipitem() below + + clif_refine(sd->fd,0,i,sd->status.inventory[i].refine); + clif_delitem(sd,i,1,3); + + //Logs items, got from (N)PC scripts [Lupus] + log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i]); + + clif_additem(sd,i,1,0); + pc_equipitem(sd,i,ep); + clif_misceffect(&sd->bl,3); + if(sd->status.inventory[i].refine == MAX_REFINE && + sd->status.inventory[i].card[0] == CARD0_FORGE && + sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3]) + ){ // Fame point system [DracoRPG] + switch (sd->inventory_data[i]->wlv){ + case 1: + pc_addfame(sd,1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point + break; + case 2: + pc_addfame(sd,25); // Success to refine to +10 a lv2 weapon you forged = +25 fame point + break; + case 3: + pc_addfame(sd,1000); // Success to refine to +10 a lv3 weapon you forged = +1000 fame point + break; + } + } + } + + return 0; } /*========================================== @@ -7526,27 +7730,27 @@ BUILDIN_FUNC(successrefitem) *------------------------------------------*/ BUILDIN_FUNC(failedrefitem) { - int i=-1,num; - TBL_PC *sd; + int i=-1,num; + TBL_PC *sd; - num = script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); - if (i >= 0) { - sd->status.inventory[i].refine = 0; - pc_unequipitem(sd,i,3); //recalculate bonus - clif_refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); + if(i >= 0) { + sd->status.inventory[i].refine = 0; + pc_unequipitem(sd,i,3); //recalculate bonus + clif_refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure - pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); - clif_misceffect(&sd->bl,2); // display failure effect - } + clif_misceffect(&sd->bl,2); // display failure effect + } - return 0; + return 0; } /*========================================== @@ -7554,37 +7758,37 @@ BUILDIN_FUNC(failedrefitem) *------------------------------------------*/ BUILDIN_FUNC(downrefitem) { - int i = -1,num,ep; - TBL_PC *sd; + int i = -1,num,ep; + TBL_PC *sd; - num = script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - if (num > 0 && num <= ARRAYLENGTH(equip)) - i = pc_checkequip(sd,equip[num-1]); - if (i >= 0) { - ep = sd->status.inventory[i].equip; + if (num > 0 && num <= ARRAYLENGTH(equip)) + i = pc_checkequip(sd,equip[num-1]); + if(i >= 0) { + ep = sd->status.inventory[i].equip; - //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i]); + //Logs items, got from (N)PC scripts [Lupus] + log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i]); - sd->status.inventory[i].refine++; - pc_unequipitem(sd,i,2); // status calc will happen in pc_equipitem() below + sd->status.inventory[i].refine++; + pc_unequipitem(sd,i,2); // status calc will happen in pc_equipitem() below - clif_refine(sd->fd,2,i,sd->status.inventory[i].refine = sd->status.inventory[i].refine - 2); - clif_delitem(sd,i,1,3); + clif_refine(sd->fd,2,i,sd->status.inventory[i].refine = sd->status.inventory[i].refine - 2); + clif_delitem(sd,i,1,3); - //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i]); + //Logs items, got from (N)PC scripts [Lupus] + log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i]); - clif_additem(sd,i,1,0); - pc_equipitem(sd,i,ep); - clif_misceffect(&sd->bl,2); - } + clif_additem(sd,i,1,0); + pc_equipitem(sd,i,ep); + clif_misceffect(&sd->bl,2); + } - return 0; + return 0; } /*========================================== @@ -7592,35 +7796,35 @@ BUILDIN_FUNC(downrefitem) *------------------------------------------*/ BUILDIN_FUNC(statusup) { - int type; - TBL_PC *sd; + int type; + TBL_PC *sd; - type=script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + type=script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - pc_statusup(sd,type); + pc_statusup(sd,type); - return 0; + return 0; } /*========================================== * *------------------------------------------*/ BUILDIN_FUNC(statusup2) { - int type,val; - TBL_PC *sd; + int type,val; + TBL_PC *sd; - type=script_getnum(st,2); - val=script_getnum(st,3); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + type=script_getnum(st,2); + val=script_getnum(st,3); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - pc_statusup2(sd,type,val); + pc_statusup2(sd,type,val); - return 0; + return 0; } /// See 'doc/item_bonus.txt' @@ -7632,189 +7836,192 @@ BUILDIN_FUNC(statusup2) /// bonus5 <bonus type>,<val1>,<val2>,<val3>,<val4>,<val5>; BUILDIN_FUNC(bonus) { - int type; - int val1; - int val2 = 0; - int val3 = 0; - int val4 = 0; - int val5 = 0; - TBL_PC *sd; - - sd = script_rid2sd(st); - if (sd == NULL) - return 0; // no player attached - - type = script_getnum(st,2); - switch (type) { - case SP_AUTOSPELL: - case SP_AUTOSPELL_WHENHIT: - case SP_AUTOSPELL_ONSKILL: - case SP_SKILL_ATK: - case SP_SKILL_HEAL: - case SP_SKILL_HEAL2: - case SP_ADD_SKILL_BLOW: - case SP_CASTRATE: - case SP_ADDEFF_ONSKILL: - case SP_SKILL_USE_SP_RATE: - case SP_SKILL_COOLDOWN: - case SP_SKILL_FIXEDCAST: - case SP_SKILL_VARIABLECAST: - case SP_VARCASTRATE: - case SP_SKILL_USE_SP: - // these bonuses support skill names - val1 = (script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3)); - break; - default: - val1 = script_getnum(st,3); - break; - } - - switch (script_lastdata(st)-2) { - case 1: - pc_bonus(sd, type, val1); - break; - case 2: - val2 = script_getnum(st,4); - pc_bonus2(sd, type, val1, val2); - break; - case 3: - val2 = script_getnum(st,4); - val3 = script_getnum(st,5); - pc_bonus3(sd, type, val1, val2, val3); - break; - case 4: - if (type == SP_AUTOSPELL_ONSKILL && script_isstring(st,4)) - val2 = skill_name2id(script_getstr(st,4)); // 2nd value can be skill name - else - val2 = script_getnum(st,4); - - val3 = script_getnum(st,5); - val4 = script_getnum(st,6); - pc_bonus4(sd, type, val1, val2, val3, val4); - break; - case 5: - if (type == SP_AUTOSPELL_ONSKILL && script_isstring(st,4)) - val2 = skill_name2id(script_getstr(st,4)); // 2nd value can be skill name - else - val2 = script_getnum(st,4); - - val3 = script_getnum(st,5); - val4 = script_getnum(st,6); - val5 = script_getnum(st,7); - pc_bonus5(sd, type, val1, val2, val3, val4, val5); - break; - default: - ShowDebug("buildin_bonus: unexpected number of arguments (%d)\n", (script_lastdata(st) - 1)); - break; - } - - return 0; + int type; + int val1; + int val2 = 0; + int val3 = 0; + int val4 = 0; + int val5 = 0; + TBL_PC* sd; + + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; // no player attached + + type = script_getnum(st,2); + switch( type ) { + case SP_AUTOSPELL: + case SP_AUTOSPELL_WHENHIT: + case SP_AUTOSPELL_ONSKILL: + case SP_SKILL_ATK: + case SP_SKILL_HEAL: + case SP_SKILL_HEAL2: + case SP_ADD_SKILL_BLOW: + case SP_CASTRATE: + case SP_ADDEFF_ONSKILL: + case SP_SKILL_USE_SP_RATE: + case SP_SKILL_COOLDOWN: + case SP_SKILL_FIXEDCAST: + case SP_SKILL_VARIABLECAST: + case SP_VARCASTRATE: + case SP_SKILL_USE_SP: + // these bonuses support skill names + val1 = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) ); + break; + default: + val1 = script_getnum(st,3); + break; + } + + switch( script_lastdata(st)-2 ) { + case 1: + pc_bonus(sd, type, val1); + break; + case 2: + val2 = script_getnum(st,4); + pc_bonus2(sd, type, val1, val2); + break; + case 3: + val2 = script_getnum(st,4); + val3 = script_getnum(st,5); + pc_bonus3(sd, type, val1, val2, val3); + break; + case 4: + if( type == SP_AUTOSPELL_ONSKILL && script_isstring(st,4) ) + val2 = skill_name2id(script_getstr(st,4)); // 2nd value can be skill name + else + val2 = script_getnum(st,4); + + val3 = script_getnum(st,5); + val4 = script_getnum(st,6); + pc_bonus4(sd, type, val1, val2, val3, val4); + break; + case 5: + if( type == SP_AUTOSPELL_ONSKILL && script_isstring(st,4) ) + val2 = skill_name2id(script_getstr(st,4)); // 2nd value can be skill name + else + val2 = script_getnum(st,4); + + val3 = script_getnum(st,5); + val4 = script_getnum(st,6); + val5 = script_getnum(st,7); + pc_bonus5(sd, type, val1, val2, val3, val4, val5); + break; + default: + ShowDebug("buildin_bonus: unexpected number of arguments (%d)\n", (script_lastdata(st) - 1)); + break; + } + + return 0; } BUILDIN_FUNC(autobonus) { - unsigned int dur; - short rate; - short atk_type = 0; - TBL_PC *sd; - const char *bonus_script, *other_script = NULL; + unsigned int dur; + short rate; + short atk_type = 0; + TBL_PC* sd; + const char *bonus_script, *other_script = NULL; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; // no player attached + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; // no player attached - if (sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip) - return 0; + if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip ) + return 0; - rate = script_getnum(st,3); - dur = script_getnum(st,4); - bonus_script = script_getstr(st,2); - if (!rate || !dur || !bonus_script) - return 0; + rate = script_getnum(st,3); + dur = script_getnum(st,4); + bonus_script = script_getstr(st,2); + if( !rate || !dur || !bonus_script ) + return 0; - if (script_hasdata(st,5)) - atk_type = script_getnum(st,5); - if (script_hasdata(st,6)) - other_script = script_getstr(st,6); + if( script_hasdata(st,5) ) + atk_type = script_getnum(st,5); + if( script_hasdata(st,6) ) + other_script = script_getstr(st,6); - if (pc_addautobonus(sd->autobonus,ARRAYLENGTH(sd->autobonus), - bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false)) { - script_add_autobonus(bonus_script); - if (other_script) - script_add_autobonus(other_script); - } + if( pc_addautobonus(sd->autobonus,ARRAYLENGTH(sd->autobonus), + bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) ) + { + script_add_autobonus(bonus_script); + if( other_script ) + script_add_autobonus(other_script); + } - return 0; + return 0; } BUILDIN_FUNC(autobonus2) { - unsigned int dur; - short rate; - short atk_type = 0; - TBL_PC *sd; - const char *bonus_script, *other_script = NULL; + unsigned int dur; + short rate; + short atk_type = 0; + TBL_PC* sd; + const char *bonus_script, *other_script = NULL; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; // no player attached + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; // no player attached - if (sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip) - return 0; + if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip ) + return 0; - rate = script_getnum(st,3); - dur = script_getnum(st,4); - bonus_script = script_getstr(st,2); - if (!rate || !dur || !bonus_script) - return 0; + rate = script_getnum(st,3); + dur = script_getnum(st,4); + bonus_script = script_getstr(st,2); + if( !rate || !dur || !bonus_script ) + return 0; - if (script_hasdata(st,5)) - atk_type = script_getnum(st,5); - if (script_hasdata(st,6)) - other_script = script_getstr(st,6); + if( script_hasdata(st,5) ) + atk_type = script_getnum(st,5); + if( script_hasdata(st,6) ) + other_script = script_getstr(st,6); - if (pc_addautobonus(sd->autobonus2,ARRAYLENGTH(sd->autobonus2), - bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false)) { - script_add_autobonus(bonus_script); - if (other_script) - script_add_autobonus(other_script); - } + if( pc_addautobonus(sd->autobonus2,ARRAYLENGTH(sd->autobonus2), + bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) ) + { + script_add_autobonus(bonus_script); + if( other_script ) + script_add_autobonus(other_script); + } - return 0; + return 0; } BUILDIN_FUNC(autobonus3) { - unsigned int dur; - short rate,atk_type; - TBL_PC *sd; - const char *bonus_script, *other_script = NULL; + unsigned int dur; + short rate,atk_type; + TBL_PC* sd; + const char *bonus_script, *other_script = NULL; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; // no player attached + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; // no player attached - if (sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip) - return 0; + if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip ) + return 0; - rate = script_getnum(st,3); - dur = script_getnum(st,4); - atk_type = (script_isstring(st,5) ? skill_name2id(script_getstr(st,5)) : script_getnum(st,5)); - bonus_script = script_getstr(st,2); - if (!rate || !dur || !atk_type || !bonus_script) - return 0; + rate = script_getnum(st,3); + dur = script_getnum(st,4); + atk_type = ( script_isstring(st,5) ? skill_name2id(script_getstr(st,5)) : script_getnum(st,5) ); + bonus_script = script_getstr(st,2); + if( !rate || !dur || !atk_type || !bonus_script ) + return 0; - if (script_hasdata(st,6)) - other_script = script_getstr(st,6); + if( script_hasdata(st,6) ) + other_script = script_getstr(st,6); - if (pc_addautobonus(sd->autobonus3,ARRAYLENGTH(sd->autobonus3), - bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,true)) { - script_add_autobonus(bonus_script); - if (other_script) - script_add_autobonus(other_script); - } + if( pc_addautobonus(sd->autobonus3,ARRAYLENGTH(sd->autobonus3), + bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,true) ) + { + script_add_autobonus(bonus_script); + if( other_script ) + script_add_autobonus(other_script); + } - return 0; + return 0; } /// Changes the level of a player skill. @@ -7829,22 +8036,22 @@ BUILDIN_FUNC(autobonus3) /// skill "<skill name>",<level> BUILDIN_FUNC(skill) { - int id; - int level; - int flag = 1; - TBL_PC *sd; + int id; + int level; + int flag = 1; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - id = (script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2)); - level = script_getnum(st,3); - if (script_hasdata(st,4)) - flag = script_getnum(st,4); - pc_skill(sd, id, level, flag); + id = ( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + level = script_getnum(st,3); + if( script_hasdata(st,4) ) + flag = script_getnum(st,4); + pc_skill(sd, id, level, flag); - return 0; + return 0; } /// Changes the level of a player skill. @@ -7858,22 +8065,22 @@ BUILDIN_FUNC(skill) /// @see skill BUILDIN_FUNC(addtoskill) { - int id; - int level; - int flag = 2; - TBL_PC *sd; + int id; + int level; + int flag = 2; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - id = (script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2)); - level = script_getnum(st,3); - if (script_hasdata(st,4)) - flag = script_getnum(st,4); - pc_skill(sd, id, level, flag); + id = ( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + level = script_getnum(st,3); + if( script_hasdata(st,4) ) + flag = script_getnum(st,4); + pc_skill(sd, id, level, flag); - return 0; + return 0; } /// Increases the level of a guild skill. @@ -7882,21 +8089,21 @@ BUILDIN_FUNC(addtoskill) /// guildskill "<skill name>",<amount>; BUILDIN_FUNC(guildskill) { - int id; - int level; - TBL_PC *sd; - int i; + int id; + int level; + TBL_PC* sd; + int i; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - id = (script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2)); - level = script_getnum(st,3); - for (i=0; i < level; i++) - guild_skillup(sd, id); + id = ( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + level = script_getnum(st,3); + for( i=0; i < level; i++ ) + guild_skillup(sd, id); - return 0; + return 0; } /// Returns the level of the player skill. @@ -7905,17 +8112,17 @@ BUILDIN_FUNC(guildskill) /// getskilllv("<skill name>") -> <level> BUILDIN_FUNC(getskilllv) { - int id; - TBL_PC *sd; + int id; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - id = (script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2)); - script_pushint(st, pc_checkskill(sd,id)); + id = ( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + script_pushint(st, pc_checkskill(sd,id)); - return 0; + return 0; } /// Returns the level of the guild skill. @@ -7924,19 +8131,19 @@ BUILDIN_FUNC(getskilllv) /// getgdskilllv(<guild id>,"<skill name>") -> <level> BUILDIN_FUNC(getgdskilllv) { - int guild_id; - int skill_id; - struct guild *g; + int guild_id; + int skill_id; + struct guild* g; - guild_id = script_getnum(st,2); - skill_id = (script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3)); - g = guild_search(guild_id); - if (g == NULL) - script_pushint(st, -1); - else - script_pushint(st, guild_checkskill(g,skill_id)); + guild_id = script_getnum(st,2); + skill_id = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) ); + g = guild_search(guild_id); + if( g == NULL ) + script_pushint(st, -1); + else + script_pushint(st, guild_checkskill(g,skill_id)); - return 0; + return 0; } /// Returns the 'basic_skill_check' setting. @@ -7946,8 +8153,8 @@ BUILDIN_FUNC(getgdskilllv) /// basicskillcheck() -> <bool> BUILDIN_FUNC(basicskillcheck) { - script_pushint(st, battle_config.basic_skill_check); - return 0; + script_pushint(st, battle_config.basic_skill_check); + return 0; } /// Returns the GM level of the player. @@ -7955,15 +8162,15 @@ BUILDIN_FUNC(basicskillcheck) /// getgmlevel() -> <level> BUILDIN_FUNC(getgmlevel) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - script_pushint(st, pc_get_group_level(sd)); + script_pushint(st, pc_get_group_level(sd)); - return 0; + return 0; } /// Returns the group ID of the player. @@ -7971,14 +8178,14 @@ BUILDIN_FUNC(getgmlevel) /// getgroupid() -> <int> BUILDIN_FUNC(getgroupid) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 1; // no player attached, report source - script_pushint(st, pc_get_group_id(sd)); + sd = script_rid2sd(st); + if (sd == NULL) + return 1; // no player attached, report source + script_pushint(st, pc_get_group_id(sd)); - return 0; + return 0; } /// Terminates the execution of this script instance. @@ -7986,8 +8193,8 @@ BUILDIN_FUNC(getgroupid) /// end BUILDIN_FUNC(end) { - st->state = END; - return 0; + st->state = END; + return 0; } /// Checks if the player has that effect state (option). @@ -7995,20 +8202,20 @@ BUILDIN_FUNC(end) /// checkoption(<option>) -> <bool> BUILDIN_FUNC(checkoption) { - int option; - TBL_PC *sd; + int option; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - option = script_getnum(st,2); - if (sd->sc.option&option) - script_pushint(st, 1); - else - script_pushint(st, 0); + option = script_getnum(st,2); + if( sd->sc.option&option ) + script_pushint(st, 1); + else + script_pushint(st, 0); - return 0; + return 0; } /// Checks if the player is in that body state (opt1). @@ -8016,20 +8223,20 @@ BUILDIN_FUNC(checkoption) /// checkoption1(<opt1>) -> <bool> BUILDIN_FUNC(checkoption1) { - int opt1; - TBL_PC *sd; + int opt1; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - opt1 = script_getnum(st,2); - if (sd->sc.opt1 == opt1) - script_pushint(st, 1); - else - script_pushint(st, 0); + opt1 = script_getnum(st,2); + if( sd->sc.opt1 == opt1 ) + script_pushint(st, 1); + else + script_pushint(st, 0); - return 0; + return 0; } /// Checks if the player has that health state (opt2). @@ -8037,20 +8244,20 @@ BUILDIN_FUNC(checkoption1) /// checkoption2(<opt2>) -> <bool> BUILDIN_FUNC(checkoption2) { - int opt2; - TBL_PC *sd; + int opt2; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - opt2 = script_getnum(st,2); - if (sd->sc.opt2&opt2) - script_pushint(st, 1); - else - script_pushint(st, 0); + opt2 = script_getnum(st,2); + if( sd->sc.opt2&opt2 ) + script_pushint(st, 1); + else + script_pushint(st, 0); - return 0; + return 0; } /// Changes the effect state (option) of the player. @@ -8062,32 +8269,32 @@ BUILDIN_FUNC(checkoption2) /// setoption <option>; BUILDIN_FUNC(setoption) { - int option; - int flag = 1; - TBL_PC *sd; + int option; + int flag = 1; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - option = script_getnum(st,2); - if (script_hasdata(st,3)) - flag = script_getnum(st,3); - else if (!option) {// Request to remove everything. - flag = 0; - option = OPTION_FALCON|OPTION_RIDING; + option = script_getnum(st,2); + if( script_hasdata(st,3) ) + flag = script_getnum(st,3); + else if( !option ){// Request to remove everything. + flag = 0; + option = OPTION_FALCON|OPTION_RIDING; #ifndef NEW_CARTS - option |= OPTION_CART; + option |= OPTION_CART; #endif - } - if (flag) {// Add option - if (option&OPTION_WEDDING && !battle_config.wedding_modifydisplay) - option &= ~OPTION_WEDDING;// Do not show the wedding sprites - pc_setoption(sd, sd->sc.option|option); - } else// Remove option - pc_setoption(sd, sd->sc.option&~option); + } + if( flag ){// Add option + if( option&OPTION_WEDDING && !battle_config.wedding_modifydisplay ) + option &= ~OPTION_WEDDING;// Do not show the wedding sprites + pc_setoption(sd, sd->sc.option|option); + } else// Remove option + pc_setoption(sd, sd->sc.option&~option); - return 0; + return 0; } /// Returns if the player has a cart. @@ -8097,18 +8304,18 @@ BUILDIN_FUNC(setoption) /// @author Valaris BUILDIN_FUNC(checkcart) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - if (pc_iscarton(sd)) - script_pushint(st, 1); - else - script_pushint(st, 0); + if( pc_iscarton(sd) ) + script_pushint(st, 1); + else + script_pushint(st, 0); - return 0; + return 0; } /// Sets the cart of the player. @@ -8124,18 +8331,18 @@ BUILDIN_FUNC(checkcart) /// setcart; BUILDIN_FUNC(setcart) { - int type = 1; - TBL_PC *sd; + int type = 1; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - if (script_hasdata(st,2)) - type = script_getnum(st,2); - pc_setcart(sd, type); + if( script_hasdata(st,2) ) + type = script_getnum(st,2); + pc_setcart(sd, type); - return 0; + return 0; } /// Returns if the player has a falcon. @@ -8145,18 +8352,18 @@ BUILDIN_FUNC(setcart) /// @author Valaris BUILDIN_FUNC(checkfalcon) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - if (pc_isfalcon(sd)) - script_pushint(st, 1); - else - script_pushint(st, 0); + if( pc_isfalcon(sd) ) + script_pushint(st, 1); + else + script_pushint(st, 0); - return 0; + return 0; } /// Sets if the player has a falcon or not. @@ -8166,19 +8373,19 @@ BUILDIN_FUNC(checkfalcon) /// setfalcon; BUILDIN_FUNC(setfalcon) { - int flag = 1; - TBL_PC *sd; + int flag = 1; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - if (script_hasdata(st,2)) - flag = script_getnum(st,2); + if( script_hasdata(st,2) ) + flag = script_getnum(st,2); - pc_setfalcon(sd, flag); + pc_setfalcon(sd, flag); - return 0; + return 0; } /// Returns if the player is riding. @@ -8188,18 +8395,18 @@ BUILDIN_FUNC(setfalcon) /// @author Valaris BUILDIN_FUNC(checkriding) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - if (pc_isriding(sd) || pc_isridingwug(sd) || pc_isridingdragon(sd)) - script_pushint(st, 1); - else - script_pushint(st, 0); + if( pc_isriding(sd) || pc_isridingwug(sd) || pc_isridingdragon(sd) ) + script_pushint(st, 1); + else + script_pushint(st, 0); - return 0; + return 0; } /// Sets if the player is riding. @@ -8209,18 +8416,18 @@ BUILDIN_FUNC(checkriding) /// setriding; BUILDIN_FUNC(setriding) { - int flag = 1; - TBL_PC *sd; + int flag = 1; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - if (script_hasdata(st,2)) - flag = script_getnum(st,2); - pc_setriding(sd, flag); + if( script_hasdata(st,2) ) + flag = script_getnum(st,2); + pc_setriding(sd, flag); - return 0; + return 0; } /// Returns if the player has a warg. @@ -8229,18 +8436,18 @@ BUILDIN_FUNC(setriding) /// BUILDIN_FUNC(checkwug) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - if (pc_iswug(sd)) - script_pushint(st, 1); - else - script_pushint(st, 0); + if( pc_iswug(sd) ) + script_pushint(st, 1); + else + script_pushint(st, 0); - return 0; + return 0; } /// Returns if the player is wearing MADO Gear. @@ -8249,18 +8456,18 @@ BUILDIN_FUNC(checkwug) /// BUILDIN_FUNC(checkmadogear) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - if (pc_ismadogear(sd)) - script_pushint(st, 1); - else - script_pushint(st, 0); + if( pc_ismadogear(sd) ) + script_pushint(st, 1); + else + script_pushint(st, 0); - return 0; + return 0; } /// Sets if the player is riding MADO Gear. @@ -8270,18 +8477,18 @@ BUILDIN_FUNC(checkmadogear) /// setmadogear; BUILDIN_FUNC(setmadogear) { - int flag = 1; - TBL_PC *sd; + int flag = 1; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - if (script_hasdata(st,2)) - flag = script_getnum(st,2); - pc_setmadogear(sd, flag); + if( script_hasdata(st,2) ) + flag = script_getnum(st,2); + pc_setmadogear(sd, flag); - return 0; + return 0; } /// Sets the save point of the player. @@ -8290,56 +8497,56 @@ BUILDIN_FUNC(setmadogear) /// savepoint "<map name>",<x>,<y> BUILDIN_FUNC(savepoint) { - int x; - int y; - short map; - const char *str; - TBL_PC *sd; + int x; + int y; + short map; + const char* str; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached, report source + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached, report source - str = script_getstr(st, 2); - x = script_getnum(st,3); - y = script_getnum(st,4); - map = mapindex_name2id(str); - if (map) - pc_setsavepoint(sd, map, x, y); + str = script_getstr(st, 2); + x = script_getnum(st,3); + y = script_getnum(st,4); + map = mapindex_name2id(str); + if( map ) + pc_setsavepoint(sd, map, x, y); - return 0; + return 0; } /*========================================== * GetTimeTick(0: System Tick, 1: Time Second Tick) *------------------------------------------*/ -BUILDIN_FUNC(gettimetick) /* Asgard Version */ -{ - int type; - time_t timer; - struct tm *t; - - type=script_getnum(st,2); - - switch (type) { - case 2: - //type 2:(Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC - // from the system clock.) - script_pushint(st,(int)time(NULL)); - break; - case 1: - //type 1:(Second Ticks: 0-86399, 00:00:00-23:59:59) - time(&timer); - t=localtime(&timer); - script_pushint(st,((t->tm_hour)*3600+(t->tm_min)*60+t->tm_sec)); - break; - case 0: - default: - //type 0:(System Ticks) - script_pushint(st,gettick()); - break; - } - return 0; +BUILDIN_FUNC(gettimetick) /* Asgard Version */ +{ + int type; + time_t timer; + struct tm *t; + + type=script_getnum(st,2); + + switch(type){ + case 2: + //type 2:(Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC + // from the system clock.) + script_pushint(st,(int)time(NULL)); + break; + case 1: + //type 1:(Second Ticks: 0-86399, 00:00:00-23:59:59) + time(&timer); + t=localtime(&timer); + script_pushint(st,((t->tm_hour)*3600+(t->tm_min)*60+t->tm_sec)); + break; + case 0: + default: + //type 0:(System Ticks) + script_pushint(st,gettick()); + break; + } + return 0; } /*========================================== @@ -8348,47 +8555,47 @@ BUILDIN_FUNC(gettimetick) /* Asgard Version */ * 4: WeekDay 5: MonthDay 6: Month * 7: Year *------------------------------------------*/ -BUILDIN_FUNC(gettime) /* Asgard Version */ -{ - int type; - time_t timer; - struct tm *t; - - type=script_getnum(st,2); - - time(&timer); - t=localtime(&timer); - - switch (type) { - case 1://Sec(0~59) - script_pushint(st,t->tm_sec); - break; - case 2://Min(0~59) - script_pushint(st,t->tm_min); - break; - case 3://Hour(0~23) - script_pushint(st,t->tm_hour); - break; - case 4://WeekDay(0~6) - script_pushint(st,t->tm_wday); - break; - case 5://MonthDay(01~31) - script_pushint(st,t->tm_mday); - break; - case 6://Month(01~12) - script_pushint(st,t->tm_mon+1); - break; - case 7://Year(20xx) - script_pushint(st,t->tm_year+1900); - break; - case 8://Year Day(01~366) - script_pushint(st,t->tm_yday+1); - break; - default://(format error) - script_pushint(st,-1); - break; - } - return 0; +BUILDIN_FUNC(gettime) /* Asgard Version */ +{ + int type; + time_t timer; + struct tm *t; + + type=script_getnum(st,2); + + time(&timer); + t=localtime(&timer); + + switch(type){ + case 1://Sec(0~59) + script_pushint(st,t->tm_sec); + break; + case 2://Min(0~59) + script_pushint(st,t->tm_min); + break; + case 3://Hour(0~23) + script_pushint(st,t->tm_hour); + break; + case 4://WeekDay(0~6) + script_pushint(st,t->tm_wday); + break; + case 5://MonthDay(01~31) + script_pushint(st,t->tm_mday); + break; + case 6://Month(01~12) + script_pushint(st,t->tm_mon+1); + break; + case 7://Year(20xx) + script_pushint(st,t->tm_year+1900); + break; + case 8://Year Day(01~366) + script_pushint(st,t->tm_yday+1); + break; + default://(format error) + script_pushint(st,-1); + break; + } + return 0; } /*========================================== @@ -8396,20 +8603,20 @@ BUILDIN_FUNC(gettime) /* Asgard Version */ *------------------------------------------*/ BUILDIN_FUNC(gettimestr) { - char *tmpstr; - const char *fmtstr; - int maxlen; - time_t now = time(NULL); + char *tmpstr; + const char *fmtstr; + int maxlen; + time_t now = time(NULL); - fmtstr=script_getstr(st,2); - maxlen=script_getnum(st,3); + fmtstr=script_getstr(st,2); + maxlen=script_getnum(st,3); - tmpstr=(char *)aMalloc((maxlen+1)*sizeof(char)); - strftime(tmpstr,maxlen,fmtstr,localtime(&now)); - tmpstr[maxlen]='\0'; + tmpstr=(char *)aMalloc((maxlen+1)*sizeof(char)); + strftime(tmpstr,maxlen,fmtstr,localtime(&now)); + tmpstr[maxlen]='\0'; - script_pushstr(st,tmpstr); - return 0; + script_pushstr(st,tmpstr); + return 0; } /*========================================== @@ -8417,28 +8624,28 @@ BUILDIN_FUNC(gettimestr) *------------------------------------------*/ BUILDIN_FUNC(openstorage) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - storage_storageopen(sd); - return 0; + storage_storageopen(sd); + return 0; } BUILDIN_FUNC(guildopenstorage) { - TBL_PC *sd; - int ret; + TBL_PC* sd; + int ret; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - ret = storage_guild_storageopen(sd); - script_pushint(st,ret); - return 0; + ret = storage_guild_storageopen(sd); + script_pushint(st,ret); + return 0; } /*========================================== @@ -8448,108 +8655,108 @@ BUILDIN_FUNC(guildopenstorage) /// itemskill "<skill name>",<level> BUILDIN_FUNC(itemskill) { - int id; - int lv; - TBL_PC *sd; + int id; + int lv; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL || sd->ud.skilltimer != INVALID_TIMER) - return 0; + sd = script_rid2sd(st); + if( sd == NULL || sd->ud.skilltimer != INVALID_TIMER ) + return 0; - id = (script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2)); - lv = script_getnum(st,3); + id = ( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + lv = script_getnum(st,3); - sd->skillitem=id; - sd->skillitemlv=lv; - clif_item_skill(sd,id,lv); - return 0; + sd->skillitem=id; + sd->skillitemlv=lv; + clif_item_skill(sd,id,lv); + return 0; } /*========================================== * Attempt to create an item *------------------------------------------*/ BUILDIN_FUNC(produce) { - int trigger; - TBL_PC *sd; + int trigger; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - trigger=script_getnum(st,2); - clif_skill_produce_mix_list(sd, -1, trigger); - return 0; + trigger=script_getnum(st,2); + clif_skill_produce_mix_list(sd, -1, trigger); + return 0; } /*========================================== * *------------------------------------------*/ BUILDIN_FUNC(cooking) { - int trigger; - TBL_PC *sd; + int trigger; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - trigger=script_getnum(st,2); - clif_cooking_list(sd, trigger, AM_PHARMACY, 1, 1); - return 0; + trigger=script_getnum(st,2); + clif_cooking_list(sd, trigger, AM_PHARMACY, 1, 1); + return 0; } /*========================================== * Create a pet *------------------------------------------*/ BUILDIN_FUNC(makepet) { - TBL_PC *sd; - int id,pet_id; + TBL_PC* sd; + int id,pet_id; - id=script_getnum(st,2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + id=script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - pet_id = search_petDB_index(id, PET_CLASS); - - 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_; - intif_create_pet( - sd->status.account_id, 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); - } + pet_id = search_petDB_index(id, PET_CLASS); - return 0; + 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_; + intif_create_pet( + sd->status.account_id, 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); + } + + return 0; } /*========================================== * Give player exp base,job * quest_exp_rate/100 *------------------------------------------*/ BUILDIN_FUNC(getexp) { - TBL_PC *sd; - int base=0,job=0; - double bonus; + TBL_PC* sd; + int base=0,job=0; + double bonus; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - base=script_getnum(st,2); - job =script_getnum(st,3); - if (base<0 || job<0) - return 0; + base=script_getnum(st,2); + job =script_getnum(st,3); + if(base<0 || job<0) + return 0; - // bonus for npc-given exp - bonus = battle_config.quest_exp_rate / 100.; - base = (int) cap_value(base * bonus, 0, INT_MAX); - job = (int) cap_value(job * bonus, 0, INT_MAX); + // bonus for npc-given exp + bonus = battle_config.quest_exp_rate / 100.; + base = (int) cap_value(base * bonus, 0, INT_MAX); + job = (int) cap_value(job * bonus, 0, INT_MAX); - pc_gainexp(sd, NULL, base, job, true); + pc_gainexp(sd, NULL, base, job, true); - return 0; + return 0; } /*========================================== @@ -8557,20 +8764,20 @@ BUILDIN_FUNC(getexp) *------------------------------------------*/ BUILDIN_FUNC(guildgetexp) { - TBL_PC *sd; - int exp; + TBL_PC* sd; + int exp; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - exp = script_getnum(st,2); - if (exp < 0) - return 0; - if (sd && sd->status.guild_id > 0) - guild_getexp(sd, exp); + exp = script_getnum(st,2); + if(exp < 0) + return 0; + if(sd && sd->status.guild_id > 0) + guild_getexp (sd, exp); - return 0; + return 0; } /*========================================== @@ -8578,20 +8785,20 @@ BUILDIN_FUNC(guildgetexp) *------------------------------------------*/ BUILDIN_FUNC(guildchangegm) { - TBL_PC *sd; - int guild_id; - const char *name; + TBL_PC *sd; + int guild_id; + const char *name; - guild_id = script_getnum(st,2); - name = script_getstr(st,3); - sd=map_nick2sd(name); + guild_id = script_getnum(st,2); + name = script_getstr(st,3); + sd=map_nick2sd(name); - if (!sd) - script_pushint(st,0); - else - script_pushint(st,guild_gm_change(guild_id, sd)); + if (!sd) + script_pushint(st,0); + else + script_pushint(st,guild_gm_change(guild_id, sd)); - return 0; + return 0; } /*========================================== @@ -8604,260 +8811,275 @@ BUILDIN_FUNC(guildchangegm) *------------------------------------------*/ BUILDIN_FUNC(monster) { - const char *mapn = script_getstr(st,2); - int x = script_getnum(st,3); - int y = script_getnum(st,4); - const char *str = script_getstr(st,5); - int class_ = script_getnum(st,6); - int amount = script_getnum(st,7); - const char *event = ""; - unsigned int size = SZ_SMALL; - unsigned int ai = AI_NONE; - - struct map_session_data *sd; - int m; - - if (script_hasdata(st, 8)) { - event = script_getstr(st, 8); - check_event(st, event); - } - - if (script_hasdata(st, 9)) { - size = script_getnum(st, 9); - if (size > 3) { - ShowWarning("buildin_monster: Attempted to spawn non-existing size %d for monster class %d\n", size, class_); - return 1; - } - } - - if (script_hasdata(st, 10)) { - ai = script_getnum(st, 10); - if (ai > 4) { - ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); - return 1; - } - } - - if (class_ >= 0 && !mobdb_checkid(class_)) { - ShowWarning("buildin_monster: Attempted to spawn non-existing monster class %d\n", class_); - return 1; - } - - sd = map_id2sd(st->rid); - - if (sd && strcmp(mapn, "this") == 0) - m = sd->bl.m; - else { - m = map_mapname2mapid(mapn); - if (map[m].flag.src4instance && st->instance_id) { - // Try to redirect to the instance map, not the src map - if ((m = instance_mapid2imapid(m, st->instance_id)) < 0) { - ShowError("buildin_monster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn); - return 1; - } - } - } - - mob_once_spawn(sd, m, x, y, str, class_, amount, event, size, ai); - return 0; + const char* mapn = script_getstr(st,2); + int x = script_getnum(st,3); + int y = script_getnum(st,4); + const char* str = script_getstr(st,5); + int class_ = script_getnum(st,6); + int amount = script_getnum(st,7); + const char* event = ""; + unsigned int size = SZ_SMALL; + unsigned int ai = AI_NONE; + + struct map_session_data* sd; + int m; + + if (script_hasdata(st, 8)) + { + event = script_getstr(st, 8); + check_event(st, event); + } + + if (script_hasdata(st, 9)) + { + size = script_getnum(st, 9); + if (size > 3) + { + ShowWarning("buildin_monster: Attempted to spawn non-existing size %d for monster class %d\n", size, class_); + return 1; + } + } + + if (script_hasdata(st, 10)) + { + ai = script_getnum(st, 10); + if (ai > 4) + { + ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); + return 1; + } + } + + if (class_ >= 0 && !mobdb_checkid(class_)) + { + ShowWarning("buildin_monster: Attempted to spawn non-existing monster class %d\n", class_); + return 1; + } + + sd = map_id2sd(st->rid); + + if (sd && strcmp(mapn, "this") == 0) + m = sd->bl.m; + else + { + m = map_mapname2mapid(mapn); + if (map[m].flag.src4instance && st->instance_id) + { // Try to redirect to the instance map, not the src map + if ((m = instance_mapid2imapid(m, st->instance_id)) < 0) + { + ShowError("buildin_monster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn); + return 1; + } + } + } + + mob_once_spawn(sd, m, x, y, str, class_, amount, event, size, ai); + return 0; } /*========================================== * Request List of Monster Drops *------------------------------------------*/ BUILDIN_FUNC(getmobdrops) { - int class_ = script_getnum(st,2); - int i, j = 0; - struct mob_db *mob; + int class_ = script_getnum(st,2); + int i, j = 0; + struct mob_db *mob; - if (!mobdb_checkid(class_)) { - script_pushint(st, 0); - return 0; - } + if( !mobdb_checkid(class_) ) + { + script_pushint(st, 0); + return 0; + } - mob = mob_db(class_); + mob = mob_db(class_); - for (i = 0; i < MAX_MOB_DROP; i++) { - if (mob->dropitem[i].nameid < 1) - continue; - if (itemdb_exists(mob->dropitem[i].nameid) == NULL) - continue; + for( i = 0; i < MAX_MOB_DROP; i++ ) + { + if( mob->dropitem[i].nameid < 1 ) + continue; + if( itemdb_exists(mob->dropitem[i].nameid) == NULL ) + continue; - mapreg_setreg(reference_uid(add_str("$@MobDrop_item"), j), mob->dropitem[i].nameid); - mapreg_setreg(reference_uid(add_str("$@MobDrop_rate"), j), mob->dropitem[i].p); + mapreg_setreg(reference_uid(add_str("$@MobDrop_item"), j), mob->dropitem[i].nameid); + mapreg_setreg(reference_uid(add_str("$@MobDrop_rate"), j), mob->dropitem[i].p); - j++; - } + j++; + } - mapreg_setreg(add_str("$@MobDrop_count"), j); - script_pushint(st, 1); + mapreg_setreg(add_str("$@MobDrop_count"), j); + script_pushint(st, 1); - return 0; + return 0; } /*========================================== * Same as monster but randomize location in x0,x1,y0,y1 area *------------------------------------------*/ BUILDIN_FUNC(areamonster) { - const char *mapn = script_getstr(st,2); - int x0 = script_getnum(st,3); - int y0 = script_getnum(st,4); - int x1 = script_getnum(st,5); - int y1 = script_getnum(st,6); - const char *str = script_getstr(st,7); - int class_ = script_getnum(st,8); - int amount = script_getnum(st,9); - const char *event = ""; - unsigned int size = SZ_SMALL; - unsigned int ai = AI_NONE; - - struct map_session_data *sd; - int m; - - if (script_hasdata(st,10)) { - event = script_getstr(st, 10); - check_event(st, event); - } - - if (script_hasdata(st, 11)) { - size = script_getnum(st, 11); - if (size > 3) { - ShowWarning("buildin_monster: Attempted to spawn non-existing size %d for monster class %d\n", size, class_); - return 1; - } - } - - if (script_hasdata(st, 12)) { - ai = script_getnum(st, 12); - if (ai > 4) { - ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); - return 1; - } - } - - sd = map_id2sd(st->rid); - - if (sd && strcmp(mapn, "this") == 0) - m = sd->bl.m; - else { - m = map_mapname2mapid(mapn); - if (map[m].flag.src4instance && st->instance_id) { - // Try to redirect to the instance map, not the src map - if ((m = instance_mapid2imapid(m, st->instance_id)) < 0) { - ShowError("buildin_areamonster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn); - return 1; - } - } - } - - mob_once_spawn_area(sd, m, x0, y0, x1, y1, str, class_, amount, event, size, ai); - return 0; + const char* mapn = script_getstr(st,2); + int x0 = script_getnum(st,3); + int y0 = script_getnum(st,4); + int x1 = script_getnum(st,5); + int y1 = script_getnum(st,6); + const char* str = script_getstr(st,7); + int class_ = script_getnum(st,8); + int amount = script_getnum(st,9); + const char* event = ""; + unsigned int size = SZ_SMALL; + unsigned int ai = AI_NONE; + + struct map_session_data* sd; + int m; + + if (script_hasdata(st,10)) + { + event = script_getstr(st, 10); + check_event(st, event); + } + + if (script_hasdata(st, 11)) + { + size = script_getnum(st, 11); + if (size > 3) + { + ShowWarning("buildin_monster: Attempted to spawn non-existing size %d for monster class %d\n", size, class_); + return 1; + } + } + + if (script_hasdata(st, 12)) + { + ai = script_getnum(st, 12); + if (ai > 4) + { + ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); + return 1; + } + } + + sd = map_id2sd(st->rid); + + if (sd && strcmp(mapn, "this") == 0) + m = sd->bl.m; + else + { + m = map_mapname2mapid(mapn); + if (map[m].flag.src4instance && st->instance_id) + { // Try to redirect to the instance map, not the src map + if ((m = instance_mapid2imapid(m, st->instance_id)) < 0) + { + ShowError("buildin_areamonster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn); + return 1; + } + } + } + + mob_once_spawn_area(sd, m, x0, y0, x1, y1, str, class_, amount, event, size, ai); + return 0; } /*========================================== * KillMonster subcheck, verify if mob to kill ain't got an even to handle, could be force kill by allflag *------------------------------------------*/ -static int buildin_killmonster_sub_strip(struct block_list *bl,va_list ap) -{ - //same fix but with killmonster instead - stripping events from mobs. - TBL_MOB *md = (TBL_MOB *)bl; - char *event=va_arg(ap,char *); - int allflag=va_arg(ap,int); - - md->state.npc_killmonster = 1; - - if (!allflag) { - if (strcmp(event,md->npc_event)==0) - status_kill(bl); - } else { - if (!md->spawn) - status_kill(bl); - } - md->state.npc_killmonster = 0; - return 0; + static int buildin_killmonster_sub_strip(struct block_list *bl,va_list ap) +{ //same fix but with killmonster instead - stripping events from mobs. + TBL_MOB* md = (TBL_MOB*)bl; + char *event=va_arg(ap,char *); + int allflag=va_arg(ap,int); + + md->state.npc_killmonster = 1; + + if(!allflag){ + if(strcmp(event,md->npc_event)==0) + status_kill(bl); + }else{ + if(!md->spawn) + status_kill(bl); + } + md->state.npc_killmonster = 0; + return 0; } static int buildin_killmonster_sub(struct block_list *bl,va_list ap) { - TBL_MOB *md = (TBL_MOB *)bl; - char *event=va_arg(ap,char *); - int allflag=va_arg(ap,int); + TBL_MOB* md = (TBL_MOB*)bl; + char *event=va_arg(ap,char *); + int allflag=va_arg(ap,int); - if (!allflag) { - if (strcmp(event,md->npc_event)==0) - status_kill(bl); - } else { - if (!md->spawn) - status_kill(bl); - } - return 0; + if(!allflag){ + if(strcmp(event,md->npc_event)==0) + status_kill(bl); + }else{ + if(!md->spawn) + status_kill(bl); + } + return 0; } BUILDIN_FUNC(killmonster) { - const char *mapname,*event; - int m,allflag=0; - mapname=script_getstr(st,2); - event=script_getstr(st,3); - if (strcmp(event,"All")==0) - allflag = 1; - else - check_event(st, event); + const char *mapname,*event; + int m,allflag=0; + mapname=script_getstr(st,2); + event=script_getstr(st,3); + if(strcmp(event,"All")==0) + allflag = 1; + else + check_event(st, event); - if ((m=map_mapname2mapid(mapname))<0) - return 0; + if( (m=map_mapname2mapid(mapname))<0 ) + return 0; - if (map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0) - return 0; + if( map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) + return 0; - if (script_hasdata(st,4)) { - if (script_getnum(st,4) == 1) { - map_foreachinmap(buildin_killmonster_sub, m, BL_MOB, event ,allflag); - return 0; - } - } + if( script_hasdata(st,4) ) { + if ( script_getnum(st,4) == 1 ) { + map_foreachinmap(buildin_killmonster_sub, m, BL_MOB, event ,allflag); + return 0; + } + } - map_freeblock_lock(); - map_foreachinmap(buildin_killmonster_sub_strip, m, BL_MOB, event ,allflag); - map_freeblock_unlock(); - return 0; + map_freeblock_lock(); + map_foreachinmap(buildin_killmonster_sub_strip, m, BL_MOB, event ,allflag); + map_freeblock_unlock(); + return 0; } static int buildin_killmonsterall_sub_strip(struct block_list *bl,va_list ap) -{ - //Strips the event from the mob if it's killed the old method. - struct mob_data *md; +{ //Strips the event from the mob if it's killed the old method. + struct mob_data *md; - md = BL_CAST(BL_MOB, bl); - if (md->npc_event[0]) - md->npc_event[0] = 0; + md = BL_CAST(BL_MOB, bl); + if (md->npc_event[0]) + md->npc_event[0] = 0; - status_kill(bl); - return 0; + status_kill(bl); + return 0; } static int buildin_killmonsterall_sub(struct block_list *bl,va_list ap) { - status_kill(bl); - return 0; + status_kill(bl); + return 0; } BUILDIN_FUNC(killmonsterall) { - const char *mapname; - int m; - mapname=script_getstr(st,2); + const char *mapname; + int m; + mapname=script_getstr(st,2); - if ((m = map_mapname2mapid(mapname))<0) - return 0; + if( (m = map_mapname2mapid(mapname))<0 ) + return 0; - if (map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0) - return 0; + if( map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) + return 0; - if (script_hasdata(st,3)) { - if (script_getnum(st,3) == 1) { - map_foreachinmap(buildin_killmonsterall_sub,m,BL_MOB); - return 0; - } - } + if( script_hasdata(st,3) ) { + if ( script_getnum(st,3) == 1 ) { + map_foreachinmap(buildin_killmonsterall_sub,m,BL_MOB); + return 0; + } + } - map_foreachinmap(buildin_killmonsterall_sub_strip,m,BL_MOB); - return 0; + map_foreachinmap(buildin_killmonsterall_sub_strip,m,BL_MOB); + return 0; } /*========================================== @@ -8866,327 +9088,347 @@ BUILDIN_FUNC(killmonsterall) *------------------------------------------*/ BUILDIN_FUNC(clone) { - TBL_PC *sd, *msd=NULL; - int char_id,master_id=0,x,y, mode = 0, flag = 0, m; - unsigned int duration = 0; - const char *map,*event=""; + TBL_PC *sd, *msd=NULL; + int char_id,master_id=0,x,y, mode = 0, flag = 0, m; + unsigned int duration = 0; + const char *map,*event=""; - map=script_getstr(st,2); - x=script_getnum(st,3); - y=script_getnum(st,4); - event=script_getstr(st,5); - char_id=script_getnum(st,6); + map=script_getstr(st,2); + x=script_getnum(st,3); + y=script_getnum(st,4); + event=script_getstr(st,5); + char_id=script_getnum(st,6); - if (script_hasdata(st,7)) - master_id=script_getnum(st,7); + if( script_hasdata(st,7) ) + master_id=script_getnum(st,7); - if (script_hasdata(st,8)) - mode=script_getnum(st,8); + if( script_hasdata(st,8) ) + mode=script_getnum(st,8); - if (script_hasdata(st,9)) - flag=script_getnum(st,9); + if( script_hasdata(st,9) ) + flag=script_getnum(st,9); - if (script_hasdata(st,10)) - duration=script_getnum(st,10); + if( script_hasdata(st,10) ) + duration=script_getnum(st,10); - check_event(st, event); + check_event(st, event); - m = map_mapname2mapid(map); - if (m < 0) return 0; + m = map_mapname2mapid(map); + if (m < 0) return 0; - sd = map_charid2sd(char_id); + sd = map_charid2sd(char_id); - if (master_id) { - msd = map_charid2sd(master_id); - if (msd) - master_id = msd->bl.id; - else - master_id = 0; - } - if (sd) //Return ID of newly crafted clone. - script_pushint(st,mob_clone_spawn(sd, m, x, y, event, master_id, mode, flag, 1000*duration)); - else //Failed to create clone. - script_pushint(st,0); + if (master_id) { + msd = map_charid2sd(master_id); + if (msd) + master_id = msd->bl.id; + else + master_id = 0; + } + if (sd) //Return ID of newly crafted clone. + script_pushint(st,mob_clone_spawn(sd, m, x, y, event, master_id, mode, flag, 1000*duration)); + else //Failed to create clone. + script_pushint(st,0); - return 0; + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(doevent) { - const char *event = script_getstr(st,2); - struct map_session_data *sd; + const char* event = script_getstr(st,2); + struct map_session_data* sd; - if ((sd = script_rid2sd(st)) == NULL) { - return 0; - } + if( ( sd = script_rid2sd(st) ) == NULL ) + { + return 0; + } - check_event(st, event); - npc_event(sd, event, 0); - return 0; + check_event(st, event); + npc_event(sd, event, 0); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(donpcevent) { - const char *event = script_getstr(st,2); - check_event(st, event); - if (!npc_event_do(event)) { - struct npc_data *nd = map_id2nd(st->oid); - ShowDebug("NPCEvent '%s' not found! (source: %s)\n",event,nd?nd->name:"Unknown"); - script_pushint(st, 0); - } else - script_pushint(st, 1); - return 0; + const char* event = script_getstr(st,2); + check_event(st, event); + if( !npc_event_do(event) ) { + struct npc_data * nd = map_id2nd(st->oid); + ShowDebug("NPCEvent '%s' not found! (source: %s)\n",event,nd?nd->name:"Unknown"); + script_pushint(st, 0); + } else + script_pushint(st, 1); + return 0; } /// for Aegis compatibility /// basically a specialized 'donpcevent', with the event specified as two arguments instead of one -BUILDIN_FUNC(cmdothernpc) // Added by RoVeRT -{ - const char *npc = script_getstr(st,2); - const char *command = script_getstr(st,3); - char event[EVENT_NAME_LENGTH]; - snprintf(event, sizeof(event), "%s::OnCommand%s", npc, command); - check_event(st, event); - npc_event_do(event); - return 0; +BUILDIN_FUNC(cmdothernpc) // Added by RoVeRT +{ + const char* npc = script_getstr(st,2); + const char* command = script_getstr(st,3); + char event[EVENT_NAME_LENGTH]; + snprintf(event, sizeof(event), "%s::OnCommand%s", npc, command); + check_event(st, event); + npc_event_do(event); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(addtimer) { - int tick = script_getnum(st,2); - const char *event = script_getstr(st, 3); - TBL_PC *sd; + int tick = script_getnum(st,2); + const char* event = script_getstr(st, 3); + TBL_PC* sd; - check_event(st, event); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + check_event(st, event); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - pc_addeventtimer(sd,tick,event); - return 0; + pc_addeventtimer(sd,tick,event); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(deltimer) { - const char *event; - TBL_PC *sd; + const char *event; + TBL_PC* sd; - event=script_getstr(st, 2); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + event=script_getstr(st, 2); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - check_event(st, event); - pc_deleventtimer(sd,event); - return 0; + check_event(st, event); + pc_deleventtimer(sd,event); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(addtimercount) { - const char *event; - int tick; - TBL_PC *sd; + const char *event; + int tick; + TBL_PC* sd; - event=script_getstr(st, 2); - tick=script_getnum(st,3); - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + event=script_getstr(st, 2); + tick=script_getnum(st,3); + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - check_event(st, event); - pc_addeventtimercount(sd,event,tick); - return 0; + check_event(st, event); + pc_addeventtimercount(sd,event,tick); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(initnpctimer) { - struct npc_data *nd; - int flag = 0; - - if (script_hasdata(st,3)) { - //Two arguments: NPC name and attach flag. - nd = npc_name2id(script_getstr(st, 2)); - flag = script_getnum(st,3); - } else if (script_hasdata(st,2)) { - //Check if argument is numeric (flag) or string (npc name) - struct script_data *data; - data = script_getdata(st,2); - get_val(st,data); - if (data_isstring(data)) //NPC name - nd = npc_name2id(conv_str(st, data)); - else if (data_isint(data)) { //Flag - nd = (struct npc_data *)map_id2bl(st->oid); - flag = conv_num(st,data); - } else { - ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n"); - return 1; - } - } else - nd = (struct npc_data *)map_id2bl(st->oid); - - if (!nd) - return 0; - if (flag) { //Attach - TBL_PC *sd = script_rid2sd(st); - if (sd == NULL) - return 0; - nd->u.scr.rid = sd->bl.id; - } - - nd->u.scr.timertick = 0; - npc_settimerevent_tick(nd,0); - npc_timerevent_start(nd, st->rid); - return 0; + struct npc_data *nd; + int flag = 0; + + if( script_hasdata(st,3) ) + { //Two arguments: NPC name and attach flag. + nd = npc_name2id(script_getstr(st, 2)); + flag = script_getnum(st,3); + } + else if( script_hasdata(st,2) ) + { //Check if argument is numeric (flag) or string (npc name) + struct script_data *data; + data = script_getdata(st,2); + get_val(st,data); + if( data_isstring(data) ) //NPC name + nd = npc_name2id(conv_str(st, data)); + else if( data_isint(data) ) //Flag + { + nd = (struct npc_data *)map_id2bl(st->oid); + flag = conv_num(st,data); + } + else + { + ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n"); + return 1; + } + } + else + nd = (struct npc_data *)map_id2bl(st->oid); + + if( !nd ) + return 0; + if( flag ) //Attach + { + TBL_PC* sd = script_rid2sd(st); + if( sd == NULL ) + return 0; + nd->u.scr.rid = sd->bl.id; + } + + nd->u.scr.timertick = 0; + npc_settimerevent_tick(nd,0); + npc_timerevent_start(nd, st->rid); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(startnpctimer) { - struct npc_data *nd; - int flag = 0; - - if (script_hasdata(st,3)) { - //Two arguments: NPC name and attach flag. - nd = npc_name2id(script_getstr(st, 2)); - flag = script_getnum(st,3); - } else if (script_hasdata(st,2)) { - //Check if argument is numeric (flag) or string (npc name) - struct script_data *data; - data = script_getdata(st,2); - get_val(st,data); - if (data_isstring(data)) //NPC name - nd = npc_name2id(conv_str(st, data)); - else if (data_isint(data)) { //Flag - nd = (struct npc_data *)map_id2bl(st->oid); - flag = conv_num(st,data); - } else { - ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n"); - return 1; - } - } else - nd=(struct npc_data *)map_id2bl(st->oid); - - if (!nd) - return 0; - if (flag) { //Attach - TBL_PC *sd = script_rid2sd(st); - if (sd == NULL) - return 0; - nd->u.scr.rid = sd->bl.id; - } - - npc_timerevent_start(nd, st->rid); - return 0; + struct npc_data *nd; + int flag = 0; + + if( script_hasdata(st,3) ) + { //Two arguments: NPC name and attach flag. + nd = npc_name2id(script_getstr(st, 2)); + flag = script_getnum(st,3); + } + else if( script_hasdata(st,2) ) + { //Check if argument is numeric (flag) or string (npc name) + struct script_data *data; + data = script_getdata(st,2); + get_val(st,data); + if( data_isstring(data) ) //NPC name + nd = npc_name2id(conv_str(st, data)); + else if( data_isint(data) ) //Flag + { + nd = (struct npc_data *)map_id2bl(st->oid); + flag = conv_num(st,data); + } + else + { + ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n"); + return 1; + } + } + else + nd=(struct npc_data *)map_id2bl(st->oid); + + if( !nd ) + return 0; + if( flag ) //Attach + { + TBL_PC* sd = script_rid2sd(st); + if( sd == NULL ) + return 0; + nd->u.scr.rid = sd->bl.id; + } + + npc_timerevent_start(nd, st->rid); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(stopnpctimer) { - struct npc_data *nd; - int flag = 0; - - if (script_hasdata(st,3)) { - //Two arguments: NPC name and attach flag. - nd = npc_name2id(script_getstr(st, 2)); - flag = script_getnum(st,3); - } else if (script_hasdata(st,2)) { - //Check if argument is numeric (flag) or string (npc name) - struct script_data *data; - data = script_getdata(st,2); - get_val(st,data); - if (data_isstring(data)) //NPC name - nd = npc_name2id(conv_str(st, data)); - else if (data_isint(data)) { //Flag - nd = (struct npc_data *)map_id2bl(st->oid); - flag = conv_num(st,data); - } else { - ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n"); - return 1; - } - } else - nd=(struct npc_data *)map_id2bl(st->oid); - - if (!nd) - return 0; - if (flag) //Detach - nd->u.scr.rid = 0; - - npc_timerevent_stop(nd); - return 0; + struct npc_data *nd; + int flag = 0; + + if( script_hasdata(st,3) ) + { //Two arguments: NPC name and attach flag. + nd = npc_name2id(script_getstr(st, 2)); + flag = script_getnum(st,3); + } + else if( script_hasdata(st,2) ) + { //Check if argument is numeric (flag) or string (npc name) + struct script_data *data; + data = script_getdata(st,2); + get_val(st,data); + if( data_isstring(data) ) //NPC name + nd = npc_name2id(conv_str(st, data)); + else if( data_isint(data) ) //Flag + { + nd = (struct npc_data *)map_id2bl(st->oid); + flag = conv_num(st,data); + } + else + { + ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n"); + return 1; + } + } + else + nd=(struct npc_data *)map_id2bl(st->oid); + + if( !nd ) + return 0; + if( flag ) //Detach + nd->u.scr.rid = 0; + + npc_timerevent_stop(nd); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(getnpctimer) { - struct npc_data *nd; - TBL_PC *sd; - int type = script_getnum(st,2); - int val = 0; - - if (script_hasdata(st,3)) - nd = npc_name2id(script_getstr(st,3)); - else - nd = (struct npc_data *)map_id2bl(st->oid); - - if (!nd || nd->bl.type != BL_NPC) { - script_pushint(st,0); - ShowError("getnpctimer: Invalid NPC.\n"); - return 1; - } - - switch (type) { - case 0: - val = npc_gettimerevent_tick(nd); - break; - case 1: - if (nd->u.scr.rid) { - sd = map_id2sd(nd->u.scr.rid); - if (!sd) { - ShowError("buildin_getnpctimer: Attached player not found!\n"); - break; - } - val = (sd->npc_timer_id != INVALID_TIMER); - } else - val = (nd->u.scr.timerid != INVALID_TIMER); - break; - case 2: - val = nd->u.scr.timeramount; - break; - } - - script_pushint(st,val); - return 0; + struct npc_data *nd; + TBL_PC *sd; + int type = script_getnum(st,2); + int val = 0; + + if( script_hasdata(st,3) ) + nd = npc_name2id(script_getstr(st,3)); + else + nd = (struct npc_data *)map_id2bl(st->oid); + + if( !nd || nd->bl.type != BL_NPC ) + { + script_pushint(st,0); + ShowError("getnpctimer: Invalid NPC.\n"); + return 1; + } + + switch( type ) + { + case 0: val = npc_gettimerevent_tick(nd); break; + case 1: + if( nd->u.scr.rid ) + { + sd = map_id2sd(nd->u.scr.rid); + if( !sd ) + { + ShowError("buildin_getnpctimer: Attached player not found!\n"); + break; + } + val = (sd->npc_timer_id != INVALID_TIMER); + } + else + val = (nd->u.scr.timerid != INVALID_TIMER); + break; + case 2: val = nd->u.scr.timeramount; break; + } + + script_pushint(st,val); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(setnpctimer) { - int tick; - struct npc_data *nd; + int tick; + struct npc_data *nd; - tick = script_getnum(st,2); - if (script_hasdata(st,3)) - nd = npc_name2id(script_getstr(st,3)); - else - nd = (struct npc_data *)map_id2bl(st->oid); + tick = script_getnum(st,2); + if( script_hasdata(st,3) ) + nd = npc_name2id(script_getstr(st,3)); + else + nd = (struct npc_data *)map_id2bl(st->oid); - if (!nd || nd->bl.type != BL_NPC) { - script_pushint(st,1); - ShowError("setnpctimer: Invalid NPC.\n"); - return 1; - } + if( !nd || nd->bl.type != BL_NPC ) + { + script_pushint(st,1); + ShowError("setnpctimer: Invalid NPC.\n"); + return 1; + } - npc_settimerevent_tick(nd,tick); - script_pushint(st,0); - return 0; + npc_settimerevent_tick(nd,tick); + script_pushint(st,0); + return 0; } /*========================================== @@ -9194,29 +9436,31 @@ BUILDIN_FUNC(setnpctimer) *------------------------------------------*/ BUILDIN_FUNC(attachnpctimer) { - TBL_PC *sd; - struct npc_data *nd = (struct npc_data *)map_id2bl(st->oid); + TBL_PC *sd; + struct npc_data *nd = (struct npc_data *)map_id2bl(st->oid); - if (!nd || nd->bl.type != BL_NPC) { - script_pushint(st,1); - ShowError("setnpctimer: Invalid NPC.\n"); - return 1; - } + if( !nd || nd->bl.type != BL_NPC ) + { + script_pushint(st,1); + ShowError("setnpctimer: Invalid NPC.\n"); + return 1; + } - if (script_hasdata(st,2)) - sd = map_nick2sd(script_getstr(st,2)); - else - sd = script_rid2sd(st); + if( script_hasdata(st,2) ) + sd = map_nick2sd(script_getstr(st,2)); + else + sd = script_rid2sd(st); - if (!sd) { - script_pushint(st,1); - ShowWarning("attachnpctimer: Invalid player.\n"); - return 1; - } + if( !sd ) + { + script_pushint(st,1); + ShowWarning("attachnpctimer: Invalid player.\n"); + return 1; + } - nd->u.scr.rid = sd->bl.id; - script_pushint(st,0); - return 0; + nd->u.scr.rid = sd->bl.id; + script_pushint(st,0); + return 0; } /*========================================== @@ -9224,22 +9468,23 @@ BUILDIN_FUNC(attachnpctimer) *------------------------------------------*/ BUILDIN_FUNC(detachnpctimer) { - struct npc_data *nd; + struct npc_data *nd; - if (script_hasdata(st,2)) - nd = npc_name2id(script_getstr(st,2)); - else - nd = (struct npc_data *)map_id2bl(st->oid); + if( script_hasdata(st,2) ) + nd = npc_name2id(script_getstr(st,2)); + else + nd = (struct npc_data *)map_id2bl(st->oid); - if (!nd || nd->bl.type != BL_NPC) { - script_pushint(st,1); - ShowError("detachnpctimer: Invalid NPC.\n"); - return 1; - } + if( !nd || nd->bl.type != BL_NPC ) + { + script_pushint(st,1); + ShowError("detachnpctimer: Invalid NPC.\n"); + return 1; + } - nd->u.scr.rid = 0; - script_pushint(st,0); - return 0; + nd->u.scr.rid = 0; + script_pushint(st,0); + return 0; } /*========================================== @@ -9249,325 +9494,333 @@ BUILDIN_FUNC(detachnpctimer) *------------------------------------------*/ BUILDIN_FUNC(playerattached) { - if (st->rid == 0 || map_id2sd(st->rid) == NULL) - script_pushint(st,0); - else - script_pushint(st,st->rid); - return 0; + if(st->rid == 0 || map_id2sd(st->rid) == NULL) + script_pushint(st,0); + else + script_pushint(st,st->rid); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(announce) { - const char *mes = script_getstr(st,2); - int flag = script_getnum(st,3); - const char *fontColor = script_hasdata(st,4) ? script_getstr(st,4) : NULL; - int fontType = script_hasdata(st,5) ? script_getnum(st,5) : 0x190; // default fontType (FW_NORMAL) - int fontSize = script_hasdata(st,6) ? script_getnum(st,6) : 12; // default fontSize - int fontAlign = script_hasdata(st,7) ? script_getnum(st,7) : 0; // default fontAlign - int fontY = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontY - - if (flag&0x0f) { // Broadcast source or broadcast region defined - send_target target; - struct block_list *bl = (flag&0x08) ? map_id2bl(st->oid) : (struct block_list *)script_rid2sd(st); // If bc_npc flag is set, use NPC as broadcast source - if (bl == NULL) - return 0; - - flag &= 0x07; - target = (flag == 1) ? ALL_SAMEMAP : - (flag == 2) ? AREA : - (flag == 3) ? SELF : - ALL_CLIENT; - if (fontColor) - clif_broadcast2(bl, mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target); - else - clif_broadcast(bl, mes, (int)strlen(mes)+1, flag&0xf0, target); - } else { - if (fontColor) - intif_broadcast2(mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY); - else - intif_broadcast(mes, (int)strlen(mes)+1, flag&0xf0); - } - return 0; + const char *mes = script_getstr(st,2); + int flag = script_getnum(st,3); + const char *fontColor = script_hasdata(st,4) ? script_getstr(st,4) : NULL; + int fontType = script_hasdata(st,5) ? script_getnum(st,5) : 0x190; // default fontType (FW_NORMAL) + int fontSize = script_hasdata(st,6) ? script_getnum(st,6) : 12; // default fontSize + int fontAlign = script_hasdata(st,7) ? script_getnum(st,7) : 0; // default fontAlign + int fontY = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontY + + if (flag&0x0f) // Broadcast source or broadcast region defined + { + send_target target; + struct block_list *bl = (flag&0x08) ? map_id2bl(st->oid) : (struct block_list *)script_rid2sd(st); // If bc_npc flag is set, use NPC as broadcast source + if (bl == NULL) + return 0; + + flag &= 0x07; + target = (flag == 1) ? ALL_SAMEMAP : + (flag == 2) ? AREA : + (flag == 3) ? SELF : + ALL_CLIENT; + if (fontColor) + clif_broadcast2(bl, mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target); + else + clif_broadcast(bl, mes, (int)strlen(mes)+1, flag&0xf0, target); + } + else + { + if (fontColor) + intif_broadcast2(mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY); + else + intif_broadcast(mes, (int)strlen(mes)+1, flag&0xf0); + } + return 0; } /*========================================== *------------------------------------------*/ static int buildin_announce_sub(struct block_list *bl, va_list ap) { - char *mes = va_arg(ap, char *); - int len = va_arg(ap, int); - int type = va_arg(ap, int); - char *fontColor = va_arg(ap, char *); - short fontType = (short)va_arg(ap, int); - short fontSize = (short)va_arg(ap, int); - short fontAlign = (short)va_arg(ap, int); - short fontY = (short)va_arg(ap, int); - if (fontColor) - clif_broadcast2(bl, mes, len, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, SELF); - else - clif_broadcast(bl, mes, len, type, SELF); - return 0; + char *mes = va_arg(ap, char *); + int len = va_arg(ap, int); + int type = va_arg(ap, int); + char *fontColor = va_arg(ap, char *); + short fontType = (short)va_arg(ap, int); + short fontSize = (short)va_arg(ap, int); + short fontAlign = (short)va_arg(ap, int); + short fontY = (short)va_arg(ap, int); + if (fontColor) + clif_broadcast2(bl, mes, len, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, SELF); + else + clif_broadcast(bl, mes, len, type, SELF); + return 0; } BUILDIN_FUNC(mapannounce) { - const char *mapname = script_getstr(st,2); - const char *mes = script_getstr(st,3); - int flag = script_getnum(st,4); - const char *fontColor = script_hasdata(st,5) ? script_getstr(st,5) : NULL; - int fontType = script_hasdata(st,6) ? script_getnum(st,6) : 0x190; // default fontType (FW_NORMAL) - int fontSize = script_hasdata(st,7) ? script_getnum(st,7) : 12; // default fontSize - int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign - int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY - int m; - - if ((m = map_mapname2mapid(mapname)) < 0) - return 0; + const char *mapname = script_getstr(st,2); + const char *mes = script_getstr(st,3); + int flag = script_getnum(st,4); + const char *fontColor = script_hasdata(st,5) ? script_getstr(st,5) : NULL; + int fontType = script_hasdata(st,6) ? script_getnum(st,6) : 0x190; // default fontType (FW_NORMAL) + int fontSize = script_hasdata(st,7) ? script_getnum(st,7) : 12; // default fontSize + int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign + int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY + int m; - map_foreachinmap(buildin_announce_sub, m, BL_PC, - mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); - return 0; + if ((m = map_mapname2mapid(mapname)) < 0) + return 0; + + map_foreachinmap(buildin_announce_sub, m, BL_PC, + mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(areaannounce) { - const char *mapname = script_getstr(st,2); - int x0 = script_getnum(st,3); - int y0 = script_getnum(st,4); - int x1 = script_getnum(st,5); - int y1 = script_getnum(st,6); - const char *mes = script_getstr(st,7); - int flag = script_getnum(st,8); - const char *fontColor = script_hasdata(st,9) ? script_getstr(st,9) : NULL; - int fontType = script_hasdata(st,10) ? script_getnum(st,10) : 0x190; // default fontType (FW_NORMAL) - int fontSize = script_hasdata(st,11) ? script_getnum(st,11) : 12; // default fontSize - int fontAlign = script_hasdata(st,12) ? script_getnum(st,12) : 0; // default fontAlign - int fontY = script_hasdata(st,13) ? script_getnum(st,13) : 0; // default fontY - int m; - - if ((m = map_mapname2mapid(mapname)) < 0) - return 0; + const char *mapname = script_getstr(st,2); + int x0 = script_getnum(st,3); + int y0 = script_getnum(st,4); + int x1 = script_getnum(st,5); + int y1 = script_getnum(st,6); + const char *mes = script_getstr(st,7); + int flag = script_getnum(st,8); + const char *fontColor = script_hasdata(st,9) ? script_getstr(st,9) : NULL; + int fontType = script_hasdata(st,10) ? script_getnum(st,10) : 0x190; // default fontType (FW_NORMAL) + int fontSize = script_hasdata(st,11) ? script_getnum(st,11) : 12; // default fontSize + int fontAlign = script_hasdata(st,12) ? script_getnum(st,12) : 0; // default fontAlign + int fontY = script_hasdata(st,13) ? script_getnum(st,13) : 0; // default fontY + int m; - map_foreachinarea(buildin_announce_sub, m, x0, y0, x1, y1, BL_PC, - mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); - return 0; + if ((m = map_mapname2mapid(mapname)) < 0) + return 0; + + map_foreachinarea(buildin_announce_sub, m, x0, y0, x1, y1, BL_PC, + mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(getusers) { - int flag, val = 0; - struct map_session_data *sd; - struct block_list *bl = NULL; - - flag = script_getnum(st,2); - - switch (flag&0x07) { - case 0: - if (flag&0x8) { - // npc - bl = map_id2bl(st->oid); - } else if ((sd = script_rid2sd(st))!=NULL) { - // pc - bl = &sd->bl; - } - - if (bl) { - val = map[bl->m].users; - } - break; - case 1: - val = map_getusers(); - break; - default: - ShowWarning("buildin_getusers: Unknown type %d.\n", flag); - script_pushint(st,0); - return 1; - } - - script_pushint(st,val); - return 0; + int flag, val = 0; + struct map_session_data* sd; + struct block_list* bl = NULL; + + flag = script_getnum(st,2); + + switch(flag&0x07) + { + case 0: + if(flag&0x8) + {// npc + bl = map_id2bl(st->oid); + } + else if((sd = script_rid2sd(st))!=NULL) + {// pc + bl = &sd->bl; + } + + if(bl) + { + val = map[bl->m].users; + } + break; + case 1: + val = map_getusers(); + break; + default: + ShowWarning("buildin_getusers: Unknown type %d.\n", flag); + script_pushint(st,0); + return 1; + } + + script_pushint(st,val); + return 0; } /*========================================== * Works like @WHO - displays all online users names in window *------------------------------------------*/ BUILDIN_FUNC(getusersname) { - TBL_PC *sd, *pl_sd; - int /*disp_num=1,*/ group_level = 0; - struct s_mapiterator *iter; + TBL_PC *sd, *pl_sd; + int /*disp_num=1,*/ group_level = 0; + struct s_mapiterator* iter; - sd = script_rid2sd(st); - if (!sd) return 0; + sd = script_rid2sd(st); + if (!sd) return 0; - group_level = pc_get_group_level(sd); - iter = mapit_getallusers(); - for (pl_sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC *)mapit_next(iter)) { - if (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > group_level) - continue; // skip hidden sessions + group_level = pc_get_group_level(sd); + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + { + if (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > group_level) + continue; // skip hidden sessions - /* Temporary fix for bugreport:1023. - * Do not uncomment unless you want thousands of 'next' buttons. - if((disp_num++)%10==0) - clif_scriptnext(sd,st->oid);*/ - clif_scriptmes(sd,st->oid,pl_sd->status.name); - } - mapit_free(iter); + /* Temporary fix for bugreport:1023. + * Do not uncomment unless you want thousands of 'next' buttons. + if((disp_num++)%10==0) + clif_scriptnext(sd,st->oid);*/ + clif_scriptmes(sd,st->oid,pl_sd->status.name); + } + mapit_free(iter); - return 0; + return 0; } /*========================================== * getmapguildusers("mapname",guild ID) Returns the number guild members present on a map [Reddozen] *------------------------------------------*/ BUILDIN_FUNC(getmapguildusers) { - const char *str; - int m, gid; - int i=0,c=0; - struct guild *g = NULL; - str=script_getstr(st,2); - gid=script_getnum(st,3); - if ((m = map_mapname2mapid(str)) < 0) { // map id on this server (m == -1 if not in actual map-server) - script_pushint(st,-1); - return 0; - } - g = guild_search(gid); - - if (g) { - for (i = 0; i < g->max_member; i++) { - if (g->member[i].sd && g->member[i].sd->bl.m == m) - c++; - } - } - - script_pushint(st,c); - return 0; + const char *str; + int m, gid; + int i=0,c=0; + struct guild *g = NULL; + str=script_getstr(st,2); + gid=script_getnum(st,3); + if ((m = map_mapname2mapid(str)) < 0) { // map id on this server (m == -1 if not in actual map-server) + script_pushint(st,-1); + return 0; + } + g = guild_search(gid); + + if (g){ + for(i = 0; i < g->max_member; i++) + { + if (g->member[i].sd && g->member[i].sd->bl.m == m) + c++; + } + } + + script_pushint(st,c); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(getmapusers) { - const char *str; - int m; - str=script_getstr(st,2); - if ((m=map_mapname2mapid(str))< 0) { - script_pushint(st,-1); - return 0; - } - script_pushint(st,map[m].users); - return 0; + const char *str; + int m; + str=script_getstr(st,2); + if( (m=map_mapname2mapid(str))< 0){ + script_pushint(st,-1); + return 0; + } + script_pushint(st,map[m].users); + return 0; } /*========================================== *------------------------------------------*/ static int buildin_getareausers_sub(struct block_list *bl,va_list ap) { - int *users=va_arg(ap,int *); - (*users)++; - return 0; + int *users=va_arg(ap,int *); + (*users)++; + return 0; } BUILDIN_FUNC(getareausers) { - const char *str; - int m,x0,y0,x1,y1,users=0; - str=script_getstr(st,2); - x0=script_getnum(st,3); - y0=script_getnum(st,4); - x1=script_getnum(st,5); - y1=script_getnum(st,6); - if ((m=map_mapname2mapid(str))< 0) { - script_pushint(st,-1); - return 0; - } - map_foreachinarea(buildin_getareausers_sub, - m,x0,y0,x1,y1,BL_PC,&users); - script_pushint(st,users); - return 0; + const char *str; + int m,x0,y0,x1,y1,users=0; + str=script_getstr(st,2); + x0=script_getnum(st,3); + y0=script_getnum(st,4); + x1=script_getnum(st,5); + y1=script_getnum(st,6); + if( (m=map_mapname2mapid(str))< 0){ + script_pushint(st,-1); + return 0; + } + map_foreachinarea(buildin_getareausers_sub, + m,x0,y0,x1,y1,BL_PC,&users); + script_pushint(st,users); + return 0; } /*========================================== *------------------------------------------*/ static int buildin_getareadropitem_sub(struct block_list *bl,va_list ap) { - int item=va_arg(ap,int); - int *amount=va_arg(ap,int *); - struct flooritem_data *drop=(struct flooritem_data *)bl; + int item=va_arg(ap,int); + int *amount=va_arg(ap,int *); + struct flooritem_data *drop=(struct flooritem_data *)bl; - if (drop->item_data.nameid==item) - (*amount)+=drop->item_data.amount; + if(drop->item_data.nameid==item) + (*amount)+=drop->item_data.amount; - return 0; + return 0; } BUILDIN_FUNC(getareadropitem) { - const char *str; - int m,x0,y0,x1,y1,item,amount=0; - struct script_data *data; - - str=script_getstr(st,2); - x0=script_getnum(st,3); - y0=script_getnum(st,4); - x1=script_getnum(st,5); - y1=script_getnum(st,6); - - data=script_getdata(st,7); - get_val(st,data); - if (data_isstring(data)) { - const char *name=conv_str(st,data); - struct item_data *item_data = itemdb_searchname(name); - item=UNKNOWN_ITEM_ID; - if (item_data) - item=item_data->nameid; - } else - item=conv_num(st,data); - - if ((m=map_mapname2mapid(str))< 0) { - script_pushint(st,-1); - return 0; - } - map_foreachinarea(buildin_getareadropitem_sub, - m,x0,y0,x1,y1,BL_ITEM,item,&amount); - script_pushint(st,amount); - return 0; + const char *str; + int m,x0,y0,x1,y1,item,amount=0; + struct script_data *data; + + str=script_getstr(st,2); + x0=script_getnum(st,3); + y0=script_getnum(st,4); + x1=script_getnum(st,5); + y1=script_getnum(st,6); + + data=script_getdata(st,7); + get_val(st,data); + if( data_isstring(data) ){ + const char *name=conv_str(st,data); + struct item_data *item_data = itemdb_searchname(name); + item=UNKNOWN_ITEM_ID; + if( item_data ) + item=item_data->nameid; + }else + item=conv_num(st,data); + + if( (m=map_mapname2mapid(str))< 0){ + script_pushint(st,-1); + return 0; + } + map_foreachinarea(buildin_getareadropitem_sub, + m,x0,y0,x1,y1,BL_ITEM,item,&amount); + script_pushint(st,amount); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(enablenpc) { - const char *str; - str=script_getstr(st,2); - npc_enable(str,1); - return 0; + const char *str; + str=script_getstr(st,2); + npc_enable(str,1); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(disablenpc) { - const char *str; - str=script_getstr(st,2); - npc_enable(str,0); - return 0; + const char *str; + str=script_getstr(st,2); + npc_enable(str,0); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(hideoffnpc) { - const char *str; - str=script_getstr(st,2); - npc_enable(str,2); - return 0; + const char *str; + str=script_getstr(st,2); + npc_enable(str,2); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(hideonnpc) { - const char *str; - str=script_getstr(st,2); - npc_enable(str,4); - return 0; + const char *str; + str=script_getstr(st,2); + npc_enable(str,4); + return 0; } /// Starts a status effect on the target unit or on the attached player. @@ -9575,36 +9828,36 @@ BUILDIN_FUNC(hideonnpc) /// sc_start <effect_id>,<duration>,<val1>{,<unit_id>}; BUILDIN_FUNC(sc_start) { - struct block_list *bl; - enum sc_type type; - int tick; - int val1; - int val4 = 0; - - type = (sc_type)script_getnum(st,2); - tick = script_getnum(st,3); - val1 = script_getnum(st,4); - if (script_hasdata(st,5)) - bl = map_id2bl(script_getnum(st,5)); - else - bl = map_id2bl(st->rid); - - if (tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0) { - // When there isn't a duration specified, try to get it from the skill_db - tick = skill_get_time(status_sc2skill(type), val1); - } + struct block_list* bl; + enum sc_type type; + int tick; + int val1; + int val4 = 0; - if (potion_flag == 1 && potion_target) { - //skill.c set the flags before running the script, this must be a potion-pitched effect. - bl = map_id2bl(potion_target); - tick /= 2;// Thrown potions only last half. - val4 = 1;// Mark that this was a thrown sc_effect - } + type = (sc_type)script_getnum(st,2); + tick = script_getnum(st,3); + val1 = script_getnum(st,4); + if( script_hasdata(st,5) ) + bl = map_id2bl(script_getnum(st,5)); + else + bl = map_id2bl(st->rid); - if (bl) - status_change_start(bl, type, 10000, val1, 0, 0, val4, tick, 2); + if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0 ) + {// When there isn't a duration specified, try to get it from the skill_db + tick = skill_get_time(status_sc2skill(type), val1); + } - return 0; + if( potion_flag == 1 && potion_target ) + { //skill.c set the flags before running the script, this must be a potion-pitched effect. + bl = map_id2bl(potion_target); + tick /= 2;// Thrown potions only last half. + val4 = 1;// Mark that this was a thrown sc_effect + } + + if( bl ) + status_change_start(bl, type, 10000, val1, 0, 0, val4, tick, 2); + + return 0; } /// Starts a status effect on the target unit or on the attached player. @@ -9612,38 +9865,38 @@ BUILDIN_FUNC(sc_start) /// sc_start2 <effect_id>,<duration>,<val1>,<percent chance>{,<unit_id>}; BUILDIN_FUNC(sc_start2) { - struct block_list *bl; - enum sc_type type; - int tick; - int val1; - int val4 = 0; - int rate; - - type = (sc_type)script_getnum(st,2); - tick = script_getnum(st,3); - val1 = script_getnum(st,4); - rate = script_getnum(st,5); - if (script_hasdata(st,6)) - bl = map_id2bl(script_getnum(st,6)); - else - bl = map_id2bl(st->rid); - - if (tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0) { - // When there isn't a duration specified, try to get it from the skill_db - tick = skill_get_time(status_sc2skill(type), val1); - } + struct block_list* bl; + enum sc_type type; + int tick; + int val1; + int val4 = 0; + int rate; - if (potion_flag == 1 && potion_target) { - //skill.c set the flags before running the script, this must be a potion-pitched effect. - bl = map_id2bl(potion_target); - tick /= 2;// Thrown potions only last half. - val4 = 1;// Mark that this was a thrown sc_effect - } + type = (sc_type)script_getnum(st,2); + tick = script_getnum(st,3); + val1 = script_getnum(st,4); + rate = script_getnum(st,5); + if( script_hasdata(st,6) ) + bl = map_id2bl(script_getnum(st,6)); + else + bl = map_id2bl(st->rid); - if (bl) - status_change_start(bl, type, rate, val1, 0, 0, val4, tick, 2); + if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0 ) + {// When there isn't a duration specified, try to get it from the skill_db + tick = skill_get_time(status_sc2skill(type), val1); + } - return 0; + if( potion_flag == 1 && potion_target ) + { //skill.c set the flags before running the script, this must be a potion-pitched effect. + bl = map_id2bl(potion_target); + tick /= 2;// Thrown potions only last half. + val4 = 1;// Mark that this was a thrown sc_effect + } + + if( bl ) + status_change_start(bl, type, rate, val1, 0, 0, val4, tick, 2); + + return 0; } /// Starts a status effect on the target unit or on the attached player. @@ -9651,40 +9904,40 @@ BUILDIN_FUNC(sc_start2) /// sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<unit_id>}; BUILDIN_FUNC(sc_start4) { - struct block_list *bl; - enum sc_type type; - int tick; - int val1; - int val2; - int val3; - int val4; - - type = (sc_type)script_getnum(st,2); - tick = script_getnum(st,3); - val1 = script_getnum(st,4); - val2 = script_getnum(st,5); - val3 = script_getnum(st,6); - val4 = script_getnum(st,7); - if (script_hasdata(st,8)) - bl = map_id2bl(script_getnum(st,8)); - else - bl = map_id2bl(st->rid); - - if (tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0) { - // When there isn't a duration specified, try to get it from the skill_db - tick = skill_get_time(status_sc2skill(type), val1); - } - - if (potion_flag == 1 && potion_target) { - //skill.c set the flags before running the script, this must be a potion-pitched effect. - bl = map_id2bl(potion_target); - tick /= 2;// Thrown potions only last half. - } - - if (bl) - status_change_start(bl, type, 10000, val1, val2, val3, val4, tick, 2); - - return 0; + struct block_list* bl; + enum sc_type type; + int tick; + int val1; + int val2; + int val3; + int val4; + + type = (sc_type)script_getnum(st,2); + tick = script_getnum(st,3); + val1 = script_getnum(st,4); + val2 = script_getnum(st,5); + val3 = script_getnum(st,6); + val4 = script_getnum(st,7); + if( script_hasdata(st,8) ) + bl = map_id2bl(script_getnum(st,8)); + else + bl = map_id2bl(st->rid); + + if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0 ) + {// When there isn't a duration specified, try to get it from the skill_db + tick = skill_get_time(status_sc2skill(type), val1); + } + + if( potion_flag == 1 && potion_target ) + { //skill.c set the flags before running the script, this must be a potion-pitched effect. + bl = map_id2bl(potion_target); + tick /= 2;// Thrown potions only last half. + } + + if( bl ) + status_change_start(bl, type, 10000, val1, val2, val3, val4, tick, 2); + + return 0; } /// Ends one or all status effects on the target unit or on the attached player. @@ -9692,47 +9945,50 @@ BUILDIN_FUNC(sc_start4) /// sc_end <effect_id>{,<unit_id>}; BUILDIN_FUNC(sc_end) { - struct block_list *bl; - int type; + struct block_list* bl; + int type; - type = script_getnum(st, 2); - if (script_hasdata(st, 3)) - bl = map_id2bl(script_getnum(st, 3)); - else - bl = map_id2bl(st->rid); + type = script_getnum(st, 2); + if (script_hasdata(st, 3)) + bl = map_id2bl(script_getnum(st, 3)); + else + bl = map_id2bl(st->rid); - if (potion_flag == 1 && potion_target) //##TODO how does this work [FlavioJS] - bl = map_id2bl(potion_target); + if (potion_flag == 1 && potion_target) //##TODO how does this work [FlavioJS] + bl = map_id2bl(potion_target); - if (!bl) - return 0; + if (!bl) + return 0; - if (type >= 0 && type < SC_MAX) { - struct status_change *sc = status_get_sc(bl); - struct status_change_entry *sce = sc ? sc->data[type] : NULL; + if (type >= 0 && type < SC_MAX) + { + struct status_change *sc = status_get_sc(bl); + struct status_change_entry *sce = sc ? sc->data[type] : NULL; - if (!sce) - return 0; + if (!sce) + return 0; - switch (type) { - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_NOCHAT: - case SC_PUSH_CART: - return 0; + switch (type) + { + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_NOCHAT: + case SC_PUSH_CART: + return 0; - default: - break; - } + default: + break; + } - //This should help status_change_end force disabling the SC in case it has no limit. - sce->val1 = sce->val2 = sce->val3 = sce->val4 = 0; - status_change_end(bl, (sc_type)type, INVALID_TIMER); - } else - status_change_clear(bl, 3); // remove all effects + //This should help status_change_end force disabling the SC in case it has no limit. + sce->val1 = sce->val2 = sce->val3 = sce->val4 = 0; + status_change_end(bl, (sc_type)type, INVALID_TIMER); + } + else + status_change_clear(bl, 3); // remove all effects - return 0; + return 0; } /*========================================== @@ -9740,21 +9996,21 @@ BUILDIN_FUNC(sc_end) *------------------------------------------*/ BUILDIN_FUNC(getscrate) { - struct block_list *bl; - int type,rate; + struct block_list *bl; + int type,rate; - type=script_getnum(st,2); - rate=script_getnum(st,3); - if (script_hasdata(st,4)) //get for the bl assigned - bl = map_id2bl(script_getnum(st,4)); - else - bl = map_id2bl(st->rid); + type=script_getnum(st,2); + rate=script_getnum(st,3); + if( script_hasdata(st,4) ) //get for the bl assigned + bl = map_id2bl(script_getnum(st,4)); + else + bl = map_id2bl(st->rid); - if (bl) - rate = status_get_sc_def(bl, (sc_type)type, 10000, 10000, 0); + if (bl) + rate = status_get_sc_def(bl, (sc_type)type, 10000, 10000, 0); - script_pushint(st,rate); - return 0; + script_pushint(st,rate); + return 0; } /*========================================== @@ -9762,57 +10018,49 @@ BUILDIN_FUNC(getscrate) *------------------------------------------*/ BUILDIN_FUNC(getstatus) { - int id, type; - struct map_session_data *sd = script_rid2sd(st); - - if (sd == NULL) { - // no player attached - return 0; - } - - id = script_getnum(st, 2); - type = script_hasdata(st, 3) ? script_getnum(st, 3) : 0; - - if (id <= SC_NONE || id >= SC_MAX) { - // invalid status type given - ShowWarning("script.c:getstatus: Invalid status type given (%d).\n", id); - return 0; - } - - if (sd->sc.count == 0 || !sd->sc.data[id]) { - // no status is active - script_pushint(st, 0); - return 0; - } - - switch (type) { - case 1: - script_pushint(st, sd->sc.data[id]->val1); - break; - case 2: - script_pushint(st, sd->sc.data[id]->val2); - break; - case 3: - script_pushint(st, sd->sc.data[id]->val3); - break; - case 4: - script_pushint(st, sd->sc.data[id]->val4); - break; - case 5: { - struct TimerData *timer = (struct TimerData *)get_timer(sd->sc.data[id]->timer); - - if (timer) { - // return the amount of time remaining - script_pushint(st, timer->tick - gettick()); - } - } - break; - default: - script_pushint(st, 1); - break; - } - - return 0; + int id, type; + struct map_session_data* sd = script_rid2sd(st); + + if( sd == NULL ) + {// no player attached + return 0; + } + + id = script_getnum(st, 2); + type = script_hasdata(st, 3) ? script_getnum(st, 3) : 0; + + if( id <= SC_NONE || id >= SC_MAX ) + {// invalid status type given + ShowWarning("script.c:getstatus: Invalid status type given (%d).\n", id); + return 0; + } + + if( sd->sc.count == 0 || !sd->sc.data[id] ) + {// no status is active + script_pushint(st, 0); + return 0; + } + + switch( type ) + { + case 1: script_pushint(st, sd->sc.data[id]->val1); break; + case 2: script_pushint(st, sd->sc.data[id]->val2); break; + case 3: script_pushint(st, sd->sc.data[id]->val3); break; + case 4: script_pushint(st, sd->sc.data[id]->val4); break; + case 5: + { + struct TimerData* timer = (struct TimerData*)get_timer(sd->sc.data[id]->timer); + + if( timer ) + {// return the amount of time remaining + script_pushint(st, timer->tick - gettick()); + } + } + break; + default: script_pushint(st, 1); break; + } + + return 0; } /*========================================== @@ -9820,26 +10068,26 @@ BUILDIN_FUNC(getstatus) *------------------------------------------*/ BUILDIN_FUNC(debugmes) { - const char *str; - str=script_getstr(st,2); - ShowDebug("script debug : %d %d : %s\n",st->rid,st->oid,str); - return 0; + const char *str; + str=script_getstr(st,2); + ShowDebug("script debug : %d %d : %s\n",st->rid,st->oid,str); + return 0; } /*========================================== *------------------------------------------*/ BUILDIN_FUNC(catchpet) { - int pet_id; - TBL_PC *sd; + int pet_id; + TBL_PC *sd; - pet_id= script_getnum(st,2); - sd=script_rid2sd(st); - if (sd == NULL) - return 0; + pet_id= script_getnum(st,2); + sd=script_rid2sd(st); + if( sd == NULL ) + return 0; - pet_catch_process1(sd,pet_id); - return 0; + pet_catch_process1(sd,pet_id); + return 0; } /*========================================== @@ -9847,19 +10095,20 @@ BUILDIN_FUNC(catchpet) *------------------------------------------*/ BUILDIN_FUNC(homunculus_evolution) { - TBL_PC *sd; + TBL_PC *sd; - sd=script_rid2sd(st); - if (sd == NULL) - return 0; + sd=script_rid2sd(st); + if( sd == NULL ) + return 0; - if (merc_is_hom_active(sd->hd)) { - if (sd->hd->homunculus.intimacy > 91000) - merc_hom_evolution(sd->hd); - else - clif_emotion(&sd->hd->bl, E_SWT); - } - return 0; + if(merc_is_hom_active(sd->hd)) + { + if (sd->hd->homunculus.intimacy > 91000) + merc_hom_evolution(sd->hd); + else + clif_emotion(&sd->hd->bl, E_SWT); + } + return 0; } /*========================================== @@ -9867,80 +10116,80 @@ BUILDIN_FUNC(homunculus_evolution) *------------------------------------------*/ BUILDIN_FUNC(homunculus_mutate) { - int homun_id, m_class, m_id; - int homun_array[5] = {6048,6049,6050,6051,6052}; - TBL_PC *sd; + int homun_id, m_class, m_id; + int homun_array[5] = {6048,6049,6050,6051,6052}; + TBL_PC *sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - if (script_hasdata(st,2)) - homun_id = script_getnum(st,2); - else - homun_id = homun_array[rnd() % 5]; + if(script_hasdata(st,2)) + homun_id = script_getnum(st,2); + else + homun_id = homun_array[rnd() % 5]; - if (merc_is_hom_active(sd->hd)) { - m_class = hom_class2mapid(sd->hd->homunculus.class_); - m_id = hom_class2mapid(homun_id); + if(merc_is_hom_active(sd->hd)) { + m_class = hom_class2mapid(sd->hd->homunculus.class_); + m_id = hom_class2mapid(homun_id); - if (m_class != -1 && m_id != -1 && m_class&HOM_EVO && m_id&HOM_S && sd->hd->homunculus.level >= 99) - hom_mutate(sd->hd, homun_id); - else - clif_emotion(&sd->hd->bl, E_SWT); - } - return 0; + if ( m_class != -1 && m_id != -1 && m_class&HOM_EVO && m_id&HOM_S && sd->hd->homunculus.level >= 99 ) + hom_mutate(sd->hd, homun_id); + else + clif_emotion(&sd->hd->bl, E_SWT); + } + return 0; } // [Zephyrus] BUILDIN_FUNC(homunculus_shuffle) { - TBL_PC *sd; + TBL_PC *sd; - sd=script_rid2sd(st); - if (sd == NULL) - return 0; + sd=script_rid2sd(st); + if( sd == NULL ) + return 0; - if (merc_is_hom_active(sd->hd)) - merc_hom_shuffle(sd->hd); + if(merc_is_hom_active(sd->hd)) + merc_hom_shuffle(sd->hd); - return 0; + return 0; } //These two functions bring the eA MAPID_* class functionality to scripts. BUILDIN_FUNC(eaclass) { - int class_; - if (script_hasdata(st,2)) - class_ = script_getnum(st,2); - else { - TBL_PC *sd; - sd=script_rid2sd(st); - if (!sd) { - script_pushint(st,-1); - return 0; - } - class_ = sd->status.class_; - } - script_pushint(st,pc_jobid2mapid(class_)); - return 0; + int class_; + if( script_hasdata(st,2) ) + class_ = script_getnum(st,2); + else { + TBL_PC *sd; + sd=script_rid2sd(st); + if (!sd) { + script_pushint(st,-1); + return 0; + } + class_ = sd->status.class_; + } + script_pushint(st,pc_jobid2mapid(class_)); + return 0; } BUILDIN_FUNC(roclass) { - int class_ =script_getnum(st,2); - int sex; - if (script_hasdata(st,3)) - sex = script_getnum(st,3); - else { - TBL_PC *sd; - if (st->rid && (sd=script_rid2sd(st))) - sex = sd->status.sex; - else - sex = 1; //Just use male when not found. - } - script_pushint(st,pc_mapid2jobid(class_, sex)); - return 0; + int class_ =script_getnum(st,2); + int sex; + if( script_hasdata(st,3) ) + sex = script_getnum(st,3); + else { + TBL_PC *sd; + if (st->rid && (sd=script_rid2sd(st))) + sex = sd->status.sex; + else + sex = 1; //Just use male when not found. + } + script_pushint(st,pc_mapid2jobid(class_, sex)); + return 0; } /*========================================== @@ -9948,50 +10197,50 @@ BUILDIN_FUNC(roclass) *------------------------------------------*/ BUILDIN_FUNC(birthpet) { - TBL_PC *sd; - sd=script_rid2sd(st); - if (sd == NULL) - return 0; + TBL_PC *sd; + sd=script_rid2sd(st); + if( sd == NULL ) + return 0; - if (sd->status.pet_id) { - // do not send egg list, when you already have a pet - return 0; - } + if( sd->status.pet_id ) + {// do not send egg list, when you already have a pet + return 0; + } - clif_sendegg(sd); - return 0; + clif_sendegg(sd); + return 0; } /*========================================== * Added - AppleGirl For Advanced Classes, (Updated for Cleaner Script Purposes) * @type - * 1 : make like after rebirth - * 2 : blvl,jlvl=1, skillpoint=0 - * 3 : don't reset skill, blvl=1 - * 4 : jlvl=0 + * 1 : make like after rebirth + * 2 : blvl,jlvl=1, skillpoint=0 + * 3 : don't reset skill, blvl=1 + * 4 : jlvl=0 *------------------------------------------*/ BUILDIN_FUNC(resetlvl) { - TBL_PC *sd; + TBL_PC *sd; - int type=script_getnum(st,2); + int type=script_getnum(st,2); - sd=script_rid2sd(st); - if (sd == NULL) - return 0; + sd=script_rid2sd(st); + if( sd == NULL ) + return 0; - pc_resetlvl(sd,type); - return 0; + pc_resetlvl(sd,type); + return 0; } /*========================================== * Reset a player status point *------------------------------------------*/ BUILDIN_FUNC(resetstatus) { - TBL_PC *sd; - sd=script_rid2sd(st); - pc_resetstate(sd); - return 0; + TBL_PC *sd; + sd=script_rid2sd(st); + pc_resetstate(sd); + return 0; } /*========================================== @@ -9999,10 +10248,10 @@ BUILDIN_FUNC(resetstatus) *------------------------------------------*/ BUILDIN_FUNC(resetskill) { - TBL_PC *sd; - sd=script_rid2sd(st); - pc_resetskill(sd,1); - return 0; + TBL_PC *sd; + sd=script_rid2sd(st); + pc_resetskill(sd,1); + return 0; } /*========================================== @@ -10010,10 +10259,10 @@ BUILDIN_FUNC(resetskill) *------------------------------------------*/ BUILDIN_FUNC(skillpointcount) { - TBL_PC *sd; - sd=script_rid2sd(st); - script_pushint(st,sd->status.skill_point + pc_resetskill(sd,2)); - return 0; + TBL_PC *sd; + sd=script_rid2sd(st); + script_pushint(st,sd->status.skill_point + pc_resetskill(sd,2)); + return 0; } /*========================================== @@ -10021,36 +10270,37 @@ BUILDIN_FUNC(skillpointcount) *------------------------------------------*/ BUILDIN_FUNC(changebase) { - TBL_PC *sd=NULL; - int vclass; + TBL_PC *sd=NULL; + int vclass; - if (script_hasdata(st,3)) - sd=map_id2sd(script_getnum(st,3)); - else - sd=script_rid2sd(st); + if( script_hasdata(st,3) ) + sd=map_id2sd(script_getnum(st,3)); + else + sd=script_rid2sd(st); - if (sd == NULL) - return 0; + if(sd == NULL) + return 0; - vclass = script_getnum(st,2); - if (vclass == JOB_WEDDING) { - if (!battle_config.wedding_modifydisplay || //Do not show the wedding sprites - sd->class_&JOBL_BABY //Baby classes screw up when showing wedding sprites. [Skotlex] They don't seem to anymore. - ) - return 0; - } + vclass = script_getnum(st,2); + if(vclass == JOB_WEDDING) + { + if (!battle_config.wedding_modifydisplay || //Do not show the wedding sprites + sd->class_&JOBL_BABY //Baby classes screw up when showing wedding sprites. [Skotlex] They don't seem to anymore. + ) + return 0; + } - if (!sd->disguise && vclass != sd->vd.class_) { - status_set_viewdata(&sd->bl, vclass); - //Updated client view. Base, Weapon and Cloth Colors. - clif_changelook(&sd->bl,LOOK_BASE,sd->vd.class_); - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); - if (sd->vd.cloth_color) - clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); - clif_skillinfoblock(sd); - } + if(!sd->disguise && vclass != sd->vd.class_) { + status_set_viewdata(&sd->bl, vclass); + //Updated client view. Base, Weapon and Cloth Colors. + clif_changelook(&sd->bl,LOOK_BASE,sd->vd.class_); + clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); + if (sd->vd.cloth_color) + clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); + clif_skillinfoblock(sd); + } - return 0; + return 0; } /*========================================== @@ -10058,16 +10308,16 @@ BUILDIN_FUNC(changebase) *------------------------------------------*/ BUILDIN_FUNC(changesex) { - int i; - TBL_PC *sd = NULL; - sd = script_rid2sd(st); + int i; + TBL_PC *sd = NULL; + sd = script_rid2sd(st); - pc_resetskill(sd,4); - // to avoid any problem with equipment and invalid sex, equipment is unequiped. - for (i=0; i<EQI_MAX; i++) - if (sd->equip_index[i] >= 0) pc_unequipitem(sd, sd->equip_index[i], 3); - chrif_changesex(sd); - return 0; + pc_resetskill(sd,4); + // to avoid any problem with equipment and invalid sex, equipment is unequiped. + for( i=0; i<EQI_MAX; i++ ) + if( sd->equip_index[i] >= 0 ) pc_unequipitem(sd, sd->equip_index[i], 3); + chrif_changesex(sd); + return 0; } /*========================================== @@ -10075,22 +10325,22 @@ BUILDIN_FUNC(changesex) *------------------------------------------*/ BUILDIN_FUNC(globalmes) { - struct block_list *bl = map_id2bl(st->oid); - struct npc_data *nd = (struct npc_data *)bl; - const char *name=NULL,*mes; + struct block_list *bl = map_id2bl(st->oid); + struct npc_data *nd = (struct npc_data *)bl; + const char *name=NULL,*mes; - mes=script_getstr(st,2); - if (mes==NULL) return 0; + mes=script_getstr(st,2); + if(mes==NULL) return 0; - if (script_hasdata(st,3)) { // npc name to display - name=script_getstr(st,3); - } else { - name=nd->name; //use current npc name - } + if(script_hasdata(st,3)){ // npc name to display + name=script_getstr(st,3); + } else { + name=nd->name; //use current npc name + } - npc_globalmessage(name,mes); // broadcast to all players connected + npc_globalmessage(name,mes); // broadcast to all players connected - return 0; + return 0; } ///////////////////////////////////////////////////////////////////// @@ -10102,21 +10352,21 @@ BUILDIN_FUNC(globalmes) /// waitingroom "<title>",<limit>{,"<event>"{,<trigger>{,<zeny>{,<minlvl>{,<maxlvl>}}}}}; BUILDIN_FUNC(waitingroom) { - struct npc_data *nd; - int pub = 1; - const char *title = script_getstr(st, 2); - int limit = script_getnum(st, 3); - const char *ev = script_hasdata(st,4) ? script_getstr(st,4) : ""; - int trigger = script_hasdata(st,5) ? script_getnum(st,5) : limit; - int zeny = script_hasdata(st,6) ? script_getnum(st,6) : 0; - int minLvl = script_hasdata(st,7) ? script_getnum(st,7) : 1; - int maxLvl = script_hasdata(st,8) ? script_getnum(st,8) : MAX_LEVEL; + struct npc_data* nd; + int pub = 1; + const char* title = script_getstr(st, 2); + int limit = script_getnum(st, 3); + const char* ev = script_hasdata(st,4) ? script_getstr(st,4) : ""; + int trigger = script_hasdata(st,5) ? script_getnum(st,5) : limit; + int zeny = script_hasdata(st,6) ? script_getnum(st,6) : 0; + int minLvl = script_hasdata(st,7) ? script_getnum(st,7) : 1; + int maxLvl = script_hasdata(st,8) ? script_getnum(st,8) : MAX_LEVEL; - nd = (struct npc_data *)map_id2bl(st->oid); - if (nd != NULL) - chat_createnpcchat(nd, title, limit, pub, trigger, ev, zeny, minLvl, maxLvl); + nd = (struct npc_data *)map_id2bl(st->oid); + if( nd != NULL ) + chat_createnpcchat(nd, title, limit, pub, trigger, ev, zeny, minLvl, maxLvl); - return 0; + return 0; } /// Removes the waiting room of the current or target npc. @@ -10125,14 +10375,14 @@ BUILDIN_FUNC(waitingroom) /// delwaitingroom; BUILDIN_FUNC(delwaitingroom) { - struct npc_data *nd; - if (script_hasdata(st,2)) - nd = npc_name2id(script_getstr(st, 2)); - else - nd = (struct npc_data *)map_id2bl(st->oid); - if (nd != NULL) - chat_deletenpcchat(nd); - return 0; + struct npc_data* nd; + if( script_hasdata(st,2) ) + nd = npc_name2id(script_getstr(st, 2)); + else + nd = (struct npc_data *)map_id2bl(st->oid); + if( nd != NULL ) + chat_deletenpcchat(nd); + return 0; } /// Kicks all the players from the waiting room of the current or target npc. @@ -10141,17 +10391,17 @@ BUILDIN_FUNC(delwaitingroom) /// kickwaitingroomall; BUILDIN_FUNC(waitingroomkickall) { - struct npc_data *nd; - struct chat_data *cd; + struct npc_data* nd; + struct chat_data* cd; - if (script_hasdata(st,2)) - nd = npc_name2id(script_getstr(st,2)); - else - nd = (struct npc_data *)map_id2bl(st->oid); + if( script_hasdata(st,2) ) + nd = npc_name2id(script_getstr(st,2)); + else + nd = (struct npc_data *)map_id2bl(st->oid); - if (nd != NULL && (cd=(struct chat_data *)map_id2bl(nd->chat_id)) != NULL) - chat_npckickall(cd); - return 0; + if( nd != NULL && (cd=(struct chat_data *)map_id2bl(nd->chat_id)) != NULL ) + chat_npckickall(cd); + return 0; } /// Enables the waiting room event of the current or target npc. @@ -10160,17 +10410,17 @@ BUILDIN_FUNC(waitingroomkickall) /// enablewaitingroomevent; BUILDIN_FUNC(enablewaitingroomevent) { - struct npc_data *nd; - struct chat_data *cd; + struct npc_data* nd; + struct chat_data* cd; - if (script_hasdata(st,2)) - nd = npc_name2id(script_getstr(st, 2)); - else - nd = (struct npc_data *)map_id2bl(st->oid); + if( script_hasdata(st,2) ) + nd = npc_name2id(script_getstr(st, 2)); + else + nd = (struct npc_data *)map_id2bl(st->oid); - if (nd != NULL && (cd=(struct chat_data *)map_id2bl(nd->chat_id)) != NULL) - chat_enableevent(cd); - return 0; + if( nd != NULL && (cd=(struct chat_data *)map_id2bl(nd->chat_id)) != NULL ) + chat_enableevent(cd); + return 0; } /// Disables the waiting room event of the current or target npc. @@ -10179,17 +10429,17 @@ BUILDIN_FUNC(enablewaitingroomevent) /// disablewaitingroomevent; BUILDIN_FUNC(disablewaitingroomevent) { - struct npc_data *nd; - struct chat_data *cd; + struct npc_data *nd; + struct chat_data *cd; - if (script_hasdata(st,2)) - nd = npc_name2id(script_getstr(st, 2)); - else - nd = (struct npc_data *)map_id2bl(st->oid); + if( script_hasdata(st,2) ) + nd = npc_name2id(script_getstr(st, 2)); + else + nd = (struct npc_data *)map_id2bl(st->oid); - if (nd != NULL && (cd=(struct chat_data *)map_id2bl(nd->chat_id)) != NULL) - chat_disableevent(cd); - return 0; + if( nd != NULL && (cd=(struct chat_data *)map_id2bl(nd->chat_id)) != NULL ) + chat_disableevent(cd); + return 0; } /// Returns info on the waiting room of the current or target npc. @@ -10208,54 +10458,36 @@ BUILDIN_FUNC(disablewaitingroomevent) /// getwaitingroomstate(<type>) -> <info> BUILDIN_FUNC(getwaitingroomstate) { - struct npc_data *nd; - struct chat_data *cd; - int type; - - type = script_getnum(st,2); - if (script_hasdata(st,3)) - nd = npc_name2id(script_getstr(st, 3)); - else - nd = (struct npc_data *)map_id2bl(st->oid); - - if (nd == NULL || (cd=(struct chat_data *)map_id2bl(nd->chat_id)) == NULL) { - script_pushint(st, -1); - return 0; - } - - switch (type) { - case 0: - script_pushint(st, cd->users); - break; - case 1: - script_pushint(st, cd->limit); - break; - case 2: - script_pushint(st, cd->trigger&0x7f); - break; - case 3: - script_pushint(st, ((cd->trigger&0x80)!=0)); - break; - case 4: - script_pushstrcopy(st, cd->title); - break; - case 5: - script_pushstrcopy(st, cd->pass); - break; - case 16: - script_pushstrcopy(st, cd->npc_event); - break; - case 32: - script_pushint(st, (cd->users >= cd->limit)); - break; - case 33: - script_pushint(st, (cd->users >= cd->trigger)); - break; - default: - script_pushint(st, -1); - break; - } - return 0; + struct npc_data *nd; + struct chat_data *cd; + int type; + + type = script_getnum(st,2); + if( script_hasdata(st,3) ) + nd = npc_name2id(script_getstr(st, 3)); + else + nd = (struct npc_data *)map_id2bl(st->oid); + + if( nd == NULL || (cd=(struct chat_data *)map_id2bl(nd->chat_id)) == NULL ) + { + script_pushint(st, -1); + return 0; + } + + switch(type) + { + case 0: script_pushint(st, cd->users); break; + case 1: script_pushint(st, cd->limit); break; + case 2: script_pushint(st, cd->trigger&0x7f); break; + case 3: script_pushint(st, ((cd->trigger&0x80)!=0)); break; + case 4: script_pushstrcopy(st, cd->title); break; + case 5: script_pushstrcopy(st, cd->pass); break; + case 16: script_pushstrcopy(st, cd->npc_event);break; + case 32: script_pushint(st, (cd->users >= cd->limit)); break; + case 33: script_pushint(st, (cd->users >= cd->trigger)); break; + default: script_pushint(st, -1); break; + } + return 0; } /// Warps the trigger or target amount of players to the target map and position. @@ -10272,55 +10504,56 @@ BUILDIN_FUNC(getwaitingroomstate) /// warpwaitingpc "<map name>",<x>,<y>; BUILDIN_FUNC(warpwaitingpc) { - int x; - int y; - int i; - int n; - const char *map_name; - struct npc_data *nd; - struct chat_data *cd; - TBL_PC *sd; - - nd = (struct npc_data *)map_id2bl(st->oid); - if (nd == NULL || (cd=(struct chat_data *)map_id2bl(nd->chat_id)) == NULL) - return 0; - - map_name = script_getstr(st,2); - x = script_getnum(st,3); - y = script_getnum(st,4); - n = cd->trigger&0x7f; - - if (script_hasdata(st,5)) - n = script_getnum(st,5); - - for (i = 0; i < n && cd->users > 0; i++) { - sd = cd->usersd[0]; - - if (strcmp(map_name,"SavePoint") == 0 && map[sd->bl.m].flag.noteleport) { - // can't teleport on this map - break; - } - - if (cd->zeny) { - // fee set - if ((uint32)sd->status.zeny < cd->zeny) { - // no zeny to cover set fee - break; - } - pc_payzeny(sd, cd->zeny, LOG_TYPE_NPC, NULL); - } - - mapreg_setreg(reference_uid(add_str("$@warpwaitingpc"), i), sd->bl.id); - - if (strcmp(map_name,"Random") == 0) - pc_randomwarp(sd,CLR_TELEPORT); - else if (strcmp(map_name,"SavePoint") == 0) - pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); - else - pc_setpos(sd, mapindex_name2id(map_name), x, y, CLR_OUTSIGHT); - } - mapreg_setreg(add_str("$@warpwaitingpcnum"), i); - return 0; + int x; + int y; + int i; + int n; + const char* map_name; + struct npc_data* nd; + struct chat_data* cd; + TBL_PC* sd; + + nd = (struct npc_data *)map_id2bl(st->oid); + if( nd == NULL || (cd=(struct chat_data *)map_id2bl(nd->chat_id)) == NULL ) + return 0; + + map_name = script_getstr(st,2); + x = script_getnum(st,3); + y = script_getnum(st,4); + n = cd->trigger&0x7f; + + if( script_hasdata(st,5) ) + n = script_getnum(st,5); + + for( i = 0; i < n && cd->users > 0; i++ ) + { + sd = cd->usersd[0]; + + if( strcmp(map_name,"SavePoint") == 0 && map[sd->bl.m].flag.noteleport ) + {// can't teleport on this map + break; + } + + if( cd->zeny ) + {// fee set + if( (uint32)sd->status.zeny < cd->zeny ) + {// no zeny to cover set fee + break; + } + pc_payzeny(sd, cd->zeny, LOG_TYPE_NPC, NULL); + } + + mapreg_setreg(reference_uid(add_str("$@warpwaitingpc"), i), sd->bl.id); + + if( strcmp(map_name,"Random") == 0 ) + pc_randomwarp(sd,CLR_TELEPORT); + else if( strcmp(map_name,"SavePoint") == 0 ) + pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); + else + pc_setpos(sd, mapindex_name2id(map_name), x, y, CLR_OUTSIGHT); + } + mapreg_setreg(add_str("$@warpwaitingpcnum"), i); + return 0; } ///////////////////////////////////////////////////////////////////// @@ -10330,12 +10563,13 @@ BUILDIN_FUNC(warpwaitingpc) /// Detaches a character from a script. /// /// @param st Script state to detach the character from. -static void script_detach_rid(struct script_state *st) +static void script_detach_rid(struct script_state* st) { - if (st->rid) { - script_detach_state(st, false); - st->rid = 0; - } + if(st->rid) + { + script_detach_state(st, false); + st->rid = 0; + } } /*========================================== @@ -10343,38 +10577,38 @@ static void script_detach_rid(struct script_state *st) *------------------------------------------*/ BUILDIN_FUNC(attachrid) { - int rid = script_getnum(st,2); - struct map_session_data *sd; + int rid = script_getnum(st,2); + struct map_session_data* sd; - if ((sd = map_id2sd(rid))!=NULL) { - script_detach_rid(st); + if ((sd = map_id2sd(rid))!=NULL) { + script_detach_rid(st); - st->rid = rid; - script_attach_state(st); - script_pushint(st,1); - } else - script_pushint(st,0); - return 0; + st->rid = rid; + script_attach_state(st); + script_pushint(st,1); + } else + script_pushint(st,0); + return 0; } /*========================================== * Detach script to rid *------------------------------------------*/ BUILDIN_FUNC(detachrid) { - script_detach_rid(st); - return 0; + script_detach_rid(st); + return 0; } /*========================================== * Chk if account connected, (and charid from account if specified) *------------------------------------------*/ BUILDIN_FUNC(isloggedin) { - TBL_PC *sd = map_id2sd(script_getnum(st,2)); - if (script_hasdata(st,3) && sd && - sd->status.char_id != script_getnum(st,3)) - sd = NULL; - push_val(st->stack,C_INT,sd!=NULL); - return 0; + TBL_PC* sd = map_id2sd(script_getnum(st,2)); + if (script_hasdata(st,3) && sd && + sd->status.char_id != script_getnum(st,3)) + sd = NULL; + push_val(st->stack,C_INT,sd!=NULL); + return 0; } @@ -10383,802 +10617,509 @@ BUILDIN_FUNC(isloggedin) *------------------------------------------*/ BUILDIN_FUNC(setmapflagnosave) { - int m,x,y; - unsigned short mapindex; - const char *str,*str2; - - str=script_getstr(st,2); - str2=script_getstr(st,3); - x=script_getnum(st,4); - y=script_getnum(st,5); - m = map_mapname2mapid(str); - mapindex = mapindex_name2id(str2); - - if (m >= 0 && mapindex) { - map[m].flag.nosave=1; - map[m].save.map=mapindex; - map[m].save.x=x; - map[m].save.y=y; - } + int m,x,y; + unsigned short mapindex; + const char *str,*str2; - return 0; + str=script_getstr(st,2); + str2=script_getstr(st,3); + x=script_getnum(st,4); + y=script_getnum(st,5); + m = map_mapname2mapid(str); + mapindex = mapindex_name2id(str2); + + if(m >= 0 && mapindex) { + map[m].flag.nosave=1; + map[m].save.map=mapindex; + map[m].save.x=x; + map[m].save.y=y; + } + + return 0; } BUILDIN_FUNC(getmapflag) { - int m,i; - const char *str; - - str=script_getstr(st,2); - i=script_getnum(st,3); - - m = map_mapname2mapid(str); - if (m >= 0) { - switch (i) { - case MF_NOMEMO: - script_pushint(st,map[m].flag.nomemo); - break; - case MF_NOTELEPORT: - script_pushint(st,map[m].flag.noteleport); - break; - case MF_NOSAVE: - script_pushint(st,map[m].flag.nosave); - break; - case MF_NOBRANCH: - script_pushint(st,map[m].flag.nobranch); - break; - case MF_NOPENALTY: - script_pushint(st,map[m].flag.noexppenalty); - break; - case MF_NOZENYPENALTY: - script_pushint(st,map[m].flag.nozenypenalty); - break; - case MF_PVP: - script_pushint(st,map[m].flag.pvp); - break; - case MF_PVP_NOPARTY: - script_pushint(st,map[m].flag.pvp_noparty); - break; - case MF_PVP_NOGUILD: - script_pushint(st,map[m].flag.pvp_noguild); - break; - case MF_GVG: - script_pushint(st,map[m].flag.gvg); - break; - case MF_GVG_NOPARTY: - script_pushint(st,map[m].flag.gvg_noparty); - break; - case MF_NOTRADE: - script_pushint(st,map[m].flag.notrade); - break; - case MF_NOSKILL: - script_pushint(st,map[m].flag.noskill); - break; - case MF_NOWARP: - script_pushint(st,map[m].flag.nowarp); - break; - case MF_PARTYLOCK: - script_pushint(st,map[m].flag.partylock); - break; - case MF_NOICEWALL: - script_pushint(st,map[m].flag.noicewall); - break; - case MF_SNOW: - script_pushint(st,map[m].flag.snow); - break; - case MF_FOG: - script_pushint(st,map[m].flag.fog); - break; - case MF_SAKURA: - script_pushint(st,map[m].flag.sakura); - break; - case MF_LEAVES: - script_pushint(st,map[m].flag.leaves); - break; - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //case MF_RAIN: script_pushint(st,map[m].flag.rain); break; - case MF_NOGO: - script_pushint(st,map[m].flag.nogo); - break; - case MF_CLOUDS: - script_pushint(st,map[m].flag.clouds); - break; - case MF_CLOUDS2: - script_pushint(st,map[m].flag.clouds2); - break; - case MF_FIREWORKS: - script_pushint(st,map[m].flag.fireworks); - break; - case MF_GVG_CASTLE: - script_pushint(st,map[m].flag.gvg_castle); - break; - case MF_GVG_DUNGEON: - script_pushint(st,map[m].flag.gvg_dungeon); - break; - case MF_NIGHTENABLED: - script_pushint(st,map[m].flag.nightenabled); - break; - case MF_NOBASEEXP: - script_pushint(st,map[m].flag.nobaseexp); - break; - case MF_NOJOBEXP: - script_pushint(st,map[m].flag.nojobexp); - break; - case MF_NOMOBLOOT: - script_pushint(st,map[m].flag.nomobloot); - break; - case MF_NOMVPLOOT: - script_pushint(st,map[m].flag.nomvploot); - break; - case MF_NORETURN: - script_pushint(st,map[m].flag.noreturn); - break; - case MF_NOWARPTO: - script_pushint(st,map[m].flag.nowarpto); - break; - case MF_NIGHTMAREDROP: - script_pushint(st,map[m].flag.pvp_nightmaredrop); - break; - case MF_RESTRICTED: - script_pushint(st,map[m].flag.restricted); - break; - case MF_NOCOMMAND: - script_pushint(st,map[m].nocommand); - break; - case MF_NODROP: - script_pushint(st,map[m].flag.nodrop); - break; - case MF_JEXP: - script_pushint(st,map[m].jexp); - break; - case MF_BEXP: - script_pushint(st,map[m].bexp); - break; - case MF_NOVENDING: - script_pushint(st,map[m].flag.novending); - break; - case MF_LOADEVENT: - script_pushint(st,map[m].flag.loadevent); - break; - case MF_NOCHAT: - script_pushint(st,map[m].flag.nochat); - break; - case MF_NOEXPPENALTY: - script_pushint(st,map[m].flag.noexppenalty); - break; - case MF_GUILDLOCK: - script_pushint(st,map[m].flag.guildlock); - break; - case MF_TOWN: - script_pushint(st,map[m].flag.town); - break; - case MF_AUTOTRADE: - script_pushint(st,map[m].flag.autotrade); - break; - case MF_ALLOWKS: - script_pushint(st,map[m].flag.allowks); - break; - case MF_MONSTER_NOTELEPORT: - script_pushint(st,map[m].flag.monster_noteleport); - break; - case MF_PVP_NOCALCRANK: - script_pushint(st,map[m].flag.pvp_nocalcrank); - break; - case MF_BATTLEGROUND: - script_pushint(st,map[m].flag.battleground); - break; - case MF_RESET: - script_pushint(st,map[m].flag.reset); - break; - } - } - - return 0; + int m,i; + const char *str; + + str=script_getstr(st,2); + i=script_getnum(st,3); + + m = map_mapname2mapid(str); + if(m >= 0) { + switch(i) { + case MF_NOMEMO: script_pushint(st,map[m].flag.nomemo); break; + case MF_NOTELEPORT: script_pushint(st,map[m].flag.noteleport); break; + case MF_NOSAVE: script_pushint(st,map[m].flag.nosave); break; + case MF_NOBRANCH: script_pushint(st,map[m].flag.nobranch); break; + case MF_NOPENALTY: script_pushint(st,map[m].flag.noexppenalty); break; + case MF_NOZENYPENALTY: script_pushint(st,map[m].flag.nozenypenalty); break; + case MF_PVP: script_pushint(st,map[m].flag.pvp); break; + case MF_PVP_NOPARTY: script_pushint(st,map[m].flag.pvp_noparty); break; + case MF_PVP_NOGUILD: script_pushint(st,map[m].flag.pvp_noguild); break; + case MF_GVG: script_pushint(st,map[m].flag.gvg); break; + case MF_GVG_NOPARTY: script_pushint(st,map[m].flag.gvg_noparty); break; + case MF_NOTRADE: script_pushint(st,map[m].flag.notrade); break; + case MF_NOSKILL: script_pushint(st,map[m].flag.noskill); break; + case MF_NOWARP: script_pushint(st,map[m].flag.nowarp); break; + case MF_PARTYLOCK: script_pushint(st,map[m].flag.partylock); break; + case MF_NOICEWALL: script_pushint(st,map[m].flag.noicewall); break; + case MF_SNOW: script_pushint(st,map[m].flag.snow); break; + case MF_FOG: script_pushint(st,map[m].flag.fog); break; + case MF_SAKURA: script_pushint(st,map[m].flag.sakura); break; + case MF_LEAVES: script_pushint(st,map[m].flag.leaves); break; + /** + * No longer available, keeping here just in case it's back someday. [Ind] + **/ + //case MF_RAIN: script_pushint(st,map[m].flag.rain); break; + case MF_NOGO: script_pushint(st,map[m].flag.nogo); break; + case MF_CLOUDS: script_pushint(st,map[m].flag.clouds); break; + case MF_CLOUDS2: script_pushint(st,map[m].flag.clouds2); break; + case MF_FIREWORKS: script_pushint(st,map[m].flag.fireworks); break; + case MF_GVG_CASTLE: script_pushint(st,map[m].flag.gvg_castle); break; + case MF_GVG_DUNGEON: script_pushint(st,map[m].flag.gvg_dungeon); break; + case MF_NIGHTENABLED: script_pushint(st,map[m].flag.nightenabled); break; + case MF_NOBASEEXP: script_pushint(st,map[m].flag.nobaseexp); break; + case MF_NOJOBEXP: script_pushint(st,map[m].flag.nojobexp); break; + case MF_NOMOBLOOT: script_pushint(st,map[m].flag.nomobloot); break; + case MF_NOMVPLOOT: script_pushint(st,map[m].flag.nomvploot); break; + case MF_NORETURN: script_pushint(st,map[m].flag.noreturn); break; + case MF_NOWARPTO: script_pushint(st,map[m].flag.nowarpto); break; + case MF_NIGHTMAREDROP: script_pushint(st,map[m].flag.pvp_nightmaredrop); break; + case MF_RESTRICTED: script_pushint(st,map[m].flag.restricted); break; + case MF_NOCOMMAND: script_pushint(st,map[m].nocommand); break; + case MF_NODROP: script_pushint(st,map[m].flag.nodrop); break; + case MF_JEXP: script_pushint(st,map[m].jexp); break; + case MF_BEXP: script_pushint(st,map[m].bexp); break; + case MF_NOVENDING: script_pushint(st,map[m].flag.novending); break; + case MF_LOADEVENT: script_pushint(st,map[m].flag.loadevent); break; + case MF_NOCHAT: script_pushint(st,map[m].flag.nochat); break; + case MF_NOEXPPENALTY: script_pushint(st,map[m].flag.noexppenalty ); break; + case MF_GUILDLOCK: script_pushint(st,map[m].flag.guildlock); break; + case MF_TOWN: script_pushint(st,map[m].flag.town); break; + case MF_AUTOTRADE: script_pushint(st,map[m].flag.autotrade); break; + case MF_ALLOWKS: script_pushint(st,map[m].flag.allowks); break; + case MF_MONSTER_NOTELEPORT: script_pushint(st,map[m].flag.monster_noteleport); break; + case MF_PVP_NOCALCRANK: script_pushint(st,map[m].flag.pvp_nocalcrank); break; + case MF_BATTLEGROUND: script_pushint(st,map[m].flag.battleground); break; + case MF_RESET: script_pushint(st,map[m].flag.reset); break; + } + } + + return 0; } /* pvp timer handling */ -static int script_mapflag_pvp_sub(struct block_list *bl,va_list ap) -{ - TBL_PC *sd = (TBL_PC *)bl; - if (sd->pvp_timer == INVALID_TIMER) { - sd->pvp_timer = add_timer(gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0); - sd->pvp_rank = 0; - sd->pvp_lastusers = 0; - sd->pvp_point = 5; - sd->pvp_won = 0; - sd->pvp_lost = 0; - } - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - return 0; +static int script_mapflag_pvp_sub(struct block_list *bl,va_list ap) { + TBL_PC* sd = (TBL_PC*)bl; + if (sd->pvp_timer == INVALID_TIMER) { + sd->pvp_timer = add_timer(gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0); + sd->pvp_rank = 0; + sd->pvp_lastusers = 0; + sd->pvp_point = 5; + sd->pvp_won = 0; + sd->pvp_lost = 0; + } + clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); + return 0; } BUILDIN_FUNC(setmapflag) { - int m,i; - const char *str; - int val=0; - - str=script_getstr(st,2); - i=script_getnum(st,3); - if (script_hasdata(st,4)) { - val=script_getnum(st,4); - } - m = map_mapname2mapid(str); - if (m >= 0) { - switch (i) { - case MF_NOMEMO: - map[m].flag.nomemo = 1; - break; - case MF_NOTELEPORT: - map[m].flag.noteleport = 1; - break; - case MF_NOSAVE: - map[m].flag.nosave = 1; - break; - case MF_NOBRANCH: - map[m].flag.nobranch = 1; - break; - case MF_NOPENALTY: - map[m].flag.noexppenalty = 1; - map[m].flag.nozenypenalty = 1; - break; - case MF_NOZENYPENALTY: - map[m].flag.nozenypenalty = 1; - break; - case MF_PVP: - map[m].flag.pvp = 1; - if (!battle_config.pk_mode) { - map_foreachinmap(script_mapflag_pvp_sub,m,BL_PC); - } - break; - case MF_PVP_NOPARTY: - map[m].flag.pvp_noparty = 1; - break; - case MF_PVP_NOGUILD: - map[m].flag.pvp_noguild = 1; - break; - case MF_GVG: - map[m].flag.gvg = 1; - clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); - break; - case MF_GVG_NOPARTY: - map[m].flag.gvg_noparty = 1; - break; - case MF_NOTRADE: - map[m].flag.notrade = 1; - break; - case MF_NOSKILL: - map[m].flag.noskill = 1; - break; - case MF_NOWARP: - map[m].flag.nowarp = 1; - break; - case MF_PARTYLOCK: - map[m].flag.partylock = 1; - break; - case MF_NOICEWALL: - map[m].flag.noicewall = 1; - break; - case MF_SNOW: - map[m].flag.snow = 1; - break; - case MF_FOG: - map[m].flag.fog = 1; - break; - case MF_SAKURA: - map[m].flag.sakura = 1; - break; - case MF_LEAVES: - map[m].flag.leaves = 1; - break; - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //case MF_RAIN: map[m].flag.rain = 1; break; - case MF_NOGO: - map[m].flag.nogo = 1; - break; - case MF_CLOUDS: - map[m].flag.clouds = 1; - break; - case MF_CLOUDS2: - map[m].flag.clouds2 = 1; - break; - case MF_FIREWORKS: - map[m].flag.fireworks = 1; - break; - case MF_GVG_CASTLE: - map[m].flag.gvg_castle = 1; - break; - case MF_GVG_DUNGEON: - map[m].flag.gvg_dungeon = 1; - break; - case MF_NIGHTENABLED: - map[m].flag.nightenabled = 1; - break; - case MF_NOBASEEXP: - map[m].flag.nobaseexp = 1; - break; - case MF_NOJOBEXP: - map[m].flag.nojobexp = 1; - break; - case MF_NOMOBLOOT: - map[m].flag.nomobloot = 1; - break; - case MF_NOMVPLOOT: - map[m].flag.nomvploot = 1; - break; - case MF_NORETURN: - map[m].flag.noreturn = 1; - break; - case MF_NOWARPTO: - map[m].flag.nowarpto = 1; - break; - case MF_NIGHTMAREDROP: - map[m].flag.pvp_nightmaredrop = 1; - break; - case MF_RESTRICTED: - map[m].zone |= 1<<(val+1); - map[m].flag.restricted=1; - break; - case MF_NOCOMMAND: - map[m].nocommand = (val <= 0) ? 100 : val; - break; - case MF_NODROP: - map[m].flag.nodrop = 1; - break; - case MF_JEXP: - map[m].jexp = (val <= 0) ? 100 : val; - break; - case MF_BEXP: - map[m].bexp = (val <= 0) ? 100 : val; - break; - case MF_NOVENDING: - map[m].flag.novending = 1; - break; - case MF_LOADEVENT: - map[m].flag.loadevent = 1; - break; - case MF_NOCHAT: - map[m].flag.nochat = 1; - break; - case MF_NOEXPPENALTY: - map[m].flag.noexppenalty = 1; - break; - case MF_GUILDLOCK: - map[m].flag.guildlock = 1; - break; - case MF_TOWN: - map[m].flag.town = 1; - break; - case MF_AUTOTRADE: - map[m].flag.autotrade = 1; - break; - case MF_ALLOWKS: - map[m].flag.allowks = 1; - break; - case MF_MONSTER_NOTELEPORT: - map[m].flag.monster_noteleport = 1; - break; - case MF_PVP_NOCALCRANK: - map[m].flag.pvp_nocalcrank = 1; - break; - case MF_BATTLEGROUND: - map[m].flag.battleground = (val <= 0 || val > 2) ? 1 : val; - break; - case MF_RESET: - map[m].flag.reset = 1; - break; - } - } - - return 0; + int m,i; + const char *str; + int val=0; + + str=script_getstr(st,2); + i=script_getnum(st,3); + if(script_hasdata(st,4)){ + val=script_getnum(st,4); + } + m = map_mapname2mapid(str); + if(m >= 0) { + switch(i) { + case MF_NOMEMO: map[m].flag.nomemo = 1; break; + case MF_NOTELEPORT: map[m].flag.noteleport = 1; break; + case MF_NOSAVE: map[m].flag.nosave = 1; break; + case MF_NOBRANCH: map[m].flag.nobranch = 1; break; + case MF_NOPENALTY: map[m].flag.noexppenalty = 1; map[m].flag.nozenypenalty = 1; break; + case MF_NOZENYPENALTY: map[m].flag.nozenypenalty = 1; break; + case MF_PVP: + map[m].flag.pvp = 1; + if( !battle_config.pk_mode ) { + map_foreachinmap(script_mapflag_pvp_sub,m,BL_PC); + } + break; + case MF_PVP_NOPARTY: map[m].flag.pvp_noparty = 1; break; + case MF_PVP_NOGUILD: map[m].flag.pvp_noguild = 1; break; + case MF_GVG: + map[m].flag.gvg = 1; + clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); + break; + case MF_GVG_NOPARTY: map[m].flag.gvg_noparty = 1; break; + case MF_NOTRADE: map[m].flag.notrade = 1; break; + case MF_NOSKILL: map[m].flag.noskill = 1; break; + case MF_NOWARP: map[m].flag.nowarp = 1; break; + case MF_PARTYLOCK: map[m].flag.partylock = 1; break; + case MF_NOICEWALL: map[m].flag.noicewall = 1; break; + case MF_SNOW: map[m].flag.snow = 1; break; + case MF_FOG: map[m].flag.fog = 1; break; + case MF_SAKURA: map[m].flag.sakura = 1; break; + case MF_LEAVES: map[m].flag.leaves = 1; break; + /** + * No longer available, keeping here just in case it's back someday. [Ind] + **/ + //case MF_RAIN: map[m].flag.rain = 1; break; + case MF_NOGO: map[m].flag.nogo = 1; break; + case MF_CLOUDS: map[m].flag.clouds = 1; break; + case MF_CLOUDS2: map[m].flag.clouds2 = 1; break; + case MF_FIREWORKS: map[m].flag.fireworks = 1; break; + case MF_GVG_CASTLE: map[m].flag.gvg_castle = 1; break; + case MF_GVG_DUNGEON: map[m].flag.gvg_dungeon = 1; break; + case MF_NIGHTENABLED: map[m].flag.nightenabled = 1; break; + case MF_NOBASEEXP: map[m].flag.nobaseexp = 1; break; + case MF_NOJOBEXP: map[m].flag.nojobexp = 1; break; + case MF_NOMOBLOOT: map[m].flag.nomobloot = 1; break; + case MF_NOMVPLOOT: map[m].flag.nomvploot = 1; break; + case MF_NORETURN: map[m].flag.noreturn = 1; break; + case MF_NOWARPTO: map[m].flag.nowarpto = 1; break; + case MF_NIGHTMAREDROP: map[m].flag.pvp_nightmaredrop = 1; break; + case MF_RESTRICTED: + map[m].zone |= 1<<(val+1); + map[m].flag.restricted=1; + break; + case MF_NOCOMMAND: map[m].nocommand = (val <= 0) ? 100 : val; break; + case MF_NODROP: map[m].flag.nodrop = 1; break; + case MF_JEXP: map[m].jexp = (val <= 0) ? 100 : val; break; + case MF_BEXP: map[m].bexp = (val <= 0) ? 100 : val; break; + case MF_NOVENDING: map[m].flag.novending = 1; break; + case MF_LOADEVENT: map[m].flag.loadevent = 1; break; + case MF_NOCHAT: map[m].flag.nochat = 1; break; + case MF_NOEXPPENALTY: map[m].flag.noexppenalty = 1; break; + case MF_GUILDLOCK: map[m].flag.guildlock = 1; break; + case MF_TOWN: map[m].flag.town = 1; break; + case MF_AUTOTRADE: map[m].flag.autotrade = 1; break; + case MF_ALLOWKS: map[m].flag.allowks = 1; break; + case MF_MONSTER_NOTELEPORT: map[m].flag.monster_noteleport = 1; break; + case MF_PVP_NOCALCRANK: map[m].flag.pvp_nocalcrank = 1; break; + case MF_BATTLEGROUND: map[m].flag.battleground = (val <= 0 || val > 2) ? 1 : val; break; + case MF_RESET: map[m].flag.reset = 1; break; + } + } + + return 0; } BUILDIN_FUNC(removemapflag) { - int m,i; - const char *str; - int val=0; - - str=script_getstr(st,2); - i=script_getnum(st,3); - if (script_hasdata(st,4)) { - val=script_getnum(st,4); - } - m = map_mapname2mapid(str); - if (m >= 0) { - switch (i) { - case MF_NOMEMO: - map[m].flag.nomemo = 0; - break; - case MF_NOTELEPORT: - map[m].flag.noteleport = 0; - break; - case MF_NOSAVE: - map[m].flag.nosave = 0; - break; - case MF_NOBRANCH: - map[m].flag.nobranch = 0; - break; - case MF_NOPENALTY: - map[m].flag.noexppenalty = 0; - map[m].flag.nozenypenalty = 0; - break; - case MF_NOZENYPENALTY: - map[m].flag.nozenypenalty = 0; - break; - case MF_PVP: - map[m].flag.pvp = 0; - clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - break; - case MF_PVP_NOPARTY: - map[m].flag.pvp_noparty = 0; - break; - case MF_PVP_NOGUILD: - map[m].flag.pvp_noguild = 0; - break; - case MF_GVG: - map[m].flag.gvg = 0; - clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - break; - case MF_GVG_NOPARTY: - map[m].flag.gvg_noparty = 0; - break; - case MF_NOTRADE: - map[m].flag.notrade = 0; - break; - case MF_NOSKILL: - map[m].flag.noskill = 0; - break; - case MF_NOWARP: - map[m].flag.nowarp = 0; - break; - case MF_PARTYLOCK: - map[m].flag.partylock = 0; - break; - case MF_NOICEWALL: - map[m].flag.noicewall = 0; - break; - case MF_SNOW: - map[m].flag.snow = 0; - break; - case MF_FOG: - map[m].flag.fog = 0; - break; - case MF_SAKURA: - map[m].flag.sakura = 0; - break; - case MF_LEAVES: - map[m].flag.leaves = 0; - break; - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //case MF_RAIN: map[m].flag.rain = 0; break; - case MF_NOGO: - map[m].flag.nogo = 0; - break; - case MF_CLOUDS: - map[m].flag.clouds = 0; - break; - case MF_CLOUDS2: - map[m].flag.clouds2 = 0; - break; - case MF_FIREWORKS: - map[m].flag.fireworks = 0; - break; - case MF_GVG_CASTLE: - map[m].flag.gvg_castle = 0; - break; - case MF_GVG_DUNGEON: - map[m].flag.gvg_dungeon = 0; - break; - case MF_NIGHTENABLED: - map[m].flag.nightenabled = 0; - break; - case MF_NOBASEEXP: - map[m].flag.nobaseexp = 0; - break; - case MF_NOJOBEXP: - map[m].flag.nojobexp = 0; - break; - case MF_NOMOBLOOT: - map[m].flag.nomobloot = 0; - break; - case MF_NOMVPLOOT: - map[m].flag.nomvploot = 0; - break; - case MF_NORETURN: - map[m].flag.noreturn = 0; - break; - case MF_NOWARPTO: - map[m].flag.nowarpto = 0; - break; - case MF_NIGHTMAREDROP: - map[m].flag.pvp_nightmaredrop = 0; - break; - case MF_RESTRICTED: - map[m].zone ^= 1<<(val+1); - if (map[m].zone == 0) { - map[m].flag.restricted=0; - } - break; - case MF_NOCOMMAND: - map[m].nocommand = 0; - break; - case MF_NODROP: - map[m].flag.nodrop = 0; - break; - case MF_JEXP: - map[m].jexp = 0; - break; - case MF_BEXP: - map[m].bexp = 0; - break; - case MF_NOVENDING: - map[m].flag.novending = 0; - break; - case MF_LOADEVENT: - map[m].flag.loadevent = 0; - break; - case MF_NOCHAT: - map[m].flag.nochat = 0; - break; - case MF_NOEXPPENALTY: - map[m].flag.noexppenalty = 0; - break; - case MF_GUILDLOCK: - map[m].flag.guildlock = 0; - break; - case MF_TOWN: - map[m].flag.town = 0; - break; - case MF_AUTOTRADE: - map[m].flag.autotrade = 0; - break; - case MF_ALLOWKS: - map[m].flag.allowks = 0; - break; - case MF_MONSTER_NOTELEPORT: - map[m].flag.monster_noteleport = 0; - break; - case MF_PVP_NOCALCRANK: - map[m].flag.pvp_nocalcrank = 0; - break; - case MF_BATTLEGROUND: - map[m].flag.battleground = 0; - break; - case MF_RESET: - map[m].flag.reset = 0; - break; - } - } - - return 0; + int m,i; + const char *str; + int val=0; + + str=script_getstr(st,2); + i=script_getnum(st,3); + if(script_hasdata(st,4)){ + val=script_getnum(st,4); + } + m = map_mapname2mapid(str); + if(m >= 0) { + switch(i) { + case MF_NOMEMO: map[m].flag.nomemo = 0; break; + case MF_NOTELEPORT: map[m].flag.noteleport = 0; break; + case MF_NOSAVE: map[m].flag.nosave = 0; break; + case MF_NOBRANCH: map[m].flag.nobranch = 0; break; + case MF_NOPENALTY: map[m].flag.noexppenalty = 0; map[m].flag.nozenypenalty = 0; break; + case MF_NOZENYPENALTY: map[m].flag.nozenypenalty = 0; break; + case MF_PVP: + map[m].flag.pvp = 0; + clif_map_property_mapall(m, MAPPROPERTY_NOTHING); + break; + case MF_PVP_NOPARTY: map[m].flag.pvp_noparty = 0; break; + case MF_PVP_NOGUILD: map[m].flag.pvp_noguild = 0; break; + case MF_GVG: + map[m].flag.gvg = 0; + clif_map_property_mapall(m, MAPPROPERTY_NOTHING); + break; + case MF_GVG_NOPARTY: map[m].flag.gvg_noparty = 0; break; + case MF_NOTRADE: map[m].flag.notrade = 0; break; + case MF_NOSKILL: map[m].flag.noskill = 0; break; + case MF_NOWARP: map[m].flag.nowarp = 0; break; + case MF_PARTYLOCK: map[m].flag.partylock = 0; break; + case MF_NOICEWALL: map[m].flag.noicewall = 0; break; + case MF_SNOW: map[m].flag.snow = 0; break; + case MF_FOG: map[m].flag.fog = 0; break; + case MF_SAKURA: map[m].flag.sakura = 0; break; + case MF_LEAVES: map[m].flag.leaves = 0; break; + /** + * No longer available, keeping here just in case it's back someday. [Ind] + **/ + //case MF_RAIN: map[m].flag.rain = 0; break; + case MF_NOGO: map[m].flag.nogo = 0; break; + case MF_CLOUDS: map[m].flag.clouds = 0; break; + case MF_CLOUDS2: map[m].flag.clouds2 = 0; break; + case MF_FIREWORKS: map[m].flag.fireworks = 0; break; + case MF_GVG_CASTLE: map[m].flag.gvg_castle = 0; break; + case MF_GVG_DUNGEON: map[m].flag.gvg_dungeon = 0; break; + case MF_NIGHTENABLED: map[m].flag.nightenabled = 0; break; + case MF_NOBASEEXP: map[m].flag.nobaseexp = 0; break; + case MF_NOJOBEXP: map[m].flag.nojobexp = 0; break; + case MF_NOMOBLOOT: map[m].flag.nomobloot = 0; break; + case MF_NOMVPLOOT: map[m].flag.nomvploot = 0; break; + case MF_NORETURN: map[m].flag.noreturn = 0; break; + case MF_NOWARPTO: map[m].flag.nowarpto = 0; break; + case MF_NIGHTMAREDROP: map[m].flag.pvp_nightmaredrop = 0; break; + case MF_RESTRICTED: + map[m].zone ^= 1<<(val+1); + if (map[m].zone == 0){ + map[m].flag.restricted=0; + } + break; + case MF_NOCOMMAND: map[m].nocommand = 0; break; + case MF_NODROP: map[m].flag.nodrop = 0; break; + case MF_JEXP: map[m].jexp = 0; break; + case MF_BEXP: map[m].bexp = 0; break; + case MF_NOVENDING: map[m].flag.novending = 0; break; + case MF_LOADEVENT: map[m].flag.loadevent = 0; break; + case MF_NOCHAT: map[m].flag.nochat = 0; break; + case MF_NOEXPPENALTY: map[m].flag.noexppenalty = 0; break; + case MF_GUILDLOCK: map[m].flag.guildlock = 0; break; + case MF_TOWN: map[m].flag.town = 0; break; + case MF_AUTOTRADE: map[m].flag.autotrade = 0; break; + case MF_ALLOWKS: map[m].flag.allowks = 0; break; + case MF_MONSTER_NOTELEPORT: map[m].flag.monster_noteleport = 0; break; + case MF_PVP_NOCALCRANK: map[m].flag.pvp_nocalcrank = 0; break; + case MF_BATTLEGROUND: map[m].flag.battleground = 0; break; + case MF_RESET: map[m].flag.reset = 0; break; + } + } + + return 0; } BUILDIN_FUNC(pvpon) { - int m; - const char *str; - TBL_PC *sd = NULL; - struct s_mapiterator *iter; + int m; + const char *str; + TBL_PC* sd = NULL; + struct s_mapiterator* iter; - str = script_getstr(st,2); - m = map_mapname2mapid(str); - if (m < 0 || map[m].flag.pvp) - return 0; // nothing to do + str = script_getstr(st,2); + m = map_mapname2mapid(str); + if( m < 0 || map[m].flag.pvp ) + return 0; // nothing to do - map[m].flag.pvp = 1; - clif_map_property_mapall(m, MAPPROPERTY_FREEPVPZONE); + map[m].flag.pvp = 1; + clif_map_property_mapall(m, MAPPROPERTY_FREEPVPZONE); - if (battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris] - return 0; + if(battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris] + return 0; - iter = mapit_getallusers(); - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) { - if (sd->bl.m != m || sd->pvp_timer != INVALID_TIMER) - continue; // not applicable - - sd->pvp_timer = add_timer(gettick()+200,pc_calc_pvprank_timer,sd->bl.id,0); - sd->pvp_rank = 0; - sd->pvp_lastusers = 0; - sd->pvp_point = 5; - sd->pvp_won = 0; - sd->pvp_lost = 0; - } - mapit_free(iter); + iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + { + if( sd->bl.m != m || sd->pvp_timer != INVALID_TIMER ) + continue; // not applicable - return 0; + sd->pvp_timer = add_timer(gettick()+200,pc_calc_pvprank_timer,sd->bl.id,0); + sd->pvp_rank = 0; + sd->pvp_lastusers = 0; + sd->pvp_point = 5; + sd->pvp_won = 0; + sd->pvp_lost = 0; + } + mapit_free(iter); + + return 0; } static int buildin_pvpoff_sub(struct block_list *bl,va_list ap) { - TBL_PC *sd = (TBL_PC *)bl; - clif_pvpset(sd, 0, 0, 2); - if (sd->pvp_timer != INVALID_TIMER) { - delete_timer(sd->pvp_timer, pc_calc_pvprank_timer); - sd->pvp_timer = INVALID_TIMER; - } - return 0; + TBL_PC* sd = (TBL_PC*)bl; + clif_pvpset(sd, 0, 0, 2); + if (sd->pvp_timer != INVALID_TIMER) { + delete_timer(sd->pvp_timer, pc_calc_pvprank_timer); + sd->pvp_timer = INVALID_TIMER; + } + return 0; } BUILDIN_FUNC(pvpoff) { - int m; - const char *str; + int m; + const char *str; - str=script_getstr(st,2); - m = map_mapname2mapid(str); - if (m < 0 || !map[m].flag.pvp) - return 0; //fixed Lupus + str=script_getstr(st,2); + m = map_mapname2mapid(str); + if(m < 0 || !map[m].flag.pvp) + return 0; //fixed Lupus - map[m].flag.pvp = 0; - clif_map_property_mapall(m, MAPPROPERTY_NOTHING); + map[m].flag.pvp = 0; + clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - if (battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris] - return 0; + if(battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris] + return 0; - map_foreachinmap(buildin_pvpoff_sub, m, BL_PC); - return 0; + map_foreachinmap(buildin_pvpoff_sub, m, BL_PC); + return 0; } BUILDIN_FUNC(gvgon) { - int m; - const char *str; + int m; + const char *str; - str=script_getstr(st,2); - m = map_mapname2mapid(str); - if (m >= 0 && !map[m].flag.gvg) { - map[m].flag.gvg = 1; - clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); - } + str=script_getstr(st,2); + m = map_mapname2mapid(str); + if(m >= 0 && !map[m].flag.gvg) { + map[m].flag.gvg = 1; + clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); + } - return 0; + return 0; } BUILDIN_FUNC(gvgoff) { - int m; - const char *str; + int m; + const char *str; - str=script_getstr(st,2); - m = map_mapname2mapid(str); - if (m >= 0 && map[m].flag.gvg) { - map[m].flag.gvg = 0; - clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - } + str=script_getstr(st,2); + m = map_mapname2mapid(str); + if(m >= 0 && map[m].flag.gvg) { + map[m].flag.gvg = 0; + clif_map_property_mapall(m, MAPPROPERTY_NOTHING); + } - return 0; + return 0; } /*========================================== - * Shows an emoticon on top of the player/npc - * emotion emotion#, <target: 0 - NPC, 1 - PC>, <NPC/PC name> + * Shows an emoticon on top of the player/npc + * emotion emotion#, <target: 0 - NPC, 1 - PC>, <NPC/PC name> *------------------------------------------*/ //Optional second parameter added by [Skotlex] BUILDIN_FUNC(emotion) { - int type; - int player=0; - - type=script_getnum(st,2); - if (type < 0 || type > 100) - return 0; - - if (script_hasdata(st,3)) - player=script_getnum(st,3); - - if (player) { - TBL_PC *sd = NULL; - if (script_hasdata(st,4)) - sd = map_nick2sd(script_getstr(st,4)); - else - sd = script_rid2sd(st); - if (sd) - clif_emotion(&sd->bl,type); - } else if (script_hasdata(st,4)) { - TBL_NPC *nd = npc_name2id(script_getstr(st,4)); - if (nd) - clif_emotion(&nd->bl,type); - } else - clif_emotion(map_id2bl(st->oid),type); - return 0; -} - -static int buildin_maprespawnguildid_sub_pc(struct map_session_data *sd, va_list ap) -{ - int m=va_arg(ap,int); - int g_id=va_arg(ap,int); - int flag=va_arg(ap,int); - - if (!sd || sd->bl.m != m) - return 0; - if ( - (sd->status.guild_id == g_id && flag&1) || //Warp out owners - (sd->status.guild_id != g_id && flag&2) || //Warp out outsiders - (sd->status.guild_id == 0) // Warp out players not in guild [Valaris] - ) - pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - return 1; + int type; + int player=0; + + type=script_getnum(st,2); + if(type < 0 || type > 100) + return 0; + + if( script_hasdata(st,3) ) + player=script_getnum(st,3); + + if (player) { + TBL_PC *sd = NULL; + if( script_hasdata(st,4) ) + sd = map_nick2sd(script_getstr(st,4)); + else + sd = script_rid2sd(st); + if (sd) + clif_emotion(&sd->bl,type); + } else + if( script_hasdata(st,4) ) + { + TBL_NPC *nd = npc_name2id(script_getstr(st,4)); + if(nd) + clif_emotion(&nd->bl,type); + } + else + clif_emotion(map_id2bl(st->oid),type); + return 0; +} + +static int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list ap) +{ + int m=va_arg(ap,int); + int g_id=va_arg(ap,int); + int flag=va_arg(ap,int); + + if(!sd || sd->bl.m != m) + return 0; + if( + (sd->status.guild_id == g_id && flag&1) || //Warp out owners + (sd->status.guild_id != g_id && flag&2) || //Warp out outsiders + (sd->status.guild_id == 0) // Warp out players not in guild [Valaris] + ) + pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + return 1; } static int buildin_maprespawnguildid_sub_mob(struct block_list *bl,va_list ap) { - struct mob_data *md=(struct mob_data *)bl; + struct mob_data *md=(struct mob_data *)bl; - if (!md->guardian_data && md->class_ != MOBID_EMPERIUM) - status_kill(bl); + if(!md->guardian_data && md->class_ != MOBID_EMPERIUM) + status_kill(bl); - return 0; + return 0; } BUILDIN_FUNC(maprespawnguildid) { - const char *mapname=script_getstr(st,2); - int g_id=script_getnum(st,3); - int flag=script_getnum(st,4); + const char *mapname=script_getstr(st,2); + int g_id=script_getnum(st,3); + int flag=script_getnum(st,4); - int m=map_mapname2mapid(mapname); + int m=map_mapname2mapid(mapname); - if (m == -1) - return 0; + if(m == -1) + return 0; - //Catch ALL players (in case some are 'between maps' on execution time) - map_foreachpc(buildin_maprespawnguildid_sub_pc,m,g_id,flag); - if (flag&4) //Remove script mobs. - map_foreachinmap(buildin_maprespawnguildid_sub_mob,m,BL_MOB); - return 0; + //Catch ALL players (in case some are 'between maps' on execution time) + map_foreachpc(buildin_maprespawnguildid_sub_pc,m,g_id,flag); + if (flag&4) //Remove script mobs. + map_foreachinmap(buildin_maprespawnguildid_sub_mob,m,BL_MOB); + return 0; } BUILDIN_FUNC(agitstart) { - if (agit_flag==1) return 0; // Agit already Start. - agit_flag=1; - guild_agit_start(); - return 0; + if(agit_flag==1) return 0; // Agit already Start. + agit_flag=1; + guild_agit_start(); + return 0; } BUILDIN_FUNC(agitend) { - if (agit_flag==0) return 0; // Agit already End. - agit_flag=0; - guild_agit_end(); - return 0; + if(agit_flag==0) return 0; // Agit already End. + agit_flag=0; + guild_agit_end(); + return 0; } BUILDIN_FUNC(agitstart2) { - if (agit2_flag==1) return 0; // Agit2 already Start. - agit2_flag=1; - guild_agit2_start(); - return 0; + if(agit2_flag==1) return 0; // Agit2 already Start. + agit2_flag=1; + guild_agit2_start(); + return 0; } BUILDIN_FUNC(agitend2) { - if (agit2_flag==0) return 0; // Agit2 already End. - agit2_flag=0; - guild_agit2_end(); - return 0; + if(agit2_flag==0) return 0; // Agit2 already End. + agit2_flag=0; + guild_agit2_end(); + return 0; } /*========================================== - * Returns whether woe is on or off. // choice script + * Returns whether woe is on or off. // choice script *------------------------------------------*/ BUILDIN_FUNC(agitcheck) { - script_pushint(st,agit_flag); - return 0; + script_pushint(st,agit_flag); + return 0; } /*========================================== - * Returns whether woese is on or off. // choice script + * Returns whether woese is on or off. // choice script *------------------------------------------*/ BUILDIN_FUNC(agitcheck2) { - script_pushint(st,agit2_flag); - return 0; + script_pushint(st,agit2_flag); + return 0; } /// Sets the guild_id of this npc. @@ -11186,219 +11127,210 @@ BUILDIN_FUNC(agitcheck2) /// flagemblem <guild_id>; BUILDIN_FUNC(flagemblem) { - TBL_NPC *nd; - int g_id = script_getnum(st,2); - - if (g_id < 0) return 0; - - nd = (TBL_NPC *)map_id2nd(st->oid); - if (nd == NULL) { - ShowError("script:flagemblem: npc %d not found\n", st->oid); - } else if (nd->subtype != SCRIPT) { - ShowError("script:flagemblem: unexpected subtype %d for npc %d '%s'\n", nd->subtype, st->oid, nd->exname); - } else { - bool changed = (nd->u.scr.guild_id != g_id)?true:false; - nd->u.scr.guild_id = g_id; - clif_guild_emblem_area(&nd->bl); - /* guild flag caching */ - if (g_id) /* adding a id */ - guild_flag_add(nd); - else if (changed) /* removing a flag */ - guild_flag_remove(nd); - } - return 0; + TBL_NPC* nd; + int g_id = script_getnum(st,2); + + if(g_id < 0) return 0; + + nd = (TBL_NPC*)map_id2nd(st->oid); + if( nd == NULL ) { + ShowError("script:flagemblem: npc %d not found\n", st->oid); + } else if( nd->subtype != SCRIPT ) { + ShowError("script:flagemblem: unexpected subtype %d for npc %d '%s'\n", nd->subtype, st->oid, nd->exname); + } else { + bool changed = ( nd->u.scr.guild_id != g_id )?true:false; + nd->u.scr.guild_id = g_id; + clif_guild_emblem_area(&nd->bl); + /* guild flag caching */ + if( g_id ) /* adding a id */ + guild_flag_add(nd); + else if( changed ) /* removing a flag */ + guild_flag_remove(nd); + } + return 0; } BUILDIN_FUNC(getcastlename) { - const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL); - struct guild_castle *gc = guild_mapname2gc(mapname); - const char *name = (gc) ? gc->castle_name : ""; - script_pushstrcopy(st,name); - return 0; + const char* mapname = mapindex_getmapname(script_getstr(st,2),NULL); + struct guild_castle* gc = guild_mapname2gc(mapname); + const char* name = (gc) ? gc->castle_name : ""; + script_pushstrcopy(st,name); + return 0; } BUILDIN_FUNC(getcastledata) { - const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL); - int index = script_getnum(st,3); - struct guild_castle *gc = guild_mapname2gc(mapname); - - if (gc == NULL) { - script_pushint(st,0); - ShowWarning("buildin_setcastledata: guild castle for map '%s' not found\n", mapname); - return 1; - } - - switch (index) { - case 1: - script_pushint(st,gc->guild_id); - break; - case 2: - script_pushint(st,gc->economy); - break; - case 3: - script_pushint(st,gc->defense); - break; - case 4: - script_pushint(st,gc->triggerE); - break; - case 5: - script_pushint(st,gc->triggerD); - break; - case 6: - script_pushint(st,gc->nextTime); - break; - case 7: - script_pushint(st,gc->payTime); - break; - case 8: - script_pushint(st,gc->createTime); - break; - case 9: - script_pushint(st,gc->visibleC); - break; - default: - if (index > 9 && index <= 9+MAX_GUARDIANS) { - script_pushint(st,gc->guardian[index-10].visible); - break; - } - script_pushint(st,0); - ShowWarning("buildin_setcastledata: index = '%d' is out of allowed range\n", index); - return 1; - } - return 0; + const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL); + int index = script_getnum(st,3); + struct guild_castle *gc = guild_mapname2gc(mapname); + + if (gc == NULL) { + script_pushint(st,0); + ShowWarning("buildin_setcastledata: guild castle for map '%s' not found\n", mapname); + return 1; + } + + switch (index) { + case 1: + script_pushint(st,gc->guild_id); break; + case 2: + script_pushint(st,gc->economy); break; + case 3: + script_pushint(st,gc->defense); break; + case 4: + script_pushint(st,gc->triggerE); break; + case 5: + script_pushint(st,gc->triggerD); break; + case 6: + script_pushint(st,gc->nextTime); break; + case 7: + script_pushint(st,gc->payTime); break; + case 8: + script_pushint(st,gc->createTime); break; + case 9: + script_pushint(st,gc->visibleC); break; + default: + if (index > 9 && index <= 9+MAX_GUARDIANS) { + script_pushint(st,gc->guardian[index-10].visible); + break; + } + script_pushint(st,0); + ShowWarning("buildin_setcastledata: index = '%d' is out of allowed range\n", index); + return 1; + } + return 0; } BUILDIN_FUNC(setcastledata) { - const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL); - int index = script_getnum(st,3); - int value = script_getnum(st,4); - struct guild_castle *gc = guild_mapname2gc(mapname); + const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL); + int index = script_getnum(st,3); + int value = script_getnum(st,4); + struct guild_castle *gc = guild_mapname2gc(mapname); - if (gc == NULL) { - ShowWarning("buildin_setcastledata: guild castle for map '%s' not found\n", mapname); - return 1; - } + if (gc == NULL) { + ShowWarning("buildin_setcastledata: guild castle for map '%s' not found\n", mapname); + return 1; + } - if (index <= 0 || index > 9+MAX_GUARDIANS) { - ShowWarning("buildin_setcastledata: index = '%d' is out of allowed range\n", index); - return 1; - } + if (index <= 0 || index > 9+MAX_GUARDIANS) { + ShowWarning("buildin_setcastledata: index = '%d' is out of allowed range\n", index); + return 1; + } - guild_castledatasave(gc->castle_id, index, value); - return 0; + guild_castledatasave(gc->castle_id, index, value); + return 0; } /* ===================================================================== * ---------------------------------------------------------------------*/ BUILDIN_FUNC(requestguildinfo) { - int guild_id=script_getnum(st,2); - const char *event=NULL; + int guild_id=script_getnum(st,2); + const char *event=NULL; - if (script_hasdata(st,3)) { - event=script_getstr(st,3); - check_event(st, event); - } + if( script_hasdata(st,3) ){ + event=script_getstr(st,3); + check_event(st, event); + } - if (guild_id>0) - guild_npc_request_info(guild_id,event); - return 0; + if(guild_id>0) + guild_npc_request_info(guild_id,event); + return 0; } /// Returns the number of cards that have been compounded onto the specified equipped item. /// getequipcardcnt(<equipment slot>); BUILDIN_FUNC(getequipcardcnt) { - int i=-1,j,num; - TBL_PC *sd; - int count; + int i=-1,j,num; + TBL_PC *sd; + int count; - num=script_getnum(st,2); - sd=script_rid2sd(st); - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); + num=script_getnum(st,2); + sd=script_rid2sd(st); + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); - if (i < 0 || !sd->inventory_data[i]) { - script_pushint(st,0); - return 0; - } + if (i < 0 || !sd->inventory_data[i]) { + script_pushint(st,0); + return 0; + } - if (itemdb_isspecial(sd->status.inventory[i].card[0])) { - script_pushint(st,0); - return 0; - } + if(itemdb_isspecial(sd->status.inventory[i].card[0])) + { + script_pushint(st,0); + return 0; + } - count = 0; - for (j = 0; j < sd->inventory_data[i]->slot; j++) - if (sd->status.inventory[i].card[j] && itemdb_type(sd->status.inventory[i].card[j]) == IT_CARD) - count++; + count = 0; + for( j = 0; j < sd->inventory_data[i]->slot; j++ ) + if( sd->status.inventory[i].card[j] && itemdb_type(sd->status.inventory[i].card[j]) == IT_CARD ) + count++; - script_pushint(st,count); - return 0; + script_pushint(st,count); + return 0; } /// Removes all cards from the item found in the specified equipment slot of the invoking character, /// and give them to the character. If any cards were removed in this manner, it will also show a success effect. /// successremovecards <slot>; -BUILDIN_FUNC(successremovecards) -{ - int i=-1,j,c,cardflag=0; - - TBL_PC *sd = script_rid2sd(st); - int num = script_getnum(st,2); - - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); - - if (i < 0 || !sd->inventory_data[i]) { - return 0; - } - - if (itemdb_isspecial(sd->status.inventory[i].card[0])) - return 0; - - for (c = sd->inventory_data[i]->slot - 1; c >= 0; --c) { - if (sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD) { // extract this card from the item - int flag; - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - cardflag = 1; - item_tmp.nameid = sd->status.inventory[i].card[c]; - item_tmp.identify = 1; - - if ((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) { // get back the cart in inventory - clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - } - - if (cardflag == 1) { //if card was remove remplace item with no card - int flag; - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - - item_tmp.nameid = sd->status.inventory[i].nameid; - item_tmp.identify = 1; - item_tmp.refine = sd->status.inventory[i].refine; - item_tmp.attribute = sd->status.inventory[i].attribute; - item_tmp.expire_time = sd->status.inventory[i].expire_time; - - for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) - item_tmp.card[j]=sd->status.inventory[i].card[j]; - - pc_delitem(sd,i,1,0,3,LOG_TYPE_SCRIPT); - if ((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) { //chk if can be spawn in inventory otherwise put on floor - clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - - clif_misceffect(&sd->bl,3); - } - return 0; +BUILDIN_FUNC(successremovecards) { + int i=-1,j,c,cardflag=0; + + TBL_PC* sd = script_rid2sd(st); + int num = script_getnum(st,2); + + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); + + if (i < 0 || !sd->inventory_data[i]) { + return 0; + } + + if(itemdb_isspecial(sd->status.inventory[i].card[0])) + return 0; + + for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) { + if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) {// extract this card from the item + int flag; + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + cardflag = 1; + item_tmp.nameid = sd->status.inventory[i].card[c]; + item_tmp.identify = 1; + + if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ // get back the cart in inventory + clif_additem(sd,0,0,flag); + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + } + + if(cardflag == 1) {//if card was remove remplace item with no card + int flag; + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + + item_tmp.nameid = sd->status.inventory[i].nameid; + item_tmp.identify = 1; + item_tmp.refine = sd->status.inventory[i].refine; + item_tmp.attribute = sd->status.inventory[i].attribute; + item_tmp.expire_time = sd->status.inventory[i].expire_time; + + for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) + item_tmp.card[j]=sd->status.inventory[i].card[j]; + + pc_delitem(sd,i,1,0,3,LOG_TYPE_SCRIPT); + if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ //chk if can be spawn in inventory otherwise put on floor + clif_additem(sd,0,0,flag); + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + + clif_misceffect(&sd->bl,3); + } + return 0; } /// Removes all cards from the item found in the specified equipment slot of the invoking character. @@ -11407,225 +11339,227 @@ BUILDIN_FUNC(successremovecards) /// <type>=1 : will keep the item, but destroy the cards. /// <type>=2 : will keep the cards, but destroy the item. /// <type>=? : will just display the failure effect. -BUILDIN_FUNC(failedremovecards) -{ - int i=-1,j,c,cardflag=0; +BUILDIN_FUNC(failedremovecards) { + int i=-1,j,c,cardflag=0; - TBL_PC *sd = script_rid2sd(st); - int num = script_getnum(st,2); - int typefail = script_getnum(st,3); + TBL_PC* sd = script_rid2sd(st); + int num = script_getnum(st,2); + int typefail = script_getnum(st,3); - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); - if (i < 0 || !sd->inventory_data[i]) - return 0; + if (i < 0 || !sd->inventory_data[i]) + return 0; - if (itemdb_isspecial(sd->status.inventory[i].card[0])) - return 0; + if(itemdb_isspecial(sd->status.inventory[i].card[0])) + return 0; - for (c = sd->inventory_data[i]->slot - 1; c >= 0; --c) { - if (sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD) { - cardflag = 1; + for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) { + if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) { + cardflag = 1; - if (typefail == 2) { // add cards to inventory, clear - int flag; - struct item item_tmp; + if(typefail == 2) {// add cards to inventory, clear + int flag; + struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); + memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = sd->status.inventory[i].card[c]; - item_tmp.identify = 1; + item_tmp.nameid = sd->status.inventory[i].card[c]; + item_tmp.identify = 1; - if ((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) { - clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - } - } + if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ + clif_additem(sd,0,0,flag); + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + } + } - if (cardflag == 1) { - if (typefail == 0 || typefail == 2) { // destroy the item - pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); - } - if (typefail == 1) { // destroy the card - int flag; - struct item item_tmp; + if(cardflag == 1) { + if(typefail == 0 || typefail == 2){ // destroy the item + pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + } + if(typefail == 1){ // destroy the card + int flag; + struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); + memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = sd->status.inventory[i].nameid; - item_tmp.identify = 1; - item_tmp.refine = sd->status.inventory[i].refine; - item_tmp.attribute = sd->status.inventory[i].attribute; - item_tmp.expire_time = sd->status.inventory[i].expire_time; + item_tmp.nameid = sd->status.inventory[i].nameid; + item_tmp.identify = 1; + item_tmp.refine = sd->status.inventory[i].refine; + item_tmp.attribute = sd->status.inventory[i].attribute; + item_tmp.expire_time = sd->status.inventory[i].expire_time; - for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) - item_tmp.card[j]=sd->status.inventory[i].card[j]; + for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) + item_tmp.card[j]=sd->status.inventory[i].card[j]; - pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); - if ((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) { - clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - clif_misceffect(&sd->bl,2); - } + if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ + clif_additem(sd,0,0,flag); + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + clif_misceffect(&sd->bl,2); + } - return 0; + return 0; } /* ================================================================ * mapwarp "<from map>","<to map>",<x>,<y>,<type>,<ID for Type>; - * type: 0=everyone, 1=guild, 2=party; [Reddozen] + * type: 0=everyone, 1=guild, 2=party; [Reddozen] * improved by [Lance] * ================================================================*/ -BUILDIN_FUNC(mapwarp) // Added by RoVeRT -{ - int x,y,m,check_val=0,check_ID=0,i=0; - struct guild *g = NULL; - struct party_data *p = NULL; - const char *str; - const char *mapname; - unsigned int index; - mapname=script_getstr(st,2); - str=script_getstr(st,3); - x=script_getnum(st,4); - y=script_getnum(st,5); - if (script_hasdata(st,7)) { - check_val=script_getnum(st,6); - check_ID=script_getnum(st,7); - } - - if ((m=map_mapname2mapid(mapname))< 0) - return 0; - - if (!(index=mapindex_name2id(str))) - return 0; - - switch (check_val) { - case 1: - g = guild_search(check_ID); - if (g) { - for (i=0; i < g->max_member; i++) { - if (g->member[i].sd && g->member[i].sd->bl.m==m) { - pc_setpos(g->member[i].sd,index,x,y,CLR_TELEPORT); - } - } - } - break; - case 2: - p = party_search(check_ID); - if (p) { - for (i=0; i<MAX_PARTY; i++) { - if (p->data[i].sd && p->data[i].sd->bl.m == m) { - pc_setpos(p->data[i].sd,index,x,y,CLR_TELEPORT); - } - } - } - break; - default: - map_foreachinmap(buildin_areawarp_sub,m,BL_PC,index,x,y,0,0); - break; - } - - return 0; -} - -static int buildin_mobcount_sub(struct block_list *bl,va_list ap) // Added by RoVeRT -{ - char *event=va_arg(ap,char *); - struct mob_data *md = ((struct mob_data *)bl); - if (md->status.hp > 0 && (!event || strcmp(event,md->npc_event) == 0)) - return 1; - return 0; -} - -BUILDIN_FUNC(mobcount) // Added by RoVeRT -{ - const char *mapname,*event; - int m; - mapname=script_getstr(st,2); - event=script_getstr(st,3); - - if (strcmp(event, "all") == 0) - event = NULL; - else - check_event(st, event); - - if (strcmp(mapname, "this") == 0) { - struct map_session_data *sd = script_rid2sd(st); - if (sd) - m = sd->bl.m; - else { - script_pushint(st,-1); - return 0; - } - } else if ((m = map_mapname2mapid(mapname)) < 0) { - script_pushint(st,-1); - return 0; - } - - if (map[m].flag.src4instance && map[m].instance_id == 0 && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0) { - script_pushint(st,-1); - return 0; - } - - script_pushint(st,map_foreachinmap(buildin_mobcount_sub, m, BL_MOB, event)); - - return 0; +BUILDIN_FUNC(mapwarp) // Added by RoVeRT +{ + int x,y,m,check_val=0,check_ID=0,i=0; + struct guild *g = NULL; + struct party_data *p = NULL; + const char *str; + const char *mapname; + unsigned int index; + mapname=script_getstr(st,2); + str=script_getstr(st,3); + x=script_getnum(st,4); + y=script_getnum(st,5); + if(script_hasdata(st,7)){ + check_val=script_getnum(st,6); + check_ID=script_getnum(st,7); + } + + if((m=map_mapname2mapid(mapname))< 0) + return 0; + + if(!(index=mapindex_name2id(str))) + return 0; + + switch(check_val){ + case 1: + g = guild_search(check_ID); + if (g){ + for( i=0; i < g->max_member; i++) + { + if(g->member[i].sd && g->member[i].sd->bl.m==m){ + pc_setpos(g->member[i].sd,index,x,y,CLR_TELEPORT); + } + } + } + break; + case 2: + p = party_search(check_ID); + if(p){ + for(i=0;i<MAX_PARTY; i++){ + if(p->data[i].sd && p->data[i].sd->bl.m == m){ + pc_setpos(p->data[i].sd,index,x,y,CLR_TELEPORT); + } + } + } + break; + default: + map_foreachinmap(buildin_areawarp_sub,m,BL_PC,index,x,y,0,0); + break; + } + + return 0; +} + +static int buildin_mobcount_sub(struct block_list *bl,va_list ap) // Added by RoVeRT +{ + char *event=va_arg(ap,char *); + struct mob_data *md = ((struct mob_data *)bl); + if( md->status.hp > 0 && (!event || strcmp(event,md->npc_event) == 0) ) + return 1; + return 0; +} + +BUILDIN_FUNC(mobcount) // Added by RoVeRT +{ + const char *mapname,*event; + int m; + mapname=script_getstr(st,2); + event=script_getstr(st,3); + + if( strcmp(event, "all") == 0 ) + event = NULL; + else + check_event(st, event); + + if( strcmp(mapname, "this") == 0 ) { + struct map_session_data *sd = script_rid2sd(st); + if( sd ) + m = sd->bl.m; + else { + script_pushint(st,-1); + return 0; + } + } + else if( (m = map_mapname2mapid(mapname)) < 0 ) { + script_pushint(st,-1); + return 0; + } + + if( map[m].flag.src4instance && map[m].instance_id == 0 && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) + { + script_pushint(st,-1); + return 0; + } + + script_pushint(st,map_foreachinmap(buildin_mobcount_sub, m, BL_MOB, event)); + + return 0; } BUILDIN_FUNC(marriage) { - const char *partner=script_getstr(st,2); - TBL_PC *sd=script_rid2sd(st); - TBL_PC *p_sd=map_nick2sd(partner); + const char *partner=script_getstr(st,2); + TBL_PC *sd=script_rid2sd(st); + TBL_PC *p_sd=map_nick2sd(partner); - if (sd==NULL || p_sd==NULL || pc_marriage(sd,p_sd) < 0) { - script_pushint(st,0); - return 0; - } - script_pushint(st,1); - return 0; + if(sd==NULL || p_sd==NULL || pc_marriage(sd,p_sd) < 0){ + script_pushint(st,0); + return 0; + } + script_pushint(st,1); + return 0; } BUILDIN_FUNC(wedding_effect) { - TBL_PC *sd=script_rid2sd(st); - struct block_list *bl; + TBL_PC *sd=script_rid2sd(st); + struct block_list *bl; - if (sd==NULL) { - bl=map_id2bl(st->oid); - } else - bl=&sd->bl; - clif_wedding_effect(bl); - return 0; + if(sd==NULL) { + bl=map_id2bl(st->oid); + } else + bl=&sd->bl; + clif_wedding_effect(bl); + return 0; } BUILDIN_FUNC(divorce) { - TBL_PC *sd=script_rid2sd(st); - if (sd==NULL || pc_divorce(sd) < 0) { - script_pushint(st,0); - return 0; - } - script_pushint(st,1); - return 0; + TBL_PC *sd=script_rid2sd(st); + if(sd==NULL || pc_divorce(sd) < 0){ + script_pushint(st,0); + return 0; + } + script_pushint(st,1); + return 0; } BUILDIN_FUNC(ispartneron) { - TBL_PC *sd=script_rid2sd(st); + TBL_PC *sd=script_rid2sd(st); - if (sd==NULL || !pc_ismarried(sd) || - map_charid2sd(sd->status.partner_id) == NULL) { - script_pushint(st,0); - return 0; - } + if(sd==NULL || !pc_ismarried(sd) || + map_charid2sd(sd->status.partner_id) == NULL) { + script_pushint(st,0); + return 0; + } - script_pushint(st,1); - return 0; + script_pushint(st,1); + return 0; } BUILDIN_FUNC(getpartnerid) @@ -11678,29 +11612,29 @@ BUILDIN_FUNC(getfatherid) BUILDIN_FUNC(warppartner) { - int x,y; - unsigned short mapindex; - const char *str; - TBL_PC *sd=script_rid2sd(st); - TBL_PC *p_sd=NULL; + int x,y; + unsigned short mapindex; + const char *str; + TBL_PC *sd=script_rid2sd(st); + TBL_PC *p_sd=NULL; - if (sd==NULL || !pc_ismarried(sd) || - (p_sd=map_charid2sd(sd->status.partner_id)) == NULL) { - script_pushint(st,0); - return 0; - } + if(sd==NULL || !pc_ismarried(sd) || + (p_sd=map_charid2sd(sd->status.partner_id)) == NULL) { + script_pushint(st,0); + return 0; + } - str=script_getstr(st,2); - x=script_getnum(st,3); - y=script_getnum(st,4); + str=script_getstr(st,2); + x=script_getnum(st,3); + y=script_getnum(st,4); - mapindex = mapindex_name2id(str); - if (mapindex) { - pc_setpos(p_sd,mapindex,x,y,CLR_OUTSIGHT); - script_pushint(st,1); - } else - script_pushint(st,0); - return 0; + mapindex = mapindex_name2id(str); + if (mapindex) { + pc_setpos(p_sd,mapindex,x,y,CLR_OUTSIGHT); + script_pushint(st,1); + } else + script_pushint(st,0); + return 0; } /*================================================ @@ -11709,41 +11643,28 @@ BUILDIN_FUNC(warppartner) BUILDIN_FUNC(strmobinfo) { - int num=script_getnum(st,2); - int class_=script_getnum(st,3); + int num=script_getnum(st,2); + int class_=script_getnum(st,3); - if (!mobdb_checkid(class_)) { - script_pushint(st,0); - return 0; - } + if(!mobdb_checkid(class_)) + { + script_pushint(st,0); + return 0; + } - switch (num) { - case 1: - script_pushstrcopy(st,mob_db(class_)->name); - break; - case 2: - script_pushstrcopy(st,mob_db(class_)->jname); - break; - case 3: - script_pushint(st,mob_db(class_)->lv); - break; - case 4: - script_pushint(st,mob_db(class_)->status.max_hp); - break; - case 5: - script_pushint(st,mob_db(class_)->status.max_sp); - break; - case 6: - script_pushint(st,mob_db(class_)->base_exp); - break; - case 7: - script_pushint(st,mob_db(class_)->job_exp); - break; - default: - script_pushint(st,0); - break; - } - return 0; + switch (num) { + case 1: script_pushstrcopy(st,mob_db(class_)->name); break; + case 2: script_pushstrcopy(st,mob_db(class_)->jname); break; + case 3: script_pushint(st,mob_db(class_)->lv); break; + case 4: script_pushint(st,mob_db(class_)->status.max_hp); break; + case 5: script_pushint(st,mob_db(class_)->status.max_sp); break; + case 6: script_pushint(st,mob_db(class_)->base_exp); break; + case 7: script_pushint(st,mob_db(class_)->job_exp); break; + default: + script_pushint(st,0); + break; + } + return 0; } /*========================================== @@ -11752,73 +11673,73 @@ BUILDIN_FUNC(strmobinfo) *------------------------------------------*/ BUILDIN_FUNC(guardian) { - int class_=0,x=0,y=0,guardian=0; - const char *str,*map,*evt=""; - struct script_data *data; - bool has_index = false; - - map =script_getstr(st,2); - x =script_getnum(st,3); - y =script_getnum(st,4); - str =script_getstr(st,5); - class_=script_getnum(st,6); - - if (script_hasdata(st,8)) { - // "<event label>",<guardian index> - evt=script_getstr(st,7); - guardian=script_getnum(st,8); - has_index = true; - } else if (script_hasdata(st,7)) { - data=script_getdata(st,7); - get_val(st,data); - if (data_isstring(data)) { - // "<event label>" - evt=script_getstr(st,7); - } else if (data_isint(data)) { - // <guardian index> - guardian=script_getnum(st,7); - has_index = true; - } else { - ShowError("script:guardian: invalid data type for argument #6 (from 1)\n"); - script_reportdata(data); - return 1; - } - } - - check_event(st, evt); - script_pushint(st, mob_spawn_guardian(map,x,y,str,class_,evt,guardian,has_index)); - - return 0; + int class_=0,x=0,y=0,guardian=0; + const char *str,*map,*evt=""; + struct script_data *data; + bool has_index = false; + + map =script_getstr(st,2); + x =script_getnum(st,3); + y =script_getnum(st,4); + str =script_getstr(st,5); + class_=script_getnum(st,6); + + if( script_hasdata(st,8) ) + {// "<event label>",<guardian index> + evt=script_getstr(st,7); + guardian=script_getnum(st,8); + has_index = true; + } else if( script_hasdata(st,7) ){ + data=script_getdata(st,7); + get_val(st,data); + if( data_isstring(data) ) + {// "<event label>" + evt=script_getstr(st,7); + } else if( data_isint(data) ) + {// <guardian index> + guardian=script_getnum(st,7); + has_index = true; + } else { + ShowError("script:guardian: invalid data type for argument #6 (from 1)\n"); + script_reportdata(data); + return 1; + } + } + + check_event(st, evt); + script_pushint(st, mob_spawn_guardian(map,x,y,str,class_,evt,guardian,has_index)); + + return 0; } /*========================================== * Invisible Walls [Zephyrus] *------------------------------------------*/ BUILDIN_FUNC(setwall) { - const char *map, *name; - int x, y, m, size, dir; - bool shootable; + const char *map, *name; + int x, y, m, size, dir; + bool shootable; - map = script_getstr(st,2); - x = script_getnum(st,3); - y = script_getnum(st,4); - size = script_getnum(st,5); - dir = script_getnum(st,6); - shootable = script_getnum(st,7); - name = script_getstr(st,8); + map = script_getstr(st,2); + x = script_getnum(st,3); + y = script_getnum(st,4); + size = script_getnum(st,5); + dir = script_getnum(st,6); + shootable = script_getnum(st,7); + name = script_getstr(st,8); - if ((m = map_mapname2mapid(map)) < 0) - return 0; // Invalid Map + if( (m = map_mapname2mapid(map)) < 0 ) + return 0; // Invalid Map - map_iwall_set(m, x, y, size, dir, shootable, name); - return 0; + map_iwall_set(m, x, y, size, dir, shootable, name); + return 0; } BUILDIN_FUNC(delwall) { - const char *name = script_getstr(st,2); - map_iwall_remove(name); + const char *name = script_getstr(st,2); + map_iwall_remove(name); - return 0; + return 0; } /// Retrieves various information about the specified guardian. @@ -11830,32 +11751,36 @@ BUILDIN_FUNC(delwall) /// BUILDIN_FUNC(guardianinfo) { - const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL); - int id = script_getnum(st,3); - int type = script_getnum(st,4); - - struct guild_castle *gc = guild_mapname2gc(mapname); - struct mob_data *gd; - - if (gc == NULL || id < 0 || id >= MAX_GUARDIANS) { - script_pushint(st,-1); - return 0; - } - - if (type == 0) - script_pushint(st, gc->guardian[id].visible); - else if (!gc->guardian[id].visible) - script_pushint(st,-1); - else if ((gd = map_id2md(gc->guardian[id].id)) == NULL) - script_pushint(st,-1); - else { - if (type == 1) script_pushint(st,gd->status.max_hp); - else if (type == 2) script_pushint(st,gd->status.hp); - else - script_pushint(st,-1); - } - - return 0; + const char* mapname = mapindex_getmapname(script_getstr(st,2),NULL); + int id = script_getnum(st,3); + int type = script_getnum(st,4); + + struct guild_castle* gc = guild_mapname2gc(mapname); + struct mob_data* gd; + + if( gc == NULL || id < 0 || id >= MAX_GUARDIANS ) + { + script_pushint(st,-1); + return 0; + } + + if( type == 0 ) + script_pushint(st, gc->guardian[id].visible); + else + if( !gc->guardian[id].visible ) + script_pushint(st,-1); + else + if( (gd = map_id2md(gc->guardian[id].id)) == NULL ) + script_pushint(st,-1); + else + { + if ( type == 1 ) script_pushint(st,gd->status.max_hp); + else if( type == 2 ) script_pushint(st,gd->status.hp); + else + script_pushint(st,-1); + } + + return 0; } /*========================================== @@ -11863,50 +11788,51 @@ BUILDIN_FUNC(guardianinfo) *------------------------------------------*/ BUILDIN_FUNC(getitemname) { - int item_id=0; - struct item_data *i_data; - char *item_name; - struct script_data *data; - - data=script_getdata(st,2); - get_val(st,data); - - if (data_isstring(data)) { - const char *name=conv_str(st,data); - struct item_data *item_data = itemdb_searchname(name); - if (item_data) - item_id=item_data->nameid; - } else - item_id=conv_num(st,data); - - i_data = itemdb_exists(item_id); - if (i_data == NULL) { - script_pushconststr(st,"null"); - return 0; - } - item_name=(char *)aMalloc(ITEM_NAME_LENGTH*sizeof(char)); - - memcpy(item_name, i_data->jname, ITEM_NAME_LENGTH); - script_pushstr(st,item_name); - return 0; + int item_id=0; + struct item_data *i_data; + char *item_name; + struct script_data *data; + + data=script_getdata(st,2); + get_val(st,data); + + if( data_isstring(data) ){ + const char *name=conv_str(st,data); + struct item_data *item_data = itemdb_searchname(name); + if( item_data ) + item_id=item_data->nameid; + }else + item_id=conv_num(st,data); + + i_data = itemdb_exists(item_id); + if (i_data == NULL) + { + script_pushconststr(st,"null"); + return 0; + } + item_name=(char *)aMalloc(ITEM_NAME_LENGTH*sizeof(char)); + + memcpy(item_name, i_data->jname, ITEM_NAME_LENGTH); + script_pushstr(st,item_name); + return 0; } /*========================================== * Returns number of slots an item has. [Skotlex] *------------------------------------------*/ BUILDIN_FUNC(getitemslots) { - int item_id; - struct item_data *i_data; + int item_id; + struct item_data *i_data; - item_id=script_getnum(st,2); + item_id=script_getnum(st,2); - i_data = itemdb_exists(item_id); + i_data = itemdb_exists(item_id); - if (i_data) - script_pushint(st,i_data->slot); - else - script_pushint(st,-1); - return 0; + if (i_data) + script_pushint(st,i_data->slot); + else + script_pushint(st,-1); + return 0; } // TODO: add matk here if needed/once we get rid of RENEWAL @@ -11914,114 +11840,114 @@ BUILDIN_FUNC(getitemslots) /*========================================== * Returns some values of an item [Lupus] * Price, Weight, etc... - getiteminfo(itemID,n), where n - 0 value_buy; - 1 value_sell; - 2 type; - 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc.. - if = 0, then monsters don't drop it at all (rare or a quest item) - if = -1, then this item is sold in NPC shops only - 4 sex; - 5 equip; - 6 weight; - 7 atk; - 8 def; - 9 range; - 10 slot; - 11 look; - 12 elv; - 13 wlv; - 14 view id + getiteminfo(itemID,n), where n + 0 value_buy; + 1 value_sell; + 2 type; + 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc.. + if = 0, then monsters don't drop it at all (rare or a quest item) + if = -1, then this item is sold in NPC shops only + 4 sex; + 5 equip; + 6 weight; + 7 atk; + 8 def; + 9 range; + 10 slot; + 11 look; + 12 elv; + 13 wlv; + 14 view id *------------------------------------------*/ BUILDIN_FUNC(getiteminfo) { - int item_id,n; - int *item_arr; - struct item_data *i_data; + int item_id,n; + int *item_arr; + struct item_data *i_data; - item_id = script_getnum(st,2); - n = script_getnum(st,3); - i_data = itemdb_exists(item_id); + item_id = script_getnum(st,2); + n = script_getnum(st,3); + i_data = itemdb_exists(item_id); - if (i_data && n>=0 && n<=14) { - item_arr = (int *)&i_data->value_buy; - script_pushint(st,item_arr[n]); - } else - script_pushint(st,-1); - return 0; + if (i_data && n>=0 && n<=14) { + item_arr = (int*)&i_data->value_buy; + script_pushint(st,item_arr[n]); + } else + script_pushint(st,-1); + return 0; } /*========================================== * Set some values of an item [Lupus] * Price, Weight, etc... - setiteminfo(itemID,n,Value), where n - 0 value_buy; - 1 value_sell; - 2 type; - 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc.. - if = 0, then monsters don't drop it at all (rare or a quest item) - if = -1, then this item is sold in NPC shops only - 4 sex; - 5 equip; - 6 weight; - 7 atk; - 8 def; - 9 range; - 10 slot; - 11 look; - 12 elv; - 13 wlv; - 14 view id + setiteminfo(itemID,n,Value), where n + 0 value_buy; + 1 value_sell; + 2 type; + 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc.. + if = 0, then monsters don't drop it at all (rare or a quest item) + if = -1, then this item is sold in NPC shops only + 4 sex; + 5 equip; + 6 weight; + 7 atk; + 8 def; + 9 range; + 10 slot; + 11 look; + 12 elv; + 13 wlv; + 14 view id * Returns Value or -1 if the wrong field's been set *------------------------------------------*/ BUILDIN_FUNC(setiteminfo) { - int item_id,n,value; - int *item_arr; - struct item_data *i_data; - - item_id = script_getnum(st,2); - n = script_getnum(st,3); - value = script_getnum(st,4); - i_data = itemdb_exists(item_id); - - if (i_data && n>=0 && n<=14) { - item_arr = (int *)&i_data->value_buy; - item_arr[n] = value; - script_pushint(st,value); - } else - script_pushint(st,-1); - return 0; + int item_id,n,value; + int *item_arr; + struct item_data *i_data; + + item_id = script_getnum(st,2); + n = script_getnum(st,3); + value = script_getnum(st,4); + i_data = itemdb_exists(item_id); + + if (i_data && n>=0 && n<=14) { + item_arr = (int*)&i_data->value_buy; + item_arr[n] = value; + script_pushint(st,value); + } else + script_pushint(st,-1); + return 0; } /*========================================== * Returns value from equipped item slot n [Lupus] - getequipcardid(num,slot) - where - num = eqip position slot - slot = 0,1,2,3 (Card Slot N) - - This func returns CARD ID, 255,254,-255 (for card 0, if the item is produced) - it's useful when you want to check item cards or if it's signed - Useful for such quests as "Sign this refined item with players name" etc - Hat[0] +4 -> Player's Hat[0] +4 + getequipcardid(num,slot) + where + num = eqip position slot + slot = 0,1,2,3 (Card Slot N) + + This func returns CARD ID, 255,254,-255 (for card 0, if the item is produced) + it's useful when you want to check item cards or if it's signed + Useful for such quests as "Sign this refined item with players name" etc + Hat[0] +4 -> Player's Hat[0] +4 *------------------------------------------*/ BUILDIN_FUNC(getequipcardid) { - int i=-1,num,slot; - TBL_PC *sd; - - num=script_getnum(st,2); - slot=script_getnum(st,3); - sd=script_rid2sd(st); - if (num > 0 && num <= ARRAYLENGTH(equip)) - i=pc_checkequip(sd,equip[num-1]); - if (i >= 0 && slot>=0 && slot<4) - script_pushint(st,sd->status.inventory[i].card[slot]); - else - script_pushint(st,0); + int i=-1,num,slot; + TBL_PC *sd; - return 0; + num=script_getnum(st,2); + slot=script_getnum(st,3); + sd=script_rid2sd(st); + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); + if(i >= 0 && slot>=0 && slot<4) + script_pushint(st,sd->status.inventory[i].card[slot]); + else + script_pushint(st,0); + + return 0; } /*========================================== @@ -12029,36 +11955,36 @@ BUILDIN_FUNC(getequipcardid) *------------------------------------------*/ BUILDIN_FUNC(petskillbonus) { - struct pet_data *pd; + struct pet_data *pd; - TBL_PC *sd=script_rid2sd(st); + TBL_PC *sd=script_rid2sd(st); - if (sd==NULL || sd->pd==NULL) - return 0; + if(sd==NULL || sd->pd==NULL) + return 0; - pd=sd->pd; - if (pd->bonus) { - //Clear previous bonus - if (pd->bonus->timer != INVALID_TIMER) - delete_timer(pd->bonus->timer, pet_skill_bonus_timer); - } else //init - pd->bonus = (struct pet_bonus *) aMalloc(sizeof(struct pet_bonus)); + pd=sd->pd; + if (pd->bonus) + { //Clear previous bonus + if (pd->bonus->timer != INVALID_TIMER) + delete_timer(pd->bonus->timer, pet_skill_bonus_timer); + } else //init + pd->bonus = (struct pet_bonus *) aMalloc(sizeof(struct pet_bonus)); - pd->bonus->type=script_getnum(st,2); - pd->bonus->val=script_getnum(st,3); - pd->bonus->duration=script_getnum(st,4); - pd->bonus->delay=script_getnum(st,5); + pd->bonus->type=script_getnum(st,2); + pd->bonus->val=script_getnum(st,3); + pd->bonus->duration=script_getnum(st,4); + pd->bonus->delay=script_getnum(st,5); - if (pd->state.skillbonus == 1) - pd->state.skillbonus=0; // waiting state + if (pd->state.skillbonus == 1) + pd->state.skillbonus=0; // waiting state - // wait for timer to start - if (battle_config.pet_equip_required && pd->pet.equip == 0) - pd->bonus->timer = INVALID_TIMER; - else - pd->bonus->timer = add_timer(gettick()+pd->bonus->delay*1000, pet_skill_bonus_timer, sd->bl.id, 0); + // wait for timer to start + if (battle_config.pet_equip_required && pd->pet.equip == 0) + pd->bonus->timer = INVALID_TIMER; + else + pd->bonus->timer = add_timer(gettick()+pd->bonus->delay*1000, pet_skill_bonus_timer, sd->bl.id, 0); - return 0; + return 0; } /*========================================== @@ -12066,35 +11992,36 @@ BUILDIN_FUNC(petskillbonus) *------------------------------------------*/ BUILDIN_FUNC(petloot) { - int max; - struct pet_data *pd; - TBL_PC *sd=script_rid2sd(st); + int max; + struct pet_data *pd; + TBL_PC *sd=script_rid2sd(st); - if (sd==NULL || sd->pd==NULL) - return 0; + if(sd==NULL || sd->pd==NULL) + return 0; - max=script_getnum(st,2); + max=script_getnum(st,2); - if (max < 1) - max = 1; //Let'em loot at least 1 item. - else if (max > MAX_PETLOOT_SIZE) - max = MAX_PETLOOT_SIZE; + if(max < 1) + max = 1; //Let'em loot at least 1 item. + else if (max > MAX_PETLOOT_SIZE) + max = MAX_PETLOOT_SIZE; - pd = sd->pd; - if (pd->loot != NULL) { - //Release whatever was there already and reallocate memory - pet_lootitem_drop(pd, pd->msd); - aFree(pd->loot->item); - } else - pd->loot = (struct pet_loot *)aMalloc(sizeof(struct pet_loot)); + pd = sd->pd; + if (pd->loot != NULL) + { //Release whatever was there already and reallocate memory + pet_lootitem_drop(pd, pd->msd); + aFree(pd->loot->item); + } + else + pd->loot = (struct pet_loot *)aMalloc(sizeof(struct pet_loot)); - pd->loot->item = (struct item *)aCalloc(max,sizeof(struct item)); + pd->loot->item = (struct item *)aCalloc(max,sizeof(struct item)); - pd->loot->max=max; - pd->loot->count = 0; - pd->loot->weight = 0; + pd->loot->max=max; + pd->loot->count = 0; + pd->loot->weight = 0; - return 0; + return 0; } /*========================================== * Set arrays with info of all sd inventory : @@ -12105,59 +12032,60 @@ BUILDIN_FUNC(petloot) *------------------------------------------*/ BUILDIN_FUNC(getinventorylist) { - TBL_PC *sd=script_rid2sd(st); - char card_var[NAME_LENGTH]; - - int i,j=0,k; - 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,reference_uid(add_str("@inventorylist_id"), j),sd->status.inventory[i].nameid); - pc_setreg(sd,reference_uid(add_str("@inventorylist_amount"), j),sd->status.inventory[i].amount); - pc_setreg(sd,reference_uid(add_str("@inventorylist_equip"), j),sd->status.inventory[i].equip); - pc_setreg(sd,reference_uid(add_str("@inventorylist_refine"), j),sd->status.inventory[i].refine); - pc_setreg(sd,reference_uid(add_str("@inventorylist_identify"), j),sd->status.inventory[i].identify); - pc_setreg(sd,reference_uid(add_str("@inventorylist_attribute"), j),sd->status.inventory[i].attribute); - for (k = 0; k < MAX_SLOTS; k++) { - sprintf(card_var, "@inventorylist_card%d",k+1); - pc_setreg(sd,reference_uid(add_str(card_var), j),sd->status.inventory[i].card[k]); - } - pc_setreg(sd,reference_uid(add_str("@inventorylist_expire"), j),sd->status.inventory[i].expire_time); - j++; - } - } - pc_setreg(sd,add_str("@inventorylist_count"),j); - return 0; + TBL_PC *sd=script_rid2sd(st); + char card_var[NAME_LENGTH]; + + int i,j=0,k; + 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,reference_uid(add_str("@inventorylist_id"), j),sd->status.inventory[i].nameid); + pc_setreg(sd,reference_uid(add_str("@inventorylist_amount"), j),sd->status.inventory[i].amount); + pc_setreg(sd,reference_uid(add_str("@inventorylist_equip"), j),sd->status.inventory[i].equip); + pc_setreg(sd,reference_uid(add_str("@inventorylist_refine"), j),sd->status.inventory[i].refine); + pc_setreg(sd,reference_uid(add_str("@inventorylist_identify"), j),sd->status.inventory[i].identify); + pc_setreg(sd,reference_uid(add_str("@inventorylist_attribute"), j),sd->status.inventory[i].attribute); + for (k = 0; k < MAX_SLOTS; k++) + { + sprintf(card_var, "@inventorylist_card%d",k+1); + pc_setreg(sd,reference_uid(add_str(card_var), j),sd->status.inventory[i].card[k]); + } + pc_setreg(sd,reference_uid(add_str("@inventorylist_expire"), j),sd->status.inventory[i].expire_time); + j++; + } + } + pc_setreg(sd,add_str("@inventorylist_count"),j); + return 0; } BUILDIN_FUNC(getskilllist) { - TBL_PC *sd=script_rid2sd(st); - int i,j=0; - 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,reference_uid(add_str("@skilllist_id"), j),sd->status.skill[i].id); - pc_setreg(sd,reference_uid(add_str("@skilllist_lv"), j),sd->status.skill[i].lv); - pc_setreg(sd,reference_uid(add_str("@skilllist_flag"), j),sd->status.skill[i].flag); - j++; - } - } - pc_setreg(sd,add_str("@skilllist_count"),j); - return 0; + TBL_PC *sd=script_rid2sd(st); + int i,j=0; + 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,reference_uid(add_str("@skilllist_id"), j),sd->status.skill[i].id); + pc_setreg(sd,reference_uid(add_str("@skilllist_lv"), j),sd->status.skill[i].lv); + pc_setreg(sd,reference_uid(add_str("@skilllist_flag"), j),sd->status.skill[i].flag); + j++; + } + } + pc_setreg(sd,add_str("@skilllist_count"),j); + return 0; } BUILDIN_FUNC(clearitem) { - TBL_PC *sd=script_rid2sd(st); - int i; - if (sd==NULL) return 0; - for (i=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].amount) { - pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_SCRIPT); - } - } - return 0; + TBL_PC *sd=script_rid2sd(st); + int i; + if(sd==NULL) return 0; + for (i=0; i<MAX_INVENTORY; i++) { + if (sd->status.inventory[i].amount) { + pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_SCRIPT); + } + } + return 0; } /*========================================== @@ -12165,19 +12093,19 @@ BUILDIN_FUNC(clearitem) *------------------------------------------*/ BUILDIN_FUNC(disguise) { - int id; - TBL_PC *sd = script_rid2sd(st); - if (sd == NULL) return 0; + int id; + TBL_PC* sd = script_rid2sd(st); + if (sd == NULL) return 0; - id = script_getnum(st,2); + id = script_getnum(st,2); - if (mobdb_checkid(id) || npcdb_checkid(id)) { - pc_disguise(sd, id); - script_pushint(st,id); - } else - script_pushint(st,0); + if (mobdb_checkid(id) || npcdb_checkid(id)) { + pc_disguise(sd, id); + script_pushint(st,id); + } else + script_pushint(st,0); - return 0; + return 0; } /*========================================== @@ -12185,16 +12113,16 @@ BUILDIN_FUNC(disguise) *------------------------------------------*/ BUILDIN_FUNC(undisguise) { - TBL_PC *sd = script_rid2sd(st); - if (sd == NULL) return 0; + TBL_PC* sd = script_rid2sd(st); + if (sd == NULL) return 0; - if (sd->disguise) { - pc_disguise(sd, 0); - script_pushint(st,0); - } else { - script_pushint(st,1); - } - return 0; + if (sd->disguise) { + pc_disguise(sd, 0); + script_pushint(st,0); + } else { + script_pushint(st,1); + } + return 0; } /*========================================== @@ -12203,15 +12131,15 @@ BUILDIN_FUNC(undisguise) *------------------------------------------*/ BUILDIN_FUNC(classchange) { - int _class,type; - struct block_list *bl=map_id2bl(st->oid); + int _class,type; + struct block_list *bl=map_id2bl(st->oid); - if (bl==NULL) return 0; + if(bl==NULL) return 0; - _class=script_getnum(st,2); - type=script_getnum(st,3); - clif_class_change(bl,_class,type); - return 0; + _class=script_getnum(st,2); + type=script_getnum(st,3); + clif_class_change(bl,_class,type); + return 0; } /*========================================== @@ -12219,52 +12147,53 @@ BUILDIN_FUNC(classchange) *------------------------------------------*/ BUILDIN_FUNC(misceffect) { - int type; - - type=script_getnum(st,2); - if (st->oid && st->oid != fake_nd->bl.id) { - struct block_list *bl = map_id2bl(st->oid); - if (bl) - clif_specialeffect(bl,type,AREA); - } else { - TBL_PC *sd=script_rid2sd(st); - if (sd) - clif_specialeffect(&sd->bl,type,AREA); - } - return 0; + int type; + + type=script_getnum(st,2); + if(st->oid && st->oid != fake_nd->bl.id) { + struct block_list *bl = map_id2bl(st->oid); + if (bl) + clif_specialeffect(bl,type,AREA); + } else{ + TBL_PC *sd=script_rid2sd(st); + if(sd) + clif_specialeffect(&sd->bl,type,AREA); + } + return 0; } /*========================================== * Play a BGM on a single client [Rikter/Yommy] *------------------------------------------*/ BUILDIN_FUNC(playBGM) { - const char *name; - struct map_session_data *sd; + const char* name; + struct map_session_data* sd; - if ((sd = script_rid2sd(st)) != NULL) { - name = script_getstr(st,2); + if( ( sd = script_rid2sd(st) ) != NULL ) + { + name = script_getstr(st,2); - clif_playBGM(sd, name); - } + clif_playBGM(sd, name); + } - return 0; + return 0; } -static int playBGM_sub(struct block_list *bl,va_list ap) +static int playBGM_sub(struct block_list* bl,va_list ap) { - const char *name = va_arg(ap,const char *); + const char* name = va_arg(ap,const char*); - clif_playBGM(BL_CAST(BL_PC, bl), name); + clif_playBGM(BL_CAST(BL_PC, bl), name); - return 0; + return 0; } -static int playBGM_foreachpc_sub(struct map_session_data *sd, va_list args) +static int playBGM_foreachpc_sub(struct map_session_data* sd, va_list args) { - const char *name = va_arg(args, const char *); + const char* name = va_arg(args, const char*); - clif_playBGM(sd, name); - return 0; + clif_playBGM(sd, name); + return 0; } /*========================================== @@ -12272,30 +12201,32 @@ static int playBGM_foreachpc_sub(struct map_session_data *sd, va_list args) *------------------------------------------*/ BUILDIN_FUNC(playBGMall) { - const char *name; + const char* name; - name = script_getstr(st,2); + name = script_getstr(st,2); - if (script_hasdata(st,7)) { - // specified part of map - const char *map = script_getstr(st,3); - int x0 = script_getnum(st,4); - int y0 = script_getnum(st,5); - int x1 = script_getnum(st,6); - int y1 = script_getnum(st,7); + if( script_hasdata(st,7) ) + {// specified part of map + const char* map = script_getstr(st,3); + int x0 = script_getnum(st,4); + int y0 = script_getnum(st,5); + int x1 = script_getnum(st,6); + int y1 = script_getnum(st,7); - map_foreachinarea(playBGM_sub, map_mapname2mapid(map), x0, y0, x1, y1, BL_PC, name); - } else if (script_hasdata(st,3)) { - // entire map - const char *map = script_getstr(st,3); + map_foreachinarea(playBGM_sub, map_mapname2mapid(map), x0, y0, x1, y1, BL_PC, name); + } + else if( script_hasdata(st,3) ) + {// entire map + const char* map = script_getstr(st,3); - map_foreachinmap(playBGM_sub, map_mapname2mapid(map), BL_PC, name); - } else { - // entire server - map_foreachpc(&playBGM_foreachpc_sub, name); - } + map_foreachinmap(playBGM_sub, map_mapname2mapid(map), BL_PC, name); + } + else + {// entire server + map_foreachpc(&playBGM_foreachpc_sub, name); + } - return 0; + return 0; } /*========================================== @@ -12303,24 +12234,25 @@ BUILDIN_FUNC(playBGMall) *------------------------------------------*/ BUILDIN_FUNC(soundeffect) { - TBL_PC *sd = script_rid2sd(st); - const char *name = script_getstr(st,2); - int type = script_getnum(st,3); + TBL_PC* sd = script_rid2sd(st); + const char* name = script_getstr(st,2); + int type = script_getnum(st,3); - if (sd) { - clif_soundeffect(sd,&sd->bl,name,type); - } - return 0; + if(sd) + { + clif_soundeffect(sd,&sd->bl,name,type); + } + return 0; } -int soundeffect_sub(struct block_list *bl,va_list ap) +int soundeffect_sub(struct block_list* bl,va_list ap) { - char *name = va_arg(ap,char *); - int type = va_arg(ap,int); + char* name = va_arg(ap,char*); + int type = va_arg(ap,int); - clif_soundeffect((TBL_PC *)bl, bl, name, type); + clif_soundeffect((TBL_PC *)bl, bl, name, type); - return 0; + return 0; } /*========================================== @@ -12329,65 +12261,71 @@ int soundeffect_sub(struct block_list *bl,va_list ap) *------------------------------------------*/ BUILDIN_FUNC(soundeffectall) { - struct block_list *bl; - const char *name; - int type; - - bl = (st->rid) ? &(script_rid2sd(st)->bl) : map_id2bl(st->oid); - if (!bl) - return 0; - - name = script_getstr(st,2); - type = script_getnum(st,3); - - //FIXME: enumerating map squares (map_foreach) is slower than enumerating the list of online players (map_foreachpc?) [ultramage] - - if (!script_hasdata(st,4)) { - // area around - clif_soundeffectall(bl, name, type, AREA); - } else if (!script_hasdata(st,5)) { - // entire map - const char *map = script_getstr(st,4); - map_foreachinmap(soundeffect_sub, map_mapname2mapid(map), BL_PC, name, type); - } else if (script_hasdata(st,8)) { - // specified part of map - const char *map = script_getstr(st,4); - int x0 = script_getnum(st,5); - int y0 = script_getnum(st,6); - int x1 = script_getnum(st,7); - int y1 = script_getnum(st,8); - map_foreachinarea(soundeffect_sub, map_mapname2mapid(map), x0, y0, x1, y1, BL_PC, name, type); - } else { - ShowError("buildin_soundeffectall: insufficient arguments for specific area broadcast.\n"); - } - - return 0; + struct block_list* bl; + const char* name; + int type; + + bl = (st->rid) ? &(script_rid2sd(st)->bl) : map_id2bl(st->oid); + if (!bl) + return 0; + + name = script_getstr(st,2); + type = script_getnum(st,3); + + //FIXME: enumerating map squares (map_foreach) is slower than enumerating the list of online players (map_foreachpc?) [ultramage] + + if(!script_hasdata(st,4)) + { // area around + clif_soundeffectall(bl, name, type, AREA); + } + else + if(!script_hasdata(st,5)) + { // entire map + const char* map = script_getstr(st,4); + map_foreachinmap(soundeffect_sub, map_mapname2mapid(map), BL_PC, name, type); + } + else + if(script_hasdata(st,8)) + { // specified part of map + const char* map = script_getstr(st,4); + int x0 = script_getnum(st,5); + int y0 = script_getnum(st,6); + int x1 = script_getnum(st,7); + int y1 = script_getnum(st,8); + map_foreachinarea(soundeffect_sub, map_mapname2mapid(map), x0, y0, x1, y1, BL_PC, name, type); + } + else + { + ShowError("buildin_soundeffectall: insufficient arguments for specific area broadcast.\n"); + } + + return 0; } /*========================================== * pet status recovery [Valaris] / Rewritten by [Skotlex] *------------------------------------------*/ BUILDIN_FUNC(petrecovery) { - struct pet_data *pd; - TBL_PC *sd=script_rid2sd(st); + struct pet_data *pd; + TBL_PC *sd=script_rid2sd(st); - if (sd==NULL || sd->pd==NULL) - return 0; + if(sd==NULL || sd->pd==NULL) + return 0; - pd=sd->pd; + pd=sd->pd; - if (pd->recovery) { - //Halt previous bonus - if (pd->recovery->timer != INVALID_TIMER) - delete_timer(pd->recovery->timer, pet_recovery_timer); - } else //Init - pd->recovery = (struct pet_recovery *)aMalloc(sizeof(struct pet_recovery)); + if (pd->recovery) + { //Halt previous bonus + if (pd->recovery->timer != INVALID_TIMER) + delete_timer(pd->recovery->timer, pet_recovery_timer); + } else //Init + pd->recovery = (struct pet_recovery *)aMalloc(sizeof(struct pet_recovery)); - pd->recovery->type = (sc_type)script_getnum(st,2); - pd->recovery->delay = script_getnum(st,3); - pd->recovery->timer = INVALID_TIMER; + pd->recovery->type = (sc_type)script_getnum(st,2); + pd->recovery->delay = script_getnum(st,3); + pd->recovery->timer = INVALID_TIMER; - return 0; + return 0; } /*========================================== @@ -12395,38 +12333,39 @@ BUILDIN_FUNC(petrecovery) *------------------------------------------*/ BUILDIN_FUNC(petheal) { - struct pet_data *pd; - TBL_PC *sd=script_rid2sd(st); - - if (sd==NULL || sd->pd==NULL) - return 0; - - pd=sd->pd; - if (pd->s_skill) { - //Clear previous skill - if (pd->s_skill->timer != INVALID_TIMER) { - if (pd->s_skill->id) - delete_timer(pd->s_skill->timer, pet_skill_support_timer); - else - delete_timer(pd->s_skill->timer, pet_heal_timer); - } - } else //init memory - pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support)); - - pd->s_skill->id=0; //This id identifies that it IS petheal rather than pet_skillsupport - //Use the lv as the amount to heal - pd->s_skill->lv=script_getnum(st,2); - pd->s_skill->delay=script_getnum(st,3); - pd->s_skill->hp=script_getnum(st,4); - pd->s_skill->sp=script_getnum(st,5); - - //Use delay as initial offset to avoid skill/heal exploits - if (battle_config.pet_equip_required && pd->pet.equip == 0) - pd->s_skill->timer = INVALID_TIMER; - else - pd->s_skill->timer = add_timer(gettick()+pd->s_skill->delay*1000,pet_heal_timer,sd->bl.id,0); - - return 0; + struct pet_data *pd; + TBL_PC *sd=script_rid2sd(st); + + if(sd==NULL || sd->pd==NULL) + return 0; + + pd=sd->pd; + if (pd->s_skill) + { //Clear previous skill + if (pd->s_skill->timer != INVALID_TIMER) + { + if (pd->s_skill->id) + delete_timer(pd->s_skill->timer, pet_skill_support_timer); + else + delete_timer(pd->s_skill->timer, pet_heal_timer); + } + } else //init memory + pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support)); + + pd->s_skill->id=0; //This id identifies that it IS petheal rather than pet_skillsupport + //Use the lv as the amount to heal + pd->s_skill->lv=script_getnum(st,2); + pd->s_skill->delay=script_getnum(st,3); + pd->s_skill->hp=script_getnum(st,4); + pd->s_skill->sp=script_getnum(st,5); + + //Use delay as initial offset to avoid skill/heal exploits + if (battle_config.pet_equip_required && pd->pet.equip == 0) + pd->s_skill->timer = INVALID_TIMER; + else + pd->s_skill->timer = add_timer(gettick()+pd->s_skill->delay*1000,pet_heal_timer,sd->bl.id,0); + + return 0; } /*========================================== @@ -12436,23 +12375,23 @@ BUILDIN_FUNC(petheal) /// petskillattack "<skill name>",<level>,<rate>,<bonusrate> BUILDIN_FUNC(petskillattack) { - struct pet_data *pd; - TBL_PC *sd=script_rid2sd(st); + struct pet_data *pd; + TBL_PC *sd=script_rid2sd(st); - if (sd==NULL || sd->pd==NULL) - return 0; + if(sd==NULL || sd->pd==NULL) + return 0; - pd=sd->pd; - if (pd->a_skill == NULL) - pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack)); + pd=sd->pd; + if (pd->a_skill == NULL) + pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack)); - pd->a_skill->id=(script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2)); - pd->a_skill->lv=script_getnum(st,3); - pd->a_skill->div_ = 0; - pd->a_skill->rate=script_getnum(st,4); - pd->a_skill->bonusrate=script_getnum(st,5); + pd->a_skill->id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + pd->a_skill->lv=script_getnum(st,3); + pd->a_skill->div_ = 0; + pd->a_skill->rate=script_getnum(st,4); + pd->a_skill->bonusrate=script_getnum(st,5); - return 0; + return 0; } /*========================================== @@ -12462,23 +12401,23 @@ BUILDIN_FUNC(petskillattack) /// petskillattack2 "<skill name>",<level>,<div>,<rate>,<bonusrate> BUILDIN_FUNC(petskillattack2) { - struct pet_data *pd; - TBL_PC *sd=script_rid2sd(st); + struct pet_data *pd; + TBL_PC *sd=script_rid2sd(st); - if (sd==NULL || sd->pd==NULL) - return 0; + if(sd==NULL || sd->pd==NULL) + return 0; - pd=sd->pd; - if (pd->a_skill == NULL) - pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack)); + pd=sd->pd; + if (pd->a_skill == NULL) + pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack)); - pd->a_skill->id=(script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2)); - pd->a_skill->lv=script_getnum(st,3); - pd->a_skill->div_ = script_getnum(st,4); - pd->a_skill->rate=script_getnum(st,5); - pd->a_skill->bonusrate=script_getnum(st,6); + pd->a_skill->id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + pd->a_skill->lv=script_getnum(st,3); + pd->a_skill->div_ = script_getnum(st,4); + pd->a_skill->rate=script_getnum(st,5); + pd->a_skill->bonusrate=script_getnum(st,6); - return 0; + return 0; } /*========================================== @@ -12488,37 +12427,38 @@ BUILDIN_FUNC(petskillattack2) /// petskillsupport "<skill name>",<level>,<delay>,<hp>,<sp> BUILDIN_FUNC(petskillsupport) { - struct pet_data *pd; - TBL_PC *sd=script_rid2sd(st); + struct pet_data *pd; + TBL_PC *sd=script_rid2sd(st); - if (sd==NULL || sd->pd==NULL) - return 0; + if(sd==NULL || sd->pd==NULL) + return 0; - pd=sd->pd; - if (pd->s_skill) { - //Clear previous skill - if (pd->s_skill->timer != INVALID_TIMER) { - if (pd->s_skill->id) - delete_timer(pd->s_skill->timer, pet_skill_support_timer); - else - delete_timer(pd->s_skill->timer, pet_heal_timer); - } - } else //init memory - pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support)); + pd=sd->pd; + if (pd->s_skill) + { //Clear previous skill + if (pd->s_skill->timer != INVALID_TIMER) + { + if (pd->s_skill->id) + delete_timer(pd->s_skill->timer, pet_skill_support_timer); + else + delete_timer(pd->s_skill->timer, pet_heal_timer); + } + } else //init memory + pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support)); - pd->s_skill->id=(script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2)); - pd->s_skill->lv=script_getnum(st,3); - pd->s_skill->delay=script_getnum(st,4); - pd->s_skill->hp=script_getnum(st,5); - pd->s_skill->sp=script_getnum(st,6); + pd->s_skill->id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + pd->s_skill->lv=script_getnum(st,3); + pd->s_skill->delay=script_getnum(st,4); + pd->s_skill->hp=script_getnum(st,5); + pd->s_skill->sp=script_getnum(st,6); - //Use delay as initial offset to avoid skill/heal exploits - if (battle_config.pet_equip_required && pd->pet.equip == 0) - pd->s_skill->timer = INVALID_TIMER; - else - pd->s_skill->timer = add_timer(gettick()+pd->s_skill->delay*1000,pet_skill_support_timer,sd->bl.id,0); + //Use delay as initial offset to avoid skill/heal exploits + if (battle_config.pet_equip_required && pd->pet.equip == 0) + pd->s_skill->timer = INVALID_TIMER; + else + pd->s_skill->timer = add_timer(gettick()+pd->s_skill->delay*1000,pet_skill_support_timer,sd->bl.id,0); - return 0; + return 0; } /*========================================== @@ -12528,15 +12468,15 @@ BUILDIN_FUNC(petskillsupport) /// skilleffect "<skill name>",<level> BUILDIN_FUNC(skilleffect) { - TBL_PC *sd; + TBL_PC *sd; - int skillid=(script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2)); - int skilllv=script_getnum(st,3); - sd=script_rid2sd(st); + int skillid=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + int skilllv=script_getnum(st,3); + sd=script_rid2sd(st); - clif_skill_nodamage(&sd->bl,&sd->bl,skillid,skilllv,1); + clif_skill_nodamage(&sd->bl,&sd->bl,skillid,skilllv,1); - return 0; + return 0; } /*========================================== @@ -12546,17 +12486,17 @@ BUILDIN_FUNC(skilleffect) /// npcskilleffect "<skill name>",<level>,<x>,<y> BUILDIN_FUNC(npcskilleffect) { - struct block_list *bl= map_id2bl(st->oid); + struct block_list *bl= map_id2bl(st->oid); - int skillid=(script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2)); - int skilllv=script_getnum(st,3); - int x=script_getnum(st,4); - int y=script_getnum(st,5); + int skillid=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + int skilllv=script_getnum(st,3); + int x=script_getnum(st,4); + int y=script_getnum(st,5); - if (bl) - clif_skill_poseffect(bl,skillid,skilllv,x,y,gettick()); + if (bl) + clif_skill_poseffect(bl,skillid,skilllv,x,y,gettick()); - return 0; + return 0; } /*========================================== @@ -12564,43 +12504,46 @@ BUILDIN_FUNC(npcskilleffect) *------------------------------------------*/ BUILDIN_FUNC(specialeffect) { - struct block_list *bl=map_id2bl(st->oid); - int type = script_getnum(st,2); - enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA; - - if (bl==NULL) - return 0; - - if (script_hasdata(st,4)) { - TBL_NPC *nd = npc_name2id(script_getstr(st,4)); - if (nd) - clif_specialeffect(&nd->bl, type, target); - } else { - if (target == SELF) { - TBL_PC *sd=script_rid2sd(st); - if (sd) - clif_specialeffect_single(bl,type,sd->fd); - } else { - clif_specialeffect(bl, type, target); - } - } - - return 0; + struct block_list *bl=map_id2bl(st->oid); + int type = script_getnum(st,2); + enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA; + + if(bl==NULL) + return 0; + + if( script_hasdata(st,4) ) + { + TBL_NPC *nd = npc_name2id(script_getstr(st,4)); + if(nd) + clif_specialeffect(&nd->bl, type, target); + } + else + { + if (target == SELF) { + TBL_PC *sd=script_rid2sd(st); + if (sd) + clif_specialeffect_single(bl,type,sd->fd); + } else { + clif_specialeffect(bl, type, target); + } + } + + return 0; } BUILDIN_FUNC(specialeffect2) { - TBL_PC *sd=script_rid2sd(st); - int type = script_getnum(st,2); - enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA; + TBL_PC *sd=script_rid2sd(st); + int type = script_getnum(st,2); + enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA; - if (script_hasdata(st,4)) - sd = map_nick2sd(script_getstr(st,4)); + if( script_hasdata(st,4) ) + sd = map_nick2sd(script_getstr(st,4)); - if (sd) - clif_specialeffect(&sd->bl, type, target); + if (sd) + clif_specialeffect(&sd->bl, type, target); - return 0; + return 0; } /*========================================== @@ -12608,24 +12551,24 @@ BUILDIN_FUNC(specialeffect2) *------------------------------------------*/ BUILDIN_FUNC(nude) { - TBL_PC *sd = script_rid2sd(st); - int i, calcflag = 0; + TBL_PC *sd = script_rid2sd(st); + int i, calcflag = 0; - if (sd == NULL) - return 0; + if( sd == NULL ) + return 0; - for (i = 0 ; i < EQI_MAX; i++) { - if (sd->equip_index[ i ] >= 0) { - if (!calcflag) - calcflag = 1; - pc_unequipitem(sd , sd->equip_index[ i ] , 2); - } - } + for( i = 0 ; i < EQI_MAX; i++ ) { + if( sd->equip_index[ i ] >= 0 ) { + if( !calcflag ) + calcflag = 1; + pc_unequipitem( sd , sd->equip_index[ i ] , 2); + } + } - if (calcflag) - status_calc_pc(sd,0); + if( calcflag ) + status_calc_pc(sd,0); - return 0; + return 0; } /*========================================== @@ -12633,36 +12576,37 @@ BUILDIN_FUNC(nude) *------------------------------------------*/ BUILDIN_FUNC(atcommand) { - TBL_PC dummy_sd; - TBL_PC *sd; - int fd; - const char *cmd; - - cmd = script_getstr(st,2); - - if (st->rid) { - sd = script_rid2sd(st); - fd = sd->fd; - } else { //Use a dummy character. - sd = &dummy_sd; - fd = 0; - - memset(&dummy_sd, 0, sizeof(TBL_PC)); - if (st->oid) { - struct block_list *bl = map_id2bl(st->oid); - memcpy(&dummy_sd.bl, bl, sizeof(struct block_list)); - if (bl->type == BL_NPC) - safestrncpy(dummy_sd.status.name, ((TBL_NPC *)bl)->name, NAME_LENGTH); - } - } + TBL_PC dummy_sd; + TBL_PC* sd; + int fd; + const char* cmd; - if (!is_atcommand(fd, sd, cmd, 0)) { - ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd); - script_reportsrc(st); - return 1; - } + cmd = script_getstr(st,2); - return 0; + if (st->rid) { + sd = script_rid2sd(st); + fd = sd->fd; + } else { //Use a dummy character. + sd = &dummy_sd; + fd = 0; + + memset(&dummy_sd, 0, sizeof(TBL_PC)); + if (st->oid) + { + struct block_list* bl = map_id2bl(st->oid); + memcpy(&dummy_sd.bl, bl, sizeof(struct block_list)); + if (bl->type == BL_NPC) + safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH); + } + } + + if (!is_atcommand(fd, sd, cmd, 0)) { + ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd); + script_reportsrc(st); + return 1; + } + + return 0; } /*========================================== @@ -12670,12 +12614,12 @@ BUILDIN_FUNC(atcommand) *------------------------------------------*/ BUILDIN_FUNC(dispbottom) { - TBL_PC *sd=script_rid2sd(st); - const char *message; - message=script_getstr(st,2); - if (sd) - clif_disp_onlyself(sd,message,(int)strlen(message)); - return 0; + TBL_PC *sd=script_rid2sd(st); + const char *message; + message=script_getstr(st,2); + if(sd) + clif_disp_onlyself(sd,message,(int)strlen(message)); + return 0; } /*========================================== @@ -12684,19 +12628,20 @@ BUILDIN_FUNC(dispbottom) *------------------------------------------*/ BUILDIN_FUNC(recovery) { - TBL_PC *sd; - struct s_mapiterator *iter; - - iter = mapit_getallusers(); - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) { - if (pc_isdead(sd)) - status_revive(&sd->bl, 100, 100); - else - status_percent_heal(&sd->bl, 100, 100); - clif_displaymessage(sd->fd,msg_txt(680)); - } - mapit_free(iter); - return 0; + TBL_PC* sd; + struct s_mapiterator* iter; + + iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + { + if(pc_isdead(sd)) + status_revive(&sd->bl, 100, 100); + else + status_percent_heal(&sd->bl, 100, 100); + clif_displaymessage(sd->fd,msg_txt(680)); + } + mapit_free(iter); + return 0; } /*========================================== * Get your pet info: getpetinfo(n) @@ -12705,42 +12650,30 @@ BUILDIN_FUNC(recovery) *------------------------------------------*/ BUILDIN_FUNC(getpetinfo) { - TBL_PC *sd=script_rid2sd(st); - TBL_PET *pd; - int type=script_getnum(st,2); - - if (!sd || !sd->pd) { - if (type == 2) - script_pushconststr(st,"null"); - else - script_pushint(st,0); - return 0; - } - pd = sd->pd; - switch (type) { - case 0: - script_pushint(st,pd->pet.pet_id); - break; - case 1: - script_pushint(st,pd->pet.class_); - break; - case 2: - script_pushstrcopy(st,pd->pet.name); - break; - case 3: - script_pushint(st,pd->pet.intimate); - break; - case 4: - script_pushint(st,pd->pet.hungry); - break; - case 5: - script_pushint(st,pd->pet.rename_flag); - break; - default: - script_pushint(st,0); - break; - } - return 0; + TBL_PC *sd=script_rid2sd(st); + TBL_PET *pd; + int type=script_getnum(st,2); + + if(!sd || !sd->pd) { + if (type == 2) + script_pushconststr(st,"null"); + else + script_pushint(st,0); + return 0; + } + pd = sd->pd; + switch(type){ + case 0: script_pushint(st,pd->pet.pet_id); break; + case 1: script_pushint(st,pd->pet.class_); break; + case 2: script_pushstrcopy(st,pd->pet.name); break; + case 3: script_pushint(st,pd->pet.intimate); break; + case 4: script_pushint(st,pd->pet.hungry); break; + case 5: script_pushint(st,pd->pet.rename_flag); break; + default: + script_pushint(st,0); + break; + } + return 0; } /*========================================== @@ -12751,159 +12684,138 @@ BUILDIN_FUNC(getpetinfo) *------------------------------------------*/ BUILDIN_FUNC(gethominfo) { - TBL_PC *sd=script_rid2sd(st); - TBL_HOM *hd; - int type=script_getnum(st,2); - - hd = sd?sd->hd:NULL; - if (!merc_is_hom_active(hd)) { - if (type == 2) - script_pushconststr(st,"null"); - else - script_pushint(st,0); - return 0; - } - - switch (type) { - case 0: - script_pushint(st,hd->homunculus.hom_id); - break; - case 1: - script_pushint(st,hd->homunculus.class_); - break; - case 2: - script_pushstrcopy(st,hd->homunculus.name); - break; - case 3: - script_pushint(st,hd->homunculus.intimacy); - break; - case 4: - script_pushint(st,hd->homunculus.hunger); - break; - case 5: - script_pushint(st,hd->homunculus.rename_flag); - break; - case 6: - script_pushint(st,hd->homunculus.level); - break; - default: - script_pushint(st,0); - break; - } - return 0; + TBL_PC *sd=script_rid2sd(st); + TBL_HOM *hd; + int type=script_getnum(st,2); + + hd = sd?sd->hd:NULL; + if(!merc_is_hom_active(hd)) + { + if (type == 2) + script_pushconststr(st,"null"); + else + script_pushint(st,0); + return 0; + } + + switch(type){ + case 0: script_pushint(st,hd->homunculus.hom_id); break; + case 1: script_pushint(st,hd->homunculus.class_); break; + case 2: script_pushstrcopy(st,hd->homunculus.name); break; + case 3: script_pushint(st,hd->homunculus.intimacy); break; + case 4: script_pushint(st,hd->homunculus.hunger); break; + case 5: script_pushint(st,hd->homunculus.rename_flag); break; + case 6: script_pushint(st,hd->homunculus.level); break; + default: + script_pushint(st,0); + break; + } + return 0; } /// Retrieves information about character's mercenary /// getmercinfo <type>[,<char id>]; BUILDIN_FUNC(getmercinfo) { - int type, char_id; - struct map_session_data *sd; - struct mercenary_data *md; - - type = script_getnum(st,2); - - if (script_hasdata(st,3)) { - char_id = script_getnum(st,3); - - if ((sd = map_charid2sd(char_id)) == NULL) { - ShowError("buildin_getmercinfo: No such character (char_id=%d).\n", char_id); - script_pushnil(st); - return 1; - } - } else { - if ((sd = script_rid2sd(st)) == NULL) { - script_pushnil(st); - return 0; - } - } - - md = (sd->status.mer_id && sd->md) ? sd->md : NULL; - - switch (type) { - case 0: - script_pushint(st,md ? md->mercenary.mercenary_id : 0); - break; - case 1: - script_pushint(st,md ? md->mercenary.class_ : 0); - break; - case 2: - if (md) - script_pushstrcopy(st,md->db->name); - else - script_pushconststr(st,""); - break; - case 3: - script_pushint(st,md ? mercenary_get_faith(md) : 0); - break; - case 4: - script_pushint(st,md ? mercenary_get_calls(md) : 0); - break; - case 5: - script_pushint(st,md ? md->mercenary.kill_count : 0); - break; - case 6: - script_pushint(st,md ? mercenary_get_lifetime(md) : 0); - break; - case 7: - script_pushint(st,md ? md->db->lv : 0); - break; - default: - ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id); - script_pushnil(st); - return 1; - } - - return 0; + int type, char_id; + struct map_session_data* sd; + struct mercenary_data* md; + + type = script_getnum(st,2); + + if( script_hasdata(st,3) ) + { + char_id = script_getnum(st,3); + + if( ( sd = map_charid2sd(char_id) ) == NULL ) + { + ShowError("buildin_getmercinfo: No such character (char_id=%d).\n", char_id); + script_pushnil(st); + return 1; + } + } + else + { + if( ( sd = script_rid2sd(st) ) == NULL ) + { + script_pushnil(st); + return 0; + } + } + + md = ( sd->status.mer_id && sd->md ) ? sd->md : NULL; + + switch( type ) + { + case 0: script_pushint(st,md ? md->mercenary.mercenary_id : 0); break; + case 1: script_pushint(st,md ? md->mercenary.class_ : 0); break; + case 2: + if( md ) + script_pushstrcopy(st,md->db->name); + else + script_pushconststr(st,""); + break; + case 3: script_pushint(st,md ? mercenary_get_faith(md) : 0); break; + case 4: script_pushint(st,md ? mercenary_get_calls(md) : 0); break; + case 5: script_pushint(st,md ? md->mercenary.kill_count : 0); break; + case 6: script_pushint(st,md ? mercenary_get_lifetime(md) : 0); break; + case 7: script_pushint(st,md ? md->db->lv : 0); break; + default: + ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id); + script_pushnil(st); + return 1; + } + + return 0; } /*========================================== * Shows wether your inventory(and equips) contain selected card or not. - checkequipedcard(4001); + checkequipedcard(4001); *------------------------------------------*/ BUILDIN_FUNC(checkequipedcard) { - TBL_PC *sd=script_rid2sd(st); - - if (sd) { - int n,i,c=0; - c=script_getnum(st,2); - - for (i=0; i<MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount && sd->inventory_data[i]) { - if (itemdb_isspecial(sd->status.inventory[i].card[0])) - continue; - for (n=0; n<sd->inventory_data[i]->slot; n++) { - if (sd->status.inventory[i].card[n]==c) { - script_pushint(st,1); - return 0; - } - } - } - } - } - script_pushint(st,0); - return 0; + TBL_PC *sd=script_rid2sd(st); + + if(sd){ + int n,i,c=0; + c=script_getnum(st,2); + + for(i=0;i<MAX_INVENTORY;i++){ + if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount && sd->inventory_data[i]){ + if (itemdb_isspecial(sd->status.inventory[i].card[0])) + continue; + for(n=0;n<sd->inventory_data[i]->slot;n++){ + if(sd->status.inventory[i].card[n]==c){ + script_pushint(st,1); + return 0; + } + } + } + } + } + script_pushint(st,0); + return 0; } BUILDIN_FUNC(jump_zero) { - int sel; - sel=script_getnum(st,2); - if (!sel) { - int pos; - if (!data_islabel(script_getdata(st,3))) { - ShowError("script: jump_zero: not label !\n"); - st->state=END; - return 1; - } + int sel; + sel=script_getnum(st,2); + if(!sel) { + int pos; + if( !data_islabel(script_getdata(st,3)) ){ + ShowError("script: jump_zero: not label !\n"); + st->state=END; + return 1; + } - pos=script_getnum(st,3); - st->pos=pos; - st->state=GOTO; - } - return 0; + pos=script_getnum(st,3); + st->pos=pos; + st->state=GOTO; + } + return 0; } /*========================================== @@ -12911,21 +12823,21 @@ BUILDIN_FUNC(jump_zero) *------------------------------------------*/ BUILDIN_FUNC(movenpc) { - TBL_NPC *nd = NULL; - const char *npc; - int x,y; + TBL_NPC *nd = NULL; + const char *npc; + int x,y; - npc = script_getstr(st,2); - x = script_getnum(st,3); - y = script_getnum(st,4); + npc = script_getstr(st,2); + x = script_getnum(st,3); + y = script_getnum(st,4); - if ((nd = npc_name2id(npc)) == NULL) - return -1; + if ((nd = npc_name2id(npc)) == NULL) + return -1; - if (script_hasdata(st,5)) - nd->ud.dir = script_getnum(st,5) % 8; - npc_movenpc(nd, x, y); - return 0; + if (script_hasdata(st,5)) + nd->ud.dir = script_getnum(st,5) % 8; + npc_movenpc(nd, x, y); + return 0; } /*========================================== @@ -12933,17 +12845,17 @@ BUILDIN_FUNC(movenpc) *------------------------------------------*/ BUILDIN_FUNC(message) { - const char *msg,*player; - TBL_PC *pl_sd = NULL; + const char *msg,*player; + TBL_PC *pl_sd = NULL; - player = script_getstr(st,2); - msg = script_getstr(st,3); + player = script_getstr(st,2); + msg = script_getstr(st,3); - if ((pl_sd=map_nick2sd((char *) player)) == NULL) - return 0; - clif_displaymessage(pl_sd->fd, msg); + if((pl_sd=map_nick2sd((char *) player)) == NULL) + return 0; + clif_displaymessage(pl_sd->fd, msg); - return 0; + return 0; } /*========================================== @@ -12951,63 +12863,65 @@ BUILDIN_FUNC(message) *------------------------------------------*/ BUILDIN_FUNC(npctalk) { - const char *str; - char name[NAME_LENGTH], message[256]; + const char* str; + char name[NAME_LENGTH], message[256]; - struct npc_data *nd = (struct npc_data *)map_id2bl(st->oid); - str = script_getstr(st,2); + struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid); + str = script_getstr(st,2); - if (nd) { - safestrncpy(name, nd->name, sizeof(name)); - strtok(name, "#"); // discard extra name identifier if present - safesnprintf(message, sizeof(message), "%s : %s", name, str); - clif_message(&nd->bl, message); - } + if(nd) + { + safestrncpy(name, nd->name, sizeof(name)); + strtok(name, "#"); // discard extra name identifier if present + safesnprintf(message, sizeof(message), "%s : %s", name, str); + clif_message(&nd->bl, message); + } - return 0; + return 0; } // change npc walkspeed [Valaris] BUILDIN_FUNC(npcspeed) { - struct npc_data *nd; - int speed; + struct npc_data* nd; + int speed; - speed = script_getnum(st,2); - nd =(struct npc_data *)map_id2bl(st->oid); + speed = script_getnum(st,2); + nd =(struct npc_data *)map_id2bl(st->oid); - if (nd) { - nd->speed = speed; - nd->ud.state.speed_changed = 1; - } + if( nd ) + { + nd->speed = speed; + nd->ud.state.speed_changed = 1; + } - return 0; + return 0; } // make an npc walk to a position [Valaris] BUILDIN_FUNC(npcwalkto) { - struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); - int x=0,y=0; + struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); + int x=0,y=0; - x=script_getnum(st,2); - y=script_getnum(st,3); + x=script_getnum(st,2); + y=script_getnum(st,3); - if (nd) { - unit_walktoxy(&nd->bl,x,y,0); - } + if(nd) { + unit_walktoxy(&nd->bl,x,y,0); + } - return 0; + return 0; } // stop an npc's movement [Valaris] BUILDIN_FUNC(npcstop) { - struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); + struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); - if (nd) { - unit_stop_walking(&nd->bl,1|4); - } + if(nd) { + unit_stop_walking(&nd->bl,1|4); + } - return 0; + return 0; } @@ -13016,43 +12930,26 @@ BUILDIN_FUNC(npcstop) *------------------------------------------*/ BUILDIN_FUNC(getlook) { - int type,val; - TBL_PC *sd; - sd=script_rid2sd(st); - - type=script_getnum(st,2); - val=-1; - switch (type) { - case LOOK_HAIR: - val=sd->status.hair; - break; //1 - case LOOK_WEAPON: - val=sd->status.weapon; - break; //2 - case LOOK_HEAD_BOTTOM: - val=sd->status.head_bottom; - break; //3 - case LOOK_HEAD_TOP: - val=sd->status.head_top; - break; //4 - case LOOK_HEAD_MID: - val=sd->status.head_mid; - break; //5 - case LOOK_HAIR_COLOR: - val=sd->status.hair_color; - break; //6 - case LOOK_CLOTHES_COLOR: - val=sd->status.clothes_color; - break; //7 - case LOOK_SHIELD: - val=sd->status.shield; - break; //8 - case LOOK_SHOES: - break; //9 - } + int type,val; + TBL_PC *sd; + sd=script_rid2sd(st); - script_pushint(st,val); - return 0; + type=script_getnum(st,2); + val=-1; + switch(type) { + case LOOK_HAIR: val=sd->status.hair; break; //1 + case LOOK_WEAPON: val=sd->status.weapon; break; //2 + case LOOK_HEAD_BOTTOM: val=sd->status.head_bottom; break; //3 + case LOOK_HEAD_TOP: val=sd->status.head_top; break; //4 + case LOOK_HEAD_MID: val=sd->status.head_mid; break; //5 + case LOOK_HAIR_COLOR: val=sd->status.hair_color; break; //6 + case LOOK_CLOTHES_COLOR: val=sd->status.clothes_color; break; //7 + case LOOK_SHIELD: val=sd->status.shield; break; //8 + case LOOK_SHOES: break; //9 + } + + script_pushint(st,val); + return 0; } /*========================================== @@ -13060,32 +12957,26 @@ BUILDIN_FUNC(getlook) *------------------------------------------*/ BUILDIN_FUNC(getsavepoint) { - TBL_PC *sd; - int type; + TBL_PC* sd; + int type; - sd = script_rid2sd(st); - if (sd == NULL) { - script_pushint(st,0); - return 0; - } + sd = script_rid2sd(st); + if (sd == NULL) { + script_pushint(st,0); + return 0; + } - type = script_getnum(st,2); - - switch (type) { - case 0: - script_pushstrcopy(st,mapindex_id2name(sd->status.save_point.map)); - break; - case 1: - script_pushint(st,sd->status.save_point.x); - break; - case 2: - script_pushint(st,sd->status.save_point.y); - break; - default: - script_pushint(st,0); - break; - } - return 0; + type = script_getnum(st,2); + + switch(type) { + case 0: script_pushstrcopy(st,mapindex_id2name(sd->status.save_point.map)); break; + case 1: script_pushint(st,sd->status.save_point.x); break; + case 2: script_pushint(st,sd->status.save_point.y); break; + default: + script_pushint(st,0); + break; + } + return 0; } /*========================================== @@ -13112,142 +13003,143 @@ BUILDIN_FUNC(getsavepoint) *------------------------------------------*/ BUILDIN_FUNC(getmapxy) { - struct block_list *bl = NULL; - TBL_PC *sd=NULL; - - int num; - const char *name; - char prefix; - - int x,y,type; - char mapname[MAP_NAME_LENGTH]; - - if (!data_isreference(script_getdata(st,2))) { - ShowWarning("script: buildin_getmapxy: not mapname variable\n"); - script_pushint(st,-1); - return 1; - } - if (!data_isreference(script_getdata(st,3))) { - ShowWarning("script: buildin_getmapxy: not mapx variable\n"); - script_pushint(st,-1); - return 1; - } - if (!data_isreference(script_getdata(st,4))) { - ShowWarning("script: buildin_getmapxy: not mapy variable\n"); - script_pushint(st,-1); - return 1; - } - - // Possible needly check function parameters on C_STR,C_INT,C_INT - type=script_getnum(st,5); - - switch (type) { - case 0: //Get Character Position - if (script_hasdata(st,6)) - sd=map_nick2sd(script_getstr(st,6)); - else - sd=script_rid2sd(st); - - if (sd) - bl = &sd->bl; - break; - case 1: //Get NPC Position - if (script_hasdata(st,6)) { - struct npc_data *nd; - nd=npc_name2id(script_getstr(st,6)); - if (nd) - bl = &nd->bl; - } else //In case the origin is not an npc? - bl=map_id2bl(st->oid); - break; - case 2: //Get Pet Position - if (script_hasdata(st,6)) - sd=map_nick2sd(script_getstr(st,6)); - else - sd=script_rid2sd(st); - - if (sd && sd->pd) - bl = &sd->pd->bl; - break; - case 3: //Get Mob Position - break; //Not supported? - case 4: //Get Homun Position - if (script_hasdata(st,6)) - sd=map_nick2sd(script_getstr(st,6)); - else - sd=script_rid2sd(st); - - if (sd && sd->hd) - bl = &sd->hd->bl; - break; - case 5: //Get Mercenary Position - if (script_hasdata(st,6)) - sd=map_nick2sd(script_getstr(st,6)); - else - sd=script_rid2sd(st); - - if (sd && sd->md) - bl = &sd->md->bl; - break; - case 6: //Get Elemental Position - if (script_hasdata(st,6)) - sd=map_nick2sd(script_getstr(st,6)); - else - sd=script_rid2sd(st); - - if (sd && sd->ed) - bl = &sd->ed->bl; - break; - default: - ShowWarning("script: buildin_getmapxy: Invalid type %d\n", type); - script_pushint(st,-1); - return 1; - } - if (!bl) { //No object found. - script_pushint(st,-1); - return 0; - } - - x= bl->x; - y= bl->y; - safestrncpy(mapname, map[bl->m].name, MAP_NAME_LENGTH); - - //Set MapName$ - num=st->stack->stack_data[st->start+2].u.num; - name=get_str(num&0x00ffffff); - prefix=*name; - - if (not_server_variable(prefix)) - sd=script_rid2sd(st); - else - sd=NULL; - set_reg(st,sd,num,name,(void *)mapname,script_getref(st,2)); - - //Set MapX - num=st->stack->stack_data[st->start+3].u.num; - name=get_str(num&0x00ffffff); - prefix=*name; - - if (not_server_variable(prefix)) - sd=script_rid2sd(st); - else - sd=NULL; - set_reg(st,sd,num,name,(void *)__64BPRTSIZE(x),script_getref(st,3)); - - //Set MapY - num=st->stack->stack_data[st->start+4].u.num; - name=get_str(num&0x00ffffff); - prefix=*name; - - if (not_server_variable(prefix)) - sd=script_rid2sd(st); - else - sd=NULL; - set_reg(st,sd,num,name,(void *)__64BPRTSIZE(y),script_getref(st,4)); - - //Return Success value - script_pushint(st,0); - return 0; + struct block_list *bl = NULL; + TBL_PC *sd=NULL; + + int num; + const char *name; + char prefix; + + int x,y,type; + char mapname[MAP_NAME_LENGTH]; + + if( !data_isreference(script_getdata(st,2)) ){ + ShowWarning("script: buildin_getmapxy: not mapname variable\n"); + script_pushint(st,-1); + return 1; + } + if( !data_isreference(script_getdata(st,3)) ){ + ShowWarning("script: buildin_getmapxy: not mapx variable\n"); + script_pushint(st,-1); + return 1; + } + if( !data_isreference(script_getdata(st,4)) ){ + ShowWarning("script: buildin_getmapxy: not mapy variable\n"); + script_pushint(st,-1); + return 1; + } + + // Possible needly check function parameters on C_STR,C_INT,C_INT + type=script_getnum(st,5); + + switch (type){ + case 0: //Get Character Position + if( script_hasdata(st,6) ) + sd=map_nick2sd(script_getstr(st,6)); + else + sd=script_rid2sd(st); + + if (sd) + bl = &sd->bl; + break; + case 1: //Get NPC Position + if( script_hasdata(st,6) ) + { + struct npc_data *nd; + nd=npc_name2id(script_getstr(st,6)); + if (nd) + bl = &nd->bl; + } else //In case the origin is not an npc? + bl=map_id2bl(st->oid); + break; + case 2: //Get Pet Position + if(script_hasdata(st,6)) + sd=map_nick2sd(script_getstr(st,6)); + else + sd=script_rid2sd(st); + + if (sd && sd->pd) + bl = &sd->pd->bl; + break; + case 3: //Get Mob Position + break; //Not supported? + case 4: //Get Homun Position + if(script_hasdata(st,6)) + sd=map_nick2sd(script_getstr(st,6)); + else + sd=script_rid2sd(st); + + if (sd && sd->hd) + bl = &sd->hd->bl; + break; + case 5: //Get Mercenary Position + if(script_hasdata(st,6)) + sd=map_nick2sd(script_getstr(st,6)); + else + sd=script_rid2sd(st); + + if (sd && sd->md) + bl = &sd->md->bl; + break; + case 6: //Get Elemental Position + if(script_hasdata(st,6)) + sd=map_nick2sd(script_getstr(st,6)); + else + sd=script_rid2sd(st); + + if (sd && sd->ed) + bl = &sd->ed->bl; + break; + default: + ShowWarning("script: buildin_getmapxy: Invalid type %d\n", type); + script_pushint(st,-1); + return 1; + } + if (!bl) { //No object found. + script_pushint(st,-1); + return 0; + } + + x= bl->x; + y= bl->y; + safestrncpy(mapname, map[bl->m].name, MAP_NAME_LENGTH); + + //Set MapName$ + num=st->stack->stack_data[st->start+2].u.num; + name=get_str(num&0x00ffffff); + prefix=*name; + + if(not_server_variable(prefix)) + sd=script_rid2sd(st); + else + sd=NULL; + set_reg(st,sd,num,name,(void*)mapname,script_getref(st,2)); + + //Set MapX + num=st->stack->stack_data[st->start+3].u.num; + name=get_str(num&0x00ffffff); + prefix=*name; + + if(not_server_variable(prefix)) + sd=script_rid2sd(st); + else + sd=NULL; + set_reg(st,sd,num,name,(void*)__64BPRTSIZE(x),script_getref(st,3)); + + //Set MapY + num=st->stack->stack_data[st->start+4].u.num; + name=get_str(num&0x00ffffff); + prefix=*name; + + if(not_server_variable(prefix)) + sd=script_rid2sd(st); + else + sd=NULL; + set_reg(st,sd,num,name,(void*)__64BPRTSIZE(y),script_getref(st,4)); + + //Return Success value + script_pushint(st,0); + return 0; } /*========================================== @@ -13255,52 +13147,52 @@ BUILDIN_FUNC(getmapxy) *------------------------------------------*/ BUILDIN_FUNC(logmes) { - const char *str; - TBL_PC *sd; + const char *str; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 1; + sd = script_rid2sd(st); + if( sd == NULL ) + return 1; - str = script_getstr(st,2); - log_npc(sd,str); - return 0; + str = script_getstr(st,2); + log_npc(sd,str); + return 0; } BUILDIN_FUNC(summon) { - int _class, timeout=0; - const char *str,*event=""; - TBL_PC *sd; - struct mob_data *md; - int tick = gettick(); - - sd=script_rid2sd(st); - if (!sd) return 0; - - str =script_getstr(st,2); - _class=script_getnum(st,3); - if (script_hasdata(st,4)) - timeout=script_getnum(st,4); - if (script_hasdata(st,5)) { - event=script_getstr(st,5); - check_event(st, event); - } - - clif_skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick); - - md = mob_once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, _class, event, SZ_SMALL, AI_NONE); - if (md) { - md->master_id=sd->bl.id; - md->special_state.ai = AI_ATTACK; - if (md->deletetimer != INVALID_TIMER) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer(tick+(timeout>0?timeout*1000:60000),mob_timer_delete,md->bl.id,0); - mob_spawn(md); //Now it is ready for spawning. - clif_specialeffect(&md->bl,344,AREA); - sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); - } - return 0; + int _class, timeout=0; + const char *str,*event=""; + TBL_PC *sd; + struct mob_data *md; + int tick = gettick(); + + sd=script_rid2sd(st); + if (!sd) return 0; + + str =script_getstr(st,2); + _class=script_getnum(st,3); + if( script_hasdata(st,4) ) + timeout=script_getnum(st,4); + if( script_hasdata(st,5) ){ + event=script_getstr(st,5); + check_event(st, event); + } + + clif_skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick); + + md = mob_once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, _class, event, SZ_SMALL, AI_NONE); + if (md) { + md->master_id=sd->bl.id; + md->special_state.ai = AI_ATTACK; + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer(tick+(timeout>0?timeout*1000:60000),mob_timer_delete,md->bl.id,0); + mob_spawn (md); //Now it is ready for spawning. + clif_specialeffect(&md->bl,344,AREA); + sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); + } + return 0; } /*========================================== @@ -13308,14 +13200,14 @@ BUILDIN_FUNC(summon) *------------------------------------------*/ BUILDIN_FUNC(isnight) { - script_pushint(st,(night_flag == 1)); - return 0; + script_pushint(st,(night_flag == 1)); + return 0; } BUILDIN_FUNC(isday) { - script_pushint(st,(night_flag == 0)); - return 0; + script_pushint(st,(night_flag == 0)); + return 0; } /*================================================ @@ -13324,48 +13216,48 @@ BUILDIN_FUNC(isday) *------------------------------------------------*/ BUILDIN_FUNC(isequippedcnt) { - TBL_PC *sd; - int i, j, k, id = 1; - int ret = 0; - - sd = script_rid2sd(st); - if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing... - script_pushint(st,0); - return 0; - } - - for (i=0; id!=0; i++) { - FETCH(i+2, id) else id = 0; - if (id <= 0) - continue; - - for (j=0; j<EQI_MAX; j++) { - int index; - index = sd->equip_index[j]; - if (index < 0) continue; - if (j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue; - if (j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue; - if (j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue; - - if (!sd->inventory_data[index]) - continue; - - if (itemdb_type(id) != IT_CARD) { //No card. Count amount in inventory. - if (sd->inventory_data[index]->nameid == id) - ret+= sd->status.inventory[index].amount; - } else { //Count cards. - if (itemdb_isspecial(sd->status.inventory[index].card[0])) - continue; //No cards - for (k=0; k<sd->inventory_data[index]->slot; k++) { - if (sd->status.inventory[index].card[k] == id) - ret++; //[Lupus] - } - } - } - } - - script_pushint(st,ret); - return 0; + TBL_PC *sd; + int i, j, k, id = 1; + int ret = 0; + + sd = script_rid2sd(st); + if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing... + script_pushint(st,0); + return 0; + } + + for (i=0; id!=0; i++) { + FETCH (i+2, id) else id = 0; + if (id <= 0) + continue; + + for (j=0; j<EQI_MAX; j++) { + int index; + index = sd->equip_index[j]; + if(index < 0) continue; + if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue; + if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue; + if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue; + + if(!sd->inventory_data[index]) + continue; + + if (itemdb_type(id) != IT_CARD) { //No card. Count amount in inventory. + if (sd->inventory_data[index]->nameid == id) + ret+= sd->status.inventory[index].amount; + } else { //Count cards. + if (itemdb_isspecial(sd->status.inventory[index].card[0])) + continue; //No cards + for(k=0; k<sd->inventory_data[index]->slot; k++) { + if (sd->status.inventory[index].card[k] == id) + ret++; //[Lupus] + } + } + } + } + + script_pushint(st,ret); + return 0; } /*================================================ @@ -13376,82 +13268,82 @@ BUILDIN_FUNC(isequippedcnt) *------------------------------------------------*/ BUILDIN_FUNC(isequipped) { - TBL_PC *sd; - int i, j, k, id = 1; - int index, flag; - int ret = -1; - //Original hash to reverse it when full check fails. - unsigned int setitem_hash = 0, setitem_hash2 = 0; - - sd = script_rid2sd(st); - - if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing... - script_pushint(st,0); - return 0; - } - - setitem_hash = sd->bonus.setitem_hash; - setitem_hash2 = sd->bonus.setitem_hash2; - for (i=0; id!=0; i++) { - FETCH(i+2, id) else id = 0; - if (id <= 0) - continue; - flag = 0; - for (j=0; j<EQI_MAX; j++) { - index = sd->equip_index[j]; - if (index < 0) continue; - if (j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue; - if (j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue; - if (j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue; - - if (!sd->inventory_data[index]) - continue; - - if (itemdb_type(id) != IT_CARD) { - if (sd->inventory_data[index]->nameid != id) - continue; - flag = 1; - break; - } else { //Cards - if (sd->inventory_data[index]->slot == 0 || - itemdb_isspecial(sd->status.inventory[index].card[0])) - continue; - - for (k = 0; k < sd->inventory_data[index]->slot; k++) { - //New hash system which should support up to 4 slots on any equipment. [Skotlex] - unsigned int hash = 0; - if (sd->status.inventory[index].card[k] != id) - continue; - - hash = 1<<((j<5?j:j-5)*4 + k); - // check if card is already used by another set - if ((j < 5 ? sd->bonus.setitem_hash : sd->bonus.setitem_hash2) & hash) - continue; - - // We have found a match - flag = 1; - // Set hash so this card cannot be used by another - if (j<5) - sd->bonus.setitem_hash |= hash; - else - sd->bonus.setitem_hash2 |= hash; - break; - } - } - if (flag) break; //Card found - } - if (ret == -1) - ret = flag; - else - ret &= flag; - if (!ret) break; - } - if (!ret) {//When check fails, restore original hash values. [Skotlex] - sd->bonus.setitem_hash = setitem_hash; - sd->bonus.setitem_hash2 = setitem_hash2; - } - script_pushint(st,ret); - return 0; + TBL_PC *sd; + int i, j, k, id = 1; + int index, flag; + int ret = -1; + //Original hash to reverse it when full check fails. + unsigned int setitem_hash = 0, setitem_hash2 = 0; + + sd = script_rid2sd(st); + + if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing... + script_pushint(st,0); + return 0; + } + + setitem_hash = sd->bonus.setitem_hash; + setitem_hash2 = sd->bonus.setitem_hash2; + for (i=0; id!=0; i++) { + FETCH (i+2, id) else id = 0; + if (id <= 0) + continue; + flag = 0; + for (j=0; j<EQI_MAX; j++) { + index = sd->equip_index[j]; + if(index < 0) continue; + if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue; + if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue; + if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue; + + if(!sd->inventory_data[index]) + continue; + + if (itemdb_type(id) != IT_CARD) { + if (sd->inventory_data[index]->nameid != id) + continue; + flag = 1; + break; + } else { //Cards + if (sd->inventory_data[index]->slot == 0 || + itemdb_isspecial(sd->status.inventory[index].card[0])) + continue; + + for (k = 0; k < sd->inventory_data[index]->slot; k++) + { //New hash system which should support up to 4 slots on any equipment. [Skotlex] + unsigned int hash = 0; + if (sd->status.inventory[index].card[k] != id) + continue; + + hash = 1<<((j<5?j:j-5)*4 + k); + // check if card is already used by another set + if ( ( j < 5 ? sd->bonus.setitem_hash : sd->bonus.setitem_hash2 ) & hash) + continue; + + // We have found a match + flag = 1; + // Set hash so this card cannot be used by another + if (j<5) + sd->bonus.setitem_hash |= hash; + else + sd->bonus.setitem_hash2 |= hash; + break; + } + } + if (flag) break; //Card found + } + if (ret == -1) + ret = flag; + else + ret &= flag; + if (!ret) break; + } + if (!ret) {//When check fails, restore original hash values. [Skotlex] + sd->bonus.setitem_hash = setitem_hash; + sd->bonus.setitem_hash2 = setitem_hash2; + } + script_pushint(st,ret); + return 0; } /*================================================ @@ -13460,39 +13352,39 @@ BUILDIN_FUNC(isequipped) *------------------------------------------------*/ BUILDIN_FUNC(cardscnt) { - TBL_PC *sd; - int i, k, id = 1; - int ret = 0; - int index; - - 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; - - if (!sd->inventory_data[index]) - continue; - - if (itemdb_type(id) != IT_CARD) { - if (sd->inventory_data[index]->nameid == id) - ret+= sd->status.inventory[index].amount; - } else { - if (itemdb_isspecial(sd->status.inventory[index].card[0])) - continue; - for (k=0; k<sd->inventory_data[index]->slot; k++) { - if (sd->status.inventory[index].card[k] == id) - ret++; - } - } - } - script_pushint(st,ret); - // script_pushint(st,current_equip_item_index); - return 0; + TBL_PC *sd; + int i, k, id = 1; + int ret = 0; + int index; + + 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; + + if(!sd->inventory_data[index]) + continue; + + if(itemdb_type(id) != IT_CARD) { + if (sd->inventory_data[index]->nameid == id) + ret+= sd->status.inventory[index].amount; + } else { + if (itemdb_isspecial(sd->status.inventory[index].card[0])) + continue; + for(k=0; k<sd->inventory_data[index]->slot; k++) { + if (sd->status.inventory[index].card[k] == id) + ret++; + } + } + } + script_pushint(st,ret); +// script_pushint(st,current_equip_item_index); + return 0; } /*======================================================= @@ -13501,12 +13393,12 @@ BUILDIN_FUNC(cardscnt) *-------------------------------------------------------*/ BUILDIN_FUNC(getrefine) { - TBL_PC *sd; - if ((sd = script_rid2sd(st))!= NULL) - script_pushint(st,sd->status.inventory[current_equip_item_index].refine); - else - script_pushint(st,0); - return 0; + TBL_PC *sd; + if ((sd = script_rid2sd(st))!= NULL) + script_pushint(st,sd->status.inventory[current_equip_item_index].refine); + else + script_pushint(st,0); + return 0; } /*======================================================= @@ -13514,13 +13406,13 @@ BUILDIN_FUNC(getrefine) *-------------------------------------------------------*/ BUILDIN_FUNC(night) { - if (night_flag != 1) map_night_timer(night_timer_tid, 0, 0, 1); - return 0; + if (night_flag != 1) map_night_timer(night_timer_tid, 0, 0, 1); + return 0; } BUILDIN_FUNC(day) { - if (night_flag != 0) map_day_timer(day_timer_tid, 0, 0, 1); - return 0; + if (night_flag != 0) map_day_timer(day_timer_tid, 0, 0, 1); + return 0; } //======================================================= @@ -13528,82 +13420,86 @@ BUILDIN_FUNC(day) //------------------------------------------------------- BUILDIN_FUNC(unequip) { - int i; - size_t num; - TBL_PC *sd; + int i; + size_t num; + TBL_PC *sd; - num = script_getnum(st,2); - sd = script_rid2sd(st); - if (sd != NULL && num >= 1 && num <= ARRAYLENGTH(equip)) { - i = pc_checkequip(sd,equip[num-1]); - if (i >= 0) - pc_unequipitem(sd,i,1|2); - } - return 0; + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd != NULL && num >= 1 && num <= ARRAYLENGTH(equip) ) + { + i = pc_checkequip(sd,equip[num-1]); + if (i >= 0) + pc_unequipitem(sd,i,1|2); + } + return 0; } BUILDIN_FUNC(equip) { - int nameid=0,i; - TBL_PC *sd; - struct item_data *item_data; + int nameid=0,i; + TBL_PC *sd; + struct item_data *item_data; - sd = script_rid2sd(st); + sd = script_rid2sd(st); - nameid=script_getnum(st,2); - if ((item_data = itemdb_exists(nameid)) == NULL) { - ShowError("wrong item ID : equipitem(%i)\n",nameid); - return 1; - } - ARR_FIND(0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid); - if (i < MAX_INVENTORY) - pc_equipitem(sd,i,item_data->equip); + nameid=script_getnum(st,2); + if((item_data = itemdb_exists(nameid)) == NULL) + { + ShowError("wrong item ID : equipitem(%i)\n",nameid); + return 1; + } + ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid ); + if( i < MAX_INVENTORY ) + pc_equipitem(sd,i,item_data->equip); - return 0; + return 0; } BUILDIN_FUNC(autoequip) { - int nameid, flag; - struct item_data *item_data; - nameid=script_getnum(st,2); - flag=script_getnum(st,3); + int nameid, flag; + struct item_data *item_data; + nameid=script_getnum(st,2); + flag=script_getnum(st,3); - if ((item_data = itemdb_exists(nameid)) == NULL) { - ShowError("buildin_autoequip: Invalid item '%d'.\n", nameid); - return 1; - } + if( ( item_data = itemdb_exists(nameid) ) == NULL ) + { + ShowError("buildin_autoequip: Invalid item '%d'.\n", nameid); + return 1; + } - if (!itemdb_isequip2(item_data)) { - ShowError("buildin_autoequip: Item '%d' cannot be equipped.\n", nameid); - return 1; - } + if( !itemdb_isequip2(item_data) ) + { + ShowError("buildin_autoequip: Item '%d' cannot be equipped.\n", nameid); + return 1; + } - item_data->flag.autoequip = flag>0?1:0; - return 0; + item_data->flag.autoequip = flag>0?1:0; + return 0; } BUILDIN_FUNC(setbattleflag) { - const char *flag, *value; + const char *flag, *value; - flag = script_getstr(st,2); - value = script_getstr(st,3); // HACK: Retrieve number as string (auto-converted) for battle_set_value + flag = script_getstr(st,2); + value = script_getstr(st,3); // HACK: Retrieve number as string (auto-converted) for battle_set_value - if (battle_set_value(flag, value) == 0) - ShowWarning("buildin_setbattleflag: unknown battle_config flag '%s'\n",flag); - else - ShowInfo("buildin_setbattleflag: battle_config flag '%s' is now set to '%s'.\n",flag,value); + if (battle_set_value(flag, value) == 0) + ShowWarning("buildin_setbattleflag: unknown battle_config flag '%s'\n",flag); + else + ShowInfo("buildin_setbattleflag: battle_config flag '%s' is now set to '%s'.\n",flag,value); - return 0; + return 0; } BUILDIN_FUNC(getbattleflag) { - const char *flag; - flag = script_getstr(st,2); - script_pushint(st,battle_get_value(flag)); - return 0; + const char *flag; + flag = script_getstr(st,2); + script_pushint(st,battle_get_value(flag)); + return 0; } //======================================================= @@ -13612,11 +13508,11 @@ BUILDIN_FUNC(getbattleflag) BUILDIN_FUNC(getstrlen) { - const char *str = script_getstr(st,2); - int len = (str) ? (int)strlen(str) : 0; + const char *str = script_getstr(st,2); + int len = (str) ? (int)strlen(str) : 0; - script_pushint(st,len); - return 0; + script_pushint(st,len); + return 0; } //======================================================= @@ -13624,13 +13520,13 @@ BUILDIN_FUNC(getstrlen) //------------------------------------------------------- BUILDIN_FUNC(charisalpha) { - const char *str=script_getstr(st,2); - int pos=script_getnum(st,3); + const char *str=script_getstr(st,2); + int pos=script_getnum(st,3); - int val = (str && pos >= 0 && (unsigned int)pos < strlen(str)) ? ISALPHA(str[pos]) != 0 : 0; + int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISALPHA( str[pos] ) != 0 : 0; - script_pushint(st,val); - return 0; + script_pushint(st,val); + return 0; } //======================================================= @@ -13638,13 +13534,13 @@ BUILDIN_FUNC(charisalpha) //------------------------------------------------------- BUILDIN_FUNC(charisupper) { - const char *str = script_getstr(st,2); - int pos = script_getnum(st,3); + const char *str = script_getstr(st,2); + int pos = script_getnum(st,3); - int val = (str && pos >= 0 && (unsigned int)pos < strlen(str)) ? ISUPPER(str[pos]) : 0; + int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISUPPER( str[pos] ) : 0; - script_pushint(st,val); - return 0; + script_pushint(st,val); + return 0; } //======================================================= @@ -13652,31 +13548,30 @@ BUILDIN_FUNC(charisupper) //------------------------------------------------------- BUILDIN_FUNC(charislower) { - const char *str = script_getstr(st,2); - int pos = script_getnum(st,3); + const char *str = script_getstr(st,2); + int pos = script_getnum(st,3); - int val = (str && pos >= 0 && (unsigned int)pos < strlen(str)) ? ISLOWER(str[pos]) : 0; + int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISLOWER( str[pos] ) : 0; - script_pushint(st,val); - return 0; + script_pushint(st,val); + return 0; } //======================================================= // charat <str>, <index> //------------------------------------------------------- -BUILDIN_FUNC(charat) -{ - const char *str = script_getstr(st,2); - int pos = script_getnum(st,3); - - if (pos >= 0 && (unsigned int)pos < strlen(str)) { - char output[2]; - output[0] = str[pos]; - output[1] = '\0'; - script_pushstrcopy(st, output); - } else - script_pushconststr(st, ""); - return 0; +BUILDIN_FUNC(charat) { + const char *str = script_getstr(st,2); + int pos = script_getnum(st,3); + + if( pos >= 0 && (unsigned int)pos < strlen(str) ) { + char output[2]; + output[0] = str[pos]; + output[1] = '\0'; + script_pushstrcopy(st, output); + } else + script_pushconststr(st, ""); + return 0; } //======================================================= @@ -13684,16 +13579,16 @@ BUILDIN_FUNC(charat) //------------------------------------------------------- BUILDIN_FUNC(setchar) { - const char *str = script_getstr(st,2); - const char *c = script_getstr(st,3); - int index = script_getnum(st,4); - char *output = aStrdup(str); + const char *str = script_getstr(st,2); + const char *c = script_getstr(st,3); + int index = script_getnum(st,4); + char *output = aStrdup(str); - if (index >= 0 && index < strlen(output)) - output[index] = *c; + if(index >= 0 && index < strlen(output)) + output[index] = *c; - script_pushstr(st, output); - return 0; + script_pushstr(st, output); + return 0; } //======================================================= @@ -13701,26 +13596,26 @@ BUILDIN_FUNC(setchar) //------------------------------------------------------- BUILDIN_FUNC(insertchar) { - const char *str = script_getstr(st,2); - const char *c = script_getstr(st,3); - int index = script_getnum(st,4); - char *output; - size_t len = strlen(str); + const char *str = script_getstr(st,2); + const char *c = script_getstr(st,3); + int index = script_getnum(st,4); + char *output; + size_t len = strlen(str); - if (index < 0) - index = 0; - else if (index > len) - index = len; + if(index < 0) + index = 0; + else if(index > len) + index = len; - output = (char *)aMalloc(len + 2); + output = (char*)aMalloc(len + 2); - memcpy(output, str, index); - output[index] = c[0]; - memcpy(&output[index+1], &str[index], len - index); - output[len+1] = '\0'; + memcpy(output, str, index); + output[index] = c[0]; + memcpy(&output[index+1], &str[index], len - index); + output[len+1] = '\0'; - script_pushstr(st, output); - return 0; + script_pushstr(st, output); + return 0; } //======================================================= @@ -13728,25 +13623,25 @@ BUILDIN_FUNC(insertchar) //------------------------------------------------------- BUILDIN_FUNC(delchar) { - const char *str = script_getstr(st,2); - int index = script_getnum(st,3); - char *output; - size_t len = strlen(str); + const char *str = script_getstr(st,2); + int index = script_getnum(st,3); + char *output; + size_t len = strlen(str); - if (index < 0 || index > len) { - //return original - output = aStrdup(str); - script_pushstr(st, output); - return 0; - } + if(index < 0 || index > len) { + //return original + output = aStrdup(str); + script_pushstr(st, output); + return 0; + } - output = (char *)aMalloc(len); + output = (char*)aMalloc(len); - memcpy(output, str, index); - memcpy(&output[index], &str[index+1], len - index); + memcpy(output, str, index); + memcpy(&output[index], &str[index+1], len - index); - script_pushstr(st, output); - return 0; + script_pushstr(st, output); + return 0; } //======================================================= @@ -13754,17 +13649,17 @@ BUILDIN_FUNC(delchar) //------------------------------------------------------- BUILDIN_FUNC(strtoupper) { - const char *str = script_getstr(st,2); - char *output = aStrdup(str); - char *cursor = output; + const char *str = script_getstr(st,2); + char *output = aStrdup(str); + char *cursor = output; - while (*cursor != '\0') { - *cursor = TOUPPER(*cursor); - cursor++; - } + while (*cursor != '\0') { + *cursor = TOUPPER(*cursor); + cursor++; + } - script_pushstr(st, output); - return 0; + script_pushstr(st, output); + return 0; } //======================================================= @@ -13772,17 +13667,17 @@ BUILDIN_FUNC(strtoupper) //------------------------------------------------------- BUILDIN_FUNC(strtolower) { - const char *str = script_getstr(st,2); - char *output = aStrdup(str); - char *cursor = output; + const char *str = script_getstr(st,2); + char *output = aStrdup(str); + char *cursor = output; - while (*cursor != '\0') { - *cursor = TOLOWER(*cursor); - cursor++; - } + while (*cursor != '\0') { + *cursor = TOLOWER(*cursor); + cursor++; + } - script_pushstr(st, output); - return 0; + script_pushstr(st, output); + return 0; } //======================================================= @@ -13790,24 +13685,24 @@ BUILDIN_FUNC(strtolower) //------------------------------------------------------- BUILDIN_FUNC(substr) { - const char *str = script_getstr(st,2); - char *output; - int start = script_getnum(st,3); - int end = script_getnum(st,4); + const char *str = script_getstr(st,2); + char *output; + int start = script_getnum(st,3); + int end = script_getnum(st,4); - int len = 0; + int len = 0; - if (start >= 0 && end < strlen(str) && start <= end) { - len = end - start + 1; - output = (char *)aMalloc(len + 1); - memcpy(output, &str[start], len); - } else - output = (char *)aMalloc(1); + if(start >= 0 && end < strlen(str) && start <= end) { + len = end - start + 1; + output = (char*)aMalloc(len + 1); + memcpy(output, &str[start], len); + } else + output = (char*)aMalloc(1); - output[len] = '\0'; + output[len] = '\0'; - script_pushstr(st, output); - return 0; + script_pushstr(st, output); + return 0; } //======================================================= @@ -13816,69 +13711,73 @@ BUILDIN_FUNC(substr) //------------------------------------------------------- BUILDIN_FUNC(explode) { - struct script_data *data = script_getdata(st, 2); - const char *str = script_getstr(st,3); - const char delimiter = script_getstr(st, 4)[0]; - int32 id; - size_t len = strlen(str); - int i = 0, j = 0; - int start; - - - char *temp; - const char *name; - - TBL_PC *sd = NULL; - - temp = (char *)aMalloc(len + 1); - - if (!data_isreference(data)) { - ShowError("script:explode: not a variable\n"); - script_reportdata(data); - st->state = END; - return 1;// not a variable - } - - id = reference_getid(data); - start = reference_getindex(data); - name = reference_getname(data); - - if (not_array_variable(*name)) { - ShowError("script:explode: illegal scope\n"); - script_reportdata(data); - st->state = END; - return 1;// not supported - } - - if (!is_string_variable(name)) { - ShowError("script:explode: not string array\n"); - script_reportdata(data); - st->state = END; - return 1;// data type mismatch - } - - if (not_server_variable(*name)) { - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached - } - - while (str[i] != '\0') { - if (str[i] == delimiter && start < 127) { //break at delimiter but ignore after reaching last array index - temp[j] = '\0'; - set_reg(st, sd, reference_uid(id, start++), name, (void *)temp, reference_getref(data)); - j = 0; - ++i; - } else { - temp[j++] = str[i++]; - } - } - //set last string - temp[j] = '\0'; - set_reg(st, sd, reference_uid(id, start), name, (void *)temp, reference_getref(data)); - - aFree(temp); - return 0; + struct script_data* data = script_getdata(st, 2); + const char *str = script_getstr(st,3); + const char delimiter = script_getstr(st, 4)[0]; + int32 id; + size_t len = strlen(str); + int i = 0, j = 0; + int start; + + + char *temp; + const char* name; + + TBL_PC* sd = NULL; + + temp = (char*)aMalloc(len + 1); + + if( !data_isreference(data) ) + { + ShowError("script:explode: not a variable\n"); + script_reportdata(data); + st->state = END; + return 1;// not a variable + } + + id = reference_getid(data); + start = reference_getindex(data); + name = reference_getname(data); + + if( not_array_variable(*name) ) + { + ShowError("script:explode: illegal scope\n"); + script_reportdata(data); + st->state = END; + return 1;// not supported + } + + if( !is_string_variable(name) ) + { + ShowError("script:explode: not string array\n"); + script_reportdata(data); + st->state = END; + return 1;// data type mismatch + } + + if( not_server_variable(*name) ) + { + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached + } + + while(str[i] != '\0') { + if(str[i] == delimiter && start < 127) { //break at delimiter but ignore after reaching last array index + temp[j] = '\0'; + set_reg(st, sd, reference_uid(id, start++), name, (void*)temp, reference_getref(data)); + j = 0; + ++i; + } else { + temp[j++] = str[i++]; + } + } + //set last string + temp[j] = '\0'; + set_reg(st, sd, reference_uid(id, start), name, (void*)temp, reference_getref(data)); + + aFree(temp); + return 0; } //======================================================= @@ -13887,91 +13786,96 @@ BUILDIN_FUNC(explode) //------------------------------------------------------- BUILDIN_FUNC(implode) { - struct script_data *data = script_getdata(st, 2); - const char *glue = NULL, *name, *temp; - int32 glue_len = 0, array_size, id; - size_t len = 0; - int i, k = 0; - - TBL_PC *sd = NULL; - - char *output; - - if (!data_isreference(data)) { - ShowError("script:implode: not a variable\n"); - script_reportdata(data); - st->state = END; - return 1;// not a variable - } - - id = reference_getid(data); - name = reference_getname(data); - - if (not_array_variable(*name)) { - ShowError("script:implode: illegal scope\n"); - script_reportdata(data); - st->state = END; - return 1;// not supported - } - - if (!is_string_variable(name)) { - ShowError("script:implode: not string array\n"); - script_reportdata(data); - st->state = END; - return 1;// data type mismatch - } - - if (not_server_variable(*name)) { - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached - } - - //count chars - array_size = getarraysize(st, id, reference_getindex(data), is_string_variable(name), reference_getref(data)) - 1; - - if (array_size == -1) { //empty array check (AmsTaff) + struct script_data* data = script_getdata(st, 2); + const char *glue = NULL, *name, *temp; + int32 glue_len = 0, array_size, id; + size_t len = 0; + int i, k = 0; + + TBL_PC* sd = NULL; + + char *output; + + if( !data_isreference(data) ) + { + ShowError("script:implode: not a variable\n"); + script_reportdata(data); + st->state = END; + return 1;// not a variable + } + + id = reference_getid(data); + name = reference_getname(data); + + if( not_array_variable(*name) ) + { + ShowError("script:implode: illegal scope\n"); + script_reportdata(data); + st->state = END; + return 1;// not supported + } + + if( !is_string_variable(name) ) + { + ShowError("script:implode: not string array\n"); + script_reportdata(data); + st->state = END; + return 1;// data type mismatch + } + + if( not_server_variable(*name) ) + { + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached + } + + //count chars + array_size = getarraysize(st, id, reference_getindex(data), is_string_variable(name), reference_getref(data)) - 1; + + if(array_size == -1) //empty array check (AmsTaff) + { ShowWarning("script:implode: array length = 0\n"); - output = (char *)aMalloc(sizeof(char)*5); + output = (char*)aMalloc(sizeof(char)*5); sprintf(output,"%s","NULL"); - } else { - for (i = 0; i <= array_size; ++i) { - temp = (char *) get_val2(st, reference_uid(id, i), reference_getref(data)); - len += strlen(temp); - script_removetop(st, -1, 0); - } - - //allocate mem - if (script_hasdata(st,3)) { - glue = script_getstr(st,3); - glue_len = strlen(glue); - len += glue_len * (array_size); - } - output = (char *)aMalloc(len + 1); - - //build output - for (i = 0; i < array_size; ++i) { - temp = (char *) get_val2(st, reference_uid(id, i), reference_getref(data)); - len = strlen(temp); - memcpy(&output[k], temp, len); - k += len; - if (glue_len != 0) { - memcpy(&output[k], glue, glue_len); - k += glue_len; - } - script_removetop(st, -1, 0); - } - temp = (char *) get_val2(st, reference_uid(id, array_size), reference_getref(data)); - len = strlen(temp); - memcpy(&output[k], temp, len); - k += len; - script_removetop(st, -1, 0); - - output[k] = '\0'; - } - - script_pushstr(st, output); - return 0; + } else { + for(i = 0; i <= array_size; ++i) { + temp = (char*) get_val2(st, reference_uid(id, i), reference_getref(data)); + len += strlen(temp); + script_removetop(st, -1, 0); + } + + //allocate mem + if( script_hasdata(st,3) ) { + glue = script_getstr(st,3); + glue_len = strlen(glue); + len += glue_len * (array_size); + } + output = (char*)aMalloc(len + 1); + + //build output + for(i = 0; i < array_size; ++i) { + temp = (char*) get_val2(st, reference_uid(id, i), reference_getref(data)); + len = strlen(temp); + memcpy(&output[k], temp, len); + k += len; + if(glue_len != 0) { + memcpy(&output[k], glue, glue_len); + k += glue_len; + } + script_removetop(st, -1, 0); + } + temp = (char*) get_val2(st, reference_uid(id, array_size), reference_getref(data)); + len = strlen(temp); + memcpy(&output[k], temp, len); + k += len; + script_removetop(st, -1, 0); + + output[k] = '\0'; + } + + script_pushstr(st, output); + return 0; } //======================================================= @@ -13982,12 +13886,12 @@ BUILDIN_FUNC(implode) BUILDIN_FUNC(sprintf) { unsigned int len, argc = 0, arg = 0, buf2_len = 0; - const char *format; - char *p; - char *q; - char *buf = NULL; - char *buf2 = NULL; - struct script_data *data; + const char* format; + char* p; + char* q; + char* buf = NULL; + char* buf2 = NULL; + struct script_data* data; StringBuf final_buf; // Fetch init data @@ -13996,7 +13900,7 @@ BUILDIN_FUNC(sprintf) len = strlen(format); // Skip parsing, where no parsing is required. - if (len==0) { + if(len==0){ script_pushconststr(st,""); return 0; } @@ -14005,8 +13909,8 @@ BUILDIN_FUNC(sprintf) CREATE(buf, char, len+1); // Need not be parsed, just solve stuff like %%. - if (argc==0) { - memcpy(buf,format,len+1); + if(argc==0){ + memcpy(buf,format,len+1); script_pushstrcopy(st, buf); aFree(buf); return 0; @@ -14017,10 +13921,10 @@ BUILDIN_FUNC(sprintf) // Issue sprintf for each parameter StringBuf_Init(&final_buf); q = buf; - while ((p = strchr(q, '%'))!=NULL) { - if (p!=q) { + while((p = strchr(q, '%'))!=NULL){ + if(p!=q){ len = p-q+1; - if (buf2_len<len) { + if(buf2_len<len){ RECREATE(buf2, char, len); buf2_len = len; } @@ -14029,30 +13933,30 @@ BUILDIN_FUNC(sprintf) q = p; } p = q+1; - if (*p=='%') { // %% + if(*p=='%'){ // %% StringBuf_AppendStr(&final_buf, "%"); q+=2; continue; } - if (*p=='n') { // %n + if(*p=='n'){ // %n ShowWarning("buildin_sprintf: Format %%n not supported! Skipping...\n"); script_reportsrc(st); q+=2; continue; } - if (arg>=argc) { + if(arg>=argc){ ShowError("buildin_sprintf: Not enough arguments passed!\n"); - if (buf) aFree(buf); - if (buf2) aFree(buf2); + if(buf) aFree(buf); + if(buf2) aFree(buf2); StringBuf_Destroy(&final_buf); script_pushconststr(st,""); return 1; } - if ((p = strchr(q+1, '%'))==NULL) { + if((p = strchr(q+1, '%'))==NULL){ p = strchr(q, 0); // EOS } len = p-q+1; - if (buf2_len<len) { + if(buf2_len<len){ RECREATE(buf2, char, len); buf2_len = len; } @@ -14065,21 +13969,21 @@ BUILDIN_FUNC(sprintf) // but it would behave in normal code the same way so it's // the scripter's responsibility. data = script_getdata(st, arg+3); - if (data_isstring(data)) { // String + if(data_isstring(data)){ // String StringBuf_Printf(&final_buf, buf2, script_getstr(st, arg+3)); - } else if (data_isint(data)) { // Number + }else if(data_isint(data)){ // Number StringBuf_Printf(&final_buf, buf2, script_getnum(st, arg+3)); - } else if (data_isreference(data)) { // Variable - char *name = reference_getname(data); - if (name[strlen(name)-1]=='$') { // var Str + }else if(data_isreference(data)){ // Variable + char* name = reference_getname(data); + if(name[strlen(name)-1]=='$'){ // var Str StringBuf_Printf(&final_buf, buf2, script_getstr(st, arg+3)); - } else { // var Int + }else{ // var Int StringBuf_Printf(&final_buf, buf2, script_getnum(st, arg+3)); } - } else { // Unsupported type + }else{ // Unsupported type ShowError("buildin_sprintf: Unknown argument type!\n"); - if (buf) aFree(buf); - if (buf2) aFree(buf2); + if(buf) aFree(buf); + if(buf2) aFree(buf2); StringBuf_Destroy(&final_buf); script_pushconststr(st,""); return 1; @@ -14088,20 +13992,20 @@ BUILDIN_FUNC(sprintf) } // Append anything left - if (*q) { + if(*q){ StringBuf_AppendStr(&final_buf, q); } // Passed more, than needed - if (arg<argc) { + if(arg<argc){ ShowWarning("buildin_sprintf: Unused arguments passed.\n"); script_reportsrc(st); } script_pushstrcopy(st, StringBuf_Value(&final_buf)); - if (buf) aFree(buf); - if (buf2) aFree(buf2); + if(buf) aFree(buf); + if(buf2) aFree(buf2); StringBuf_Destroy(&final_buf); return 0; @@ -14111,18 +14015,17 @@ BUILDIN_FUNC(sprintf) // sscanf(<str>, <format>, ...); // Implements C sscanf. //------------------------------------------------------- -BUILDIN_FUNC(sscanf) -{ +BUILDIN_FUNC(sscanf){ unsigned int argc, arg = 0, len; - struct script_data *data; - struct map_session_data *sd = NULL; - const char *str; - const char *format; - const char *p; - const char *q; - char *buf = NULL; - char *buf_p; - char *ref_str = NULL; + struct script_data* data; + struct map_session_data* sd = NULL; + const char* str; + const char* format; + const char* p; + const char* q; + char* buf = NULL; + char* buf_p; + char* ref_str = NULL; int ref_int; // Get data @@ -14136,25 +14039,25 @@ BUILDIN_FUNC(sscanf) // Issue sscanf for each parameter *buf = 0; q = format; - while ((p = strchr(q, '%'))) { - if (p!=q) { + while((p = strchr(q, '%'))){ + if(p!=q){ strncat(buf, q, (size_t)(p-q)); q = p; } p = q+1; - if (*p=='*' || *p=='%') { // Skip + if(*p=='*' || *p=='%'){ // Skip strncat(buf, q, 2); q+=2; continue; } - if (arg>=argc) { + if(arg>=argc){ ShowError("buildin_sscanf: Not enough arguments passed!\n"); script_pushint(st, -1); - if (buf) aFree(buf); - if (ref_str) aFree(ref_str); + if(buf) aFree(buf); + if(ref_str) aFree(ref_str); return 1; } - if ((p = strchr(q+1, '%'))==NULL) { + if((p = strchr(q+1, '%'))==NULL){ p = strchr(q, 0); // EOS } len = p-q; @@ -14163,32 +14066,32 @@ BUILDIN_FUNC(sscanf) // Validate output data = script_getdata(st, arg+4); - if (!data_isreference(data) || !reference_tovariable(data)) { + if(!data_isreference(data) || !reference_tovariable(data)){ ShowError("buildin_sscanf: Target argument is not a variable!\n"); script_pushint(st, -1); - if (buf) aFree(buf); - if (ref_str) aFree(ref_str); + if(buf) aFree(buf); + if(ref_str) aFree(ref_str); return 1; } buf_p = reference_getname(data); - if (not_server_variable(*buf_p) && (sd = script_rid2sd(st))==NULL) { + if(not_server_variable(*buf_p) && (sd = script_rid2sd(st))==NULL){ script_pushint(st, -1); - if (buf) aFree(buf); - if (ref_str) aFree(ref_str); + if(buf) aFree(buf); + if(ref_str) aFree(ref_str); return 0; } // Save value if any - if (buf_p[strlen(buf_p)-1]=='$') { // String - if (ref_str==NULL) { + if(buf_p[strlen(buf_p)-1]=='$'){ // String + if(ref_str==NULL){ CREATE(ref_str, char, strlen(str)+1); } - if (sscanf(str, buf, ref_str)==0) { + if(sscanf(str, buf, ref_str)==0){ break; } set_reg(st, sd, add_str(buf_p), buf_p, (void *)(ref_str), reference_getref(data)); - } else { // Number - if (sscanf(str, buf, &ref_int)==0) { + }else{ // Number + if(sscanf(str, buf, &ref_int)==0){ break; } set_reg(st, sd, add_str(buf_p), buf_p, (void *)__64BPRTSIZE(ref_int), reference_getref(data)); @@ -14202,14 +14105,14 @@ BUILDIN_FUNC(sscanf) } // Passed more, than needed - if (arg<argc) { + if(arg<argc){ ShowWarning("buildin_sscanf: Unused arguments passed.\n"); script_reportsrc(st); } script_pushint(st, arg); - if (buf) aFree(buf); - if (ref_str) aFree(ref_str); + if(buf) aFree(buf); + if(ref_str) aFree(ref_str); return 0; } @@ -14221,41 +14124,40 @@ BUILDIN_FUNC(sscanf) // Implements PHP style strpos. Adapted from code from // http://www.daniweb.com/code/snippet313.html, Dave Sinkula //------------------------------------------------------- -BUILDIN_FUNC(strpos) -{ - const char *haystack = script_getstr(st,2); - const char *needle = script_getstr(st,3); - int i; - size_t len; - - if (script_hasdata(st,4)) - i = script_getnum(st,4); - else - i = 0; - - if (needle[0] == '\0') { - script_pushint(st, -1); - return 0; - } - - len = strlen(haystack); - for (; i < len; ++i) { - if (haystack[i] == *needle) { - // matched starting char -- loop through remaining chars - const char *h, *n; - for (h = &haystack[i], n = needle; *h && *n; ++h, ++n) { - if (*h != *n) { - break; - } - } - if (!*n) { // matched all of 'needle' to null termination - script_pushint(st, i); - return 0; - } - } - } - script_pushint(st, -1); - return 0; +BUILDIN_FUNC(strpos) { + const char *haystack = script_getstr(st,2); + const char *needle = script_getstr(st,3); + int i; + size_t len; + + if( script_hasdata(st,4) ) + i = script_getnum(st,4); + else + i = 0; + + if ( strlen(needle) == 0 ) { + script_pushint(st, -1); + return 0; + } + + len = strlen(haystack); + for ( ; i < len; ++i ) { + if ( haystack[i] == *needle ) { + // matched starting char -- loop through remaining chars + const char *h, *n; + for ( h = &haystack[i], n = needle; *h && *n; ++h, ++n ) { + if ( *h != *n ) { + break; + } + } + if ( !*n ) { // matched all of 'needle' to null termination + script_pushint(st, i); + return 0; + } + } + } + script_pushint(st, -1); + return 0; } //=============================================================== @@ -14268,80 +14170,80 @@ BUILDIN_FUNC(strpos) //--------------------------------------------------------------- BUILDIN_FUNC(replacestr) { - const char *input = script_getstr(st, 2); - const char *find = script_getstr(st, 3); - const char *replace = script_getstr(st, 4); - size_t inputlen = strlen(input); - size_t findlen = strlen(find); - struct StringBuf output; - bool usecase = true; - - int count = 0; - int numFinds = 0; - int i = 0, f = 0; - - if (findlen == 0) { - ShowError("script:replacestr: Invalid search length.\n"); - st->state = END; - return 1; - } - - if (script_hasdata(st, 5)) { - if (!script_isstring(st,5)) - usecase = script_getnum(st, 5) != 0; - else { - ShowError("script:replacestr: Invalid usecase value. Expected int got string\n"); - st->state = END; - return 1; - } - } - - if (script_hasdata(st, 6)) { - count = script_getnum(st, 6); - if (count == 0) { - ShowError("script:replacestr: Invalid count value. Expected int got string\n"); - st->state = END; - return 1; - } - } - - StringBuf_Init(&output); - - for (; i < inputlen; i++) { - if (count && count == numFinds) { //found enough, stop looking - break; - } - - for (f = 0; f <= findlen; f++) { - if (f == findlen) { //complete match - numFinds++; - StringBuf_AppendStr(&output, replace); - - i += findlen - 1; - break; - } else { - if (usecase) { - if ((i + f) > inputlen || input[i + f] != find[f]) { - StringBuf_Printf(&output, "%c", input[i]); - break; - } - } else { - if (((i + f) > inputlen || input[i + f] != find[f]) && TOUPPER(input[i+f]) != TOUPPER(find[f])) { - StringBuf_Printf(&output, "%c", input[i]); - break; - } - } - } - } - } - - //append excess after enough found - if (i < inputlen) - StringBuf_AppendStr(&output, &(input[i])); - - script_pushstrcopy(st, StringBuf_Value(&output)); - StringBuf_Destroy(&output); - return 0; + const char *input = script_getstr(st, 2); + const char *find = script_getstr(st, 3); + const char *replace = script_getstr(st, 4); + size_t inputlen = strlen(input); + size_t findlen = strlen(find); + struct StringBuf output; + bool usecase = true; + + int count = 0; + int numFinds = 0; + int i = 0, f = 0; + + if(findlen == 0) { + ShowError("script:replacestr: Invalid search length.\n"); + st->state = END; + return 1; + } + + if(script_hasdata(st, 5)) { + if( !script_isstring(st,5) ) + usecase = script_getnum(st, 5) != 0; + else { + ShowError("script:replacestr: Invalid usecase value. Expected int got string\n"); + st->state = END; + return 1; + } + } + + if(script_hasdata(st, 6)) { + count = script_getnum(st, 6); + if(count == 0) { + ShowError("script:replacestr: Invalid count value. Expected int got string\n"); + st->state = END; + return 1; + } + } + + StringBuf_Init(&output); + + for(; i < inputlen; i++) { + if(count && count == numFinds) { //found enough, stop looking + break; + } + + for(f = 0; f <= findlen; f++) { + if(f == findlen) { //complete match + numFinds++; + StringBuf_AppendStr(&output, replace); + + i += findlen - 1; + break; + } else { + if(usecase) { + if((i + f) > inputlen || input[i + f] != find[f]) { + StringBuf_Printf(&output, "%c", input[i]); + break; + } + } else { + if(((i + f) > inputlen || input[i + f] != find[f]) && TOUPPER(input[i+f]) != TOUPPER(find[f])) { + StringBuf_Printf(&output, "%c", input[i]); + break; + } + } + } + } + } + + //append excess after enough found + if(i < inputlen) + StringBuf_AppendStr(&output, &(input[i])); + + script_pushstrcopy(st, StringBuf_Value(&output)); + StringBuf_Destroy(&output); + return 0; } //======================================================== @@ -14352,52 +14254,52 @@ BUILDIN_FUNC(replacestr) //-------------------------------------------------------- BUILDIN_FUNC(countstr) { - const char *input = script_getstr(st, 2); - const char *find = script_getstr(st, 3); - size_t inputlen = strlen(input); - size_t findlen = strlen(find); - bool usecase = true; - - int numFinds = 0; - int i = 0, f = 0; - - if (findlen == 0) { - ShowError("script:countstr: Invalid search length.\n"); - st->state = END; - return 1; - } - - if (script_hasdata(st, 4)) { - if (!script_isstring(st,4)) - usecase = script_getnum(st, 4) != 0; - else { - ShowError("script:countstr: Invalid usecase value. Expected int got string\n"); - st->state = END; - return 1; - } - } - - for (; i < inputlen; i++) { - for (f = 0; f <= findlen; f++) { - if (f == findlen) { //complete match - numFinds++; - i += findlen - 1; - break; - } else { - if (usecase) { - if ((i + f) > inputlen || input[i + f] != find[f]) { - break; - } - } else { - if (((i + f) > inputlen || input[i + f] != find[f]) && TOUPPER(input[i+f]) != TOUPPER(find[f])) { - break; - } - } - } - } - } - script_pushint(st, numFinds); - return 0; + const char *input = script_getstr(st, 2); + const char *find = script_getstr(st, 3); + size_t inputlen = strlen(input); + size_t findlen = strlen(find); + bool usecase = true; + + int numFinds = 0; + int i = 0, f = 0; + + if(findlen == 0) { + ShowError("script:countstr: Invalid search length.\n"); + st->state = END; + return 1; + } + + if(script_hasdata(st, 4)) { + if( !script_isstring(st,4) ) + usecase = script_getnum(st, 4) != 0; + else { + ShowError("script:countstr: Invalid usecase value. Expected int got string\n"); + st->state = END; + return 1; + } + } + + for(; i < inputlen; i++) { + for(f = 0; f <= findlen; f++) { + if(f == findlen) { //complete match + numFinds++; + i += findlen - 1; + break; + } else { + if(usecase) { + if((i + f) > inputlen || input[i + f] != find[f]) { + break; + } + } else { + if(((i + f) > inputlen || input[i + f] != find[f]) && TOUPPER(input[i+f]) != TOUPPER(find[f])) { + break; + } + } + } + } + } + script_pushint(st, numFinds); + return 0; } @@ -14410,915 +14312,853 @@ BUILDIN_FUNC(countstr) /// setnpcdisplay("<npc name>", <new class id>) -> <int> BUILDIN_FUNC(setnpcdisplay) { - const char *name; - const char *newname = NULL; - int class_ = -1, size = -1; - struct script_data *data; - struct npc_data *nd; - - name = script_getstr(st,2); - data = script_getdata(st,3); - - if (script_hasdata(st,4)) - class_ = script_getnum(st,4); - if (script_hasdata(st,5)) - size = script_getnum(st,5); - - get_val(st, data); - if (data_isstring(data)) - newname = conv_str(st,data); - else if (data_isint(data)) - class_ = conv_num(st,data); - else { - ShowError("script:setnpcdisplay: expected a string or number\n"); - script_reportdata(data); - return 1; - } - - nd = npc_name2id(name); - if (nd == NULL) { - // not found - script_pushint(st,1); - return 0; - } - - // update npc - if (newname) - npc_setdisplayname(nd, newname); - - if (size != -1 && size != (int)nd->size) - nd->size = size; - else - size = -1; - - if (class_ != -1 && nd->class_ != class_) - npc_setclass(nd, class_); - else if (size != -1) { - // Required to update the visual size - clif_clearunit_area(&nd->bl, CLR_OUTSIGHT); - clif_spawn(&nd->bl); - } - - script_pushint(st,0); - return 0; + const char* name; + const char* newname = NULL; + int class_ = -1, size = -1; + struct script_data* data; + struct npc_data* nd; + + name = script_getstr(st,2); + data = script_getdata(st,3); + + if( script_hasdata(st,4) ) + class_ = script_getnum(st,4); + if( script_hasdata(st,5) ) + size = script_getnum(st,5); + + get_val(st, data); + if( data_isstring(data) ) + newname = conv_str(st,data); + else if( data_isint(data) ) + class_ = conv_num(st,data); + else + { + ShowError("script:setnpcdisplay: expected a string or number\n"); + script_reportdata(data); + return 1; + } + + nd = npc_name2id(name); + if( nd == NULL ) + {// not found + script_pushint(st,1); + return 0; + } + + // update npc + if( newname ) + npc_setdisplayname(nd, newname); + + if( size != -1 && size != (int)nd->size ) + nd->size = size; + else + size = -1; + + if( class_ != -1 && nd->class_ != class_ ) + npc_setclass(nd, class_); + else if( size != -1 ) + { // Required to update the visual size + clif_clearunit_area(&nd->bl, CLR_OUTSIGHT); + clif_spawn(&nd->bl); + } + + script_pushint(st,0); + return 0; } BUILDIN_FUNC(atoi) { - const char *value; - value = script_getstr(st,2); - script_pushint(st,atoi(value)); - return 0; + const char *value; + value = script_getstr(st,2); + script_pushint(st,atoi(value)); + return 0; } // case-insensitive substring search [lordalfa] BUILDIN_FUNC(compare) { - const char *message; - const char *cmpstring; - message = script_getstr(st,2); - cmpstring = script_getstr(st,3); - script_pushint(st,(stristr(message,cmpstring) != NULL)); - return 0; + const char *message; + const char *cmpstring; + message = script_getstr(st,2); + cmpstring = script_getstr(st,3); + script_pushint(st,(stristr(message,cmpstring) != NULL)); + return 0; } // [zBuffer] List of mathematics commands ---> BUILDIN_FUNC(sqrt) { - double i, a; - i = script_getnum(st,2); - a = sqrt(i); - script_pushint(st,(int)a); - return 0; + double i, a; + i = script_getnum(st,2); + a = sqrt(i); + script_pushint(st,(int)a); + return 0; } BUILDIN_FUNC(pow) { - double i, a, b; - a = script_getnum(st,2); - b = script_getnum(st,3); - i = pow(a,b); - script_pushint(st,(int)i); - return 0; + double i, a, b; + a = script_getnum(st,2); + b = script_getnum(st,3); + i = pow(a,b); + script_pushint(st,(int)i); + return 0; } BUILDIN_FUNC(distance) { - int x0, y0, x1, y1; + int x0, y0, x1, y1; - x0 = script_getnum(st,2); - y0 = script_getnum(st,3); - x1 = script_getnum(st,4); - y1 = script_getnum(st,5); + x0 = script_getnum(st,2); + y0 = script_getnum(st,3); + x1 = script_getnum(st,4); + y1 = script_getnum(st,5); - script_pushint(st,distance_xy(x0,y0,x1,y1)); - return 0; + script_pushint(st,distance_xy(x0,y0,x1,y1)); + return 0; } // <--- [zBuffer] List of mathematics commands BUILDIN_FUNC(md5) { - const char *tmpstr; - char *md5str; + const char *tmpstr; + char *md5str; - tmpstr = script_getstr(st,2); - md5str = (char *)aMalloc((32+1)*sizeof(char)); - MD5_String(tmpstr, md5str); - script_pushstr(st, md5str); - return 0; + tmpstr = script_getstr(st,2); + md5str = (char *)aMalloc((32+1)*sizeof(char)); + MD5_String(tmpstr, md5str); + script_pushstr(st, md5str); + return 0; } // [zBuffer] List of dynamic var commands ---> BUILDIN_FUNC(setd) { - TBL_PC *sd=NULL; - char varname[100]; - const char *buffer; - int elem; - buffer = script_getstr(st, 2); - - if (sscanf(buffer, "%99[^[][%d]", varname, &elem) < 2) - elem = 0; - - if (not_server_variable(*varname)) { - sd = script_rid2sd(st); - if (sd == NULL) { - ShowError("script:setd: no player attached for player variable '%s'\n", buffer); - return 0; - } - } - - if (is_string_variable(varname)) { - setd_sub(st, sd, varname, elem, (void *)script_getstr(st, 3), NULL); - } else { - setd_sub(st, sd, varname, elem, (void *)__64BPRTSIZE(script_getnum(st, 3)), NULL); - } - - return 0; -} - -int buildin_query_sql_sub(struct script_state *st, Sql *handle) -{ - int i, j; - TBL_PC *sd = NULL; - const char *query; - struct script_data *data; - const char *name; - int max_rows = SCRIPT_MAX_ARRAYSIZE; // maximum number of rows - int num_vars; - int num_cols; - - // check target variables - for (i = 3; script_hasdata(st,i); ++i) { - data = script_getdata(st, i); - if (data_isreference(data)) { // it's a variable - name = reference_getname(data); - if (not_server_variable(*name) && sd == NULL) { // requires a player - sd = script_rid2sd(st); - if (sd == NULL) { // no player attached - script_reportdata(data); - st->state = END; - return 1; - } - } - if (not_array_variable(*name)) - max_rows = 1;// not an array, limit to one row - } else { - ShowError("script:query_sql: not a variable\n"); - script_reportdata(data); - st->state = END; - return 1; - } - } - num_vars = i - 3; - - // Execute the query - query = script_getstr(st,2); - - if (SQL_ERROR == Sql_QueryStr(handle, query)) { - Sql_ShowDebug(handle); - script_pushint(st, 0); - return 1; - } - - if (Sql_NumRows(handle) == 0) { // No data received - Sql_FreeResult(handle); - script_pushint(st, 0); - return 0; - } - - // Count the number of columns to store - num_cols = Sql_NumColumns(handle); - if (num_vars < num_cols) { - ShowWarning("script:query_sql: Too many columns, discarding last %u columns.\n", (unsigned int)(num_cols-num_vars)); - script_reportsrc(st); - } else if (num_vars > num_cols) { - ShowWarning("script:query_sql: Too many variables (%u extra).\n", (unsigned int)(num_vars-num_cols)); - script_reportsrc(st); - } - - // Store data - for (i = 0; i < max_rows && SQL_SUCCESS == Sql_NextRow(handle); ++i) { - for (j = 0; j < num_vars; ++j) { - char *str = NULL; - - if (j < num_cols) - Sql_GetData(handle, j, &str, NULL); - - data = script_getdata(st, j+3); - name = reference_getname(data); - if (is_string_variable(name)) - setd_sub(st, sd, name, i, (void *)(str?str:""), reference_getref(data)); - else - setd_sub(st, sd, name, i, (void *)__64BPRTSIZE((str?atoi(str):0)), reference_getref(data)); - } - } - if (i == max_rows && max_rows < Sql_NumRows(handle)) { - ShowWarning("script:query_sql: Only %d/%u rows have been stored.\n", max_rows, (unsigned int)Sql_NumRows(handle)); - script_reportsrc(st); - } - - // Free data - Sql_FreeResult(handle); - script_pushint(st, i); - - return 0; -} - -BUILDIN_FUNC(query_sql) -{ + TBL_PC *sd=NULL; + char varname[100]; + const char *buffer; + int elem; + buffer = script_getstr(st, 2); + + if(sscanf(buffer, "%99[^[][%d]", varname, &elem) < 2) + elem = 0; + + if( not_server_variable(*varname) ) + { + sd = script_rid2sd(st); + if( sd == NULL ) + { + ShowError("script:setd: no player attached for player variable '%s'\n", buffer); + return 0; + } + } + + if( is_string_variable(varname) ) { + setd_sub(st, sd, varname, elem, (void *)script_getstr(st, 3), NULL); + } else { + setd_sub(st, sd, varname, elem, (void *)__64BPRTSIZE(script_getnum(st, 3)), NULL); + } + + return 0; +} + +int buildin_query_sql_sub(struct script_state* st, Sql* handle) +{ + int i, j; + TBL_PC* sd = NULL; + const char* query; + struct script_data* data; + const char* name; + int max_rows = SCRIPT_MAX_ARRAYSIZE; // maximum number of rows + int num_vars; + int num_cols; + + // check target variables + for( i = 3; script_hasdata(st,i); ++i ) { + data = script_getdata(st, i); + if( data_isreference(data) ) { // it's a variable + name = reference_getname(data); + if( not_server_variable(*name) && sd == NULL ) { // requires a player + sd = script_rid2sd(st); + if( sd == NULL ) { // no player attached + script_reportdata(data); + st->state = END; + return 1; + } + } + if( not_array_variable(*name) ) + max_rows = 1;// not an array, limit to one row + } else { + ShowError("script:query_sql: not a variable\n"); + script_reportdata(data); + st->state = END; + return 1; + } + } + num_vars = i - 3; + + // Execute the query + query = script_getstr(st,2); + + if( SQL_ERROR == Sql_QueryStr(handle, query) ) { + Sql_ShowDebug(handle); + script_pushint(st, 0); + return 1; + } + + if( Sql_NumRows(handle) == 0 ) { // No data received + Sql_FreeResult(handle); + script_pushint(st, 0); + return 0; + } + + // Count the number of columns to store + num_cols = Sql_NumColumns(handle); + if( num_vars < num_cols ) { + ShowWarning("script:query_sql: Too many columns, discarding last %u columns.\n", (unsigned int)(num_cols-num_vars)); + script_reportsrc(st); + } else if( num_vars > num_cols ) { + ShowWarning("script:query_sql: Too many variables (%u extra).\n", (unsigned int)(num_vars-num_cols)); + script_reportsrc(st); + } + + // Store data + for( i = 0; i < max_rows && SQL_SUCCESS == Sql_NextRow(handle); ++i ) { + for( j = 0; j < num_vars; ++j ) { + char* str = NULL; + + if( j < num_cols ) + Sql_GetData(handle, j, &str, NULL); + + data = script_getdata(st, j+3); + name = reference_getname(data); + if( is_string_variable(name) ) + setd_sub(st, sd, name, i, (void *)(str?str:""), reference_getref(data)); + else + setd_sub(st, sd, name, i, (void *)__64BPRTSIZE((str?atoi(str):0)), reference_getref(data)); + } + } + if( i == max_rows && max_rows < Sql_NumRows(handle) ) { + ShowWarning("script:query_sql: Only %d/%u rows have been stored.\n", max_rows, (unsigned int)Sql_NumRows(handle)); + script_reportsrc(st); + } + + // Free data + Sql_FreeResult(handle); + script_pushint(st, i); + + return 0; +} + +BUILDIN_FUNC(query_sql) { #ifdef BETA_THREAD_TEST - if (st->state != RERUNLINE) { - queryThread_add(st,false); + if( st->state != RERUNLINE ) { + queryThread_add(st,false); - st->state = RERUNLINE;/* will continue when the query is finished running. */ - } else - st->state = RUN; + st->state = RERUNLINE;/* will continue when the query is finished running. */ + } else + st->state = RUN; - return 0; + return 0; #else - return buildin_query_sql_sub(st, mmysql_handle); + return buildin_query_sql_sub(st, mmysql_handle); #endif } -BUILDIN_FUNC(query_logsql) -{ - if (!log_config.sql_logs) { // logmysql_handle == NULL - ShowWarning("buildin_query_logsql: SQL logs are disabled, query '%s' will not be executed.\n", script_getstr(st,2)); - script_pushint(st,-1); - return 1; - } +BUILDIN_FUNC(query_logsql) { + if( !log_config.sql_logs ) {// logmysql_handle == NULL + ShowWarning("buildin_query_logsql: SQL logs are disabled, query '%s' will not be executed.\n", script_getstr(st,2)); + script_pushint(st,-1); + return 1; + } #ifdef BETA_THREAD_TEST - if (st->state != RERUNLINE) { - queryThread_add(st,true); + if( st->state != RERUNLINE ) { + queryThread_add(st,true); - st->state = RERUNLINE;/* will continue when the query is finished running. */ - } else - st->state = RUN; + st->state = RERUNLINE;/* will continue when the query is finished running. */ + } else + st->state = RUN; - return 0; + return 0; #else - return buildin_query_sql_sub(st, logmysql_handle); + return buildin_query_sql_sub(st, logmysql_handle); #endif } //Allows escaping of a given string. BUILDIN_FUNC(escape_sql) { - const char *str; - char *esc_str; - size_t len; + const char *str; + char *esc_str; + size_t len; - str = script_getstr(st,2); - len = strlen(str); - esc_str = (char *)aMalloc(len*2+1); - Sql_EscapeStringLen(mmysql_handle, esc_str, str, len); - script_pushstr(st, esc_str); - return 0; + str = script_getstr(st,2); + len = strlen(str); + esc_str = (char*)aMalloc(len*2+1); + Sql_EscapeStringLen(mmysql_handle, esc_str, str, len); + script_pushstr(st, esc_str); + return 0; } BUILDIN_FUNC(getd) { - char varname[100]; - const char *buffer; - int elem; + char varname[100]; + const char *buffer; + int elem; - buffer = script_getstr(st, 2); + buffer = script_getstr(st, 2); - if (sscanf(buffer, "%[^[][%d]", varname, &elem) < 2) - elem = 0; + if(sscanf(buffer, "%[^[][%d]", varname, &elem) < 2) + elem = 0; - // Push the 'pointer' so it's more flexible [Lance] - push_val(st->stack, C_NAME, reference_uid(add_str(varname), elem)); + // Push the 'pointer' so it's more flexible [Lance] + push_val(st->stack, C_NAME, reference_uid(add_str(varname), elem)); - return 0; + return 0; } // <--- [zBuffer] List of dynamic var commands // Pet stat [Lance] BUILDIN_FUNC(petstat) { - TBL_PC *sd = NULL; - struct pet_data *pd; - int flag = script_getnum(st,2); - sd = script_rid2sd(st); - if (!sd || !sd->status.pet_id || !sd->pd) { - if (flag == 2) - script_pushconststr(st, ""); - else - script_pushint(st,0); - return 0; - } - pd = sd->pd; - switch (flag) { - case 1: - script_pushint(st,(int)pd->pet.class_); - break; - case 2: - script_pushstrcopy(st, pd->pet.name); - break; - case 3: - script_pushint(st,(int)pd->pet.level); - break; - case 4: - script_pushint(st,(int)pd->pet.hungry); - break; - case 5: - script_pushint(st,(int)pd->pet.intimate); - break; - default: - script_pushint(st,0); - break; - } - return 0; + TBL_PC *sd = NULL; + struct pet_data *pd; + int flag = script_getnum(st,2); + sd = script_rid2sd(st); + if(!sd || !sd->status.pet_id || !sd->pd){ + if(flag == 2) + script_pushconststr(st, ""); + else + script_pushint(st,0); + return 0; + } + pd = sd->pd; + switch(flag){ + case 1: script_pushint(st,(int)pd->pet.class_); break; + case 2: script_pushstrcopy(st, pd->pet.name); break; + case 3: script_pushint(st,(int)pd->pet.level); break; + case 4: script_pushint(st,(int)pd->pet.hungry); break; + case 5: script_pushint(st,(int)pd->pet.intimate); break; + default: + script_pushint(st,0); + break; + } + return 0; } BUILDIN_FUNC(callshop) { - TBL_PC *sd = NULL; - struct npc_data *nd; - const char *shopname; - int flag = 0; - sd = script_rid2sd(st); - if (!sd) { - script_pushint(st,0); - return 0; - } - shopname = script_getstr(st, 2); - if (script_hasdata(st,3)) - flag = script_getnum(st,3); - nd = npc_name2id(shopname); - if (!nd || nd->bl.type != BL_NPC || (nd->subtype != SHOP && nd->subtype != CASHSHOP)) { - ShowError("buildin_callshop: Shop [%s] not found (or NPC is not shop type)\n", shopname); - script_pushint(st,0); - return 1; - } - - if (nd->subtype == SHOP) { - // flag the user as using a valid script call for opening the shop (for floating NPCs) - sd->state.callshop = 1; - - switch (flag) { - case 1: - npc_buysellsel(sd,nd->bl.id,0); - break; //Buy window - case 2: - npc_buysellsel(sd,nd->bl.id,1); - break; //Sell window - default: - clif_npcbuysell(sd,nd->bl.id); - break; //Show menu - } - } else - clif_cashshop_show(sd, nd); - - sd->npc_shopid = nd->bl.id; - script_pushint(st,1); - return 0; + TBL_PC *sd = NULL; + struct npc_data *nd; + const char *shopname; + int flag = 0; + sd = script_rid2sd(st); + if (!sd) { + script_pushint(st,0); + return 0; + } + shopname = script_getstr(st, 2); + if( script_hasdata(st,3) ) + flag = script_getnum(st,3); + nd = npc_name2id(shopname); + if( !nd || nd->bl.type != BL_NPC || (nd->subtype != SHOP && nd->subtype != CASHSHOP) ) + { + ShowError("buildin_callshop: Shop [%s] not found (or NPC is not shop type)\n", shopname); + script_pushint(st,0); + return 1; + } + + if( nd->subtype == SHOP ) + { + // flag the user as using a valid script call for opening the shop (for floating NPCs) + sd->state.callshop = 1; + + switch( flag ) + { + case 1: npc_buysellsel(sd,nd->bl.id,0); break; //Buy window + case 2: npc_buysellsel(sd,nd->bl.id,1); break; //Sell window + default: clif_npcbuysell(sd,nd->bl.id); break; //Show menu + } + } + else + clif_cashshop_show(sd, nd); + + sd->npc_shopid = nd->bl.id; + script_pushint(st,1); + return 0; } BUILDIN_FUNC(npcshopitem) { - const char *npcname = script_getstr(st, 2); - struct npc_data *nd = npc_name2id(npcname); - int n, i; - int amount; + const char* npcname = script_getstr(st, 2); + struct npc_data* nd = npc_name2id(npcname); + int n, i; + int amount; - if (!nd || (nd->subtype != SHOP && nd->subtype != CASHSHOP)) { - //Not found. - script_pushint(st,0); - return 0; - } + if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) + { //Not found. + script_pushint(st,0); + return 0; + } - // get the count of new entries - amount = (script_lastdata(st)-2)/2; + // get the count of new entries + amount = (script_lastdata(st)-2)/2; - // generate new shop item list - RECREATE(nd->u.shop.shop_item, struct npc_item_list, amount); - for (n = 0, i = 3; n < amount; n++, i+=2) { - nd->u.shop.shop_item[n].nameid = script_getnum(st,i); - nd->u.shop.shop_item[n].value = script_getnum(st,i+1); - } - nd->u.shop.count = n; + // generate new shop item list + RECREATE(nd->u.shop.shop_item, struct npc_item_list, amount); + for( n = 0, i = 3; n < amount; n++, i+=2 ) + { + nd->u.shop.shop_item[n].nameid = script_getnum(st,i); + nd->u.shop.shop_item[n].value = script_getnum(st,i+1); + } + nd->u.shop.count = n; - script_pushint(st,1); - return 0; + script_pushint(st,1); + return 0; } BUILDIN_FUNC(npcshopadditem) { - const char *npcname = script_getstr(st,2); - struct npc_data *nd = npc_name2id(npcname); - int n, i; - int amount; + const char* npcname = script_getstr(st,2); + struct npc_data* nd = npc_name2id(npcname); + int n, i; + int amount; - if (!nd || (nd->subtype != SHOP && nd->subtype != CASHSHOP)) { - //Not found. - script_pushint(st,0); - return 0; - } + if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) + { //Not found. + script_pushint(st,0); + return 0; + } - // get the count of new entries - amount = (script_lastdata(st)-2)/2; + // get the count of new entries + amount = (script_lastdata(st)-2)/2; - // append new items to existing shop item list - RECREATE(nd->u.shop.shop_item, struct npc_item_list, nd->u.shop.count+amount); - for (n = nd->u.shop.count, i = 3; n < nd->u.shop.count+amount; n++, i+=2) { - nd->u.shop.shop_item[n].nameid = script_getnum(st,i); - nd->u.shop.shop_item[n].value = script_getnum(st,i+1); - } - nd->u.shop.count = n; + // append new items to existing shop item list + RECREATE(nd->u.shop.shop_item, struct npc_item_list, nd->u.shop.count+amount); + for( n = nd->u.shop.count, i = 3; n < nd->u.shop.count+amount; n++, i+=2 ) + { + nd->u.shop.shop_item[n].nameid = script_getnum(st,i); + nd->u.shop.shop_item[n].value = script_getnum(st,i+1); + } + nd->u.shop.count = n; - script_pushint(st,1); - return 0; + script_pushint(st,1); + return 0; } BUILDIN_FUNC(npcshopdelitem) { - const char *npcname = script_getstr(st,2); - struct npc_data *nd = npc_name2id(npcname); - unsigned int nameid; - int n, i; - int amount; - int size; + const char* npcname = script_getstr(st,2); + struct npc_data* nd = npc_name2id(npcname); + unsigned int nameid; + int n, i; + int amount; + int size; - if (!nd || (nd->subtype != SHOP && nd->subtype != CASHSHOP)) { - //Not found. - script_pushint(st,0); - return 0; - } + if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) + { //Not found. + script_pushint(st,0); + return 0; + } - amount = script_lastdata(st)-2; - size = nd->u.shop.count; + amount = script_lastdata(st)-2; + size = nd->u.shop.count; - // remove specified items from the shop item list - for (i = 3; i < 3 + amount; i++) { - nameid = script_getnum(st,i); + // remove specified items from the shop item list + for( i = 3; i < 3 + amount; i++ ) + { + nameid = script_getnum(st,i); - ARR_FIND(0, size, n, nd->u.shop.shop_item[n].nameid == nameid); - if (n < size) { - memmove(&nd->u.shop.shop_item[n], &nd->u.shop.shop_item[n+1], sizeof(nd->u.shop.shop_item[0])*(size-n)); - size--; - } - } + ARR_FIND( 0, size, n, nd->u.shop.shop_item[n].nameid == nameid ); + if( n < size ) + { + memmove(&nd->u.shop.shop_item[n], &nd->u.shop.shop_item[n+1], sizeof(nd->u.shop.shop_item[0])*(size-n)); + size--; + } + } - RECREATE(nd->u.shop.shop_item, struct npc_item_list, size); - nd->u.shop.count = size; + RECREATE(nd->u.shop.shop_item, struct npc_item_list, size); + nd->u.shop.count = size; - script_pushint(st,1); - return 0; + script_pushint(st,1); + return 0; } //Sets a script to attach to a shop npc. BUILDIN_FUNC(npcshopattach) { - const char *npcname = script_getstr(st,2); - struct npc_data *nd = npc_name2id(npcname); - int flag = 1; + const char* npcname = script_getstr(st,2); + struct npc_data* nd = npc_name2id(npcname); + int flag = 1; - if (script_hasdata(st,3)) - flag = script_getnum(st,3); + if( script_hasdata(st,3) ) + flag = script_getnum(st,3); - if (!nd || nd->subtype != SHOP) { - //Not found. - script_pushint(st,0); - return 0; - } + if( !nd || nd->subtype != SHOP ) + { //Not found. + script_pushint(st,0); + return 0; + } - if (flag) - nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); - else - nd->master_nd = NULL; + if (flag) + nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); + else + nd->master_nd = NULL; - script_pushint(st,1); - return 0; + script_pushint(st,1); + return 0; } /*========================================== * Returns some values of an item [Lupus] * Price, Weight, etc... - setitemscript(itemID,"{new item bonus script}",[n]); + setitemscript(itemID,"{new item bonus script}",[n]); Where n: - 0 - script - 1 - Equip script - 2 - Unequip script + 0 - script + 1 - Equip script + 2 - Unequip script *------------------------------------------*/ BUILDIN_FUNC(setitemscript) { - int item_id,n=0; - const char *script; - struct item_data *i_data; - struct script_code **dstscript; - - item_id = script_getnum(st,2); - script = script_getstr(st,3); - if (script_hasdata(st,4)) - n=script_getnum(st,4); - i_data = itemdb_exists(item_id); - - if (!i_data || script==NULL || (script[0] && script[0]!='{')) { - script_pushint(st,0); - return 0; - } - switch (n) { - case 2: - dstscript = &i_data->unequip_script; - break; - case 1: - dstscript = &i_data->equip_script; - break; - default: - dstscript = &i_data->script; - break; - } - if (*dstscript) - script_free_code(*dstscript); - - *dstscript = script[0] ? parse_script(script, "script_setitemscript", 0, 0) : NULL; - script_pushint(st,1); - return 0; + int item_id,n=0; + const char *script; + struct item_data *i_data; + struct script_code **dstscript; + + item_id = script_getnum(st,2); + script = script_getstr(st,3); + if( script_hasdata(st,4) ) + n=script_getnum(st,4); + i_data = itemdb_exists(item_id); + + if (!i_data || script==NULL || ( script[0] && script[0]!='{' )) { + script_pushint(st,0); + return 0; + } + switch (n) { + case 2: + dstscript = &i_data->unequip_script; + break; + case 1: + dstscript = &i_data->equip_script; + break; + default: + dstscript = &i_data->script; + break; + } + if(*dstscript) + script_free_code(*dstscript); + + *dstscript = script[0] ? parse_script(script, "script_setitemscript", 0, 0) : NULL; + script_pushint(st,1); + return 0; } /* Work In Progress [Lupus] BUILDIN_FUNC(addmonsterdrop) { - int class_,item_id,chance; - class_=script_getnum(st,2); - item_id=script_getnum(st,3); - chance=script_getnum(st,4); - if(class_>1000 && item_id>500 && chance>0) { - script_pushint(st,1); - } else { - script_pushint(st,0); - } + int class_,item_id,chance; + class_=script_getnum(st,2); + item_id=script_getnum(st,3); + chance=script_getnum(st,4); + if(class_>1000 && item_id>500 && chance>0) { + script_pushint(st,1); + } else { + script_pushint(st,0); + } } BUILDIN_FUNC(delmonsterdrop) { - int class_,item_id; - class_=script_getnum(st,2); - item_id=script_getnum(st,3); - if(class_>1000 && item_id>500) { - script_pushint(st,1); - } else { - script_pushint(st,0); - } + int class_,item_id; + class_=script_getnum(st,2); + item_id=script_getnum(st,3); + if(class_>1000 && item_id>500) { + script_pushint(st,1); + } else { + script_pushint(st,0); + } } */ /*========================================== * Returns some values of a monster [Lupus] * Name, Level, race, size, etc... - getmonsterinfo(monsterID,queryIndex); + getmonsterinfo(monsterID,queryIndex); *------------------------------------------*/ BUILDIN_FUNC(getmonsterinfo) { - struct mob_db *mob; - int mob_id; - - mob_id = script_getnum(st,2); - if (!mobdb_checkid(mob_id)) { - ShowError("buildin_getmonsterinfo: Wrong Monster ID: %i\n", mob_id); - if (!script_getnum(st,3)) //requested a string - script_pushconststr(st,"null"); - else - script_pushint(st,-1); - return -1; - } - mob = mob_db(mob_id); - switch (script_getnum(st,3)) { - case 0: - script_pushstrcopy(st,mob->jname); - break; - case 1: - script_pushint(st,mob->lv); - break; - case 2: - script_pushint(st,mob->status.max_hp); - break; - case 3: - script_pushint(st,mob->base_exp); - break; - case 4: - script_pushint(st,mob->job_exp); - break; - case 5: - script_pushint(st,mob->status.rhw.atk); - break; - case 6: - script_pushint(st,mob->status.rhw.atk2); - break; - case 7: - script_pushint(st,mob->status.def); - break; - case 8: - script_pushint(st,mob->status.mdef); - break; - case 9: - script_pushint(st,mob->status.str); - break; - case 10: - script_pushint(st,mob->status.agi); - break; - case 11: - script_pushint(st,mob->status.vit); - break; - case 12: - script_pushint(st,mob->status.int_); - break; - case 13: - script_pushint(st,mob->status.dex); - break; - case 14: - script_pushint(st,mob->status.luk); - break; - case 15: - script_pushint(st,mob->status.rhw.range); - break; - case 16: - script_pushint(st,mob->range2); - break; - case 17: - script_pushint(st,mob->range3); - break; - case 18: - script_pushint(st,mob->status.size); - break; - case 19: - script_pushint(st,mob->status.race); - break; - case 20: - script_pushint(st,mob->status.def_ele); - break; - case 21: - script_pushint(st,mob->status.mode); - break; - case 22: - script_pushint(st,mob->mexp); - break; - default: - script_pushint(st,-1); //wrong Index - } - return 0; + struct mob_db *mob; + int mob_id; + + mob_id = script_getnum(st,2); + if (!mobdb_checkid(mob_id)) { + ShowError("buildin_getmonsterinfo: Wrong Monster ID: %i\n", mob_id); + if ( !script_getnum(st,3) ) //requested a string + script_pushconststr(st,"null"); + else + script_pushint(st,-1); + return -1; + } + mob = mob_db(mob_id); + switch ( script_getnum(st,3) ) { + case 0: script_pushstrcopy(st,mob->jname); break; + case 1: script_pushint(st,mob->lv); break; + case 2: script_pushint(st,mob->status.max_hp); break; + case 3: script_pushint(st,mob->base_exp); break; + case 4: script_pushint(st,mob->job_exp); break; + case 5: script_pushint(st,mob->status.rhw.atk); break; + case 6: script_pushint(st,mob->status.rhw.atk2); break; + case 7: script_pushint(st,mob->status.def); break; + case 8: script_pushint(st,mob->status.mdef); break; + case 9: script_pushint(st,mob->status.str); break; + case 10: script_pushint(st,mob->status.agi); break; + case 11: script_pushint(st,mob->status.vit); break; + case 12: script_pushint(st,mob->status.int_); break; + case 13: script_pushint(st,mob->status.dex); break; + case 14: script_pushint(st,mob->status.luk); break; + case 15: script_pushint(st,mob->status.rhw.range); break; + case 16: script_pushint(st,mob->range2); break; + case 17: script_pushint(st,mob->range3); break; + case 18: script_pushint(st,mob->status.size); break; + case 19: script_pushint(st,mob->status.race); break; + case 20: script_pushint(st,mob->status.def_ele); break; + case 21: script_pushint(st,mob->status.mode); break; + case 22: script_pushint(st,mob->mexp); break; + default: script_pushint(st,-1); //wrong Index + } + return 0; } BUILDIN_FUNC(checkvending) // check vending [Nab4] { - TBL_PC *sd = NULL; + TBL_PC *sd = NULL; - if (script_hasdata(st,2)) - sd = map_nick2sd(script_getstr(st,2)); - else - sd = script_rid2sd(st); + if(script_hasdata(st,2)) + sd = map_nick2sd(script_getstr(st,2)); + else + sd = script_rid2sd(st); - if (sd) - script_pushint(st, sd->state.autotrade ? 2 : sd->state.vending); - else - script_pushint(st,0); + if(sd) + script_pushint(st, sd->state.autotrade ? 2 : sd->state.vending); + else + script_pushint(st,0); - return 0; + return 0; } BUILDIN_FUNC(checkchatting) // check chatting [Marka] { - TBL_PC *sd = NULL; + TBL_PC *sd = NULL; - if (script_hasdata(st,2)) - sd = map_nick2sd(script_getstr(st,2)); - else - sd = script_rid2sd(st); + if(script_hasdata(st,2)) + sd = map_nick2sd(script_getstr(st,2)); + else + sd = script_rid2sd(st); - if (sd) - script_pushint(st,(sd->chatID != 0)); - else - script_pushint(st,0); + if(sd) + script_pushint(st,(sd->chatID != 0)); + else + script_pushint(st,0); - return 0; + return 0; } BUILDIN_FUNC(searchitem) { - struct script_data *data = script_getdata(st, 2); - const char *itemname = script_getstr(st,3); - struct item_data *items[MAX_SEARCH]; - int count; - - char *name; - int32 start; - int32 id; - int32 i; - TBL_PC *sd = NULL; - - if ((items[0] = itemdb_exists(atoi(itemname)))) - count = 1; - else { - count = itemdb_searchname_array(items, ARRAYLENGTH(items), itemname); - if (count > MAX_SEARCH) count = MAX_SEARCH; - } - - if (!count) { - script_pushint(st, 0); - return 0; - } - - if (!data_isreference(data)) { - ShowError("script:searchitem: not a variable\n"); - script_reportdata(data); - st->state = END; - return 1;// not a variable - } - - id = reference_getid(data); - start = reference_getindex(data); - name = reference_getname(data); - if (not_array_variable(*name)) { - ShowError("script:searchitem: illegal scope\n"); - script_reportdata(data); - st->state = END; - return 1;// not supported - } - - if (not_server_variable(*name)) { - sd = script_rid2sd(st); - if (sd == NULL) - return 0;// no player attached - } - - if (is_string_variable(name)) { - // string array - ShowError("script:searchitem: not an integer array reference\n"); - script_reportdata(data); - st->state = END; - return 1;// not supported - } - - for (i = 0; i < count; ++start, ++i) { - // Set array - void *v = (void *)__64BPRTSIZE(items[i]->nameid); - set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data)); - } - - script_pushint(st, count); - return 0; + struct script_data* data = script_getdata(st, 2); + const char *itemname = script_getstr(st,3); + struct item_data *items[MAX_SEARCH]; + int count; + + char* name; + int32 start; + int32 id; + int32 i; + TBL_PC* sd = NULL; + + if ((items[0] = itemdb_exists(atoi(itemname)))) + count = 1; + else { + count = itemdb_searchname_array(items, ARRAYLENGTH(items), itemname); + if (count > MAX_SEARCH) count = MAX_SEARCH; + } + + if (!count) { + script_pushint(st, 0); + return 0; + } + + if( !data_isreference(data) ) + { + ShowError("script:searchitem: not a variable\n"); + script_reportdata(data); + st->state = END; + return 1;// not a variable + } + + id = reference_getid(data); + start = reference_getindex(data); + name = reference_getname(data); + if( not_array_variable(*name) ) + { + ShowError("script:searchitem: illegal scope\n"); + script_reportdata(data); + st->state = END; + return 1;// not supported + } + + if( not_server_variable(*name) ) + { + sd = script_rid2sd(st); + if( sd == NULL ) + return 0;// no player attached + } + + if( is_string_variable(name) ) + {// string array + ShowError("script:searchitem: not an integer array reference\n"); + script_reportdata(data); + st->state = END; + return 1;// not supported + } + + for( i = 0; i < count; ++start, ++i ) + {// Set array + void* v = (void*)__64BPRTSIZE(items[i]->nameid); + set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data)); + } + + script_pushint(st, count); + return 0; } int axtoi(const char *hexStg) { - int n = 0; // position in string - int m = 0; // position in digit[] to shift - int count; // loop index - int intValue = 0; // integer value of hex string - int digit[11]; // hold values to convert - while (n < 10) { - if (hexStg[n]=='\0') - break; - if (hexStg[n] > 0x29 && hexStg[n] < 0x40) //if 0 to 9 - digit[n] = hexStg[n] & 0x0f; //convert to int - else if (hexStg[n] >='a' && hexStg[n] <= 'f') //if a to f - digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int - else if (hexStg[n] >='A' && hexStg[n] <= 'F') //if A to F - digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int - else break; - n++; - } - count = n; - m = n - 1; - n = 0; - while (n < count) { - // digit[n] is value of hex digit at position n - // (m << 2) is the number of positions to shift - // OR the bits into return value - intValue = intValue | (digit[n] << (m << 2)); - m--; // adjust the position to set - n++; // next digit to process - } - return (intValue); + int n = 0; // position in string + int m = 0; // position in digit[] to shift + int count; // loop index + int intValue = 0; // integer value of hex string + int digit[11]; // hold values to convert + while (n < 10) { + if (hexStg[n]=='\0') + break; + if (hexStg[n] > 0x29 && hexStg[n] < 0x40 ) //if 0 to 9 + digit[n] = hexStg[n] & 0x0f; //convert to int + else if (hexStg[n] >='a' && hexStg[n] <= 'f') //if a to f + digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int + else if (hexStg[n] >='A' && hexStg[n] <= 'F') //if A to F + digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int + else break; + n++; + } + count = n; + m = n - 1; + n = 0; + while(n < count) { + // digit[n] is value of hex digit at position n + // (m << 2) is the number of positions to shift + // OR the bits into return value + intValue = intValue | (digit[n] << (m << 2)); + m--; // adjust the position to set + n++; // next digit to process + } + return (intValue); } // [Lance] Hex string to integer converter BUILDIN_FUNC(axtoi) { - const char *hex = script_getstr(st,2); - script_pushint(st,axtoi(hex)); - return 0; + const char *hex = script_getstr(st,2); + script_pushint(st,axtoi(hex)); + return 0; } // [zBuffer] List of player cont commands ---> BUILDIN_FUNC(rid2name) { - struct block_list *bl = NULL; - int rid = script_getnum(st,2); - if ((bl = map_id2bl(rid))) { - switch (bl->type) { - case BL_MOB: - script_pushstrcopy(st,((TBL_MOB *)bl)->name); - break; - case BL_PC: - script_pushstrcopy(st,((TBL_PC *)bl)->status.name); - break; - case BL_NPC: - script_pushstrcopy(st,((TBL_NPC *)bl)->exname); - break; - case BL_PET: - script_pushstrcopy(st,((TBL_PET *)bl)->pet.name); - break; - case BL_HOM: - script_pushstrcopy(st,((TBL_HOM *)bl)->homunculus.name); - break; - case BL_MER: - script_pushstrcopy(st,((TBL_MER *)bl)->db->name); - break; - default: - ShowError("buildin_rid2name: BL type unknown.\n"); - script_pushconststr(st,""); - break; - } - } else { - ShowError("buildin_rid2name: invalid RID\n"); - script_pushconststr(st,"(null)"); - } - return 0; + struct block_list *bl = NULL; + int rid = script_getnum(st,2); + if((bl = map_id2bl(rid))) + { + switch(bl->type) { + case BL_MOB: script_pushstrcopy(st,((TBL_MOB*)bl)->name); break; + case BL_PC: script_pushstrcopy(st,((TBL_PC*)bl)->status.name); break; + case BL_NPC: script_pushstrcopy(st,((TBL_NPC*)bl)->exname); break; + case BL_PET: script_pushstrcopy(st,((TBL_PET*)bl)->pet.name); break; + case BL_HOM: script_pushstrcopy(st,((TBL_HOM*)bl)->homunculus.name); break; + case BL_MER: script_pushstrcopy(st,((TBL_MER*)bl)->db->name); break; + default: + ShowError("buildin_rid2name: BL type unknown.\n"); + script_pushconststr(st,""); + break; + } + } else { + ShowError("buildin_rid2name: invalid RID\n"); + script_pushconststr(st,"(null)"); + } + return 0; } BUILDIN_FUNC(pcblockmove) { - int id, flag; - TBL_PC *sd = NULL; + int id, flag; + TBL_PC *sd = NULL; - id = script_getnum(st,2); - flag = script_getnum(st,3); + id = script_getnum(st,2); + flag = script_getnum(st,3); - if (id) - sd = map_id2sd(id); - else - sd = script_rid2sd(st); + if(id) + sd = map_id2sd(id); + else + sd = script_rid2sd(st); - if (sd) - sd->state.blockedmove = flag > 0; + if(sd) + sd->state.blockedmove = flag > 0; - return 0; + return 0; } BUILDIN_FUNC(pcfollow) { - int id, targetid; - TBL_PC *sd = NULL; + int id, targetid; + TBL_PC *sd = NULL; - id = script_getnum(st,2); - targetid = script_getnum(st,3); + id = script_getnum(st,2); + targetid = script_getnum(st,3); - if (id) - sd = map_id2sd(id); - else - sd = script_rid2sd(st); + if(id) + sd = map_id2sd(id); + else + sd = script_rid2sd(st); - if (sd) - pc_follow(sd, targetid); + if(sd) + pc_follow(sd, targetid); return 0; } BUILDIN_FUNC(pcstopfollow) { - int id; - TBL_PC *sd = NULL; + int id; + TBL_PC *sd = NULL; - id = script_getnum(st,2); + id = script_getnum(st,2); - if (id) - sd = map_id2sd(id); - else - sd = script_rid2sd(st); + if(id) + sd = map_id2sd(id); + else + sd = script_rid2sd(st); - if (sd) - pc_stop_following(sd); + if(sd) + pc_stop_following(sd); - return 0; + return 0; } // <--- [zBuffer] List of player cont commands // [zBuffer] List of mob control commands ---> @@ -15331,21 +15171,26 @@ BUILDIN_FUNC(pcstopfollow) /// unitwalk(<unit_id>,<map_id>) -> <bool> BUILDIN_FUNC(unitwalk) { - struct block_list *bl; - - bl = map_id2bl(script_getnum(st,2)); - if (bl == NULL) { - script_pushint(st, 0); - } else if (script_hasdata(st,4)) { - int x = script_getnum(st,3); - int y = script_getnum(st,4); - script_pushint(st, unit_walktoxy(bl,x,y,0));// We'll use harder calculations. - } else { - int map_id = script_getnum(st,3); - script_pushint(st, unit_walktobl(bl,map_id2bl(map_id),65025,1)); - } + struct block_list* bl; - return 0; + bl = map_id2bl(script_getnum(st,2)); + if( bl == NULL ) + { + script_pushint(st, 0); + } + else if( script_hasdata(st,4) ) + { + int x = script_getnum(st,3); + int y = script_getnum(st,4); + script_pushint(st, unit_walktoxy(bl,x,y,0));// We'll use harder calculations. + } + else + { + int map_id = script_getnum(st,3); + script_pushint(st, unit_walktobl(bl,map_id2bl(map_id),65025,1)); + } + + return 0; } /// Kills the unit @@ -15353,11 +15198,11 @@ BUILDIN_FUNC(unitwalk) /// unitkill <unit_id>; BUILDIN_FUNC(unitkill) { - struct block_list *bl = map_id2bl(script_getnum(st,2)); - if (bl != NULL) - status_kill(bl); + struct block_list* bl = map_id2bl(script_getnum(st,2)); + if( bl != NULL ) + status_kill(bl); - return 0; + return 0; } /// Warps the unit to the target position in the target map @@ -15366,34 +15211,34 @@ BUILDIN_FUNC(unitkill) /// unitwarp(<unit_id>,"<map name>",<x>,<y>) -> <bool> BUILDIN_FUNC(unitwarp) { - int unit_id; - int map; - short x; - short y; - struct block_list *bl; - const char *mapname; - - unit_id = script_getnum(st,2); - mapname = script_getstr(st, 3); - x = (short)script_getnum(st,4); - y = (short)script_getnum(st,5); - - if (!unit_id) //Warp the script's runner - bl = map_id2bl(st->rid); - else - bl = map_id2bl(unit_id); - - if (strcmp(mapname,"this") == 0) - map = bl?bl->m:-1; - else - map = map_mapname2mapid(mapname); - - if (map >= 0 && bl != NULL) - script_pushint(st, unit_warp(bl,map,x,y,CLR_OUTSIGHT)); - else - script_pushint(st, 0); + int unit_id; + int map; + short x; + short y; + struct block_list* bl; + const char *mapname; - return 0; + unit_id = script_getnum(st,2); + mapname = script_getstr(st, 3); + x = (short)script_getnum(st,4); + y = (short)script_getnum(st,5); + + if (!unit_id) //Warp the script's runner + bl = map_id2bl(st->rid); + else + bl = map_id2bl(unit_id); + + if( strcmp(mapname,"this") == 0 ) + map = bl?bl->m:-1; + else + map = map_mapname2mapid(mapname); + + if( map >= 0 && bl != NULL ) + script_pushint(st, unit_warp(bl,map,x,y,CLR_OUTSIGHT)); + else + script_pushint(st, 0); + + return 0; } /// Makes the unit attack the target. @@ -15405,54 +15250,57 @@ BUILDIN_FUNC(unitwarp) /// unitattack(<unit_id>,<target_id>{,<action type>}) -> <bool> BUILDIN_FUNC(unitattack) { - struct block_list *unit_bl; - struct block_list *target_bl = NULL; - struct script_data *data; - int actiontype = 0; - - // get unit - unit_bl = map_id2bl(script_getnum(st,2)); - if (unit_bl == NULL) { - script_pushint(st, 0); - return 0; - } - - data = script_getdata(st, 3); - get_val(st, data); - if (data_isstring(data)) { - TBL_PC *sd = map_nick2sd(conv_str(st, data)); - if (sd != NULL) - target_bl = &sd->bl; - } else - target_bl = map_id2bl(conv_num(st, data)); - // request the attack - if (target_bl == NULL) { - script_pushint(st, 0); - return 0; - } - - // get actiontype - if (script_hasdata(st,4)) - actiontype = script_getnum(st,4); - - switch (unit_bl->type) { - case BL_PC: - clif_parse_ActionRequest_sub(((TBL_PC *)unit_bl), actiontype > 0 ? 0x07 : 0x00, target_bl->id, gettick()); - script_pushint(st, 1); - return 0; - case BL_MOB: - ((TBL_MOB *)unit_bl)->target_id = target_bl->id; - break; - case BL_PET: - ((TBL_PET *)unit_bl)->target_id = target_bl->id; - break; - default: - ShowError("script:unitattack: unsupported source unit type %d\n", unit_bl->type); - script_pushint(st, 0); - return 1; - } - script_pushint(st, unit_walktobl(unit_bl, target_bl, 65025, 2)); - return 0; + struct block_list* unit_bl; + struct block_list* target_bl = NULL; + struct script_data* data; + int actiontype = 0; + + // get unit + unit_bl = map_id2bl(script_getnum(st,2)); + if( unit_bl == NULL ) { + script_pushint(st, 0); + return 0; + } + + data = script_getdata(st, 3); + get_val(st, data); + if( data_isstring(data) ) + { + TBL_PC* sd = map_nick2sd(conv_str(st, data)); + if( sd != NULL ) + target_bl = &sd->bl; + } else + target_bl = map_id2bl(conv_num(st, data)); + // request the attack + if( target_bl == NULL ) + { + script_pushint(st, 0); + return 0; + } + + // get actiontype + if( script_hasdata(st,4) ) + actiontype = script_getnum(st,4); + + switch( unit_bl->type ) + { + case BL_PC: + clif_parse_ActionRequest_sub(((TBL_PC *)unit_bl), actiontype > 0 ? 0x07 : 0x00, target_bl->id, gettick()); + script_pushint(st, 1); + return 0; + case BL_MOB: + ((TBL_MOB *)unit_bl)->target_id = target_bl->id; + break; + case BL_PET: + ((TBL_PET *)unit_bl)->target_id = target_bl->id; + break; + default: + ShowError("script:unitattack: unsupported source unit type %d\n", unit_bl->type); + script_pushint(st, 0); + return 1; + } + script_pushint(st, unit_walktobl(unit_bl, target_bl, 65025, 2)); + return 0; } /// Makes the unit stop attacking and moving @@ -15460,20 +15308,21 @@ BUILDIN_FUNC(unitattack) /// unitstop <unit_id>; BUILDIN_FUNC(unitstop) { - int unit_id; - struct block_list *bl; + int unit_id; + struct block_list* bl; - unit_id = script_getnum(st,2); + unit_id = script_getnum(st,2); - bl = map_id2bl(unit_id); - if (bl != NULL) { - unit_stop_attack(bl); - unit_stop_walking(bl,4); - if (bl->type == BL_MOB) - ((TBL_MOB *)bl)->target_id = 0; - } + bl = map_id2bl(unit_id); + if( bl != NULL ) + { + unit_stop_attack(bl); + unit_stop_walking(bl,4); + if( bl->type == BL_MOB ) + ((TBL_MOB*)bl)->target_id = 0; + } - return 0; + return 0; } /// Makes the unit say the message @@ -15481,25 +15330,26 @@ BUILDIN_FUNC(unitstop) /// unittalk <unit_id>,"<message>"; BUILDIN_FUNC(unittalk) { - int unit_id; - const char *message; - struct block_list *bl; - - unit_id = script_getnum(st,2); - message = script_getstr(st, 3); - - bl = map_id2bl(unit_id); - if (bl != NULL) { - struct StringBuf sbuf; - StringBuf_Init(&sbuf); - StringBuf_Printf(&sbuf, "%s : %s", status_get_name(bl), message); - clif_message(bl, StringBuf_Value(&sbuf)); - if (bl->type == BL_PC) - clif_displaymessage(((TBL_PC *)bl)->fd, StringBuf_Value(&sbuf)); - StringBuf_Destroy(&sbuf); - } + int unit_id; + const char* message; + struct block_list* bl; - return 0; + unit_id = script_getnum(st,2); + message = script_getstr(st, 3); + + bl = map_id2bl(unit_id); + if( bl != NULL ) + { + struct StringBuf sbuf; + StringBuf_Init(&sbuf); + StringBuf_Printf(&sbuf, "%s : %s", status_get_name(bl), message); + clif_message(bl, StringBuf_Value(&sbuf)); + if( bl->type == BL_PC ) + clif_displaymessage(((TBL_PC*)bl)->fd, StringBuf_Value(&sbuf)); + StringBuf_Destroy(&sbuf); + } + + return 0; } /// Makes the unit do an emotion @@ -15509,17 +15359,17 @@ BUILDIN_FUNC(unittalk) /// @see e_* in const.txt BUILDIN_FUNC(unitemote) { - int unit_id; - int emotion; - struct block_list *bl; + int unit_id; + int emotion; + struct block_list* bl; - unit_id = script_getnum(st,2); - emotion = script_getnum(st,3); - bl = map_id2bl(unit_id); - if (bl != NULL) - clif_emotion(bl, emotion); + unit_id = script_getnum(st,2); + emotion = script_getnum(st,3); + bl = map_id2bl(unit_id); + if( bl != NULL ) + clif_emotion(bl, emotion); - return 0; + return 0; } /// Makes the unit cast the skill on the target or self if no target is specified @@ -15528,22 +15378,22 @@ BUILDIN_FUNC(unitemote) /// unitskilluseid <unit_id>,"<skill name>",<skill_lv>{,<target_id>}; BUILDIN_FUNC(unitskilluseid) { - int unit_id; - int skill_id; - int skill_lv; - int target_id; - struct block_list *bl; + int unit_id; + int skill_id; + int skill_lv; + int target_id; + struct block_list* bl; - unit_id = script_getnum(st,2); - skill_id = (script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3)); - skill_lv = script_getnum(st,4); - target_id = (script_hasdata(st,5) ? script_getnum(st,5) : unit_id); + unit_id = script_getnum(st,2); + skill_id = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) ); + skill_lv = script_getnum(st,4); + target_id = ( script_hasdata(st,5) ? script_getnum(st,5) : unit_id ); - bl = map_id2bl(unit_id); - if (bl != NULL) - unit_skilluse_id(bl, target_id, skill_id, skill_lv); + bl = map_id2bl(unit_id); + if( bl != NULL ) + unit_skilluse_id(bl, target_id, skill_id, skill_lv); - return 0; + return 0; } /// Makes the unit cast the skill on the target position. @@ -15552,24 +15402,24 @@ BUILDIN_FUNC(unitskilluseid) /// unitskillusepos <unit_id>,"<skill name>",<skill_lv>,<target_x>,<target_y>; BUILDIN_FUNC(unitskillusepos) { - int unit_id; - int skill_id; - int skill_lv; - int skill_x; - int skill_y; - struct block_list *bl; + int unit_id; + int skill_id; + int skill_lv; + int skill_x; + int skill_y; + struct block_list* bl; - unit_id = script_getnum(st,2); - skill_id = (script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3)); - skill_lv = script_getnum(st,4); - skill_x = script_getnum(st,5); - skill_y = script_getnum(st,6); + unit_id = script_getnum(st,2); + skill_id = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) ); + skill_lv = script_getnum(st,4); + skill_x = script_getnum(st,5); + skill_y = script_getnum(st,6); - bl = map_id2bl(unit_id); - if (bl != NULL) - unit_skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv); + bl = map_id2bl(unit_id); + if( bl != NULL ) + unit_skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv); - return 0; + return 0; } // <--- [zBuffer] List of mob control commands @@ -15579,25 +15429,27 @@ BUILDIN_FUNC(unitskillusepos) /// sleep <mili seconds>; BUILDIN_FUNC(sleep) { - int ticks; + int ticks; - ticks = script_getnum(st,2); + ticks = script_getnum(st,2); - // detach the player - script_detach_rid(st); + // detach the player + script_detach_rid(st); - if (ticks <= 0) { - // do nothing - } else if (st->sleep.tick == 0) { - // sleep for the target amount of time - st->state = RERUNLINE; - st->sleep.tick = ticks; - } else { - // sleep time is over - st->state = RUN; - st->sleep.tick = 0; - } - return 0; + if( ticks <= 0 ) + {// do nothing + } + else if( st->sleep.tick == 0 ) + {// sleep for the target amount of time + st->state = RERUNLINE; + st->sleep.tick = ticks; + } + else + {// sleep time is over + st->state = RUN; + st->sleep.tick = 0; + } + return 0; } /// Pauses the execution of the script, keeping the player attached @@ -15606,24 +15458,26 @@ BUILDIN_FUNC(sleep) /// sleep2(<mili secconds>) -> <bool> BUILDIN_FUNC(sleep2) { - int ticks; - - ticks = script_getnum(st,2); - - if (ticks <= 0) { - // do nothing - script_pushint(st, (map_id2sd(st->rid)!=NULL)); - } else if (!st->sleep.tick) { - // sleep for the target amount of time - st->state = RERUNLINE; - st->sleep.tick = ticks; - } else { - // sleep time is over - st->state = RUN; - st->sleep.tick = 0; - script_pushint(st, (map_id2sd(st->rid)!=NULL)); - } - return 0; + int ticks; + + ticks = script_getnum(st,2); + + if( ticks <= 0 ) + {// do nothing + script_pushint(st, (map_id2sd(st->rid)!=NULL)); + } + else if( !st->sleep.tick ) + {// sleep for the target amount of time + st->state = RERUNLINE; + st->sleep.tick = ticks; + } + else + {// sleep time is over + st->state = RUN; + st->sleep.tick = 0; + script_pushint(st, (map_id2sd(st->rid)!=NULL)); + } + return 0; } /// Awakes all the sleep timers of the target npc @@ -15631,43 +15485,46 @@ BUILDIN_FUNC(sleep2) /// awake "<npc name>"; BUILDIN_FUNC(awake) { - struct npc_data *nd; - struct linkdb_node *node = (struct linkdb_node *)sleep_db; - - nd = npc_name2id(script_getstr(st, 2)); - if (nd == NULL) { - ShowError("awake: NPC \"%s\" not found\n", script_getstr(st, 2)); - return 1; - } - - while (node) { - if ((int)__64BPRTSIZE(node->key) == nd->bl.id) { - // sleep timer for the npc - struct script_state *tst = (struct script_state *)node->data; - TBL_PC *sd = map_id2sd(tst->rid); - - if (tst->sleep.timer == INVALID_TIMER) { - // already awake ??? - node = node->next; - continue; - } - if ((sd && sd->status.char_id != tst->sleep.charid) || (tst->rid && !sd)) { - // char not online anymore / another char of the same account is online - Cancel execution - tst->state = END; - tst->rid = 0; - } - - delete_timer(tst->sleep.timer, run_script_timer); - node = script_erase_sleepdb(node); - tst->sleep.timer = INVALID_TIMER; - if (tst->state != RERUNLINE) - tst->sleep.tick = 0; - run_script_main(tst); - } else { - node = node->next; - } - } - return 0; + struct npc_data* nd; + struct linkdb_node *node = (struct linkdb_node *)sleep_db; + + nd = npc_name2id(script_getstr(st, 2)); + if( nd == NULL ) { + ShowError("awake: NPC \"%s\" not found\n", script_getstr(st, 2)); + return 1; + } + + while( node ) + { + if( (int)__64BPRTSIZE(node->key) == nd->bl.id ) + {// sleep timer for the npc + struct script_state* tst = (struct script_state*)node->data; + TBL_PC* sd = map_id2sd(tst->rid); + + if( tst->sleep.timer == INVALID_TIMER ) + {// already awake ??? + node = node->next; + continue; + } + if( (sd && sd->status.char_id != tst->sleep.charid) || (tst->rid && !sd)) + {// char not online anymore / another char of the same account is online - Cancel execution + tst->state = END; + tst->rid = 0; + } + + delete_timer(tst->sleep.timer, run_script_timer); + node = script_erase_sleepdb(node); + tst->sleep.timer = INVALID_TIMER; + if(tst->state != RERUNLINE) + tst->sleep.tick = 0; + run_script_main(tst); + } + else + { + node = node->next; + } + } + return 0; } /// Returns a reference to a variable of the target NPC. @@ -15676,41 +15533,41 @@ BUILDIN_FUNC(awake) /// getvariableofnpc(<variable>, "<npc name>") -> <reference> BUILDIN_FUNC(getvariableofnpc) { - struct script_data *data; - const char *name; - struct npc_data *nd; - - data = script_getdata(st,2); - if (!data_isreference(data)) { - // Not a reference (aka varaible name) - ShowError("script:getvariableofnpc: not a variable\n"); - script_reportdata(data); - script_pushnil(st); - st->state = END; - return 1; - } - - name = reference_getname(data); - if (*name != '.' || name[1] == '@') { - // not a npc variable - ShowError("script:getvariableofnpc: invalid scope (not npc variable)\n"); - script_reportdata(data); - script_pushnil(st); - st->state = END; - return 1; - } - - nd = npc_name2id(script_getstr(st,3)); - if (nd == NULL || nd->subtype != SCRIPT || nd->u.scr.script == NULL) { - // NPC not found or has no script - ShowError("script:getvariableofnpc: can't find npc %s\n", script_getstr(st,3)); - script_pushnil(st); - st->state = END; - return 1; - } - - push_val2(st->stack, C_NAME, reference_getuid(data), &nd->u.scr.script->script_vars); - return 0; + struct script_data* data; + const char* name; + struct npc_data* nd; + + data = script_getdata(st,2); + if( !data_isreference(data) ) + {// Not a reference (aka varaible name) + ShowError("script:getvariableofnpc: not a variable\n"); + script_reportdata(data); + script_pushnil(st); + st->state = END; + return 1; + } + + name = reference_getname(data); + if( *name != '.' || name[1] == '@' ) + {// not a npc variable + ShowError("script:getvariableofnpc: invalid scope (not npc variable)\n"); + script_reportdata(data); + script_pushnil(st); + st->state = END; + return 1; + } + + nd = npc_name2id(script_getstr(st,3)); + if( nd == NULL || nd->subtype != SCRIPT || nd->u.scr.script == NULL ) + {// NPC not found or has no script + ShowError("script:getvariableofnpc: can't find npc %s\n", script_getstr(st,3)); + script_pushnil(st); + st->state = END; + return 1; + } + + push_val2(st->stack, C_NAME, reference_getuid(data), &nd->u.scr.script->script_vars ); + return 0; } /// Opens a warp portal. @@ -15721,62 +15578,63 @@ BUILDIN_FUNC(getvariableofnpc) /// @author blackhole89 BUILDIN_FUNC(warpportal) { - int spx; - int spy; - unsigned short mapindex; - int tpx; - int tpy; - struct skill_unit_group *group; - struct block_list *bl; - - bl = map_id2bl(st->oid); - if (bl == NULL) { - ShowError("script:warpportal: npc is needed\n"); - return 1; - } + int spx; + int spy; + unsigned short mapindex; + int tpx; + int tpy; + struct skill_unit_group* group; + struct block_list* bl; - spx = script_getnum(st,2); - spy = script_getnum(st,3); - mapindex = mapindex_name2id(script_getstr(st, 4)); - tpx = script_getnum(st,5); - tpy = script_getnum(st,6); + bl = map_id2bl(st->oid); + if( bl == NULL ) + { + ShowError("script:warpportal: npc is needed\n"); + return 1; + } - if (mapindex == 0) - return 0;// map not found + spx = script_getnum(st,2); + spy = script_getnum(st,3); + mapindex = mapindex_name2id(script_getstr(st, 4)); + tpx = script_getnum(st,5); + tpy = script_getnum(st,6); - group = skill_unitsetting(bl, AL_WARP, 4, spx, spy, 0); - if (group == NULL) - return 0;// failed - group->val2 = (tpx<<16) | tpy; - group->val3 = mapindex; + if( mapindex == 0 ) + return 0;// map not found - return 0; + group = skill_unitsetting(bl, AL_WARP, 4, spx, spy, 0); + if( group == NULL ) + return 0;// failed + group->val2 = (tpx<<16) | tpy; + group->val3 = mapindex; + + return 0; } BUILDIN_FUNC(openmail) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - mail_openmail(sd); + mail_openmail(sd); - return 0; + return 0; } BUILDIN_FUNC(openauction) { - TBL_PC *sd; + TBL_PC* sd; - sd = script_rid2sd(st); - if (sd == NULL) - return 0; + sd = script_rid2sd(st); + if( sd == NULL ) + return 0; - clif_Auction_openwindow(sd); + clif_Auction_openwindow(sd); - return 0; + return 0; } /// Retrieves the value of the specified flag of the specified cell. @@ -15786,14 +15644,14 @@ BUILDIN_FUNC(openauction) /// @see cell_chk* constants in const.txt for the types BUILDIN_FUNC(checkcell) { - int m = map_mapname2mapid(script_getstr(st,2)); - int x = script_getnum(st,3); - int y = script_getnum(st,4); - cell_chk type = (cell_chk)script_getnum(st,5); + int m = map_mapname2mapid(script_getstr(st,2)); + int x = script_getnum(st,3); + int y = script_getnum(st,4); + cell_chk type = (cell_chk)script_getnum(st,5); - script_pushint(st, map_getcell(m, x, y, type)); + script_pushint(st, map_getcell(m, x, y, type)); - return 0; + return 0; } /// Modifies flags of cells in the specified area. @@ -15803,24 +15661,24 @@ BUILDIN_FUNC(checkcell) /// @see cell_* constants in const.txt for the types BUILDIN_FUNC(setcell) { - int m = map_mapname2mapid(script_getstr(st,2)); - int x1 = script_getnum(st,3); - int y1 = script_getnum(st,4); - int x2 = script_getnum(st,5); - int y2 = script_getnum(st,6); - cell_t type = (cell_t)script_getnum(st,7); - bool flag = (bool)script_getnum(st,8); + int m = map_mapname2mapid(script_getstr(st,2)); + int x1 = script_getnum(st,3); + int y1 = script_getnum(st,4); + int x2 = script_getnum(st,5); + int y2 = script_getnum(st,6); + cell_t type = (cell_t)script_getnum(st,7); + bool flag = (bool)script_getnum(st,8); - int x,y; + int x,y; - if (x1 > x2) swap(x1,x2); - if (y1 > y2) swap(y1,y2); + if( x1 > x2 ) swap(x1,x2); + if( y1 > y2 ) swap(y1,y2); - for (y = y1; y <= y2; ++y) - for (x = x1; x <= x2; ++x) - map_setcell(m, x, y, type, flag); + for( y = y1; y <= y2; ++y ) + for( x = x1; x <= x2; ++x ) + map_setcell(m, x, y, type, flag); - return 0; + return 0; } /*========================================== @@ -15828,169 +15686,173 @@ BUILDIN_FUNC(setcell) *------------------------------------------*/ BUILDIN_FUNC(mercenary_create) { - struct map_session_data *sd; - int class_, contract_time; + struct map_session_data *sd; + int class_, contract_time; - if ((sd = script_rid2sd(st)) == NULL || sd->md || sd->status.mer_id != 0) - return 0; + if( (sd = script_rid2sd(st)) == NULL || sd->md || sd->status.mer_id != 0 ) + return 0; - class_ = script_getnum(st,2); + class_ = script_getnum(st,2); - if (!merc_class(class_)) - return 0; + if( !merc_class(class_) ) + return 0; - contract_time = script_getnum(st,3); - merc_create(sd, class_, contract_time); - return 0; + contract_time = script_getnum(st,3); + merc_create(sd, class_, contract_time); + return 0; } BUILDIN_FUNC(mercenary_heal) { - struct map_session_data *sd = script_rid2sd(st); - int hp, sp; + struct map_session_data *sd = script_rid2sd(st); + int hp, sp; - if (sd == NULL || sd->md == NULL) - return 0; - hp = script_getnum(st,2); - sp = script_getnum(st,3); + if( sd == NULL || sd->md == NULL ) + return 0; + hp = script_getnum(st,2); + sp = script_getnum(st,3); - status_heal(&sd->md->bl, hp, sp, 0); - return 0; + status_heal(&sd->md->bl, hp, sp, 0); + return 0; } BUILDIN_FUNC(mercenary_sc_start) { - struct map_session_data *sd = script_rid2sd(st); - enum sc_type type; - int tick, val1; + struct map_session_data *sd = script_rid2sd(st); + enum sc_type type; + int tick, val1; - if (sd == NULL || sd->md == NULL) - return 0; + if( sd == NULL || sd->md == NULL ) + return 0; - type = (sc_type)script_getnum(st,2); - tick = script_getnum(st,3); - val1 = script_getnum(st,4); + type = (sc_type)script_getnum(st,2); + tick = script_getnum(st,3); + val1 = script_getnum(st,4); - status_change_start(&sd->md->bl, type, 10000, val1, 0, 0, 0, tick, 2); - return 0; + status_change_start(&sd->md->bl, type, 10000, val1, 0, 0, 0, tick, 2); + return 0; } BUILDIN_FUNC(mercenary_get_calls) { - struct map_session_data *sd = script_rid2sd(st); - int guild; + struct map_session_data *sd = script_rid2sd(st); + int guild; - if (sd == NULL) - return 0; + if( sd == NULL ) + return 0; - guild = script_getnum(st,2); - switch (guild) { - case ARCH_MERC_GUILD: - script_pushint(st,sd->status.arch_calls); - break; - case SPEAR_MERC_GUILD: - script_pushint(st,sd->status.spear_calls); - break; - case SWORD_MERC_GUILD: - script_pushint(st,sd->status.sword_calls); - break; - default: - script_pushint(st,0); - break; - } + guild = script_getnum(st,2); + switch( guild ) + { + case ARCH_MERC_GUILD: + script_pushint(st,sd->status.arch_calls); + break; + case SPEAR_MERC_GUILD: + script_pushint(st,sd->status.spear_calls); + break; + case SWORD_MERC_GUILD: + script_pushint(st,sd->status.sword_calls); + break; + default: + script_pushint(st,0); + break; + } - return 0; + return 0; } BUILDIN_FUNC(mercenary_set_calls) { - struct map_session_data *sd = script_rid2sd(st); - int guild, value, *calls; + struct map_session_data *sd = script_rid2sd(st); + int guild, value, *calls; - if (sd == NULL) - return 0; + if( sd == NULL ) + return 0; - guild = script_getnum(st,2); - value = script_getnum(st,3); - - switch (guild) { - case ARCH_MERC_GUILD: - calls = &sd->status.arch_calls; - break; - case SPEAR_MERC_GUILD: - calls = &sd->status.spear_calls; - break; - case SWORD_MERC_GUILD: - calls = &sd->status.sword_calls; - break; - default: - return 0; // Invalid Guild - } + guild = script_getnum(st,2); + value = script_getnum(st,3); - *calls += value; - *calls = cap_value(*calls, 0, INT_MAX); + switch( guild ) + { + case ARCH_MERC_GUILD: + calls = &sd->status.arch_calls; + break; + case SPEAR_MERC_GUILD: + calls = &sd->status.spear_calls; + break; + case SWORD_MERC_GUILD: + calls = &sd->status.sword_calls; + break; + default: + return 0; // Invalid Guild + } - return 0; + *calls += value; + *calls = cap_value(*calls, 0, INT_MAX); + + return 0; } BUILDIN_FUNC(mercenary_get_faith) { - struct map_session_data *sd = script_rid2sd(st); - int guild; + struct map_session_data *sd = script_rid2sd(st); + int guild; - if (sd == NULL) - return 0; + if( sd == NULL ) + return 0; - guild = script_getnum(st,2); - switch (guild) { - case ARCH_MERC_GUILD: - script_pushint(st,sd->status.arch_faith); - break; - case SPEAR_MERC_GUILD: - script_pushint(st,sd->status.spear_faith); - break; - case SWORD_MERC_GUILD: - script_pushint(st,sd->status.sword_faith); - break; - default: - script_pushint(st,0); - break; - } + guild = script_getnum(st,2); + switch( guild ) + { + case ARCH_MERC_GUILD: + script_pushint(st,sd->status.arch_faith); + break; + case SPEAR_MERC_GUILD: + script_pushint(st,sd->status.spear_faith); + break; + case SWORD_MERC_GUILD: + script_pushint(st,sd->status.sword_faith); + break; + default: + script_pushint(st,0); + break; + } - return 0; + return 0; } BUILDIN_FUNC(mercenary_set_faith) { - struct map_session_data *sd = script_rid2sd(st); - int guild, value, *calls; + struct map_session_data *sd = script_rid2sd(st); + int guild, value, *calls; - if (sd == NULL) - return 0; + if( sd == NULL ) + return 0; - guild = script_getnum(st,2); - value = script_getnum(st,3); - - switch (guild) { - case ARCH_MERC_GUILD: - calls = &sd->status.arch_faith; - break; - case SPEAR_MERC_GUILD: - calls = &sd->status.spear_faith; - break; - case SWORD_MERC_GUILD: - calls = &sd->status.sword_faith; - break; - default: - return 0; // Invalid Guild - } + guild = script_getnum(st,2); + value = script_getnum(st,3); - *calls += value; - *calls = cap_value(*calls, 0, INT_MAX); - if (mercenary_get_guild(sd->md) == guild) - clif_mercenary_updatestatus(sd,SP_MERCFAITH); + switch( guild ) + { + case ARCH_MERC_GUILD: + calls = &sd->status.arch_faith; + break; + case SPEAR_MERC_GUILD: + calls = &sd->status.spear_faith; + break; + case SWORD_MERC_GUILD: + calls = &sd->status.sword_faith; + break; + default: + return 0; // Invalid Guild + } - return 0; + *calls += value; + *calls = cap_value(*calls, 0, INT_MAX); + if( mercenary_get_guild(sd->md) == guild ) + clif_mercenary_updatestatus(sd,SP_MERCFAITH); + + return 0; } /*------------------------------------------ @@ -15998,17 +15860,17 @@ BUILDIN_FUNC(mercenary_set_faith) *------------------------------------------*/ BUILDIN_FUNC(readbook) { - struct map_session_data *sd; - int book_id, page; + struct map_session_data *sd; + int book_id, page; - if ((sd = script_rid2sd(st)) == NULL) - return 0; + if( (sd = script_rid2sd(st)) == NULL ) + return 0; - book_id = script_getnum(st,2); - page = script_getnum(st,3); + book_id = script_getnum(st,2); + page = script_getnum(st,3); - clif_readbook(sd->fd, book_id, page); - return 0; + clif_readbook(sd->fd, book_id, page); + return 0; } /****************** @@ -16017,71 +15879,71 @@ Questlog script commands BUILDIN_FUNC(setquest) { - struct map_session_data *sd = script_rid2sd(st); - nullpo_ret(sd); + struct map_session_data *sd = script_rid2sd(st); + nullpo_ret(sd); - quest_add(sd, script_getnum(st, 2)); - return 0; + quest_add(sd, script_getnum(st, 2)); + return 0; } BUILDIN_FUNC(erasequest) { - struct map_session_data *sd = script_rid2sd(st); - nullpo_ret(sd); + struct map_session_data *sd = script_rid2sd(st); + nullpo_ret(sd); - quest_delete(sd, script_getnum(st, 2)); - return 0; + quest_delete(sd, script_getnum(st, 2)); + return 0; } BUILDIN_FUNC(completequest) { - struct map_session_data *sd = script_rid2sd(st); - nullpo_ret(sd); + struct map_session_data *sd = script_rid2sd(st); + nullpo_ret(sd); - quest_update_status(sd, script_getnum(st, 2), Q_COMPLETE); - return 0; + quest_update_status(sd, script_getnum(st, 2), Q_COMPLETE); + return 0; } BUILDIN_FUNC(changequest) { - struct map_session_data *sd = script_rid2sd(st); - nullpo_ret(sd); + struct map_session_data *sd = script_rid2sd(st); + nullpo_ret(sd); - quest_change(sd, script_getnum(st, 2),script_getnum(st, 3)); - return 0; + quest_change(sd, script_getnum(st, 2),script_getnum(st, 3)); + return 0; } BUILDIN_FUNC(checkquest) { - struct map_session_data *sd = script_rid2sd(st); - quest_check_type type = HAVEQUEST; + struct map_session_data *sd = script_rid2sd(st); + quest_check_type type = HAVEQUEST; - nullpo_ret(sd); + nullpo_ret(sd); - if (script_hasdata(st, 3)) - type = (quest_check_type)script_getnum(st, 3); + if( script_hasdata(st, 3) ) + type = (quest_check_type)script_getnum(st, 3); - script_pushint(st, quest_check(sd, script_getnum(st, 2), type)); + script_pushint(st, quest_check(sd, script_getnum(st, 2), type)); - return 0; + return 0; } BUILDIN_FUNC(showevent) { - TBL_PC *sd = script_rid2sd(st); - struct npc_data *nd = map_id2nd(st->oid); - int state, color; + TBL_PC *sd = script_rid2sd(st); + struct npc_data *nd = map_id2nd(st->oid); + int state, color; - if (sd == NULL || nd == NULL) - return 0; - state = script_getnum(st, 2); - color = script_getnum(st, 3); + if( sd == NULL || nd == NULL ) + return 0; + state = script_getnum(st, 2); + color = script_getnum(st, 3); - if (color < 0 || color > 3) - color = 0; // set default color + if( color < 0 || color > 3 ) + color = 0; // set default color - clif_quest_show_event(sd, &nd->bl, state, color); - return 0; + clif_quest_show_event(sd, &nd->bl, state, color); + return 0; } /*========================================== @@ -16089,241 +15951,248 @@ BUILDIN_FUNC(showevent) *------------------------------------------*/ BUILDIN_FUNC(waitingroom2bg) { - struct npc_data *nd; - struct chat_data *cd; - const char *map_name, *ev = "", *dev = ""; - int x, y, i, mapindex = 0, bg_id, n; - struct map_session_data *sd; - - if (script_hasdata(st,7)) - nd = npc_name2id(script_getstr(st,7)); - else - nd = (struct npc_data *)map_id2bl(st->oid); - - if (nd == NULL || (cd = (struct chat_data *)map_id2bl(nd->chat_id)) == NULL) { - script_pushint(st,0); - return 0; - } - - map_name = script_getstr(st,2); - if (strcmp(map_name,"-") != 0) { - mapindex = mapindex_name2id(map_name); - if (mapindex == 0) { - // Invalid Map - script_pushint(st,0); - return 0; - } - } - - x = script_getnum(st,3); - y = script_getnum(st,4); - ev = script_getstr(st,5); // Logout Event - dev = script_getstr(st,6); // Die Event - - if ((bg_id = bg_create(mapindex, x, y, ev, dev)) == 0) { - // Creation failed - script_pushint(st,0); - return 0; - } - - n = cd->users; - for (i = 0; i < n && i < MAX_BG_MEMBERS; i++) { - if ((sd = cd->usersd[i]) != NULL && bg_team_join(bg_id, sd)) - mapreg_setreg(reference_uid(add_str("$@arenamembers"), i), sd->bl.id); - else - mapreg_setreg(reference_uid(add_str("$@arenamembers"), i), 0); - } - - mapreg_setreg(add_str("$@arenamembersnum"), i); - script_pushint(st,bg_id); - return 0; + struct npc_data *nd; + struct chat_data *cd; + const char *map_name, *ev = "", *dev = ""; + int x, y, i, mapindex = 0, bg_id, n; + struct map_session_data *sd; + + if( script_hasdata(st,7) ) + nd = npc_name2id(script_getstr(st,7)); + else + nd = (struct npc_data *)map_id2bl(st->oid); + + if( nd == NULL || (cd = (struct chat_data *)map_id2bl(nd->chat_id)) == NULL ) + { + script_pushint(st,0); + return 0; + } + + map_name = script_getstr(st,2); + if( strcmp(map_name,"-") != 0 ) + { + mapindex = mapindex_name2id(map_name); + if( mapindex == 0 ) + { // Invalid Map + script_pushint(st,0); + return 0; + } + } + + x = script_getnum(st,3); + y = script_getnum(st,4); + ev = script_getstr(st,5); // Logout Event + dev = script_getstr(st,6); // Die Event + + if( (bg_id = bg_create(mapindex, x, y, ev, dev)) == 0 ) + { // Creation failed + script_pushint(st,0); + return 0; + } + + n = cd->users; + for( i = 0; i < n && i < MAX_BG_MEMBERS; i++ ) + { + if( (sd = cd->usersd[i]) != NULL && bg_team_join(bg_id, sd) ) + mapreg_setreg(reference_uid(add_str("$@arenamembers"), i), sd->bl.id); + else + mapreg_setreg(reference_uid(add_str("$@arenamembers"), i), 0); + } + + mapreg_setreg(add_str("$@arenamembersnum"), i); + script_pushint(st,bg_id); + return 0; } BUILDIN_FUNC(waitingroom2bg_single) { - const char *map_name; - struct npc_data *nd; - struct chat_data *cd; - struct map_session_data *sd; - int x, y, mapindex, bg_id; + const char* map_name; + struct npc_data *nd; + struct chat_data *cd; + struct map_session_data *sd; + int x, y, mapindex, bg_id; - bg_id = script_getnum(st,2); - map_name = script_getstr(st,3); - if ((mapindex = mapindex_name2id(map_name)) == 0) - return 0; // Invalid Map + bg_id = script_getnum(st,2); + map_name = script_getstr(st,3); + if( (mapindex = mapindex_name2id(map_name)) == 0 ) + return 0; // Invalid Map - x = script_getnum(st,4); - y = script_getnum(st,5); - nd = npc_name2id(script_getstr(st,6)); + x = script_getnum(st,4); + y = script_getnum(st,5); + nd = npc_name2id(script_getstr(st,6)); - if (nd == NULL || (cd = (struct chat_data *)map_id2bl(nd->chat_id)) == NULL || cd->users <= 0) - return 0; + if( nd == NULL || (cd = (struct chat_data *)map_id2bl(nd->chat_id)) == NULL || cd->users <= 0 ) + return 0; - if ((sd = cd->usersd[0]) == NULL) - return 0; + if( (sd = cd->usersd[0]) == NULL ) + return 0; - if (bg_team_join(bg_id, sd)) { - pc_setpos(sd, mapindex, x, y, CLR_TELEPORT); - script_pushint(st,1); - } else - script_pushint(st,0); + if( bg_team_join(bg_id, sd) ) + { + pc_setpos(sd, mapindex, x, y, CLR_TELEPORT); + script_pushint(st,1); + } + else + script_pushint(st,0); - return 0; + return 0; } BUILDIN_FUNC(bg_team_setxy) { - struct battleground_data *bg; - int bg_id; + struct battleground_data *bg; + int bg_id; - bg_id = script_getnum(st,2); - if ((bg = bg_team_search(bg_id)) == NULL) - return 0; + bg_id = script_getnum(st,2); + if( (bg = bg_team_search(bg_id)) == NULL ) + return 0; - bg->x = script_getnum(st,3); - bg->y = script_getnum(st,4); - return 0; + bg->x = script_getnum(st,3); + bg->y = script_getnum(st,4); + return 0; } BUILDIN_FUNC(bg_warp) { - int x, y, mapindex, bg_id; - const char *map_name; + int x, y, mapindex, bg_id; + const char* map_name; - bg_id = script_getnum(st,2); - map_name = script_getstr(st,3); - if ((mapindex = mapindex_name2id(map_name)) == 0) - return 0; // Invalid Map - x = script_getnum(st,4); - y = script_getnum(st,5); - bg_team_warp(bg_id, mapindex, x, y); - return 0; + bg_id = script_getnum(st,2); + map_name = script_getstr(st,3); + if( (mapindex = mapindex_name2id(map_name)) == 0 ) + return 0; // Invalid Map + x = script_getnum(st,4); + y = script_getnum(st,5); + bg_team_warp(bg_id, mapindex, x, y); + return 0; } BUILDIN_FUNC(bg_monster) { - int class_ = 0, x = 0, y = 0, bg_id = 0; - const char *str,*map, *evt=""; - - bg_id = script_getnum(st,2); - map = script_getstr(st,3); - x = script_getnum(st,4); - y = script_getnum(st,5); - str = script_getstr(st,6); - class_ = script_getnum(st,7); - if (script_hasdata(st,8)) evt = script_getstr(st,8); - check_event(st, evt); - script_pushint(st, mob_spawn_bg(map,x,y,str,class_,evt,bg_id)); - return 0; + int class_ = 0, x = 0, y = 0, bg_id = 0; + const char *str,*map, *evt=""; + + bg_id = script_getnum(st,2); + map = script_getstr(st,3); + x = script_getnum(st,4); + y = script_getnum(st,5); + str = script_getstr(st,6); + class_ = script_getnum(st,7); + if( script_hasdata(st,8) ) evt = script_getstr(st,8); + check_event(st, evt); + script_pushint(st, mob_spawn_bg(map,x,y,str,class_,evt,bg_id)); + return 0; } BUILDIN_FUNC(bg_monster_set_team) { - struct mob_data *md; - struct block_list *mbl; - int id = script_getnum(st,2), - bg_id = script_getnum(st,3); + struct mob_data *md; + struct block_list *mbl; + int id = script_getnum(st,2), + bg_id = script_getnum(st,3); - if ((mbl = map_id2bl(id)) == NULL || mbl->type != BL_MOB) - return 0; - md = (TBL_MOB *)mbl; - md->bg_id = bg_id; + if( (mbl = map_id2bl(id)) == NULL || mbl->type != BL_MOB ) + return 0; + md = (TBL_MOB *)mbl; + md->bg_id = bg_id; - mob_stop_attack(md); - mob_stop_walking(md, 0); - md->target_id = md->attacked_id = 0; - clif_charnameack(0, &md->bl); + mob_stop_attack(md); + mob_stop_walking(md, 0); + md->target_id = md->attacked_id = 0; + clif_charnameack(0, &md->bl); - return 0; + return 0; } BUILDIN_FUNC(bg_leave) { - struct map_session_data *sd = script_rid2sd(st); - if (sd == NULL || !sd->bg_id) - return 0; + struct map_session_data *sd = script_rid2sd(st); + if( sd == NULL || !sd->bg_id ) + return 0; - bg_team_leave(sd,0); - return 0; + bg_team_leave(sd,0); + return 0; } BUILDIN_FUNC(bg_destroy) { - int bg_id = script_getnum(st,2); - bg_team_delete(bg_id); - return 0; + int bg_id = script_getnum(st,2); + bg_team_delete(bg_id); + return 0; } BUILDIN_FUNC(bg_getareausers) { - const char *str; - int m, x0, y0, x1, y1, bg_id; - int i = 0, c = 0; - struct battleground_data *bg = NULL; - struct map_session_data *sd; + const char *str; + int m, x0, y0, x1, y1, bg_id; + int i = 0, c = 0; + struct battleground_data *bg = NULL; + struct map_session_data *sd; - bg_id = script_getnum(st,2); - str = script_getstr(st,3); + bg_id = script_getnum(st,2); + str = script_getstr(st,3); - if ((bg = bg_team_search(bg_id)) == NULL || (m = map_mapname2mapid(str)) < 0) { - script_pushint(st,0); - return 0; - } + if( (bg = bg_team_search(bg_id)) == NULL || (m = map_mapname2mapid(str)) < 0 ) + { + script_pushint(st,0); + return 0; + } - x0 = script_getnum(st,4); - y0 = script_getnum(st,5); - x1 = script_getnum(st,6); - y1 = script_getnum(st,7); + x0 = script_getnum(st,4); + y0 = script_getnum(st,5); + x1 = script_getnum(st,6); + y1 = script_getnum(st,7); - for (i = 0; i < MAX_BG_MEMBERS; i++) { - if ((sd = bg->members[i].sd) == NULL) - continue; - if (sd->bl.m != m || sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) - continue; - c++; - } + for( i = 0; i < MAX_BG_MEMBERS; i++ ) + { + if( (sd = bg->members[i].sd) == NULL ) + continue; + if( sd->bl.m != m || sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1 ) + continue; + c++; + } - script_pushint(st,c); - return 0; + script_pushint(st,c); + return 0; } BUILDIN_FUNC(bg_updatescore) { - const char *str; - int m; + const char *str; + int m; - str = script_getstr(st,2); - if ((m = map_mapname2mapid(str)) < 0) - return 0; + str = script_getstr(st,2); + if( (m = map_mapname2mapid(str)) < 0 ) + return 0; - map[m].bgscore_lion = script_getnum(st,3); - map[m].bgscore_eagle = script_getnum(st,4); + map[m].bgscore_lion = script_getnum(st,3); + map[m].bgscore_eagle = script_getnum(st,4); - clif_bg_updatescore(m); - return 0; + clif_bg_updatescore(m); + return 0; } BUILDIN_FUNC(bg_get_data) { - struct battleground_data *bg; - int bg_id = script_getnum(st,2), - type = script_getnum(st,3); + struct battleground_data *bg; + int bg_id = script_getnum(st,2), + type = script_getnum(st,3); - if ((bg = bg_team_search(bg_id)) == NULL) { - script_pushint(st,0); - return 0; - } + if( (bg = bg_team_search(bg_id)) == NULL ) + { + script_pushint(st,0); + return 0; + } - switch (type) { - case 0: - script_pushint(st, bg->count); - break; - default: - ShowError("script:bg_get_data: unknown data identifier %d\n", type); - break; - } + switch( type ) + { + case 0: script_pushint(st, bg->count); break; + default: + ShowError("script:bg_get_data: unknown data identifier %d\n", type); + break; + } - return 0; + return 0; } /*========================================== @@ -16332,299 +16201,306 @@ BUILDIN_FUNC(bg_get_data) BUILDIN_FUNC(instance_create) { - const char *name; - int party_id, res; - - name = script_getstr(st, 2); - party_id = script_getnum(st, 3); - - res = instance_create(party_id, name); - if (res == -4) { // Already exists - script_pushint(st, -1); - return 0; - } else if (res < 0) { - const char *err; - switch (res) { - case -3: - err = "No free instances"; - break; - case -2: - err = "Invalid party ID"; - break; - case -1: - err = "Invalid type"; - break; - default: - err = "Unknown"; - break; - } - ShowError("buildin_instance_create: %s [%d].\n", err, res); - script_pushint(st, -2); - return 0; - } - - script_pushint(st, res); - return 0; + const char *name; + int party_id, res; + + name = script_getstr(st, 2); + party_id = script_getnum(st, 3); + + res = instance_create(party_id, name); + if( res == -4 ) // Already exists + { + script_pushint(st, -1); + return 0; + } + else if( res < 0 ) + { + const char *err; + switch(res) + { + case -3: err = "No free instances"; break; + case -2: err = "Invalid party ID"; break; + case -1: err = "Invalid type"; break; + default: err = "Unknown"; break; + } + ShowError("buildin_instance_create: %s [%d].\n", err, res); + script_pushint(st, -2); + return 0; + } + + script_pushint(st, res); + return 0; } BUILDIN_FUNC(instance_destroy) { - int instance_id; - struct map_session_data *sd; - struct party_data *p; + int instance_id; + struct map_session_data *sd; + struct party_data *p; - if (script_hasdata(st, 2)) - instance_id = script_getnum(st, 2); - else if (st->instance_id) - instance_id = st->instance_id; - else if ((sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id) - instance_id = p->instance_id; - else return 0; + if( script_hasdata(st, 2) ) + instance_id = script_getnum(st, 2); + else if( st->instance_id ) + instance_id = st->instance_id; + else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) + instance_id = p->instance_id; + else return 0; - if (instance_id <= 0 || instance_id >= MAX_INSTANCE) { - ShowError("buildin_instance_destroy: Trying to destroy invalid instance %d.\n", instance_id); - return 0; - } + if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) + { + ShowError("buildin_instance_destroy: Trying to destroy invalid instance %d.\n", instance_id); + return 0; + } - instance_destroy(instance_id); - return 0; + instance_destroy(instance_id); + return 0; } BUILDIN_FUNC(instance_attachmap) { - const char *name; - int m; - int instance_id; - bool usebasename = false; + const char *name; + int m; + int instance_id; + bool usebasename = false; - name = script_getstr(st,2); - instance_id = script_getnum(st,3); - if (script_hasdata(st,4) && script_getnum(st,4) > 0) - usebasename = true; + name = script_getstr(st,2); + instance_id = script_getnum(st,3); + if( script_hasdata(st,4) && script_getnum(st,4) > 0) + usebasename = true; - if ((m = instance_add_map(name, instance_id, usebasename)) < 0) { // [Saithis] - ShowError("buildin_instance_attachmap: instance creation failed (%s): %d\n", name, m); - script_pushconststr(st, ""); - return 0; - } - script_pushconststr(st, map[m].name); + if( (m = instance_add_map(name, instance_id, usebasename)) < 0 ) // [Saithis] + { + ShowError("buildin_instance_attachmap: instance creation failed (%s): %d\n", name, m); + script_pushconststr(st, ""); + return 0; + } + script_pushconststr(st, map[m].name); - return 0; + return 0; } BUILDIN_FUNC(instance_detachmap) { - struct map_session_data *sd; - struct party_data *p; - const char *str; - int m, instance_id; + struct map_session_data *sd; + struct party_data *p; + const char *str; + int m, instance_id; - str = script_getstr(st, 2); - if (script_hasdata(st, 3)) - instance_id = script_getnum(st, 3); - else if (st->instance_id) - instance_id = st->instance_id; - else if ((sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id) - instance_id = p->instance_id; - else return 0; - - if ((m = map_mapname2mapid(str)) < 0 || (m = instance_map2imap(m,instance_id)) < 0) { - ShowError("buildin_instance_detachmap: Trying to detach invalid map %s\n", str); - return 0; - } + str = script_getstr(st, 2); + if( script_hasdata(st, 3) ) + instance_id = script_getnum(st, 3); + else if( st->instance_id ) + instance_id = st->instance_id; + else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) + instance_id = p->instance_id; + else return 0; - instance_del_map(m); - return 0; + if( (m = map_mapname2mapid(str)) < 0 || (m = instance_map2imap(m,instance_id)) < 0 ) + { + ShowError("buildin_instance_detachmap: Trying to detach invalid map %s\n", str); + return 0; + } + + instance_del_map(m); + return 0; } BUILDIN_FUNC(instance_attach) { - int instance_id; + int instance_id; - instance_id = script_getnum(st, 2); - if (instance_id <= 0 || instance_id >= MAX_INSTANCE) - return 0; + instance_id = script_getnum(st, 2); + if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) + return 0; - st->instance_id = instance_id; - return 0; + st->instance_id = instance_id; + return 0; } BUILDIN_FUNC(instance_id) { - int type, instance_id; - struct map_session_data *sd; - struct party_data *p; - - if (script_hasdata(st, 2)) { - type = script_getnum(st, 2); - if (type == 0) - instance_id = st->instance_id; - else if (type == 1 && (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL) - instance_id = p->instance_id; - else - instance_id = 0; - } else - instance_id = st->instance_id; - - script_pushint(st, instance_id); - return 0; + int type, instance_id; + struct map_session_data *sd; + struct party_data *p; + + if( script_hasdata(st, 2) ) + { + type = script_getnum(st, 2); + if( type == 0 ) + instance_id = st->instance_id; + else if( type == 1 && (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL ) + instance_id = p->instance_id; + else + instance_id = 0; + } + else + instance_id = st->instance_id; + + script_pushint(st, instance_id); + return 0; } BUILDIN_FUNC(instance_set_timeout) { - int progress_timeout, idle_timeout; - int instance_id; - struct map_session_data *sd; - struct party_data *p; + int progress_timeout, idle_timeout; + int instance_id; + struct map_session_data *sd; + struct party_data *p; - progress_timeout = script_getnum(st, 2); - idle_timeout = script_getnum(st, 3); + progress_timeout = script_getnum(st, 2); + idle_timeout = script_getnum(st, 3); - if (script_hasdata(st, 4)) - instance_id = script_getnum(st, 4); - else if (st->instance_id) - instance_id = st->instance_id; - else if ((sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id) - instance_id = p->instance_id; - else return 0; + if( script_hasdata(st, 4) ) + instance_id = script_getnum(st, 4); + else if( st->instance_id ) + instance_id = st->instance_id; + else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) + instance_id = p->instance_id; + else return 0; - if (instance_id > 0) - instance_set_timeout(instance_id, progress_timeout, idle_timeout); + if( instance_id > 0 ) + instance_set_timeout(instance_id, progress_timeout, idle_timeout); - return 0; + return 0; } BUILDIN_FUNC(instance_init) { - int instance_id = script_getnum(st, 2); + int instance_id = script_getnum(st, 2); - if (instance[instance_id].state != INSTANCE_IDLE) { - ShowError("instance_init: instance already initialized.\n"); - return 0; - } + if( instance[instance_id].state != INSTANCE_IDLE ) + { + ShowError("instance_init: instance already initialized.\n"); + return 0; + } - instance_init(instance_id); - return 0; + instance_init(instance_id); + return 0; } BUILDIN_FUNC(instance_announce) { - int instance_id = script_getnum(st,2); - const char *mes = script_getstr(st,3); - int flag = script_getnum(st,4); - const char *fontColor = script_hasdata(st,5) ? script_getstr(st,5) : NULL; - int fontType = script_hasdata(st,6) ? script_getnum(st,6) : 0x190; // default fontType (FW_NORMAL) - int fontSize = script_hasdata(st,7) ? script_getnum(st,7) : 12; // default fontSize - int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign - int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY - - int i; - struct map_session_data *sd; - struct party_data *p; - - if (instance_id == 0) { - if (st->instance_id) - instance_id = st->instance_id; - else if ((sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id) - instance_id = p->instance_id; - else return 0; - } + int instance_id = script_getnum(st,2); + const char *mes = script_getstr(st,3); + int flag = script_getnum(st,4); + const char *fontColor = script_hasdata(st,5) ? script_getstr(st,5) : NULL; + int fontType = script_hasdata(st,6) ? script_getnum(st,6) : 0x190; // default fontType (FW_NORMAL) + int fontSize = script_hasdata(st,7) ? script_getnum(st,7) : 12; // default fontSize + int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign + int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY - if (instance_id <= 0 || instance_id >= MAX_INSTANCE) - return 0; + int i; + struct map_session_data *sd; + struct party_data *p; - for (i = 0; i < instance[instance_id].num_map; i++) - map_foreachinmap(buildin_announce_sub, instance[instance_id].map[i], BL_PC, - mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); + if( instance_id == 0 ) + { + if( st->instance_id ) + instance_id = st->instance_id; + else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) + instance_id = p->instance_id; + else return 0; + } - return 0; + if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) + return 0; + + for( i = 0; i < instance[instance_id].num_map; i++ ) + map_foreachinmap(buildin_announce_sub, instance[instance_id].map[i], BL_PC, + mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); + + return 0; } BUILDIN_FUNC(instance_npcname) { - const char *str; - int instance_id = 0; - - struct map_session_data *sd; - struct party_data *p; - struct npc_data *nd; - - str = script_getstr(st, 2); - if (script_hasdata(st, 3)) - instance_id = script_getnum(st, 3); - else if (st->instance_id) - instance_id = st->instance_id; - else if ((sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id) - instance_id = p->instance_id; - - if (instance_id && (nd = npc_name2id(str)) != NULL) { - static char npcname[NAME_LENGTH]; - snprintf(npcname, sizeof(npcname), "dup_%d_%d", instance_id, nd->bl.id); - script_pushconststr(st,npcname); - } else { - ShowError("script:instance_npcname: invalid instance NPC (instance_id: %d, NPC name: \"%s\".)\n", instance_id, str); - st->state = END; - return 1; - } - - return 0; + const char *str; + int instance_id = 0; + + struct map_session_data *sd; + struct party_data *p; + struct npc_data *nd; + + str = script_getstr(st, 2); + if( script_hasdata(st, 3) ) + instance_id = script_getnum(st, 3); + else if( st->instance_id ) + instance_id = st->instance_id; + else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) + instance_id = p->instance_id; + + if( instance_id && (nd = npc_name2id(str)) != NULL ) + { + static char npcname[NAME_LENGTH]; + snprintf(npcname, sizeof(npcname), "dup_%d_%d", instance_id, nd->bl.id); + script_pushconststr(st,npcname); + } + else + { + ShowError("script:instance_npcname: invalid instance NPC (instance_id: %d, NPC name: \"%s\".)\n", instance_id, str); + st->state = END; + return 1; + } + + return 0; } BUILDIN_FUNC(has_instance) { - struct map_session_data *sd; - struct party_data *p; - const char *str; - int m, instance_id = 0; + struct map_session_data *sd; + struct party_data *p; + const char *str; + int m, instance_id = 0; - str = script_getstr(st, 2); - if (script_hasdata(st, 3)) - instance_id = script_getnum(st, 3); - else if (st->instance_id) - instance_id = st->instance_id; - else if ((sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id) - instance_id = p->instance_id; - - if (!instance_id || (m = map_mapname2mapid(str)) < 0 || (m = instance_map2imap(m, instance_id)) < 0) { - script_pushconststr(st, ""); - return 0; - } + str = script_getstr(st, 2); + if( script_hasdata(st, 3) ) + instance_id = script_getnum(st, 3); + else if( st->instance_id ) + instance_id = st->instance_id; + else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) + instance_id = p->instance_id; - script_pushconststr(st, map[m].name); - return 0; + if( !instance_id || (m = map_mapname2mapid(str)) < 0 || (m = instance_map2imap(m, instance_id)) < 0 ) + { + script_pushconststr(st, ""); + return 0; + } + + script_pushconststr(st, map[m].name); + return 0; } BUILDIN_FUNC(instance_warpall) { - struct map_session_data *pl_sd; - int m, i, instance_id; - const char *mapn; - int x, y; - unsigned short mapindex; - struct party_data *p = NULL; - - mapn = script_getstr(st,2); - x = script_getnum(st,3); - y = script_getnum(st,4); - if (script_hasdata(st,5)) - instance_id = script_getnum(st,5); - else if (st->instance_id) - instance_id = st->instance_id; - else if ((pl_sd = script_rid2sd(st)) != NULL && pl_sd->status.party_id && (p = party_search(pl_sd->status.party_id)) != NULL && p->instance_id) - instance_id = p->instance_id; - else return 0; - - if ((m = map_mapname2mapid(mapn)) < 0 || (map[m].flag.src4instance && (m = instance_mapid2imapid(m, instance_id)) < 0)) - return 0; + struct map_session_data *pl_sd; + int m, i, instance_id; + const char *mapn; + int x, y; + unsigned short mapindex; + struct party_data *p = NULL; - if (!(p = party_search(instance[instance_id].party_id))) - return 0; + mapn = script_getstr(st,2); + x = script_getnum(st,3); + y = script_getnum(st,4); + if( script_hasdata(st,5) ) + instance_id = script_getnum(st,5); + else if( st->instance_id ) + instance_id = st->instance_id; + else if( (pl_sd = script_rid2sd(st)) != NULL && pl_sd->status.party_id && (p = party_search(pl_sd->status.party_id)) != NULL && p->instance_id ) + instance_id = p->instance_id; + else return 0; - mapindex = map_id2index(m); - for (i = 0; i < MAX_PARTY; i++) - if ((pl_sd = p->data[i].sd) && map[pl_sd->bl.m].instance_id == st->instance_id) pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT); + if( (m = map_mapname2mapid(mapn)) < 0 || (map[m].flag.src4instance && (m = instance_mapid2imapid(m, instance_id)) < 0) ) + return 0; - return 0; + if( !(p = party_search(instance[instance_id].party_id)) ) + return 0; + + mapindex = map_id2index(m); + for( i = 0; i < MAX_PARTY; i++ ) + if( (pl_sd = p->data[i].sd) && map[pl_sd->bl.m].instance_id == st->instance_id ) pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT); + + return 0; } /*========================================== @@ -16639,50 +16515,50 @@ BUILDIN_FUNC(instance_warpall) *------------------------------------------*/ BUILDIN_FUNC(instance_check_party) { - struct map_session_data *pl_sd; - int amount, min, max, i, party_id, c = 0; - struct party_data *p = NULL; - - amount = script_hasdata(st,3) ? script_getnum(st,3) : 1; // Amount of needed Partymembers for the Instance. - min = script_hasdata(st,4) ? script_getnum(st,4) : 1; // Minimum Level needed to join the Instance. - max = script_hasdata(st,5) ? script_getnum(st,5) : MAX_LEVEL; // Maxium Level allowed to join the Instance. - - if (min < 1 || min > MAX_LEVEL) { - ShowError("instance_check_party: Invalid min level, %d\n", min); - return 0; - } else if (max < 1 || max > MAX_LEVEL) { - ShowError("instance_check_party: Invalid max level, %d\n", max); - return 0; - } - - if (script_hasdata(st,2)) - party_id = script_getnum(st,2); - else return 0; - - if (!(p = party_search(party_id))) { - script_pushint(st, 0); // Returns false if party does not exist. - return 0; - } - - for (i = 0; i < MAX_PARTY; i++) - if ((pl_sd = p->data[i].sd)) - if (map_id2bl(pl_sd->bl.id)) { - if (pl_sd->status.base_level < min) { - script_pushint(st, 0); - return 0; - } else if (pl_sd->status.base_level > max) { - script_pushint(st, 0); - return 0; - } - c++; - } - - if (c < amount) { - script_pushint(st, 0); // Not enough Members in the Party to join Instance. - } else - script_pushint(st, 1); - - return 0; + struct map_session_data *pl_sd; + int amount, min, max, i, party_id, c = 0; + struct party_data *p = NULL; + + amount = script_hasdata(st,3) ? script_getnum(st,3) : 1; // Amount of needed Partymembers for the Instance. + min = script_hasdata(st,4) ? script_getnum(st,4) : 1; // Minimum Level needed to join the Instance. + max = script_hasdata(st,5) ? script_getnum(st,5) : MAX_LEVEL; // Maxium Level allowed to join the Instance. + + if( min < 1 || min > MAX_LEVEL){ + ShowError("instance_check_party: Invalid min level, %d\n", min); + return 0; + }else if( max < 1 || max > MAX_LEVEL){ + ShowError("instance_check_party: Invalid max level, %d\n", max); + return 0; + } + + if( script_hasdata(st,2) ) + party_id = script_getnum(st,2); + else return 0; + + if( !(p = party_search(party_id)) ){ + script_pushint(st, 0); // Returns false if party does not exist. + return 0; + } + + for( i = 0; i < MAX_PARTY; i++ ) + if( (pl_sd = p->data[i].sd) ) + if(map_id2bl(pl_sd->bl.id)){ + if(pl_sd->status.base_level < min){ + script_pushint(st, 0); + return 0; + }else if(pl_sd->status.base_level > max){ + script_pushint(st, 0); + return 0; + } + c++; + } + + if(c < amount){ + script_pushint(st, 0); // Not enough Members in the Party to join Instance. + }else + script_pushint(st, 1); + + return 0; } /*========================================== @@ -16690,155 +16566,152 @@ BUILDIN_FUNC(instance_check_party) *------------------------------------------*/ BUILDIN_FUNC(setfont) { - struct map_session_data *sd = script_rid2sd(st); - int font = script_getnum(st,2); - if (sd == NULL) - return 0; + struct map_session_data *sd = script_rid2sd(st); + int font = script_getnum(st,2); + if( sd == NULL ) + return 0; - if (sd->user_font != font) - sd->user_font = font; - else - sd->user_font = 0; + if( sd->user_font != font ) + sd->user_font = font; + else + sd->user_font = 0; - clif_font(sd); - return 0; + clif_font(sd); + return 0; } static int buildin_mobuseskill_sub(struct block_list *bl,va_list ap) { - TBL_MOB *md = (TBL_MOB *)bl; - struct block_list *tbl; - int mobid = va_arg(ap,int); - int skillid = va_arg(ap,int); - int skilllv = va_arg(ap,int); - int casttime = va_arg(ap,int); - int cancel = va_arg(ap,int); - int emotion = va_arg(ap,int); - int target = va_arg(ap,int); - - if (md->class_ != mobid) - return 0; + TBL_MOB* md = (TBL_MOB*)bl; + struct block_list *tbl; + int mobid = va_arg(ap,int); + int skillid = va_arg(ap,int); + int skilllv = va_arg(ap,int); + int casttime = va_arg(ap,int); + int cancel = va_arg(ap,int); + int emotion = va_arg(ap,int); + int target = va_arg(ap,int); - // 0:self, 1:target, 2:master, default:random - switch (target) { - case 0: - tbl = map_id2bl(md->bl.id); - break; - case 1: - tbl = map_id2bl(md->target_id); - break; - case 2: - tbl = map_id2bl(md->master_id); - break; - default: - tbl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md),skill_get_range2(&md->bl, skillid, skilllv)); - break; - } + if( md->class_ != mobid ) + return 0; - if (!tbl) - return 0; + // 0:self, 1:target, 2:master, default:random + switch( target ) + { + case 0: tbl = map_id2bl(md->bl.id); break; + case 1: tbl = map_id2bl(md->target_id); break; + case 2: tbl = map_id2bl(md->master_id); break; + default:tbl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md),skill_get_range2(&md->bl, skillid, skilllv)); break; + } - if (md->ud.skilltimer != INVALID_TIMER) // Cancel the casting skill. - unit_skillcastcancel(bl,0); + if( !tbl ) + return 0; - if (skill_get_casttype(skillid) == CAST_GROUND) - unit_skilluse_pos2(&md->bl, tbl->x, tbl->y, skillid, skilllv, casttime, cancel); - else - unit_skilluse_id2(&md->bl, tbl->id, skillid, skilllv, casttime, cancel); + if( md->ud.skilltimer != INVALID_TIMER ) // Cancel the casting skill. + unit_skillcastcancel(bl,0); - clif_emotion(&md->bl, emotion); + if( skill_get_casttype(skillid) == CAST_GROUND ) + unit_skilluse_pos2(&md->bl, tbl->x, tbl->y, skillid, skilllv, casttime, cancel); + else + unit_skilluse_id2(&md->bl, tbl->id, skillid, skilllv, casttime, cancel); - return 0; + clif_emotion(&md->bl, emotion); + + return 0; } /*========================================== * areamobuseskill "Map Name",<x>,<y>,<range>,<Mob ID>,"Skill Name"/<Skill ID>,<Skill Lv>,<Cast Time>,<Cancelable>,<Emotion>,<Target Type>; *------------------------------------------*/ BUILDIN_FUNC(areamobuseskill) { - struct block_list center; - int m,range,mobid,skillid,skilllv,casttime,emotion,target,cancel; + struct block_list center; + int m,range,mobid,skillid,skilllv,casttime,emotion,target,cancel; - if ((m = map_mapname2mapid(script_getstr(st,2))) < 0) { - ShowError("areamobuseskill: invalid map name.\n"); - return 0; - } + if( (m = map_mapname2mapid(script_getstr(st,2))) < 0 ) + { + ShowError("areamobuseskill: invalid map name.\n"); + return 0; + } - if (map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0) - return 0; + if( map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) + return 0; - center.m = m; - center.x = script_getnum(st,3); - center.y = script_getnum(st,4); - range = script_getnum(st,5); - mobid = script_getnum(st,6); - skillid = (script_isstring(st,7) ? skill_name2id(script_getstr(st,7)) : script_getnum(st,7)); - if ((skilllv = script_getnum(st,8)) > battle_config.mob_max_skilllvl) - skilllv = battle_config.mob_max_skilllvl; - - casttime = script_getnum(st,9); - cancel = script_getnum(st,10); - emotion = script_getnum(st,11); - target = script_getnum(st,12); - - map_foreachinrange(buildin_mobuseskill_sub, ¢er, range, BL_MOB, mobid, skillid, skilllv, casttime, cancel, emotion, target); - return 0; + center.m = m; + center.x = script_getnum(st,3); + center.y = script_getnum(st,4); + range = script_getnum(st,5); + mobid = script_getnum(st,6); + skillid = ( script_isstring(st,7) ? skill_name2id(script_getstr(st,7)) : script_getnum(st,7) ); + if( (skilllv = script_getnum(st,8)) > battle_config.mob_max_skilllvl ) + skilllv = battle_config.mob_max_skilllvl; + + casttime = script_getnum(st,9); + cancel = script_getnum(st,10); + emotion = script_getnum(st,11); + target = script_getnum(st,12); + + map_foreachinrange(buildin_mobuseskill_sub, ¢er, range, BL_MOB, mobid, skillid, skilllv, casttime, cancel, emotion, target); + return 0; } BUILDIN_FUNC(progressbar) { - struct map_session_data *sd = script_rid2sd(st); - const char *color; - unsigned int second; + struct map_session_data * sd = script_rid2sd(st); + const char * color; + unsigned int second; - if (!st || !sd) - return 0; + if( !st || !sd ) + return 0; - st->state = STOP; + st->state = STOP; - color = script_getstr(st,2); - second = script_getnum(st,3); + color = script_getstr(st,2); + second = script_getnum(st,3); - sd->progressbar.npc_id = st->oid; - sd->progressbar.timeout = gettick() + second*1000; + sd->progressbar.npc_id = st->oid; + sd->progressbar.timeout = gettick() + second*1000; - clif_progressbar(sd, strtol(color, (char **)NULL, 0), second); + clif_progressbar(sd, strtol(color, (char **)NULL, 0), second); return 0; } BUILDIN_FUNC(pushpc) { - int direction, cells, dx, dy; - struct map_session_data *sd; + int direction, cells, dx, dy; + struct map_session_data* sd; - if ((sd = script_rid2sd(st))==NULL) { - return 0; - } + if((sd = script_rid2sd(st))==NULL) + { + return 0; + } - direction = script_getnum(st,2); - cells = script_getnum(st,3); + direction = script_getnum(st,2); + cells = script_getnum(st,3); - if (direction<0 || direction>7) { - ShowWarning("buildin_pushpc: Invalid direction %d specified.\n", direction); - script_reportsrc(st); + if(direction<0 || direction>7) + { + ShowWarning("buildin_pushpc: Invalid direction %d specified.\n", direction); + script_reportsrc(st); - direction%= 8; // trim spin-over - } + direction%= 8; // trim spin-over + } - if (!cells) { - // zero distance - return 0; - } else if (cells<0) { - // pushing backwards - direction = (direction+4)%8; // turn around - cells = -cells; - } + if(!cells) + {// zero distance + return 0; + } + else if(cells<0) + {// pushing backwards + direction = (direction+4)%8; // turn around + cells = -cells; + } - dx = dirx[direction]; - dy = diry[direction]; + dx = dirx[direction]; + dy = diry[direction]; - unit_blown(&sd->bl, dx, dy, cells, 0); - return 0; + unit_blown(&sd->bl, dx, dy, cells, 0); + return 0; } @@ -16846,14 +16719,15 @@ BUILDIN_FUNC(pushpc) /// buyingstore <slots>; BUILDIN_FUNC(buyingstore) { - struct map_session_data *sd; + struct map_session_data* sd; - if ((sd = script_rid2sd(st)) == NULL) { - return 0; - } + if( ( sd = script_rid2sd(st) ) == NULL ) + { + return 0; + } - buyingstore_setup(sd, script_getnum(st,2)); - return 0; + buyingstore_setup(sd, script_getnum(st,2)); + return 0; } @@ -16861,81 +16735,85 @@ BUILDIN_FUNC(buyingstore) /// searchstores <uses>,<effect>; BUILDIN_FUNC(searchstores) { - unsigned short effect; - unsigned int uses; - struct map_session_data *sd; + unsigned short effect; + unsigned int uses; + struct map_session_data* sd; - if ((sd = script_rid2sd(st)) == NULL) { - return 0; - } + if( ( sd = script_rid2sd(st) ) == NULL ) + { + return 0; + } - uses = script_getnum(st,2); - effect = script_getnum(st,3); + uses = script_getnum(st,2); + effect = script_getnum(st,3); - if (!uses) { - ShowError("buildin_searchstores: Amount of uses cannot be zero.\n"); - return 1; - } + if( !uses ) + { + ShowError("buildin_searchstores: Amount of uses cannot be zero.\n"); + return 1; + } - if (effect > 1) { - ShowError("buildin_searchstores: Invalid effect id %hu, specified.\n", effect); - return 1; - } + if( effect > 1 ) + { + ShowError("buildin_searchstores: Invalid effect id %hu, specified.\n", effect); + return 1; + } - searchstore_open(sd, uses, effect); - return 0; + searchstore_open(sd, uses, effect); + return 0; } /// Displays a number as large digital clock. /// showdigit <value>[,<type>]; BUILDIN_FUNC(showdigit) { - unsigned int type = 0; - int value; - struct map_session_data *sd; + unsigned int type = 0; + int value; + struct map_session_data* sd; - if ((sd = script_rid2sd(st)) == NULL) { - return 0; - } + if( ( sd = script_rid2sd(st) ) == NULL ) + { + return 0; + } - value = script_getnum(st,2); + value = script_getnum(st,2); - if (script_hasdata(st,3)) { - type = script_getnum(st,3); + if( script_hasdata(st,3) ) + { + type = script_getnum(st,3); - if (type > 3) { - ShowError("buildin_showdigit: Invalid type %u.\n", type); - return 1; - } - } + if( type > 3 ) + { + ShowError("buildin_showdigit: Invalid type %u.\n", type); + return 1; + } + } - clif_showdigit(sd, (unsigned char)type, value); - return 0; + clif_showdigit(sd, (unsigned char)type, value); + return 0; } /** * Rune Knight **/ -BUILDIN_FUNC(makerune) -{ - TBL_PC *sd; - if ((sd = script_rid2sd(st)) == NULL) - return 0; - clif_skill_produce_mix_list(sd,RK_RUNEMASTERY,24); - sd->itemid = script_getnum(st,2); - return 0; +BUILDIN_FUNC(makerune) { + TBL_PC* sd; + if( (sd = script_rid2sd(st)) == NULL ) + return 0; + clif_skill_produce_mix_list(sd,RK_RUNEMASTERY,24); + sd->itemid = script_getnum(st,2); + return 0; } /** * checkdragon() returns 1 if mounting a dragon or 0 otherwise. **/ -BUILDIN_FUNC(checkdragon) -{ - TBL_PC *sd; - if ((sd = script_rid2sd(st)) == NULL) - return 0; - if (pc_isridingdragon(sd)) - script_pushint(st,1); - else - script_pushint(st,0); - return 0; +BUILDIN_FUNC(checkdragon) { + TBL_PC* sd; + if( (sd = script_rid2sd(st)) == NULL ) + return 0; + if( pc_isridingdragon(sd) ) + script_pushint(st,1); + else + script_pushint(st,0); + return 0; } /** * setdragon({optional Color}) returns 1 on success or 0 otherwise @@ -16947,49 +16825,47 @@ BUILDIN_FUNC(checkdragon) * - 4 : Blue Dragon * - 5 : Red Dragon **/ -BUILDIN_FUNC(setdragon) -{ - TBL_PC *sd; - int color = script_hasdata(st,2) ? script_getnum(st,2) : 0; - unsigned int option = OPTION_DRAGON1; - if ((sd = script_rid2sd(st)) == NULL) - return 0; - if (!pc_checkskill(sd,RK_DRAGONTRAINING) || (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT) - script_pushint(st,0);//Doesn't have the skill or it's not a Rune Knight - else if (pc_isridingdragon(sd)) { //Is mounted; release - pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); - script_pushint(st,1); - } else {//Not mounted; Mount now. - if (color) { - option = (color == 1 ? OPTION_DRAGON1 : - color == 2 ? OPTION_DRAGON2 : - color == 3 ? OPTION_DRAGON3 : - color == 4 ? OPTION_DRAGON4 : - color == 5 ? OPTION_DRAGON5 : 0); - if (!option) { - ShowWarning("script_setdragon: Unknown Color %d used; changing to green (1)\n",color); - option = OPTION_DRAGON1; - } - } - pc_setoption(sd, sd->sc.option|option); - script_pushint(st,1); - } - return 0; +BUILDIN_FUNC(setdragon) { + TBL_PC* sd; + int color = script_hasdata(st,2) ? script_getnum(st,2) : 0; + unsigned int option = OPTION_DRAGON1; + if( (sd = script_rid2sd(st)) == NULL ) + return 0; + if( !pc_checkskill(sd,RK_DRAGONTRAINING) || (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT ) + script_pushint(st,0);//Doesn't have the skill or it's not a Rune Knight + else if ( pc_isridingdragon(sd) ) {//Is mounted; release + pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); + script_pushint(st,1); + } else {//Not mounted; Mount now. + if( color ) { + option = ( color == 1 ? OPTION_DRAGON1 : + color == 2 ? OPTION_DRAGON2 : + color == 3 ? OPTION_DRAGON3 : + color == 4 ? OPTION_DRAGON4 : + color == 5 ? OPTION_DRAGON5 : 0); + if( !option ) { + ShowWarning("script_setdragon: Unknown Color %d used; changing to green (1)\n",color); + option = OPTION_DRAGON1; + } + } + pc_setoption(sd, sd->sc.option|option); + script_pushint(st,1); + } + return 0; } /** * ismounting() returns 1 if mounting a new mount or 0 otherwise **/ -BUILDIN_FUNC(ismounting) -{ - TBL_PC *sd; - if ((sd = script_rid2sd(st)) == NULL) - return 0; - if (sd->sc.option&OPTION_MOUNTING) - script_pushint(st,1); - else - script_pushint(st,0); - return 0; +BUILDIN_FUNC(ismounting) { + TBL_PC* sd; + if( (sd = script_rid2sd(st)) == NULL ) + return 0; + if( sd->sc.option&OPTION_MOUNTING ) + script_pushint(st,1); + else + script_pushint(st,0); + return 0; } /** @@ -16998,398 +16874,357 @@ BUILDIN_FUNC(ismounting) * - Will fail if the player is mounting a non-new mount, e.g. dragon, peco, wug, etc. * - Will unmount the player is he is already mounting **/ -BUILDIN_FUNC(setmounting) -{ - TBL_PC *sd; - if ((sd = script_rid2sd(st)) == NULL) - return 0; - if (sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR)) - script_pushint(st,0);//can't mount with one of these - else { - if (sd->sc.option&OPTION_MOUNTING) - pc_setoption(sd, sd->sc.option&~OPTION_MOUNTING);//release mount - else - pc_setoption(sd, sd->sc.option|OPTION_MOUNTING);//mount - script_pushint(st,1);//in both cases, return 1. - } - return 0; +BUILDIN_FUNC(setmounting) { + TBL_PC* sd; + if( (sd = script_rid2sd(st)) == NULL ) + return 0; + if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ) + script_pushint(st,0);//can't mount with one of these + else { + if( sd->sc.option&OPTION_MOUNTING ) + pc_setoption(sd, sd->sc.option&~OPTION_MOUNTING);//release mount + else + pc_setoption(sd, sd->sc.option|OPTION_MOUNTING);//mount + script_pushint(st,1);//in both cases, return 1. + } + return 0; } /** * Retrieves quantity of arguments provided to callfunc/callsub. * getargcount() -> amount of arguments received in a function **/ -BUILDIN_FUNC(getargcount) -{ - struct script_retinfo *ri; +BUILDIN_FUNC(getargcount) { + struct script_retinfo* ri; - if (st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO) { - ShowError("script:getargcount: used out of function or callsub label!\n"); - st->state = END; - return 1; - } - ri = st->stack->stack_data[st->stack->defsp - 1].u.ri; + if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO ) { + ShowError("script:getargcount: used out of function or callsub label!\n"); + st->state = END; + return 1; + } + ri = st->stack->stack_data[st->stack->defsp - 1].u.ri; - script_pushint(st, ri->nargs); + script_pushint(st, ri->nargs); - return 0; + return 0; } /** * getcharip(<account ID>/<character ID>/<character name>) **/ BUILDIN_FUNC(getcharip) { - struct map_session_data *sd = NULL; - int id = 0; - - /* check if a character name is specified */ - if (script_hasdata(st, 2)) { - if (script_isstring(st, 2)) - sd = map_nick2sd(script_getstr(st, 2)); - else if (script_isint(st, 2) || script_getnum(st, 2)) { - id = script_getnum(st, 2); - sd = (map_id2sd(id) ? map_id2sd(id) : map_charid2sd(id)); - } - } else - sd = script_rid2sd(st); - - /* check for sd and IP */ - if (!sd || !session[sd->fd]->client_addr) { - script_pushconststr(st, ""); - return 0; - } - - /* return the client ip_addr converted for output */ - if (sd && sd->fd && session[sd->fd]) { - /* initiliaze */ - const char *ip_addr = NULL; - uint32 ip; - - /* set ip, ip_addr and convert to ip and push str */ - ip = session[sd->fd]->client_addr; - ip_addr = ip2str(ip, NULL); - script_pushstrcopy(st, ip_addr); - } - - return 0; + struct map_session_data* sd = NULL; + int id = 0; + + /* check if a character name is specified */ + if( script_hasdata(st, 2) ) + { + if (script_isstring(st, 2)) + sd = map_nick2sd(script_getstr(st, 2)); + else if (script_isint(st, 2) || script_getnum(st, 2)) + { + id = script_getnum(st, 2); + sd = (map_id2sd(id) ? map_id2sd(id) : map_charid2sd(id)); + } + } + else + sd = script_rid2sd(st); + + /* check for sd and IP */ + if (!sd || !session[sd->fd]->client_addr) + { + script_pushconststr(st, ""); + return 0; + } + + /* return the client ip_addr converted for output */ + if (sd && sd->fd && session[sd->fd]) + { + /* initiliaze */ + const char *ip_addr = NULL; + uint32 ip; + + /* set ip, ip_addr and convert to ip and push str */ + ip = session[sd->fd]->client_addr; + ip_addr = ip2str(ip, NULL); + script_pushstrcopy(st, ip_addr); + } + + return 0; } /** * is_function(<function name>) -> 1 if function exists, 0 otherwise **/ -BUILDIN_FUNC(is_function) -{ - const char *str = script_getstr(st,2); +BUILDIN_FUNC(is_function) { + const char* str = script_getstr(st,2); - if (strdb_exists(userfunc_db, str)) - script_pushint(st,1); - else - script_pushint(st,0); + if( strdb_exists(userfunc_db, str) ) + script_pushint(st,1); + else + script_pushint(st,0); - return 0; + return 0; } /** * get_revision() -> retrieves the current svn revision (if available) **/ -BUILDIN_FUNC(get_revision) -{ - const char *revision; +BUILDIN_FUNC(get_revision) { + const char * revision; - if ((revision = get_svn_revision()) != 0) - script_pushint(st,atoi(revision)); - else - script_pushint(st,-1);//unknown + if ( (revision = get_svn_revision()) != 0 ) + script_pushint(st,atoi(revision)); + else + script_pushint(st,-1);//unknown - return 0; + return 0; } /** * freeloop(<toggle>) -> toggles this script instance's looping-check ability **/ -BUILDIN_FUNC(freeloop) -{ +BUILDIN_FUNC(freeloop) { - if (script_getnum(st,2)) - st->freeloop = 1; - else - st->freeloop = 0; + if( script_getnum(st,2) ) + st->freeloop = 1; + else + st->freeloop = 0; - script_pushint(st, st->freeloop); + script_pushint(st, st->freeloop); - return 0; + return 0; } /** * @commands (script based) **/ -BUILDIN_FUNC(bindatcmd) -{ - const char *atcmd; - const char *eventName; - int i, level = 0, level2 = 0; - bool create = false; - - atcmd = script_getstr(st,2); - eventName = script_getstr(st,3); - - if (*atcmd == atcommand_symbol || *atcmd == charcommand_symbol) - atcmd++; - - if (script_hasdata(st,4)) level = script_getnum(st,4); - if (script_hasdata(st,5)) level2 = script_getnum(st,5); - - if (atcmd_binding_count == 0) { - CREATE(atcmd_binding,struct atcmd_binding_data *,1); - - create = true; - } else { - ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command,atcmd) == 0); - if (i < atcmd_binding_count) { /* update existent entry */ - safestrncpy(atcmd_binding[i]->npc_event, eventName, 50); - atcmd_binding[i]->level = level; - atcmd_binding[i]->level2 = level2; - } else - create = true; - } +BUILDIN_FUNC(bindatcmd) { + const char* atcmd; + const char* eventName; + int i, level = 0, level2 = 0; + bool create = false; - if (create) { - i = atcmd_binding_count; + atcmd = script_getstr(st,2); + eventName = script_getstr(st,3); - if (atcmd_binding_count++ != 0) - RECREATE(atcmd_binding,struct atcmd_binding_data *,atcmd_binding_count); + if( *atcmd == atcommand_symbol || *atcmd == charcommand_symbol ) + atcmd++; - CREATE(atcmd_binding[i],struct atcmd_binding_data,1); + if( script_hasdata(st,4) ) level = script_getnum(st,4); + if( script_hasdata(st,5) ) level2 = script_getnum(st,5); - safestrncpy(atcmd_binding[i]->command, atcmd, 50); - safestrncpy(atcmd_binding[i]->npc_event, eventName, 50); - atcmd_binding[i]->level = level; - atcmd_binding[i]->level2 = level2; - } + if( atcmd_binding_count == 0 ) { + CREATE(atcmd_binding,struct atcmd_binding_data*,1); - return 0; + create = true; + } else { + ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command,atcmd) == 0); + if( i < atcmd_binding_count ) {/* update existent entry */ + safestrncpy(atcmd_binding[i]->npc_event, eventName, 50); + atcmd_binding[i]->level = level; + atcmd_binding[i]->level2 = level2; + } else + create = true; + } + + if( create ) { + i = atcmd_binding_count; + + if( atcmd_binding_count++ != 0 ) + RECREATE(atcmd_binding,struct atcmd_binding_data*,atcmd_binding_count); + + CREATE(atcmd_binding[i],struct atcmd_binding_data,1); + + safestrncpy(atcmd_binding[i]->command, atcmd, 50); + safestrncpy(atcmd_binding[i]->npc_event, eventName, 50); + atcmd_binding[i]->level = level; + atcmd_binding[i]->level2 = level2; + } + + return 0; } -BUILDIN_FUNC(unbindatcmd) -{ - const char *atcmd; - int i = 0; +BUILDIN_FUNC(unbindatcmd) { + const char* atcmd; + int i = 0; - atcmd = script_getstr(st, 2); + atcmd = script_getstr(st, 2); - if (*atcmd == atcommand_symbol || *atcmd == charcommand_symbol) - atcmd++; + if( *atcmd == atcommand_symbol || *atcmd == charcommand_symbol ) + atcmd++; - if (atcmd_binding_count == 0) { - script_pushint(st, 0); - return 0; - } + if( atcmd_binding_count == 0 ) { + script_pushint(st, 0); + return 0; + } - ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command, atcmd) == 0); - if (i < atcmd_binding_count) { - int cursor = 0; - aFree(atcmd_binding[i]); - atcmd_binding[i] = NULL; - /* compact the list now that we freed a slot somewhere */ - for (i = 0, cursor = 0; i < atcmd_binding_count; i++) { - if (atcmd_binding[i] == NULL) - continue; - - if (cursor != i) { - memmove(&atcmd_binding[cursor], &atcmd_binding[i], sizeof(struct atcmd_binding_data *)); - } + ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command, atcmd) == 0); + if( i < atcmd_binding_count ) { + int cursor = 0; + aFree(atcmd_binding[i]); + atcmd_binding[i] = NULL; + /* compact the list now that we freed a slot somewhere */ + for( i = 0, cursor = 0; i < atcmd_binding_count; i++ ) { + if( atcmd_binding[i] == NULL ) + continue; - cursor++; - } + if( cursor != i ) { + memmove(&atcmd_binding[cursor], &atcmd_binding[i], sizeof(struct atcmd_binding_data*)); + } - if ((atcmd_binding_count = cursor) == 0) - aFree(atcmd_binding); + cursor++; + } - script_pushint(st, 1); - } else - script_pushint(st, 0);/* not found */ + if( (atcmd_binding_count = cursor) == 0 ) + aFree(atcmd_binding); - return 0; + script_pushint(st, 1); + } else + script_pushint(st, 0);/* not found */ + + return 0; } BUILDIN_FUNC(useatcmd) { - TBL_PC dummy_sd; - TBL_PC *sd; - int fd; - const char *cmd; - - cmd = script_getstr(st,2); - - if (st->rid) { - sd = script_rid2sd(st); - fd = sd->fd; - } else { - // Use a dummy character. - sd = &dummy_sd; - fd = 0; - - memset(&dummy_sd, 0, sizeof(TBL_PC)); - if (st->oid) { - struct block_list *bl = map_id2bl(st->oid); - memcpy(&dummy_sd.bl, bl, sizeof(struct block_list)); - if (bl->type == BL_NPC) - safestrncpy(dummy_sd.status.name, ((TBL_NPC *)bl)->name, NAME_LENGTH); - } - } - - // compatibility with previous implementation (deprecated!) - if (cmd[0] != atcommand_symbol) { - cmd += strlen(sd->status.name); - while (*cmd != atcommand_symbol && *cmd != 0) - cmd++; - } - - is_atcommand(fd, sd, cmd, 1); - return 0; + TBL_PC dummy_sd; + TBL_PC* sd; + int fd; + const char* cmd; + + cmd = script_getstr(st,2); + + if( st->rid ) + { + sd = script_rid2sd(st); + fd = sd->fd; + } + else + { // Use a dummy character. + sd = &dummy_sd; + fd = 0; + + memset(&dummy_sd, 0, sizeof(TBL_PC)); + if( st->oid ) + { + struct block_list* bl = map_id2bl(st->oid); + memcpy(&dummy_sd.bl, bl, sizeof(struct block_list)); + if( bl->type == BL_NPC ) + safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH); + } + } + + // compatibility with previous implementation (deprecated!) + if( cmd[0] != atcommand_symbol ) + { + cmd += strlen(sd->status.name); + while( *cmd != atcommand_symbol && *cmd != 0 ) + cmd++; + } + + is_atcommand(fd, sd, cmd, 1); + return 0; } BUILDIN_FUNC(checkre) { - int num; - - num=script_getnum(st,2); - switch (num) { - case 0: -#ifdef RENEWAL - script_pushint(st, 1); -#else - script_pushint(st, 0); -#endif - break; - case 1: -#ifdef RENEWAL_CAST - script_pushint(st, 1); -#else - script_pushint(st, 0); -#endif - break; - case 2: -#ifdef RENEWAL_DROP - script_pushint(st, 1); -#else - script_pushint(st, 0); -#endif - break; - case 3: -#ifdef RENEWAL_EXP - script_pushint(st, 1); -#else - script_pushint(st, 0); -#endif - break; - case 4: -#ifdef RENEWAL_LVDMG - script_pushint(st, 1); -#else - script_pushint(st, 0); -#endif - break; - case 5: -#ifdef RENEWAL_EDP - script_pushint(st, 1); -#else - script_pushint(st, 0); -#endif - break; - case 6: -#ifdef RENEWAL_ASPD - script_pushint(st, 1); -#else - script_pushint(st, 0); -#endif - break; - default: - ShowWarning("buildin_checkre: unknown parameter.\n"); - break; - } - return 0; + int num; + + num=script_getnum(st,2); + switch(num){ + case 0: + #ifdef RENEWAL + script_pushint(st, 1); + #else + script_pushint(st, 0); + #endif + break; + case 1: + #ifdef RENEWAL_CAST + script_pushint(st, 1); + #else + script_pushint(st, 0); + #endif + break; + case 2: + #ifdef RENEWAL_DROP + script_pushint(st, 1); + #else + script_pushint(st, 0); + #endif + break; + case 3: + #ifdef RENEWAL_EXP + script_pushint(st, 1); + #else + script_pushint(st, 0); + #endif + break; + case 4: + #ifdef RENEWAL_LVDMG + script_pushint(st, 1); + #else + script_pushint(st, 0); + #endif + break; + case 5: + #ifdef RENEWAL_EDP + script_pushint(st, 1); + #else + script_pushint(st, 0); + #endif + break; + case 6: + #ifdef RENEWAL_ASPD + script_pushint(st, 1); + #else + script_pushint(st, 0); + #endif + break; + default: + ShowWarning("buildin_checkre: unknown parameter.\n"); + break; + } + return 0; } /* getrandgroupitem <group_id>,<quantity> */ -BUILDIN_FUNC(getrandgroupitem) -{ - TBL_PC *sd; - int i, get_count = 0, flag, nameid, group = script_getnum(st, 2), qty = script_getnum(st,3); - struct item item_tmp; +BUILDIN_FUNC(getrandgroupitem) { + TBL_PC* sd; + int i, get_count = 0, flag, nameid, group = script_getnum(st, 2), qty = script_getnum(st,3); + struct item item_tmp; - if (!(sd = script_rid2sd(st))) - return 0; + if( !( sd = script_rid2sd(st) ) ) + return 0; - if (qty <= 0) { - ShowError("getrandgroupitem: qty is <= 0!\n"); - return 1; - } - if ((nameid = itemdb_searchrandomid(group)) == UNKNOWN_ITEM_ID) { - return 1;/* itemdb_searchrandomid will already scream a error */ - } + if( qty <= 0 ) { + ShowError("getrandgroupitem: qty is <= 0!\n"); + return 1; + } + if( (nameid = itemdb_searchrandomid(group)) == UNKNOWN_ITEM_ID ) { + return 1;/* itemdb_searchrandomid will already scream a error */ + } - memset(&item_tmp,0,sizeof(item_tmp)); + memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = nameid; - item_tmp.identify = itemdb_isidentified(nameid); + item_tmp.nameid = nameid; + item_tmp.identify = itemdb_isidentified(nameid); - //Check if it's stackable. - if (!itemdb_isstackable(nameid)) - get_count = 1; - else - get_count = qty; + //Check if it's stackable. + if (!itemdb_isstackable(nameid)) + get_count = 1; + else + get_count = qty; - for (i = 0; i < qty; i += get_count) { - // if not pet egg - if (!pet_create_egg(sd, nameid)) { - if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) { - clif_additem(sd, 0, 0, flag); - if (pc_candrop(sd,&item_tmp)) - map_addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - } + for (i = 0; i < qty; i += get_count) { + // if not pet egg + if (!pet_create_egg(sd, nameid)) { + if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) { + clif_additem(sd, 0, 0, flag); + if( pc_candrop(sd,&item_tmp) ) + map_addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + } - return 0; -} - -/* cleanmap <map_name>; - * cleanfloor <map_name, <x0>, <y0>, <x1>, <y1>; */ -static int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap) -{ - nullpo_ret(bl); - map_clearflooritem(bl); - - return 0; -} - -BUILDIN_FUNC(cleanmap) -{ - const char *map; - int m = -1, index = -1; - short x0 = 0, y0 = 0, x1 = 0, y1 = 0; - - map = script_getstr(st, 2); - index = mapindex_name2id(map); - if (index) - m = map_mapindex2mapid(index); - - if (!m) - return 1; - - if ((script_lastdata(st) - 2) < 4) { - map_foreachinmap(atcommand_cleanfloor_sub, m, BL_ITEM); - } else { - x0 = script_getnum(st, 3); - y0 = script_getnum(st, 4); - x1 = script_getnum(st, 5); - y1 = script_getnum(st, 6); - if (x0 > 0 && y0 > 0 && x1 > 0 && y1 > 0) { - map_foreachinarea(atcommand_cleanfloor_sub, m, x0, y0, x1, y1, BL_ITEM); - } else { - ShowError("cleanarea: invalid coordinate defined!\n"); - return 1; - } - } - - return 0; + return 0; } @@ -17404,450 +17239,448 @@ BUILDIN_FUNC(deletepset); /// script command definitions /// for an explanation on args, see add_buildin_func struct script_function buildin_func[] = { - // NPC interaction - BUILDIN_DEF(mes,"s*"), - BUILDIN_DEF(next,""), - BUILDIN_DEF(close,""), - BUILDIN_DEF(close2,""), - BUILDIN_DEF(menu,"sl*"), - BUILDIN_DEF(select,"s*"), //for future jA script compatibility - BUILDIN_DEF(prompt,"s*"), - // - BUILDIN_DEF(goto,"l"), - BUILDIN_DEF(callsub,"l*"), - BUILDIN_DEF(callfunc,"s*"), - BUILDIN_DEF(return,"?"), - BUILDIN_DEF(getarg,"i?"), - BUILDIN_DEF(jobchange,"i?"), - BUILDIN_DEF(jobname,"i"), - BUILDIN_DEF(input,"r??"), - BUILDIN_DEF(warp,"sii"), - BUILDIN_DEF(areawarp,"siiiisii??"), - BUILDIN_DEF(warpchar,"siii"), // [LuzZza] - BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X] - BUILDIN_DEF(warpguild,"siii"), // [Fredzilla] - BUILDIN_DEF(setlook,"ii"), - BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it - BUILDIN_DEF(set,"rv"), - BUILDIN_DEF(setarray,"rv*"), - BUILDIN_DEF(cleararray,"rvi"), - BUILDIN_DEF(copyarray,"rri"), - BUILDIN_DEF(getarraysize,"r"), - BUILDIN_DEF(deletearray,"r?"), - BUILDIN_DEF(getelementofarray,"ri"), - BUILDIN_DEF(getitem,"vi?"), - BUILDIN_DEF(rentitem,"vi"), - BUILDIN_DEF(getitem2,"viiiiiiii?"), - BUILDIN_DEF(getnameditem,"vv"), - BUILDIN_DEF2(grouprandomitem,"groupranditem","i"), - BUILDIN_DEF(makeitem,"visii"), - BUILDIN_DEF(delitem,"vi?"), - BUILDIN_DEF(delitem2,"viiiiiiii?"), - BUILDIN_DEF2(enableitemuse,"enable_items",""), - BUILDIN_DEF2(disableitemuse,"disable_items",""), - BUILDIN_DEF(cutin,"si"), - BUILDIN_DEF(viewpoint,"iiiii"), - BUILDIN_DEF(heal,"ii"), - BUILDIN_DEF(itemheal,"ii"), - BUILDIN_DEF(percentheal,"ii"), - BUILDIN_DEF(rand,"i?"), - BUILDIN_DEF(countitem,"v"), - BUILDIN_DEF(countitem2,"viiiiiii"), - BUILDIN_DEF(checkweight,"vi*"), - BUILDIN_DEF(checkweight2,"rr"), - BUILDIN_DEF(readparam,"i?"), - BUILDIN_DEF(getcharid,"i?"), - BUILDIN_DEF(getnpcid,"i?"), - BUILDIN_DEF(getpartyname,"i"), - BUILDIN_DEF(getpartymember,"i?"), - BUILDIN_DEF(getpartyleader,"i?"), - BUILDIN_DEF(getguildname,"i"), - BUILDIN_DEF(getguildmaster,"i"), - BUILDIN_DEF(getguildmasterid,"i"), - BUILDIN_DEF(strcharinfo,"i"), - BUILDIN_DEF(strnpcinfo,"i"), - BUILDIN_DEF(getequipid,"i"), - BUILDIN_DEF(getequipname,"i"), - BUILDIN_DEF(getbrokenid,"i"), // [Valaris] - BUILDIN_DEF(repair,"i"), // [Valaris] - BUILDIN_DEF(repairall,""), - BUILDIN_DEF(getequipisequiped,"i"), - BUILDIN_DEF(getequipisenableref,"i"), - BUILDIN_DEF(getequipisidentify,"i"), - BUILDIN_DEF(getequiprefinerycnt,"i"), - BUILDIN_DEF(getequipweaponlv,"i"), - BUILDIN_DEF(getequippercentrefinery,"i"), - BUILDIN_DEF(successrefitem,"i"), - BUILDIN_DEF(failedrefitem,"i"), - BUILDIN_DEF(downrefitem,"i"), - BUILDIN_DEF(statusup,"i"), - BUILDIN_DEF(statusup2,"ii"), - BUILDIN_DEF(bonus,"iv"), - BUILDIN_DEF2(bonus,"bonus2","ivi"), - BUILDIN_DEF2(bonus,"bonus3","ivii"), - BUILDIN_DEF2(bonus,"bonus4","ivvii"), - BUILDIN_DEF2(bonus,"bonus5","ivviii"), - BUILDIN_DEF(autobonus,"sii??"), - BUILDIN_DEF(autobonus2,"sii??"), - BUILDIN_DEF(autobonus3,"siiv?"), - BUILDIN_DEF(skill,"vi?"), - BUILDIN_DEF(addtoskill,"vi?"), // [Valaris] - BUILDIN_DEF(guildskill,"vi"), - BUILDIN_DEF(getskilllv,"v"), - BUILDIN_DEF(getgdskilllv,"iv"), - BUILDIN_DEF(basicskillcheck,""), - BUILDIN_DEF(getgmlevel,""), - BUILDIN_DEF(getgroupid,""), - BUILDIN_DEF(end,""), - BUILDIN_DEF(checkoption,"i"), - BUILDIN_DEF(setoption,"i?"), - BUILDIN_DEF(setcart,"?"), - BUILDIN_DEF(checkcart,""), - BUILDIN_DEF(setfalcon,"?"), - BUILDIN_DEF(checkfalcon,""), - BUILDIN_DEF(setriding,"?"), - BUILDIN_DEF(checkriding,""), - BUILDIN_DEF(checkwug,""), - BUILDIN_DEF(checkmadogear,""), - BUILDIN_DEF(setmadogear,"?"), - BUILDIN_DEF2(savepoint,"save","sii"), - BUILDIN_DEF(savepoint,"sii"), - BUILDIN_DEF(gettimetick,"i"), - BUILDIN_DEF(gettime,"i"), - BUILDIN_DEF(gettimestr,"si"), - BUILDIN_DEF(openstorage,""), - BUILDIN_DEF(guildopenstorage,""), - BUILDIN_DEF(itemskill,"vi"), - BUILDIN_DEF(produce,"i"), - BUILDIN_DEF(cooking,"i"), - BUILDIN_DEF(monster,"siisii???"), - BUILDIN_DEF(getmobdrops,"i"), - BUILDIN_DEF(areamonster,"siiiisii???"), - BUILDIN_DEF(killmonster,"ss?"), - BUILDIN_DEF(killmonsterall,"s?"), - BUILDIN_DEF(clone,"siisi????"), - BUILDIN_DEF(doevent,"s"), - BUILDIN_DEF(donpcevent,"s"), - BUILDIN_DEF(cmdothernpc,"ss"), - BUILDIN_DEF(addtimer,"is"), - BUILDIN_DEF(deltimer,"s"), - BUILDIN_DEF(addtimercount,"si"), - BUILDIN_DEF(initnpctimer,"??"), - BUILDIN_DEF(stopnpctimer,"??"), - BUILDIN_DEF(startnpctimer,"??"), - BUILDIN_DEF(setnpctimer,"i?"), - BUILDIN_DEF(getnpctimer,"i?"), - BUILDIN_DEF(attachnpctimer,"?"), // attached the player id to the npc timer [Celest] - BUILDIN_DEF(detachnpctimer,"?"), // detached the player id from the npc timer [Celest] - BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex] - BUILDIN_DEF(announce,"si?????"), - BUILDIN_DEF(mapannounce,"ssi?????"), - BUILDIN_DEF(areaannounce,"siiiisi?????"), - BUILDIN_DEF(getusers,"i"), - BUILDIN_DEF(getmapguildusers,"si"), - BUILDIN_DEF(getmapusers,"s"), - BUILDIN_DEF(getareausers,"siiii"), - BUILDIN_DEF(getareadropitem,"siiiiv"), - BUILDIN_DEF(enablenpc,"s"), - BUILDIN_DEF(disablenpc,"s"), - BUILDIN_DEF(hideoffnpc,"s"), - BUILDIN_DEF(hideonnpc,"s"), - BUILDIN_DEF(sc_start,"iii?"), - BUILDIN_DEF(sc_start2,"iiii?"), - BUILDIN_DEF(sc_start4,"iiiiii?"), - BUILDIN_DEF(sc_end,"i?"), - BUILDIN_DEF(getstatus, "i?"), - BUILDIN_DEF(getscrate,"ii?"), - BUILDIN_DEF(debugmes,"s"), - BUILDIN_DEF2(catchpet,"pet","i"), - BUILDIN_DEF2(birthpet,"bpet",""), - BUILDIN_DEF(resetlvl,"i"), - BUILDIN_DEF(resetstatus,""), - BUILDIN_DEF(resetskill,""), - BUILDIN_DEF(skillpointcount,""), - BUILDIN_DEF(changebase,"i?"), - BUILDIN_DEF(changesex,""), - BUILDIN_DEF(waitingroom,"si?????"), - BUILDIN_DEF(delwaitingroom,"?"), - BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"), - BUILDIN_DEF(enablewaitingroomevent,"?"), - BUILDIN_DEF(disablewaitingroomevent,"?"), - BUILDIN_DEF2(enablewaitingroomevent,"enablearena",""), // Added by RoVeRT - BUILDIN_DEF2(disablewaitingroomevent,"disablearena",""), // Added by RoVeRT - BUILDIN_DEF(getwaitingroomstate,"i?"), - BUILDIN_DEF(warpwaitingpc,"sii?"), - BUILDIN_DEF(attachrid,"i"), - BUILDIN_DEF(detachrid,""), - BUILDIN_DEF(isloggedin,"i?"), - BUILDIN_DEF(setmapflagnosave,"ssii"), - BUILDIN_DEF(getmapflag,"si"), - BUILDIN_DEF(setmapflag,"si?"), - BUILDIN_DEF(removemapflag,"si?"), - BUILDIN_DEF(pvpon,"s"), - BUILDIN_DEF(pvpoff,"s"), - BUILDIN_DEF(gvgon,"s"), - BUILDIN_DEF(gvgoff,"s"), - BUILDIN_DEF(emotion,"i??"), - BUILDIN_DEF(maprespawnguildid,"sii"), - BUILDIN_DEF(agitstart,""), // <Agit> - BUILDIN_DEF(agitend,""), - BUILDIN_DEF(agitcheck,""), // <Agitcheck> - BUILDIN_DEF(flagemblem,"i"), // Flag Emblem - BUILDIN_DEF(getcastlename,"s"), - BUILDIN_DEF(getcastledata,"si"), - BUILDIN_DEF(setcastledata,"sii"), - BUILDIN_DEF(requestguildinfo,"i?"), - BUILDIN_DEF(getequipcardcnt,"i"), - BUILDIN_DEF(successremovecards,"i"), - BUILDIN_DEF(failedremovecards,"ii"), - BUILDIN_DEF(marriage,"s"), - BUILDIN_DEF2(wedding_effect,"wedding",""), - BUILDIN_DEF(divorce,""), - BUILDIN_DEF(ispartneron,""), - BUILDIN_DEF(getpartnerid,""), - BUILDIN_DEF(getchildid,""), - BUILDIN_DEF(getmotherid,""), - BUILDIN_DEF(getfatherid,""), - BUILDIN_DEF(warppartner,"sii"), - BUILDIN_DEF(getitemname,"v"), - BUILDIN_DEF(getitemslots,"i"), - BUILDIN_DEF(makepet,"i"), - BUILDIN_DEF(getexp,"ii"), - BUILDIN_DEF(getinventorylist,""), - BUILDIN_DEF(getskilllist,""), - BUILDIN_DEF(clearitem,""), - BUILDIN_DEF(classchange,"ii"), - BUILDIN_DEF(misceffect,"i"), - BUILDIN_DEF(playBGM,"s"), - BUILDIN_DEF(playBGMall,"s?????"), - BUILDIN_DEF(soundeffect,"si"), - BUILDIN_DEF(soundeffectall,"si?????"), // SoundEffectAll [Codemaster] - BUILDIN_DEF(strmobinfo,"ii"), // display mob data [Valaris] - BUILDIN_DEF(guardian,"siisi??"), // summon guardians - BUILDIN_DEF(guardianinfo,"sii"), // display guardian data [Valaris] - BUILDIN_DEF(petskillbonus,"iiii"), // [Valaris] - BUILDIN_DEF(petrecovery,"ii"), // [Valaris] - BUILDIN_DEF(petloot,"i"), // [Valaris] - BUILDIN_DEF(petheal,"iiii"), // [Valaris] - BUILDIN_DEF(petskillattack,"viii"), // [Skotlex] - BUILDIN_DEF(petskillattack2,"viiii"), // [Valaris] - BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex] - BUILDIN_DEF(skilleffect,"vi"), // skill effect [Celest] - BUILDIN_DEF(npcskilleffect,"viii"), // npc skill effect [Valaris] - BUILDIN_DEF(specialeffect,"i??"), // npc skill effect [Valaris] - BUILDIN_DEF(specialeffect2,"i??"), // skill effect on players[Valaris] - BUILDIN_DEF(nude,""), // nude command [Valaris] - BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT - BUILDIN_DEF(atcommand,"s"), // [MouseJstr] - BUILDIN_DEF2(atcommand,"charcommand","s"), // [MouseJstr] - BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr] - BUILDIN_DEF(message,"ss"), // [MouseJstr] - BUILDIN_DEF(npctalk,"s"), // [Valaris] - BUILDIN_DEF(mobcount,"ss"), - BUILDIN_DEF(getlook,"i"), - BUILDIN_DEF(getsavepoint,"i"), - BUILDIN_DEF(npcspeed,"i"), // [Valaris] - BUILDIN_DEF(npcwalkto,"ii"), // [Valaris] - BUILDIN_DEF(npcstop,""), // [Valaris] - BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus] - BUILDIN_DEF(checkoption1,"i"), - BUILDIN_DEF(checkoption2,"i"), - BUILDIN_DEF(guildgetexp,"i"), - BUILDIN_DEF(guildchangegm,"is"), - BUILDIN_DEF(logmes,"s"), //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus] - BUILDIN_DEF(summon,"si??"), // summons a slave monster [Celest] - BUILDIN_DEF(isnight,""), // check whether it is night time [Celest] - BUILDIN_DEF(isday,""), // check whether it is day time [Celest] - BUILDIN_DEF(isequipped,"i*"), // check whether another item/card has been equipped [Celest] - BUILDIN_DEF(isequippedcnt,"i*"), // check how many items/cards are being equipped [Celest] - BUILDIN_DEF(cardscnt,"i*"), // check how many items/cards are being equipped in the same arm [Lupus] - BUILDIN_DEF(getrefine,""), // returns the refined number of the current item, or an item with index specified [celest] - BUILDIN_DEF(night,""), // sets the server to night time - BUILDIN_DEF(day,""), // sets the server to day time + // NPC interaction + BUILDIN_DEF(mes,"s*"), + BUILDIN_DEF(next,""), + BUILDIN_DEF(close,""), + BUILDIN_DEF(close2,""), + BUILDIN_DEF(menu,"sl*"), + BUILDIN_DEF(select,"s*"), //for future jA script compatibility + BUILDIN_DEF(prompt,"s*"), + // + BUILDIN_DEF(goto,"l"), + BUILDIN_DEF(callsub,"l*"), + BUILDIN_DEF(callfunc,"s*"), + BUILDIN_DEF(return,"?"), + BUILDIN_DEF(getarg,"i?"), + BUILDIN_DEF(jobchange,"i?"), + BUILDIN_DEF(jobname,"i"), + BUILDIN_DEF(input,"r??"), + BUILDIN_DEF(warp,"sii"), + BUILDIN_DEF(areawarp,"siiiisii??"), + BUILDIN_DEF(warpchar,"siii"), // [LuzZza] + BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X] + BUILDIN_DEF(warpguild,"siii"), // [Fredzilla] + BUILDIN_DEF(setlook,"ii"), + BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it + BUILDIN_DEF(set,"rv"), + BUILDIN_DEF(setarray,"rv*"), + BUILDIN_DEF(cleararray,"rvi"), + BUILDIN_DEF(copyarray,"rri"), + BUILDIN_DEF(getarraysize,"r"), + BUILDIN_DEF(deletearray,"r?"), + BUILDIN_DEF(getelementofarray,"ri"), + BUILDIN_DEF(getitem,"vi?"), + BUILDIN_DEF(rentitem,"vi"), + BUILDIN_DEF(getitem2,"viiiiiiii?"), + BUILDIN_DEF(getnameditem,"vv"), + BUILDIN_DEF2(grouprandomitem,"groupranditem","i"), + BUILDIN_DEF(makeitem,"visii"), + BUILDIN_DEF(delitem,"vi?"), + BUILDIN_DEF(delitem2,"viiiiiiii?"), + BUILDIN_DEF2(enableitemuse,"enable_items",""), + BUILDIN_DEF2(disableitemuse,"disable_items",""), + BUILDIN_DEF(cutin,"si"), + BUILDIN_DEF(viewpoint,"iiiii"), + BUILDIN_DEF(heal,"ii"), + BUILDIN_DEF(itemheal,"ii"), + BUILDIN_DEF(percentheal,"ii"), + BUILDIN_DEF(rand,"i?"), + BUILDIN_DEF(countitem,"v"), + BUILDIN_DEF(countitem2,"viiiiiii"), + BUILDIN_DEF(checkweight,"vi*"), + BUILDIN_DEF(checkweight2,"rr"), + BUILDIN_DEF(readparam,"i?"), + BUILDIN_DEF(getcharid,"i?"), + BUILDIN_DEF(getnpcid,"i?"), + BUILDIN_DEF(getpartyname,"i"), + BUILDIN_DEF(getpartymember,"i?"), + BUILDIN_DEF(getpartyleader,"i?"), + BUILDIN_DEF(getguildname,"i"), + BUILDIN_DEF(getguildmaster,"i"), + BUILDIN_DEF(getguildmasterid,"i"), + BUILDIN_DEF(strcharinfo,"i"), + BUILDIN_DEF(strnpcinfo,"i"), + BUILDIN_DEF(getequipid,"i"), + BUILDIN_DEF(getequipname,"i"), + BUILDIN_DEF(getbrokenid,"i"), // [Valaris] + BUILDIN_DEF(repair,"i"), // [Valaris] + BUILDIN_DEF(repairall,""), + BUILDIN_DEF(getequipisequiped,"i"), + BUILDIN_DEF(getequipisenableref,"i"), + BUILDIN_DEF(getequipisidentify,"i"), + BUILDIN_DEF(getequiprefinerycnt,"i"), + BUILDIN_DEF(getequipweaponlv,"i"), + BUILDIN_DEF(getequippercentrefinery,"i"), + BUILDIN_DEF(successrefitem,"i"), + BUILDIN_DEF(failedrefitem,"i"), + BUILDIN_DEF(downrefitem,"i"), + BUILDIN_DEF(statusup,"i"), + BUILDIN_DEF(statusup2,"ii"), + BUILDIN_DEF(bonus,"iv"), + BUILDIN_DEF2(bonus,"bonus2","ivi"), + BUILDIN_DEF2(bonus,"bonus3","ivii"), + BUILDIN_DEF2(bonus,"bonus4","ivvii"), + BUILDIN_DEF2(bonus,"bonus5","ivviii"), + BUILDIN_DEF(autobonus,"sii??"), + BUILDIN_DEF(autobonus2,"sii??"), + BUILDIN_DEF(autobonus3,"siiv?"), + BUILDIN_DEF(skill,"vi?"), + BUILDIN_DEF(addtoskill,"vi?"), // [Valaris] + BUILDIN_DEF(guildskill,"vi"), + BUILDIN_DEF(getskilllv,"v"), + BUILDIN_DEF(getgdskilllv,"iv"), + BUILDIN_DEF(basicskillcheck,""), + BUILDIN_DEF(getgmlevel,""), + BUILDIN_DEF(getgroupid,""), + BUILDIN_DEF(end,""), + BUILDIN_DEF(checkoption,"i"), + BUILDIN_DEF(setoption,"i?"), + BUILDIN_DEF(setcart,"?"), + BUILDIN_DEF(checkcart,""), + BUILDIN_DEF(setfalcon,"?"), + BUILDIN_DEF(checkfalcon,""), + BUILDIN_DEF(setriding,"?"), + BUILDIN_DEF(checkriding,""), + BUILDIN_DEF(checkwug,""), + BUILDIN_DEF(checkmadogear,""), + BUILDIN_DEF(setmadogear,"?"), + BUILDIN_DEF2(savepoint,"save","sii"), + BUILDIN_DEF(savepoint,"sii"), + BUILDIN_DEF(gettimetick,"i"), + BUILDIN_DEF(gettime,"i"), + BUILDIN_DEF(gettimestr,"si"), + BUILDIN_DEF(openstorage,""), + BUILDIN_DEF(guildopenstorage,""), + BUILDIN_DEF(itemskill,"vi"), + BUILDIN_DEF(produce,"i"), + BUILDIN_DEF(cooking,"i"), + BUILDIN_DEF(monster,"siisii???"), + BUILDIN_DEF(getmobdrops,"i"), + BUILDIN_DEF(areamonster,"siiiisii???"), + BUILDIN_DEF(killmonster,"ss?"), + BUILDIN_DEF(killmonsterall,"s?"), + BUILDIN_DEF(clone,"siisi????"), + BUILDIN_DEF(doevent,"s"), + BUILDIN_DEF(donpcevent,"s"), + BUILDIN_DEF(cmdothernpc,"ss"), + BUILDIN_DEF(addtimer,"is"), + BUILDIN_DEF(deltimer,"s"), + BUILDIN_DEF(addtimercount,"si"), + BUILDIN_DEF(initnpctimer,"??"), + BUILDIN_DEF(stopnpctimer,"??"), + BUILDIN_DEF(startnpctimer,"??"), + BUILDIN_DEF(setnpctimer,"i?"), + BUILDIN_DEF(getnpctimer,"i?"), + BUILDIN_DEF(attachnpctimer,"?"), // attached the player id to the npc timer [Celest] + BUILDIN_DEF(detachnpctimer,"?"), // detached the player id from the npc timer [Celest] + BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex] + BUILDIN_DEF(announce,"si?????"), + BUILDIN_DEF(mapannounce,"ssi?????"), + BUILDIN_DEF(areaannounce,"siiiisi?????"), + BUILDIN_DEF(getusers,"i"), + BUILDIN_DEF(getmapguildusers,"si"), + BUILDIN_DEF(getmapusers,"s"), + BUILDIN_DEF(getareausers,"siiii"), + BUILDIN_DEF(getareadropitem,"siiiiv"), + BUILDIN_DEF(enablenpc,"s"), + BUILDIN_DEF(disablenpc,"s"), + BUILDIN_DEF(hideoffnpc,"s"), + BUILDIN_DEF(hideonnpc,"s"), + BUILDIN_DEF(sc_start,"iii?"), + BUILDIN_DEF(sc_start2,"iiii?"), + BUILDIN_DEF(sc_start4,"iiiiii?"), + BUILDIN_DEF(sc_end,"i?"), + BUILDIN_DEF(getstatus, "i?"), + BUILDIN_DEF(getscrate,"ii?"), + BUILDIN_DEF(debugmes,"s"), + BUILDIN_DEF2(catchpet,"pet","i"), + BUILDIN_DEF2(birthpet,"bpet",""), + BUILDIN_DEF(resetlvl,"i"), + BUILDIN_DEF(resetstatus,""), + BUILDIN_DEF(resetskill,""), + BUILDIN_DEF(skillpointcount,""), + BUILDIN_DEF(changebase,"i?"), + BUILDIN_DEF(changesex,""), + BUILDIN_DEF(waitingroom,"si?????"), + BUILDIN_DEF(delwaitingroom,"?"), + BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"), + BUILDIN_DEF(enablewaitingroomevent,"?"), + BUILDIN_DEF(disablewaitingroomevent,"?"), + BUILDIN_DEF2(enablewaitingroomevent,"enablearena",""), // Added by RoVeRT + BUILDIN_DEF2(disablewaitingroomevent,"disablearena",""), // Added by RoVeRT + BUILDIN_DEF(getwaitingroomstate,"i?"), + BUILDIN_DEF(warpwaitingpc,"sii?"), + BUILDIN_DEF(attachrid,"i"), + BUILDIN_DEF(detachrid,""), + BUILDIN_DEF(isloggedin,"i?"), + BUILDIN_DEF(setmapflagnosave,"ssii"), + BUILDIN_DEF(getmapflag,"si"), + BUILDIN_DEF(setmapflag,"si?"), + BUILDIN_DEF(removemapflag,"si?"), + BUILDIN_DEF(pvpon,"s"), + BUILDIN_DEF(pvpoff,"s"), + BUILDIN_DEF(gvgon,"s"), + BUILDIN_DEF(gvgoff,"s"), + BUILDIN_DEF(emotion,"i??"), + BUILDIN_DEF(maprespawnguildid,"sii"), + BUILDIN_DEF(agitstart,""), // <Agit> + BUILDIN_DEF(agitend,""), + BUILDIN_DEF(agitcheck,""), // <Agitcheck> + BUILDIN_DEF(flagemblem,"i"), // Flag Emblem + BUILDIN_DEF(getcastlename,"s"), + BUILDIN_DEF(getcastledata,"si"), + BUILDIN_DEF(setcastledata,"sii"), + BUILDIN_DEF(requestguildinfo,"i?"), + BUILDIN_DEF(getequipcardcnt,"i"), + BUILDIN_DEF(successremovecards,"i"), + BUILDIN_DEF(failedremovecards,"ii"), + BUILDIN_DEF(marriage,"s"), + BUILDIN_DEF2(wedding_effect,"wedding",""), + BUILDIN_DEF(divorce,""), + BUILDIN_DEF(ispartneron,""), + BUILDIN_DEF(getpartnerid,""), + BUILDIN_DEF(getchildid,""), + BUILDIN_DEF(getmotherid,""), + BUILDIN_DEF(getfatherid,""), + BUILDIN_DEF(warppartner,"sii"), + BUILDIN_DEF(getitemname,"v"), + BUILDIN_DEF(getitemslots,"i"), + BUILDIN_DEF(makepet,"i"), + BUILDIN_DEF(getexp,"ii"), + BUILDIN_DEF(getinventorylist,""), + BUILDIN_DEF(getskilllist,""), + BUILDIN_DEF(clearitem,""), + BUILDIN_DEF(classchange,"ii"), + BUILDIN_DEF(misceffect,"i"), + BUILDIN_DEF(playBGM,"s"), + BUILDIN_DEF(playBGMall,"s?????"), + BUILDIN_DEF(soundeffect,"si"), + BUILDIN_DEF(soundeffectall,"si?????"), // SoundEffectAll [Codemaster] + BUILDIN_DEF(strmobinfo,"ii"), // display mob data [Valaris] + BUILDIN_DEF(guardian,"siisi??"), // summon guardians + BUILDIN_DEF(guardianinfo,"sii"), // display guardian data [Valaris] + BUILDIN_DEF(petskillbonus,"iiii"), // [Valaris] + BUILDIN_DEF(petrecovery,"ii"), // [Valaris] + BUILDIN_DEF(petloot,"i"), // [Valaris] + BUILDIN_DEF(petheal,"iiii"), // [Valaris] + BUILDIN_DEF(petskillattack,"viii"), // [Skotlex] + BUILDIN_DEF(petskillattack2,"viiii"), // [Valaris] + BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex] + BUILDIN_DEF(skilleffect,"vi"), // skill effect [Celest] + BUILDIN_DEF(npcskilleffect,"viii"), // npc skill effect [Valaris] + BUILDIN_DEF(specialeffect,"i??"), // npc skill effect [Valaris] + BUILDIN_DEF(specialeffect2,"i??"), // skill effect on players[Valaris] + BUILDIN_DEF(nude,""), // nude command [Valaris] + BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT + BUILDIN_DEF(atcommand,"s"), // [MouseJstr] + BUILDIN_DEF2(atcommand,"charcommand","s"), // [MouseJstr] + BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr] + BUILDIN_DEF(message,"ss"), // [MouseJstr] + BUILDIN_DEF(npctalk,"s"), // [Valaris] + BUILDIN_DEF(mobcount,"ss"), + BUILDIN_DEF(getlook,"i"), + BUILDIN_DEF(getsavepoint,"i"), + BUILDIN_DEF(npcspeed,"i"), // [Valaris] + BUILDIN_DEF(npcwalkto,"ii"), // [Valaris] + BUILDIN_DEF(npcstop,""), // [Valaris] + BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus] + BUILDIN_DEF(checkoption1,"i"), + BUILDIN_DEF(checkoption2,"i"), + BUILDIN_DEF(guildgetexp,"i"), + BUILDIN_DEF(guildchangegm,"is"), + BUILDIN_DEF(logmes,"s"), //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus] + BUILDIN_DEF(summon,"si??"), // summons a slave monster [Celest] + BUILDIN_DEF(isnight,""), // check whether it is night time [Celest] + BUILDIN_DEF(isday,""), // check whether it is day time [Celest] + BUILDIN_DEF(isequipped,"i*"), // check whether another item/card has been equipped [Celest] + BUILDIN_DEF(isequippedcnt,"i*"), // check how many items/cards are being equipped [Celest] + BUILDIN_DEF(cardscnt,"i*"), // check how many items/cards are being equipped in the same arm [Lupus] + BUILDIN_DEF(getrefine,""), // returns the refined number of the current item, or an item with index specified [celest] + BUILDIN_DEF(night,""), // sets the server to night time + BUILDIN_DEF(day,""), // sets the server to day time #ifdef PCRE_SUPPORT - BUILDIN_DEF(defpattern,"iss"), // Define pattern to listen for [MouseJstr] - BUILDIN_DEF(activatepset,"i"), // Activate a pattern set [MouseJstr] - BUILDIN_DEF(deactivatepset,"i"), // Deactive a pattern set [MouseJstr] - BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr] + BUILDIN_DEF(defpattern,"iss"), // Define pattern to listen for [MouseJstr] + BUILDIN_DEF(activatepset,"i"), // Activate a pattern set [MouseJstr] + BUILDIN_DEF(deactivatepset,"i"), // Deactive a pattern set [MouseJstr] + BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr] #endif - BUILDIN_DEF(dispbottom,"s"), //added from jA [Lupus] - BUILDIN_DEF(getusersname,""), - BUILDIN_DEF(recovery,""), - BUILDIN_DEF(getpetinfo,"i"), - BUILDIN_DEF(gethominfo,"i"), - BUILDIN_DEF(getmercinfo,"i?"), - BUILDIN_DEF(checkequipedcard,"i"), - BUILDIN_DEF(jump_zero,"il"), //for future jA script compatibility - BUILDIN_DEF(globalmes,"s?"), //end jA addition - BUILDIN_DEF(unequip,"i"), // unequip command [Spectre] - BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris] - BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris] - BUILDIN_DEF(charat,"si"), - BUILDIN_DEF(setchar,"ssi"), - BUILDIN_DEF(insertchar,"ssi"), - BUILDIN_DEF(delchar,"si"), - BUILDIN_DEF(strtoupper,"s"), - BUILDIN_DEF(strtolower,"s"), - BUILDIN_DEF(charisupper, "si"), - BUILDIN_DEF(charislower, "si"), - BUILDIN_DEF(substr,"sii"), - BUILDIN_DEF(explode, "rss"), - BUILDIN_DEF(implode, "r?"), - BUILDIN_DEF(sprintf,"s*"), // [Mirei] - BUILDIN_DEF(sscanf,"ss*"), // [Mirei] - BUILDIN_DEF(strpos,"ss?"), - BUILDIN_DEF(replacestr,"sss??"), - BUILDIN_DEF(countstr,"ss?"), - BUILDIN_DEF(setnpcdisplay,"sv??"), - BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine. - BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info - BUILDIN_DEF(setiteminfo,"iii"), //[Lupus] set Items Buy / sell Price, etc info - BUILDIN_DEF(getequipcardid,"ii"), //[Lupus] returns CARD ID or other info from CARD slot N of equipped item - // [zBuffer] List of mathematics commands ---> - BUILDIN_DEF(sqrt,"i"), - BUILDIN_DEF(pow,"ii"), - BUILDIN_DEF(distance,"iiii"), - // <--- [zBuffer] List of mathematics commands - BUILDIN_DEF(md5,"s"), - // [zBuffer] List of dynamic var commands ---> - BUILDIN_DEF(getd,"s"), - BUILDIN_DEF(setd,"sv"), - // <--- [zBuffer] List of dynamic var commands - BUILDIN_DEF(petstat,"i"), - BUILDIN_DEF(callshop,"s?"), // [Skotlex] - BUILDIN_DEF(npcshopitem,"sii*"), // [Lance] - BUILDIN_DEF(npcshopadditem,"sii*"), - BUILDIN_DEF(npcshopdelitem,"si*"), - BUILDIN_DEF(npcshopattach,"s?"), - BUILDIN_DEF(equip,"i"), - BUILDIN_DEF(autoequip,"ii"), - BUILDIN_DEF(setbattleflag,"si"), - BUILDIN_DEF(getbattleflag,"s"), - BUILDIN_DEF(setitemscript,"is?"), //Set NEW item bonus script. Lupus - BUILDIN_DEF(disguise,"i"), //disguise player. Lupus - BUILDIN_DEF(undisguise,""), //undisguise player. Lupus - BUILDIN_DEF(getmonsterinfo,"ii"), //Lupus - BUILDIN_DEF(axtoi,"s"), - BUILDIN_DEF(query_sql,"s*"), - BUILDIN_DEF(query_logsql,"s*"), - BUILDIN_DEF(escape_sql,"v"), - BUILDIN_DEF(atoi,"s"), - // [zBuffer] List of player cont commands ---> - BUILDIN_DEF(rid2name,"i"), - BUILDIN_DEF(pcfollow,"ii"), - BUILDIN_DEF(pcstopfollow,"i"), - BUILDIN_DEF(pcblockmove,"ii"), - // <--- [zBuffer] List of player cont commands - // [zBuffer] List of mob control commands ---> - BUILDIN_DEF(unitwalk,"ii?"), - BUILDIN_DEF(unitkill,"i"), - BUILDIN_DEF(unitwarp,"isii"), - BUILDIN_DEF(unitattack,"iv?"), - BUILDIN_DEF(unitstop,"i"), - BUILDIN_DEF(unittalk,"is"), - BUILDIN_DEF(unitemote,"ii"), - BUILDIN_DEF(unitskilluseid,"ivi?"), // originally by Qamera [Celest] - BUILDIN_DEF(unitskillusepos,"iviii"), // [Celest] - // <--- [zBuffer] List of mob control commands - BUILDIN_DEF(sleep,"i"), - BUILDIN_DEF(sleep2,"i"), - BUILDIN_DEF(awake,"s"), - BUILDIN_DEF(getvariableofnpc,"rs"), - BUILDIN_DEF(warpportal,"iisii"), - BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn] - BUILDIN_DEF2(homunculus_mutate,"hommutate","?"), - BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus] - BUILDIN_DEF(eaclass,"?"), //[Skotlex] - BUILDIN_DEF(roclass,"i?"), //[Skotlex] - BUILDIN_DEF(checkvending,"?"), - BUILDIN_DEF(checkchatting,"?"), - BUILDIN_DEF(openmail,""), - BUILDIN_DEF(openauction,""), - BUILDIN_DEF(checkcell,"siii"), - BUILDIN_DEF(setcell,"siiiiii"), - BUILDIN_DEF(setwall,"siiiiis"), - BUILDIN_DEF(delwall,"s"), - BUILDIN_DEF(searchitem,"rs"), - BUILDIN_DEF(mercenary_create,"ii"), - BUILDIN_DEF(mercenary_heal,"ii"), - BUILDIN_DEF(mercenary_sc_start,"iii"), - BUILDIN_DEF(mercenary_get_calls,"i"), - BUILDIN_DEF(mercenary_get_faith,"i"), - BUILDIN_DEF(mercenary_set_calls,"ii"), - BUILDIN_DEF(mercenary_set_faith,"ii"), - BUILDIN_DEF(readbook,"ii"), - BUILDIN_DEF(setfont,"i"), - BUILDIN_DEF(areamobuseskill,"siiiiviiiii"), - BUILDIN_DEF(progressbar,"si"), - BUILDIN_DEF(pushpc,"ii"), - BUILDIN_DEF(buyingstore,"i"), - BUILDIN_DEF(searchstores,"ii"), - BUILDIN_DEF(showdigit,"i?"), - // WoE SE - BUILDIN_DEF(agitstart2,""), - BUILDIN_DEF(agitend2,""), - BUILDIN_DEF(agitcheck2,""), - // BattleGround - BUILDIN_DEF(waitingroom2bg,"siiss?"), - BUILDIN_DEF(waitingroom2bg_single,"isiis"), - BUILDIN_DEF(bg_team_setxy,"iii"), - BUILDIN_DEF(bg_warp,"isii"), - BUILDIN_DEF(bg_monster,"isiisi?"), - BUILDIN_DEF(bg_monster_set_team,"ii"), - BUILDIN_DEF(bg_leave,""), - BUILDIN_DEF(bg_destroy,"i"), - BUILDIN_DEF(areapercentheal,"siiiiii"), - BUILDIN_DEF(bg_get_data,"ii"), - BUILDIN_DEF(bg_getareausers,"isiiii"), - BUILDIN_DEF(bg_updatescore,"sii"), - - // Instancing - BUILDIN_DEF(instance_create,"si"), - BUILDIN_DEF(instance_destroy,"?"), - BUILDIN_DEF(instance_attachmap,"si?"), - BUILDIN_DEF(instance_detachmap,"s?"), - BUILDIN_DEF(instance_attach,"i"), - BUILDIN_DEF(instance_id,"?"), - BUILDIN_DEF(instance_set_timeout,"ii?"), - BUILDIN_DEF(instance_init,"i"), - BUILDIN_DEF(instance_announce,"isi?????"), - BUILDIN_DEF(instance_npcname,"s?"), - BUILDIN_DEF(has_instance,"s?"), - BUILDIN_DEF(instance_warpall,"sii?"), - BUILDIN_DEF(instance_check_party,"i???"), - /** - * 3rd-related - **/ - BUILDIN_DEF(makerune,"i"), - BUILDIN_DEF(checkdragon,""),//[Ind] - BUILDIN_DEF(setdragon,"?"),//[Ind] - BUILDIN_DEF(ismounting,""),//[Ind] - BUILDIN_DEF(setmounting,""),//[Ind] - BUILDIN_DEF(checkre,"i"), - /** - * rAthena and beyond! - **/ - BUILDIN_DEF(getargcount,""), - BUILDIN_DEF(getcharip,"?"), - BUILDIN_DEF(is_function,"s"), - BUILDIN_DEF(get_revision,""), - BUILDIN_DEF(freeloop,"i"), - BUILDIN_DEF(getrandgroupitem, "ii"), - BUILDIN_DEF(cleanmap, "s"), - BUILDIN_DEF2(cleanmap, "cleanarea", "siiii"), - /** - * @commands (script based) - **/ - BUILDIN_DEF(bindatcmd, "ss??"), - BUILDIN_DEF(unbindatcmd, "s"), - BUILDIN_DEF(useatcmd, "s"), - - //Quest Log System [Inkfish] - BUILDIN_DEF(setquest, "i"), - BUILDIN_DEF(erasequest, "i"), - BUILDIN_DEF(completequest, "i"), - BUILDIN_DEF(checkquest, "i?"), - BUILDIN_DEF(changequest, "ii"), - BUILDIN_DEF(showevent, "ii"), - {NULL,NULL,NULL}, + BUILDIN_DEF(dispbottom,"s"), //added from jA [Lupus] + BUILDIN_DEF(getusersname,""), + BUILDIN_DEF(recovery,""), + BUILDIN_DEF(getpetinfo,"i"), + BUILDIN_DEF(gethominfo,"i"), + BUILDIN_DEF(getmercinfo,"i?"), + BUILDIN_DEF(checkequipedcard,"i"), + BUILDIN_DEF(jump_zero,"il"), //for future jA script compatibility + BUILDIN_DEF(globalmes,"s?"), //end jA addition + BUILDIN_DEF(unequip,"i"), // unequip command [Spectre] + BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris] + BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris] + BUILDIN_DEF(charat,"si"), + BUILDIN_DEF(setchar,"ssi"), + BUILDIN_DEF(insertchar,"ssi"), + BUILDIN_DEF(delchar,"si"), + BUILDIN_DEF(strtoupper,"s"), + BUILDIN_DEF(strtolower,"s"), + BUILDIN_DEF(charisupper, "si"), + BUILDIN_DEF(charislower, "si"), + BUILDIN_DEF(substr,"sii"), + BUILDIN_DEF(explode, "rss"), + BUILDIN_DEF(implode, "r?"), + BUILDIN_DEF(sprintf,"s*"), // [Mirei] + BUILDIN_DEF(sscanf,"ss*"), // [Mirei] + BUILDIN_DEF(strpos,"ss?"), + BUILDIN_DEF(replacestr,"sss??"), + BUILDIN_DEF(countstr,"ss?"), + BUILDIN_DEF(setnpcdisplay,"sv??"), + BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine. + BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info + BUILDIN_DEF(setiteminfo,"iii"), //[Lupus] set Items Buy / sell Price, etc info + BUILDIN_DEF(getequipcardid,"ii"), //[Lupus] returns CARD ID or other info from CARD slot N of equipped item + // [zBuffer] List of mathematics commands ---> + BUILDIN_DEF(sqrt,"i"), + BUILDIN_DEF(pow,"ii"), + BUILDIN_DEF(distance,"iiii"), + // <--- [zBuffer] List of mathematics commands + BUILDIN_DEF(md5,"s"), + // [zBuffer] List of dynamic var commands ---> + BUILDIN_DEF(getd,"s"), + BUILDIN_DEF(setd,"sv"), + // <--- [zBuffer] List of dynamic var commands + BUILDIN_DEF(petstat,"i"), + BUILDIN_DEF(callshop,"s?"), // [Skotlex] + BUILDIN_DEF(npcshopitem,"sii*"), // [Lance] + BUILDIN_DEF(npcshopadditem,"sii*"), + BUILDIN_DEF(npcshopdelitem,"si*"), + BUILDIN_DEF(npcshopattach,"s?"), + BUILDIN_DEF(equip,"i"), + BUILDIN_DEF(autoequip,"ii"), + BUILDIN_DEF(setbattleflag,"si"), + BUILDIN_DEF(getbattleflag,"s"), + BUILDIN_DEF(setitemscript,"is?"), //Set NEW item bonus script. Lupus + BUILDIN_DEF(disguise,"i"), //disguise player. Lupus + BUILDIN_DEF(undisguise,""), //undisguise player. Lupus + BUILDIN_DEF(getmonsterinfo,"ii"), //Lupus + BUILDIN_DEF(axtoi,"s"), + BUILDIN_DEF(query_sql,"s*"), + BUILDIN_DEF(query_logsql,"s*"), + BUILDIN_DEF(escape_sql,"v"), + BUILDIN_DEF(atoi,"s"), + // [zBuffer] List of player cont commands ---> + BUILDIN_DEF(rid2name,"i"), + BUILDIN_DEF(pcfollow,"ii"), + BUILDIN_DEF(pcstopfollow,"i"), + BUILDIN_DEF(pcblockmove,"ii"), + // <--- [zBuffer] List of player cont commands + // [zBuffer] List of mob control commands ---> + BUILDIN_DEF(unitwalk,"ii?"), + BUILDIN_DEF(unitkill,"i"), + BUILDIN_DEF(unitwarp,"isii"), + BUILDIN_DEF(unitattack,"iv?"), + BUILDIN_DEF(unitstop,"i"), + BUILDIN_DEF(unittalk,"is"), + BUILDIN_DEF(unitemote,"ii"), + BUILDIN_DEF(unitskilluseid,"ivi?"), // originally by Qamera [Celest] + BUILDIN_DEF(unitskillusepos,"iviii"), // [Celest] +// <--- [zBuffer] List of mob control commands + BUILDIN_DEF(sleep,"i"), + BUILDIN_DEF(sleep2,"i"), + BUILDIN_DEF(awake,"s"), + BUILDIN_DEF(getvariableofnpc,"rs"), + BUILDIN_DEF(warpportal,"iisii"), + BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn] + BUILDIN_DEF2(homunculus_mutate,"hommutate","?"), + BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus] + BUILDIN_DEF(eaclass,"?"), //[Skotlex] + BUILDIN_DEF(roclass,"i?"), //[Skotlex] + BUILDIN_DEF(checkvending,"?"), + BUILDIN_DEF(checkchatting,"?"), + BUILDIN_DEF(openmail,""), + BUILDIN_DEF(openauction,""), + BUILDIN_DEF(checkcell,"siii"), + BUILDIN_DEF(setcell,"siiiiii"), + BUILDIN_DEF(setwall,"siiiiis"), + BUILDIN_DEF(delwall,"s"), + BUILDIN_DEF(searchitem,"rs"), + BUILDIN_DEF(mercenary_create,"ii"), + BUILDIN_DEF(mercenary_heal,"ii"), + BUILDIN_DEF(mercenary_sc_start,"iii"), + BUILDIN_DEF(mercenary_get_calls,"i"), + BUILDIN_DEF(mercenary_get_faith,"i"), + BUILDIN_DEF(mercenary_set_calls,"ii"), + BUILDIN_DEF(mercenary_set_faith,"ii"), + BUILDIN_DEF(readbook,"ii"), + BUILDIN_DEF(setfont,"i"), + BUILDIN_DEF(areamobuseskill,"siiiiviiiii"), + BUILDIN_DEF(progressbar,"si"), + BUILDIN_DEF(pushpc,"ii"), + BUILDIN_DEF(buyingstore,"i"), + BUILDIN_DEF(searchstores,"ii"), + BUILDIN_DEF(showdigit,"i?"), + // WoE SE + BUILDIN_DEF(agitstart2,""), + BUILDIN_DEF(agitend2,""), + BUILDIN_DEF(agitcheck2,""), + // BattleGround + BUILDIN_DEF(waitingroom2bg,"siiss?"), + BUILDIN_DEF(waitingroom2bg_single,"isiis"), + BUILDIN_DEF(bg_team_setxy,"iii"), + BUILDIN_DEF(bg_warp,"isii"), + BUILDIN_DEF(bg_monster,"isiisi?"), + BUILDIN_DEF(bg_monster_set_team,"ii"), + BUILDIN_DEF(bg_leave,""), + BUILDIN_DEF(bg_destroy,"i"), + BUILDIN_DEF(areapercentheal,"siiiiii"), + BUILDIN_DEF(bg_get_data,"ii"), + BUILDIN_DEF(bg_getareausers,"isiiii"), + BUILDIN_DEF(bg_updatescore,"sii"), + + // Instancing + BUILDIN_DEF(instance_create,"si"), + BUILDIN_DEF(instance_destroy,"?"), + BUILDIN_DEF(instance_attachmap,"si?"), + BUILDIN_DEF(instance_detachmap,"s?"), + BUILDIN_DEF(instance_attach,"i"), + BUILDIN_DEF(instance_id,"?"), + BUILDIN_DEF(instance_set_timeout,"ii?"), + BUILDIN_DEF(instance_init,"i"), + BUILDIN_DEF(instance_announce,"isi?????"), + BUILDIN_DEF(instance_npcname,"s?"), + BUILDIN_DEF(has_instance,"s?"), + BUILDIN_DEF(instance_warpall,"sii?"), + BUILDIN_DEF(instance_check_party,"i???"), + /** + * 3rd-related + **/ + BUILDIN_DEF(makerune,"i"), + BUILDIN_DEF(checkdragon,""),//[Ind] + BUILDIN_DEF(setdragon,"?"),//[Ind] + BUILDIN_DEF(ismounting,""),//[Ind] + BUILDIN_DEF(setmounting,""),//[Ind] + BUILDIN_DEF(checkre,"i"), + /** + * rAthena and beyond! + **/ + BUILDIN_DEF(getargcount,""), + BUILDIN_DEF(getcharip,"?"), + BUILDIN_DEF(is_function,"s"), + BUILDIN_DEF(get_revision,""), + BUILDIN_DEF(freeloop,"i"), + BUILDIN_DEF(getrandgroupitem, "ii"), + /** + * @commands (script based) + **/ + BUILDIN_DEF(bindatcmd, "ss??"), + BUILDIN_DEF(unbindatcmd, "s"), + BUILDIN_DEF(useatcmd, "s"), + + //Quest Log System [Inkfish] + BUILDIN_DEF(setquest, "i"), + BUILDIN_DEF(erasequest, "i"), + BUILDIN_DEF(completequest, "i"), + BUILDIN_DEF(checkquest, "i?"), + BUILDIN_DEF(changequest, "ii"), + BUILDIN_DEF(showevent, "ii"), + {NULL,NULL,NULL}, }; diff --git a/src/map/script.h b/src/map/script.h index e4c12de28..ed56b8ebe 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -13,101 +13,101 @@ extern int potion_hp, potion_per_hp, potion_sp, potion_per_sp; extern int potion_target; extern struct Script_Config { - unsigned warn_func_mismatch_argtypes : 1; - unsigned warn_func_mismatch_paramnum : 1; - int check_cmdcount; - int check_gotocount; - int input_min_value; - int input_max_value; - - const char *die_event_name; - const char *kill_pc_event_name; - const char *kill_mob_event_name; - const char *login_event_name; - const char *logout_event_name; - const char *loadmap_event_name; - const char *baselvup_event_name; - const char *joblvup_event_name; - - const char *ontouch_name; - const char *ontouch2_name; + unsigned warn_func_mismatch_argtypes : 1; + unsigned warn_func_mismatch_paramnum : 1; + int check_cmdcount; + int check_gotocount; + int input_min_value; + int input_max_value; + + const char *die_event_name; + const char *kill_pc_event_name; + const char *kill_mob_event_name; + const char *login_event_name; + const char *logout_event_name; + const char *loadmap_event_name; + const char *baselvup_event_name; + const char *joblvup_event_name; + + const char* ontouch_name; + const char* ontouch2_name; } script_config; typedef enum c_op { - C_NOP, // end of script/no value (nil) - C_POS, - C_INT, // number - C_PARAM, // parameter variable (see pc_readparam/pc_setparam) - C_FUNC, // buildin function call - C_STR, // string (free'd automatically) - C_CONSTSTR, // string (not free'd) - C_ARG, // start of argument list - C_NAME, - C_EOL, // end of line (extra stack values are cleared) - C_RETINFO, - C_USERFUNC, // internal script function - C_USERFUNC_POS, // internal script function label - C_REF, // the next call to c_op2 should push back a ref to the left operand - - // operators - C_OP3, // a ? b : c - C_LOR, // a || b - C_LAND, // a && b - C_LE, // a <= b - C_LT, // a < b - C_GE, // a >= b - C_GT, // a > b - C_EQ, // a == b - C_NE, // a != b - C_XOR, // a ^ b - C_OR, // a | b - C_AND, // a & b - C_ADD, // a + b - C_SUB, // a - b - C_MUL, // a * b - C_DIV, // a / b - C_MOD, // a % b - C_NEG, // - a - C_LNOT, // ! a - C_NOT, // ~ a - C_R_SHIFT, // a >> b - C_L_SHIFT, // a << b - C_ADD_PP, // ++a - C_SUB_PP, // --a + C_NOP, // end of script/no value (nil) + C_POS, + C_INT, // number + C_PARAM, // parameter variable (see pc_readparam/pc_setparam) + C_FUNC, // buildin function call + C_STR, // string (free'd automatically) + C_CONSTSTR, // string (not free'd) + C_ARG, // start of argument list + C_NAME, + C_EOL, // end of line (extra stack values are cleared) + C_RETINFO, + C_USERFUNC, // internal script function + C_USERFUNC_POS, // internal script function label + C_REF, // the next call to c_op2 should push back a ref to the left operand + + // operators + C_OP3, // a ? b : c + C_LOR, // a || b + C_LAND, // a && b + C_LE, // a <= b + C_LT, // a < b + C_GE, // a >= b + C_GT, // a > b + C_EQ, // a == b + C_NE, // a != b + C_XOR, // a ^ b + C_OR, // a | b + C_AND, // a & b + C_ADD, // a + b + C_SUB, // a - b + C_MUL, // a * b + C_DIV, // a / b + C_MOD, // a % b + C_NEG, // - a + C_LNOT, // ! a + C_NOT, // ~ a + C_R_SHIFT, // a >> b + C_L_SHIFT, // a << b + C_ADD_PP, // ++a + C_SUB_PP, // --a } c_op; struct script_retinfo { - struct DBMap *var_function;// scope variables - struct script_code *script;// script code - int pos;// script location - int nargs;// argument count - int defsp;// default stack pointer + struct DBMap* var_function;// scope variables + struct script_code* script;// script code + int pos;// script location + int nargs;// argument count + int defsp;// default stack pointer }; struct script_data { - enum c_op type; - union script_data_val { - int num; - char *str; - struct script_retinfo *ri; - } u; - struct DBMap **ref; + enum c_op type; + union script_data_val { + int num; + char *str; + struct script_retinfo* ri; + } u; + struct DBMap** ref; }; // Moved defsp from script_state to script_stack since // it must be saved when script state is RERUNLINE. [Eoe / jA 1094] struct script_code { - int script_size; - unsigned char *script_buf; - struct DBMap *script_vars; + int script_size; + unsigned char* script_buf; + struct DBMap* script_vars; }; struct script_stack { - int sp;// number of entries in the stack - int sp_max;// capacity of the stack - int defsp; - struct script_data *stack_data;// stack - struct DBMap *var_function;// scope variables + int sp;// number of entries in the stack + int sp_max;// capacity of the stack + int defsp; + struct script_data *stack_data;// stack + struct DBMap* var_function;// scope variables }; @@ -117,81 +117,81 @@ struct script_stack { enum e_script_state { RUN,STOP,END,RERUNLINE,GOTO,RETFUNC }; struct script_state { - struct script_stack *stack; - int start,end; - int pos; - enum e_script_state state; - int rid,oid; - struct script_code *script, *scriptroot; - struct sleep_data { - int tick,timer,charid; - } sleep; - int instance_id; - //For backing up purposes - struct script_state *bk_st; - int bk_npcid; - unsigned freeloop : 1;// used by buildin_freeloop - unsigned op2ref : 1;// used by op_2 + struct script_stack* stack; + int start,end; + int pos; + enum e_script_state state; + int rid,oid; + struct script_code *script, *scriptroot; + struct sleep_data { + int tick,timer,charid; + } sleep; + int instance_id; + //For backing up purposes + struct script_state *bk_st; + int bk_npcid; + unsigned freeloop : 1;// used by buildin_freeloop + unsigned op2ref : 1;// used by op_2 }; struct script_reg { - int index; - int data; + int index; + int data; }; struct script_regstr { - int index; - char *data; + int index; + char* data; }; enum script_parse_options { - SCRIPT_USE_LABEL_DB = 0x1,// records labels in scriptlabel_db - SCRIPT_IGNORE_EXTERNAL_BRACKETS = 0x2,// ignores the check for {} brackets around the script - SCRIPT_RETURN_EMPTY_SCRIPT = 0x4// returns the script object instead of NULL for empty scripts + SCRIPT_USE_LABEL_DB = 0x1,// records labels in scriptlabel_db + SCRIPT_IGNORE_EXTERNAL_BRACKETS = 0x2,// ignores the check for {} brackets around the script + SCRIPT_RETURN_EMPTY_SCRIPT = 0x4// returns the script object instead of NULL for empty scripts }; -const char *skip_space(const char *p); -void script_error(const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos); +const char* skip_space(const char* p); +void script_error(const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos); -struct script_code *parse_script(const char *src,const char *file,int line,int options); -void run_script_sub(struct script_code *rootscript,int pos,int rid,int oid, char *file, int lineno); -void run_script(struct script_code *,int,int,int); +struct script_code* parse_script(const char* src,const char* file,int line,int options); +void run_script_sub(struct script_code *rootscript,int pos,int rid,int oid, char* file, int lineno); +void run_script(struct script_code*,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); -const char *conv_str(struct script_state *st,struct script_data *data); +const char* conv_str(struct script_state *st,struct script_data *data); int run_script_timer(int tid, unsigned int tick, int id, intptr_t data); void run_script_main(struct script_state *st); void script_stop_sleeptimers(int id); -struct linkdb_node *script_erase_sleepdb(struct linkdb_node *n); -void script_free_code(struct script_code *code); +struct linkdb_node* script_erase_sleepdb(struct linkdb_node *n); +void script_free_code(struct script_code* code); void script_free_vars(struct DBMap *storage); -struct script_state *script_alloc_state(struct script_code *script, int pos, int rid, int oid); -void script_free_state(struct script_state *st); +struct script_state* script_alloc_state(struct script_code* script, int pos, int rid, int oid); +void script_free_state(struct script_state* st); -struct DBMap *script_get_label_db(void); -struct DBMap *script_get_userfunc_db(void); +struct DBMap* script_get_label_db(void); +struct DBMap* script_get_userfunc_db(void); void script_run_autobonus(const char *autobonus,int id, int pos); -bool script_get_constant(const char *name, int *value); -void script_set_constant(const char *name, int value, bool isparameter); +bool script_get_constant(const char* name, int* value); +void script_set_constant(const char* name, int value, bool isparameter); -void script_cleararray_pc(struct map_session_data *sd, const char *varname, void *value); -void script_setarray_pc(struct map_session_data *sd, const char *varname, uint8 idx, void *value, int *refcache); +void script_cleararray_pc(struct map_session_data* sd, const char* varname, void* value); +void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 idx, void* value, int* refcache); int script_config_read(char *cfgName); int do_init_script(void); int do_final_script(void); -int add_str(const char *p); -const char *get_str(int id); +int add_str(const char* p); +const char* get_str(int id); int script_reload(void); // @commands (script based) void setd_sub(struct script_state *st, TBL_PC *sd, const char *varname, int elem, void *value, struct DBMap **ref); #ifdef BETA_THREAD_TEST -void queryThread_log(char *entry, int length); +void queryThread_log(char * entry, int length); #endif #endif /* _SCRIPT_H_ */ diff --git a/src/map/searchstore.c b/src/map/searchstore.c index 041376260..c59c13bed 100644 --- a/src/map/searchstore.c +++ b/src/map/searchstore.c @@ -12,377 +12,394 @@ /// failure constants for clif functions -enum e_searchstore_failure { - SSI_FAILED_NOTHING_SEARCH_ITEM = 0, // "No matching stores were found." - SSI_FAILED_OVER_MAXCOUNT = 1, // "There are too many results. Please enter more detailed search term." - SSI_FAILED_SEARCH_CNT = 2, // "You cannot search anymore." - SSI_FAILED_LIMIT_SEARCH_TIME = 3, // "You cannot search yet." - SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE = 4, // "No sale (purchase) information available." +enum e_searchstore_failure +{ + SSI_FAILED_NOTHING_SEARCH_ITEM = 0, // "No matching stores were found." + SSI_FAILED_OVER_MAXCOUNT = 1, // "There are too many results. Please enter more detailed search term." + SSI_FAILED_SEARCH_CNT = 2, // "You cannot search anymore." + SSI_FAILED_LIMIT_SEARCH_TIME = 3, // "You cannot search yet." + SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE = 4, // "No sale (purchase) information available." }; -enum e_searchstore_searchtype { - SEARCHTYPE_VENDING = 0, - SEARCHTYPE_BUYING_STORE = 1, +enum e_searchstore_searchtype +{ + SEARCHTYPE_VENDING = 0, + SEARCHTYPE_BUYING_STORE = 1, }; -enum e_searchstore_effecttype { - EFFECTTYPE_NORMAL = 0, - EFFECTTYPE_CASH = 1, - EFFECTTYPE_MAX +enum e_searchstore_effecttype +{ + EFFECTTYPE_NORMAL = 0, + EFFECTTYPE_CASH = 1, + EFFECTTYPE_MAX }; /// type for shop search function -typedef bool (*searchstore_search_t)(struct map_session_data *sd, unsigned short nameid); -typedef bool (*searchstore_searchall_t)(struct map_session_data *sd, const struct s_search_store_search *s); +typedef bool (*searchstore_search_t)(struct map_session_data* sd, unsigned short nameid); +typedef bool (*searchstore_searchall_t)(struct map_session_data* sd, const struct s_search_store_search* s); /// retrieves search function by type static searchstore_search_t searchstore_getsearchfunc(unsigned char type) { - switch (type) { - case SEARCHTYPE_VENDING: - return &vending_search; - case SEARCHTYPE_BUYING_STORE: - return &buyingstore_search; - } - return NULL; + switch( type ) + { + case SEARCHTYPE_VENDING: return &vending_search; + case SEARCHTYPE_BUYING_STORE: return &buyingstore_search; + } + return NULL; } /// retrieves search-all function by type static searchstore_searchall_t searchstore_getsearchallfunc(unsigned char type) { - switch (type) { - case SEARCHTYPE_VENDING: - return &vending_searchall; - case SEARCHTYPE_BUYING_STORE: - return &buyingstore_searchall; - } - return NULL; + switch( type ) + { + case SEARCHTYPE_VENDING: return &vending_searchall; + case SEARCHTYPE_BUYING_STORE: return &buyingstore_searchall; + } + return NULL; } /// checks if the player has a store by type -static bool searchstore_hasstore(struct map_session_data *sd, unsigned char type) +static bool searchstore_hasstore(struct map_session_data* sd, unsigned char type) { - switch (type) { - case SEARCHTYPE_VENDING: - return sd->state.vending; - case SEARCHTYPE_BUYING_STORE: - return sd->state.buyingstore; - } - return false; + switch( type ) + { + case SEARCHTYPE_VENDING: return sd->state.vending; + case SEARCHTYPE_BUYING_STORE: return sd->state.buyingstore; + } + return false; } /// returns player's store id by type -static int searchstore_getstoreid(struct map_session_data *sd, unsigned char type) +static int searchstore_getstoreid(struct map_session_data* sd, unsigned char type) { - switch (type) { - case SEARCHTYPE_VENDING: - return sd->vender_id; - case SEARCHTYPE_BUYING_STORE: - return sd->buyer_id; - } - return 0; + switch( type ) + { + case SEARCHTYPE_VENDING: return sd->vender_id; + case SEARCHTYPE_BUYING_STORE: return sd->buyer_id; + } + return 0; } -bool searchstore_open(struct map_session_data *sd, unsigned int uses, unsigned short effect) +bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned short effect) { - if (!battle_config.feature_search_stores || sd->searchstore.open) { - return false; - } + if( !battle_config.feature_search_stores || sd->searchstore.open ) + { + return false; + } - if (!uses || effect >= EFFECTTYPE_MAX) { - // invalid input - return false; - } + if( !uses || effect >= EFFECTTYPE_MAX ) + {// invalid input + return false; + } - sd->searchstore.open = true; - sd->searchstore.uses = uses; - sd->searchstore.effect = effect; + sd->searchstore.open = true; + sd->searchstore.uses = uses; + sd->searchstore.effect = effect; - clif_open_search_store_info(sd); + clif_open_search_store_info(sd); - return true; + return true; } -void searchstore_query(struct map_session_data *sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short *itemlist, unsigned int item_count, const unsigned short *cardlist, unsigned int card_count) +void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count) { - unsigned int i; - struct map_session_data *pl_sd; - struct s_mapiterator *iter; - struct s_search_store_search s; - searchstore_searchall_t store_searchall; - time_t querytime; - - if (!battle_config.feature_search_stores) { - return; - } - - if (!sd->searchstore.open) { - return; - } - - if ((store_searchall = searchstore_getsearchallfunc(type)) == NULL) { - ShowError("searchstore_query: Unknown search type %u (account_id=%d).\n", (unsigned int)type, sd->bl.id); - return; - } - - time(&querytime); - - if (sd->searchstore.nextquerytime > querytime) { - clif_search_store_info_failed(sd, SSI_FAILED_LIMIT_SEARCH_TIME); - return; - } - - if (!sd->searchstore.uses) { - clif_search_store_info_failed(sd, SSI_FAILED_SEARCH_CNT); - return; - } - - // validate lists - for (i = 0; i < item_count; i++) { - if (!itemdb_exists(itemlist[i])) { - ShowWarning("searchstore_query: Client resolved item %hu is not known.\n", itemlist[i]); - clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); - return; - } - } - for (i = 0; i < card_count; i++) { - if (!itemdb_exists(cardlist[i])) { - ShowWarning("searchstore_query: Client resolved card %hu is not known.\n", cardlist[i]); - clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); - return; - } - } - - if (max_price < min_price) { - swap(min_price, max_price); - } - - sd->searchstore.uses--; - sd->searchstore.type = type; - sd->searchstore.nextquerytime = querytime+battle_config.searchstore_querydelay; - - // drop previous results - searchstore_clear(sd); - - // allocate max. amount of results - sd->searchstore.items = (struct s_search_store_info_item *)aMalloc(sizeof(struct s_search_store_info_item)*battle_config.searchstore_maxresults); - - // search - s.search_sd = sd; - s.itemlist = itemlist; - s.cardlist = cardlist; - s.item_count = item_count; - s.card_count = card_count; - s.min_price = min_price; - s.max_price = max_price; - iter = mapit_geteachpc(); - - for (pl_sd = (struct map_session_data *)mapit_first(iter); mapit_exists(iter); pl_sd = (struct map_session_data *)mapit_next(iter)) { - if (sd == pl_sd) { - // skip own shop, if any - continue; - } - - if (!store_searchall(pl_sd, &s)) { - // exceeded result size - clif_search_store_info_failed(sd, SSI_FAILED_OVER_MAXCOUNT); - break; - } - } - - mapit_free(iter); - - if (sd->searchstore.count) { - // reclaim unused memory - sd->searchstore.items = (struct s_search_store_info_item *)aRealloc(sd->searchstore.items, sizeof(struct s_search_store_info_item)*sd->searchstore.count); - - // present results - clif_search_store_info_ack(sd); - - // one page displayed - sd->searchstore.pages++; - } else { - // cleanup - searchstore_clear(sd); - - // update uses - clif_search_store_info_ack(sd); - - // notify of failure - clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); - } + unsigned int i; + struct map_session_data* pl_sd; + struct s_mapiterator* iter; + struct s_search_store_search s; + searchstore_searchall_t store_searchall; + time_t querytime; + + if( !battle_config.feature_search_stores ) + { + return; + } + + if( !sd->searchstore.open ) + { + return; + } + + if( ( store_searchall = searchstore_getsearchallfunc(type) ) == NULL ) + { + ShowError("searchstore_query: Unknown search type %u (account_id=%d).\n", (unsigned int)type, sd->bl.id); + return; + } + + time(&querytime); + + if( sd->searchstore.nextquerytime > querytime ) + { + clif_search_store_info_failed(sd, SSI_FAILED_LIMIT_SEARCH_TIME); + return; + } + + if( !sd->searchstore.uses ) + { + clif_search_store_info_failed(sd, SSI_FAILED_SEARCH_CNT); + return; + } + + // validate lists + for( i = 0; i < item_count; i++ ) + { + if( !itemdb_exists(itemlist[i]) ) + { + ShowWarning("searchstore_query: Client resolved item %hu is not known.\n", itemlist[i]); + clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); + return; + } + } + for( i = 0; i < card_count; i++ ) + { + if( !itemdb_exists(cardlist[i]) ) + { + ShowWarning("searchstore_query: Client resolved card %hu is not known.\n", cardlist[i]); + clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); + return; + } + } + + if( max_price < min_price ) + { + swap(min_price, max_price); + } + + sd->searchstore.uses--; + sd->searchstore.type = type; + sd->searchstore.nextquerytime = querytime+battle_config.searchstore_querydelay; + + // drop previous results + searchstore_clear(sd); + + // allocate max. amount of results + sd->searchstore.items = (struct s_search_store_info_item*)aMalloc(sizeof(struct s_search_store_info_item)*battle_config.searchstore_maxresults); + + // search + s.search_sd = sd; + s.itemlist = itemlist; + s.cardlist = cardlist; + s.item_count = item_count; + s.card_count = card_count; + s.min_price = min_price; + s.max_price = max_price; + iter = mapit_geteachpc(); + + for( pl_sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); pl_sd = (struct map_session_data*)mapit_next(iter) ) + { + if( sd == pl_sd ) + {// skip own shop, if any + continue; + } + + if( !store_searchall(pl_sd, &s) ) + {// exceeded result size + clif_search_store_info_failed(sd, SSI_FAILED_OVER_MAXCOUNT); + break; + } + } + + mapit_free(iter); + + if( sd->searchstore.count ) + { + // reclaim unused memory + sd->searchstore.items = (struct s_search_store_info_item*)aRealloc(sd->searchstore.items, sizeof(struct s_search_store_info_item)*sd->searchstore.count); + + // present results + clif_search_store_info_ack(sd); + + // one page displayed + sd->searchstore.pages++; + } + else + { + // cleanup + searchstore_clear(sd); + + // update uses + clif_search_store_info_ack(sd); + + // notify of failure + clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); + } } /// checks whether or not more results are available for the client -bool searchstore_querynext(struct map_session_data *sd) +bool searchstore_querynext(struct map_session_data* sd) { - if (sd->searchstore.count && (sd->searchstore.count-1)/SEARCHSTORE_RESULTS_PER_PAGE < sd->searchstore.pages) { - return true; - } + if( sd->searchstore.count && ( sd->searchstore.count-1 )/SEARCHSTORE_RESULTS_PER_PAGE < sd->searchstore.pages ) + { + return true; + } - return false; + return false; } -void searchstore_next(struct map_session_data *sd) +void searchstore_next(struct map_session_data* sd) { - if (!battle_config.feature_search_stores || !sd->searchstore.open || sd->searchstore.count <= sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE) { - // nothing (more) to display - return; - } + if( !battle_config.feature_search_stores || !sd->searchstore.open || sd->searchstore.count <= sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE ) + {// nothing (more) to display + return; + } - // present results - clif_search_store_info_ack(sd); + // present results + clif_search_store_info_ack(sd); - // one more page displayed - sd->searchstore.pages++; + // one more page displayed + sd->searchstore.pages++; } -void searchstore_clear(struct map_session_data *sd) +void searchstore_clear(struct map_session_data* sd) { - searchstore_clearremote(sd); + searchstore_clearremote(sd); - if (sd->searchstore.items) { - // release results - aFree(sd->searchstore.items); - sd->searchstore.items = NULL; - } + if( sd->searchstore.items ) + {// release results + aFree(sd->searchstore.items); + sd->searchstore.items = NULL; + } - sd->searchstore.count = 0; - sd->searchstore.pages = 0; + sd->searchstore.count = 0; + sd->searchstore.pages = 0; } -void searchstore_close(struct map_session_data *sd) +void searchstore_close(struct map_session_data* sd) { - if (sd->searchstore.open) { - searchstore_clear(sd); + if( sd->searchstore.open ) + { + searchstore_clear(sd); - sd->searchstore.uses = 0; - sd->searchstore.open = false; - } + sd->searchstore.uses = 0; + sd->searchstore.open = false; + } } -void searchstore_click(struct map_session_data *sd, int account_id, int store_id, unsigned short nameid) +void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid) { - unsigned int i; - struct map_session_data *pl_sd; - searchstore_search_t store_search; - - if (!battle_config.feature_search_stores || !sd->searchstore.open || !sd->searchstore.count) { - return; - } - - searchstore_clearremote(sd); - - ARR_FIND(0, sd->searchstore.count, i, sd->searchstore.items[i].store_id == store_id && sd->searchstore.items[i].account_id == account_id && sd->searchstore.items[i].nameid == nameid); - if (i == sd->searchstore.count) { - // no such result, crafted - ShowWarning("searchstore_click: Received request with item %hu of account %d, which is not part of current result set (account_id=%d, char_id=%d).\n", nameid, account_id, sd->bl.id, sd->status.char_id); - clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); - return; - } - - if ((pl_sd = map_id2sd(account_id)) == NULL) { - // no longer online - clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); - return; - } - - if (!searchstore_hasstore(pl_sd, sd->searchstore.type) || searchstore_getstoreid(pl_sd, sd->searchstore.type) != store_id) { - // no longer vending/buying or not same shop - clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); - return; - } - - store_search = searchstore_getsearchfunc(sd->searchstore.type); - - if (!store_search(pl_sd, nameid)) { - // item no longer being sold/bought - clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); - return; - } - - switch (sd->searchstore.effect) { - case EFFECTTYPE_NORMAL: - // display coords - - if (sd->bl.m != pl_sd->bl.m) { - // not on same map, wipe previous marker - clif_search_store_info_click_ack(sd, -1, -1); - } else { - clif_search_store_info_click_ack(sd, pl_sd->bl.x, pl_sd->bl.y); - } - - break; - case EFFECTTYPE_CASH: - // open remotely - - // to bypass range checks - sd->searchstore.remote_id = account_id; - - switch (sd->searchstore.type) { - case SEARCHTYPE_VENDING: - vending_vendinglistreq(sd, account_id); - break; - case SEARCHTYPE_BUYING_STORE: - buyingstore_open(sd, account_id); - break; - } - - break; - default: - // unknown - ShowError("searchstore_click: Unknown search store effect %u (account_id=%d).\n", (unsigned int)sd->searchstore.effect, sd->bl.id); - } + unsigned int i; + struct map_session_data* pl_sd; + searchstore_search_t store_search; + + if( !battle_config.feature_search_stores || !sd->searchstore.open || !sd->searchstore.count ) + { + return; + } + + searchstore_clearremote(sd); + + ARR_FIND( 0, sd->searchstore.count, i, sd->searchstore.items[i].store_id == store_id && sd->searchstore.items[i].account_id == account_id && sd->searchstore.items[i].nameid == nameid ); + if( i == sd->searchstore.count ) + {// no such result, crafted + ShowWarning("searchstore_click: Received request with item %hu of account %d, which is not part of current result set (account_id=%d, char_id=%d).\n", nameid, account_id, sd->bl.id, sd->status.char_id); + clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); + return; + } + + if( ( pl_sd = map_id2sd(account_id) ) == NULL ) + {// no longer online + clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); + return; + } + + if( !searchstore_hasstore(pl_sd, sd->searchstore.type) || searchstore_getstoreid(pl_sd, sd->searchstore.type) != store_id ) + {// no longer vending/buying or not same shop + clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); + return; + } + + store_search = searchstore_getsearchfunc(sd->searchstore.type); + + if( !store_search(pl_sd, nameid) ) + {// item no longer being sold/bought + clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); + return; + } + + switch( sd->searchstore.effect ) + { + case EFFECTTYPE_NORMAL: + // display coords + + if( sd->bl.m != pl_sd->bl.m ) + {// not on same map, wipe previous marker + clif_search_store_info_click_ack(sd, -1, -1); + } + else + { + clif_search_store_info_click_ack(sd, pl_sd->bl.x, pl_sd->bl.y); + } + + break; + case EFFECTTYPE_CASH: + // open remotely + + // to bypass range checks + sd->searchstore.remote_id = account_id; + + switch( sd->searchstore.type ) + { + case SEARCHTYPE_VENDING: vending_vendinglistreq(sd, account_id); break; + case SEARCHTYPE_BUYING_STORE: buyingstore_open(sd, account_id); break; + } + + break; + default: + // unknown + ShowError("searchstore_click: Unknown search store effect %u (account_id=%d).\n", (unsigned int)sd->searchstore.effect, sd->bl.id); + } } /// checks whether or not sd has opened account_id's shop remotely -bool searchstore_queryremote(struct map_session_data *sd, int account_id) +bool searchstore_queryremote(struct map_session_data* sd, int account_id) { - return (bool)(sd->searchstore.open && sd->searchstore.count && sd->searchstore.remote_id == account_id); + return (bool)( sd->searchstore.open && sd->searchstore.count && sd->searchstore.remote_id == account_id ); } /// removes range-check bypassing for remotely opened stores -void searchstore_clearremote(struct map_session_data *sd) +void searchstore_clearremote(struct map_session_data* sd) { - sd->searchstore.remote_id = 0; + sd->searchstore.remote_id = 0; } /// receives results from a store-specific callback -bool searchstore_result(struct map_session_data *sd, int store_id, int account_id, const char *store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short *card, unsigned char refine) +bool searchstore_result(struct map_session_data* sd, int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine) { - struct s_search_store_info_item *ssitem; - - if (sd->searchstore.count >= (unsigned int)battle_config.searchstore_maxresults) { - // no more - return false; - } - - ssitem = &sd->searchstore.items[sd->searchstore.count++]; - ssitem->store_id = store_id; - ssitem->account_id = account_id; - safestrncpy(ssitem->store_name, store_name, sizeof(ssitem->store_name)); - ssitem->nameid = nameid; - ssitem->amount = amount; - ssitem->price = price; - memcpy(ssitem->card, card, sizeof(ssitem->card)); - ssitem->refine = refine; - - return true; + struct s_search_store_info_item* ssitem; + + if( sd->searchstore.count >= (unsigned int)battle_config.searchstore_maxresults ) + {// no more + return false; + } + + ssitem = &sd->searchstore.items[sd->searchstore.count++]; + ssitem->store_id = store_id; + ssitem->account_id = account_id; + safestrncpy(ssitem->store_name, store_name, sizeof(ssitem->store_name)); + ssitem->nameid = nameid; + ssitem->amount = amount; + ssitem->price = price; + memcpy(ssitem->card, card, sizeof(ssitem->card)); + ssitem->refine = refine; + + return true; } diff --git a/src/map/searchstore.h b/src/map/searchstore.h index 0ac7c8d66..ffa8e9784 100644 --- a/src/map/searchstore.h +++ b/src/map/searchstore.h @@ -7,48 +7,51 @@ #define SEARCHSTORE_RESULTS_PER_PAGE 10 /// information about the search being performed -struct s_search_store_search { - struct map_session_data *search_sd; // sd of the searching player - const unsigned short *itemlist; - const unsigned short *cardlist; - unsigned int item_count; - unsigned int card_count; - unsigned int min_price; - unsigned int max_price; +struct s_search_store_search +{ + struct map_session_data* search_sd; // sd of the searching player + const unsigned short* itemlist; + const unsigned short* cardlist; + unsigned int item_count; + unsigned int card_count; + unsigned int min_price; + unsigned int max_price; }; -struct s_search_store_info_item { - int store_id; - int account_id; - char store_name[MESSAGE_SIZE]; - unsigned short nameid; - unsigned short amount; - unsigned int price; - short card[MAX_SLOTS]; - unsigned char refine; +struct s_search_store_info_item +{ + int store_id; + int account_id; + char store_name[MESSAGE_SIZE]; + unsigned short nameid; + unsigned short amount; + unsigned int price; + short card[MAX_SLOTS]; + unsigned char refine; }; -struct s_search_store_info { - unsigned int count; - struct s_search_store_info_item *items; - unsigned int pages; // amount of pages already sent to client - unsigned int uses; - int remote_id; - time_t nextquerytime; - unsigned short effect; // 0 = Normal (display coords), 1 = Cash (remote open store) - unsigned char type; // 0 = Vending, 1 = Buying Store - bool open; +struct s_search_store_info +{ + unsigned int count; + struct s_search_store_info_item* items; + unsigned int pages; // amount of pages already sent to client + unsigned int uses; + int remote_id; + time_t nextquerytime; + unsigned short effect; // 0 = Normal (display coords), 1 = Cash (remote open store) + unsigned char type; // 0 = Vending, 1 = Buying Store + bool open; }; -bool searchstore_open(struct map_session_data *sd, unsigned int uses, unsigned short effect); -void searchstore_query(struct map_session_data *sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short *itemlist, unsigned int item_count, const unsigned short *cardlist, unsigned int card_count); -bool searchstore_querynext(struct map_session_data *sd); -void searchstore_next(struct map_session_data *sd); -void searchstore_clear(struct map_session_data *sd); -void searchstore_close(struct map_session_data *sd); -void searchstore_click(struct map_session_data *sd, int account_id, int store_id, unsigned short nameid); -bool searchstore_queryremote(struct map_session_data *sd, int account_id); -void searchstore_clearremote(struct map_session_data *sd); -bool searchstore_result(struct map_session_data *sd, int store_id, int account_id, const char *store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short *card, unsigned char refine); +bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned short effect); +void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count); +bool searchstore_querynext(struct map_session_data* sd); +void searchstore_next(struct map_session_data* sd); +void searchstore_clear(struct map_session_data* sd); +void searchstore_close(struct map_session_data* sd); +void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid); +bool searchstore_queryremote(struct map_session_data* sd, int account_id); +void searchstore_clearremote(struct map_session_data* sd); +bool searchstore_result(struct map_session_data* sd, int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine); #endif // _SEARCHSTORE_H_ diff --git a/src/map/skill.c b/src/map/skill.c index f599ed63d..82b502420 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -42,7 +42,7 @@ #include <math.h> -#define SKILLUNITTIMER_INTERVAL 100 +#define SKILLUNITTIMER_INTERVAL 100 // ranges reserved for mapping skill ids to skilldb offsets #define HM_SKILLRANGEMIN 700 @@ -55,14 +55,14 @@ #define GD_SKILLRANGEMAX GD_SKILLRANGEMIN + MAX_GUILDSKILL #if GD_SKILLRANGEMAX > 999 -#error GD_SKILLRANGEMAX is greater than 999 + #error GD_SKILLRANGEMAX is greater than 999 #endif static struct eri *skill_unit_ers = NULL; //For handling skill_unit's [Skotlex] static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Skotlex] -DBMap *skillunit_db = NULL; // int id -> struct skill_unit* +DBMap* skillunit_db = NULL; // int id -> struct skill_unit* -DBMap *skilldb_name2id = NULL; +DBMap* skilldb_name2id = NULL; /** * Skill Cool Down Delay Saving @@ -70,20 +70,20 @@ DBMap *skilldb_name2id = NULL; * to keep cooldowns in memory between player log-ins. * All cooldowns are reset when server is restarted. **/ -DBMap *skillcd_db = NULL; // char_id -> struct skill_cd +DBMap* skillcd_db = NULL; // char_id -> struct skill_cd struct skill_cd { - int duration[MAX_SKILL_TREE];//milliseconds - short skidx[MAX_SKILL_TREE];//the skill index entries belong to - short nameid[MAX_SKILL_TREE];//skill id - unsigned char cursor; + int duration[MAX_SKILL_TREE];//milliseconds + short skidx[MAX_SKILL_TREE];//the skill index entries belong to + short nameid[MAX_SKILL_TREE];//skill id + unsigned char cursor; }; /** * Skill Unit Persistency during endack routes (mostly for songs see bugreport:4574) **/ -DBMap *skillusave_db = NULL; // char_id -> struct skill_usave +DBMap* skillusave_db = NULL; // char_id -> struct skill_usave struct skill_usave { - int skill_num, skill_lv; + int skill_num, skill_lv; }; struct s_skill_db skill_db[MAX_SKILL_DB]; @@ -91,24 +91,24 @@ struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB]; struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB]; struct s_skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB]; struct s_skill_improvise_db { - int skillid; - short per;//1-10000 + int skillid; + short per;//1-10000 }; struct s_skill_improvise_db skill_improvise_db[MAX_SKILL_IMPROVISE_DB]; bool skill_reproduce_db[MAX_SKILL_DB]; struct s_skill_changematerial_db { - int itemid; - short rate; - int qty[5]; - short qty_rate[5]; + int itemid; + short rate; + int qty[5]; + short qty_rate[5]; }; struct s_skill_changematerial_db skill_changematerial_db[MAX_SKILL_PRODUCE_DB]; //Warlock struct s_skill_spellbook_db { - int nameid; - int skillid; - int point; + int nameid; + int skillid; + int point; }; struct s_skill_spellbook_db skill_spellbook_db[MAX_SKILL_SPELLBOOK_DB]; @@ -121,265 +121,132 @@ int icewall_unit_pos; int earthstrain_unit_pos; //early declaration int skill_block_check(struct block_list *bl, enum sc_type type, int skillid); -static int skill_check_unit_range(struct block_list *bl, int x, int y, int skillid, int skilllv); -static int skill_check_unit_range2(struct block_list *bl, int x, int y, int skillid, int skilllv); -static int skill_destroy_trap(struct block_list *bl, va_list ap); +static int skill_check_unit_range (struct block_list *bl, int x, int y, int skillid, int skilllv); +static int skill_check_unit_range2 (struct block_list *bl, int x, int y, int skillid, int skilllv); +static int skill_destroy_trap( struct block_list *bl, va_list ap ); //Since only mob-casted splash skills can hit ice-walls -static inline int splash_target(struct block_list *bl) +static inline int splash_target(struct block_list* bl) { #ifndef RENEWAL - return (bl->type == BL_MOB) ? BL_SKILL|BL_CHAR : BL_CHAR; + return ( bl->type == BL_MOB ) ? BL_SKILL|BL_CHAR : BL_CHAR; #else // Some skills can now hit ground skills(traps, ice wall & etc.) - return BL_SKILL|BL_CHAR; + return BL_SKILL|BL_CHAR; #endif } /// Returns the id of the skill, or 0 if not found. -int skill_name2id(const char *name) +int skill_name2id(const char* name) { - if (name == NULL) - return 0; + if( name == NULL ) + return 0; - return strdb_iget(skilldb_name2id, name); + return strdb_iget(skilldb_name2id, name); } /// Maps skill ids to skill db offsets. /// Returns the skill's array index, or 0 (Unknown Skill). -int skill_get_index(int id) +int skill_get_index( int id ) { - // avoid ranges reserved for mapping guild/homun/mercenary skills - if ((id >= GD_SKILLRANGEMIN && id <= GD_SKILLRANGEMAX) - || (id >= HM_SKILLRANGEMIN && id <= HM_SKILLRANGEMAX) - || (id >= MC_SKILLRANGEMIN && id <= MC_SKILLRANGEMAX) - || (id >= EL_SKILLRANGEMIN && id <= EL_SKILLRANGEMAX)) - return 0; - - // map skill id to skill db index - if (id >= GD_SKILLBASE) - id = GD_SKILLRANGEMIN + id - GD_SKILLBASE; - else if (id >= EL_SKILLBASE) - id = EL_SKILLRANGEMIN + id - EL_SKILLBASE; - else if (id >= MC_SKILLBASE) - id = MC_SKILLRANGEMIN + id - MC_SKILLBASE; - else if (id >= HM_SKILLBASE) - id = HM_SKILLRANGEMIN + id - HM_SKILLBASE; - - // validate result - if (id <= 0 || id >= MAX_SKILL_DB) - return 0; - - return id; + // avoid ranges reserved for mapping guild/homun/mercenary skills + if( (id >= GD_SKILLRANGEMIN && id <= GD_SKILLRANGEMAX) + || (id >= HM_SKILLRANGEMIN && id <= HM_SKILLRANGEMAX) + || (id >= MC_SKILLRANGEMIN && id <= MC_SKILLRANGEMAX) + || (id >= EL_SKILLRANGEMIN && id <= EL_SKILLRANGEMAX) ) + return 0; + + // map skill id to skill db index + if( id >= GD_SKILLBASE ) + id = GD_SKILLRANGEMIN + id - GD_SKILLBASE; + else if( id >= EL_SKILLBASE ) + id = EL_SKILLRANGEMIN + id - EL_SKILLBASE; + else if( id >= MC_SKILLBASE ) + id = MC_SKILLRANGEMIN + id - MC_SKILLBASE; + else if( id >= HM_SKILLBASE ) + id = HM_SKILLRANGEMIN + id - HM_SKILLBASE; + + // validate result + if( id <= 0 || id >= MAX_SKILL_DB ) + return 0; + + return id; } -const char *skill_get_name(int id) +const char* skill_get_name( int id ) { - return skill_db[skill_get_index(id)].name; + return skill_db[skill_get_index(id)].name; } -const char *skill_get_desc(int id) +const char* skill_get_desc( int id ) { - return skill_db[skill_get_index(id)].desc; + return skill_db[skill_get_index(id)].desc; } // out of bounds error checking [celest] -static void skill_chk(int *id, int lv) +static void skill_chk(int* id, int lv) { - *id = skill_get_index(*id); // checks/adjusts id - if (lv <= 0 || lv > MAX_SKILL_LEVEL) *id = 0; + *id = skill_get_index(*id); // checks/adjusts id + if( lv <= 0 || lv > MAX_SKILL_LEVEL ) *id = 0; } #define skill_get(var,id,lv) { skill_chk(&id,lv); if(!id) return 0; 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_get(skill_db[id].inf, id, 1); -} -int skill_get_ele(int id , int lv) -{ - skill_get(skill_db[id].element[lv-1], id, lv); -} -int skill_get_nk(int id) -{ - skill_get(skill_db[id].nk, id, 1); -} -int skill_get_max(int id) -{ - skill_get(skill_db[id].max, id, 1); -} -int skill_get_range(int id , int lv) -{ - skill_get(skill_db[id].range[lv-1], id, lv); -} -int skill_get_splash(int id , int lv) -{ - skill_chk(&id, lv); - return (skill_db[id].splash[lv-1]>=0?skill_db[id].splash[lv-1]:AREA_SIZE); -} -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_hp_rate(int id, int lv) -{ - skill_get(skill_db[id].hp_rate[lv-1], id, lv); -} -int skill_get_sp_rate(int id, int lv) -{ - skill_get(skill_db[id].sp_rate[lv-1], id, lv); -} -int skill_get_state(int id) -{ - skill_get(skill_db[id].state, id, 1); -} -int skill_get_spiritball(int id, int lv) -{ - skill_get(skill_db[id].spiritball[lv-1], id, lv); -} -int skill_get_itemid(int id, int idx) -{ - skill_get(skill_db[id].itemid[idx], id, 1); -} -int skill_get_itemqty(int id, int idx) -{ - skill_get(skill_db[id].amount[idx], id, 1); -} -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_walkdelay(int id ,int lv) -{ - skill_get(skill_db[id].walkdelay[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_ammotype(int id) -{ - skill_get(skill_db[id].ammo, id, 1); -} -int skill_get_ammo_qty(int id, int lv) -{ - skill_get(skill_db[id].ammo_qty[lv-1], id, lv); -} -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 ,int lv) -{ - skill_get(skill_db[id].maxcount[lv-1], id, lv); -} -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_type(int id) -{ - skill_get(skill_db[id].skill_type, 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_interval(int id) -{ - skill_get(skill_db[id].unit_interval, id, 1); -} -int skill_get_unit_range(int id, int lv) -{ - skill_get(skill_db[id].unit_range[lv-1], id, lv); -} -int skill_get_unit_target(int id) -{ - skill_get(skill_db[id].unit_target&BCT_ALL, id, 1); -} -int skill_get_unit_bl_target(int id) -{ - skill_get(skill_db[id].unit_target&BL_ALL, id, 1); -} -int skill_get_unit_flag(int id) -{ - skill_get(skill_db[id].unit_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_cooldown(int id ,int lv) -{ - skill_get(skill_db[id].cooldown[lv-1], id, lv); -} +int skill_get_hit( int id ) { skill_get (skill_db[id].hit, id, 1); } +int skill_get_inf( int id ) { skill_get (skill_db[id].inf, id, 1); } +int skill_get_ele( int id , int lv ) { skill_get (skill_db[id].element[lv-1], id, lv); } +int skill_get_nk( int id ) { skill_get (skill_db[id].nk, id, 1); } +int skill_get_max( int id ) { skill_get (skill_db[id].max, id, 1); } +int skill_get_range( int id , int lv ) { skill_get (skill_db[id].range[lv-1], id, lv); } +int skill_get_splash( int id , int lv ) { skill_chk (&id, lv); return (skill_db[id].splash[lv-1]>=0?skill_db[id].splash[lv-1]:AREA_SIZE); } +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_hp_rate(int id, int lv ) { skill_get (skill_db[id].hp_rate[lv-1], id, lv); } +int skill_get_sp_rate(int id, int lv ) { skill_get (skill_db[id].sp_rate[lv-1], id, lv); } +int skill_get_state(int id) { skill_get (skill_db[id].state, id, 1); } +int skill_get_spiritball(int id, int lv) { skill_get (skill_db[id].spiritball[lv-1], id, lv); } +int skill_get_itemid(int id, int idx) { skill_get (skill_db[id].itemid[idx], id, 1); } +int skill_get_itemqty(int id, int idx) { skill_get (skill_db[id].amount[idx], id, 1); } +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_walkdelay( int id ,int lv ) { skill_get (skill_db[id].walkdelay[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_ammotype( int id ) { skill_get (skill_db[id].ammo, id, 1); } +int skill_get_ammo_qty( int id, int lv ) { skill_get (skill_db[id].ammo_qty[lv-1], id, lv); } +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 ,int lv ) { skill_get (skill_db[id].maxcount[lv-1], id, lv); } +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_type( int id ) { skill_get (skill_db[id].skill_type, 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_interval( int id ) { skill_get (skill_db[id].unit_interval, id, 1); } +int skill_get_unit_range( int id, int lv ){ skill_get (skill_db[id].unit_range[lv-1], id, lv); } +int skill_get_unit_target( int id ) { skill_get (skill_db[id].unit_target&BCT_ALL, id, 1); } +int skill_get_unit_bl_target( int id ) { skill_get (skill_db[id].unit_target&BL_ALL, id, 1); } +int skill_get_unit_flag( int id ) { skill_get (skill_db[id].unit_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_cooldown( int id ,int lv ) { skill_get (skill_db[id].cooldown[lv-1], id, lv); } #ifdef RENEWAL_CAST -int skill_get_fixed_cast(int id ,int lv) -{ - skill_get(skill_db[id].fixed_cast[lv-1], id, lv); -} +int skill_get_fixed_cast( int id ,int lv ){ skill_get (skill_db[id].fixed_cast[lv-1], id, lv); } #endif int skill_tree_get_max(int id, int b_class) { - int i; - b_class = pc_class2idx(b_class); - - ARR_FIND(0, MAX_SKILL_TREE, i, skill_tree[b_class][i].id == 0 || skill_tree[b_class][i].id == id); - if (i < MAX_SKILL_TREE && skill_tree[b_class][i].id == id) - return skill_tree[b_class][i].max; - else - return skill_get_max(id); + int i; + b_class = pc_class2idx(b_class); + + ARR_FIND( 0, MAX_SKILL_TREE, i, skill_tree[b_class][i].id == 0 || skill_tree[b_class][i].id == id ); + if( i < MAX_SKILL_TREE && skill_tree[b_class][i].id == id ) + return skill_tree[b_class][i].max; + else + return skill_get_max(id); } int skill_frostjoke_scream(struct block_list *bl,va_list ap); @@ -398,1654 +265,1634 @@ static 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 }; -int skill_get_casttype(int id) +int skill_get_casttype (int id) { - int inf = skill_get_inf(id); - if (inf&(INF_GROUND_SKILL)) - return CAST_GROUND; - if (inf&INF_SUPPORT_SKILL) - return CAST_NODAMAGE; - if (inf&INF_SELF_SKILL) { - if (skill_get_inf2(id)&INF2_NO_TARGET_SELF) - return CAST_DAMAGE; //Combo skill. - return CAST_NODAMAGE; - } - if (skill_get_nk(id)&NK_NO_DAMAGE) - return CAST_NODAMAGE; - return CAST_DAMAGE; + int inf = skill_get_inf(id); + if (inf&(INF_GROUND_SKILL)) + return CAST_GROUND; + if (inf&INF_SUPPORT_SKILL) + return CAST_NODAMAGE; + if (inf&INF_SELF_SKILL) { + if(skill_get_inf2(id)&INF2_NO_TARGET_SELF) + return CAST_DAMAGE; //Combo skill. + return CAST_NODAMAGE; + } + if (skill_get_nk(id)&NK_NO_DAMAGE) + return CAST_NODAMAGE; + return CAST_DAMAGE; } //Returns actual skill range taking into account attack range and AC_OWL [Skotlex] -int skill_get_range2(struct block_list *bl, int id, int lv) +int skill_get_range2 (struct block_list *bl, int id, int lv) { - int range; - if (bl->type == BL_MOB && battle_config.mob_ai&0x400) - return 9; //Mobs have a range of 9 regardless of skill used. - - range = skill_get_range(id, lv); - - if (range < 0) { - if (battle_config.use_weapon_skill_range&bl->type) - return status_get_range(bl); - range *=-1; - } - - //TODO: Find a way better than hardcoding the list of skills affected by AC_VULTURE - switch (id) { - case AC_SHOWER: - case MA_SHOWER: - case AC_DOUBLE: - case MA_DOUBLE: - case HT_BLITZBEAT: - case AC_CHARGEARROW: - case MA_CHARGEARROW: - case SN_FALCONASSAULT: - case HT_POWER: - /** - * Ranger - **/ - case RA_ARROWSTORM: - case RA_AIMEDBOLT: - case RA_WUGBITE: - if (bl->type == BL_PC) - range += pc_checkskill((TBL_PC *)bl, AC_VULTURE); - else - range += 10; //Assume level 10? - break; - // added to allow GS skills to be effected by the range of Snake Eyes [Reddozen] - case GS_RAPIDSHOWER: - case GS_PIERCINGSHOT: - case GS_FULLBUSTER: - case GS_SPREADATTACK: - case GS_GROUNDDRIFT: - if (bl->type == BL_PC) - range += pc_checkskill((TBL_PC *)bl, GS_SNAKEEYE); - else - range += 10; //Assume level 10? - break; - case NJ_KIRIKAGE: - if (bl->type == BL_PC) - range = skill_get_range(NJ_SHADOWJUMP,pc_checkskill((TBL_PC *)bl,NJ_SHADOWJUMP)); - break; - /** - * Warlock - **/ - case WL_WHITEIMPRISON: - case WL_SOULEXPANSION: - case WL_FROSTMISTY: - case WL_MARSHOFABYSS: - case WL_SIENNAEXECRATE: - case WL_DRAINLIFE: - case WL_CRIMSONROCK: - case WL_HELLINFERNO: - case WL_COMET: - case WL_CHAINLIGHTNING: - case WL_TETRAVORTEX: - case WL_RELEASE: - if (bl->type == BL_PC) - range += pc_checkskill((TBL_PC *)bl, WL_RADIUS); - break; - /** - * Ranger Bonus - **/ - case HT_LANDMINE: - case HT_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case RA_CLUSTERBOMB: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - if (bl->type == BL_PC) - range += (1 + pc_checkskill((TBL_PC *)bl, RA_RESEARCHTRAP))/2; - } - - if (!range && bl->type != BL_PC) - return 9; // Enable non players to use self skills on others. [Skotlex] - return range; + int range; + if( bl->type == BL_MOB && battle_config.mob_ai&0x400 ) + return 9; //Mobs have a range of 9 regardless of skill used. + + range = skill_get_range(id, lv); + + if( range < 0 ) + { + if( battle_config.use_weapon_skill_range&bl->type ) + return status_get_range(bl); + range *=-1; + } + + //TODO: Find a way better than hardcoding the list of skills affected by AC_VULTURE + switch( id ) + { + case AC_SHOWER: case MA_SHOWER: + case AC_DOUBLE: case MA_DOUBLE: + case HT_BLITZBEAT: + case AC_CHARGEARROW: + case MA_CHARGEARROW: + case SN_FALCONASSAULT: + case HT_POWER: + /** + * Ranger + **/ + case RA_ARROWSTORM: + case RA_AIMEDBOLT: + case RA_WUGBITE: + if( bl->type == BL_PC ) + range += pc_checkskill((TBL_PC*)bl, AC_VULTURE); + else + range += 10; //Assume level 10? + break; + // added to allow GS skills to be effected by the range of Snake Eyes [Reddozen] + case GS_RAPIDSHOWER: + case GS_PIERCINGSHOT: + case GS_FULLBUSTER: + case GS_SPREADATTACK: + case GS_GROUNDDRIFT: + if (bl->type == BL_PC) + range += pc_checkskill((TBL_PC*)bl, GS_SNAKEEYE); + else + range += 10; //Assume level 10? + break; + case NJ_KIRIKAGE: + if (bl->type == BL_PC) + range = skill_get_range(NJ_SHADOWJUMP,pc_checkskill((TBL_PC*)bl,NJ_SHADOWJUMP)); + break; + /** + * Warlock + **/ + case WL_WHITEIMPRISON: + case WL_SOULEXPANSION: + case WL_FROSTMISTY: + case WL_MARSHOFABYSS: + case WL_SIENNAEXECRATE: + case WL_DRAINLIFE: + case WL_CRIMSONROCK: + case WL_HELLINFERNO: + case WL_COMET: + case WL_CHAINLIGHTNING: + case WL_TETRAVORTEX: + case WL_RELEASE: + if( bl->type == BL_PC ) + range += pc_checkskill((TBL_PC*)bl, WL_RADIUS); + break; + /** + * Ranger Bonus + **/ + case HT_LANDMINE: + case HT_FREEZINGTRAP: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + case RA_CLUSTERBOMB: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + if( bl->type == BL_PC ) + range += (1 + pc_checkskill((TBL_PC*)bl, RA_RESEARCHTRAP))/2; + } + + if( !range && bl->type != BL_PC ) + return 9; // Enable non players to use self skills on others. [Skotlex] + return range; } -int skill_calc_heal(struct block_list *src, struct block_list *target, int skill_id, int skill_lv, bool heal) -{ - int skill, hp; - struct map_session_data *sd = BL_CAST(BL_PC, src); - struct map_session_data *tsd = BL_CAST(BL_PC, target); - struct status_change *sc; +int skill_calc_heal(struct block_list *src, struct block_list *target, int skill_id, int skill_lv, bool heal) { + int skill, hp; + struct map_session_data *sd = BL_CAST(BL_PC, src); + struct map_session_data *tsd = BL_CAST(BL_PC, target); + struct status_change* sc; - switch (skill_id) { - case BA_APPLEIDUN: -#ifdef RENEWAL - hp = 100+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery -#else - hp = 30+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery -#endif - if (sd) - hp += 5*pc_checkskill(sd,BA_MUSICALLESSON); - break; - case PR_SANCTUARY: - hp = (skill_lv>6)?777:skill_lv*100; - break; - case NPC_EVILLAND: - hp = (skill_lv>6)?666:skill_lv*100; - break; - default: - if (skill_lv >= battle_config.max_heal_lv) - return battle_config.max_heal; -#ifdef RENEWAL - /** - * Renewal Heal Formula - * Formula: ( [(Base Level + INT) / 5] ラ 30 ) ラ (Heal Level / 10) ラ (Modifiers) + MATK - **/ - hp = (status_get_lv(src) + status_get_int(src)) / 5 * 30 * skill_lv / 10; -#else - hp = (status_get_lv(src) + status_get_int(src)) / 8 * (4 + (skill_id == AB_HIGHNESSHEAL ? (sd ? pc_checkskill(sd,AL_HEAL) : 10) : skill_lv) * 8); -#endif - if (sd && ((skill = pc_checkskill(sd, HP_MEDITATIO)) > 0)) - hp += hp * skill * 2 / 100; - else if (src->type == BL_HOM && (skill = merc_hom_checkskill(((TBL_HOM *)src), HLIF_BRAIN)) > 0) - hp += hp * skill * 2 / 100; - break; - } - - if (((target && target->type == BL_MER) || !heal) && skill_id != NPC_EVILLAND) - hp >>= 1; - - if (sd && (skill = pc_skillheal_bonus(sd, skill_id))) - hp += hp*skill/100; - - if (tsd && (skill = pc_skillheal2_bonus(tsd, skill_id))) - hp += hp*skill/100; - - sc = status_get_sc(target); - if (sc && sc->count) { - if (sc->data[SC_CRITICALWOUND] && heal) // Critical Wound has no effect on offensive heal. [Inkfish] - hp -= hp * sc->data[SC_CRITICALWOUND]->val2/100; - if (sc->data[SC_DEATHHURT] && heal) - hp -= hp * 20/100; - if (sc->data[SC_INCHEALRATE] && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN) - hp += hp * sc->data[SC_INCHEALRATE]->val1/100; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish] - if (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) - hp += hp / 10; - } - -#ifdef RENEWAL - // MATK part of the RE heal formula [malufett] - // Note: in this part matk bonuses from items or skills are not applied switch( skill_id ) { - case BA_APPLEIDUN: case PR_SANCTUARY: - case NPC_EVILLAND: break; + case BA_APPLEIDUN: + #ifdef RENEWAL + hp = 100+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery + #else + hp = 30+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery + #endif + if( sd ) + hp += 5*pc_checkskill(sd,BA_MUSICALLESSON); + break; + case PR_SANCTUARY: + hp = (skill_lv>6)?777:skill_lv*100; + break; + case NPC_EVILLAND: + hp = (skill_lv>6)?666:skill_lv*100; + break; default: - { - struct status_data *status = status_get_status_data(src); - int min, max, wMatk, variance; - - min = max = status_base_matk(status, status_get_lv(src)); - if( status->rhw.matk > 0 ){ - wMatk = status->rhw.matk; - variance = wMatk * status->rhw.wlv / 10; - min += wMatk - variance; - max += wMatk + variance; - } - - if( sc && sc->data[SC_RECOGNIZEDSPELL] ) - min = max; - - if( sd && sd->right_weapon.overrefine > 0 ){ - min++; - max += sd->right_weapon.overrefine - 1; - } + if (skill_lv >= battle_config.max_heal_lv) + return battle_config.max_heal; + #ifdef RENEWAL + /** + * Renewal Heal Formula (from Doddler) + * TODO: whats that( 1+ %Modifier / 100 ) ? currently using 'x1' (100/100) until found out + * - Min = ( [ ( BaseLvl + INT ) / 5 ] * 30 ) * (1+( %Modifier / 100)) * (HealLvl * 0.1) + StatusMATK + EquipMATK - [(WeaponMATK * WeaponLvl) / 10] + * - Max = ( [ ( BaseLvl + INT ) / 5 ] * 30 ) * (1+( %Modifier / 100)) * (HealLvl * 0.1) + StatusMATK + EquipMATK + [(WeaponMATK * WeaponLvl) / 10] + **/ + hp = ( ( ( ( status_get_lv(src) + status_get_int(src) ) / 5 ) * 3 ) * skill_lv + status_get_matk_min(src) + status_get_matk_max(src) - ( ( status_get_matk_max(src) * status_get_wlv(src) ) / 10 ) ) + rnd()%( ( ( ( status_get_lv(src) + status_get_int(src) ) / 5 ) * 3 ) * skill_lv + status_get_matk_min(src) + status_get_matk_max(src) + ( ( status_get_matk_max(src) * status_get_wlv(src) ) / 10 ) ); + #else + hp = ( status_get_lv(src) + status_get_int(src) ) / 8 * (4 + ( skill_id == AB_HIGHNESSHEAL ? ( sd ? pc_checkskill(sd,AL_HEAL) : 10 ) : skill_lv ) * 8); + #endif + if( sd && ((skill = pc_checkskill(sd, HP_MEDITATIO)) > 0) ) + hp += hp * skill * 2 / 100; + else if( src->type == BL_HOM && (skill = merc_hom_checkskill(((TBL_HOM*)src), HLIF_BRAIN)) > 0 ) + hp += hp * skill * 2 / 100; + break; + } - if(max > min) - hp += min+rnd()%(max-min); - else - hp += min; - } + if( ( (target && target->type == BL_MER) || !heal ) && skill_id != NPC_EVILLAND ) + hp >>= 1; + + if( sd && (skill = pc_skillheal_bonus(sd, skill_id)) ) + hp += hp*skill/100; + + if( tsd && (skill = pc_skillheal2_bonus(tsd, skill_id)) ) + hp += hp*skill/100; + + sc = status_get_sc(target); + if( sc && sc->count ) { + if( sc->data[SC_CRITICALWOUND] && heal ) // Critical Wound has no effect on offensive heal. [Inkfish] + hp -= hp * sc->data[SC_CRITICALWOUND]->val2/100; + if( sc->data[SC_DEATHHURT] && heal ) + hp -= hp * 20/100; + if( sc->data[SC_INCHEALRATE] && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN ) + hp += hp * sc->data[SC_INCHEALRATE]->val1/100; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish] + if( sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) + hp += hp / 10; } -#endif - return hp; + + return hp; } // Making plagiarize check its own function [Aru] -int can_copy(struct map_session_data *sd, int skillid, struct block_list *bl) +int can_copy (struct map_session_data *sd, int skillid, struct block_list* bl) { - // Never copy NPC/Wedding Skills - if (skill_get_inf2(skillid)&(INF2_NPC_SKILL|INF2_WEDDING_SKILL)) - return 0; - - // High-class skills - if ((skillid >= LK_AURABLADE && skillid <= ASC_CDP) || (skillid >= ST_PRESERVE && skillid <= CR_CULTIVATION)) { - if (battle_config.copyskill_restrict == 2) - return 0; - else if (battle_config.copyskill_restrict) - return (sd->status.class_ == JOB_STALKER); - } - - //Added so plagarize can't copy agi/bless if you're undead since it damages you - if ((skillid == AL_INCAGI || skillid == AL_BLESSING || - skillid == CASH_BLESSING || skillid == CASH_INCAGI || - skillid == MER_INCAGI || skillid == MER_BLESSING)) - return 0; - - // Couldn't preserve 3rd Class skills except only when using Reproduce skill. [Jobbie] - if (!(sd->sc.data[SC__REPRODUCE]) && (skillid >= RK_ENCHANTBLADE && skillid <= SR_RIDEINLIGHTNING)) - return 0; - // Reproduce will only copy skills according on the list. [Jobbie] - else if (sd->sc.data[SC__REPRODUCE] && !skill_reproduce_db[skillid]) - return 0; - - return 1; + // Never copy NPC/Wedding Skills + if (skill_get_inf2(skillid)&(INF2_NPC_SKILL|INF2_WEDDING_SKILL)) + return 0; + + // High-class skills + if((skillid >= LK_AURABLADE && skillid <= ASC_CDP) || (skillid >= ST_PRESERVE && skillid <= CR_CULTIVATION)) + { + if(battle_config.copyskill_restrict == 2) + return 0; + else if(battle_config.copyskill_restrict) + return (sd->status.class_ == JOB_STALKER); + } + + //Added so plagarize can't copy agi/bless if you're undead since it damages you + if ((skillid == AL_INCAGI || skillid == AL_BLESSING || + skillid == CASH_BLESSING || skillid == CASH_INCAGI || + skillid == MER_INCAGI || skillid == MER_BLESSING)) + return 0; + + // Couldn't preserve 3rd Class skills except only when using Reproduce skill. [Jobbie] + if( !(sd->sc.data[SC__REPRODUCE]) && (skillid >= RK_ENCHANTBLADE && skillid <= SR_RIDEINLIGHTNING) ) + return 0; + // Reproduce will only copy skills according on the list. [Jobbie] + else if( sd->sc.data[SC__REPRODUCE] && !skill_reproduce_db[skillid] ) + return 0; + + return 1; } // [MouseJstr] - skill ok to cast? and when? -int skillnotok(int skillid, struct map_session_data *sd) +int skillnotok (int skillid, struct map_session_data *sd) { - int i,m; - nullpo_retr(1, sd); - m = sd->bl.m; - i = skill_get_index(skillid); - - if (i == 0) - return 1; // invalid skill id - - if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL)) - return 0; // can do any damn thing they want - - if (skillid == AL_TELEPORT && sd->skillitem == skillid && sd->skillitemlv > 2) - return 0; // Teleport lv 3 bypasses this check.[Inkfish] - - // Epoque: - // This code will compare the player's attack motion value which is influenced by ASPD before - // allowing a skill to be cast. This is to prevent no-delay ACT files from spamming skills such as - // AC_DOUBLE which do not have a skill delay and are not regarded in terms of attack motion. - if (!sd->state.autocast && sd->skillitem != skillid && sd->canskill_tick && - DIFF_TICK(gettick(), sd->canskill_tick) < (sd->battle_status.amotion * (100 + battle_config.skill_amotion_leniency) / 100)) { - // attempted to cast a skill before the attack motion has finished - return 1; - } - - if (sd->blockskill[i] > 0) { - clif_skill_fail(sd, skillid, USESKILL_FAIL_SKILLINTERVAL, 0); - return 1; - } - /** - * It has been confirmed on a official server (thanks to Yommy) that item-cast skills bypass all the restrictions above - * Also, without this check, an exploit where an item casting + healing (or any other kind buff) isn't deleted after used on a restricted map - **/ - if (sd->skillitem == skillid) - return 0; - // Check skill restrictions [Celest] - if ((!map_flag_vs(m) && skill_get_nocast(skillid) & 1) || - (map[m].flag.pvp && skill_get_nocast(skillid) & 2) || - (map_flag_gvg(m) && skill_get_nocast(skillid) & 4) || - (map[m].flag.battleground && skill_get_nocast(skillid) & 8) || - (map[m].flag.restricted && map[m].zone && skill_get_nocast(skillid) & (8*map[m].zone))) { - clif_msg(sd, 0x536); // This skill cannot be used within this area - return 1; - } - - if (sd->sc.option&OPTION_MOUNTING) - return 1;//You can't use skills while in the new mounts (The client doesn't let you, this is to make cheat-safe) - - switch (skillid) { - case AL_WARP: - case RETURN_TO_ELDICASTES: - case ALL_GUARDIAN_RECALL: - if (map[m].flag.nowarp) { - clif_skill_teleportmessage(sd,0); - return 1; - } - return 0; - case AL_TELEPORT: - case SC_FATALMENACE: - case SC_DIMENSIONDOOR: - if (map[m].flag.noteleport) { - clif_skill_teleportmessage(sd,0); - return 1; - } - return 0; // gonna be checked in 'skill_castend_nodamage_id' - case WE_CALLPARTNER: - case WE_CALLPARENT: - case WE_CALLBABY: - if (map[m].flag.nomemo) { - clif_skill_teleportmessage(sd,1); - return 1; - } - break; - case MC_VENDING: - case MC_IDENTIFY: - case ALL_BUYING_STORE: - return 0; // always allowed - case WZ_ICEWALL: - // noicewall flag [Valaris] - if (map[m].flag.noicewall) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - return 1; - } - break; - case GC_DARKILLUSION: - if (map_flag_gvg(m)) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - return 1; - } - break; - case GD_EMERGENCYCALL: - if ( - !(battle_config.emergency_call&((agit_flag || agit2_flag)?2:1)) || - !(battle_config.emergency_call&(map[m].flag.gvg || map[m].flag.gvg_castle?8:4)) || - (battle_config.emergency_call&16 && map[m].flag.nowarpto && !map[m].flag.gvg_castle) - ) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - return 1; - } - break; - case BS_GREED: - case WS_CARTBOOST: - case BS_HAMMERFALL: - case BS_ADRENALINE: - case MC_CARTREVOLUTION: - case MC_MAMMONITE: - case WS_MELTDOWN: - case MG_SIGHT: - case TF_HIDING: - /** - * These skills cannot be used while in mado gear (credits to Xantara) - **/ - if (pc_ismadogear(sd)) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - return 1; - } - break; + int i,m; + nullpo_retr (1, sd); + m = sd->bl.m; + i = skill_get_index(skillid); + + if (i == 0) + return 1; // invalid skill id + + if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL)) + return 0; // can do any damn thing they want + + if( skillid == AL_TELEPORT && sd->skillitem == skillid && sd->skillitemlv > 2 ) + return 0; // Teleport lv 3 bypasses this check.[Inkfish] + + // Epoque: + // This code will compare the player's attack motion value which is influenced by ASPD before + // allowing a skill to be cast. This is to prevent no-delay ACT files from spamming skills such as + // AC_DOUBLE which do not have a skill delay and are not regarded in terms of attack motion. + if( !sd->state.autocast && sd->skillitem != skillid && sd->canskill_tick && + DIFF_TICK(gettick(), sd->canskill_tick) < (sd->battle_status.amotion * (100 + battle_config.skill_amotion_leniency) / 100) ) + {// attempted to cast a skill before the attack motion has finished + return 1; + } - case WM_SIRCLEOFNATURE: - case WM_SOUND_OF_DESTRUCTION: - case SC_MANHOLE: - case WM_LULLABY_DEEPSLEEP: - case WM_SATURDAY_NIGHT_FEVER: - if (!map_flag_vs(m)) { - clif_skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails. - return 1; - } - break; + if (sd->blockskill[i] > 0){ + clif_skill_fail(sd, skillid, USESKILL_FAIL_SKILLINTERVAL, 0); + return 1; + } + /** + * It has been confirmed on a official server (thanks to Yommy) that item-cast skills bypass all the restrictions above + * Also, without this check, an exploit where an item casting + healing (or any other kind buff) isn't deleted after used on a restricted map + **/ + if( sd->skillitem == skillid ) + return 0; + // Check skill restrictions [Celest] + if( (!map_flag_vs(m) && skill_get_nocast (skillid) & 1) || + (map[m].flag.pvp && skill_get_nocast (skillid) & 2) || + (map_flag_gvg(m) && skill_get_nocast (skillid) & 4) || + (map[m].flag.battleground && skill_get_nocast (skillid) & 8) || + (map[m].flag.restricted && map[m].zone && skill_get_nocast (skillid) & (8*map[m].zone)) ){ + clif_msg(sd, 0x536); // This skill cannot be used within this area + return 1; + } + + if( sd->sc.option&OPTION_MOUNTING ) + return 1;//You can't use skills while in the new mounts (The client doesn't let you, this is to make cheat-safe) - } - return (map[m].flag.noskill); + switch (skillid) { + case AL_WARP: + case RETURN_TO_ELDICASTES: + case ALL_GUARDIAN_RECALL: + if(map[m].flag.nowarp) { + clif_skill_teleportmessage(sd,0); + return 1; + } + return 0; + case AL_TELEPORT: + case SC_FATALMENACE: + case SC_DIMENSIONDOOR: + if(map[m].flag.noteleport) { + clif_skill_teleportmessage(sd,0); + return 1; + } + return 0; // gonna be checked in 'skill_castend_nodamage_id' + case WE_CALLPARTNER: + case WE_CALLPARENT: + case WE_CALLBABY: + if (map[m].flag.nomemo) { + clif_skill_teleportmessage(sd,1); + return 1; + } + break; + case MC_VENDING: + case MC_IDENTIFY: + case ALL_BUYING_STORE: + return 0; // always allowed + case WZ_ICEWALL: + // noicewall flag [Valaris] + if (map[m].flag.noicewall) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + return 1; + } + break; + case GC_DARKILLUSION: + if( map_flag_gvg(m) ) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + return 1; + } + break; + case GD_EMERGENCYCALL: + if ( + !(battle_config.emergency_call&((agit_flag || agit2_flag)?2:1)) || + !(battle_config.emergency_call&(map[m].flag.gvg || map[m].flag.gvg_castle?8:4)) || + (battle_config.emergency_call&16 && map[m].flag.nowarpto && !map[m].flag.gvg_castle) + ) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + return 1; + } + break; + case BS_GREED: + case WS_CARTBOOST: + case BS_HAMMERFALL: + case BS_ADRENALINE: + case MC_CARTREVOLUTION: + case MC_MAMMONITE: + case WS_MELTDOWN: + case MG_SIGHT: + case TF_HIDING: + /** + * These skills cannot be used while in mado gear (credits to Xantara) + **/ + if( pc_ismadogear(sd) ) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + return 1; + } + break; + + case WM_SIRCLEOFNATURE: + case WM_SOUND_OF_DESTRUCTION: + case SC_MANHOLE: + case WM_LULLABY_DEEPSLEEP: + case WM_SATURDAY_NIGHT_FEVER: + if( !map_flag_vs(m) ) { + clif_skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails. + return 1; + } + break; + + } + return (map[m].flag.noskill); } int skillnotok_hom(int skillid, struct homun_data *hd) { - int i = skill_get_index(skillid); - nullpo_retr(1,hd); - - if (i == 0) - return 1; // invalid skill id - - if (hd->blockskill[i] > 0) - return 1; - switch (skillid) { - case MH_LIGHT_OF_REGENE: - if (hd->homunculus.intimacy <= 750) //if not cordial - return 1; - break; - case MH_OVERED_BOOST: - if (hd->homunculus.hunger <= 1) //if we starving - return 1; - case MH_GOLDENE_FERSE: //can be used with angriff - if (hd->sc.data[SC_ANGRIFFS_MODUS]) - return 1; - case MH_ANGRIFFS_MODUS: - if (hd->sc.data[SC_GOLDENE_FERSE]) - return 1; - break; - } + int i = skill_get_index(skillid); + nullpo_retr(1,hd); + + if (i == 0) + return 1; // invalid skill id + + if (hd->blockskill[i] > 0) + return 1; + switch(skillid){ + case MH_LIGHT_OF_REGENE: + if(hd->homunculus.intimacy <= 750) //if not cordial + return 1; + break; + case MH_OVERED_BOOST: + if(hd->homunculus.hunger <= 1) //if we starving + return 1; + case MH_GOLDENE_FERSE: //can be used with angriff + if(hd->sc.data[SC_ANGRIFFS_MODUS]) + return 1; + case MH_ANGRIFFS_MODUS: + if(hd->sc.data[SC_GOLDENE_FERSE]) + return 1; + break; + } - //Use master's criteria. - return skillnotok(skillid, hd->master); + //Use master's criteria. + return skillnotok(skillid, hd->master); } int skillnotok_mercenary(int skillid, struct mercenary_data *md) { - int i = skill_get_index(skillid); - nullpo_retr(1,md); + int i = skill_get_index(skillid); + nullpo_retr(1,md); - if (i == 0) - return 1; // Invalid Skill ID - if (md->blockskill[i] > 0) - return 1; + if( i == 0 ) + return 1; // Invalid Skill ID + if( md->blockskill[i] > 0 ) + return 1; - return skillnotok(skillid, md->master); + return skillnotok(skillid, md->master); } -struct s_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; +struct s_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 || pos >= MAX_SKILL_UNIT_LAYOUT) { - ShowError("skill_get_unit_layout: unsupported layout type %d for skill %d (level %d)\n", pos, skillid, skilllv); - pos = cap_value(pos, 0, MAX_SQUARE_LAYOUT); // cap to nearest square layout - } + if (pos < -1 || pos >= MAX_SKILL_UNIT_LAYOUT) { + ShowError("skill_get_unit_layout: unsupported layout type %d for skill %d (level %d)\n", pos, skillid, skilllv); + pos = cap_value(pos, 0, MAX_SQUARE_LAYOUT); // cap to nearest square layout + } - if (pos != -1) // simple single-definition layout - return &skill_unit_layout[pos]; + if (pos != -1) // simple single-definition layout + return &skill_unit_layout[pos]; - dir = (src->x == x && src->y == y) ? 6 : map_calc_dir(src,x,y); // 6 - default aegis direction + dir = (src->x == x && src->y == y) ? 6 : map_calc_dir(src,x,y); // 6 - default aegis direction - 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]; - else if (skillid == WL_EARTHSTRAIN) //Warlock - return &skill_unit_layout [earthstrain_unit_pos + dir]; + 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]; + else if( skillid == WL_EARTHSTRAIN ) //Warlock + return &skill_unit_layout [earthstrain_unit_pos + dir]; - ShowError("skill_get_unit_layout: unknown unit layout for skill %d (level %d)\n", skillid, skilllv); - return &skill_unit_layout[0]; // default 1x1 layout + ShowError("skill_get_unit_layout: unknown unit layout for skill %d (level %d)\n", skillid, skilllv); + return &skill_unit_layout[0]; // default 1x1 layout } /*========================================== * *------------------------------------------*/ -int skill_additional_effect(struct block_list *src, struct block_list *bl, int skillid, int skilllv, int attack_type, int dmg_lv, unsigned int tick) +int skill_additional_effect (struct block_list* src, struct block_list *bl, int skillid, int skilllv, int attack_type, int dmg_lv, unsigned int tick) { - struct map_session_data *sd, *dstsd; - struct mob_data *md, *dstmd; - struct status_data *sstatus, *tstatus; - struct status_change *sc, *tsc; - - enum sc_type status; - int skill; - int rate; - - nullpo_ret(src); - nullpo_ret(bl); - - if (skillid < 0) return 0; - if (skillid > 0 && skilllv <= 0) return 0; // don't forget auto attacks! - celest - - if (dmg_lv < ATK_BLOCK) // Don't apply effect if miss. - return 0; - - sd = BL_CAST(BL_PC, src); - md = BL_CAST(BL_MOB, src); - dstsd = BL_CAST(BL_PC, bl); - dstmd = BL_CAST(BL_MOB, bl); - - sc = status_get_sc(src); - tsc = status_get_sc(bl); - sstatus = status_get_status_data(src); - tstatus = status_get_status_data(bl); - if (!tsc) //skill additional effect is about adding effects to the target... - //So if the target can't be inflicted with statuses, this is pointless. - return 0; - - if (sd) { - // These statuses would be applied anyway even if the damage was blocked by some skills. [Inkfish] - if (skillid != WS_CARTTERMINATION && skillid != AM_DEMONSTRATION && skillid != CR_REFLECTSHIELD && skillid != MS_REFLECTSHIELD && skillid != ASC_BREAKER) { - // Trigger status effects - enum sc_type type; - int i; - for (i = 0; i < ARRAYLENGTH(sd->addeff) && sd->addeff[i].flag; i++) { - rate = sd->addeff[i].rate; - if (attack_type&BF_LONG) // Any ranged physical attack takes status arrows into account (Grimtooth...) [DracoRPG] - rate += sd->addeff[i].arrow_rate; - if (!rate) continue; - - if ((sd->addeff[i].flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC)) != (ATF_WEAPON|ATF_MAGIC|ATF_MISC)) { - // Trigger has attack type consideration. - if ((sd->addeff[i].flag&ATF_WEAPON && attack_type&BF_WEAPON) || - (sd->addeff[i].flag&ATF_MAGIC && attack_type&BF_MAGIC) || - (sd->addeff[i].flag&ATF_MISC && attack_type&BF_MISC)) ; - else - continue; - } - - if ((sd->addeff[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT)) { - // Trigger has range consideration. - if ((sd->addeff[i].flag&ATF_LONG && !(attack_type&BF_LONG)) || - (sd->addeff[i].flag&ATF_SHORT && !(attack_type&BF_SHORT))) - continue; //Range Failed. - } - - type = sd->addeff[i].id; - skill = skill_get_time2(status_sc2skill(type),7); - - if (sd->addeff[i].flag&ATF_TARGET) - status_change_start(bl,type,rate,7,0,0,0,skill,0); - - if (sd->addeff[i].flag&ATF_SELF) - status_change_start(src,type,rate,7,0,0,0,skill,0); - } - } - - if (skillid) { - // Trigger status effects on skills - enum sc_type type; - int i; - for (i = 0; i < ARRAYLENGTH(sd->addeff3) && sd->addeff3[i].skill; i++) { - if (skillid != sd->addeff3[i].skill || !sd->addeff3[i].rate) - continue; - type = sd->addeff3[i].id; - skill = skill_get_time2(status_sc2skill(type),7); - - if (sd->addeff3[i].target&ATF_TARGET) - status_change_start(bl,type,sd->addeff3[i].rate,7,0,0,0,skill,0); - if (sd->addeff3[i].target&ATF_SELF) - status_change_start(src,type,sd->addeff3[i].rate,7,0,0,0,skill,0); - } - } - } - - if (dmg_lv < ATK_DEF) // no damage, return; - return 0; - - switch (skillid) { - case 0: { // Normal attacks (no skill used) - if (attack_type&BF_SKILL) - break; // If a normal attack is a skill, it's splash damage. [Inkfish] - if (sd) { - // Automatic trigger of Blitz Beat - if (pc_isfalcon(sd) && sd->status.weapon == W_BOW && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 && - rnd()%1000 <= sstatus->luk*10/3+1) { - rate=(sd->status.job_level+9)/10; - skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<rate)?skill:rate,tick,SD_LEVEL); - } - // Automatic trigger of Warg Strike [Jobbie] - if (pc_iswug(sd) && (sd->status.weapon == W_BOW || sd->status.weapon == W_FIST) && (skill=pc_checkskill(sd,RA_WUGSTRIKE)) > 0 && rnd()%1000 <= sstatus->luk*10/3+1) - skill_castend_damage_id(src,bl,RA_WUGSTRIKE,skill,tick,0); - // Gank - if (dstmd && sd->status.weapon != W_BOW && - (skill=pc_checkskill(sd,RG_SNATCHER)) > 0 && - (skill*15 + 55) + pc_checkskill(sd,TF_STEAL)*10 > rnd()%1000) { - if (pc_steal_item(sd,bl,pc_checkskill(sd,TF_STEAL))) - clif_skill_nodamage(src,bl,TF_STEAL,skill,1); - else - clif_skill_fail(sd,RG_SNATCHER,USESKILL_FAIL_LEVEL,0); - } - // Chance to trigger Taekwon kicks [Dralnu] - if (sc && !sc->data[SC_COMBO]) { - if (sc->data[SC_READYSTORM] && - sc_start(src,SC_COMBO, 15, TK_STORMKICK, - (2000 - 4*sstatus->agi - 2*sstatus->dex))) - ; //Stance triggered - else if (sc->data[SC_READYDOWN] && - sc_start(src,SC_COMBO, 15, TK_DOWNKICK, - (2000 - 4*sstatus->agi - 2*sstatus->dex))) - ; //Stance triggered - else if (sc->data[SC_READYTURN] && - sc_start(src,SC_COMBO, 15, TK_TURNKICK, - (2000 - 4*sstatus->agi - 2*sstatus->dex))) - ; //Stance triggered - else if (sc->data[SC_READYCOUNTER]) { //additional chance from SG_FRIEND [Komurka] - rate = 20; - if (sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == TK_COUNTER) { - rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100; - status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); - } - sc_start2(src, SC_COMBO, rate, TK_COUNTER, bl->id, - (2000 - 4*sstatus->agi - 2*sstatus->dex)); - } - } - if (sc && sc->data[SC_PYROCLASTIC] && (rnd() % 1000 <= sstatus->luk * 10 / 3 + 1)) - skill_castend_pos2(src, bl->x, bl->y, BS_HAMMERFALL,sc->data[SC_PYROCLASTIC]->val1, tick, 0); - } - - if (sc) { - struct status_change_entry *sce; - // Enchant Poison gives a chance to poison attacked enemies - if ((sce=sc->data[SC_ENCPOISON])) //Don't use sc_start since chance comes in 1/10000 rate. - status_change_start(bl,SC_POISON,sce->val2, sce->val1,src->id,0,0, - skill_get_time2(AS_ENCHANTPOISON,sce->val1),0); - // Enchant Deadly Poison gives a chance to deadly poison attacked enemies - if ((sce=sc->data[SC_EDP])) - sc_start4(bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0, - skill_get_time2(ASC_EDP,sce->val1)); - } - } - break; + struct map_session_data *sd, *dstsd; + struct mob_data *md, *dstmd; + struct status_data *sstatus, *tstatus; + struct status_change *sc, *tsc; + + enum sc_type status; + int skill; + int rate; + + nullpo_ret(src); + nullpo_ret(bl); + + if(skillid < 0) return 0; + if(skillid > 0 && skilllv <= 0) return 0; // don't forget auto attacks! - celest + + if( dmg_lv < ATK_BLOCK ) // Don't apply effect if miss. + return 0; + + sd = BL_CAST(BL_PC, src); + md = BL_CAST(BL_MOB, src); + dstsd = BL_CAST(BL_PC, bl); + dstmd = BL_CAST(BL_MOB, bl); + + sc = status_get_sc(src); + tsc = status_get_sc(bl); + sstatus = status_get_status_data(src); + tstatus = status_get_status_data(bl); + if (!tsc) //skill additional effect is about adding effects to the target... + //So if the target can't be inflicted with statuses, this is pointless. + return 0; + + if( sd ) + { // These statuses would be applied anyway even if the damage was blocked by some skills. [Inkfish] + if( skillid != WS_CARTTERMINATION && skillid != AM_DEMONSTRATION && skillid != CR_REFLECTSHIELD && skillid != MS_REFLECTSHIELD && skillid != ASC_BREAKER ) + { // Trigger status effects + enum sc_type type; + int i; + for( i = 0; i < ARRAYLENGTH(sd->addeff) && sd->addeff[i].flag; i++ ) + { + rate = sd->addeff[i].rate; + if( attack_type&BF_LONG ) // Any ranged physical attack takes status arrows into account (Grimtooth...) [DracoRPG] + rate += sd->addeff[i].arrow_rate; + if( !rate ) continue; + + if( (sd->addeff[i].flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC)) != (ATF_WEAPON|ATF_MAGIC|ATF_MISC) ) + { // Trigger has attack type consideration. + if( (sd->addeff[i].flag&ATF_WEAPON && attack_type&BF_WEAPON) || + (sd->addeff[i].flag&ATF_MAGIC && attack_type&BF_MAGIC) || + (sd->addeff[i].flag&ATF_MISC && attack_type&BF_MISC) ) ; + else + continue; + } - case SM_BASH: - if (sd && skilllv > 5 && pc_checkskill(sd,SM_FATALBLOW)>0) { - //TODO: How much % per base level it actually is? - sc_start(bl,SC_STUN,(5*(skilllv-5)+(int)sd->status.base_level/10), - skilllv,skill_get_time2(SM_FATALBLOW,skilllv)); - } - break; + if( (sd->addeff[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT) ) + { // Trigger has range consideration. + if((sd->addeff[i].flag&ATF_LONG && !(attack_type&BF_LONG)) || + (sd->addeff[i].flag&ATF_SHORT && !(attack_type&BF_SHORT))) + continue; //Range Failed. + } - case MER_CRASH: - sc_start(bl,SC_STUN,(6*skilllv),skilllv,skill_get_time2(skillid,skilllv)); - break; + type = sd->addeff[i].id; + skill = skill_get_time2(status_sc2skill(type),7); - case AS_VENOMKNIFE: - if (sd) //Poison chance must be that of Envenom. [Skotlex] - skilllv = pc_checkskill(sd, TF_POISON); - case TF_POISON: - case AS_SPLASHER: - if (!sc_start2(bl,SC_POISON,(4*skilllv+10),skilllv,src->id,skill_get_time2(skillid,skilllv)) - && sd && skillid==TF_POISON - ) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; + if (sd->addeff[i].flag&ATF_TARGET) + status_change_start(bl,type,rate,7,0,0,0,skill,0); - case AS_SONICBLOW: - sc_start(bl,SC_STUN,(2*skilllv+10),skilllv,skill_get_time2(skillid,skilllv)); - break; + if (sd->addeff[i].flag&ATF_SELF) + status_change_start(src,type,rate,7,0,0,0,skill,0); + } + } - case WZ_FIREPILLAR: - unit_set_walkdelay(bl, tick, skill_get_time2(skillid, skilllv), 1); - break; + if( skillid ) + { // Trigger status effects on skills + enum sc_type type; + int i; + for( i = 0; i < ARRAYLENGTH(sd->addeff3) && sd->addeff3[i].skill; i++ ) + { + if( skillid != sd->addeff3[i].skill || !sd->addeff3[i].rate ) + continue; + type = sd->addeff3[i].id; + skill = skill_get_time2(status_sc2skill(type),7); + + if( sd->addeff3[i].target&ATF_TARGET ) + status_change_start(bl,type,sd->addeff3[i].rate,7,0,0,0,skill,0); + if( sd->addeff3[i].target&ATF_SELF ) + status_change_start(src,type,sd->addeff3[i].rate,7,0,0,0,skill,0); + } + } + } - case MG_FROSTDIVER: + if( dmg_lv < ATK_DEF ) // no damage, return; + return 0; + + switch(skillid) + { + case 0: // Normal attacks (no skill used) + { + if( attack_type&BF_SKILL ) + break; // If a normal attack is a skill, it's splash damage. [Inkfish] + if(sd) { + // Automatic trigger of Blitz Beat + if (pc_isfalcon(sd) && sd->status.weapon == W_BOW && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 && + rnd()%1000 <= sstatus->luk*10/3+1 ) { + rate=(sd->status.job_level+9)/10; + skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<rate)?skill:rate,tick,SD_LEVEL); + } + // Automatic trigger of Warg Strike [Jobbie] + if( pc_iswug(sd) && (sd->status.weapon == W_BOW || sd->status.weapon == W_FIST) && (skill=pc_checkskill(sd,RA_WUGSTRIKE)) > 0 && rnd()%1000 <= sstatus->luk*10/3+1 ) + skill_castend_damage_id(src,bl,RA_WUGSTRIKE,skill,tick,0); + // Gank + if(dstmd && sd->status.weapon != W_BOW && + (skill=pc_checkskill(sd,RG_SNATCHER)) > 0 && + (skill*15 + 55) + pc_checkskill(sd,TF_STEAL)*10 > rnd()%1000) { + if(pc_steal_item(sd,bl,pc_checkskill(sd,TF_STEAL))) + clif_skill_nodamage(src,bl,TF_STEAL,skill,1); + else + clif_skill_fail(sd,RG_SNATCHER,USESKILL_FAIL_LEVEL,0); + } + // Chance to trigger Taekwon kicks [Dralnu] + if(sc && !sc->data[SC_COMBO]) { + if(sc->data[SC_READYSTORM] && + sc_start(src,SC_COMBO, 15, TK_STORMKICK, + (2000 - 4*sstatus->agi - 2*sstatus->dex))) + ; //Stance triggered + else if(sc->data[SC_READYDOWN] && + sc_start(src,SC_COMBO, 15, TK_DOWNKICK, + (2000 - 4*sstatus->agi - 2*sstatus->dex))) + ; //Stance triggered + else if(sc->data[SC_READYTURN] && + sc_start(src,SC_COMBO, 15, TK_TURNKICK, + (2000 - 4*sstatus->agi - 2*sstatus->dex))) + ; //Stance triggered + else if (sc->data[SC_READYCOUNTER]) { //additional chance from SG_FRIEND [Komurka] + rate = 20; + if (sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == TK_COUNTER) { + rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100; + status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); + } + sc_start2(src, SC_COMBO, rate, TK_COUNTER, bl->id, + (2000 - 4*sstatus->agi - 2*sstatus->dex)); + } + } + if(sc && sc->data[SC_PYROCLASTIC] && (rnd() % 1000 <= sstatus->luk * 10 / 3 + 1) ) + skill_castend_pos2(src, bl->x, bl->y, BS_HAMMERFALL,sc->data[SC_PYROCLASTIC]->val1, tick, 0); + } + + if (sc) { + struct status_change_entry *sce; + // Enchant Poison gives a chance to poison attacked enemies + if((sce=sc->data[SC_ENCPOISON])) //Don't use sc_start since chance comes in 1/10000 rate. + status_change_start(bl,SC_POISON,sce->val2, sce->val1,src->id,0,0, + skill_get_time2(AS_ENCHANTPOISON,sce->val1),0); + // Enchant Deadly Poison gives a chance to deadly poison attacked enemies + if((sce=sc->data[SC_EDP])) + sc_start4(bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0, + skill_get_time2(ASC_EDP,sce->val1)); + } + } + break; + + case SM_BASH: + if( sd && skilllv > 5 && pc_checkskill(sd,SM_FATALBLOW)>0 ){ + //TODO: How much % per base level it actually is? + sc_start(bl,SC_STUN,(5*(skilllv-5)+(int)sd->status.base_level/10), + skilllv,skill_get_time2(SM_FATALBLOW,skilllv)); + } + break; + + case MER_CRASH: + sc_start(bl,SC_STUN,(6*skilllv),skilllv,skill_get_time2(skillid,skilllv)); + break; + + case AS_VENOMKNIFE: + if (sd) //Poison chance must be that of Envenom. [Skotlex] + skilllv = pc_checkskill(sd, TF_POISON); + case TF_POISON: + case AS_SPLASHER: + if(!sc_start2(bl,SC_POISON,(4*skilllv+10),skilllv,src->id,skill_get_time2(skillid,skilllv)) + && sd && skillid==TF_POISON + ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + + case AS_SONICBLOW: + sc_start(bl,SC_STUN,(2*skilllv+10),skilllv,skill_get_time2(skillid,skilllv)); + break; + + case WZ_FIREPILLAR: + unit_set_walkdelay(bl, tick, skill_get_time2(skillid, skilllv), 1); + break; + + case MG_FROSTDIVER: #ifndef RENEWAL - case WZ_FROSTNOVA: + case WZ_FROSTNOVA: #endif - sc_start(bl,SC_FREEZE,skilllv*3+35,skilllv,skill_get_time2(skillid,skilllv)); - break; + sc_start(bl,SC_FREEZE,skilllv*3+35,skilllv,skill_get_time2(skillid,skilllv)); + break; #ifdef RENEWAL - case WZ_FROSTNOVA: - sc_start(bl,SC_FREEZE,skilllv*5+33,skilllv,skill_get_time2(skillid,skilllv)); - break; + case WZ_FROSTNOVA: + sc_start(bl,SC_FREEZE,skilllv*5+33,skilllv,skill_get_time2(skillid,skilllv)); + break; #endif - case WZ_STORMGUST: - /** - * Storm Gust counter was dropped in renewal - **/ -#ifdef RENEWAL - sc_start(bl,SC_FREEZE,65-(5*skilllv),skilllv,skill_get_time2(skillid,skilllv)); -#else - //Tharis pointed out that this is normal freeze chance with a base of 300% - if (tsc->sg_counter >= 3 && - sc_start(bl,SC_FREEZE,300,skilllv,skill_get_time2(skillid,skilllv))) - tsc->sg_counter = 0; - /** - * being it only resets on success it'd keep stacking and eventually overflowing on mvps, so we reset at a high value - **/ - else if (tsc->sg_counter > 250) - tsc->sg_counter = 0; -#endif - break; + case WZ_STORMGUST: + /** + * Storm Gust counter was dropped in renewal + **/ + #ifdef RENEWAL + sc_start(bl,SC_FREEZE,65-(5*skilllv),skilllv,skill_get_time2(skillid,skilllv)); + #else + //Tharis pointed out that this is normal freeze chance with a base of 300% + if(tsc->sg_counter >= 3 && + sc_start(bl,SC_FREEZE,300,skilllv,skill_get_time2(skillid,skilllv))) + tsc->sg_counter = 0; + /** + * being it only resets on success it'd keep stacking and eventually overflowing on mvps, so we reset at a high value + **/ + else if( tsc->sg_counter > 250 ) + tsc->sg_counter = 0; + #endif + break; + + case WZ_METEOR: + sc_start(bl,SC_STUN,3*skilllv,skilllv,skill_get_time2(skillid,skilllv)); + break; + + case WZ_VERMILION: + sc_start(bl,SC_BLIND,4*skilllv,skilllv,skill_get_time2(skillid,skilllv)); + break; + + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + sc_start(bl,SC_FREEZE,(3*skilllv+35),skilllv,skill_get_time2(skillid,skilllv)); + break; + + case HT_FLASHER: + sc_start(bl,SC_BLIND,(10*skilllv+30),skilllv,skill_get_time2(skillid,skilllv)); + break; + + case HT_LANDMINE: + case MA_LANDMINE: + sc_start(bl,SC_STUN,(5*skilllv+30),skilllv,skill_get_time2(skillid,skilllv)); + break; + + case HT_SHOCKWAVE: + status_percent_damage(src, bl, 0, 15*skilllv+5, false); + break; + + case HT_SANDMAN: + case MA_SANDMAN: + sc_start(bl,SC_SLEEP,(10*skilllv+40),skilllv,skill_get_time2(skillid,skilllv)); + break; + + case TF_SPRINKLESAND: + sc_start(bl,SC_BLIND,20,skilllv,skill_get_time2(skillid,skilllv)); + break; + + case TF_THROWSTONE: + sc_start(bl,SC_STUN,3,skilllv,skill_get_time(skillid,skilllv)); + sc_start(bl,SC_BLIND,3,skilllv,skill_get_time2(skillid,skilllv)); + break; + + case NPC_DARKCROSS: + case CR_HOLYCROSS: + sc_start(bl,SC_BLIND,3*skilllv,skilllv,skill_get_time2(skillid,skilllv)); + break; + + case CR_GRANDCROSS: + case NPC_GRANDDARKNESS: + //Chance to cause blind status vs demon and undead element, but not against players + if(!dstsd && (battle_check_undead(tstatus->race,tstatus->def_ele) || tstatus->race == RC_DEMON)) + sc_start(bl,SC_BLIND,100,skilllv,skill_get_time2(skillid,skilllv)); + attack_type |= BF_WEAPON; + break; + + case AM_ACIDTERROR: + sc_start(bl,SC_BLEEDING,(skilllv*3),skilllv,skill_get_time2(skillid,skilllv)); + if (skill_break_equip(bl, EQP_ARMOR, 100*skill_get_time(skillid,skilllv), BCT_ENEMY)) + clif_emotion(bl,E_OMG); + break; + + case AM_DEMONSTRATION: + skill_break_equip(bl, EQP_WEAPON, 100*skilllv, BCT_ENEMY); + break; + + case CR_SHIELDCHARGE: + sc_start(bl,SC_STUN,(15+skilllv*5),skilllv,skill_get_time2(skillid,skilllv)); + break; + + case PA_PRESSURE: + status_percent_damage(src, bl, 0, 15+5*skilllv, false); + break; + + case RG_RAID: + sc_start(bl,SC_STUN,(10+3*skilllv),skilllv,skill_get_time(skillid,skilllv)); + sc_start(bl,SC_BLIND,(10+3*skilllv),skilllv,skill_get_time2(skillid,skilllv)); - case WZ_METEOR: - sc_start(bl,SC_STUN,3*skilllv,skilllv,skill_get_time2(skillid,skilllv)); - break; +#ifdef RENEWAL + sc_start(bl,SC_RAID,100,7,5000); + break; - case WZ_VERMILION: - sc_start(bl,SC_BLIND,4*skilllv,skilllv,skill_get_time2(skillid,skilllv)); - break; + case RG_BACKSTAP: + sc_start(bl,SC_STUN,(5+2*skilllv),skilllv,skill_get_time(skillid,skilllv)); +#endif + break; + + case BA_FROSTJOKER: + sc_start(bl,SC_FREEZE,(15+5*skilllv),skilllv,skill_get_time2(skillid,skilllv)); + break; + + case DC_SCREAM: + sc_start(bl,SC_STUN,(25+5*skilllv),skilllv,skill_get_time2(skillid,skilllv)); + break; + + case BD_LULLABY: + sc_start(bl,SC_SLEEP,15,skilllv,skill_get_time2(skillid,skilllv)); + break; + + case DC_UGLYDANCE: + rate = 5+5*skilllv; + if(sd && (skill=pc_checkskill(sd,DC_DANCINGLESSON))) + rate += 5+skill; + status_zap(bl, 0, rate); + break; + case SL_STUN: + if (tstatus->size==SZ_MEDIUM) //Only stuns mid-sized mobs. + sc_start(bl,SC_STUN,(30+10*skilllv),skilllv,skill_get_time(skillid,skilllv)); + break; + + case NPC_PETRIFYATTACK: + sc_start4(bl,status_skill2sc(skillid),50+10*skilllv, + skilllv,0,0,skill_get_time(skillid,skilllv), + skill_get_time2(skillid,skilllv)); + break; + case NPC_CURSEATTACK: + case NPC_SLEEPATTACK: + case NPC_BLINDATTACK: + case NPC_POISON: + case NPC_SILENCEATTACK: + case NPC_STUNATTACK: + case NPC_HELLPOWER: + sc_start(bl,status_skill2sc(skillid),50+10*skilllv,skilllv,skill_get_time2(skillid,skilllv)); + break; + case NPC_ACIDBREATH: + case NPC_ICEBREATH: + sc_start(bl,status_skill2sc(skillid),70,skilllv,skill_get_time2(skillid,skilllv)); + break; + case NPC_BLEEDING: + sc_start(bl,SC_BLEEDING,(20*skilllv),skilllv,skill_get_time2(skillid,skilllv)); + break; + case NPC_MENTALBREAKER: + { //Based on observations by Tharis, Mental Breaker should do SP damage + //equal to Matk*skLevel. + rate = sstatus->matk_min; + if (rate < sstatus->matk_max) + rate += rnd()%(sstatus->matk_max - sstatus->matk_min); + rate*=skilllv; + status_zap(bl, 0, rate); + break; + } + // Equipment breaking monster skills [Celest] + case NPC_WEAPONBRAKER: + skill_break_equip(bl, EQP_WEAPON, 150*skilllv, BCT_ENEMY); + break; + case NPC_ARMORBRAKE: + skill_break_equip(bl, EQP_ARMOR, 150*skilllv, BCT_ENEMY); + break; + case NPC_HELMBRAKE: + skill_break_equip(bl, EQP_HELM, 150*skilllv, BCT_ENEMY); + break; + case NPC_SHIELDBRAKE: + skill_break_equip(bl, EQP_SHIELD, 150*skilllv, BCT_ENEMY); + break; + + case CH_TIGERFIST: + sc_start(bl,SC_STOP,(10+skilllv*10),0,skill_get_time2(skillid,skilllv)); + break; + + case LK_SPIRALPIERCE: + case ML_SPIRALPIERCE: + sc_start(bl,SC_STOP,(15+skilllv*5),0,skill_get_time2(skillid,skilllv)); + break; + + case ST_REJECTSWORD: + sc_start(bl,SC_AUTOCOUNTER,(skilllv*15),skilllv,skill_get_time(skillid,skilllv)); + break; + + case PF_FOGWALL: + if (src != bl && !tsc->data[SC_DELUGE]) + status_change_start(bl,SC_BLIND,10000,skilllv,0,0,0,skill_get_time2(skillid,skilllv),8); + break; + + case LK_HEADCRUSH: //Headcrush has chance of causing Bleeding status, except on demon and undead element + if (!(battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON)) + sc_start(bl, SC_BLEEDING,50, skilllv, skill_get_time2(skillid,skilllv)); + break; + + case LK_JOINTBEAT: + status = status_skill2sc(skillid); + if (tsc->jb_flag) { + sc_start2(bl,status,(5*skilllv+5),skilllv,tsc->jb_flag&BREAK_FLAGS,skill_get_time2(skillid,skilllv)); + tsc->jb_flag = 0; + } + break; + case ASC_METEORASSAULT: + //Any enemies hit by this skill will receive Stun, Darkness, or external bleeding status ailment with a 5%+5*SkillLV% chance. + switch(rnd()%3) { + case 0: + sc_start(bl,SC_BLIND,(5+skilllv*5),skilllv,skill_get_time2(skillid,1)); + break; + case 1: + sc_start(bl,SC_STUN,(5+skilllv*5),skilllv,skill_get_time2(skillid,2)); + break; + default: + sc_start(bl,SC_BLEEDING,(5+skilllv*5),skilllv,skill_get_time2(skillid,3)); + } + break; + + case HW_NAPALMVULCAN: + sc_start(bl,SC_CURSE,5*skilllv,skilllv,skill_get_time2(skillid,skilllv)); + break; + + case WS_CARTTERMINATION: // Cart termination + sc_start(bl,SC_STUN,5*skilllv,skilllv,skill_get_time2(skillid,skilllv)); + break; + + case CR_ACIDDEMONSTRATION: + skill_break_equip(bl, EQP_WEAPON|EQP_ARMOR, 100*skilllv, BCT_ENEMY); + break; + + case TK_DOWNKICK: + sc_start(bl,SC_STUN,100,skilllv,skill_get_time2(skillid,skilllv)); + break; + + case TK_JUMPKICK: + if( dstsd && dstsd->class_ != MAPID_SOUL_LINKER && !tsc->data[SC_PRESERVE] ) + {// debuff the following statuses + status_change_end(bl, SC_SPIRIT, INVALID_TIMER); + status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); + status_change_end(bl, SC_KAITE, INVALID_TIMER); + status_change_end(bl, SC_KAAHI, INVALID_TIMER); + status_change_end(bl, SC_ONEHAND, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); + } + break; + case TK_TURNKICK: + case MO_BALKYOUNG: //Note: attack_type is passed as BF_WEAPON for the actual target, BF_MISC for the splash-affected mobs. + if(attack_type&BF_MISC) //70% base stun chance... + sc_start(bl,SC_STUN,70,skilllv,skill_get_time2(skillid,skilllv)); + break; + case GS_BULLSEYE: //0.1% coma rate. + if(tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN) + status_change_start(bl,SC_COMA,10,skilllv,0,src->id,0,0,0); + break; + case GS_PIERCINGSHOT: + sc_start(bl,SC_BLEEDING,(skilllv*3),skilllv,skill_get_time2(skillid,skilllv)); + break; + case NJ_HYOUSYOURAKU: + sc_start(bl,SC_FREEZE,(10+10*skilllv),skilllv,skill_get_time2(skillid,skilllv)); + break; + case GS_FLING: + sc_start(bl,SC_FLING,100, sd?sd->spiritball_old:5,skill_get_time(skillid,skilllv)); + break; + case GS_DISARM: + rate = 3*skilllv; + if (sstatus->dex > tstatus->dex) + rate += (sstatus->dex - tstatus->dex)/5; //TODO: Made up formula + skill_strip_equip(bl, EQP_WEAPON, rate, skilllv, skill_get_time(skillid,skilllv)); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + case NPC_EVILLAND: + sc_start(bl,SC_BLIND,5*skilllv,skilllv,skill_get_time2(skillid,skilllv)); + break; + case NPC_HELLJUDGEMENT: + sc_start(bl,SC_CURSE,100,skilllv,skill_get_time2(skillid,skilllv)); + break; + case NPC_CRITICALWOUND: + sc_start(bl,SC_CRITICALWOUND,100,skilllv,skill_get_time2(skillid,skilllv)); + break; + case RK_HUNDREDSPEAR: + if( !sd || pc_checkskill(sd,KN_SPEARBOOMERANG) == 0 ) + break; // Spear Boomerang auto cast chance only works if you have mastered Spear Boomerang. + rate = 10 + 3 * skilllv; + if( rnd()%100 < rate ) + skill_castend_damage_id(src,bl,KN_SPEARBOOMERANG,1,tick,0); + break; + case RK_WINDCUTTER: + sc_start(bl,SC_FEAR,3+2*skilllv,skilllv,skill_get_time(skillid,skilllv)); + break; + case RK_DRAGONBREATH: + sc_start4(bl,SC_BURNING,5+5*skilllv,skilllv,1000,src->id,0,skill_get_time(skillid,skilllv)); + break; + case AB_ADORAMUS: + if( tsc && !tsc->data[SC_DECREASEAGI] ) //Prevent duplicate agi-down effect. + sc_start(bl, SC_ADORAMUS, 100, skilllv, skill_get_time(skillid, skilllv)); + break; + case WL_CRIMSONROCK: + sc_start(bl, SC_STUN, 40, skilllv, skill_get_time(skillid, skilllv)); + break; + case WL_COMET: + sc_start4(bl,SC_BURNING,100,skilllv,1000,src->id,0,skill_get_time(skillid,skilllv)); + break; + case WL_EARTHSTRAIN: + { + int rate = 0, i; + const int pos[5] = { EQP_WEAPON, EQP_HELM, EQP_SHIELD, EQP_ARMOR, EQP_ACC }; + rate = 6 * skilllv + sstatus->dex / 10 + (sd? sd->status.job_level / 4 : 0) - tstatus->dex /5;// The tstatus->dex / 5 part is unofficial, but players gotta have some kind of way to have resistance. [Rytech] + //rate -= rate * tstatus->dex / 200; // Disabled until official resistance is found. + + for( i = 0; i < skilllv; i++ ) + skill_strip_equip(bl,pos[i],rate,skilllv,skill_get_time2(skillid,skilllv)); + } + break; + case WL_JACKFROST: + sc_start(bl,SC_FREEZE,100,skilllv,skill_get_time(skillid,skilllv)); + break; + case RA_WUGBITE: + sc_start(bl, SC_BITE, (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*2 : 0), skilllv, (skill_get_time(skillid,skilllv) + (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*500 : 0)) ); + break; + case RA_SENSITIVEKEEN: + if( rnd()%100 < 8 * skilllv ) + skill_castend_damage_id(src, bl, RA_WUGBITE, sd ? pc_checkskill(sd, RA_WUGBITE):skilllv, tick, SD_ANIMATION); + break; + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + sc_start(bl, (skillid == RA_FIRINGTRAP) ? SC_BURNING:SC_FREEZING, 40 + 10 * skilllv, skilllv, skill_get_time2(skillid, skilllv)); + break; + case NC_PILEBUNKER: + if( rnd()%100 < 5 + 15*skilllv ) + { //Deactivatable Statuses: Kyrie Eleison, Auto Guard, Steel Body, Assumptio, and Millennium Shield + status_change_end(bl, SC_KYRIE, INVALID_TIMER); + status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER); + status_change_end(bl, SC_STEELBODY, INVALID_TIMER); + status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); + status_change_end(bl, SC_MILLENNIUMSHIELD, INVALID_TIMER); + } + break; + case NC_FLAMELAUNCHER: + sc_start4(bl, SC_BURNING, 50 + 10 * skilllv, skilllv, 1000, src->id, 0, skill_get_time2(skillid, skilllv)); + break; + case NC_COLDSLOWER: + sc_start(bl, SC_FREEZE, 10 * skilllv, skilllv, skill_get_time(skillid, skilllv)); + sc_start(bl, SC_FREEZING, 20 + 10 * skilllv, skilllv, skill_get_time(skillid, skilllv)); + break; + case NC_POWERSWING: + sc_start(bl, SC_STUN, 5*skilllv, skilllv, skill_get_time(skillid, skilllv)); + if( rnd()%100 < 5*skilllv ) + skill_castend_damage_id(src, bl, NC_AXEBOOMERANG, pc_checkskill(sd, NC_AXEBOOMERANG), tick, 1); + break; + case GC_WEAPONCRUSH: + skill_castend_nodamage_id(src,bl,skillid,skilllv,tick,BCT_ENEMY); + break; + case LG_SHIELDPRESS: + sc_start(bl, SC_STUN, 30 + 8 * skilllv, skilllv, skill_get_time(skillid,skilllv)); + break; + case LG_PINPOINTATTACK: + rate = 30 + (((5 * (sd?pc_checkskill(sd,LG_PINPOINTATTACK):skilllv)) + (sstatus->agi + status_get_lv(src))) / 10); + switch( skilllv ) { + case 1: + sc_start(bl,SC_BLEEDING,rate,skilllv,skill_get_time(skillid,skilllv)); + break; + case 2: + if( dstsd && dstsd->spiritball && rnd()%100 < rate ) + pc_delspiritball(dstsd, dstsd->spiritball, 0); + break; + default: + skill_break_equip(bl,(skilllv == 3) ? EQP_SHIELD : (skilllv == 4) ? EQP_ARMOR : EQP_WEAPON,rate * 100,BCT_ENEMY); + break; + } + break; + case LG_MOONSLASHER: + rate = 32 + 8 * skilllv; + if( rnd()%100 < rate && dstsd ) // Uses skill_addtimerskill to avoid damage and setsit packet overlaping. Officially clif_setsit is received about 500 ms after damage packet. + skill_addtimerskill(src,tick+500,bl->id,0,0,skillid,skilllv,BF_WEAPON,0); + else if( dstmd && !is_boss(bl) ) + sc_start(bl,SC_STOP,100,skilllv,skill_get_time(skillid,skilllv)); + break; + case LG_RAYOFGENESIS: // 50% chance to cause Blind on Undead and Demon monsters. + if ( battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON ) + sc_start(bl, SC_BLIND,50, skilllv, skill_get_time(skillid,skilllv)); + break; + case LG_EARTHDRIVE: + skill_break_equip(src, EQP_SHIELD, 500, BCT_SELF); + sc_start(bl, SC_EARTHDRIVE, 100, skilllv, skill_get_time(skillid, skilllv)); + break; + case SR_DRAGONCOMBO: + sc_start(bl, SC_STUN, 1 + skilllv, skilllv, skill_get_time(skillid, skilllv)); + break; + case SR_FALLENEMPIRE: + sc_start(bl, SC_STOP, 100, skilllv, skill_get_time(skillid, skilllv)); + break; + case SR_WINDMILL: + if( dstsd ) + skill_addtimerskill(src,tick+status_get_amotion(src),bl->id,0,0,skillid,skilllv,BF_WEAPON,0); + else if( dstmd && !is_boss(bl) ) + sc_start(bl, SC_STUN, 100, skilllv, 1000 + 1000 * (rnd() %3)); + break; + case SR_GENTLETOUCH_QUIET: // [(Skill Level x 5) + (Caster?s DEX + Caster?s Base Level) / 10] + sc_start(bl, SC_SILENCE, 5 * skilllv + (sstatus->dex + status_get_lv(src)) / 10, skilllv, skill_get_time(skillid, skilllv)); + break; + case SR_EARTHSHAKER: + sc_start(bl,SC_STUN, 25 + 5 * skilllv,skilllv,skill_get_time(skillid,skilllv)); + break; + case SR_HOWLINGOFLION: + sc_start(bl, SC_FEAR, 5 + 5 * skilllv, skilllv, skill_get_time(skillid, skilllv)); + break; + case WM_SOUND_OF_DESTRUCTION: + if( rnd()%100 < 5 + 5 * skilllv ) { // Temporarly Check Until We Get the Official Formula + status_change_end(bl, SC_DANCING, INVALID_TIMER); + status_change_end(bl, SC_RICHMANKIM, INVALID_TIMER); + status_change_end(bl, SC_ETERNALCHAOS, INVALID_TIMER); + status_change_end(bl, SC_DRUMBATTLE, INVALID_TIMER); + status_change_end(bl, SC_NIBELUNGEN, INVALID_TIMER); + status_change_end(bl, SC_INTOABYSS, INVALID_TIMER); + status_change_end(bl, SC_SIEGFRIED, INVALID_TIMER); + status_change_end(bl, SC_WHISTLE, INVALID_TIMER); + status_change_end(bl, SC_ASSNCROS, INVALID_TIMER); + status_change_end(bl, SC_POEMBRAGI, INVALID_TIMER); + status_change_end(bl, SC_APPLEIDUN, INVALID_TIMER); + status_change_end(bl, SC_HUMMING, INVALID_TIMER); + status_change_end(bl, SC_FORTUNE, INVALID_TIMER); + status_change_end(bl, SC_SERVICE4U, INVALID_TIMER); + status_change_end(bl, SC_LONGING, INVALID_TIMER); + status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); + status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); + status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); + status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); + status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); + status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + status_change_end(bl, SC_WINKCHARM, INVALID_TIMER); + status_change_end(bl, SC_SONGOFMANA, INVALID_TIMER); + status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); + status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); + status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); + status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); + status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); + } + break; + case SO_EARTHGRAVE: + sc_start(bl, SC_BLEEDING, 5 * skilllv, skilllv, skill_get_time2(skillid, skilllv)); // Need official rate. [LimitLine] + break; + case SO_DIAMONDDUST: + rate = 5 + 5 * skilllv; + if( sc && sc->data[SC_COOLER_OPTION] ) + rate += rate * sc->data[SC_COOLER_OPTION]->val2 / 100; + sc_start(bl, SC_CRYSTALIZE, rate, skilllv, skill_get_time2(skillid, skilllv)); + break; + case SO_VARETYR_SPEAR: + sc_start(bl, SC_STUN, 5 + 5 * skilllv, skilllv, skill_get_time2(skillid, skilllv)); + break; + case GN_SLINGITEM_RANGEMELEEATK: + if( sd ) { + switch( sd->itemid ) { // Starting SCs here instead of do it in skill_additional_effect to simplify the code. + case 13261: + sc_start(bl, SC_STUN, 100, skilllv, skill_get_time2(GN_SLINGITEM, skilllv)); + sc_start(bl, SC_BLEEDING, 100, skilllv, skill_get_time2(GN_SLINGITEM, skilllv)); + break; + case 13262: + sc_start(bl, SC_MELON_BOMB, 100, skilllv, skill_get_time(GN_SLINGITEM, skilllv)); // Reduces ASPD and moviment speed + break; + case 13264: + sc_start(bl, SC_BANANA_BOMB, 100, skilllv, skill_get_time(GN_SLINGITEM, skilllv)); // Reduces LUK ??Needed confirm it, may be it's bugged in kRORE? + sc_start(bl, SC_BANANA_BOMB_SITDOWN, 75, skilllv, skill_get_time(GN_SLINGITEM_RANGEMELEEATK,skilllv)); // Sitdown for 3 seconds. + break; + } + sd->itemid = -1; + } + break; + case GN_HELLS_PLANT_ATK: + sc_start(bl, SC_STUN, 5 + 5 * skilllv, skilllv, skill_get_time2(skillid, skilllv)); + sc_start(bl, SC_BLEEDING, 20 + 10 * skilllv, skilllv, skill_get_time2(skillid, skilllv)); + break; + case EL_WIND_SLASH: // Non confirmed rate. + sc_start(bl, SC_BLEEDING, 25, skilllv, skill_get_time(skillid,skilllv)); + break; + case EL_STONE_HAMMER: + rate = 10 * skilllv; + sc_start(bl, SC_STUN, rate, skilllv, skill_get_time(skillid,skilllv)); + break; + case EL_ROCK_CRUSHER: + case EL_ROCK_CRUSHER_ATK: + sc_start(bl,status_skill2sc(skillid),50,skilllv,skill_get_time(EL_ROCK_CRUSHER,skilllv)); + break; + case EL_TYPOON_MIS: + sc_start(bl,SC_SILENCE,10*skilllv,skilllv,skill_get_time(skillid,skilllv)); + break; + case KO_JYUMONJIKIRI: // needs more info + sc_start(bl,SC_JYUMONJIKIRI,25,skilllv,skill_get_time(skillid,skilllv)); + break; + case KO_MAKIBISHI: + sc_start(bl, SC_STUN, 100, skilllv, skill_get_time2(skillid,skilllv)); + break; + case MH_LAVA_SLIDE: + if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skilllv, skilllv, 1000, src->id, 0, skill_get_time(skillid, skilllv)); + break; + case MH_STAHL_HORN: + sc_start(bl, SC_STUN, (20 + 4 * (skilllv-1)), skilllv, skill_get_time(skillid, skilllv)); + break; + case MH_NEEDLE_OF_PARALYZE: + sc_start(bl, SC_PARALYSIS, 40 + (5*skilllv), skilllv, skill_get_time(skillid, skilllv)); + break; + } - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - sc_start(bl,SC_FREEZE,(3*skilllv+35),skilllv,skill_get_time2(skillid,skilllv)); - break; + if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) + { //Pass heritage to Master for status causing effects. [Skotlex] + sd = map_id2sd(md->master_id); + src = sd?&sd->bl:src; + } - case HT_FLASHER: - sc_start(bl,SC_BLIND,(10*skilllv+30),skilllv,skill_get_time2(skillid,skilllv)); - break; + if( attack_type&BF_WEAPON ) + { // Coma, Breaking Equipment + if( sd && sd->special_state.bonus_coma ) + { + rate = sd->weapon_coma_ele[tstatus->def_ele]; + rate += sd->weapon_coma_race[tstatus->race]; + rate += sd->weapon_coma_race[tstatus->mode&MD_BOSS?RC_BOSS:RC_NONBOSS]; + if (rate) + status_change_start(bl, SC_COMA, rate, 0, 0, src->id, 0, 0, 0); + } + if( sd && battle_config.equip_self_break_rate ) + { // Self weapon breaking + rate = battle_config.equip_natural_break_rate; + if( sc ) + { + if(sc->data[SC_OVERTHRUST]) + rate += 10; + if(sc->data[SC_MAXOVERTHRUST]) + rate += 10; + } + if( rate ) + skill_break_equip(src, EQP_WEAPON, rate, BCT_SELF); + } + if( battle_config.equip_skill_break_rate && skillid != WS_CARTTERMINATION && skillid != ITM_TOMAHAWK ) + { // Cart Termination/Tomahawk won't trigger breaking data. Why? No idea, go ask Gravity. + // Target weapon breaking + rate = 0; + if( sd ) + rate += sd->bonus.break_weapon_rate; + if( sc && sc->data[SC_MELTDOWN] ) + rate += sc->data[SC_MELTDOWN]->val2; + if( rate ) + skill_break_equip(bl, EQP_WEAPON, rate, BCT_ENEMY); + + // Target armor breaking + rate = 0; + if( sd ) + rate += sd->bonus.break_armor_rate; + if( sc && sc->data[SC_MELTDOWN] ) + rate += sc->data[SC_MELTDOWN]->val3; + if( rate ) + skill_break_equip(bl, EQP_ARMOR, rate, BCT_ENEMY); + } + } - case HT_LANDMINE: - case MA_LANDMINE: - sc_start(bl,SC_STUN,(5*skilllv+30),skilllv,skill_get_time2(skillid,skilllv)); - break; + // Autospell when attacking + if( sd && !status_isdead(bl) && sd->autospell[0].id ) + { + struct block_list *tbl; + struct unit_data *ud; + int i, skilllv, type, notok; - case HT_SHOCKWAVE: - status_percent_damage(src, bl, 0, 15*skilllv+5, false); - break; + for (i = 0; i < ARRAYLENGTH(sd->autospell) && sd->autospell[i].id; i++) { - case HT_SANDMAN: - case MA_SANDMAN: - sc_start(bl,SC_SLEEP,(10*skilllv+40),skilllv,skill_get_time2(skillid,skilllv)); - break; + if(!(sd->autospell[i].flag&attack_type&BF_WEAPONMASK && + sd->autospell[i].flag&attack_type&BF_RANGEMASK && + sd->autospell[i].flag&attack_type&BF_SKILLMASK)) + continue; // one or more trigger conditions were not fulfilled - case TF_SPRINKLESAND: - sc_start(bl,SC_BLIND,20,skilllv,skill_get_time2(skillid,skilllv)); - break; + skill = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id; - case TF_THROWSTONE: - sc_start(bl,SC_STUN,3,skilllv,skill_get_time(skillid,skilllv)); - sc_start(bl,SC_BLIND,3,skilllv,skill_get_time2(skillid,skilllv)); - break; + sd->state.autocast = 1; + notok = skillnotok(skill, sd); + sd->state.autocast = 0; - case NPC_DARKCROSS: - case CR_HOLYCROSS: - sc_start(bl,SC_BLIND,3*skilllv,skilllv,skill_get_time2(skillid,skilllv)); - break; + if ( notok ) + continue; - case CR_GRANDCROSS: - case NPC_GRANDDARKNESS: - //Chance to cause blind status vs demon and undead element, but not against players - if (!dstsd && (battle_check_undead(tstatus->race,tstatus->def_ele) || tstatus->race == RC_DEMON)) - sc_start(bl,SC_BLIND,100,skilllv,skill_get_time2(skillid,skilllv)); - attack_type |= BF_WEAPON; - break; + skilllv = sd->autospell[i].lv?sd->autospell[i].lv:1; + if (skilllv < 0) skilllv = 1+rnd()%(-skilllv); - case AM_ACIDTERROR: - sc_start(bl,SC_BLEEDING,(skilllv*3),skilllv,skill_get_time2(skillid,skilllv)); - if (skill_break_equip(bl, EQP_ARMOR, 100*skill_get_time(skillid,skilllv), BCT_ENEMY)) - clif_emotion(bl,E_OMG); - break; + rate = (!sd->state.arrow_atk) ? sd->autospell[i].rate : sd->autospell[i].rate / 2; - case AM_DEMONSTRATION: - skill_break_equip(bl, EQP_WEAPON, 100*skilllv, BCT_ENEMY); - break; + if (rnd()%1000 >= rate) + continue; - case CR_SHIELDCHARGE: - sc_start(bl,SC_STUN,(15+skilllv*5),skilllv,skill_get_time2(skillid,skilllv)); - break; + tbl = (sd->autospell[i].id < 0) ? src : bl; - case PA_PRESSURE: - status_percent_damage(src, bl, 0, 15+5*skilllv, false); - break; + if( (type = skill_get_casttype(skill)) == CAST_GROUND ) { + int maxcount = 0; + if( !(BL_PC&battle_config.skill_reiteration) && + skill_get_unit_flag(skill)&UF_NOREITERATION && + skill_check_unit_range(src,tbl->x,tbl->y,skill,skilllv) + ) { + continue; + } + if( BL_PC&battle_config.skill_nofootset && + skill_get_unit_flag(skill)&UF_NOFOOTSET && + skill_check_unit_range2(src,tbl->x,tbl->y,skill,skilllv) + ) { + continue; + } + if( BL_PC&battle_config.land_skill_limit && + (maxcount = skill_get_maxcount(skill, skilllv)) > 0 + ) { + int v; + for(v=0;v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount;v++) { + if(sd->ud.skillunit[v]->skill_id == skill) + maxcount--; + } + if( maxcount == 0 ) { + continue; + } + } + } + if( battle_config.autospell_check_range && + !battle_check_range(src, tbl, skill_get_range2(src, skill,skilllv) + (skill == RG_CLOSECONFINE?0:1)) ) + continue; + + if (skill == AS_SONICBLOW) + pc_stop_attack(sd); //Special case, Sonic Blow autospell should stop the player attacking. + if (skill == PF_SPIDERWEB) //Special case, due to its nature of coding. + type = CAST_GROUND; + + sd->state.autocast = 1; + skill_consume_requirement(sd,skill,skilllv,1); + skill_toggle_magicpower(src, skill); + switch (type) { + case CAST_GROUND: + skill_castend_pos2(src, tbl->x, tbl->y, skill, skilllv, tick, 0); + break; + case CAST_NODAMAGE: + skill_castend_nodamage_id(src, tbl, skill, skilllv, tick, 0); + break; + case CAST_DAMAGE: + skill_castend_damage_id(src, tbl, skill, skilllv, tick, 0); + break; + } + sd->state.autocast = 0; + //Set canact delay. [Skotlex] + ud = unit_bl2ud(src); + if (ud) { + rate = skill_delayfix(src, skill, skilllv); + if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ + ud->canact_tick = tick+rate; + if ( battle_config.display_status_timers && sd ) + clif_status_change(src, SI_ACTIONDELAY, 1, rate, 0, 0, 0); + } + } + } + } - case RG_RAID: - sc_start(bl,SC_STUN,(10+3*skilllv),skilllv,skill_get_time(skillid,skilllv)); - sc_start(bl,SC_BLIND,(10+3*skilllv),skilllv,skill_get_time2(skillid,skilllv)); + //Autobonus when attacking + if( sd && sd->autobonus[0].rate ) + { + int i; + for( i = 0; i < ARRAYLENGTH(sd->autobonus); i++ ) + { + if( rnd()%1000 >= sd->autobonus[i].rate ) + continue; + if( sd->autobonus[i].active != INVALID_TIMER ) + continue; + if(!(sd->autobonus[i].atk_type&attack_type&BF_WEAPONMASK && + sd->autobonus[i].atk_type&attack_type&BF_RANGEMASK && + sd->autobonus[i].atk_type&attack_type&BF_SKILLMASK)) + continue; // one or more trigger conditions were not fulfilled + pc_exeautobonus(sd,&sd->autobonus[i]); + } + } -#ifdef RENEWAL - sc_start(bl,SC_RAID,100,7,5000); - break; + //Polymorph + if(sd && sd->bonus.classchange && attack_type&BF_WEAPON && + dstmd && !(tstatus->mode&MD_BOSS) && + (rnd()%10000 < sd->bonus.classchange)) + { + struct mob_db *mob; + int class_; + skill = 0; + do { + do { + class_ = rnd() % MAX_MOB_DB; + } while (!mobdb_checkid(class_)); + + rate = rnd() % 1000000; + mob = mob_db(class_); + } while ( + (mob->status.mode&(MD_BOSS|MD_PLANT) || mob->summonper[0] <= rate) && + (skill++) < 2000); + if (skill < 2000) + mob_class_change(dstmd,class_); + } - case RG_BACKSTAP: - sc_start(bl,SC_STUN,(5+2*skilllv),skilllv,skill_get_time(skillid,skilllv)); -#endif - break; + return 0; +} - case BA_FROSTJOKER: - sc_start(bl,SC_FREEZE,(15+5*skilllv),skilllv,skill_get_time2(skillid,skilllv)); - break; +int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, int skillid, unsigned int tick) { + int skill, skilllv, i, type, notok; + struct block_list *tbl; - case DC_SCREAM: - sc_start(bl,SC_STUN,(25+5*skilllv),skilllv,skill_get_time2(skillid,skilllv)); - break; + if( sd == NULL || skillid <= 0 ) + return 0; - case BD_LULLABY: - sc_start(bl,SC_SLEEP,15,skilllv,skill_get_time2(skillid,skilllv)); - break; + for( i = 0; i < ARRAYLENGTH(sd->autospell3) && sd->autospell3[i].flag; i++ ) { + if( sd->autospell3[i].flag != skillid ) + continue; - case DC_UGLYDANCE: - rate = 5+5*skilllv; - if (sd && (skill=pc_checkskill(sd,DC_DANCINGLESSON))) - rate += 5+skill; - status_zap(bl, 0, rate); - break; - case SL_STUN: - if (tstatus->size==SZ_MEDIUM) //Only stuns mid-sized mobs. - sc_start(bl,SC_STUN,(30+10*skilllv),skilllv,skill_get_time(skillid,skilllv)); - break; + if( sd->autospell3[i].lock ) + continue; // autospell already being executed - case NPC_PETRIFYATTACK: - sc_start4(bl,status_skill2sc(skillid),50+10*skilllv, - skilllv,0,0,skill_get_time(skillid,skilllv), - skill_get_time2(skillid,skilllv)); - break; - case NPC_CURSEATTACK: - case NPC_SLEEPATTACK: - case NPC_BLINDATTACK: - case NPC_POISON: - case NPC_SILENCEATTACK: - case NPC_STUNATTACK: - case NPC_HELLPOWER: - sc_start(bl,status_skill2sc(skillid),50+10*skilllv,skilllv,skill_get_time2(skillid,skilllv)); - break; - case NPC_ACIDBREATH: - case NPC_ICEBREATH: - sc_start(bl,status_skill2sc(skillid),70,skilllv,skill_get_time2(skillid,skilllv)); - break; - case NPC_BLEEDING: - sc_start(bl,SC_BLEEDING,(20*skilllv),skilllv,skill_get_time2(skillid,skilllv)); - break; - case NPC_MENTALBREAKER: { - //Based on observations by Tharis, Mental Breaker should do SP damage - //equal to Matk*skLevel. - rate = sstatus->matk_min; - if (rate < sstatus->matk_max) - rate += rnd()%(sstatus->matk_max - sstatus->matk_min); - rate*=skilllv; - status_zap(bl, 0, rate); - break; - } - // Equipment breaking monster skills [Celest] - case NPC_WEAPONBRAKER: - skill_break_equip(bl, EQP_WEAPON, 150*skilllv, BCT_ENEMY); - break; - case NPC_ARMORBRAKE: - skill_break_equip(bl, EQP_ARMOR, 150*skilllv, BCT_ENEMY); - break; - case NPC_HELMBRAKE: - skill_break_equip(bl, EQP_HELM, 150*skilllv, BCT_ENEMY); - break; - case NPC_SHIELDBRAKE: - skill_break_equip(bl, EQP_SHIELD, 150*skilllv, BCT_ENEMY); - break; + skill = (sd->autospell3[i].id > 0) ? sd->autospell3[i].id : -sd->autospell3[i].id; - case CH_TIGERFIST: - sc_start(bl,SC_STOP,(10+skilllv*10),0,skill_get_time2(skillid,skilllv)); - break; + sd->state.autocast = 1; + notok = skillnotok(skill, sd); + sd->state.autocast = 0; - case LK_SPIRALPIERCE: - case ML_SPIRALPIERCE: - sc_start(bl,SC_STOP,(15+skilllv*5),0,skill_get_time2(skillid,skilllv)); - break; + if ( notok ) + continue; - case ST_REJECTSWORD: - sc_start(bl,SC_AUTOCOUNTER,(skilllv*15),skilllv,skill_get_time(skillid,skilllv)); - break; + skilllv = sd->autospell3[i].lv ? sd->autospell3[i].lv : 1; + if( skilllv < 0 ) skilllv = 1 + rnd()%(-skilllv); - case PF_FOGWALL: - if (src != bl && !tsc->data[SC_DELUGE]) - status_change_start(bl,SC_BLIND,10000,skilllv,0,0,0,skill_get_time2(skillid,skilllv),8); - break; + if( sd->autospell3[i].id >= 0 && bl == NULL ) + continue; // No target + if( rnd()%1000 >= sd->autospell3[i].rate ) + continue; - case LK_HEADCRUSH: //Headcrush has chance of causing Bleeding status, except on demon and undead element - if (!(battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON)) - sc_start(bl, SC_BLEEDING,50, skilllv, skill_get_time2(skillid,skilllv)); - break; + tbl = (sd->autospell3[i].id < 0) ? &sd->bl : bl; - case LK_JOINTBEAT: - status = status_skill2sc(skillid); - if (tsc->jb_flag) { - sc_start2(bl,status,(5*skilllv+5),skilllv,tsc->jb_flag&BREAK_FLAGS,skill_get_time2(skillid,skilllv)); - tsc->jb_flag = 0; - } - break; - case ASC_METEORASSAULT: - //Any enemies hit by this skill will receive Stun, Darkness, or external bleeding status ailment with a 5%+5*SkillLV% chance. - switch (rnd()%3) { - case 0: - sc_start(bl,SC_BLIND,(5+skilllv*5),skilllv,skill_get_time2(skillid,1)); - break; - case 1: - sc_start(bl,SC_STUN,(5+skilllv*5),skilllv,skill_get_time2(skillid,2)); - break; - default: - sc_start(bl,SC_BLEEDING,(5+skilllv*5),skilllv,skill_get_time2(skillid,3)); - } - break; + if( (type = skill_get_casttype(skill)) == CAST_GROUND ) { + int maxcount = 0; + if( !(BL_PC&battle_config.skill_reiteration) && + skill_get_unit_flag(skill)&UF_NOREITERATION && + skill_check_unit_range(&sd->bl,tbl->x,tbl->y,skill,skilllv) + ) { + continue; + } + if( BL_PC&battle_config.skill_nofootset && + skill_get_unit_flag(skill)&UF_NOFOOTSET && + skill_check_unit_range2(&sd->bl,tbl->x,tbl->y,skill,skilllv) + ) { + continue; + } + if( BL_PC&battle_config.land_skill_limit && + (maxcount = skill_get_maxcount(skill, skilllv)) > 0 + ) { + int v; + for(v=0;v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount;v++) { + if(sd->ud.skillunit[v]->skill_id == skill) + maxcount--; + } + if( maxcount == 0 ) { + continue; + } + } + } + if( battle_config.autospell_check_range && + !battle_check_range(&sd->bl, tbl, skill_get_range2(&sd->bl, skill,skilllv) + (skill == RG_CLOSECONFINE?0:1)) ) + continue; + + sd->state.autocast = 1; + sd->autospell3[i].lock = true; + skill_consume_requirement(sd,skill,skilllv,1); + switch( type ) + { + case CAST_GROUND: skill_castend_pos2(&sd->bl, tbl->x, tbl->y, skill, skilllv, tick, 0); break; + case CAST_NODAMAGE: skill_castend_nodamage_id(&sd->bl, tbl, skill, skilllv, tick, 0); break; + case CAST_DAMAGE: skill_castend_damage_id(&sd->bl, tbl, skill, skilllv, tick, 0); break; + } + sd->autospell3[i].lock = false; + sd->state.autocast = 0; + } - case HW_NAPALMVULCAN: - sc_start(bl,SC_CURSE,5*skilllv,skilllv,skill_get_time2(skillid,skilllv)); - break; + if( sd && sd->autobonus3[0].rate ) + { + for( i = 0; i < ARRAYLENGTH(sd->autobonus3); i++ ) + { + if( rnd()%1000 >= sd->autobonus3[i].rate ) + continue; + if( sd->autobonus3[i].active != INVALID_TIMER ) + continue; + if( sd->autobonus3[i].atk_type != skillid ) + continue; + pc_exeautobonus(sd,&sd->autobonus3[i]); + } + } - case WS_CARTTERMINATION: // Cart termination - sc_start(bl,SC_STUN,5*skilllv,skilllv,skill_get_time2(skillid,skilllv)); - break; + return 1; +} - case CR_ACIDDEMONSTRATION: - skill_break_equip(bl, EQP_WEAPON|EQP_ARMOR, 100*skilllv, BCT_ENEMY); - break; +/* Splitted off from skill_additional_effect, which is never called when the + * attack skill kills the enemy. Place in this function counter status effects + * when using skills (eg: Asura's sp regen penalty, or counter-status effects + * from cards) that will take effect on the source, not the target. [Skotlex] + * Note: Currently this function only applies to Extremity Fist and BF_WEAPON + * type of skills, so not every instance of skill_additional_effect needs a call + * to this one. + */ +int skill_counter_additional_effect (struct block_list* src, struct block_list *bl, int skillid, int skilllv, int attack_type, unsigned int tick) +{ + int rate; + struct map_session_data *sd=NULL; + struct map_session_data *dstsd=NULL; + + nullpo_ret(src); + nullpo_ret(bl); + + if(skillid < 0) return 0; + if(skillid > 0 && skilllv <= 0) return 0; // don't forget auto attacks! - celest + + sd = BL_CAST(BL_PC, src); + dstsd = BL_CAST(BL_PC, bl); + + if(dstsd && attack_type&BF_WEAPON) + { //Counter effects. + enum sc_type type; + int i, time; + for(i=0; i < ARRAYLENGTH(dstsd->addeff2) && dstsd->addeff2[i].flag; i++) + { + rate = dstsd->addeff2[i].rate; + if (attack_type&BF_LONG) + rate+=dstsd->addeff2[i].arrow_rate; + if (!rate) continue; + + if ((dstsd->addeff2[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT)) + { //Trigger has range consideration. + if((dstsd->addeff2[i].flag&ATF_LONG && !(attack_type&BF_LONG)) || + (dstsd->addeff2[i].flag&ATF_SHORT && !(attack_type&BF_SHORT))) + continue; //Range Failed. + } + type = dstsd->addeff2[i].id; + time = skill_get_time2(status_sc2skill(type),7); - case TK_DOWNKICK: - sc_start(bl,SC_STUN,100,skilllv,skill_get_time2(skillid,skilllv)); - break; + if (dstsd->addeff2[i].flag&ATF_TARGET) + status_change_start(src,type,rate,7,0,0,0,time,0); - case TK_JUMPKICK: - if (dstsd && dstsd->class_ != MAPID_SOUL_LINKER && !tsc->data[SC_PRESERVE]) { - // debuff the following statuses - status_change_end(bl, SC_SPIRIT, INVALID_TIMER); - status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); - status_change_end(bl, SC_KAITE, INVALID_TIMER); - status_change_end(bl, SC_KAAHI, INVALID_TIMER); - status_change_end(bl, SC_ONEHAND, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); - } - break; - case TK_TURNKICK: - case MO_BALKYOUNG: //Note: attack_type is passed as BF_WEAPON for the actual target, BF_MISC for the splash-affected mobs. - if (attack_type&BF_MISC) //70% base stun chance... - sc_start(bl,SC_STUN,70,skilllv,skill_get_time2(skillid,skilllv)); - break; - case GS_BULLSEYE: //0.1% coma rate. - if (tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN) - status_change_start(bl,SC_COMA,10,skilllv,0,src->id,0,0,0); - break; - case GS_PIERCINGSHOT: - sc_start(bl,SC_BLEEDING,(skilllv*3),skilllv,skill_get_time2(skillid,skilllv)); - break; - case NJ_HYOUSYOURAKU: - sc_start(bl,SC_FREEZE,(10+10*skilllv),skilllv,skill_get_time2(skillid,skilllv)); - break; - case GS_FLING: - sc_start(bl,SC_FLING,100, sd?sd->spiritball_old:5,skill_get_time(skillid,skilllv)); - break; - case GS_DISARM: - rate = 3*skilllv; - if (sstatus->dex > tstatus->dex) - rate += (sstatus->dex - tstatus->dex)/5; //TODO: Made up formula - skill_strip_equip(bl, EQP_WEAPON, rate, skilllv, skill_get_time(skillid,skilllv)); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case NPC_EVILLAND: - sc_start(bl,SC_BLIND,5*skilllv,skilllv,skill_get_time2(skillid,skilllv)); - break; - case NPC_HELLJUDGEMENT: - sc_start(bl,SC_CURSE,100,skilllv,skill_get_time2(skillid,skilllv)); - break; - case NPC_CRITICALWOUND: - sc_start(bl,SC_CRITICALWOUND,100,skilllv,skill_get_time2(skillid,skilllv)); - break; - case RK_HUNDREDSPEAR: - if (!sd || pc_checkskill(sd,KN_SPEARBOOMERANG) == 0) - break; // Spear Boomerang auto cast chance only works if you have mastered Spear Boomerang. - rate = 10 + 3 * skilllv; - if (rnd()%100 < rate) - skill_castend_damage_id(src,bl,KN_SPEARBOOMERANG,1,tick,0); - break; - case RK_WINDCUTTER: - sc_start(bl,SC_FEAR,3+2*skilllv,skilllv,skill_get_time(skillid,skilllv)); - break; - case RK_DRAGONBREATH: - sc_start4(bl,SC_BURNING,5+5*skilllv,skilllv,1000,src->id,0,skill_get_time(skillid,skilllv)); - break; - case AB_ADORAMUS: - if (tsc && !tsc->data[SC_DECREASEAGI]) //Prevent duplicate agi-down effect. - sc_start(bl, SC_ADORAMUS, 100, skilllv, skill_get_time(skillid, skilllv)); - break; - case WL_CRIMSONROCK: - sc_start(bl, SC_STUN, 40, skilllv, skill_get_time(skillid, skilllv)); - break; - case WL_COMET: - sc_start4(bl,SC_BURNING,100,skilllv,1000,src->id,0,skill_get_time(skillid,skilllv)); - break; - case WL_EARTHSTRAIN: { - int rate = 0, i; - const int pos[5] = { EQP_WEAPON, EQP_HELM, EQP_SHIELD, EQP_ARMOR, EQP_ACC }; - rate = 6 * skilllv + sstatus->dex / 10 + (sd? sd->status.job_level / 4 : 0) - tstatus->dex /5;// The tstatus->dex / 5 part is unofficial, but players gotta have some kind of way to have resistance. [Rytech] - //rate -= rate * tstatus->dex / 200; // Disabled until official resistance is found. - - for (i = 0; i < skilllv; i++) - skill_strip_equip(bl,pos[i],rate,skilllv,skill_get_time2(skillid,skilllv)); - } - break; - case WL_JACKFROST: - sc_start(bl,SC_FREEZE,100,skilllv,skill_get_time(skillid,skilllv)); - break; - case RA_WUGBITE: - sc_start(bl, SC_BITE, (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*2 : 0), skilllv, (skill_get_time(skillid,skilllv) + (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*500 : 0))); - break; - case RA_SENSITIVEKEEN: - if (rnd()%100 < 8 * skilllv) - skill_castend_damage_id(src, bl, RA_WUGBITE, sd ? pc_checkskill(sd, RA_WUGBITE):skilllv, tick, SD_ANIMATION); - break; - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - sc_start(bl, (skillid == RA_FIRINGTRAP) ? SC_BURNING:SC_FREEZING, 40 + 10 * skilllv, skilllv, skill_get_time2(skillid, skilllv)); - break; - case NC_PILEBUNKER: - if (rnd()%100 < 5 + 15*skilllv) { - //Deactivatable Statuses: Kyrie Eleison, Auto Guard, Steel Body, Assumptio, and Millennium Shield - status_change_end(bl, SC_KYRIE, INVALID_TIMER); - status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER); - status_change_end(bl, SC_STEELBODY, INVALID_TIMER); - status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); - status_change_end(bl, SC_MILLENNIUMSHIELD, INVALID_TIMER); - } - break; - case NC_FLAMELAUNCHER: - sc_start4(bl, SC_BURNING, 50 + 10 * skilllv, skilllv, 1000, src->id, 0, skill_get_time2(skillid, skilllv)); - break; - case NC_COLDSLOWER: - sc_start(bl, SC_FREEZE, 10 * skilllv, skilllv, skill_get_time(skillid, skilllv)); - sc_start(bl, SC_FREEZING, 20 + 10 * skilllv, skilllv, skill_get_time(skillid, skilllv)); - break; - case NC_POWERSWING: - sc_start(bl, SC_STUN, 5*skilllv, skilllv, skill_get_time(skillid, skilllv)); - if (rnd()%100 < 5*skilllv) - skill_castend_damage_id(src, bl, NC_AXEBOOMERANG, pc_checkskill(sd, NC_AXEBOOMERANG), tick, 1); - break; - case GC_WEAPONCRUSH: - skill_castend_nodamage_id(src,bl,skillid,skilllv,tick,BCT_ENEMY); - break; - case LG_SHIELDPRESS: - sc_start(bl, SC_STUN, 30 + 8 * skilllv, skilllv, skill_get_time(skillid,skilllv)); - break; - case LG_PINPOINTATTACK: - rate = 30 + (((5 * (sd?pc_checkskill(sd,LG_PINPOINTATTACK):skilllv)) + (sstatus->agi + status_get_lv(src))) / 10); - switch (skilllv) { - case 1: - sc_start(bl,SC_BLEEDING,rate,skilllv,skill_get_time(skillid,skilllv)); - break; - case 2: - if (dstsd && dstsd->spiritball && rnd()%100 < rate) - pc_delspiritball(dstsd, dstsd->spiritball, 0); - break; - default: - skill_break_equip(bl,(skilllv == 3) ? EQP_SHIELD : (skilllv == 4) ? EQP_ARMOR : EQP_WEAPON,rate * 100,BCT_ENEMY); - break; - } - break; - case LG_MOONSLASHER: - rate = 32 + 8 * skilllv; - if (rnd()%100 < rate && dstsd) // Uses skill_addtimerskill to avoid damage and setsit packet overlaping. Officially clif_setsit is received about 500 ms after damage packet. - skill_addtimerskill(src,tick+500,bl->id,0,0,skillid,skilllv,BF_WEAPON,0); - else if (dstmd && !is_boss(bl)) - sc_start(bl,SC_STOP,100,skilllv,skill_get_time(skillid,skilllv)); - break; - case LG_RAYOFGENESIS: // 50% chance to cause Blind on Undead and Demon monsters. - if (battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON) - sc_start(bl, SC_BLIND,50, skilllv, skill_get_time(skillid,skilllv)); - break; - case LG_EARTHDRIVE: - skill_break_equip(src, EQP_SHIELD, 500, BCT_SELF); - sc_start(bl, SC_EARTHDRIVE, 100, skilllv, skill_get_time(skillid, skilllv)); - break; - case SR_DRAGONCOMBO: - sc_start(bl, SC_STUN, 1 + skilllv, skilllv, skill_get_time(skillid, skilllv)); - break; - case SR_FALLENEMPIRE: - sc_start(bl, SC_STOP, 100, skilllv, skill_get_time(skillid, skilllv)); - break; - case SR_WINDMILL: - if (dstsd) - skill_addtimerskill(src,tick+status_get_amotion(src),bl->id,0,0,skillid,skilllv,BF_WEAPON,0); - else if (dstmd && !is_boss(bl)) - sc_start(bl, SC_STUN, 100, skilllv, 1000 + 1000 * (rnd() %3)); - break; - case SR_GENTLETOUCH_QUIET: // [(Skill Level x 5) + (Caster?s DEX + Caster?s Base Level) / 10] - sc_start(bl, SC_SILENCE, 5 * skilllv + (sstatus->dex + status_get_lv(src)) / 10, skilllv, skill_get_time(skillid, skilllv)); - break; - case SR_EARTHSHAKER: - sc_start(bl,SC_STUN, 25 + 5 * skilllv,skilllv,skill_get_time(skillid,skilllv)); - break; - case SR_HOWLINGOFLION: - sc_start(bl, SC_FEAR, 5 + 5 * skilllv, skilllv, skill_get_time(skillid, skilllv)); - break; - case WM_SOUND_OF_DESTRUCTION: - if (rnd()%100 < 5 + 5 * skilllv) { // Temporarly Check Until We Get the Official Formula - status_change_end(bl, SC_DANCING, INVALID_TIMER); - status_change_end(bl, SC_RICHMANKIM, INVALID_TIMER); - status_change_end(bl, SC_ETERNALCHAOS, INVALID_TIMER); - status_change_end(bl, SC_DRUMBATTLE, INVALID_TIMER); - status_change_end(bl, SC_NIBELUNGEN, INVALID_TIMER); - status_change_end(bl, SC_INTOABYSS, INVALID_TIMER); - status_change_end(bl, SC_SIEGFRIED, INVALID_TIMER); - status_change_end(bl, SC_WHISTLE, INVALID_TIMER); - status_change_end(bl, SC_ASSNCROS, INVALID_TIMER); - status_change_end(bl, SC_POEMBRAGI, INVALID_TIMER); - status_change_end(bl, SC_APPLEIDUN, INVALID_TIMER); - status_change_end(bl, SC_HUMMING, INVALID_TIMER); - status_change_end(bl, SC_FORTUNE, INVALID_TIMER); - status_change_end(bl, SC_SERVICE4U, INVALID_TIMER); - status_change_end(bl, SC_LONGING, INVALID_TIMER); - status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); - status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); - status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); - status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); - status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); - status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - status_change_end(bl, SC_WINKCHARM, INVALID_TIMER); - status_change_end(bl, SC_SONGOFMANA, INVALID_TIMER); - status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); - status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); - status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); - status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); - status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); - } - break; - case SO_EARTHGRAVE: - sc_start(bl, SC_BLEEDING, 5 * skilllv, skilllv, skill_get_time2(skillid, skilllv)); // Need official rate. [LimitLine] - break; - case SO_DIAMONDDUST: - rate = 5 + 5 * skilllv; - if (sc && sc->data[SC_COOLER_OPTION]) - rate += rate * sc->data[SC_COOLER_OPTION]->val2 / 100; - sc_start(bl, SC_CRYSTALIZE, rate, skilllv, skill_get_time2(skillid, skilllv)); - break; - case SO_VARETYR_SPEAR: - sc_start(bl, SC_STUN, 5 + 5 * skilllv, skilllv, skill_get_time2(skillid, skilllv)); - break; - case GN_SLINGITEM_RANGEMELEEATK: - if (sd) { - switch (sd->itemid) { // Starting SCs here instead of do it in skill_additional_effect to simplify the code. - case 13261: - sc_start(bl, SC_STUN, 100, skilllv, skill_get_time2(GN_SLINGITEM, skilllv)); - sc_start(bl, SC_BLEEDING, 100, skilllv, skill_get_time2(GN_SLINGITEM, skilllv)); - break; - case 13262: - sc_start(bl, SC_MELON_BOMB, 100, skilllv, skill_get_time(GN_SLINGITEM, skilllv)); // Reduces ASPD and moviment speed - break; - case 13264: - sc_start(bl, SC_BANANA_BOMB, 100, skilllv, skill_get_time(GN_SLINGITEM, skilllv)); // Reduces LUK ??Needed confirm it, may be it's bugged in kRORE? - sc_start(bl, SC_BANANA_BOMB_SITDOWN, 75, skilllv, skill_get_time(GN_SLINGITEM_RANGEMELEEATK,skilllv)); // Sitdown for 3 seconds. - break; - } - sd->itemid = -1; - } - break; - case GN_HELLS_PLANT_ATK: - sc_start(bl, SC_STUN, 5 + 5 * skilllv, skilllv, skill_get_time2(skillid, skilllv)); - sc_start(bl, SC_BLEEDING, 20 + 10 * skilllv, skilllv, skill_get_time2(skillid, skilllv)); - break; - case EL_WIND_SLASH: // Non confirmed rate. - sc_start(bl, SC_BLEEDING, 25, skilllv, skill_get_time(skillid,skilllv)); - break; - case EL_STONE_HAMMER: - rate = 10 * skilllv; - sc_start(bl, SC_STUN, rate, skilllv, skill_get_time(skillid,skilllv)); - break; - case EL_ROCK_CRUSHER: - case EL_ROCK_CRUSHER_ATK: - sc_start(bl,status_skill2sc(skillid),50,skilllv,skill_get_time(EL_ROCK_CRUSHER,skilllv)); - break; - case EL_TYPOON_MIS: - sc_start(bl,SC_SILENCE,10*skilllv,skilllv,skill_get_time(skillid,skilllv)); - break; - case KO_JYUMONJIKIRI: // needs more info - sc_start(bl,SC_JYUMONJIKIRI,25,skilllv,skill_get_time(skillid,skilllv)); - break; - case KO_MAKIBISHI: - sc_start(bl, SC_STUN, 100, skilllv, skill_get_time2(skillid,skilllv)); - break; - case MH_LAVA_SLIDE: - if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skilllv, skilllv, 1000, src->id, 0, skill_get_time(skillid, skilllv)); - break; - case MH_STAHL_HORN: - sc_start(bl, SC_STUN, (20 + 4 * (skilllv-1)), skilllv, skill_get_time(skillid, skilllv)); - break; - case MH_NEEDLE_OF_PARALYZE: - sc_start(bl, SC_PARALYSIS, 40 + (5*skilllv), skilllv, skill_get_time(skillid, skilllv)); - break; - } - - if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) { - //Pass heritage to Master for status causing effects. [Skotlex] - sd = map_id2sd(md->master_id); - src = sd?&sd->bl:src; - } - - if (attack_type&BF_WEAPON) { - // Coma, Breaking Equipment - if (sd && sd->special_state.bonus_coma) { - rate = sd->weapon_coma_ele[tstatus->def_ele]; - rate += sd->weapon_coma_race[tstatus->race]; - rate += sd->weapon_coma_race[tstatus->mode&MD_BOSS?RC_BOSS:RC_NONBOSS]; - if (rate) - status_change_start(bl, SC_COMA, rate, 0, 0, src->id, 0, 0, 0); - } - if (sd && battle_config.equip_self_break_rate) { - // Self weapon breaking - rate = battle_config.equip_natural_break_rate; - if (sc) { - if (sc->data[SC_OVERTHRUST]) - rate += 10; - if (sc->data[SC_MAXOVERTHRUST]) - rate += 10; - } - if (rate) - skill_break_equip(src, EQP_WEAPON, rate, BCT_SELF); - } - if (battle_config.equip_skill_break_rate && skillid != WS_CARTTERMINATION && skillid != ITM_TOMAHAWK) { - // Cart Termination/Tomahawk won't trigger breaking data. Why? No idea, go ask Gravity. - // Target weapon breaking - rate = 0; - if (sd) - rate += sd->bonus.break_weapon_rate; - if (sc && sc->data[SC_MELTDOWN]) - rate += sc->data[SC_MELTDOWN]->val2; - if (rate) - skill_break_equip(bl, EQP_WEAPON, rate, BCT_ENEMY); - - // Target armor breaking - rate = 0; - if (sd) - rate += sd->bonus.break_armor_rate; - if (sc && sc->data[SC_MELTDOWN]) - rate += sc->data[SC_MELTDOWN]->val3; - if (rate) - skill_break_equip(bl, EQP_ARMOR, rate, BCT_ENEMY); - } - } - - // Autospell when attacking - if (sd && !status_isdead(bl) && sd->autospell[0].id) { - struct block_list *tbl; - struct unit_data *ud; - int i, skilllv, type, notok; - - for (i = 0; i < ARRAYLENGTH(sd->autospell) && sd->autospell[i].id; i++) { - - if (!(sd->autospell[i].flag&attack_type&BF_WEAPONMASK && - sd->autospell[i].flag&attack_type&BF_RANGEMASK && - sd->autospell[i].flag&attack_type&BF_SKILLMASK)) - continue; // one or more trigger conditions were not fulfilled - - skill = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id; - - sd->state.autocast = 1; - notok = skillnotok(skill, sd); - sd->state.autocast = 0; - - if (notok) - continue; - - skilllv = sd->autospell[i].lv?sd->autospell[i].lv:1; - if (skilllv < 0) skilllv = 1+rnd()%(-skilllv); - - rate = (!sd->state.arrow_atk) ? sd->autospell[i].rate : sd->autospell[i].rate / 2; - - if (rnd()%1000 >= rate) - continue; - - tbl = (sd->autospell[i].id < 0) ? src : bl; - - if ((type = skill_get_casttype(skill)) == CAST_GROUND) { - int maxcount = 0; - if (!(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(skill)&UF_NOREITERATION && - skill_check_unit_range(src,tbl->x,tbl->y,skill,skilllv) - ) { - continue; - } - if (BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(skill)&UF_NOFOOTSET && - skill_check_unit_range2(src,tbl->x,tbl->y,skill,skilllv) - ) { - continue; - } - if (BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(skill, skilllv)) > 0 - ) { - int v; - for (v=0; v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount; v++) { - if (sd->ud.skillunit[v]->skill_id == skill) - maxcount--; - } - if (maxcount == 0) { - continue; - } - } - } - if (battle_config.autospell_check_range && - !battle_check_range(src, tbl, skill_get_range2(src, skill,skilllv) + (skill == RG_CLOSECONFINE?0:1))) - continue; - - if (skill == AS_SONICBLOW) - pc_stop_attack(sd); //Special case, Sonic Blow autospell should stop the player attacking. - if (skill == PF_SPIDERWEB) //Special case, due to its nature of coding. - type = CAST_GROUND; - - sd->state.autocast = 1; - skill_consume_requirement(sd,skill,skilllv,1); - skill_toggle_magicpower(src, skill); - switch (type) { - case CAST_GROUND: - skill_castend_pos2(src, tbl->x, tbl->y, skill, skilllv, tick, 0); - break; - case CAST_NODAMAGE: - skill_castend_nodamage_id(src, tbl, skill, skilllv, tick, 0); - break; - case CAST_DAMAGE: - skill_castend_damage_id(src, tbl, skill, skilllv, tick, 0); - break; - } - sd->state.autocast = 0; - //Set canact delay. [Skotlex] - ud = unit_bl2ud(src); - if (ud) { - rate = skill_delayfix(src, skill, skilllv); - if (DIFF_TICK(ud->canact_tick, tick + rate) < 0) { - ud->canact_tick = tick+rate; - if (battle_config.display_status_timers && sd) - clif_status_change(src, SI_ACTIONDELAY, 1, rate, 0, 0, 0); - } - } - } - } - - //Autobonus when attacking - if (sd && sd->autobonus[0].rate) { - int i; - for (i = 0; i < ARRAYLENGTH(sd->autobonus); i++) { - if (rnd()%1000 >= sd->autobonus[i].rate) - continue; - if (sd->autobonus[i].active != INVALID_TIMER) - continue; - if (!(sd->autobonus[i].atk_type&attack_type&BF_WEAPONMASK && - sd->autobonus[i].atk_type&attack_type&BF_RANGEMASK && - sd->autobonus[i].atk_type&attack_type&BF_SKILLMASK)) - continue; // one or more trigger conditions were not fulfilled - pc_exeautobonus(sd,&sd->autobonus[i]); - } - } - - //Polymorph - if (sd && sd->bonus.classchange && attack_type&BF_WEAPON && - dstmd && !(tstatus->mode&MD_BOSS) && - (rnd()%10000 < sd->bonus.classchange)) { - struct mob_db *mob; - int class_; - skill = 0; - do { - do { - class_ = rnd() % MAX_MOB_DB; - } while (!mobdb_checkid(class_)); - - rate = rnd() % 1000000; - mob = mob_db(class_); - } while ( - (mob->status.mode&(MD_BOSS|MD_PLANT) || mob->summonper[0] <= rate) && - (skill++) < 2000); - if (skill < 2000) - mob_class_change(dstmd,class_); - } - - return 0; -} + if (dstsd->addeff2[i].flag&ATF_SELF && !status_isdead(bl)) + status_change_start(bl,type,rate,7,0,0,0,time,0); + } + } -int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, int skillid, unsigned int tick) -{ - int skill, skilllv, i, type, notok; - struct block_list *tbl; + switch(skillid){ + case MO_EXTREMITYFIST: + sc_start(src,SC_EXTREMITYFIST,100,skilllv,skill_get_time2(skillid,skilllv)); + break; + case GS_FULLBUSTER: + sc_start(src,SC_BLIND,2*skilllv,skilllv,skill_get_time2(skillid,skilllv)); + break; + case HFLI_SBR44: //[orn] + case HVAN_EXPLOSION: + if(src->type == BL_HOM){ + TBL_HOM *hd = (TBL_HOM*)src; + hd->homunculus.intimacy = 200; + if (hd->master) + clif_send_homdata(hd->master,SP_INTIMATE,hd->homunculus.intimacy/100); + } + break; + case CR_GRANDCROSS: + case NPC_GRANDDARKNESS: + attack_type |= BF_WEAPON; + break; + } - if (sd == NULL || skillid <= 0) - return 0; + if(sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && + rnd()%10000 < battle_config.sg_miracle_skill_ratio) //SG_MIRACLE [Komurka] + sc_start(src,SC_MIRACLE,100,1,battle_config.sg_miracle_skill_duration); + + if(sd && skillid && attack_type&BF_MAGIC && status_isdead(bl) && + !(skill_get_inf(skillid)&(INF_GROUND_SKILL|INF_SELF_SKILL)) && + (rate=pc_checkskill(sd,HW_SOULDRAIN))>0 + ){ //Soul Drain should only work on targetted spells [Skotlex] + if (pc_issit(sd)) pc_setstand(sd); //Character stuck in attacking animation while 'sitting' fix. [Skotlex] + clif_skill_nodamage(src,bl,HW_SOULDRAIN,rate,1); + status_heal(src, 0, status_get_lv(bl)*(95+15*rate)/100, 2); + } - for (i = 0; i < ARRAYLENGTH(sd->autospell3) && sd->autospell3[i].flag; i++) { - if (sd->autospell3[i].flag != skillid) - continue; + if( sd && status_isdead(bl) ) { + int sp = 0, hp = 0; + if( attack_type&BF_WEAPON ) { + sp += sd->bonus.sp_gain_value; + sp += sd->sp_gain_race[status_get_race(bl)]; + sp += sd->sp_gain_race[is_boss(bl)?RC_BOSS:RC_NONBOSS]; + hp += sd->bonus.hp_gain_value; + } + if( attack_type&BF_MAGIC ) { + sp += sd->bonus.magic_sp_gain_value; + hp += sd->bonus.magic_hp_gain_value; + if( skillid == WZ_WATERBALL ) {//(bugreport:5303) + struct status_change *sc = NULL; + if( ( sc = status_get_sc(src) ) ) { + if(sc->data[SC_SPIRIT] && + sc->data[SC_SPIRIT]->val2 == SL_WIZARD && + sc->data[SC_SPIRIT]->val3 == WZ_WATERBALL) + sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. + } + } + } + if( hp || sp ) { // updated to force healing to allow healing through berserk + status_heal(src, hp, sp, battle_config.show_hp_sp_gain ? 3 : 1); + } + } - if (sd->autospell3[i].lock) - continue; // autospell already being executed + // Trigger counter-spells to retaliate against damage causing skills. + if(dstsd && !status_isdead(bl) && dstsd->autospell2[0].id && + !(skillid && skill_get_nk(skillid)&NK_NO_DAMAGE)) + { + struct block_list *tbl; + struct unit_data *ud; + int i, skillid, skilllv, rate, type, notok; - skill = (sd->autospell3[i].id > 0) ? sd->autospell3[i].id : -sd->autospell3[i].id; + for (i = 0; i < ARRAYLENGTH(dstsd->autospell2) && dstsd->autospell2[i].id; i++) { - sd->state.autocast = 1; - notok = skillnotok(skill, sd); - sd->state.autocast = 0; + if(!(dstsd->autospell2[i].flag&attack_type&BF_WEAPONMASK && + dstsd->autospell2[i].flag&attack_type&BF_RANGEMASK && + dstsd->autospell2[i].flag&attack_type&BF_SKILLMASK)) + continue; // one or more trigger conditions were not fulfilled - if (notok) - continue; + skillid = (dstsd->autospell2[i].id > 0) ? dstsd->autospell2[i].id : -dstsd->autospell2[i].id; + skilllv = dstsd->autospell2[i].lv?dstsd->autospell2[i].lv:1; + if (skilllv < 0) skilllv = 1+rnd()%(-skilllv); - skilllv = sd->autospell3[i].lv ? sd->autospell3[i].lv : 1; - if (skilllv < 0) skilllv = 1 + rnd()%(-skilllv); + rate = dstsd->autospell2[i].rate; + if (attack_type&BF_LONG) + rate>>=1; - if (sd->autospell3[i].id >= 0 && bl == NULL) - continue; // No target - if (rnd()%1000 >= sd->autospell3[i].rate) - continue; + dstsd->state.autocast = 1; + notok = skillnotok(skillid, dstsd); + dstsd->state.autocast = 0; - tbl = (sd->autospell3[i].id < 0) ? &sd->bl : bl; + if ( notok ) + continue; - if ((type = skill_get_casttype(skill)) == CAST_GROUND) { - int maxcount = 0; - if (!(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(skill)&UF_NOREITERATION && - skill_check_unit_range(&sd->bl,tbl->x,tbl->y,skill,skilllv) - ) { - continue; - } - if (BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(skill)&UF_NOFOOTSET && - skill_check_unit_range2(&sd->bl,tbl->x,tbl->y,skill,skilllv) - ) { - continue; - } - if (BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(skill, skilllv)) > 0 - ) { - int v; - for (v=0; v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount; v++) { - if (sd->ud.skillunit[v]->skill_id == skill) - maxcount--; - } - if (maxcount == 0) { - continue; - } - } - } - if (battle_config.autospell_check_range && - !battle_check_range(&sd->bl, tbl, skill_get_range2(&sd->bl, skill,skilllv) + (skill == RG_CLOSECONFINE?0:1))) - continue; - - sd->state.autocast = 1; - sd->autospell3[i].lock = true; - skill_consume_requirement(sd,skill,skilllv,1); - switch (type) { - case CAST_GROUND: - skill_castend_pos2(&sd->bl, tbl->x, tbl->y, skill, skilllv, tick, 0); - break; - case CAST_NODAMAGE: - skill_castend_nodamage_id(&sd->bl, tbl, skill, skilllv, tick, 0); - break; - case CAST_DAMAGE: - skill_castend_damage_id(&sd->bl, tbl, skill, skilllv, tick, 0); - break; - } - sd->autospell3[i].lock = false; - sd->state.autocast = 0; - } - - if (sd && sd->autobonus3[0].rate) { - for (i = 0; i < ARRAYLENGTH(sd->autobonus3); i++) { - if (rnd()%1000 >= sd->autobonus3[i].rate) - continue; - if (sd->autobonus3[i].active != INVALID_TIMER) - continue; - if (sd->autobonus3[i].atk_type != skillid) - continue; - pc_exeautobonus(sd,&sd->autobonus3[i]); - } - } - - return 1; -} + if (rnd()%1000 >= rate) + continue; -/* Splitted off from skill_additional_effect, which is never called when the - * attack skill kills the enemy. Place in this function counter status effects - * when using skills (eg: Asura's sp regen penalty, or counter-status effects - * from cards) that will take effect on the source, not the target. [Skotlex] - * Note: Currently this function only applies to Extremity Fist and BF_WEAPON - * type of skills, so not every instance of skill_additional_effect needs a call - * to this one. - */ -int skill_counter_additional_effect(struct block_list *src, struct block_list *bl, int skillid, int skilllv, int attack_type, unsigned int tick) -{ - int rate; - struct map_session_data *sd=NULL; - struct map_session_data *dstsd=NULL; - - nullpo_ret(src); - nullpo_ret(bl); - - if (skillid < 0) return 0; - if (skillid > 0 && skilllv <= 0) return 0; // don't forget auto attacks! - celest - - sd = BL_CAST(BL_PC, src); - dstsd = BL_CAST(BL_PC, bl); - - if (dstsd && attack_type&BF_WEAPON) { - //Counter effects. - enum sc_type type; - int i, time; - for (i=0; i < ARRAYLENGTH(dstsd->addeff2) && dstsd->addeff2[i].flag; i++) { - rate = dstsd->addeff2[i].rate; - if (attack_type&BF_LONG) - rate+=dstsd->addeff2[i].arrow_rate; - if (!rate) continue; - - if ((dstsd->addeff2[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT)) { - //Trigger has range consideration. - if ((dstsd->addeff2[i].flag&ATF_LONG && !(attack_type&BF_LONG)) || - (dstsd->addeff2[i].flag&ATF_SHORT && !(attack_type&BF_SHORT))) - continue; //Range Failed. - } - type = dstsd->addeff2[i].id; - time = skill_get_time2(status_sc2skill(type),7); + tbl = (dstsd->autospell2[i].id < 0) ? bl : src; - if (dstsd->addeff2[i].flag&ATF_TARGET) - status_change_start(src,type,rate,7,0,0,0,time,0); + if( (type = skill_get_casttype(skillid)) == CAST_GROUND ) { + int maxcount = 0; + if( !(BL_PC&battle_config.skill_reiteration) && + skill_get_unit_flag(skillid)&UF_NOREITERATION && + skill_check_unit_range(bl,tbl->x,tbl->y,skillid,skilllv) + ) { + continue; + } + if( BL_PC&battle_config.skill_nofootset && + skill_get_unit_flag(skillid)&UF_NOFOOTSET && + skill_check_unit_range2(bl,tbl->x,tbl->y,skillid,skilllv) + ) { + continue; + } + if( BL_PC&battle_config.land_skill_limit && + (maxcount = skill_get_maxcount(skillid, skilllv)) > 0 + ) { + int v; + for(v=0;v<MAX_SKILLUNITGROUP && dstsd->ud.skillunit[v] && maxcount;v++) { + if(dstsd->ud.skillunit[v]->skill_id == skillid) + maxcount--; + } + if( maxcount == 0 ) { + continue; + } + } + } - if (dstsd->addeff2[i].flag&ATF_SELF && !status_isdead(bl)) - status_change_start(bl,type,rate,7,0,0,0,time,0); - } - } + if( !battle_check_range(src, tbl, skill_get_range2(src, skillid,skilllv) + (skillid == RG_CLOSECONFINE?0:1)) && battle_config.autospell_check_range ) + continue; + + dstsd->state.autocast = 1; + skill_consume_requirement(dstsd,skillid,skilllv,1); + switch (type) { + case CAST_GROUND: + skill_castend_pos2(bl, tbl->x, tbl->y, skillid, skilllv, tick, 0); + break; + case CAST_NODAMAGE: + skill_castend_nodamage_id(bl, tbl, skillid, skilllv, tick, 0); + break; + case CAST_DAMAGE: + skill_castend_damage_id(bl, tbl, skillid, skilllv, tick, 0); + break; + } + dstsd->state.autocast = 0; + //Set canact delay. [Skotlex] + ud = unit_bl2ud(bl); + if (ud) { + rate = skill_delayfix(bl, skillid, skilllv); + if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ + ud->canact_tick = tick+rate; + if ( battle_config.display_status_timers && dstsd ) + clif_status_change(bl, SI_ACTIONDELAY, 1, rate, 0, 0, 0); + } + } + } + } - switch (skillid) { - case MO_EXTREMITYFIST: - sc_start(src,SC_EXTREMITYFIST,100,skilllv,skill_get_time2(skillid,skilllv)); - break; - case GS_FULLBUSTER: - sc_start(src,SC_BLIND,2*skilllv,skilllv,skill_get_time2(skillid,skilllv)); - break; - case HFLI_SBR44: //[orn] - case HVAN_EXPLOSION: - if (src->type == BL_HOM) { - TBL_HOM *hd = (TBL_HOM *)src; - hd->homunculus.intimacy = 200; - if (hd->master) - clif_send_homdata(hd->master,SP_INTIMATE,hd->homunculus.intimacy/100); - } - break; - case CR_GRANDCROSS: - case NPC_GRANDDARKNESS: - attack_type |= BF_WEAPON; - break; - } - - if (sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && - rnd()%10000 < battle_config.sg_miracle_skill_ratio) //SG_MIRACLE [Komurka] - sc_start(src,SC_MIRACLE,100,1,battle_config.sg_miracle_skill_duration); - - if (sd && skillid && attack_type&BF_MAGIC && status_isdead(bl) && - !(skill_get_inf(skillid)&(INF_GROUND_SKILL|INF_SELF_SKILL)) && - (rate=pc_checkskill(sd,HW_SOULDRAIN))>0 - ) { //Soul Drain should only work on targetted spells [Skotlex] - if (pc_issit(sd)) pc_setstand(sd); //Character stuck in attacking animation while 'sitting' fix. [Skotlex] - clif_skill_nodamage(src,bl,HW_SOULDRAIN,rate,1); - status_heal(src, 0, status_get_lv(bl)*(95+15*rate)/100, 2); - } - - if (sd && status_isdead(bl)) { - int sp = 0, hp = 0; - if (attack_type&BF_WEAPON) { - sp += sd->bonus.sp_gain_value; - sp += sd->sp_gain_race[status_get_race(bl)]; - sp += sd->sp_gain_race[is_boss(bl)?RC_BOSS:RC_NONBOSS]; - hp += sd->bonus.hp_gain_value; - } - if (attack_type&BF_MAGIC) { - sp += sd->bonus.magic_sp_gain_value; - hp += sd->bonus.magic_hp_gain_value; - if (skillid == WZ_WATERBALL) { //(bugreport:5303) - struct status_change *sc = NULL; - if ((sc = status_get_sc(src))) { - if (sc->data[SC_SPIRIT] && - sc->data[SC_SPIRIT]->val2 == SL_WIZARD && - sc->data[SC_SPIRIT]->val3 == WZ_WATERBALL) - sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. - } - } - } - if (hp || sp) { // updated to force healing to allow healing through berserk - status_heal(src, hp, sp, battle_config.show_hp_sp_gain ? 3 : 1); - } - } - - // Trigger counter-spells to retaliate against damage causing skills. - if (dstsd && !status_isdead(bl) && dstsd->autospell2[0].id && - !(skillid && skill_get_nk(skillid)&NK_NO_DAMAGE)) { - struct block_list *tbl; - struct unit_data *ud; - int i, skillid, skilllv, rate, type, notok; - - for (i = 0; i < ARRAYLENGTH(dstsd->autospell2) && dstsd->autospell2[i].id; i++) { - - if (!(dstsd->autospell2[i].flag&attack_type&BF_WEAPONMASK && - dstsd->autospell2[i].flag&attack_type&BF_RANGEMASK && - dstsd->autospell2[i].flag&attack_type&BF_SKILLMASK)) - continue; // one or more trigger conditions were not fulfilled - - skillid = (dstsd->autospell2[i].id > 0) ? dstsd->autospell2[i].id : -dstsd->autospell2[i].id; - skilllv = dstsd->autospell2[i].lv?dstsd->autospell2[i].lv:1; - if (skilllv < 0) skilllv = 1+rnd()%(-skilllv); - - rate = dstsd->autospell2[i].rate; - if (attack_type&BF_LONG) - rate>>=1; - - dstsd->state.autocast = 1; - notok = skillnotok(skillid, dstsd); - dstsd->state.autocast = 0; - - if (notok) - continue; - - if (rnd()%1000 >= rate) - continue; - - tbl = (dstsd->autospell2[i].id < 0) ? bl : src; - - if ((type = skill_get_casttype(skillid)) == CAST_GROUND) { - int maxcount = 0; - if (!(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(skillid)&UF_NOREITERATION && - skill_check_unit_range(bl,tbl->x,tbl->y,skillid,skilllv) - ) { - continue; - } - if (BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(skillid)&UF_NOFOOTSET && - skill_check_unit_range2(bl,tbl->x,tbl->y,skillid,skilllv) - ) { - continue; - } - if (BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(skillid, skilllv)) > 0 - ) { - int v; - for (v=0; v<MAX_SKILLUNITGROUP && dstsd->ud.skillunit[v] && maxcount; v++) { - if (dstsd->ud.skillunit[v]->skill_id == skillid) - maxcount--; - } - if (maxcount == 0) { - continue; - } - } - } + //Autobonus when attacked + if( dstsd && !status_isdead(bl) && dstsd->autobonus2[0].rate && !(skillid && skill_get_nk(skillid)&NK_NO_DAMAGE) ) + { + int i; + for( i = 0; i < ARRAYLENGTH(dstsd->autobonus2); i++ ) + { + if( rnd()%1000 >= dstsd->autobonus2[i].rate ) + continue; + if( dstsd->autobonus2[i].active != INVALID_TIMER ) + continue; + if(!(dstsd->autobonus2[i].atk_type&attack_type&BF_WEAPONMASK && + dstsd->autobonus2[i].atk_type&attack_type&BF_RANGEMASK && + dstsd->autobonus2[i].atk_type&attack_type&BF_SKILLMASK)) + continue; // one or more trigger conditions were not fulfilled + pc_exeautobonus(dstsd,&dstsd->autobonus2[i]); + } + } - if (!battle_check_range(src, tbl, skill_get_range2(src, skillid,skilllv) + (skillid == RG_CLOSECONFINE?0:1)) && battle_config.autospell_check_range) - continue; - - dstsd->state.autocast = 1; - skill_consume_requirement(dstsd,skillid,skilllv,1); - switch (type) { - case CAST_GROUND: - skill_castend_pos2(bl, tbl->x, tbl->y, skillid, skilllv, tick, 0); - break; - case CAST_NODAMAGE: - skill_castend_nodamage_id(bl, tbl, skillid, skilllv, tick, 0); - break; - case CAST_DAMAGE: - skill_castend_damage_id(bl, tbl, skillid, skilllv, tick, 0); - break; - } - dstsd->state.autocast = 0; - //Set canact delay. [Skotlex] - ud = unit_bl2ud(bl); - if (ud) { - rate = skill_delayfix(bl, skillid, skilllv); - if (DIFF_TICK(ud->canact_tick, tick + rate) < 0) { - ud->canact_tick = tick+rate; - if (battle_config.display_status_timers && dstsd) - clif_status_change(bl, SI_ACTIONDELAY, 1, rate, 0, 0, 0); - } - } - } - } - - //Autobonus when attacked - if (dstsd && !status_isdead(bl) && dstsd->autobonus2[0].rate && !(skillid && skill_get_nk(skillid)&NK_NO_DAMAGE)) { - int i; - for (i = 0; i < ARRAYLENGTH(dstsd->autobonus2); i++) { - if (rnd()%1000 >= dstsd->autobonus2[i].rate) - continue; - if (dstsd->autobonus2[i].active != INVALID_TIMER) - continue; - if (!(dstsd->autobonus2[i].atk_type&attack_type&BF_WEAPONMASK && - dstsd->autobonus2[i].atk_type&attack_type&BF_RANGEMASK && - dstsd->autobonus2[i].atk_type&attack_type&BF_SKILLMASK)) - continue; // one or more trigger conditions were not fulfilled - pc_exeautobonus(dstsd,&dstsd->autobonus2[i]); - } - } - - return 0; + return 0; } /*========================================================================= Breaks equipment. On-non players causes the corresponding strip effect. @@ -2053,123 +1900,123 @@ int skill_counter_additional_effect(struct block_list *src, struct block_list *b - flag is a BCT_ flag to indicate which type of adjustment should be used (BCT_ENEMY/BCT_PARTY/BCT_SELF) are the valid values. --------------------------------------------------------------------------*/ -int skill_break_equip(struct block_list *bl, unsigned short where, int rate, int flag) +int skill_break_equip (struct block_list *bl, unsigned short where, int rate, int flag) { - const int where_list[4] = {EQP_WEAPON, EQP_ARMOR, EQP_SHIELD, EQP_HELM}; - const enum sc_type scatk[4] = {SC_STRIPWEAPON, SC_STRIPARMOR, SC_STRIPSHIELD, SC_STRIPHELM}; - const enum sc_type scdef[4] = {SC_CP_WEAPON, SC_CP_ARMOR, SC_CP_SHIELD, SC_CP_HELM}; - struct status_change *sc = status_get_sc(bl); - int i,j; - TBL_PC *sd; - sd = BL_CAST(BL_PC, bl); - if (sc && !sc->count) - sc = NULL; - - if (sd) { - if (sd->bonus.unbreakable_equip) - where &= ~sd->bonus.unbreakable_equip; - if (sd->bonus.unbreakable) - rate -= rate*sd->bonus.unbreakable/100; - if (where&EQP_WEAPON) { - switch (sd->status.weapon) { - case W_FIST: //Bare fists should not break :P - case W_1HAXE: - case W_2HAXE: - case W_MACE: // Axes and Maces can't be broken [DracoRPG] - case W_2HMACE: - case W_STAFF: - case W_2HSTAFF: - case W_BOOK: //Rods and Books can't be broken [Skotlex] - case W_HUUMA: - where &= ~EQP_WEAPON; - } - } - } - if (flag&BCT_ENEMY) { - if (battle_config.equip_skill_break_rate != 100) - rate = rate*battle_config.equip_skill_break_rate/100; - } else if (flag&(BCT_PARTY|BCT_SELF)) { - if (battle_config.equip_self_break_rate != 100) - rate = rate*battle_config.equip_self_break_rate/100; - } - - for (i = 0; i < 4; i++) { - if (where&where_list[i]) { - if (sc && sc->count && sc->data[scdef[i]]) - where&=~where_list[i]; - else if (rnd()%10000 >= rate) - where&=~where_list[i]; - else if (!sd && !(status_get_mode(bl)&MD_BOSS)) //Cause Strip effect. - sc_start(bl,scatk[i],100,0,skill_get_time(status_sc2skill(scatk[i]),1)); - } - } - if (!where) //Nothing to break. - return 0; - if (sd) { - for (i = 0; i < EQI_MAX; i++) { - j = sd->equip_index[i]; - if (j < 0 || sd->status.inventory[j].attribute == 1 || !sd->inventory_data[j]) - continue; - - switch (i) { - case EQI_HEAD_TOP: //Upper Head - flag = (where&EQP_HELM); - break; - case EQI_ARMOR: //Body - flag = (where&EQP_ARMOR); - break; - case EQI_HAND_R: //Left/Right hands - case EQI_HAND_L: - flag = ( - (where&EQP_WEAPON && sd->inventory_data[j]->type == IT_WEAPON) || - (where&EQP_SHIELD && sd->inventory_data[j]->type == IT_ARMOR)); - break; - case EQI_SHOES: - flag = (where&EQP_SHOES); - break; - case EQI_GARMENT: - flag = (where&EQP_GARMENT); - break; - default: - continue; - } - if (flag) { - sd->status.inventory[j].attribute = 1; - pc_unequipitem(sd, j, 3); - } - } - clif_equiplist(sd); - } + const int where_list[4] = {EQP_WEAPON, EQP_ARMOR, EQP_SHIELD, EQP_HELM}; + const enum sc_type scatk[4] = {SC_STRIPWEAPON, SC_STRIPARMOR, SC_STRIPSHIELD, SC_STRIPHELM}; + const enum sc_type scdef[4] = {SC_CP_WEAPON, SC_CP_ARMOR, SC_CP_SHIELD, SC_CP_HELM}; + struct status_change *sc = status_get_sc(bl); + int i,j; + TBL_PC *sd; + sd = BL_CAST(BL_PC, bl); + if (sc && !sc->count) + sc = NULL; + + if (sd) { + if (sd->bonus.unbreakable_equip) + where &= ~sd->bonus.unbreakable_equip; + if (sd->bonus.unbreakable) + rate -= rate*sd->bonus.unbreakable/100; + if (where&EQP_WEAPON) { + switch (sd->status.weapon) { + case W_FIST: //Bare fists should not break :P + case W_1HAXE: + case W_2HAXE: + case W_MACE: // Axes and Maces can't be broken [DracoRPG] + case W_2HMACE: + case W_STAFF: + case W_2HSTAFF: + case W_BOOK: //Rods and Books can't be broken [Skotlex] + case W_HUUMA: + where &= ~EQP_WEAPON; + } + } + } + if (flag&BCT_ENEMY) { + if (battle_config.equip_skill_break_rate != 100) + rate = rate*battle_config.equip_skill_break_rate/100; + } else if (flag&(BCT_PARTY|BCT_SELF)) { + if (battle_config.equip_self_break_rate != 100) + rate = rate*battle_config.equip_self_break_rate/100; + } + + for (i = 0; i < 4; i++) { + if (where&where_list[i]) { + if (sc && sc->count && sc->data[scdef[i]]) + where&=~where_list[i]; + else if (rnd()%10000 >= rate) + where&=~where_list[i]; + else if (!sd && !(status_get_mode(bl)&MD_BOSS)) //Cause Strip effect. + sc_start(bl,scatk[i],100,0,skill_get_time(status_sc2skill(scatk[i]),1)); + } + } + if (!where) //Nothing to break. + return 0; + if (sd) { + for (i = 0; i < EQI_MAX; i++) { + j = sd->equip_index[i]; + if (j < 0 || sd->status.inventory[j].attribute == 1 || !sd->inventory_data[j]) + continue; + + switch(i) { + case EQI_HEAD_TOP: //Upper Head + flag = (where&EQP_HELM); + break; + case EQI_ARMOR: //Body + flag = (where&EQP_ARMOR); + break; + case EQI_HAND_R: //Left/Right hands + case EQI_HAND_L: + flag = ( + (where&EQP_WEAPON && sd->inventory_data[j]->type == IT_WEAPON) || + (where&EQP_SHIELD && sd->inventory_data[j]->type == IT_ARMOR)); + break; + case EQI_SHOES: + flag = (where&EQP_SHOES); + break; + case EQI_GARMENT: + flag = (where&EQP_GARMENT); + break; + default: + continue; + } + if (flag) { + sd->status.inventory[j].attribute = 1; + pc_unequipitem(sd, j, 3); + } + } + clif_equiplist(sd); + } - return where; //Return list of pieces broken. + return where; //Return list of pieces broken. } int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time) { - struct status_change *sc; - const int pos[5] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM, EQP_ACC}; - const enum sc_type sc_atk[5] = {SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC__STRIPACCESSORY}; - const enum sc_type sc_def[5] = {SC_CP_WEAPON, SC_CP_SHIELD, SC_CP_ARMOR, SC_CP_HELM, 0}; - int i; - - if (rnd()%100 >= rate) - return 0; - - sc = status_get_sc(bl); - if (!sc || sc->option&OPTION_MADOGEAR) //Mado Gear cannot be divested [Ind] - return 0; - - for (i = 0; i < ARRAYLENGTH(pos); i++) { - if (where&pos[i] && sc->data[sc_def[i]]) - where&=~pos[i]; - } - if (!where) return 0; - - for (i = 0; i < ARRAYLENGTH(pos); i++) { - if (where&pos[i] && !sc_start(bl, sc_atk[i], 100, lv, time)) - where&=~pos[i]; - } - return where?1:0; + struct status_change *sc; + const int pos[5] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM, EQP_ACC}; + const enum sc_type sc_atk[5] = {SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC__STRIPACCESSORY}; + const enum sc_type sc_def[5] = {SC_CP_WEAPON, SC_CP_SHIELD, SC_CP_ARMOR, SC_CP_HELM, 0}; + int i; + + if (rnd()%100 >= rate) + return 0; + + sc = status_get_sc(bl); + if (!sc || sc->option&OPTION_MADOGEAR ) //Mado Gear cannot be divested [Ind] + return 0; + + for (i = 0; i < ARRAYLENGTH(pos); i++) { + if (where&pos[i] && sc->data[sc_def[i]]) + where&=~pos[i]; + } + if (!where) return 0; + + for (i = 0; i < ARRAYLENGTH(pos); i++) { + if (where&pos[i] && !sc_start(bl, sc_atk[i], 100, lv, time)) + where&=~pos[i]; + } + return where?1:0; } //Early declaration static int skill_area_temp[8]; @@ -2180,88 +2027,88 @@ static int skill_area_temp[8]; - if 'flag&0x1', position update packets must not be sent. - if 'flag&0x2', skill blown ignores players' special_state.no_knockback -------------------------------------------------------------------------*/ -int skill_blown(struct block_list *src, struct block_list *target, int count, int direction, int flag) +int skill_blown(struct block_list* src, struct block_list* target, int count, int direction, int flag) { - int dx = 0, dy = 0; - struct skill_unit *su = NULL; - - nullpo_ret(src); - - if (src != target && (map_flag_gvg(target->m) || map[target->m].flag.battleground)) - return 0; //No knocking back in WoE - if (count == 0) - return 0; //Actual knockback distance is 0. - - switch (target->type) { - case BL_MOB: { - struct mob_data *md = BL_CAST(BL_MOB, target); - if (md->class_ == MOBID_EMPERIUM) - return 0; - if (src != target && is_boss(target)) //Bosses can't be knocked-back - return 0; - } - break; - case BL_PC: { - struct map_session_data *sd = BL_CAST(BL_PC, target); - if (sd->sc.data[SC_BASILICA] && sd->sc.data[SC_BASILICA]->val4 == sd->bl.id && !is_boss(src)) - return 0; // Basilica caster can't be knocked-back by normal monsters. - if (!(flag&0x2) && src != target && sd->special_state.no_knockback) - return 0; - } - break; - case BL_SKILL: - su = (struct skill_unit *)target; - if (su && su->group && su->group->unit_id == UNT_ANKLESNARE) - return 0; // ankle snare cannot be knocked back - break; - } + int dx = 0, dy = 0; + struct skill_unit* su = NULL; + + nullpo_ret(src); + + if (src != target && (map_flag_gvg(target->m) || map[target->m].flag.battleground)) + return 0; //No knocking back in WoE + if (count == 0) + return 0; //Actual knockback distance is 0. + + switch (target->type) { + case BL_MOB: { + struct mob_data* md = BL_CAST(BL_MOB, target); + if( md->class_ == MOBID_EMPERIUM ) + return 0; + if(src != target && is_boss(target)) //Bosses can't be knocked-back + return 0; + } + break; + case BL_PC: { + struct map_session_data *sd = BL_CAST(BL_PC, target); + if( sd->sc.data[SC_BASILICA] && sd->sc.data[SC_BASILICA]->val4 == sd->bl.id && !is_boss(src)) + return 0; // Basilica caster can't be knocked-back by normal monsters. + if( !(flag&0x2) && src != target && sd->special_state.no_knockback ) + return 0; + } + break; + case BL_SKILL: + su = (struct skill_unit *)target; + if( su && su->group && su->group->unit_id == UNT_ANKLESNARE ) + return 0; // ankle snare cannot be knocked back + break; + } - if (direction == -1) // <optimized>: do the computation here instead of outside - direction = map_calc_dir(target, src->x, src->y); // direction from src to target, reversed + if (direction == -1) // <optimized>: do the computation here instead of outside + direction = map_calc_dir(target, src->x, src->y); // direction from src to target, reversed - if (direction >= 0 && direction < 8) { - // take the reversed 'direction' and reverse it - dx = -dirx[direction]; - dy = -diry[direction]; - } + if (direction >= 0 && direction < 8) + { // take the reversed 'direction' and reverse it + dx = -dirx[direction]; + dy = -diry[direction]; + } - return unit_blown(target, dx, dy, count, flag); // send over the proper flag + return unit_blown(target, dx, dy, count, flag); // send over the proper flag } //Checks if 'bl' should reflect back a spell cast by 'src'. //type is the type of magic attack: 0: indirect (aoe), 1: direct (targetted) -static int skill_magic_reflect(struct block_list *src, struct block_list *bl, int type) +static int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) { - struct status_change *sc = status_get_sc(bl); - struct map_session_data *sd = BL_CAST(BL_PC, bl); + struct status_change *sc = status_get_sc(bl); + struct map_session_data* sd = BL_CAST(BL_PC, bl); - if (sc && sc->data[SC_KYOMU]) // Nullify reflecting ability - return 0; + if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability + return 0; - // item-based reflection - if (sd && sd->bonus.magic_damage_return && type && rnd()%100 < sd->bonus.magic_damage_return) - return 1; + // item-based reflection + if( sd && sd->bonus.magic_damage_return && type && rnd()%100 < sd->bonus.magic_damage_return ) + return 1; - if (is_boss(src)) - return 0; + if( is_boss(src) ) + return 0; - // status-based reflection - if (!sc || sc->count == 0) - return 0; + // status-based reflection + if( !sc || sc->count == 0 ) + return 0; - if (sc->data[SC_MAGICMIRROR] && rnd()%100 < sc->data[SC_MAGICMIRROR]->val2) - return 1; + if( sc->data[SC_MAGICMIRROR] && rnd()%100 < sc->data[SC_MAGICMIRROR]->val2 ) + return 1; - if (sc->data[SC_KAITE] && (src->type == BL_PC || status_get_lv(src) <= 80)) { - // Kaite only works against non-players if they are low-level. - clif_specialeffect(bl, 438, AREA); - if (--sc->data[SC_KAITE]->val2 <= 0) - status_change_end(bl, SC_KAITE, INVALID_TIMER); - return 2; - } + if( sc->data[SC_KAITE] && (src->type == BL_PC || status_get_lv(src) <= 80) ) + {// Kaite only works against non-players if they are low-level. + clif_specialeffect(bl, 438, AREA); + if( --sc->data[SC_KAITE]->val2 <= 0 ) + status_change_end(bl, SC_KAITE, INVALID_TIMER); + return 2; + } - return 0; + return 0; } /* @@ -2278,623 +2125,633 @@ static int skill_magic_reflect(struct block_list *src, struct block_list *bl, in * flag&0x2000 is used to signal that the skilllv should be passed as -1 to the * client (causes player characters to not scream skill name) *-------------------------------------------------------------------------*/ -int skill_attack(int attack_type, struct block_list *src, struct block_list *dsrc, struct block_list *bl, int skillid, int skilllv, unsigned int tick, int flag) +int skill_attack (int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, int skillid, int skilllv, unsigned int tick, int flag) { - struct Damage dmg; - struct status_data *sstatus, *tstatus; - struct status_change *sc; - struct map_session_data *sd, *tsd; - int type,damage,rdamage=0; - - if (skillid > 0 && skilllv <= 0) return 0; - - nullpo_ret(src); //Source is the master behind the attack (player/mob/pet) - nullpo_ret(dsrc); //dsrc is the actual originator of the damage, can be the same as src, or a skill casted by src. - nullpo_ret(bl); //Target to be attacked. - - if (src != dsrc) { - //When caster is not the src of attack, this is a ground skill, and as such, do the relevant target checking. [Skotlex] - if (!status_check_skilluse(battle_config.skill_caster_check?src:NULL, bl, skillid, 2)) - return 0; - } else if ((flag&SD_ANIMATION) && skill_get_nk(skillid)&NK_SPLASH) { - //Note that splash attacks often only check versus the targetted mob, those around the splash area normally don't get checked for being hidden/cloaked/etc. [Skotlex] - if (!status_check_skilluse(src, bl, skillid, 2)) - return 0; - } - - sd = BL_CAST(BL_PC, src); - tsd = BL_CAST(BL_PC, bl); - - sstatus = status_get_status_data(src); - tstatus = status_get_status_data(bl); - sc= status_get_sc(bl); - if (sc && !sc->count) sc = NULL; //Don't need it. - - // Is this check really needed? FrostNova won't hurt you if you step right where the caster is? - if (skillid == WZ_FROSTNOVA && dsrc->x == bl->x && dsrc->y == bl->y) - return 0; - //Trick Dead protects you from damage, but not from buffs and the like, hence it's placed here. - if (sc && sc->data[SC_TRICKDEAD] && !(sstatus->mode&MD_BOSS)) - return 0; - - dmg = battle_calc_attack(attack_type,src,bl,skillid,skilllv,flag&0xFFF); - - //Skotlex: Adjusted to the new system - if (src->type==BL_PET) { - // [Valaris] - struct pet_data *pd = (TBL_PET *)src; - if (pd->a_skill && pd->a_skill->div_ && pd->a_skill->id == skillid) { - int element = skill_get_ele(skillid, skilllv); - if (skillid == -1) - element = sstatus->rhw.ele; - if (element != ELE_NEUTRAL || !(battle_config.attack_attr_none&BL_PET)) - dmg.damage=battle_attr_fix(src, bl, skilllv, element, tstatus->def_ele, tstatus->ele_lv); - else - dmg.damage= skilllv; - dmg.damage2=0; - dmg.div_= pd->a_skill->div_; - } - } - - if (dmg.flag&BF_MAGIC && (skillid != NPC_EARTHQUAKE || (battle_config.eq_single_target_reflectable && (flag&0xFFF) == 1))) { - // Earthquake on multiple targets is not counted as a target skill. [Inkfish] - if ((dmg.damage || dmg.damage2) && (type = skill_magic_reflect(src, bl, src==dsrc))) { - //Magic reflection, switch caster/target - struct block_list *tbl = bl; - bl = src; - src = tbl; - sd = BL_CAST(BL_PC, src); - tsd = BL_CAST(BL_PC, bl); - sc = status_get_sc(bl); - if (sc && !sc->count) - sc = NULL; //Don't need it. - /* bugreport:2564 flag&2 disables double casting trigger */ - flag |= 2; - - //Spirit of Wizard blocks Kaite's reflection - if (type == 2 && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_WIZARD) { - //Consume one Fragment per hit of the casted skill? [Skotlex] - type = tsd?pc_search_inventory(tsd, 7321):0; - if (type >= 0) { - if (tsd) pc_delitem(tsd, type, 1, 0, 1, LOG_TYPE_CONSUME); - dmg.damage = dmg.damage2 = 0; - dmg.dmg_lv = ATK_MISS; - sc->data[SC_SPIRIT]->val3 = skillid; - sc->data[SC_SPIRIT]->val4 = dsrc->id; - } - } - /** - * Official Magic Reflection Behavior : damage reflected depends on gears caster wears, not target - **/ -#if MAGIC_REFLECTION_TYPE - if (dmg.dmg_lv != ATK_MISS) //Wiz SL cancelled and consumed fragment - dmg = battle_calc_attack(BF_MAGIC,bl,bl,skillid,skilllv,flag&0xFFF); -#endif - } - if (sc && sc->data[SC_MAGICROD] && src == dsrc) { - int sp = skill_get_sp(skillid,skilllv); - dmg.damage = dmg.damage2 = 0; - dmg.dmg_lv = ATK_MISS; //This will prevent skill additional effect from taking effect. [Skotlex] - sp = sp * sc->data[SC_MAGICROD]->val2 / 100; - if (skillid == WZ_WATERBALL && skilllv > 1) - sp = sp/((skilllv|1)*(skilllv|1)); //Estimate SP cost of a single water-ball - status_heal(bl, 0, sp, 2); - } - } - - damage = dmg.damage + dmg.damage2; - - if ((skillid == AL_INCAGI || skillid == AL_BLESSING || - skillid == CASH_BLESSING || skillid == CASH_INCAGI || - skillid == MER_INCAGI || skillid == MER_BLESSING) && tsd->sc.data[SC_CHANGEUNDEAD]) - damage = 1; - - if (damage > 0 && ((dmg.flag&BF_WEAPON && src != bl && (src == dsrc || (dsrc->type == BL_SKILL && (skillid == SG_SUN_WARM || skillid == SG_MOON_WARM || skillid == SG_STAR_WARM)))) - || (sc && sc->data[SC_REFLECTDAMAGE]))) - rdamage = battle_calc_return_damage(bl,src, &damage, dmg.flag, skillid); - - if (damage && sc && sc->data[SC_GENSOU] && dmg.flag&BF_MAGIC) { - struct block_list *nbl = NULL; - nbl = battle_getenemyarea(bl,bl->x,bl->y,2,BL_CHAR,bl->id); - if (nbl) { // Only one target is chosen. - damage = damage / 2; // Deflect half of the damage to a target nearby - clif_skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,damage,0), dmg.div_, OB_OBOROGENSOU_TRANSITION_ATK, -1, 6); - } - } - - //Skill hit type - type=(skillid==0)?5:skill_get_hit(skillid); - - if (damage < dmg.div_ - //Only skills that knockback even when they miss. [Skotlex] - && skillid != CH_PALMSTRIKE) - dmg.blewcount = 0; - - if (skillid == CR_GRANDCROSS||skillid == NPC_GRANDDARKNESS) { - if (battle_config.gx_disptype) dsrc = src; - if (src == bl) type = 4; - else flag|=SD_ANIMATION; - } - if (skillid == NJ_TATAMIGAESHI) { - dsrc = src; //For correct knockback. - flag|=SD_ANIMATION; - } - - if (sd) { - int flag = 0; //Used to signal if this skill can be combo'ed later on. - struct status_change_entry *sce; - if ((sce = sd->sc.data[SC_COMBO])) {//End combo state after skill is invoked. [Skotlex] - switch (skillid) { - case TK_TURNKICK: - case TK_STORMKICK: - case TK_DOWNKICK: - case TK_COUNTER: - if (pc_famerank(sd->status.char_id,MAPID_TAEKWON)) {//Extend combo time. - sce->val1 = skillid; //Update combo-skill - sce->val3 = skillid; - if (sce->timer != INVALID_TIMER) - delete_timer(sce->timer, status_change_timer); - sce->timer = add_timer(tick+sce->val4, status_change_timer, src->id, SC_COMBO); - break; - } - unit_cancel_combo(src); // Cancel combo wait - break; - default: - if (src == dsrc) // Ground skills are exceptions. [Inkfish] - status_change_end(src, SC_COMBO, INVALID_TIMER); - } - } - switch (skillid) { - case MO_TRIPLEATTACK: - if (pc_checkskill(sd, MO_CHAINCOMBO) > 0 || pc_checkskill(sd, SR_DRAGONCOMBO) > 0) - flag=1; - break; - case MO_CHAINCOMBO: - if (pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0) - flag=1; - break; - case MO_COMBOFINISH: - if (sd->status.party_id>0) //bonus from SG_FRIEND [Komurka] - party_skill_check(sd, sd->status.party_id, MO_COMBOFINISH, skilllv); - if (pc_checkskill(sd, CH_TIGERFIST) > 0 && sd->spiritball > 0) - flag=1; - case CH_TIGERFIST: - if (!flag && pc_checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1) - flag=1; - case CH_CHAINCRUSH: - if (!flag && pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball > 0 && sd->sc.data[SC_EXPLOSIONSPIRITS]) - flag=1; - break; - case AC_DOUBLE: - if ((tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT) && pc_checkskill(sd, HT_POWER)) { - //TODO: This code was taken from Triple Blows, is this even how it should be? [Skotlex] - sc_start2(src,SC_COMBO,100,HT_POWER,bl->id,2000); - clif_combo_delay(src,2000); - } - break; - case TK_COUNTER: { - //bonus from SG_FRIEND [Komurka] - int level; - if (sd->status.party_id>0 && (level = pc_checkskill(sd,SG_FRIEND))) - party_skill_check(sd, sd->status.party_id, TK_COUNTER,level); - } - break; - case SL_STIN: - case SL_STUN: - if (skilllv >= 7 && !sd->sc.data[SC_SMA]) - sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA, skilllv)); - break; - case GS_FULLBUSTER: - //Can't attack nor use items until skill's delay expires. [Skotlex] - sd->ud.attackabletime = sd->canuseitem_tick = sd->ud.canact_tick; - break; - case SR_DRAGONCOMBO: - if (pc_checkskill(sd, SR_FALLENEMPIRE) > 0) - flag = 1; - break; - case SR_FALLENEMPIRE: - if (pc_checkskill(sd, SR_TIGERCANNON) > 0 || pc_checkskill(sd, SR_GATEOFHELL) > 0) - flag = 1; - break; - } //Switch End - if (flag) { //Possible to chain - flag = DIFF_TICK(sd->ud.canact_tick, tick); - if (flag < 1) flag = 1; - sc_start2(src,SC_COMBO,100,skillid,bl->id,flag); - clif_combo_delay(src, flag); - } - } - - //Display damage. - switch (skillid) { - case PA_GOSPEL: //Should look like Holy Cross [Skotlex] - dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, 5); - break; - //Skills that need be passed as a normal attack for the client to display correctly. - case HVAN_EXPLOSION: - case NPC_SELFDESTRUCTION: - if (src->type==BL_PC) - dmg.blewcount = 10; - dmg.amotion = 0; //Disable delay or attack will do no damage since source is dead by the time it takes effect. [Skotlex] - // fall through - case KN_AUTOCOUNTER: - case NPC_CRITICALSLASH: - case TF_DOUBLE: - case GS_CHAINACTION: - dmg.dmotion = clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2); - break; + struct Damage dmg; + struct status_data *sstatus, *tstatus; + struct status_change *sc; + struct map_session_data *sd, *tsd; + int type,damage,rdamage=0; + + if(skillid > 0 && skilllv <= 0) return 0; + + nullpo_ret(src); //Source is the master behind the attack (player/mob/pet) + nullpo_ret(dsrc); //dsrc is the actual originator of the damage, can be the same as src, or a skill casted by src. + nullpo_ret(bl); //Target to be attacked. + + if (src != dsrc) { + //When caster is not the src of attack, this is a ground skill, and as such, do the relevant target checking. [Skotlex] + if (!status_check_skilluse(battle_config.skill_caster_check?src:NULL, bl, skillid, 2)) + return 0; + } else if ((flag&SD_ANIMATION) && skill_get_nk(skillid)&NK_SPLASH) { + //Note that splash attacks often only check versus the targetted mob, those around the splash area normally don't get checked for being hidden/cloaked/etc. [Skotlex] + if (!status_check_skilluse(src, bl, skillid, 2)) + return 0; + } - case AS_SPLASHER: - if (flag&SD_ANIMATION) // the surrounding targets - dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, -1, 5); // needs -1 as skill level - else // the central target doesn't display an animation - dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, -2, 5); // needs -2(!) as skill level - break; - case WL_HELLINFERNO: - case SR_EARTHSHAKER: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skillid,-2,6); - break; - case WL_SOULEXPANSION: - case WL_COMET: - case KO_MUCHANAGE: - case NJ_HUUMA: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skillid,skilllv,8); - break; - case WL_CHAINLIGHTNING_ATK: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,6); - break; - case LG_OVERBRAND_BRANDISH: - case LG_OVERBRAND_PLUSATK: - case EL_FIRE_BOMB: - case EL_FIRE_BOMB_ATK: - case EL_FIRE_WAVE: - case EL_FIRE_WAVE_ATK: - case EL_FIRE_MANTLE: - case EL_CIRCLE_OF_FIRE: - case EL_FIRE_ARROW: - case EL_ICE_NEEDLE: - case EL_WATER_SCREW: - case EL_WATER_SCREW_ATK: - case EL_WIND_SLASH: - case EL_TIDAL_WEAPON: - case EL_ROCK_CRUSHER: - case EL_ROCK_CRUSHER_ATK: - case EL_HURRICANE: - case EL_HURRICANE_ATK: - case EL_TYPOON_MIS: - case EL_TYPOON_MIS_ATK: - case KO_BAKURETSU: - case GN_CRAZYWEED_ATK: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skillid,-1,5); - break; - case GN_SLINGITEM_RANGEMELEEATK: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,6); - break; - case EL_STONE_RAIN: - dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skillid,-1,(flag&1)?8:5); - break; - case WM_SEVERE_RAINSTORM_MELEE: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,skilllv,5); - break; - case WM_REVERBERATION_MELEE: - case WM_REVERBERATION_MAGIC: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,6); - break; - case HT_CLAYMORETRAP: - case HT_BLASTMINE: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case RA_CLUSTERBOMB: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - dmg.dmotion = clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid,flag&SD_LEVEL?-1:skilllv, 5); - if (dsrc != src) // avoid damage display redundancy - break; - case HT_LANDMINE: - dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, -1, type); - break; - case AB_DUPLELIGHT_MELEE: - case AB_DUPLELIGHT_MAGIC: - dmg.amotion = 300;/* makes the damage value not overlap with previous damage (when displayed by the client) */ - default: - if (flag&SD_ANIMATION && dmg.div_ < 2) //Disabling skill animation doesn't works on multi-hit. - type = 5; - if (bl->type == BL_SKILL) { - TBL_SKILL *su = (TBL_SKILL *)bl; - if (su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP) // show damage on trap targets - clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, flag&SD_LEVEL?-1:skilllv, 5); - } - dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, flag&SD_LEVEL?-1:skilllv, type); - break; - } - - map_freeblock_lock(); - - if (damage > 0 && dmg.flag&BF_SKILL && tsd - && pc_checkskill(tsd,RG_PLAGIARISM) - && (!sc || !sc->data[SC_PRESERVE]) - && damage < tsd->battle_status.hp) { - //Updated to not be able to copy skills if the blow will kill you. [Skotlex] - int copy_skill = skillid; - /** - * Copy Referal: dummy skills should point to their source upon copying - **/ - switch (skillid) { - case AB_DUPLELIGHT_MELEE: - case AB_DUPLELIGHT_MAGIC: - copy_skill = AB_DUPLELIGHT; - break; - case WL_CHAINLIGHTNING_ATK: - copy_skill = WL_CHAINLIGHTNING; - break; - case WM_REVERBERATION_MELEE: - case WM_REVERBERATION_MAGIC: - copy_skill = WM_REVERBERATION; - break; - case WM_SEVERE_RAINSTORM_MELEE: - copy_skill = WM_SEVERE_RAINSTORM; - break; - case GN_CRAZYWEED_ATK: - copy_skill = GN_CRAZYWEED; - break; - case GN_HELLS_PLANT_ATK: - copy_skill = GN_HELLS_PLANT; - break; - case LG_OVERBRAND_BRANDISH: - case LG_OVERBRAND_PLUSATK: - copy_skill = LG_OVERBRAND; - break; - } - - if ((tsd->status.skill[copy_skill].id == 0 || tsd->status.skill[copy_skill].flag == SKILL_FLAG_PLAGIARIZED) && - can_copy(tsd,copy_skill,bl)) { // Split all the check into their own function [Aru] - int lv; - if (sc && sc->data[SC__REPRODUCE] && (lv = sc->data[SC__REPRODUCE]->val1)) { - //Level dependent and limitation. - lv = min(lv,skill_get_max(copy_skill)); - if (tsd->reproduceskill_id && tsd->status.skill[tsd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED) { - tsd->status.skill[tsd->reproduceskill_id].id = 0; - tsd->status.skill[tsd->reproduceskill_id].lv = 0; - tsd->status.skill[tsd->reproduceskill_id].flag = 0; - clif_deleteskill(tsd,tsd->reproduceskill_id); - } + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, bl); + + sstatus = status_get_status_data(src); + tstatus = status_get_status_data(bl); + sc= status_get_sc(bl); + if (sc && !sc->count) sc = NULL; //Don't need it. + + // Is this check really needed? FrostNova won't hurt you if you step right where the caster is? + if(skillid == WZ_FROSTNOVA && dsrc->x == bl->x && dsrc->y == bl->y) + return 0; + //Trick Dead protects you from damage, but not from buffs and the like, hence it's placed here. + if (sc && sc->data[SC_TRICKDEAD] && !(sstatus->mode&MD_BOSS)) + return 0; + + dmg = battle_calc_attack(attack_type,src,bl,skillid,skilllv,flag&0xFFF); + + //Skotlex: Adjusted to the new system + if(src->type==BL_PET) + { // [Valaris] + struct pet_data *pd = (TBL_PET*)src; + if (pd->a_skill && pd->a_skill->div_ && pd->a_skill->id == skillid) + { + int element = skill_get_ele(skillid, skilllv); + if (skillid == -1) + element = sstatus->rhw.ele; + if (element != ELE_NEUTRAL || !(battle_config.attack_attr_none&BL_PET)) + dmg.damage=battle_attr_fix(src, bl, skilllv, element, tstatus->def_ele, tstatus->ele_lv); + else + dmg.damage= skilllv; + dmg.damage2=0; + dmg.div_= pd->a_skill->div_; + } + } - tsd->reproduceskill_id = copy_skill; - pc_setglobalreg(tsd, "REPRODUCE_SKILL", copy_skill); - pc_setglobalreg(tsd, "REPRODUCE_SKILL_LV", lv); - - tsd->status.skill[copy_skill].id = copy_skill; - tsd->status.skill[copy_skill].lv = lv; - tsd->status.skill[copy_skill].flag = SKILL_FLAG_PLAGIARIZED; - clif_addskill(tsd,copy_skill); - } else { - lv = skilllv; - if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED) { - tsd->status.skill[tsd->cloneskill_id].id = 0; - tsd->status.skill[tsd->cloneskill_id].lv = 0; - tsd->status.skill[tsd->cloneskill_id].flag = 0; - clif_deleteskill(tsd,tsd->cloneskill_id); - } + if( dmg.flag&BF_MAGIC && ( skillid != NPC_EARTHQUAKE || (battle_config.eq_single_target_reflectable && (flag&0xFFF) == 1) ) ) + { // Earthquake on multiple targets is not counted as a target skill. [Inkfish] + if( (dmg.damage || dmg.damage2) && (type = skill_magic_reflect(src, bl, src==dsrc)) ) + { //Magic reflection, switch caster/target + struct block_list *tbl = bl; + bl = src; + src = tbl; + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, bl); + sc = status_get_sc(bl); + if (sc && !sc->count) + sc = NULL; //Don't need it. + /* bugreport:2564 flag&2 disables double casting trigger */ + flag |= 2; + + //Spirit of Wizard blocks Kaite's reflection + if( type == 2 && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_WIZARD ) + { //Consume one Fragment per hit of the casted skill? [Skotlex] + type = tsd?pc_search_inventory (tsd, 7321):0; + if (type >= 0) { + if ( tsd ) pc_delitem(tsd, type, 1, 0, 1, LOG_TYPE_CONSUME); + dmg.damage = dmg.damage2 = 0; + dmg.dmg_lv = ATK_MISS; + sc->data[SC_SPIRIT]->val3 = skillid; + sc->data[SC_SPIRIT]->val4 = dsrc->id; + } + } + /** + * Official Magic Reflection Behavior : damage reflected depends on gears caster wears, not target + **/ + #if MAGIC_REFLECTION_TYPE + if( dmg.dmg_lv != ATK_MISS )//Wiz SL cancelled and consumed fragment + dmg = battle_calc_attack(BF_MAGIC,bl,bl,skillid,skilllv,flag&0xFFF); + #endif + } + if(sc && sc->data[SC_MAGICROD] && src == dsrc) { + int sp = skill_get_sp(skillid,skilllv); + dmg.damage = dmg.damage2 = 0; + dmg.dmg_lv = ATK_MISS; //This will prevent skill additional effect from taking effect. [Skotlex] + sp = sp * sc->data[SC_MAGICROD]->val2 / 100; + if(skillid == WZ_WATERBALL && skilllv > 1) + sp = sp/((skilllv|1)*(skilllv|1)); //Estimate SP cost of a single water-ball + status_heal(bl, 0, sp, 2); + } + } - if ((type = pc_checkskill(tsd,RG_PLAGIARISM)) < lv) - lv = type; + damage = dmg.damage + dmg.damage2; - tsd->cloneskill_id = copy_skill; - pc_setglobalreg(tsd, "CLONE_SKILL", copy_skill); - pc_setglobalreg(tsd, "CLONE_SKILL_LV", lv); + if( (skillid == AL_INCAGI || skillid == AL_BLESSING || + skillid == CASH_BLESSING || skillid == CASH_INCAGI || + skillid == MER_INCAGI || skillid == MER_BLESSING) && tsd->sc.data[SC_CHANGEUNDEAD] ) + damage = 1; - tsd->status.skill[skillid].id = copy_skill; - tsd->status.skill[skillid].lv = lv; - tsd->status.skill[skillid].flag = SKILL_FLAG_PLAGIARIZED; - clif_addskill(tsd,skillid); - } - } - } - - if (dmg.dmg_lv >= ATK_MISS && (type = skill_get_walkdelay(skillid, skilllv)) > 0) { - //Skills with can't walk delay also stop normal attacking for that - //duration when the attack connects. [Skotlex] - struct unit_data *ud = unit_bl2ud(src); - if (ud && DIFF_TICK(ud->attackabletime, tick + type) < 0) - ud->attackabletime = tick + type; - } - - if (!dmg.amotion) { - //Instant damage - if (!sc || (!sc->data[SC_DEVOTION] && skillid != CR_REFLECTSHIELD)) - status_fix_damage(src,bl,damage,dmg.dmotion); //Deal damage before knockback to allow stuff like firewall+storm gust combo. - if (!status_isdead(bl)) - skill_additional_effect(src,bl,skillid,skilllv,dmg.flag,dmg.dmg_lv,tick); - if (damage > 0) //Counter status effects [Skotlex] - skill_counter_additional_effect(src,bl,skillid,skilllv,dmg.flag,tick); - } - // Hell Inferno burning status only starts if Fire part hits. - if (skillid == WL_HELLINFERNO && dmg.damage > 0) - sc_start4(bl,SC_BURNING,55+5*skilllv,skilllv,1000,src->id,0,skill_get_time(skillid,skilllv)); - // Apply knock back chance in SC_TRIANGLESHOT skill. - else if (skillid == SC_TRIANGLESHOT && rnd()%100 > (1 + skilllv)) - dmg.blewcount = 0; - - //Only knockback if it's still alive, otherwise a "ghost" is left behind. [Skotlex] - //Reflected spells do not bounce back (bl == dsrc since it only happens for direct skills) - if (dmg.blewcount > 0 && bl!=dsrc && !status_isdead(bl)) { - int direction = -1; // default - switch (skillid) { //direction - case MG_FIREWALL: - case PR_SANCTUARY: - case SC_TRIANGLESHOT: - case LG_OVERBRAND: - case SR_KNUCKLEARROW: - case GN_WALLOFTHORN: - case EL_FIRE_MANTLE: - direction = unit_getdir(bl);// backwards - break; - // This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics. - case WZ_STORMGUST: - direction = rand()%8; - break; - case WL_CRIMSONROCK: - direction = map_calc_dir(bl,skill_area_temp[4],skill_area_temp[5]); - break; - - } - //blown-specific handling - switch (skillid) { - case LG_OVERBRAND: - if (skill_blown(dsrc,bl,dmg.blewcount,direction,0)) { - short dir_x, dir_y; - dir_x = dirx[(direction+4)%8]; - dir_y = diry[(direction+4)%8]; - if (map_getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0) - skill_addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skilllv, BF_WEAPON, flag); - } else - skill_addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skilllv, BF_WEAPON, flag); - break; - case SR_KNUCKLEARROW: - if (skill_blown(dsrc,bl,dmg.blewcount,direction,0) && !(flag&4)) { - short dir_x, dir_y; - dir_x = dirx[(direction+4)%8]; - dir_y = diry[(direction+4)%8]; - if (map_getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0) - skill_addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag|4); - } - break; - case GN_WALLOFTHORN: - unit_stop_walking(bl,1); - skill_blown(dsrc,bl,dmg.blewcount,direction, 0x2); - clif_fixpos(bl); - break; - default: - skill_blown(dsrc,bl,dmg.blewcount,direction, 0x0); - if (!dmg.blewcount && bl->type == BL_SKILL && damage > 0) { - TBL_SKILL *su = (TBL_SKILL *)bl; - if (su->group && su->group->skill_id == HT_BLASTMINE) - skill_blown(src, bl, 3, -1, 0); - } - break; - } - } - - //Delayed damage must be dealt after the knockback (it needs to know actual position of target) - if (dmg.amotion) - battle_delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skillid,skilllv,damage,dmg.dmg_lv,dmg.dmotion); - - if (sc && sc->data[SC_DEVOTION] && skillid != PA_PRESSURE) { - struct status_change_entry *sce = sc->data[SC_DEVOTION]; - struct block_list *d_bl = map_id2bl(sce->val1); - - if (d_bl && ( - (d_bl->type == BL_MER && ((TBL_MER *)d_bl)->master && ((TBL_MER *)d_bl)->master->bl.id == bl->id) || - (d_bl->type == BL_PC && ((TBL_PC *)d_bl)->devotion[sce->val2] == bl->id) - ) && check_distance_bl(bl, d_bl, sce->val3)) { - /** - * Check for devotion and change targetted dmg. - * [d_bl = paladin; bl = player; src = source of dmg] - **/ - bool devo_flag = false; /* false = paladin devoing; true = player */ - if (src) { - struct status_change *tsc; - tsc = status_get_sc(src); - - /* Per official standards, following skills should reflect at the bl */ - if ((tsc->data[SC_KAITE] && attack_type == BF_MAGIC) || - (tsc->data[SC_REFLECTDAMAGE] && attack_type != BF_MAGIC) - ) - devo_flag = true; - } + if( damage > 0 && (( dmg.flag&BF_WEAPON && src != bl && ( src == dsrc || ( dsrc->type == BL_SKILL && ( skillid == SG_SUN_WARM || skillid == SG_MOON_WARM || skillid == SG_STAR_WARM ) ) )) + || (sc && sc->data[SC_REFLECTDAMAGE])) ) + rdamage = battle_calc_return_damage(bl,src, &damage, dmg.flag, skillid); - clif_damage( - ((devo_flag) ? bl:d_bl), - ((devo_flag) ? bl:d_bl), gettick(), 0, 0, damage, 0, 0, 0); - status_fix_damage( - ((devo_flag) ? bl:NULL), - ((devo_flag) ? bl:d_bl), damage, 0); - } else { - status_change_end(bl, SC_DEVOTION, INVALID_TIMER); - if (!dmg.amotion) - status_fix_damage(src,bl,damage,dmg.dmotion); - } - } - - if (damage > 0 && !(tstatus->mode&MD_BOSS)) { - if (skillid == RG_INTIMIDATE) { - int rate = 50 + skilllv * 5; - rate = rate + (status_get_lv(src) - status_get_lv(bl)); - if (rnd()%100 < rate) - skill_addtimerskill(src,tick + 800,bl->id,0,0,skillid,skilllv,0,flag); - } else if (skillid == SC_FATALMENACE) - skill_addtimerskill(src,tick + 800,bl->id,skill_area_temp[4],skill_area_temp[5],skillid,skilllv,0,flag); - } - - if (skillid == CR_GRANDCROSS || skillid == NPC_GRANDDARKNESS) - dmg.flag |= BF_WEAPON; - - if (sd && src != bl && damage > 0 && (dmg.flag&BF_WEAPON || - (dmg.flag&BF_MISC && (skillid == RA_CLUSTERBOMB || skillid == RA_FIRINGTRAP || skillid == RA_ICEBOUNDTRAP || skillid == RK_DRAGONBREATH)))) { - if (battle_config.left_cardfix_to_right) - battle_drain(sd, bl, dmg.damage, dmg.damage, tstatus->race, tstatus->mode&MD_BOSS); - else - battle_drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->mode&MD_BOSS); - } - - if (rdamage > 0) { - if (sc && sc->data[SC_REFLECTDAMAGE]) { - if (src != bl) // Don't reflect your own damage (Grand Cross) - map_foreachinshootrange(battle_damage_area,bl,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,bl,dmg.amotion,sstatus->dmotion,rdamage,tstatus->race); - } else { - if (dmg.amotion) - battle_delay_damage(tick, dmg.amotion,bl,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,0); - else - status_fix_damage(bl,src,rdamage,0); - clif_damage(src,src,tick, dmg.amotion,0,rdamage,1,4,0); // in aegis damage reflected is shown in single hit. - //Use Reflect Shield to signal this kind of skill trigger. [Skotlex] - if (tsd && src != bl) - battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); - skill_additional_effect(bl, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); - } - } - if (damage > 0) { - /** - * Post-damage effects - **/ - switch (skillid) { - case RK_CRUSHSTRIKE: - skill_break_equip(src,EQP_WEAPON,2000,BCT_SELF); // 20% chance to destroy the weapon. - break; - case GC_VENOMPRESSURE: { - struct status_change *ssc = status_get_sc(src); - if (ssc && ssc->data[SC_POISONINGWEAPON] && rnd()%100 < 70 + 5*skilllv) { - sc_start(bl,ssc->data[SC_POISONINGWEAPON]->val2,100,ssc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1)); - status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - } - break; - case WM_METALICSOUND: - status_zap(bl, 0, damage*100/(100*(110-pc_checkskill(sd,WM_LESSON)*10))); - break; - case SR_TIGERCANNON: - status_zap(bl, 0, damage/10); // 10% of damage dealt - break; - } - if (sd) - skill_onskillusage(sd, bl, skillid, tick); - } - - if (!(flag&2) && - ( - skillid == MG_COLDBOLT || skillid == MG_FIREBOLT || skillid == MG_LIGHTNINGBOLT - ) && - (sc = status_get_sc(src)) && - sc->data[SC_DOUBLECAST] && - rnd() % 100 < sc->data[SC_DOUBLECAST]->val2) { - // skill_addtimerskill(src, tick + dmg.div_*dmg.amotion, bl->id, 0, 0, skillid, skilllv, BF_MAGIC, flag|2); - skill_addtimerskill(src, tick + dmg.amotion, bl->id, 0, 0, skillid, skilllv, BF_MAGIC, flag|2); - } - - map_freeblock_unlock(); - - return damage; + if( damage && sc && sc->data[SC_GENSOU] && dmg.flag&BF_MAGIC ){ + struct block_list *nbl = NULL; + nbl = battle_getenemyarea(bl,bl->x,bl->y,2,BL_CHAR,bl->id); + if( nbl ){ // Only one target is chosen. + damage = damage / 2; // Deflect half of the damage to a target nearby + clif_skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,damage,0), dmg.div_, OB_OBOROGENSOU_TRANSITION_ATK, -1, 6); + } + } + + //Skill hit type + type=(skillid==0)?5:skill_get_hit(skillid); + + if(damage < dmg.div_ + //Only skills that knockback even when they miss. [Skotlex] + && skillid != CH_PALMSTRIKE) + dmg.blewcount = 0; + + if(skillid == CR_GRANDCROSS||skillid == NPC_GRANDDARKNESS) { + if(battle_config.gx_disptype) dsrc = src; + if(src == bl) type = 4; + else flag|=SD_ANIMATION; + } + if(skillid == NJ_TATAMIGAESHI) { + dsrc = src; //For correct knockback. + flag|=SD_ANIMATION; + } + + if(sd) { + int flag = 0; //Used to signal if this skill can be combo'ed later on. + struct status_change_entry *sce; + if ((sce = sd->sc.data[SC_COMBO])) {//End combo state after skill is invoked. [Skotlex] + switch (skillid) { + case TK_TURNKICK: + case TK_STORMKICK: + case TK_DOWNKICK: + case TK_COUNTER: + if (pc_famerank(sd->status.char_id,MAPID_TAEKWON)) {//Extend combo time. + sce->val1 = skillid; //Update combo-skill + sce->val3 = skillid; + if( sce->timer != INVALID_TIMER ) + delete_timer(sce->timer, status_change_timer); + sce->timer = add_timer(tick+sce->val4, status_change_timer, src->id, SC_COMBO); + break; + } + unit_cancel_combo(src); // Cancel combo wait + break; + default: + if( src == dsrc ) // Ground skills are exceptions. [Inkfish] + status_change_end(src, SC_COMBO, INVALID_TIMER); + } + } + switch(skillid) { + case MO_TRIPLEATTACK: + if (pc_checkskill(sd, MO_CHAINCOMBO) > 0 || pc_checkskill(sd, SR_DRAGONCOMBO) > 0) + flag=1; + break; + case MO_CHAINCOMBO: + if(pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0) + flag=1; + break; + case MO_COMBOFINISH: + if (sd->status.party_id>0) //bonus from SG_FRIEND [Komurka] + party_skill_check(sd, sd->status.party_id, MO_COMBOFINISH, skilllv); + if (pc_checkskill(sd, CH_TIGERFIST) > 0 && sd->spiritball > 0) + flag=1; + case CH_TIGERFIST: + if (!flag && pc_checkskill(sd, CH_CHAINCRUSH) > 0 && sd->spiritball > 1) + flag=1; + case CH_CHAINCRUSH: + if (!flag && pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball > 0 && sd->sc.data[SC_EXPLOSIONSPIRITS]) + flag=1; + break; + case AC_DOUBLE: + if( (tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT) && pc_checkskill(sd, HT_POWER)) + { + //TODO: This code was taken from Triple Blows, is this even how it should be? [Skotlex] + sc_start2(src,SC_COMBO,100,HT_POWER,bl->id,2000); + clif_combo_delay(src,2000); + } + break; + case TK_COUNTER: + { //bonus from SG_FRIEND [Komurka] + int level; + if(sd->status.party_id>0 && (level = pc_checkskill(sd,SG_FRIEND))) + party_skill_check(sd, sd->status.party_id, TK_COUNTER,level); + } + break; + case SL_STIN: + case SL_STUN: + if (skilllv >= 7 && !sd->sc.data[SC_SMA]) + sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA, skilllv)); + break; + case GS_FULLBUSTER: + //Can't attack nor use items until skill's delay expires. [Skotlex] + sd->ud.attackabletime = sd->canuseitem_tick = sd->ud.canact_tick; + break; + case SR_DRAGONCOMBO: + if( pc_checkskill(sd, SR_FALLENEMPIRE) > 0 ) + flag = 1; + break; + case SR_FALLENEMPIRE: + if( pc_checkskill(sd, SR_TIGERCANNON) > 0 || pc_checkskill(sd, SR_GATEOFHELL) > 0 ) + flag = 1; + break; + } //Switch End + if (flag) { //Possible to chain + flag = DIFF_TICK(sd->ud.canact_tick, tick); + if (flag < 1) flag = 1; + sc_start2(src,SC_COMBO,100,skillid,bl->id,flag); + clif_combo_delay(src, flag); + } + } + + //Display damage. + switch( skillid ) + { + case PA_GOSPEL: //Should look like Holy Cross [Skotlex] + dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, 5); + break; + //Skills that need be passed as a normal attack for the client to display correctly. + case HVAN_EXPLOSION: + case NPC_SELFDESTRUCTION: + if(src->type==BL_PC) + dmg.blewcount = 10; + dmg.amotion = 0; //Disable delay or attack will do no damage since source is dead by the time it takes effect. [Skotlex] + // fall through + case KN_AUTOCOUNTER: + case NPC_CRITICALSLASH: + case TF_DOUBLE: + case GS_CHAINACTION: + dmg.dmotion = clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2); + break; + + case AS_SPLASHER: + if( flag&SD_ANIMATION ) // the surrounding targets + dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, -1, 5); // needs -1 as skill level + else // the central target doesn't display an animation + dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, -2, 5); // needs -2(!) as skill level + break; + case WL_HELLINFERNO: + case SR_EARTHSHAKER: + dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skillid,-2,6); + break; + case WL_SOULEXPANSION: + case WL_COMET: + case KO_MUCHANAGE: + case NJ_HUUMA: + dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skillid,skilllv,8); + break; + case WL_CHAINLIGHTNING_ATK: + dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,6); + break; + case LG_OVERBRAND_BRANDISH: + case LG_OVERBRAND_PLUSATK: + case EL_FIRE_BOMB: + case EL_FIRE_BOMB_ATK: + case EL_FIRE_WAVE: + case EL_FIRE_WAVE_ATK: + case EL_FIRE_MANTLE: + case EL_CIRCLE_OF_FIRE: + case EL_FIRE_ARROW: + case EL_ICE_NEEDLE: + case EL_WATER_SCREW: + case EL_WATER_SCREW_ATK: + case EL_WIND_SLASH: + case EL_TIDAL_WEAPON: + case EL_ROCK_CRUSHER: + case EL_ROCK_CRUSHER_ATK: + case EL_HURRICANE: + case EL_HURRICANE_ATK: + case EL_TYPOON_MIS: + case EL_TYPOON_MIS_ATK: + case KO_BAKURETSU: + case GN_CRAZYWEED_ATK: + dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skillid,-1,5); + break; + case GN_SLINGITEM_RANGEMELEEATK: + dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,6); + break; + case EL_STONE_RAIN: + dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skillid,-1,(flag&1)?8:5); + break; + case WM_SEVERE_RAINSTORM_MELEE: + dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,skilllv,5); + break; + case WM_REVERBERATION_MELEE: + case WM_REVERBERATION_MAGIC: + dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,6); + break; + case HT_CLAYMORETRAP: + case HT_BLASTMINE: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case RA_CLUSTERBOMB: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + dmg.dmotion = clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid,flag&SD_LEVEL?-1:skilllv, 5); + if( dsrc != src ) // avoid damage display redundancy + break; + case HT_LANDMINE: + dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, -1, type); + break; + case AB_DUPLELIGHT_MELEE: + case AB_DUPLELIGHT_MAGIC: + dmg.amotion = 300;/* makes the damage value not overlap with previous damage (when displayed by the client) */ + default: + if( flag&SD_ANIMATION && dmg.div_ < 2 ) //Disabling skill animation doesn't works on multi-hit. + type = 5; + if( bl->type == BL_SKILL ){ + TBL_SKILL *su = (TBL_SKILL*)bl; + if( su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP )// show damage on trap targets + clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, flag&SD_LEVEL?-1:skilllv, 5); + } + dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skillid, flag&SD_LEVEL?-1:skilllv, type); + break; + } + + map_freeblock_lock(); + + if(damage > 0 && dmg.flag&BF_SKILL && tsd + && pc_checkskill(tsd,RG_PLAGIARISM) + && (!sc || !sc->data[SC_PRESERVE]) + && damage < tsd->battle_status.hp) + { //Updated to not be able to copy skills if the blow will kill you. [Skotlex] + int copy_skill = skillid; + /** + * Copy Referal: dummy skills should point to their source upon copying + **/ + switch( skillid ) { + case AB_DUPLELIGHT_MELEE: + case AB_DUPLELIGHT_MAGIC: + copy_skill = AB_DUPLELIGHT; + break; + case WL_CHAINLIGHTNING_ATK: + copy_skill = WL_CHAINLIGHTNING; + break; + case WM_REVERBERATION_MELEE: + case WM_REVERBERATION_MAGIC: + copy_skill = WM_REVERBERATION; + break; + case WM_SEVERE_RAINSTORM_MELEE: + copy_skill = WM_SEVERE_RAINSTORM; + break; + case GN_CRAZYWEED_ATK: + copy_skill = GN_CRAZYWEED; + break; + case GN_HELLS_PLANT_ATK: + copy_skill = GN_HELLS_PLANT; + break; + case LG_OVERBRAND_BRANDISH: + case LG_OVERBRAND_PLUSATK: + copy_skill = LG_OVERBRAND; + break; + } + + if ((tsd->status.skill[copy_skill].id == 0 || tsd->status.skill[copy_skill].flag == SKILL_FLAG_PLAGIARIZED) && + can_copy(tsd,copy_skill,bl)) // Split all the check into their own function [Aru] + { + int lv; + if( sc && sc->data[SC__REPRODUCE] && (lv = sc->data[SC__REPRODUCE]->val1) ) { + //Level dependent and limitation. + lv = min(lv,skill_get_max(copy_skill)); + if( tsd->reproduceskill_id && tsd->status.skill[tsd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED ) { + tsd->status.skill[tsd->reproduceskill_id].id = 0; + tsd->status.skill[tsd->reproduceskill_id].lv = 0; + tsd->status.skill[tsd->reproduceskill_id].flag = 0; + clif_deleteskill(tsd,tsd->reproduceskill_id); + } + + tsd->reproduceskill_id = copy_skill; + pc_setglobalreg(tsd, "REPRODUCE_SKILL", copy_skill); + pc_setglobalreg(tsd, "REPRODUCE_SKILL_LV", lv); + + tsd->status.skill[copy_skill].id = copy_skill; + tsd->status.skill[copy_skill].lv = lv; + tsd->status.skill[copy_skill].flag = SKILL_FLAG_PLAGIARIZED; + clif_addskill(tsd,copy_skill); + } else { + lv = skilllv; + if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED){ + tsd->status.skill[tsd->cloneskill_id].id = 0; + tsd->status.skill[tsd->cloneskill_id].lv = 0; + tsd->status.skill[tsd->cloneskill_id].flag = 0; + clif_deleteskill(tsd,tsd->cloneskill_id); + } + + if ((type = pc_checkskill(tsd,RG_PLAGIARISM)) < lv) + lv = type; + + tsd->cloneskill_id = copy_skill; + pc_setglobalreg(tsd, "CLONE_SKILL", copy_skill); + pc_setglobalreg(tsd, "CLONE_SKILL_LV", lv); + + tsd->status.skill[skillid].id = copy_skill; + tsd->status.skill[skillid].lv = lv; + tsd->status.skill[skillid].flag = SKILL_FLAG_PLAGIARIZED; + clif_addskill(tsd,skillid); + } + } + } + + if (dmg.dmg_lv >= ATK_MISS && (type = skill_get_walkdelay(skillid, skilllv)) > 0) + { //Skills with can't walk delay also stop normal attacking for that + //duration when the attack connects. [Skotlex] + struct unit_data *ud = unit_bl2ud(src); + if (ud && DIFF_TICK(ud->attackabletime, tick + type) < 0) + ud->attackabletime = tick + type; + } + + if( !dmg.amotion ) + { //Instant damage + if( !sc || (!sc->data[SC_DEVOTION] && skillid != CR_REFLECTSHIELD) ) + status_fix_damage(src,bl,damage,dmg.dmotion); //Deal damage before knockback to allow stuff like firewall+storm gust combo. + if( !status_isdead(bl) ) + skill_additional_effect(src,bl,skillid,skilllv,dmg.flag,dmg.dmg_lv,tick); + if( damage > 0 ) //Counter status effects [Skotlex] + skill_counter_additional_effect(src,bl,skillid,skilllv,dmg.flag,tick); + } + // Hell Inferno burning status only starts if Fire part hits. + if( skillid == WL_HELLINFERNO && dmg.damage > 0 ) + sc_start4(bl,SC_BURNING,55+5*skilllv,skilllv,1000,src->id,0,skill_get_time(skillid,skilllv)); + // Apply knock back chance in SC_TRIANGLESHOT skill. + else if( skillid == SC_TRIANGLESHOT && rnd()%100 > (1 + skilllv) ) + dmg.blewcount = 0; + + //Only knockback if it's still alive, otherwise a "ghost" is left behind. [Skotlex] + //Reflected spells do not bounce back (bl == dsrc since it only happens for direct skills) + if (dmg.blewcount > 0 && bl!=dsrc && !status_isdead(bl)) { + int direction = -1; // default + switch(skillid) {//direction + case MG_FIREWALL: + case PR_SANCTUARY: + case SC_TRIANGLESHOT: + case LG_OVERBRAND: + case SR_KNUCKLEARROW: + case GN_WALLOFTHORN: + case EL_FIRE_MANTLE: + direction = unit_getdir(bl);// backwards + break; + // This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics. + case WZ_STORMGUST: + direction = rand()%8; + break; + case WL_CRIMSONROCK: + direction = map_calc_dir(bl,skill_area_temp[4],skill_area_temp[5]); + break; + + } + //blown-specific handling + switch( skillid ) { + case LG_OVERBRAND: + if( skill_blown(dsrc,bl,dmg.blewcount,direction,0) ) { + short dir_x, dir_y; + dir_x = dirx[(direction+4)%8]; + dir_y = diry[(direction+4)%8]; + if( map_getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0 ) + skill_addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skilllv, BF_WEAPON, flag ); + } else + skill_addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skilllv, BF_WEAPON, flag ); + break; + case SR_KNUCKLEARROW: + if( skill_blown(dsrc,bl,dmg.blewcount,direction,0) && !(flag&4) ) { + short dir_x, dir_y; + dir_x = dirx[(direction+4)%8]; + dir_y = diry[(direction+4)%8]; + if( map_getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0 ) + skill_addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag|4); + } + break; + case GN_WALLOFTHORN: + unit_stop_walking(bl,1); + skill_blown(dsrc,bl,dmg.blewcount,direction, 0x2 ); + clif_fixpos(bl); + break; + default: + skill_blown(dsrc,bl,dmg.blewcount,direction, 0x0 ); + if ( !dmg.blewcount && bl->type == BL_SKILL && damage > 0 ){ + TBL_SKILL *su = (TBL_SKILL*)bl; + if( su->group && su->group->skill_id == HT_BLASTMINE) + skill_blown(src, bl, 3, -1, 0); + } + break; + } + } + + //Delayed damage must be dealt after the knockback (it needs to know actual position of target) + if (dmg.amotion) + battle_delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skillid,skilllv,damage,dmg.dmg_lv,dmg.dmotion); + + if( sc && sc->data[SC_DEVOTION] && skillid != PA_PRESSURE ) + { + struct status_change_entry *sce = sc->data[SC_DEVOTION]; + struct block_list *d_bl = map_id2bl(sce->val1); + + if( d_bl && ( + (d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id) || + (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == bl->id) + ) && check_distance_bl(bl, d_bl, sce->val3) ) + { + /** + * Check for devotion and change targetted dmg. + * [d_bl = paladin; bl = player; src = source of dmg] + **/ + bool devo_flag = false; /* false = paladin devoing; true = player */ + if ( src ) + { + struct status_change *tsc; + tsc = status_get_sc(src); + + /* Per official standards, following skills should reflect at the bl */ + if( (tsc->data[SC_KAITE] && attack_type == BF_MAGIC) || + (tsc->data[SC_REFLECTDAMAGE] && attack_type != BF_MAGIC) + ) + devo_flag = true; + } + + clif_damage( + ( (devo_flag) ? bl:d_bl), + ( (devo_flag) ? bl:d_bl), gettick(), 0, 0, damage, 0, 0, 0); + status_fix_damage( + ( (devo_flag) ? bl:NULL), + ( (devo_flag) ? bl:d_bl), damage, 0); + } + else { + status_change_end(bl, SC_DEVOTION, INVALID_TIMER); + if( !dmg.amotion ) + status_fix_damage(src,bl,damage,dmg.dmotion); + } + } + + if(damage > 0 && !(tstatus->mode&MD_BOSS)) { + if( skillid == RG_INTIMIDATE ) { + int rate = 50 + skilllv * 5; + rate = rate + (status_get_lv(src) - status_get_lv(bl)); + if(rnd()%100 < rate) + skill_addtimerskill(src,tick + 800,bl->id,0,0,skillid,skilllv,0,flag); + } else if( skillid == SC_FATALMENACE ) + skill_addtimerskill(src,tick + 800,bl->id,skill_area_temp[4],skill_area_temp[5],skillid,skilllv,0,flag); + } + + if(skillid == CR_GRANDCROSS || skillid == NPC_GRANDDARKNESS) + dmg.flag |= BF_WEAPON; + + if( sd && src != bl && damage > 0 && ( dmg.flag&BF_WEAPON || + (dmg.flag&BF_MISC && (skillid == RA_CLUSTERBOMB || skillid == RA_FIRINGTRAP || skillid == RA_ICEBOUNDTRAP || skillid == RK_DRAGONBREATH)) ) ) + { + if (battle_config.left_cardfix_to_right) + battle_drain(sd, bl, dmg.damage, dmg.damage, tstatus->race, tstatus->mode&MD_BOSS); + else + battle_drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->mode&MD_BOSS); + } + + if( rdamage > 0 ) { + if( sc && sc->data[SC_REFLECTDAMAGE] ) { + if( src != bl )// Don't reflect your own damage (Grand Cross) + map_foreachinshootrange(battle_damage_area,bl,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,bl,dmg.amotion,sstatus->dmotion,rdamage,tstatus->race); + } else { + if( dmg.amotion ) + battle_delay_damage(tick, dmg.amotion,bl,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,0); + else + status_fix_damage(bl,src,rdamage,0); + clif_damage(src,src,tick, dmg.amotion,0,rdamage,1,4,0); // in aegis damage reflected is shown in single hit. + //Use Reflect Shield to signal this kind of skill trigger. [Skotlex] + if( tsd && src != bl ) + battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); + skill_additional_effect(bl, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); + } + } + if( damage > 0 ) { + /** + * Post-damage effects + **/ + switch( skillid ) { + case RK_CRUSHSTRIKE: + skill_break_equip(src,EQP_WEAPON,2000,BCT_SELF); // 20% chance to destroy the weapon. + break; + case GC_VENOMPRESSURE: { + struct status_change *ssc = status_get_sc(src); + if( ssc && ssc->data[SC_POISONINGWEAPON] && rnd()%100 < 70 + 5*skilllv ) { + sc_start(bl,ssc->data[SC_POISONINGWEAPON]->val2,100,ssc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1)); + status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + } + break; + case WM_METALICSOUND: + status_zap(bl, 0, damage*100/(100*(110-pc_checkskill(sd,WM_LESSON)*10))); + break; + case SR_TIGERCANNON: + status_zap(bl, 0, damage/10); // 10% of damage dealt + break; + } + if( sd ) + skill_onskillusage(sd, bl, skillid, tick); + } + + if (!(flag&2) && + ( + skillid == MG_COLDBOLT || skillid == MG_FIREBOLT || skillid == MG_LIGHTNINGBOLT + ) && + (sc = status_get_sc(src)) && + sc->data[SC_DOUBLECAST] && + rnd() % 100 < sc->data[SC_DOUBLECAST]->val2) + { +// skill_addtimerskill(src, tick + dmg.div_*dmg.amotion, bl->id, 0, 0, skillid, skilllv, BF_MAGIC, flag|2); + skill_addtimerskill(src, tick + dmg.amotion, bl->id, 0, 0, skillid, skilllv, BF_MAGIC, flag|2); + } + + map_freeblock_unlock(); + + return damage; } /*========================================== @@ -2903,179 +2760,181 @@ int skill_attack(int attack_type, struct block_list *src, struct block_list *dsr * then call func with source,target,skillid,skilllv,tick,flag *------------------------------------------*/ typedef int (*SkillFunc)(struct block_list *, struct block_list *, int, int, unsigned int, int); -int skill_area_sub(struct block_list *bl, va_list ap) +int skill_area_sub (struct block_list *bl, va_list ap) { - struct block_list *src; - int skill_id,skill_lv,flag; - unsigned int tick; - SkillFunc func; - - nullpo_ret(bl); - - src=va_arg(ap,struct block_list *); - skill_id=va_arg(ap,int); - skill_lv=va_arg(ap,int); - tick=va_arg(ap,unsigned int); - flag=va_arg(ap,int); - func=va_arg(ap,SkillFunc); - - if (battle_check_target(src,bl,flag) > 0) { - // several splash skills need this initial dummy packet to display correctly - if (flag&SD_PREAMBLE && skill_area_temp[2] == 0) - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - - if (flag&(SD_SPLASH|SD_PREAMBLE)) - skill_area_temp[2]++; - - return func(src,bl,skill_id,skill_lv,tick,flag); - } - return 0; + struct block_list *src; + int skill_id,skill_lv,flag; + unsigned int tick; + SkillFunc func; + + nullpo_ret(bl); + + src=va_arg(ap,struct block_list *); + skill_id=va_arg(ap,int); + skill_lv=va_arg(ap,int); + tick=va_arg(ap,unsigned int); + flag=va_arg(ap,int); + func=va_arg(ap,SkillFunc); + + if(battle_check_target(src,bl,flag) > 0) + { + // several splash skills need this initial dummy packet to display correctly + if (flag&SD_PREAMBLE && skill_area_temp[2] == 0) + clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + + if (flag&(SD_SPLASH|SD_PREAMBLE)) + skill_area_temp[2]++; + + return func(src,bl,skill_id,skill_lv,tick,flag); + } + return 0; } -static int skill_check_unit_range_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 skillid,g_skillid; - - unit = (struct skill_unit *)bl; - - if (bl->prev == NULL || bl->type != BL_SKILL) - return 0; - - if (!unit->alive) - return 0; - - skillid = va_arg(ap,int); - g_skillid = unit->group->skill_id; - - switch (skillid) { - case MH_STEINWAND: - case MG_SAFETYWALL: - case AL_PNEUMA: - case SC_MAELSTROM: - if (g_skillid != MH_STEINWAND && g_skillid != MG_SAFETYWALL && g_skillid != AL_PNEUMA && g_skillid != SC_MAELSTROM) - return 0; - break; - case AL_WARP: - case HT_SKIDTRAP: - case MA_SKIDTRAP: - case HT_LANDMINE: - case MA_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case MA_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case HT_TALKIEBOX: - case HP_BASILICA: - case RA_ELECTRICSHOCKER: - case RA_CLUSTERBOMB: - case RA_MAGENTATRAP: - case RA_COBALTTRAP: - case RA_MAIZETRAP: - case RA_VERDURETRAP: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - case SC_DIMENSIONDOOR: - case SC_BLOODYLUST: - //Non stackable on themselves and traps (including venom dust which does not has the trap inf2 set) - if (skillid != g_skillid && !(skill_get_inf2(g_skillid)&INF2_TRAP) && g_skillid != AS_VENOMDUST && g_skillid != MH_POISON_MIST) - return 0; - break; - default: //Avoid stacking with same kind of trap. [Skotlex] - if (g_skillid != skillid) - return 0; - break; - } + struct skill_unit *unit; + int skillid,g_skillid; + + unit = (struct skill_unit *)bl; + + if(bl->prev == NULL || bl->type != BL_SKILL) + return 0; + + if(!unit->alive) + return 0; + + skillid = va_arg(ap,int); + g_skillid = unit->group->skill_id; + + switch (skillid) { + case MH_STEINWAND: + case MG_SAFETYWALL: + case AL_PNEUMA: + case SC_MAELSTROM: + if(g_skillid != MH_STEINWAND && g_skillid != MG_SAFETYWALL && g_skillid != AL_PNEUMA && g_skillid != SC_MAELSTROM) + return 0; + break; + case AL_WARP: + case HT_SKIDTRAP: + case MA_SKIDTRAP: + case HT_LANDMINE: + case MA_LANDMINE: + case HT_ANKLESNARE: + case HT_SHOCKWAVE: + case HT_SANDMAN: + case MA_SANDMAN: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + case HT_TALKIEBOX: + case HP_BASILICA: + case RA_ELECTRICSHOCKER: + case RA_CLUSTERBOMB: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + case SC_DIMENSIONDOOR: + case SC_BLOODYLUST: + //Non stackable on themselves and traps (including venom dust which does not has the trap inf2 set) + if (skillid != g_skillid && !(skill_get_inf2(g_skillid)&INF2_TRAP) && g_skillid != AS_VENOMDUST && g_skillid != MH_POISON_MIST) + return 0; + break; + default: //Avoid stacking with same kind of trap. [Skotlex] + if (g_skillid != skillid) + return 0; + break; + } - return 1; + return 1; } -static int skill_check_unit_range(struct block_list *bl, int x, int y, int skillid, int skilllv) +static int skill_check_unit_range (struct block_list *bl, int x, int y, int skillid, int skilllv) { - //Non players do not check for the skill's splash-trigger area. - int range = bl->type==BL_PC?skill_get_unit_range(skillid, skilllv):0; - int layout_type = skill_get_unit_layout_type(skillid,skilllv); - if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { - ShowError("skill_check_unit_range: unsupported layout type %d for skill %d\n",layout_type,skillid); - return 0; - } - - range += layout_type; - return map_foreachinarea(skill_check_unit_range_sub,bl->m,x-range,y-range,x+range,y+range,BL_SKILL,skillid); + //Non players do not check for the skill's splash-trigger area. + int range = bl->type==BL_PC?skill_get_unit_range(skillid, skilllv):0; + int layout_type = skill_get_unit_layout_type(skillid,skilllv); + if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { + ShowError("skill_check_unit_range: unsupported layout type %d for skill %d\n",layout_type,skillid); + return 0; + } + + range += layout_type; + return map_foreachinarea(skill_check_unit_range_sub,bl->m,x-range,y-range,x+range,y+range,BL_SKILL,skillid); } -static int skill_check_unit_range2_sub(struct block_list *bl, va_list ap) +static int skill_check_unit_range2_sub (struct block_list *bl, va_list ap) { - int skillid; + int skillid; - if (bl->prev == NULL) - return 0; + if(bl->prev == NULL) + return 0; - skillid = va_arg(ap,int); + skillid = va_arg(ap,int); - if (status_isdead(bl) && skillid != AL_WARP) - return 0; + if( status_isdead(bl) && skillid != AL_WARP ) + return 0; - if (skillid == HP_BASILICA && bl->type == BL_PC) - return 0; + if( skillid == HP_BASILICA && bl->type == BL_PC ) + return 0; - if (skillid == AM_DEMONSTRATION && bl->type == BL_MOB && ((TBL_MOB *)bl)->class_ == MOBID_EMPERIUM) - return 0; //Allow casting Bomb/Demonstration Right under emperium [Skotlex] - return 1; + if( skillid == AM_DEMONSTRATION && bl->type == BL_MOB && ((TBL_MOB*)bl)->class_ == MOBID_EMPERIUM ) + return 0; //Allow casting Bomb/Demonstration Right under emperium [Skotlex] + return 1; } -static int skill_check_unit_range2(struct block_list *bl, int x, int y, int skillid, int skilllv) +static int skill_check_unit_range2 (struct block_list *bl, int x, int y, int skillid, int skilllv) { - int range, type; + int 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) { + ShowError("skill_check_unit_range2: unsupported layout type %d for skill %d\n",layout_type,skillid); + return 0; + } + range = skill_get_unit_range(skillid,skilllv) + layout_type; + } + break; + } - 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) { - ShowError("skill_check_unit_range2: unsupported layout type %d for skill %d\n",layout_type,skillid); - return 0; - } - range = skill_get_unit_range(skillid,skilllv) + layout_type; - } - break; - } - - // if the caster is a monster/NPC, only check for players - // otherwise just check characters - if (bl->type == BL_PC) - type = BL_CHAR; - else - type = BL_PC; - - return map_foreachinarea(skill_check_unit_range2_sub, bl->m, - x - range, y - range, x + range, y + range, - type, skillid); + // if the caster is a monster/NPC, only check for players + // otherwise just check characters + if (bl->type == BL_PC) + type = BL_CHAR; + else + type = BL_PC; + + return map_foreachinarea(skill_check_unit_range2_sub, bl->m, + x - range, y - range, x + range, y + range, + type, skillid); } -int skill_guildaura_sub(struct map_session_data *sd, int id, int strvit, int agidex) +int skill_guildaura_sub (struct map_session_data* sd, int id, int strvit, int agidex) { - if (id == sd->bl.id && battle_config.guild_aura&16) - return 0; // Do not affect guild leader - - if (sd->sc.data[SC_GUILDAURA]) { - struct status_change_entry *sce = sd->sc.data[SC_GUILDAURA]; - if (sce->val3 != strvit || sce->val4 != agidex) { - sce->val3 = strvit; - sce->val4 = agidex; - status_calc_bl(&sd->bl, status_sc2scb_flag(SC_GUILDAURA)); - } - return 0; - } - sc_start4(&sd->bl, SC_GUILDAURA,100, 1, id, strvit, agidex, 1000); - return 1; + if(id == sd->bl.id && battle_config.guild_aura&16) + return 0; // Do not affect guild leader + + if (sd->sc.data[SC_GUILDAURA]) { + struct status_change_entry *sce = sd->sc.data[SC_GUILDAURA]; + if( sce->val3 != strvit || sce->val4 != agidex ) { + sce->val3 = strvit; + sce->val4 = agidex; + status_calc_bl(&sd->bl, status_sc2scb_flag(SC_GUILDAURA)); + } + return 0; + } + sc_start4(&sd->bl, SC_GUILDAURA,100, 1, id, strvit, agidex, 1000); + return 1; } /*========================================== @@ -3086,118 +2945,125 @@ int skill_guildaura_sub(struct map_session_data *sd, int id, int strvit, int agi *------------------------------------------*/ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int lv, int type) { - struct status_data *status; - struct map_session_data *sd = NULL; - int i, j, hp, sp, hp_rate, sp_rate, state, mhp; - int itemid[MAX_SKILL_ITEM_REQUIRE],amount[ARRAYLENGTH(itemid)],index[ARRAYLENGTH(itemid)]; - - if (lv < 1 || lv > MAX_SKILL_LEVEL) - return 0; - nullpo_ret(bl); - - switch (bl->type) { - case BL_HOM: - sd = ((TBL_HOM *)bl)->master; - break; - case BL_MER: - sd = ((TBL_MER *)bl)->master; - break; - } - - status = status_get_status_data(bl); - if ((j = skill_get_index(skill)) == 0) - return 0; - - // Requeriments - for (i = 0; i < ARRAYLENGTH(itemid); i++) { - itemid[i] = skill_db[j].itemid[i]; - amount[i] = skill_db[j].amount[i]; - } - hp = skill_db[j].hp[lv-1]; - sp = skill_db[j].sp[lv-1]; - hp_rate = skill_db[j].hp_rate[lv-1]; - sp_rate = skill_db[j].sp_rate[lv-1]; - state = skill_db[j].state; - if ((mhp = skill_db[j].mhp[lv-1]) > 0) - hp += (status->max_hp * mhp) / 100; - if (hp_rate > 0) - hp += (status->hp * hp_rate) / 100; - else - hp += (status->max_hp * (-hp_rate)) / 100; - if (sp_rate > 0) - sp += (status->sp * sp_rate) / 100; - else - sp += (status->max_sp * (-sp_rate)) / 100; - - if (bl->type == BL_HOM) { - // Intimacy Requeriments - struct homun_data *hd = BL_CAST(BL_HOM, bl); - switch (skill) { - case HFLI_SBR44: - if (hd->homunculus.intimacy <= 200) - return 0; - break; - case HVAN_EXPLOSION: - if (hd->homunculus.intimacy < (unsigned int)battle_config.hvan_explosion_intimate) - return 0; - break; - } - } - - if (!(type&2)) { - if (hp > 0 && status->hp <= (unsigned int)hp) { - clif_skill_fail(sd, skill, USESKILL_FAIL_HP_INSUFFICIENT, 0); - return 0; - } - if (sp > 0 && status->sp <= (unsigned int)sp) { - clif_skill_fail(sd, skill, USESKILL_FAIL_SP_INSUFFICIENT, 0); - return 0; - } - } - - if (!type) - switch (state) { - case ST_MOVE_ENABLE: - if (!unit_can_move(bl)) { - clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0); - return 0; - } - break; - } - if (!(type&1)) - return 1; - - // Check item existences - for (i = 0; i < ARRAYLENGTH(itemid); i++) { - index[i] = -1; - if (itemid[i] < 1) continue; // No item - index[i] = pc_search_inventory(sd, itemid[i]); - if (index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i]) { - clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0); - return 0; - } - } - - // Consume items - for (i = 0; i < ARRAYLENGTH(itemid); i++) { - if (index[i] >= 0) pc_delitem(sd, index[i], amount[i], 0, 1, LOG_TYPE_CONSUME); - } - - if (type&2) - return 1; - - if (sp || hp) - status_zap(bl, hp, sp); - - return 1; + struct status_data *status; + struct map_session_data *sd = NULL; + int i, j, hp, sp, hp_rate, sp_rate, state, mhp; + int itemid[MAX_SKILL_ITEM_REQUIRE],amount[ARRAYLENGTH(itemid)],index[ARRAYLENGTH(itemid)]; + + if( lv < 1 || lv > MAX_SKILL_LEVEL ) + return 0; + nullpo_ret(bl); + + switch( bl->type ) + { + case BL_HOM: sd = ((TBL_HOM*)bl)->master; break; + case BL_MER: sd = ((TBL_MER*)bl)->master; break; + } + + status = status_get_status_data(bl); + if( (j = skill_get_index(skill)) == 0 ) + return 0; + + // Requeriments + for( i = 0; i < ARRAYLENGTH(itemid); i++ ) + { + itemid[i] = skill_db[j].itemid[i]; + amount[i] = skill_db[j].amount[i]; + } + hp = skill_db[j].hp[lv-1]; + sp = skill_db[j].sp[lv-1]; + hp_rate = skill_db[j].hp_rate[lv-1]; + sp_rate = skill_db[j].sp_rate[lv-1]; + state = skill_db[j].state; + if( (mhp = skill_db[j].mhp[lv-1]) > 0 ) + hp += (status->max_hp * mhp) / 100; + if( hp_rate > 0 ) + hp += (status->hp * hp_rate) / 100; + else + hp += (status->max_hp * (-hp_rate)) / 100; + if( sp_rate > 0 ) + sp += (status->sp * sp_rate) / 100; + else + sp += (status->max_sp * (-sp_rate)) / 100; + + if( bl->type == BL_HOM ) + { // Intimacy Requeriments + struct homun_data *hd = BL_CAST(BL_HOM, bl); + switch( skill ) + { + case HFLI_SBR44: + if( hd->homunculus.intimacy <= 200 ) + return 0; + break; + case HVAN_EXPLOSION: + if( hd->homunculus.intimacy < (unsigned int)battle_config.hvan_explosion_intimate ) + return 0; + break; + } + } + + if( !(type&2) ) + { + if( hp > 0 && status->hp <= (unsigned int)hp ) + { + clif_skill_fail(sd, skill, USESKILL_FAIL_HP_INSUFFICIENT, 0); + return 0; + } + if( sp > 0 && status->sp <= (unsigned int)sp ) + { + clif_skill_fail(sd, skill, USESKILL_FAIL_SP_INSUFFICIENT, 0); + return 0; + } + } + + if( !type ) + switch( state ) + { + case ST_MOVE_ENABLE: + if( !unit_can_move(bl) ) + { + clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0); + return 0; + } + break; + } + if( !(type&1) ) + return 1; + + // Check item existences + for( i = 0; i < ARRAYLENGTH(itemid); i++ ) + { + index[i] = -1; + if( itemid[i] < 1 ) continue; // No item + index[i] = pc_search_inventory(sd, itemid[i]); + if( index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i] ) + { + clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0); + return 0; + } + } + + // Consume items + for( i = 0; i < ARRAYLENGTH(itemid); i++ ) + { + if( index[i] >= 0 ) pc_delitem(sd, index[i], amount[i], 0, 1, LOG_TYPE_CONSUME); + } + + if( type&2 ) + return 1; + + if( sp || hp ) + status_zap(bl, hp, sp); + + return 1; } /*========================================== * *------------------------------------------*/ -int skill_area_sub_count(struct block_list *src, struct block_list *target, int skillid, int skilllv, unsigned int tick, int flag) +int skill_area_sub_count (struct block_list *src, struct block_list *target, int skillid, int skilllv, unsigned int tick, int flag) { - return 1; + return 1; } /*========================================== @@ -3205,5922 +3071,5877 @@ int skill_area_sub_count(struct block_list *src, struct block_list *target, int *------------------------------------------*/ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *src = map_id2bl(id),*target; - struct unit_data *ud = unit_bl2ud(src); - struct skill_timerskill *skl = NULL; - int range; - - nullpo_ret(src); - nullpo_ret(ud); - skl = ud->skilltimerskill[data]; - nullpo_ret(skl); - ud->skilltimerskill[data] = NULL; - - do { - if (src->prev == NULL) - break; // Source not on Map - if (skl->target_id) { - target = map_id2bl(skl->target_id); - if ((skl->skill_id == RG_INTIMIDATE || skl->skill_id == SC_FATALMENACE) && (!target || target->prev == NULL || !check_distance_bl(src,target,AREA_SIZE))) - target = src; //Required since it has to warp. - if (target == NULL) - break; // Target offline? - if (target->prev == NULL) - break; // Target not on Map - if (src->m != target->m) - break; // Different Maps - if (status_isdead(src)) - break; // Caster is Dead - if (status_isdead(target) && skl->skill_id != RG_INTIMIDATE && skl->skill_id != WZ_WATERBALL) - break; - - switch (skl->skill_id) { - case RG_INTIMIDATE: - if (unit_warp(src,-1,-1,-1,CLR_TELEPORT) == 0) { - short x,y; - map_search_freecell(src, 0, &x, &y, 1, 1, 0); - if (target != src && !status_isdead(target)) - unit_warp(target, -1, x, y, CLR_TELEPORT); - } - break; - case BA_FROSTJOKER: - case DC_SCREAM: - range= skill_get_splash(skl->skill_id, skl->skill_lv); - map_foreachinarea(skill_frostjoke_scream,skl->map,skl->x-range,skl->y-range, - skl->x+range,skl->y+range,BL_CHAR,src,skl->skill_id,skl->skill_lv,tick); - break; - case NPC_EARTHQUAKE: - if (skl->type > 1) - skill_addtimerskill(src,tick+250,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); - skill_area_temp[0] = map_foreachinrange(skill_area_sub, src, skill_get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, src, skl->skill_id, skl->skill_lv, tick, BCT_ENEMY, skill_area_sub_count); - skill_area_temp[1] = src->id; - skill_area_temp[2] = 0; - map_foreachinrange(skill_area_sub, src, skill_get_splash(skl->skill_id, skl->skill_lv), splash_target(src), src, skl->skill_id, skl->skill_lv, tick, skl->flag, skill_castend_damage_id); - break; - case WZ_WATERBALL: - skill_toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify - if (!status_isdead(target)) - skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); - if (skl->type>1 && !status_isdead(target) && !status_isdead(src)) { - skill_addtimerskill(src,tick+125,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); - } else { - struct status_change *sc = status_get_sc(src); - if (sc) { - if (sc->data[SC_SPIRIT] && - sc->data[SC_SPIRIT]->val2 == SL_WIZARD && - sc->data[SC_SPIRIT]->val3 == skl->skill_id) - sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. - } - } - break; - /** - * Warlock - **/ - case WL_CHAINLIGHTNING_ATK: { - struct block_list *nbl = NULL; // Next Target of Chain - skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); // Hit a Lightning on the current Target - skill_toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify - if (skl->type > 1) { - // Remaining Chains Hit - nbl = battle_getenemyarea(src,target->x,target->y,2,BL_CHAR|BL_SKILL,target->id); // Search for a new Target around current one... - if (nbl == NULL && skl->x > 1) { - nbl = target; - skl->x--; - } else skl->x = 3; - } - - if (nbl) - skill_addtimerskill(src,tick+status_get_adelay(src),nbl->id,skl->x,0,WL_CHAINLIGHTNING_ATK,skl->skill_lv,skl->type-1,skl->flag); - } - break; - case WL_TETRAVORTEX_FIRE: - case WL_TETRAVORTEX_WATER: - case WL_TETRAVORTEX_WIND: - case WL_TETRAVORTEX_GROUND: - skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag|SD_ANIMATION); - skill_toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify - if (skl->type >= 3) { - // Final Hit - if (!status_isdead(target)) { - // Final Status Effect - int effects[4] = { SC_BURNING, SC_FREEZING, SC_BLEEDING, SC_STUN }, - applyeffects[4] = { 0, 0, 0, 0 }, - i, j = 0, k = 0; - for (i = 1; i <= 8; i = i + i) { - if (skl->x&i) { - applyeffects[j] = effects[k]; - j++; - } - k++; - } - if (j) { - i = applyeffects[rnd()%j]; - status_change_start(target, i, 10000, skl->skill_lv, - (i == SC_BURNING ? 1000 : 0), - (i == SC_BURNING ? src->id : 0), - 0, skill_get_time(WL_TETRAVORTEX,skl->skill_lv), 0); - } - } - } - break; - case WM_REVERBERATION_MELEE: - case WM_REVERBERATION_MAGIC: - skill_castend_damage_id(src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL); // damage should split among targets - break; - case SC_FATALMENACE: - if (src == target) // Casters Part - unit_warp(src, -1, skl->x, skl->y, 3); - else { // Target's Part - short x = skl->x, y = skl->y; - map_search_freecell(NULL, target->m, &x, &y, 2, 2, 1); - unit_warp(target,-1,x,y,3); - } - break; - case LG_MOONSLASHER: - case SR_WINDMILL: - if (target->type == BL_PC) { - struct map_session_data *tsd = NULL; - if ((tsd = ((TBL_PC *)target)) && !pc_issit(tsd)) { - pc_setsit(tsd); - skill_sit(tsd,1); - clif_sitting(&tsd->bl); - } - } - break; - case LG_OVERBRAND_BRANDISH: - case LG_OVERBRAND_PLUSATK: - case SR_KNUCKLEARROW: - skill_attack(BF_WEAPON, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL); - break; - case GN_SPORE_EXPLOSION: - map_foreachinrange(skill_area_sub, target, skill_get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, - src, skl->skill_id, skl->skill_lv, 0, skl->flag|1|BCT_ENEMY, skill_castend_damage_id); - break; - case CH_PALMSTRIKE: { - struct status_change *tsc = status_get_sc(target); - if (tsc && tsc->option&OPTION_HIDE) { - skill_blown(src,target,skill_get_blewcount(skl->skill_id, skl->skill_lv), -1, 0x0); - break; - } - } - default: - skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); - break; - } - } else { - if (src->m != skl->map) - break; - switch (skl->skill_id) { - case WZ_METEOR: - if (skl->type >= 0) { - int x = skl->type>>16, y = skl->type&0xFFFF; - if (path_search_long(NULL, src->m, src->x, src->y, x, y, CELL_CHKWALL)) - skill_unitsetting(src,skl->skill_id,skl->skill_lv,x,y,skl->flag); - if (path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL)) - clif_skill_poseffect(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,tick); - } else if (path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL)) - skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,skl->flag); - break; - case GN_CRAZYWEED_ATK: { - int dummy = 1, i = skill_get_unit_range(skl->skill_id,skl->skill_lv); - map_foreachinarea(skill_cell_overlap, src->m, skl->x-i, skl->y-i, skl->x+i, skl->y+i, BL_SKILL, skl->skill_id, &dummy, src); - } - case WL_EARTHSTRAIN: - skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,(skl->type<<16)|skl->flag); - break; + struct block_list *src = map_id2bl(id),*target; + struct unit_data *ud = unit_bl2ud(src); + struct skill_timerskill *skl = NULL; + int range; + + nullpo_ret(src); + nullpo_ret(ud); + skl = ud->skilltimerskill[data]; + nullpo_ret(skl); + ud->skilltimerskill[data] = NULL; + + do { + if(src->prev == NULL) + break; // Source not on Map + if(skl->target_id) { + target = map_id2bl(skl->target_id); + if( ( skl->skill_id == RG_INTIMIDATE || skl->skill_id == SC_FATALMENACE ) && (!target || target->prev == NULL || !check_distance_bl(src,target,AREA_SIZE)) ) + target = src; //Required since it has to warp. + if(target == NULL) + break; // Target offline? + if(target->prev == NULL) + break; // Target not on Map + if(src->m != target->m) + break; // Different Maps + if(status_isdead(src)) + break; // Caster is Dead + if(status_isdead(target) && skl->skill_id != RG_INTIMIDATE && skl->skill_id != WZ_WATERBALL) + break; + + switch(skl->skill_id) { + case RG_INTIMIDATE: + if (unit_warp(src,-1,-1,-1,CLR_TELEPORT) == 0) { + short x,y; + map_search_freecell(src, 0, &x, &y, 1, 1, 0); + if (target != src && !status_isdead(target)) + unit_warp(target, -1, x, y, CLR_TELEPORT); + } + break; + case BA_FROSTJOKER: + case DC_SCREAM: + range= skill_get_splash(skl->skill_id, skl->skill_lv); + map_foreachinarea(skill_frostjoke_scream,skl->map,skl->x-range,skl->y-range, + skl->x+range,skl->y+range,BL_CHAR,src,skl->skill_id,skl->skill_lv,tick); + break; + case NPC_EARTHQUAKE: + if( skl->type > 1 ) + skill_addtimerskill(src,tick+250,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); + skill_area_temp[0] = map_foreachinrange(skill_area_sub, src, skill_get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, src, skl->skill_id, skl->skill_lv, tick, BCT_ENEMY, skill_area_sub_count); + skill_area_temp[1] = src->id; + skill_area_temp[2] = 0; + map_foreachinrange(skill_area_sub, src, skill_get_splash(skl->skill_id, skl->skill_lv), splash_target(src), src, skl->skill_id, skl->skill_lv, tick, skl->flag, skill_castend_damage_id); + break; + case WZ_WATERBALL: + skill_toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify + if (!status_isdead(target)) + skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); + if (skl->type>1 && !status_isdead(target) && !status_isdead(src)) { + skill_addtimerskill(src,tick+125,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); + } else { + struct status_change *sc = status_get_sc(src); + if(sc) { + if(sc->data[SC_SPIRIT] && + sc->data[SC_SPIRIT]->val2 == SL_WIZARD && + sc->data[SC_SPIRIT]->val3 == skl->skill_id) + sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. + } + } + break; + /** + * Warlock + **/ + case WL_CHAINLIGHTNING_ATK: + { + struct block_list *nbl = NULL; // Next Target of Chain + skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); // Hit a Lightning on the current Target + skill_toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify + if( skl->type > 1 ) + { // Remaining Chains Hit + nbl = battle_getenemyarea(src,target->x,target->y,2,BL_CHAR|BL_SKILL,target->id); // Search for a new Target around current one... + if( nbl == NULL && skl->x > 1 ) + { + nbl = target; + skl->x--; + } + else skl->x = 3; + } + + if( nbl ) + skill_addtimerskill(src,tick+status_get_adelay(src),nbl->id,skl->x,0,WL_CHAINLIGHTNING_ATK,skl->skill_lv,skl->type-1,skl->flag); + } + break; + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag|SD_ANIMATION); + skill_toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify + if( skl->type >= 3 ) + { // Final Hit + if( !status_isdead(target) ) + { // Final Status Effect + int effects[4] = { SC_BURNING, SC_FREEZING, SC_BLEEDING, SC_STUN }, + applyeffects[4] = { 0, 0, 0, 0 }, + i, j = 0, k = 0; + for( i = 1; i <= 8; i = i + i ) + { + if( skl->x&i ) + { + applyeffects[j] = effects[k]; + j++; + } + k++; + } + if( j ) + { + i = applyeffects[rnd()%j]; + status_change_start(target, i, 10000, skl->skill_lv, + (i == SC_BURNING ? 1000 : 0), + (i == SC_BURNING ? src->id : 0), + 0, skill_get_time(WL_TETRAVORTEX,skl->skill_lv), 0); + } + } + } + break; + case WM_REVERBERATION_MELEE: + case WM_REVERBERATION_MAGIC: + skill_castend_damage_id(src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL); // damage should split among targets + break; + case SC_FATALMENACE: + if( src == target ) // Casters Part + unit_warp(src, -1, skl->x, skl->y, 3); + else { // Target's Part + short x = skl->x, y = skl->y; + map_search_freecell(NULL, target->m, &x, &y, 2, 2, 1); + unit_warp(target,-1,x,y,3); + } + break; + case LG_MOONSLASHER: + case SR_WINDMILL: + if( target->type == BL_PC ) { + struct map_session_data *tsd = NULL; + if( (tsd = ((TBL_PC*)target)) && !pc_issit(tsd) ) { + pc_setsit(tsd); + skill_sit(tsd,1); + clif_sitting(&tsd->bl); + } + } + break; + case LG_OVERBRAND_BRANDISH: + case LG_OVERBRAND_PLUSATK: + case SR_KNUCKLEARROW: + skill_attack(BF_WEAPON, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL); + break; + case GN_SPORE_EXPLOSION: + map_foreachinrange(skill_area_sub, target, skill_get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, + src, skl->skill_id, skl->skill_lv, 0, skl->flag|1|BCT_ENEMY, skill_castend_damage_id); + break; + case CH_PALMSTRIKE: + { + struct status_change* tsc = status_get_sc(target); + if( tsc && tsc->option&OPTION_HIDE ){ + skill_blown(src,target,skill_get_blewcount(skl->skill_id, skl->skill_lv), -1, 0x0 ); + break; + } + } + default: + skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); + break; + } + } + else { + if(src->m != skl->map) + break; + switch( skl->skill_id ) + { + case WZ_METEOR: + if( skl->type >= 0 ) + { + int x = skl->type>>16, y = skl->type&0xFFFF; + if( path_search_long(NULL, src->m, src->x, src->y, x, y, CELL_CHKWALL) ) + skill_unitsetting(src,skl->skill_id,skl->skill_lv,x,y,skl->flag); + if( path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) ) + clif_skill_poseffect(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,tick); + } + else if( path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) ) + skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,skl->flag); + break; + case GN_CRAZYWEED_ATK: + { + int dummy = 1, i = skill_get_unit_range(skl->skill_id,skl->skill_lv); + map_foreachinarea(skill_cell_overlap, src->m, skl->x-i, skl->y-i, skl->x+i, skl->y+i, BL_SKILL, skl->skill_id, &dummy, src); + } + case WL_EARTHSTRAIN: + skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,(skl->type<<16)|skl->flag); + break; - } - } - } while (0); - //Free skl now that it is no longer needed. - ers_free(skill_timer_ers, skl); - return 0; + } + } + } while (0); + //Free skl now that it is no longer needed. + ers_free(skill_timer_ers, skl); + return 0; } /*========================================== * *------------------------------------------*/ -int skill_addtimerskill(struct block_list *src, unsigned int tick, int target, int x,int y, int skill_id, int skill_lv, int type, int flag) +int skill_addtimerskill (struct block_list *src, unsigned int tick, int target, int x,int y, int skill_id, int skill_lv, int type, int flag) { - int i; - struct unit_data *ud; - nullpo_retr(1, src); - if (src->prev == NULL) - return 0; - ud = unit_bl2ud(src); - nullpo_retr(1, ud); - - ARR_FIND(0, MAX_SKILLTIMERSKILL, i, ud->skilltimerskill[i] == 0); - if (i == MAX_SKILLTIMERSKILL) return 1; - - ud->skilltimerskill[i] = ers_alloc(skill_timer_ers, struct skill_timerskill); - ud->skilltimerskill[i]->timer = add_timer(tick, skill_timerskill, src->id, i); - ud->skilltimerskill[i]->src_id = src->id; - ud->skilltimerskill[i]->target_id = target; - ud->skilltimerskill[i]->skill_id = skill_id; - ud->skilltimerskill[i]->skill_lv = skill_lv; - ud->skilltimerskill[i]->map = src->m; - ud->skilltimerskill[i]->x = x; - ud->skilltimerskill[i]->y = y; - ud->skilltimerskill[i]->type = type; - ud->skilltimerskill[i]->flag = flag; - return 0; + int i; + struct unit_data *ud; + nullpo_retr(1, src); + if (src->prev == NULL) + return 0; + ud = unit_bl2ud(src); + nullpo_retr(1, ud); + + ARR_FIND( 0, MAX_SKILLTIMERSKILL, i, ud->skilltimerskill[i] == 0 ); + if( i == MAX_SKILLTIMERSKILL ) return 1; + + ud->skilltimerskill[i] = ers_alloc(skill_timer_ers, struct skill_timerskill); + ud->skilltimerskill[i]->timer = add_timer(tick, skill_timerskill, src->id, i); + ud->skilltimerskill[i]->src_id = src->id; + ud->skilltimerskill[i]->target_id = target; + ud->skilltimerskill[i]->skill_id = skill_id; + ud->skilltimerskill[i]->skill_lv = skill_lv; + ud->skilltimerskill[i]->map = src->m; + ud->skilltimerskill[i]->x = x; + ud->skilltimerskill[i]->y = y; + ud->skilltimerskill[i]->type = type; + ud->skilltimerskill[i]->flag = flag; + return 0; } /*========================================== * *------------------------------------------*/ -int skill_cleartimerskill(struct block_list *src) +int skill_cleartimerskill (struct block_list *src) { - int i; - struct unit_data *ud; - nullpo_ret(src); - ud = unit_bl2ud(src); - nullpo_ret(ud); - - for (i=0; i<MAX_SKILLTIMERSKILL; i++) { - if (ud->skilltimerskill[i]) { - delete_timer(ud->skilltimerskill[i]->timer, skill_timerskill); - ers_free(skill_timer_ers, ud->skilltimerskill[i]); - ud->skilltimerskill[i]=NULL; - } - } - return 1; + int i; + struct unit_data *ud; + nullpo_ret(src); + ud = unit_bl2ud(src); + nullpo_ret(ud); + + for(i=0;i<MAX_SKILLTIMERSKILL;i++) { + if(ud->skilltimerskill[i]) { + delete_timer(ud->skilltimerskill[i]->timer, skill_timerskill); + ers_free(skill_timer_ers, ud->skilltimerskill[i]); + ud->skilltimerskill[i]=NULL; + } + } + return 1; } -static int skill_ative_reverberation(struct block_list *bl, va_list ap) -{ - struct skill_unit *su = (TBL_SKILL *)bl; - struct skill_unit_group *sg; - if (bl->type != BL_SKILL) - return 0; - if (su->alive && (sg = su->group) && sg->skill_id == WM_REVERBERATION) { - map_foreachinrange(skill_trap_splash, bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, gettick()); - su->limit=DIFF_TICK(gettick(),sg->tick); - sg->unit_id = UNT_USED_TRAPS; - } - return 0; +static int skill_ative_reverberation( struct block_list *bl, va_list ap) { + struct skill_unit *su = (TBL_SKILL*)bl; + struct skill_unit_group *sg; + if( bl->type != BL_SKILL ) + return 0; + if( su->alive && (sg = su->group) && sg->skill_id == WM_REVERBERATION ) { + map_foreachinrange(skill_trap_splash, bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, gettick()); + su->limit=DIFF_TICK(gettick(),sg->tick); + sg->unit_id = UNT_USED_TRAPS; + } + return 0; } -static int skill_reveal_trap(struct block_list *bl, va_list ap) +static int skill_reveal_trap (struct block_list *bl, va_list ap) { - TBL_SKILL *su = (TBL_SKILL *)bl; - if (su->alive && su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP) { - //Reveal trap. - //Change look is not good enough, the client ignores it as an actual trap still. [Skotlex] - //clif_changetraplook(bl, su->group->unit_id); - clif_skill_setunit(su); - return 1; - } - return 0; + TBL_SKILL *su = (TBL_SKILL*)bl; + if (su->alive && su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP) + { //Reveal trap. + //Change look is not good enough, the client ignores it as an actual trap still. [Skotlex] + //clif_changetraplook(bl, su->group->unit_id); + clif_skill_setunit(su); + return 1; + } + return 0; } /*========================================== * * *------------------------------------------*/ -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_data *tstatus; - struct status_change *sc; - - if (skillid > 0 && skilllv <= 0) return 0; - - nullpo_retr(1, src); - nullpo_retr(1, bl); - - if (src->m != bl->m) - return 1; - - if (bl->prev == NULL) - return 1; - - sd = BL_CAST(BL_PC, src); - - if (status_isdead(bl)) - return 1; - - if (skillid && skill_get_type(skillid) == BF_MAGIC && status_isimmune(bl) == 100) { - //GTB makes all targetted magic display miss with a single bolt. - sc_type sct = status_skill2sc(skillid); - if (sct != SC_NONE) - status_change_end(bl, sct, INVALID_TIMER); - clif_skill_damage(src, bl, tick, status_get_amotion(src), status_get_dmotion(bl), 0, 1, skillid, skilllv, skill_get_hit(skillid)); - return 1; - } - - sc = status_get_sc(src); - if (sc && !sc->count) - sc = NULL; //Unneeded - - tstatus = status_get_status_data(bl); - - map_freeblock_lock(); - - switch (skillid) { - case MER_CRASH: - case SM_BASH: - case MS_BASH: - case MC_MAMMONITE: - case TF_DOUBLE: - case AC_DOUBLE: - case MA_DOUBLE: - case AS_SONICBLOW: - case KN_PIERCE: - case ML_PIERCE: - case KN_SPEARBOOMERANG: - case TF_POISON: - case TF_SPRINKLESAND: - case AC_CHARGEARROW: - case MA_CHARGEARROW: - case RG_INTIMIDATE: - case AM_ACIDTERROR: - case BA_MUSICALSTRIKE: - case DC_THROWARROW: - case BA_DISSONANCE: - case CR_HOLYCROSS: - case NPC_DARKCROSS: - case CR_SHIELDCHARGE: - case CR_SHIELDBOOMERANG: - case NPC_PIERCINGATT: - case NPC_MENTALBREAKER: - case NPC_RANGEATTACK: - case NPC_CRITICALSLASH: - case NPC_COMBOATTACK: - case NPC_GUIDEDATTACK: - case NPC_POISON: - case NPC_RANDOMATTACK: - case NPC_WATERATTACK: - case NPC_GROUNDATTACK: - case NPC_FIREATTACK: - case NPC_WINDATTACK: - case NPC_POISONATTACK: - case NPC_HOLYATTACK: - case NPC_DARKNESSATTACK: - case NPC_TELEKINESISATTACK: - case NPC_UNDEADATTACK: - case NPC_ARMORBRAKE: - case NPC_WEAPONBRAKER: - case NPC_HELMBRAKE: - case NPC_SHIELDBRAKE: - case NPC_BLINDATTACK: - case NPC_SILENCEATTACK: - case NPC_STUNATTACK: - case NPC_PETRIFYATTACK: - case NPC_CURSEATTACK: - case NPC_SLEEPATTACK: - case LK_AURABLADE: - case LK_SPIRALPIERCE: - case ML_SPIRALPIERCE: - case LK_HEADCRUSH: - case CG_ARROWVULCAN: - case HW_MAGICCRASHER: - case ITM_TOMAHAWK: - case MO_TRIPLEATTACK: - case CH_CHAINCRUSH: - case CH_TIGERFIST: - case PA_SHIELDCHAIN: // Shield Chain - case PA_SACRIFICE: - case WS_CARTTERMINATION: // Cart Termination - case AS_VENOMKNIFE: - case HT_PHANTASMIC: - case HT_POWER: - case TK_DOWNKICK: - case TK_COUNTER: - case GS_CHAINACTION: - case GS_TRIPLEACTION: - case GS_MAGICALBULLET: - case GS_TRACKING: - case GS_PIERCINGSHOT: - case GS_RAPIDSHOWER: - case GS_DUST: - case GS_DISARM: // Added disarm. [Reddozen] - case GS_FULLBUSTER: - case NJ_SYURIKEN: - case NJ_KUNAI: - case ASC_BREAKER: - case HFLI_MOON: //[orn] - case HFLI_SBR44: //[orn] - case NPC_BLEEDING: - case NPC_CRITICALWOUND: - case NPC_HELLPOWER: - case RK_SONICWAVE: - case RK_HUNDREDSPEAR: - case AB_DUPLELIGHT_MELEE: - case RA_AIMEDBOLT: - case NC_AXEBOOMERANG: - case NC_POWERSWING: - case GC_CROSSIMPACT: - case GC_VENOMPRESSURE: - case SC_TRIANGLESHOT: - case SC_FEINTBOMB: - case LG_BANISHINGPOINT: - case LG_SHIELDPRESS: - case LG_RAGEBURST: - case LG_RAYOFGENESIS: - case LG_HESPERUSLIT: - case SR_FALLENEMPIRE: - case SR_CRESCENTELBOW_AUTOSPELL: - case SR_GATEOFHELL: - case SR_GENTLETOUCH_QUIET: - case WM_SEVERE_RAINSTORM_MELEE: - case WM_GREAT_ECHO: - case GN_SLINGITEM_RANGEMELEEATK: - case KO_JYUMONJIKIRI: - case KO_SETSUDAN: - case KO_KAIHOU: - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; - - /** - * Mechanic (MADO GEAR) - **/ - case NC_BOOSTKNUCKLE: - case NC_PILEBUNKER: - case NC_VULCANARM: - case NC_COLDSLOWER: - case NC_ARMSCANNON: - if (sd) pc_overheat(sd,1); - case RK_WINDCUTTER: - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag|SD_ANIMATION); - break; - - case LK_JOINTBEAT: // decide the ailment first (affects attack damage and effect) - switch (rnd()%6) { - case 0: - flag |= BREAK_ANKLE; - break; - case 1: - flag |= BREAK_WRIST; - break; - case 2: - flag |= BREAK_KNEE; - break; - case 3: - flag |= BREAK_SHOULDER; - break; - case 4: - flag |= BREAK_WAIST; - break; - case 5: - flag |= BREAK_NECK; - break; - } - //TODO: is there really no cleaner way to do this? - sc = status_get_sc(bl); - if (sc) sc->jb_flag = flag; - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; + struct map_session_data *sd = NULL; + struct status_data *tstatus; + struct status_change *sc; - case MO_COMBOFINISH: - if (!(flag&1) && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) { - //Becomes a splash attack when Soul Linked. - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skillid, skilllv),splash_target(src), - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - } else - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; + if (skillid > 0 && skilllv <= 0) return 0; - case TK_STORMKICK: // Taekwon kicks [Dralnu] - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_area_temp[1] = 0; - map_foreachinrange(skill_attack_area, src, - skill_get_splash(skillid, skilllv), splash_target(src), - BF_WEAPON, src, src, skillid, skilllv, tick, flag, BCT_ENEMY); - break; + nullpo_retr(1, src); + nullpo_retr(1, bl); - case KN_CHARGEATK: { - bool path = path_search_long(NULL, src->m, src->x, src->y, bl->x, bl->y,CELL_CHKWALL); - unsigned int dist = distance_bl(src, bl); - unsigned int dir = map_calc_dir(bl, src->x, src->y); - - // teleport to target (if not on WoE grounds) - if (!map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 0, 1)) - clif_slide(src, bl->x, bl->y); - - // cause damage and knockback if the path to target was a straight one - if (path) { - skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, dist); - skill_blown(src, bl, dist, dir, 0); - //HACK: since knockback officially defaults to the left, the client also turns to the left... therefore, - // make the caster look in the direction of the target - unit_setdir(src, (dir+4)%8); - } + if (src->m != bl->m) + return 1; - } - break; - - case NC_FLAMELAUNCHER: - if (sd) pc_overheat(sd,1); - case SN_SHARPSHOOTING: - case MA_SHARPSHOOTING: - case NJ_KAMAITACHI: - case LG_CANNONSPEAR: - //It won't shoot through walls since on castend there has to be a direct - //line of sight between caster and target. - skill_area_temp[1] = bl->id; - map_foreachinpath(skill_attack_area,src->m,src->x,src->y,bl->x,bl->y, - skill_get_splash(skillid, skilllv),skill_get_maxcount(skillid,skilllv), splash_target(src), - skill_get_type(skillid),src,src,skillid,skilllv,tick,flag,BCT_ENEMY); - break; + if (bl->prev == NULL) + return 1; - case NPC_ACIDBREATH: - case NPC_DARKNESSBREATH: - case NPC_FIREBREATH: - case NPC_ICEBREATH: - case NPC_THUNDERBREATH: - skill_area_temp[1] = bl->id; - map_foreachinpath(skill_attack_area,src->m,src->x,src->y,bl->x,bl->y, - skill_get_splash(skillid, skilllv),skill_get_maxcount(skillid,skilllv), splash_target(src), - skill_get_type(skillid),src,src,skillid,skilllv,tick,flag,BCT_ENEMY); - break; - - case MO_INVESTIGATE: - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); - break; - - case RG_BACKSTAP: { - int dir = map_calc_dir(src, bl->x, bl->y), t_dir = unit_getdir(bl); - if ((!check_distance_bl(src, bl, 0) && !map_check_dir(dir, t_dir)) || bl->type == BL_SKILL) { - status_change_end(src, SC_HIDING, INVALID_TIMER); - skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); - dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest] - unit_setdir(bl,dir); - } else if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } - break; + sd = BL_CAST(BL_PC, src); - case MO_FINGEROFFENSIVE: - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if (battle_config.finger_offensive_type && sd) { - int i; - for (i = 1; i < sd->spiritball_old; i++) - skill_addtimerskill(src, tick + i * 200, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag); - } - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); - break; + if (status_isdead(bl)) + return 1; - case MO_CHAINCOMBO: - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); - break; + if (skillid && skill_get_type(skillid) == BF_MAGIC && status_isimmune(bl) == 100) + { //GTB makes all targetted magic display miss with a single bolt. + sc_type sct = status_skill2sc(skillid); + if(sct != SC_NONE) + status_change_end(bl, sct, INVALID_TIMER); + clif_skill_damage(src, bl, tick, status_get_amotion(src), status_get_dmotion(bl), 0, 1, skillid, skilllv, skill_get_hit(skillid)); + return 1; + } - case NJ_ISSEN: - status_change_end(src, SC_NEN, INVALID_TIMER); - status_change_end(src, SC_HIDING, INVALID_TIMER); - // fall through - case MO_EXTREMITYFIST: - if (skillid == MO_EXTREMITYFIST) { - status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); + sc = status_get_sc(src); + if (sc && !sc->count) + sc = NULL; //Unneeded + + tstatus = status_get_status_data(bl); + + map_freeblock_lock(); + + switch(skillid) + { + case MER_CRASH: + case SM_BASH: + case MS_BASH: + case MC_MAMMONITE: + case TF_DOUBLE: + case AC_DOUBLE: + case MA_DOUBLE: + case AS_SONICBLOW: + case KN_PIERCE: + case ML_PIERCE: + case KN_SPEARBOOMERANG: + case TF_POISON: + case TF_SPRINKLESAND: + case AC_CHARGEARROW: + case MA_CHARGEARROW: + case RG_INTIMIDATE: + case AM_ACIDTERROR: + case BA_MUSICALSTRIKE: + case DC_THROWARROW: + case BA_DISSONANCE: + case CR_HOLYCROSS: + case NPC_DARKCROSS: + case CR_SHIELDCHARGE: + case CR_SHIELDBOOMERANG: + case NPC_PIERCINGATT: + case NPC_MENTALBREAKER: + case NPC_RANGEATTACK: + case NPC_CRITICALSLASH: + case NPC_COMBOATTACK: + case NPC_GUIDEDATTACK: + case NPC_POISON: + case NPC_RANDOMATTACK: + case NPC_WATERATTACK: + case NPC_GROUNDATTACK: + case NPC_FIREATTACK: + case NPC_WINDATTACK: + case NPC_POISONATTACK: + case NPC_HOLYATTACK: + case NPC_DARKNESSATTACK: + case NPC_TELEKINESISATTACK: + case NPC_UNDEADATTACK: + case NPC_ARMORBRAKE: + case NPC_WEAPONBRAKER: + case NPC_HELMBRAKE: + case NPC_SHIELDBRAKE: + case NPC_BLINDATTACK: + case NPC_SILENCEATTACK: + case NPC_STUNATTACK: + case NPC_PETRIFYATTACK: + case NPC_CURSEATTACK: + case NPC_SLEEPATTACK: + case LK_AURABLADE: + case LK_SPIRALPIERCE: + case ML_SPIRALPIERCE: + case LK_HEADCRUSH: + case CG_ARROWVULCAN: + case HW_MAGICCRASHER: + case ITM_TOMAHAWK: + case MO_TRIPLEATTACK: + case CH_CHAINCRUSH: + case CH_TIGERFIST: + case PA_SHIELDCHAIN: // Shield Chain + case PA_SACRIFICE: + case WS_CARTTERMINATION: // Cart Termination + case AS_VENOMKNIFE: + case HT_PHANTASMIC: + case HT_POWER: + case TK_DOWNKICK: + case TK_COUNTER: + case GS_CHAINACTION: + case GS_TRIPLEACTION: + case GS_MAGICALBULLET: + case GS_TRACKING: + case GS_PIERCINGSHOT: + case GS_RAPIDSHOWER: + case GS_DUST: + case GS_DISARM: // Added disarm. [Reddozen] + case GS_FULLBUSTER: + case NJ_SYURIKEN: + case NJ_KUNAI: + case ASC_BREAKER: + case HFLI_MOON: //[orn] + case HFLI_SBR44: //[orn] + case NPC_BLEEDING: + case NPC_CRITICALWOUND: + case NPC_HELLPOWER: + case RK_SONICWAVE: + case RK_HUNDREDSPEAR: + case AB_DUPLELIGHT_MELEE: + case RA_AIMEDBOLT: + case NC_AXEBOOMERANG: + case NC_POWERSWING: + case GC_CROSSIMPACT: + case GC_VENOMPRESSURE: + case SC_TRIANGLESHOT: + case SC_FEINTBOMB: + case LG_BANISHINGPOINT: + case LG_SHIELDPRESS: + case LG_RAGEBURST: + case LG_RAYOFGENESIS: + case LG_HESPERUSLIT: + case SR_FALLENEMPIRE: + case SR_CRESCENTELBOW_AUTOSPELL: + case SR_GATEOFHELL: + case SR_GENTLETOUCH_QUIET: + case WM_SEVERE_RAINSTORM_MELEE: + case WM_GREAT_ECHO: + case GN_SLINGITEM_RANGEMELEEATK: + case KO_JYUMONJIKIRI: + case KO_SETSUDAN: + case KO_KAIHOU: + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + break; + + /** + * Mechanic (MADO GEAR) + **/ + case NC_BOOSTKNUCKLE: + case NC_PILEBUNKER: + case NC_VULCANARM: + case NC_COLDSLOWER: + case NC_ARMSCANNON: + if (sd) pc_overheat(sd,1); + case RK_WINDCUTTER: + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag|SD_ANIMATION); + break; + + case LK_JOINTBEAT: // decide the ailment first (affects attack damage and effect) + switch( rnd()%6 ){ + case 0: flag |= BREAK_ANKLE; break; + case 1: flag |= BREAK_WRIST; break; + case 2: flag |= BREAK_KNEE; break; + case 3: flag |= BREAK_SHOULDER; break; + case 4: flag |= BREAK_WAIST; break; + case 5: flag |= BREAK_NECK; break; + } + //TODO: is there really no cleaner way to do this? + sc = status_get_sc(bl); + if (sc) sc->jb_flag = flag; + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + break; + + case MO_COMBOFINISH: + if (!(flag&1) && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) + { //Becomes a splash attack when Soul Linked. + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv),splash_target(src), + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); + } else + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + break; + + case TK_STORMKICK: // Taekwon kicks [Dralnu] + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_area_temp[1] = 0; + map_foreachinrange(skill_attack_area, src, + skill_get_splash(skillid, skilllv), splash_target(src), + BF_WEAPON, src, src, skillid, skilllv, tick, flag, BCT_ENEMY); + break; + + case KN_CHARGEATK: + { + bool path = path_search_long(NULL, src->m, src->x, src->y, bl->x, bl->y,CELL_CHKWALL); + unsigned int dist = distance_bl(src, bl); + unsigned int dir = map_calc_dir(bl, src->x, src->y); + + // teleport to target (if not on WoE grounds) + if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 0, 1) ) + clif_slide(src, bl->x, bl->y); + + // cause damage and knockback if the path to target was a straight one + if( path ) + { + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, dist); + skill_blown(src, bl, dist, dir, 0); + //HACK: since knockback officially defaults to the left, the client also turns to the left... therefore, + // make the caster look in the direction of the target + unit_setdir(src, (dir+4)%8); + } + + } + break; + + case NC_FLAMELAUNCHER: + if (sd) pc_overheat(sd,1); + case SN_SHARPSHOOTING: + case MA_SHARPSHOOTING: + case NJ_KAMAITACHI: + case LG_CANNONSPEAR: + //It won't shoot through walls since on castend there has to be a direct + //line of sight between caster and target. + skill_area_temp[1] = bl->id; + map_foreachinpath (skill_attack_area,src->m,src->x,src->y,bl->x,bl->y, + skill_get_splash(skillid, skilllv),skill_get_maxcount(skillid,skilllv), splash_target(src), + skill_get_type(skillid),src,src,skillid,skilllv,tick,flag,BCT_ENEMY); + break; + + case NPC_ACIDBREATH: + case NPC_DARKNESSBREATH: + case NPC_FIREBREATH: + case NPC_ICEBREATH: + case NPC_THUNDERBREATH: + skill_area_temp[1] = bl->id; + map_foreachinpath(skill_attack_area,src->m,src->x,src->y,bl->x,bl->y, + skill_get_splash(skillid, skilllv),skill_get_maxcount(skillid,skilllv), splash_target(src), + skill_get_type(skillid),src,src,skillid,skilllv,tick,flag,BCT_ENEMY); + break; + + case MO_INVESTIGATE: + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); + break; + + case RG_BACKSTAP: + { + int dir = map_calc_dir(src, bl->x, bl->y), t_dir = unit_getdir(bl); + if ((!check_distance_bl(src, bl, 0) && !map_check_dir(dir, t_dir)) || bl->type == BL_SKILL) { + status_change_end(src, SC_HIDING, INVALID_TIMER); + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); + dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest] + unit_setdir(bl,dir); + } + else if (sd) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } + break; + + case MO_FINGEROFFENSIVE: + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + if (battle_config.finger_offensive_type && sd) { + int i; + for (i = 1; i < sd->spiritball_old; i++) + skill_addtimerskill(src, tick + i * 200, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag); + } + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); + break; + + case MO_CHAINCOMBO: + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); + break; + + case NJ_ISSEN: + status_change_end(src, SC_NEN, INVALID_TIMER); + status_change_end(src, SC_HIDING, INVALID_TIMER); + // fall through + case MO_EXTREMITYFIST: + if( skillid == MO_EXTREMITYFIST ) + { + status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); #ifdef RENEWAL - sc_start(src,SC_EXTREMITYFIST2,100,skilllv,skill_get_time(skillid,skilllv)); + sc_start(src,SC_EXTREMITYFIST2,100,skilllv,skill_get_time(skillid,skilllv)); #endif - } - //Client expects you to move to target regardless of distance - { - struct unit_data *ud = unit_bl2ud(src); - short dx,dy; - int i,speed; - i = skillid == MO_EXTREMITYFIST?1:2; //Move 2 cells for Issen, 1 for Asura - dx = bl->x - src->x; - dy = bl->y - src->y; - if (dx < 0) dx-=i; - else if (dx > 0) dx+=i; - if (dy < 0) dy-=i; - else if (dy > 0) dy+=i; - if (!dx && !dy) dy++; - if (map_getcell(src->m, src->x+dx, src->y+dy, CELL_CHKNOPASS)) { - dx = bl->x; - dy = bl->y; - } else { - dx = src->x + dx; - dy = src->y + dy; - } - - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - - if (unit_walktoxy(src, dx, dy, 2) && ud) { - //Increase can't walk delay to not alter your walk path - ud->canmove_tick = tick; - speed = status_get_speed(src); - for (i = 0; i < ud->walkpath.path_len; i ++) { - if (ud->walkpath.path[i]&1) - ud->canmove_tick+=7*speed/5; - else - ud->canmove_tick+=speed; - } - } - } - break; - - //Splash attack skills. - case AS_GRIMTOOTH: - case MC_CARTREVOLUTION: - case NPC_SPLASHATTACK: - flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit - case AS_SPLASHER: - case SM_MAGNUM: - case MS_MAGNUM: - case HT_BLITZBEAT: - case AC_SHOWER: - case MA_SHOWER: - case MG_NAPALMBEAT: - case MG_FIREBALL: - case RG_RAID: - case HW_NAPALMVULCAN: - case NJ_HUUMA: - case NJ_BAKUENRYU: - case ASC_METEORASSAULT: - case GS_DESPERADO: - case GS_SPREADATTACK: - case NPC_EARTHQUAKE: - case NPC_PULSESTRIKE: - case NPC_HELLJUDGEMENT: - case NPC_VAMPIRE_GIFT: - case RK_IGNITIONBREAK: - case AB_JUDEX: - case WL_SOULEXPANSION: - case WL_CRIMSONROCK: - case WL_COMET: - case WL_JACKFROST: - case RA_ARROWSTORM: - case RA_WUGDASH: - case NC_SELFDESTRUCTION: - case NC_AXETORNADO: - case GC_ROLLINGCUTTER: - case GC_COUNTERSLASH: - case LG_MOONSLASHER: - case LG_EARTHDRIVE: - case SR_TIGERCANNON: - case SR_RAMPAGEBLASTER: - case SR_SKYNETBLOW: - case SR_WINDMILL: - case SR_RIDEINLIGHTNING: - case WM_SOUND_OF_DESTRUCTION: - case WM_REVERBERATION_MELEE: - case WM_REVERBERATION_MAGIC: - case SO_VARETYR_SPEAR: - case GN_CART_TORNADO: - case GN_CARTCANNON: - case KO_HAPPOKUNAI: - case KO_HUUMARANKA: - case KO_MUCHANAGE: - case KO_BAKURETSU: - if (flag&1) { //Recursive invocation - // skill_area_temp[0] holds number of targets in area - // skill_area_temp[1] holds the id of the original target - // skill_area_temp[2] counts how many targets have already been processed - int sflag = skill_area_temp[0] & 0xFFF, heal; - if (flag&SD_LEVEL) - sflag |= SD_LEVEL; // -1 will be used in packets instead of the skill level - if (skill_area_temp[1] != bl->id && !(skill_get_inf2(skillid)&INF2_NPC_SKILL)) - sflag |= SD_ANIMATION; // original target gets no animation (as well as all NPC skills) - - heal = skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, sflag); - if (skillid == NPC_VAMPIRE_GIFT && heal > 0) { - clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1); - status_heal(src,heal,0,0); - } - } else { - switch (skillid) { - case NJ_BAKUENRYU: - case LG_EARTHDRIVE: - case GN_CARTCANNON: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case LG_MOONSLASHER: - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - break; - case NPC_EARTHQUAKE://FIXME: Isn't EarthQuake a ground skill after all? - skill_addtimerskill(src,tick+250,src->id,0,0,skillid,skilllv,2,flag|BCT_ENEMY|SD_SPLASH|1); - default: - break; - } - - skill_area_temp[0] = 0; - skill_area_temp[1] = bl->id; - skill_area_temp[2] = 0; - if (skillid == WL_CRIMSONROCK) { - skill_area_temp[4] = bl->x; - skill_area_temp[5] = bl->y; - } - if (skillid == WM_REVERBERATION_MELEE || skillid == WM_REVERBERATION_MAGIC) - skill_area_temp[1] = 0; - // if skill damage should be split among targets, count them - //SD_LEVEL -> Forced splash damage for Auto Blitz-Beat -> count targets - //special case: Venom Splasher uses a different range for searching than for splashing - if (flag&SD_LEVEL || skill_get_nk(skillid)&NK_SPLASHSPLIT) - skill_area_temp[0] = map_foreachinrange(skill_area_sub, bl, (skillid == AS_SPLASHER)?1:skill_get_splash(skillid, skilllv), BL_CHAR, src, skillid, skilllv, tick, BCT_ENEMY, skill_area_sub_count); - - // recursive invocation of skill_castend_damage_id() with flag|1 - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), (skillid == WM_REVERBERATION_MELEE || skillid == WM_REVERBERATION_MAGIC)?BL_CHAR:splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); - } - break; - - case KN_BRANDISHSPEAR: - case ML_BRANDISH: - //Coded apart for it needs the flag passed to the damage calculation. - if (skill_area_temp[1] != bl->id) - skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag|SD_ANIMATION); - else - skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); - break; - - case KN_BOWLINGBASH: - case MS_BOWLINGBASH: - if (flag&1) { - if (bl->id==skill_area_temp[1]) - break; - //two hits for 500% - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,SD_ANIMATION); - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,SD_ANIMATION); - } else { - int i,c; - c = skill_get_blewcount(skillid,skilllv); - // keep moving target in the direction that src is looking, square by square - for (i=0; i<c; i++) { - if (!skill_blown(src,bl,1,(unit_getdir(src)+4)%8,0x1)) - break; //Can't knockback - skill_area_temp[0] = map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), BL_CHAR, src, skillid, skilllv, tick, flag|BCT_ENEMY, skill_area_sub_count); - if (skill_area_temp[0] > 1) break; // collision - } - clif_blown(bl); //Update target pos. - if (i!=c) { //Splash - skill_area_temp[1] = bl->id; - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id); - } - //Weirdo dual-hit property, two attacks for 500% - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0); - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0); - } - break; - - case KN_SPEARSTAB: - if (flag&1) { - if (bl->id==skill_area_temp[1]) - break; - if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,SD_ANIMATION)) - skill_blown(src,bl,skill_area_temp[2],-1,0); - } else { - int x=bl->x,y=bl->y,i,dir; - dir = map_calc_dir(bl,src->x,src->y); - skill_area_temp[1] = bl->id; - skill_area_temp[2] = skill_get_blewcount(skillid,skilllv); - // all the enemies between the caster and the target are hit, as well as the target - if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0)) - skill_blown(src,bl,skill_area_temp[2],-1,0); - for (i=0; i<4; i++) { - map_foreachincell(skill_area_sub,bl->m,x,y,BL_CHAR, - src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - x += dirx[dir]; - y += diry[dir]; - } - } - break; - - case TK_TURNKICK: - case MO_BALKYOUNG: { //Active part of the attack. Skill-attack [Skotlex] - skill_area_temp[1] = bl->id; //NOTE: This is used in skill_castend_nodamage_id to avoid affecting the target. - if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag)) - map_foreachinrange(skill_area_sub,bl, - skill_get_splash(skillid, skilllv),BL_CHAR, - src,skillid,skilllv,tick,flag|BCT_ENEMY|1, - skill_castend_nodamage_id); - } - break; - case CH_PALMSTRIKE: // Palm Strike takes effect 1sec after casting. [Skotlex] - // clif_skill_nodamage(src,bl,skillid,skilllv,0); //Can't make this one display the correct attack animation delay :/ - clif_damage(src,bl,tick,status_get_amotion(src),0,-1,1,4,0); //Display an absorbed damage attack. - skill_addtimerskill(src, tick + 1000, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag); - break; - - case PR_TURNUNDEAD: - case ALL_RESURRECTION: - if (!battle_check_undead(tstatus->race, tstatus->def_ele)) - break; - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - break; - - case MG_SOULSTRIKE: - case NPC_DARKSTRIKE: - case MG_COLDBOLT: - case MG_FIREBOLT: - case MG_LIGHTNINGBOLT: - case WZ_EARTHSPIKE: - case AL_HEAL: - case AL_HOLYLIGHT: - case WZ_JUPITEL: - case NPC_DARKTHUNDER: - case PR_ASPERSIO: - case MG_FROSTDIVER: - case WZ_SIGHTBLASTER: - case WZ_SIGHTRASHER: - case NJ_KOUENKA: - case NJ_HYOUSENSOU: - case NJ_HUUJIN: - case AB_ADORAMUS: - case AB_RENOVATIO: - case AB_HIGHNESSHEAL: - case AB_DUPLELIGHT_MAGIC: - case WM_METALICSOUND: - case MH_ERASER_CUTTER: - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - break; - - case NPC_MAGICALATTACK: - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - sc_start(src,status_skill2sc(skillid),100,skilllv,skill_get_time(skillid,skilllv)); - break; - - case HVAN_CAPRICE: { //[blackhole89] - int ran=rnd()%4; - int sid = 0; - switch (ran) { - case 0: - sid=MG_COLDBOLT; - break; - case 1: - sid=MG_FIREBOLT; - break; - case 2: - sid=MG_LIGHTNINGBOLT; - break; - case 3: - sid=WZ_EARTHSPIKE; - break; - } - skill_attack(BF_MAGIC,src,src,bl,sid,skilllv,tick,flag|SD_LEVEL); - } - break; - case WZ_WATERBALL: { - int range = skilllv / 2; - int maxlv = skill_get_max(skillid); // learnable level - int count = 0; - int x, y; - struct skill_unit *unit; - - if (skilllv > maxlv) { - if (src->type == BL_MOB && skilllv == 10) - range = 4; - else - range = maxlv / 2; - } - - for (y = src->y - range; y <= src->y + range; ++y) - for (x = src->x - range; x <= src->x + range; ++x) { - if (!map_find_skill_unit_oncell(src,x,y,SA_LANDPROTECTOR,NULL,1)) { - if (src->type != BL_PC || map_getcell(src->m,x,y,CELL_CHKWATER)) // non-players bypass the water requirement - count++; // natural water cell - else if ((unit = map_find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL,1)) != NULL || (unit = map_find_skill_unit_oncell(src,x,y,NJ_SUITON,NULL,1)) != NULL) { - count++; // skill-induced water cell - skill_delunit(unit); // consume cell - } - } - } - - if (count > 1) // queue the remaining count - 1 timerskill Waterballs - skill_addtimerskill(src,tick+150,bl->id,0,0,skillid,skilllv,count-1,flag); - } - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - break; - - case PR_BENEDICTIO: - //Should attack undead and demons. [Skotlex] - if (battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON) - skill_attack(BF_MAGIC, src, src, bl, skillid, skilllv, tick, flag); - break; - - case SL_SMA: - status_change_end(src, SC_SMA, INVALID_TIMER); - case SL_STIN: - case SL_STUN: - if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { - status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,10); - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - break; - - case NPC_DARKBREATH: - clif_emotion(src,E_AG); - case SN_FALCONASSAULT: - case PA_PRESSURE: - case CR_ACIDDEMONSTRATION: - case TF_THROWSTONE: - case NPC_SMOKING: - case GS_FLING: - case NJ_ZENYNAGE: - case GN_THORNS_TRAP: - case GN_HELLS_PLANT_ATK: - skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); - break; - /** - * Rune Knight - **/ - case RK_DRAGONBREATH: { - struct status_change *tsc = NULL; - if ((tsc = status_get_sc(bl)) && (tsc->data[SC_HIDING])) { - clif_skill_nodamage(src,src,skillid,skilllv,1); - } else - skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); - } - break; - - case NPC_SELFDESTRUCTION: { - struct status_change *tsc = NULL; - if ((tsc = status_get_sc(bl)) && tsc->data[SC_HIDING]) - break; - } - case HVAN_EXPLOSION: - if (src != bl) - skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); - break; - - // Celest - case PF_SOULBURN: - if (rnd()%100 < (skilllv < 5 ? 30 + skilllv * 10 : 70)) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (skilllv == 5) - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - status_percent_damage(src, bl, 0, 100, false); - } else { - clif_skill_nodamage(src,src,skillid,skilllv,1); - if (skilllv == 5) - skill_attack(BF_MAGIC,src,src,src,skillid,skilllv,tick,flag); - status_percent_damage(src, src, 0, 100, false); - } - break; - - case NPC_BLOODDRAIN: - case NPC_ENERGYDRAIN: { - int heal = skill_attack((skillid == NPC_BLOODDRAIN) ? BF_WEAPON : BF_MAGIC, - src, src, bl, skillid, skilllv, tick, flag); - if (heal > 0) { - clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1); - status_heal(src, heal, 0, 0); - } - } - break; - - case GS_BULLSEYE: - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; - - case NJ_KASUMIKIRI: - if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag) > 0) - sc_start(src,SC_HIDING,100,skilllv,skill_get_time(skillid,skilllv)); - break; - case NJ_KIRIKAGE: - if (!map_flag_gvg(src->m) && !map[src->m].flag.battleground) { - //You don't move on GVG grounds. - short x, y; - map_search_freecell(bl, 0, &x, &y, 1, 1, 0); - if (unit_movepos(src, x, y, 0, 0)) - clif_slide(src,src->x,src->y); - } - status_change_end(src, SC_HIDING, INVALID_TIMER); - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; - case RK_PHANTOMTHRUST: - unit_setdir(src,map_calc_dir(src, bl->x, bl->y)); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - - skill_blown(src,bl,distance_bl(src,bl)-1,unit_getdir(src),0); - if (battle_check_target(src,bl,BCT_ENEMY)) - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; - - case RK_STORMBLAST: - case RK_CRUSHSTRIKE: - if (sd) { - if (pc_checkskill(sd,RK_RUNEMASTERY) >= (skillid == RK_CRUSHSTRIKE ? 7 : 3)) - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - else - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } else //non-sd support - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; - case GC_DARKILLUSION: { - short x, y; - short dir = map_calc_dir(src,bl->x,bl->y); - - if (dir > 4) x = -1; - else if (dir > 0 && dir < 4) x = 1; - else x = 0; - if (dir < 3 || dir > 5) y = -1; - else if (dir > 3 && dir < 5) y = 1; - else y = 0; - - if (unit_movepos(src, bl->x+x, bl->y+y, 1, 1)) { - clif_slide(src,bl->x+x,bl->y+y); - clif_fixpos(src); // the official server send these two packts. - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - if (rnd()%100 < 4 * skilllv) - skill_castend_damage_id(src,bl,GC_CROSSIMPACT,skilllv,tick,flag); - } - - } - break; - - case GC_WEAPONCRUSH: - if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == GC_WEAPONBLOCKING) - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - else if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_GC_WEAPONBLOCKING,0); - break; - - case GC_CROSSRIPPERSLASHER: - if (sd && !(sc && sc->data[SC_ROLLINGCUTTER])) - clif_skill_fail(sd,skillid,USESKILL_FAIL_CONDITION,0); - else { - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - status_change_end(src,SC_ROLLINGCUTTER,INVALID_TIMER); - } - break; - - case GC_PHANTOMMENACE: - if (flag&1) { - // Only Hits Invisible Targets - struct status_change *tsc = status_get_sc(bl); - if (tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY])) - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - } - break; - case WL_CHAINLIGHTNING: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_addtimerskill(src,tick + 150,bl->id,3,0,WL_CHAINLIGHTNING_ATK,skilllv,4+skilllv,flag); - break; - case WL_DRAINLIFE: { - int heal = skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); - int rate = 70 + 5 * skilllv; - - heal = heal * (5 + 5 * skilllv) / 100; - - if (bl->type == BL_SKILL) - heal = 0; // Don't absorb heal from Ice Walls or other skill units. - - if (heal && rnd()%100 < rate) { - status_heal(src, heal, 0, 0); - clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1); - } - } - break; - - case WL_TETRAVORTEX: - if (sd) { - int spheres[5] = { 0, 0, 0, 0, 0 }, - positions[5] = {-1,-1,-1,-1,-1 }, - i, j = 0, k, subskill = 0; - - for (i = SC_SPHERE_1; i <= SC_SPHERE_5; i++) - if (sc && sc->data[i]) { - spheres[j] = i; - positions[j] = sc->data[i]->val2; - j++; // - } - - if (j < 4) { - // Need 4 spheres minimum - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - - // Sphere Sort, this time from new to old - for (i = 0; i <= j - 2; i++) - for (k = i + 1; k <= j - 1; k++) - if (positions[i] < positions[k]) { - swap(positions[i],positions[k]); - swap(spheres[i],spheres[k]); - } - - k = 0; - for (i = 0; i < 4; i++) { - switch (sc->data[spheres[i]]->val1) { - case WLS_FIRE: - subskill = WL_TETRAVORTEX_FIRE; - k |= 1; - break; - case WLS_WIND: - subskill = WL_TETRAVORTEX_WIND; - k |= 4; - break; - case WLS_WATER: - subskill = WL_TETRAVORTEX_WATER; - k |= 2; - break; - case WLS_STONE: - subskill = WL_TETRAVORTEX_GROUND; - k |= 8; - break; - } - skill_addtimerskill(src, tick + i * 200, bl->id, k, 0, subskill, skilllv, i, flag); - clif_skill_nodamage(src, bl, subskill, skilllv, 1); - status_change_end(src, spheres[i], INVALID_TIMER); - } - } - break; - - case WL_RELEASE: - if (sd) { - int i; - // Priority is to release SpellBook - if (sc && sc->data[SC_READING_SB]) { - // SpellBook - int skill_id, skill_lv, point, s = 0; - int spell[SC_MAXSPELLBOOK-SC_SPELLBOOK1 + 1]; - - for (i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) // List all available spell to be released - if (sc->data[i]) spell[s++] = i; - - if (s == 0) - break; - - i = spell[s==1?0:rand()%s];// Random select of spell to be released. - if (s && sc->data[i]) {// Now extract the data from the preserved spell - skill_id = sc->data[i]->val1; - skill_lv = sc->data[i]->val2; - point = sc->data[i]->val3; - status_change_end(src, (sc_type)i, INVALID_TIMER); - } else //something went wrong :( - break; - - if (sc->data[SC_READING_SB]->val2 > point) - sc->data[SC_READING_SB]->val2 -= point; - else // Last spell to be released - status_change_end(src, SC_READING_SB, INVALID_TIMER); - - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - if (!skill_check_condition_castbegin(sd, skill_id, skill_lv)) - break; - - switch (skill_get_casttype(skill_id)) { - case CAST_GROUND: - skill_castend_pos2(src, bl->x, bl->y, skill_id, skill_lv, tick, 0); - break; - case CAST_NODAMAGE: - skill_castend_nodamage_id(src, bl, skill_id, skill_lv, tick, 0); - break; - case CAST_DAMAGE: - skill_castend_damage_id(src, bl, skill_id, skill_lv, tick, 0); - break; - } - - sd->ud.canact_tick = tick + skill_delayfix(src, skill_id, skill_lv); - clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, skill_id, skill_lv), 0, 0, 0); - } else { - // Summon Balls - int j = 0, k, skele; - int spheres[5] = { 0, 0, 0, 0, 0 }, - positions[5] = {-1,-1,-1,-1,-1 }; - - for (i = SC_SPHERE_1; i <= SC_SPHERE_5; i++) - if (sc && sc->data[i]) { - spheres[j] = i; - positions[j] = sc->data[i]->val2; - sc->data[i]->val2--; // Prepares for next position - j++; - } - - if (j == 0) { - // No Spheres - clif_skill_fail(sd,skillid,USESKILL_FAIL_SUMMON_NONE,0); - break; - } - - // Sphere Sort - for (i = 0; i <= j - 2; i++) - for (k = i + 1; k <= j - 1; k++) - if (positions[i] > positions[k]) { - swap(positions[i],positions[k]); - swap(spheres[i],spheres[k]); - } - - if (skilllv == 1) j = 1; // Limit only to one ball - for (i = 0; i < j; i++) { - skele = WL_RELEASE - 5 + sc->data[spheres[i]]->val1 - WLS_FIRE; // Convert Ball Element into Skill ATK for balls - // WL_SUMMON_ATK_FIRE, WL_SUMMON_ATK_WIND, WL_SUMMON_ATK_WATER, WL_SUMMON_ATK_GROUND - skill_addtimerskill(src,tick+status_get_adelay(src)*i,bl->id,0,0,skele,sc->data[spheres[i]]->val3,BF_MAGIC,flag|SD_LEVEL); - status_change_end(src, spheres[i], INVALID_TIMER); // Eliminate ball - } - clif_skill_nodamage(src,bl,skillid,0,1); - } - } - break; - case WL_FROSTMISTY: - // Causes Freezing status through walls. - sc_start(bl,status_skill2sc(skillid),20+12*skilllv+(sd ? sd->status.job_level : 50)/5,skilllv,skill_get_time(skillid,skilllv)); - // Doesn't deal damage through non-shootable walls. - if (path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKWALL)) - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag|SD_ANIMATION); - break; - case WL_HELLINFERNO: - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag|ELE_DARK); - break; - case RA_WUGSTRIKE: - if (sd && pc_isridingwug(sd)) { - short x[8]= {0,-1,-1,-1,0,1,1,1}; - short y[8]= {1,1,0,-1,-1,-1,0,1}; - int dir = map_calc_dir(bl, src->x, src->y); - - if (unit_movepos(src, bl->x+x[dir], bl->y+y[dir], 1, 1)) { - clif_slide(src, bl->x+x[dir], bl->y+y[dir]); - clif_fixpos(src); - skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); - } - break; - } - case RA_WUGBITE: - if (path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH)) { - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - } else if (sd && skillid == RA_WUGBITE) // Only RA_WUGBITE has the skill fail message. - clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); - - break; - - case RA_SENSITIVEKEEN: - if (bl->type != BL_SKILL) { // Only Hits Invisible Targets - struct status_change *tsc = status_get_sc(bl); - if (tsc && tsc->option&(OPTION_HIDE|OPTION_CLOAK)) { - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - } - } else { - struct skill_unit *su = BL_CAST(BL_SKILL,bl); - struct skill_unit_group *sg; - - if (su && (sg=su->group) && skill_get_inf2(sg->skill_id)&INF2_TRAP) { - if (!(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0))) { - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = sg->item_id?sg->item_id:ITEMID_TRAP; - item_tmp.identify = 1; - if (item_tmp.nameid) - map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0); - } - skill_delunit(su); - } - } - break; - case NC_INFRAREDSCAN: - if (flag&1) { - //TODO: Need a confirmation if the other type of hidden status is included to be scanned. [Jobbie] - if (rnd()%100 < 50) - sc_start(bl, SC_INFRAREDSCAN, 10000, skilllv, skill_get_time(skillid, skilllv)); - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); // Need confirm it. - } else { - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); - clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - if (sd) pc_overheat(sd,1); - } - break; - - case NC_MAGNETICFIELD: - sc_start2(bl,SC_MAGNETICFIELD,100,skilllv,src->id,skill_get_time(skillid,skilllv)); - break; - case SC_FATALMENACE: - if (flag&1) - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - else { - short x, y; - map_search_freecell(src, 0, &x, &y, -1, -1, 0); - // Destination area - skill_area_temp[4] = x; - skill_area_temp[5] = y; - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id); - skill_addtimerskill(src,tick + 800,src->id,x,y,skillid,skilllv,0,flag); // To teleport Self - clif_skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skillid,skilllv,6); - } - break; - case LG_PINPOINTATTACK: - if (!map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1)) - clif_slide(src,bl->x,bl->y); - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; - - case LG_SHIELDSPELL: - // flag&1: Phisycal Attack, flag&2: Magic Attack. - skill_attack((flag&1)?BF_WEAPON:BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - break; - - case LG_OVERBRAND: - skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag|SD_LEVEL); - break; - - case LG_OVERBRAND_BRANDISH: - skill_addtimerskill(src, tick + status_get_amotion(src)*8/10, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag|SD_LEVEL); - break; - case SR_DRAGONCOMBO: - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - break; - - case SR_KNUCKLEARROW: - if (!map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1)) { - clif_slide(src,bl->x,bl->y); - clif_fixpos(src); // Aegis send this packet too. - } - - if (flag&1) - skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag|SD_LEVEL); - else - skill_addtimerskill(src, tick + 300, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag|SD_LEVEL|2); - break; - - case SR_HOWLINGOFLION: - status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); - status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); - status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); - status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); - status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); - status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); - status_change_end(bl, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); - status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); - status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); - status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); - status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); - status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); - skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag|SD_ANIMATION); - break; - - case SR_EARTHSHAKER: - if (flag&1) { //by default cloaking skills are remove by aoe skills so no more checking/removing except hiding and cloaking exceed. - skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - } else { - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - } - break; - - case WM_LULLABY_DEEPSLEEP: - if (bl != src && rnd()%100 < 88 + 2 * skilllv) - sc_start(bl,status_skill2sc(skillid),100,skilllv,skill_get_time(skillid,skilllv)); - break; + } + //Client expects you to move to target regardless of distance + { + struct unit_data *ud = unit_bl2ud(src); + short dx,dy; + int i,speed; + i = skillid == MO_EXTREMITYFIST?1:2; //Move 2 cells for Issen, 1 for Asura + dx = bl->x - src->x; + dy = bl->y - src->y; + if (dx < 0) dx-=i; + else if (dx > 0) dx+=i; + if (dy < 0) dy-=i; + else if (dy > 0) dy+=i; + if (!dx && !dy) dy++; + if (map_getcell(src->m, src->x+dx, src->y+dy, CELL_CHKNOPASS)) + { + dx = bl->x; + dy = bl->y; + } else { + dx = src->x + dx; + dy = src->y + dy; + } - case SO_POISON_BUSTER: { - struct status_change *tsc = status_get_sc(bl); - if (tsc && tsc->data[SC_POISON]) { - skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); - status_change_end(bl, SC_POISON, INVALID_TIMER); - } else if (sd) - clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); - } - break; + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + + if(unit_walktoxy(src, dx, dy, 2) && ud) { + //Increase can't walk delay to not alter your walk path + ud->canmove_tick = tick; + speed = status_get_speed(src); + for (i = 0; i < ud->walkpath.path_len; i ++) + { + if(ud->walkpath.path[i]&1) + ud->canmove_tick+=7*speed/5; + else + ud->canmove_tick+=speed; + } + } + } + break; + + //Splash attack skills. + case AS_GRIMTOOTH: + case MC_CARTREVOLUTION: + case NPC_SPLASHATTACK: + flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit + case AS_SPLASHER: + case SM_MAGNUM: + case MS_MAGNUM: + case HT_BLITZBEAT: + case AC_SHOWER: + case MA_SHOWER: + case MG_NAPALMBEAT: + case MG_FIREBALL: + case RG_RAID: + case HW_NAPALMVULCAN: + case NJ_HUUMA: + case NJ_BAKUENRYU: + case ASC_METEORASSAULT: + case GS_DESPERADO: + case GS_SPREADATTACK: + case NPC_EARTHQUAKE: + case NPC_PULSESTRIKE: + case NPC_HELLJUDGEMENT: + case NPC_VAMPIRE_GIFT: + case RK_IGNITIONBREAK: + case AB_JUDEX: + case WL_SOULEXPANSION: + case WL_CRIMSONROCK: + case WL_COMET: + case WL_JACKFROST: + case RA_ARROWSTORM: + case RA_WUGDASH: + case NC_SELFDESTRUCTION: + case NC_AXETORNADO: + case GC_ROLLINGCUTTER: + case GC_COUNTERSLASH: + case LG_MOONSLASHER: + case LG_EARTHDRIVE: + case SR_TIGERCANNON: + case SR_RAMPAGEBLASTER: + case SR_SKYNETBLOW: + case SR_WINDMILL: + case SR_RIDEINLIGHTNING: + case WM_SOUND_OF_DESTRUCTION: + case WM_REVERBERATION_MELEE: + case WM_REVERBERATION_MAGIC: + case SO_VARETYR_SPEAR: + case GN_CART_TORNADO: + case GN_CARTCANNON: + case KO_HAPPOKUNAI: + case KO_HUUMARANKA: + case KO_MUCHANAGE: + case KO_BAKURETSU: + if( flag&1 ) {//Recursive invocation + // skill_area_temp[0] holds number of targets in area + // skill_area_temp[1] holds the id of the original target + // skill_area_temp[2] counts how many targets have already been processed + int sflag = skill_area_temp[0] & 0xFFF, heal; + if( flag&SD_LEVEL ) + sflag |= SD_LEVEL; // -1 will be used in packets instead of the skill level + if( skill_area_temp[1] != bl->id && !(skill_get_inf2(skillid)&INF2_NPC_SKILL) ) + sflag |= SD_ANIMATION; // original target gets no animation (as well as all NPC skills) + + heal = skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, sflag); + if( skillid == NPC_VAMPIRE_GIFT && heal > 0 ) { + clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1); + status_heal(src,heal,0,0); + } + } else { + switch ( skillid ) { + case NJ_BAKUENRYU: + case LG_EARTHDRIVE: + case GN_CARTCANNON: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + case LG_MOONSLASHER: + clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + break; + case NPC_EARTHQUAKE://FIXME: Isn't EarthQuake a ground skill after all? + skill_addtimerskill(src,tick+250,src->id,0,0,skillid,skilllv,2,flag|BCT_ENEMY|SD_SPLASH|1); + default: + break; + } - case GN_SPORE_EXPLOSION: - if (flag&1) - skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); - else { - clif_skill_nodamage(src, bl, skillid, 0, 1); - skill_addtimerskill(src, gettick() + skill_get_time(skillid, skilllv) - 1000, bl->id, 0, 0, skillid, skilllv, 0, 0); - } - break; + skill_area_temp[0] = 0; + skill_area_temp[1] = bl->id; + skill_area_temp[2] = 0; + if( skillid == WL_CRIMSONROCK ) { + skill_area_temp[4] = bl->x; + skill_area_temp[5] = bl->y; + } + if( skillid == WM_REVERBERATION_MELEE || skillid == WM_REVERBERATION_MAGIC ) + skill_area_temp[1] = 0; + // if skill damage should be split among targets, count them + //SD_LEVEL -> Forced splash damage for Auto Blitz-Beat -> count targets + //special case: Venom Splasher uses a different range for searching than for splashing + if( flag&SD_LEVEL || skill_get_nk(skillid)&NK_SPLASHSPLIT ) + skill_area_temp[0] = map_foreachinrange(skill_area_sub, bl, (skillid == AS_SPLASHER)?1:skill_get_splash(skillid, skilllv), BL_CHAR, src, skillid, skilllv, tick, BCT_ENEMY, skill_area_sub_count); + + // recursive invocation of skill_castend_damage_id() with flag|1 + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), ( skillid == WM_REVERBERATION_MELEE || skillid == WM_REVERBERATION_MAGIC )?BL_CHAR:splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); + } + break; + + case KN_BRANDISHSPEAR: + case ML_BRANDISH: + //Coded apart for it needs the flag passed to the damage calculation. + if (skill_area_temp[1] != bl->id) + skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag|SD_ANIMATION); + else + skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); + break; + + case KN_BOWLINGBASH: + case MS_BOWLINGBASH: + if(flag&1){ + if(bl->id==skill_area_temp[1]) + break; + //two hits for 500% + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,SD_ANIMATION); + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,SD_ANIMATION); + } else { + int i,c; + c = skill_get_blewcount(skillid,skilllv); + // keep moving target in the direction that src is looking, square by square + for(i=0;i<c;i++){ + if (!skill_blown(src,bl,1,(unit_getdir(src)+4)%8,0x1)) + break; //Can't knockback + skill_area_temp[0] = map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), BL_CHAR, src, skillid, skilllv, tick, flag|BCT_ENEMY, skill_area_sub_count); + if( skill_area_temp[0] > 1 ) break; // collision + } + clif_blown(bl); //Update target pos. + if (i!=c) { //Splash + skill_area_temp[1] = bl->id; + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id); + } + //Weirdo dual-hit property, two attacks for 500% + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0); + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0); + } + break; + + case KN_SPEARSTAB: + if(flag&1) { + if (bl->id==skill_area_temp[1]) + break; + if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,SD_ANIMATION)) + skill_blown(src,bl,skill_area_temp[2],-1,0); + } else { + int x=bl->x,y=bl->y,i,dir; + dir = map_calc_dir(bl,src->x,src->y); + skill_area_temp[1] = bl->id; + skill_area_temp[2] = skill_get_blewcount(skillid,skilllv); + // all the enemies between the caster and the target are hit, as well as the target + if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0)) + skill_blown(src,bl,skill_area_temp[2],-1,0); + for (i=0;i<4;i++) { + map_foreachincell(skill_area_sub,bl->m,x,y,BL_CHAR, + src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + x += dirx[dir]; + y += diry[dir]; + } + } + break; + + case TK_TURNKICK: + case MO_BALKYOUNG: //Active part of the attack. Skill-attack [Skotlex] + { + skill_area_temp[1] = bl->id; //NOTE: This is used in skill_castend_nodamage_id to avoid affecting the target. + if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag)) + map_foreachinrange(skill_area_sub,bl, + skill_get_splash(skillid, skilllv),BL_CHAR, + src,skillid,skilllv,tick,flag|BCT_ENEMY|1, + skill_castend_nodamage_id); + } + break; + case CH_PALMSTRIKE: // Palm Strike takes effect 1sec after casting. [Skotlex] + // clif_skill_nodamage(src,bl,skillid,skilllv,0); //Can't make this one display the correct attack animation delay :/ + clif_damage(src,bl,tick,status_get_amotion(src),0,-1,1,4,0); //Display an absorbed damage attack. + skill_addtimerskill(src, tick + 1000, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag); + break; + + case PR_TURNUNDEAD: + case ALL_RESURRECTION: + if (!battle_check_undead(tstatus->race, tstatus->def_ele)) + break; + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + break; + + case MG_SOULSTRIKE: + case NPC_DARKSTRIKE: + case MG_COLDBOLT: + case MG_FIREBOLT: + case MG_LIGHTNINGBOLT: + case WZ_EARTHSPIKE: + case AL_HEAL: + case AL_HOLYLIGHT: + case WZ_JUPITEL: + case NPC_DARKTHUNDER: + case PR_ASPERSIO: + case MG_FROSTDIVER: + case WZ_SIGHTBLASTER: + case WZ_SIGHTRASHER: + case NJ_KOUENKA: + case NJ_HYOUSENSOU: + case NJ_HUUJIN: + case AB_ADORAMUS: + case AB_RENOVATIO: + case AB_HIGHNESSHEAL: + case AB_DUPLELIGHT_MAGIC: + case WM_METALICSOUND: + case MH_ERASER_CUTTER: + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + break; + + case NPC_MAGICALATTACK: + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + sc_start(src,status_skill2sc(skillid),100,skilllv,skill_get_time(skillid,skilllv)); + break; + + case HVAN_CAPRICE: //[blackhole89] + { + int ran=rnd()%4; + int sid = 0; + switch(ran) + { + case 0: sid=MG_COLDBOLT; break; + case 1: sid=MG_FIREBOLT; break; + case 2: sid=MG_LIGHTNINGBOLT; break; + case 3: sid=WZ_EARTHSPIKE; break; + } + skill_attack(BF_MAGIC,src,src,bl,sid,skilllv,tick,flag|SD_LEVEL); + } + break; + case WZ_WATERBALL: + { + int range = skilllv / 2; + int maxlv = skill_get_max(skillid); // learnable level + int count = 0; + int x, y; + struct skill_unit* unit; + + if( skilllv > maxlv ) + { + if( src->type == BL_MOB && skilllv == 10 ) + range = 4; + else + range = maxlv / 2; + } - case EL_FIRE_BOMB: - case EL_FIRE_WAVE: - case EL_WATER_SCREW: - case EL_HURRICANE: - case EL_TYPOON_MIS: - if (flag&1) - skill_attack(skill_get_type(skillid+1),src,src,bl,skillid+1,skilllv,tick,flag); - else { - int i = skill_get_splash(skillid,skilllv); - clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - if (rnd()%100 < 30) - map_foreachinrange(skill_area_sub,bl,i,BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - else - skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); - } - break; + for( y = src->y - range; y <= src->y + range; ++y ) + for( x = src->x - range; x <= src->x + range; ++x ) + { + if( !map_find_skill_unit_oncell(src,x,y,SA_LANDPROTECTOR,NULL,1) ) + { + if( src->type != BL_PC || map_getcell(src->m,x,y,CELL_CHKWATER) ) // non-players bypass the water requirement + count++; // natural water cell + else if( (unit = map_find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL,1)) != NULL || (unit = map_find_skill_unit_oncell(src,x,y,NJ_SUITON,NULL,1)) != NULL ) + { + count++; // skill-induced water cell + skill_delunit(unit); // consume cell + } + } + } - case EL_ROCK_CRUSHER: - clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - if (rnd()%100 < 50) - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - else - skill_attack(BF_WEAPON,src,src,bl,EL_ROCK_CRUSHER_ATK,skilllv,tick,flag); - break; + if( count > 1 ) // queue the remaining count - 1 timerskill Waterballs + skill_addtimerskill(src,tick+150,bl->id,0,0,skillid,skilllv,count-1,flag); + } + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + break; + + case PR_BENEDICTIO: + //Should attack undead and demons. [Skotlex] + if (battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON) + skill_attack(BF_MAGIC, src, src, bl, skillid, skilllv, tick, flag); + break; + + case SL_SMA: + status_change_end(src, SC_SMA, INVALID_TIMER); + case SL_STIN: + case SL_STUN: + if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { + status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,10); + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + break; + + case NPC_DARKBREATH: + clif_emotion(src,E_AG); + case SN_FALCONASSAULT: + case PA_PRESSURE: + case CR_ACIDDEMONSTRATION: + case TF_THROWSTONE: + case NPC_SMOKING: + case GS_FLING: + case NJ_ZENYNAGE: + case GN_THORNS_TRAP: + case GN_HELLS_PLANT_ATK: + skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); + break; + /** + * Rune Knight + **/ + case RK_DRAGONBREATH: { + struct status_change *tsc = NULL; + if( (tsc = status_get_sc(bl)) && (tsc->data[SC_HIDING] )) { + clif_skill_nodamage(src,src,skillid,skilllv,1); + } else + skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); + } + break; + + case NPC_SELFDESTRUCTION: { + struct status_change *tsc = NULL; + if( (tsc = status_get_sc(bl)) && tsc->data[SC_HIDING] ) + break; + } + case HVAN_EXPLOSION: + if (src != bl) + skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); + break; + + // Celest + case PF_SOULBURN: + if (rnd()%100 < (skilllv < 5 ? 30 + skilllv * 10 : 70)) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if (skilllv == 5) + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + status_percent_damage(src, bl, 0, 100, false); + } else { + clif_skill_nodamage(src,src,skillid,skilllv,1); + if (skilllv == 5) + skill_attack(BF_MAGIC,src,src,src,skillid,skilllv,tick,flag); + status_percent_damage(src, src, 0, 100, false); + } + break; + + case NPC_BLOODDRAIN: + case NPC_ENERGYDRAIN: + { + int heal = skill_attack( (skillid == NPC_BLOODDRAIN) ? BF_WEAPON : BF_MAGIC, + src, src, bl, skillid, skilllv, tick, flag); + if (heal > 0){ + clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1); + status_heal(src, heal, 0, 0); + } + } + break; + + case GS_BULLSEYE: + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + break; + + case NJ_KASUMIKIRI: + if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag) > 0) + sc_start(src,SC_HIDING,100,skilllv,skill_get_time(skillid,skilllv)); + break; + case NJ_KIRIKAGE: + if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground ) + { //You don't move on GVG grounds. + short x, y; + map_search_freecell(bl, 0, &x, &y, 1, 1, 0); + if (unit_movepos(src, x, y, 0, 0)) + clif_slide(src,src->x,src->y); + } + status_change_end(src, SC_HIDING, INVALID_TIMER); + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + break; + case RK_PHANTOMTHRUST: + unit_setdir(src,map_calc_dir(src, bl->x, bl->y)); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + + skill_blown(src,bl,distance_bl(src,bl)-1,unit_getdir(src),0); + if( battle_check_target(src,bl,BCT_ENEMY) ) + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + break; + + case RK_STORMBLAST: + case RK_CRUSHSTRIKE: + if( sd ) { + if( pc_checkskill(sd,RK_RUNEMASTERY) >= ( skillid == RK_CRUSHSTRIKE ? 7 : 3 ) ) + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + else + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } else //non-sd support + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + break; + case GC_DARKILLUSION: + { + short x, y; + short dir = map_calc_dir(src,bl->x,bl->y); + + if( dir > 4 ) x = -1; + else if( dir > 0 && dir < 4 ) x = 1; + else x = 0; + if( dir < 3 || dir > 5 ) y = -1; + else if( dir > 3 && dir < 5 ) y = 1; + else y = 0; + + if( unit_movepos(src, bl->x+x, bl->y+y, 1, 1) ) + { + clif_slide(src,bl->x+x,bl->y+y); + clif_fixpos(src); // the official server send these two packts. + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + if( rnd()%100 < 4 * skilllv ) + skill_castend_damage_id(src,bl,GC_CROSSIMPACT,skilllv,tick,flag); + } - case EL_STONE_RAIN: - if (flag&1) - skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); - else { - int i = skill_get_splash(skillid,skilllv); - clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - if (rnd()%100 < 30) - map_foreachinrange(skill_area_sub,bl,i,BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - else - skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); - } - break; + } + break; + + case GC_WEAPONCRUSH: + if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == GC_WEAPONBLOCKING ) + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + else if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_GC_WEAPONBLOCKING,0); + break; + + case GC_CROSSRIPPERSLASHER: + if( sd && !(sc && sc->data[SC_ROLLINGCUTTER]) ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_CONDITION,0); + else + { + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + status_change_end(src,SC_ROLLINGCUTTER,INVALID_TIMER); + } + break; + + case GC_PHANTOMMENACE: + if( flag&1 ) + { // Only Hits Invisible Targets + struct status_change *tsc = status_get_sc(bl); + if(tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY]) ) + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + } + break; + case WL_CHAINLIGHTNING: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_addtimerskill(src,tick + 150,bl->id,3,0,WL_CHAINLIGHTNING_ATK,skilllv,4+skilllv,flag); + break; + case WL_DRAINLIFE: + { + int heal = skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); + int rate = 70 + 5 * skilllv; + + heal = heal * (5 + 5 * skilllv) / 100; + + if( bl->type == BL_SKILL ) + heal = 0; // Don't absorb heal from Ice Walls or other skill units. + + if( heal && rnd()%100 < rate ) + { + status_heal(src, heal, 0, 0); + clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1); + } + } + break; + + case WL_TETRAVORTEX: + if( sd ) + { + int spheres[5] = { 0, 0, 0, 0, 0 }, + positions[5] = {-1,-1,-1,-1,-1 }, + i, j = 0, k, subskill = 0; + + for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) + if( sc && sc->data[i] ) + { + spheres[j] = i; + positions[j] = sc->data[i]->val2; + j++; // + } - case EL_FIRE_ARROW: - case EL_ICE_NEEDLE: - case EL_WIND_SLASH: - case EL_STONE_HAMMER: - clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); - break; + if( j < 4 ) + { // Need 4 spheres minimum + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } - case EL_TIDAL_WEAPON: - if (src->type == BL_ELEM) { - struct elemental_data *ele = BL_CAST(BL_ELEM,src); - struct status_change *sc = status_get_sc(&ele->bl); - struct status_change *tsc = status_get_sc(bl); - sc_type type = status_skill2sc(skillid), type2; - type2 = type-1; - - clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - if ((sc && sc->data[type2]) || (tsc && tsc->data[type])) { - elemental_clean_single_effect(ele, skillid); - } - if (rnd()%100 < 50) - skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); - else { - sc_start(src,type2,100,skilllv,skill_get_time(skillid,skilllv)); - sc_start(battle_get_master(src),type,100,ele->bl.id,skill_get_time(skillid,skilllv)); - } - clif_skill_nodamage(src,src,skillid,skilllv,1); - } - break; + // Sphere Sort, this time from new to old + for( i = 0; i <= j - 2; i++ ) + for( k = i + 1; k <= j - 1; k++ ) + if( positions[i] < positions[k] ) + { + swap(positions[i],positions[k]); + swap(spheres[i],spheres[k]); + } + + k = 0; + for( i = 0; i < 4; i++ ) + { + switch( sc->data[spheres[i]]->val1 ) + { + case WLS_FIRE: subskill = WL_TETRAVORTEX_FIRE; k |= 1; break; + case WLS_WIND: subskill = WL_TETRAVORTEX_WIND; k |= 4; break; + case WLS_WATER: subskill = WL_TETRAVORTEX_WATER; k |= 2; break; + case WLS_STONE: subskill = WL_TETRAVORTEX_GROUND; k |= 8; break; + } + skill_addtimerskill(src, tick + i * 200, bl->id, k, 0, subskill, skilllv, i, flag); + clif_skill_nodamage(src, bl, subskill, skilllv, 1); + status_change_end(src, spheres[i], INVALID_TIMER); + } + } + break; + + case WL_RELEASE: + if( sd ) + { + int i; + // Priority is to release SpellBook + if( sc && sc->data[SC_READING_SB] ) + { // SpellBook + int skill_id, skill_lv, point, s = 0; + int spell[SC_MAXSPELLBOOK-SC_SPELLBOOK1 + 1]; + + for(i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) // List all available spell to be released + if( sc->data[i] ) spell[s++] = i; + + if ( s == 0 ) + break; + + i = spell[s==1?0:rand()%s];// Random select of spell to be released. + if( s && sc->data[i] ){// Now extract the data from the preserved spell + skill_id = sc->data[i]->val1; + skill_lv = sc->data[i]->val2; + point = sc->data[i]->val3; + status_change_end(src, (sc_type)i, INVALID_TIMER); + }else //something went wrong :( + break; + + if( sc->data[SC_READING_SB]->val2 > point ) + sc->data[SC_READING_SB]->val2 -= point; + else // Last spell to be released + status_change_end(src, SC_READING_SB, INVALID_TIMER); + + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + if( !skill_check_condition_castbegin(sd, skill_id, skill_lv) ) + break; + + switch( skill_get_casttype(skill_id) ) + { + case CAST_GROUND: + skill_castend_pos2(src, bl->x, bl->y, skill_id, skill_lv, tick, 0); + break; + case CAST_NODAMAGE: + skill_castend_nodamage_id(src, bl, skill_id, skill_lv, tick, 0); + break; + case CAST_DAMAGE: + skill_castend_damage_id(src, bl, skill_id, skill_lv, tick, 0); + break; + } + sd->ud.canact_tick = tick + skill_delayfix(src, skill_id, skill_lv); + clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, skill_id, skill_lv), 0, 0, 0); + } + else + { // Summon Balls + int j = 0, k, skele; + int spheres[5] = { 0, 0, 0, 0, 0 }, + positions[5] = {-1,-1,-1,-1,-1 }; + + for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) + if( sc && sc->data[i] ) + { + spheres[j] = i; + positions[j] = sc->data[i]->val2; + sc->data[i]->val2--; // Prepares for next position + j++; + } + + if( j == 0 ) + { // No Spheres + clif_skill_fail(sd,skillid,USESKILL_FAIL_SUMMON_NONE,0); + break; + } - //recursive homon skill - case MH_MAGMA_FLOW: - case MH_XENO_SLASHER: - case MH_HEILIGE_STANGE: - if (flag & 1) - skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); - else { - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id); - } - break; - case MH_STAHL_HORN: - case MH_NEEDLE_OF_PARALYZE: - skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); - break; + // Sphere Sort + for( i = 0; i <= j - 2; i++ ) + for( k = i + 1; k <= j - 1; k++ ) + if( positions[i] > positions[k] ) + { + swap(positions[i],positions[k]); + swap(spheres[i],spheres[k]); + } + + if( skilllv == 1 ) j = 1; // Limit only to one ball + for( i = 0; i < j; i++ ) + { + skele = WL_RELEASE - 5 + sc->data[spheres[i]]->val1 - WLS_FIRE; // Convert Ball Element into Skill ATK for balls + // WL_SUMMON_ATK_FIRE, WL_SUMMON_ATK_WIND, WL_SUMMON_ATK_WATER, WL_SUMMON_ATK_GROUND + skill_addtimerskill(src,tick+status_get_adelay(src)*i,bl->id,0,0,skele,sc->data[spheres[i]]->val3,BF_MAGIC,flag|SD_LEVEL); + status_change_end(src, spheres[i], INVALID_TIMER); // Eliminate ball + } + clif_skill_nodamage(src,bl,skillid,0,1); + } + } + break; + case WL_FROSTMISTY: + // Causes Freezing status through walls. + sc_start(bl,status_skill2sc(skillid),20+12*skilllv+(sd ? sd->status.job_level : 50)/5,skilllv,skill_get_time(skillid,skilllv)); + // Doesn't deal damage through non-shootable walls. + if( path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKWALL) ) + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag|SD_ANIMATION); + break; + case WL_HELLINFERNO: + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag|ELE_DARK); + break; + case RA_WUGSTRIKE: + if( sd && pc_isridingwug(sd) ){ + short x[8]={0,-1,-1,-1,0,1,1,1}; + short y[8]={1,1,0,-1,-1,-1,0,1}; + int dir = map_calc_dir(bl, src->x, src->y); + + if( unit_movepos(src, bl->x+x[dir], bl->y+y[dir], 1, 1) ) + { + clif_slide(src, bl->x+x[dir], bl->y+y[dir]); + clif_fixpos(src); + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); + } + break; + } + case RA_WUGBITE: + if( path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH) ) { + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + }else if( sd && skillid == RA_WUGBITE ) // Only RA_WUGBITE has the skill fail message. + clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); + + break; + + case RA_SENSITIVEKEEN: + if( bl->type != BL_SKILL ) { // Only Hits Invisible Targets + struct status_change * tsc = status_get_sc(bl); + if( tsc && tsc->option&(OPTION_HIDE|OPTION_CLOAK) ){ + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + } + } + else + { + struct skill_unit *su = BL_CAST(BL_SKILL,bl); + struct skill_unit_group* sg; - case 0:/* no skill - basic/normal attack */ - if (sd) { - if (flag & 3) { - if (bl->id != skill_area_temp[1]) - skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, SD_LEVEL|flag); - } else { - skill_area_temp[1] = bl->id; - map_foreachinrange(skill_area_sub, bl, - sd->bonus.splash_range, BL_CHAR, - src, skillid, skilllv, tick, flag | BCT_ENEMY | 1, - skill_castend_damage_id); - flag|=1; //Set flag to 1 so ammo is not double-consumed. [Skotlex] - } - } - break; + if( su && (sg=su->group) && skill_get_inf2(sg->skill_id)&INF2_TRAP ) + { + if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) + { + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = sg->item_id?sg->item_id:ITEMID_TRAP; + item_tmp.identify = 1; + if( item_tmp.nameid ) + map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0); + } + skill_delunit(su); + } + } + break; + case NC_INFRAREDSCAN: + if( flag&1 ) + { //TODO: Need a confirmation if the other type of hidden status is included to be scanned. [Jobbie] + if( rnd()%100 < 50 ) + sc_start(bl, SC_INFRAREDSCAN, 10000, skilllv, skill_get_time(skillid, skilllv)); + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); // Need confirm it. + } + else + { + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); + clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + if( sd ) pc_overheat(sd,1); + } + break; + + case NC_MAGNETICFIELD: + sc_start2(bl,SC_MAGNETICFIELD,100,skilllv,src->id,skill_get_time(skillid,skilllv)); + break; + case SC_FATALMENACE: + if( flag&1 ) + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + else + { + short x, y; + map_search_freecell(src, 0, &x, &y, -1, -1, 0); + // Destination area + skill_area_temp[4] = x; + skill_area_temp[5] = y; + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id); + skill_addtimerskill(src,tick + 800,src->id,x,y,skillid,skilllv,0,flag); // To teleport Self + clif_skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skillid,skilllv,6); + } + break; + case LG_PINPOINTATTACK: + if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1) ) + clif_slide(src,bl->x,bl->y); + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + break; + + case LG_SHIELDSPELL: + // flag&1: Phisycal Attack, flag&2: Magic Attack. + skill_attack((flag&1)?BF_WEAPON:BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + break; + + case LG_OVERBRAND: + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag|SD_LEVEL); + break; + + case LG_OVERBRAND_BRANDISH: + skill_addtimerskill(src, tick + status_get_amotion(src)*8/10, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag|SD_LEVEL); + break; + case SR_DRAGONCOMBO: + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + break; + + case SR_KNUCKLEARROW: + if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1) ) { + clif_slide(src,bl->x,bl->y); + clif_fixpos(src); // Aegis send this packet too. + } - default: - ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skillid); - clif_skill_damage(src, bl, tick, status_get_amotion(src), tstatus->dmotion, - 0, abs(skill_get_num(skillid, skilllv)), - skillid, skilllv, skill_get_hit(skillid)); - map_freeblock_unlock(); - return 1; - } + if( flag&1 ) + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag|SD_LEVEL); + else + skill_addtimerskill(src, tick + 300, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag|SD_LEVEL|2); + break; + + case SR_HOWLINGOFLION: + status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); + status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); + status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); + status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); + status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); + status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); + status_change_end(bl, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); + status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); + status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); + status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); + status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); + status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag|SD_ANIMATION); + break; + + case SR_EARTHSHAKER: + if( flag&1 ) { //by default cloaking skills are remove by aoe skills so no more checking/removing except hiding and cloaking exceed. + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + } else{ + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + } + break; + + case WM_LULLABY_DEEPSLEEP: + if( bl != src && rnd()%100 < 88 + 2 * skilllv ) + sc_start(bl,status_skill2sc(skillid),100,skilllv,skill_get_time(skillid,skilllv)); + break; + + case SO_POISON_BUSTER: { + struct status_change *tsc = status_get_sc(bl); + if( tsc && tsc->data[SC_POISON] ) { + skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); + status_change_end(bl, SC_POISON, INVALID_TIMER); + } + else if( sd ) + clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); + } + break; + + case GN_SPORE_EXPLOSION: + if( flag&1 ) + skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); + else { + clif_skill_nodamage(src, bl, skillid, 0, 1); + skill_addtimerskill(src, gettick() + skill_get_time(skillid, skilllv) - 1000, bl->id, 0, 0, skillid, skilllv, 0, 0); + } + break; + + case EL_FIRE_BOMB: + case EL_FIRE_WAVE: + case EL_WATER_SCREW: + case EL_HURRICANE: + case EL_TYPOON_MIS: + if( flag&1 ) + skill_attack(skill_get_type(skillid+1),src,src,bl,skillid+1,skilllv,tick,flag); + else { + int i = skill_get_splash(skillid,skilllv); + clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + if( rnd()%100 < 30 ) + map_foreachinrange(skill_area_sub,bl,i,BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + else + skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); + } + break; + + case EL_ROCK_CRUSHER: + clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + if( rnd()%100 < 50 ) + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); + else + skill_attack(BF_WEAPON,src,src,bl,EL_ROCK_CRUSHER_ATK,skilllv,tick,flag); + break; + + case EL_STONE_RAIN: + if( flag&1 ) + skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); + else { + int i = skill_get_splash(skillid,skilllv); + clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + if( rnd()%100 < 30 ) + map_foreachinrange(skill_area_sub,bl,i,BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + else + skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); + } + break; + + case EL_FIRE_ARROW: + case EL_ICE_NEEDLE: + case EL_WIND_SLASH: + case EL_STONE_HAMMER: + clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); + break; + + case EL_TIDAL_WEAPON: + if( src->type == BL_ELEM ) { + struct elemental_data *ele = BL_CAST(BL_ELEM,src); + struct status_change *sc = status_get_sc(&ele->bl); + struct status_change *tsc = status_get_sc(bl); + sc_type type = status_skill2sc(skillid), type2; + type2 = type-1; + + clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { + elemental_clean_single_effect(ele, skillid); + } + if( rnd()%100 < 50 ) + skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); + else { + sc_start(src,type2,100,skilllv,skill_get_time(skillid,skilllv)); + sc_start(battle_get_master(src),type,100,ele->bl.id,skill_get_time(skillid,skilllv)); + } + clif_skill_nodamage(src,src,skillid,skilllv,1); + } + break; + + + //recursive homon skill + case MH_MAGMA_FLOW: + case MH_XENO_SLASHER: + case MH_HEILIGE_STANGE: + if(flag & 1) + skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); + else { + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id); + } + break; + case MH_STAHL_HORN: + case MH_NEEDLE_OF_PARALYZE: + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); + break; + + case 0:/* no skill - basic/normal attack */ + if(sd) { + if (flag & 3){ + if (bl->id != skill_area_temp[1]) + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, SD_LEVEL|flag); + } else { + skill_area_temp[1] = bl->id; + map_foreachinrange(skill_area_sub, bl, + sd->bonus.splash_range, BL_CHAR, + src, skillid, skilllv, tick, flag | BCT_ENEMY | 1, + skill_castend_damage_id); + flag|=1; //Set flag to 1 so ammo is not double-consumed. [Skotlex] + } + } + break; + + default: + ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skillid); + clif_skill_damage(src, bl, tick, status_get_amotion(src), tstatus->dmotion, + 0, abs(skill_get_num(skillid, skilllv)), + skillid, skilllv, skill_get_hit(skillid)); + map_freeblock_unlock(); + return 1; + } - if (sc && sc->data[SC_CURSEDCIRCLE_ATKER]) //Should only remove after the skill has been casted. - status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); + if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] ) //Should only remove after the skill has been casted. + status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); - map_freeblock_unlock(); + map_freeblock_unlock(); - if (sd && !(flag&1)) { - // ensure that the skill last-cast tick is recorded - sd->canskill_tick = gettick(); + if( sd && !(flag&1) ) + {// ensure that the skill last-cast tick is recorded + sd->canskill_tick = gettick(); - if (sd->state.arrow_atk) { - // consume arrow on last invocation to this skill. - battle_consume_ammo(sd, skillid, skilllv); - } + if( sd->state.arrow_atk ) + {// consume arrow on last invocation to this skill. + battle_consume_ammo(sd, skillid, skilllv); + } - // perform skill requirement consumption - skill_consume_requirement(sd,skillid,skilllv,2); - } + // perform skill requirement consumption + skill_consume_requirement(sd,skillid,skilllv,2); + } - return 0; + return 0; } /*========================================== * *------------------------------------------*/ -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, *dstsd; - struct mob_data *md, *dstmd; - struct homun_data *hd; - struct mercenary_data *mer; - struct status_data *sstatus, *tstatus; - struct status_change *tsc; - struct status_change_entry *tsce; - - int i = 0; - enum sc_type type; - - if (skillid > 0 && skilllv <= 0) return 0; // celest - - nullpo_retr(1, src); - nullpo_retr(1, bl); - - if (src->m != bl->m) - return 1; - - sd = BL_CAST(BL_PC, src); - hd = BL_CAST(BL_HOM, src); - md = BL_CAST(BL_MOB, src); - mer = BL_CAST(BL_MER, src); - - dstsd = BL_CAST(BL_PC, bl); - dstmd = BL_CAST(BL_MOB, bl); - - if (bl->prev == NULL) - return 1; - if (status_isdead(src)) - return 1; - - if (src != bl && status_isdead(bl)) { - /** - * Skills that may be cast on dead targets - **/ - switch (skillid) { - case NPC_WIDESOULDRAIN: - case PR_REDEMPTIO: - case ALL_RESURRECTION: - case WM_DEADHILLHERE: - break; - default: - return 1; - } - } - - tstatus = status_get_status_data(bl); - sstatus = status_get_status_data(src); - - //Check for undead skills that convert a no-damage skill into a damage one. [Skotlex] - switch (skillid) { - case HLIF_HEAL: //[orn] - if (bl->type != BL_HOM) { - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0) ; - break ; - } - case AL_HEAL: - case ALL_RESURRECTION: - case PR_ASPERSIO: - /** - * Arch Bishop - **/ - case AB_RENOVATIO: - case AB_HIGHNESSHEAL: - //Apparently only player casted skills can be offensive like this. - if (sd && battle_check_undead(tstatus->race,tstatus->def_ele)) { - if (battle_check_target(src, bl, BCT_ENEMY) < 1) { - //Offensive heal does not works on non-enemies. [Skotlex] - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - return 0; - } - return skill_castend_damage_id(src, bl, skillid, skilllv, tick, flag); - } - break; - case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex] - return skill_castend_damage_id(src, bl, skillid, skilllv, tick, flag); - case MH_STEINWAND: { - struct block_list *s_src = battle_get_master(src); - short ret = 0; - if (!skill_check_unit_range(src, src->x, src->y, skillid, skilllv)) //prevent reiteration - ret = skill_castend_pos2(src,src->x,src->y,skillid,skilllv,tick,flag); //cast on homon - if (s_src && !skill_check_unit_range(s_src, s_src->x, s_src->y, skillid, skilllv)) - ret |= skill_castend_pos2(s_src,s_src->x,s_src->y,skillid,skilllv,tick,flag); //cast on master - if (hd) - skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); - return ret; - } - break; - default: - //Skill is actually ground placed. - if (src == bl && skill_get_unit_id(skillid,0)) - return skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0); - } - - type = status_skill2sc(skillid); - tsc = status_get_sc(bl); - tsce = (tsc && type != -1)?tsc->data[type]:NULL; - - if (src!=bl && type > -1 && - (i = skill_get_ele(skillid, skilllv)) > ELE_NEUTRAL && - skill_get_inf(skillid) != INF_SUPPORT_SKILL && - battle_attr_fix(NULL, NULL, 100, i, tstatus->def_ele, tstatus->ele_lv) <= 0) - return 1; //Skills that cause an status should be blocked if the target element blocks its element. - - map_freeblock_lock(); - switch (skillid) { - case HLIF_HEAL: //[orn] - case AL_HEAL: - /** - * Arch Bishop - **/ - case AB_HIGHNESSHEAL: { - int heal = skill_calc_heal(src, bl, (skillid == AB_HIGHNESSHEAL)?AL_HEAL:skillid, (skillid == AB_HIGHNESSHEAL)?10:skilllv, true); - int heal_get_jobexp; - //Highness Heal: starts at 1.5 boost + 0.5 for each level - if (skillid == AB_HIGHNESSHEAL) { - heal = heal * (15 + 5 * skilllv) / 10; - } - if (status_isimmune(bl) || - (dstmd && (dstmd->class_ == MOBID_EMPERIUM || mob_is_battleground(dstmd))) || - (dstsd && pc_ismadogear(dstsd))) //Mado is immune to heal - heal=0; - - if (sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0) - heal = heal*2; - - if (tsc && tsc->count) { - if (tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS)) { - //Bounce back heal - if (--tsc->data[SC_KAITE]->val2 <= 0) - status_change_end(bl, SC_KAITE, INVALID_TIMER); - if (src == bl) - heal=0; //When you try to heal yourself under Kaite, the heal is voided. - else { - bl = src; - dstsd = sd; - } - } else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAYNIGHTFEVER] || tsc->data[SC__BLOODYLUST]) - heal = 0; //Needed so that it actually displays 0 when healing. - } - clif_skill_nodamage(src, bl, skillid, heal, 1); - if (tsc && tsc->data[SC_AKAITSUKI] && heal && skillid != HLIF_HEAL) - heal = ~heal + 1; - heal_get_jobexp = status_heal(bl,heal,0,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) - heal_get_jobexp = 1; - pc_gainexp(sd, bl, 0, heal_get_jobexp, false); - } - } - break; - - case PR_REDEMPTIO: - if (sd && !(flag&1)) { - if (sd->status.party_id == 0) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - skill_area_temp[0] = 0; - party_foreachsamemap(skill_area_sub, - sd,skill_get_splash(skillid, skilllv), - src,skillid,skilllv,tick, flag|BCT_PARTY|1, - skill_castend_nodamage_id); - if (skill_area_temp[0] == 0) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty... - if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty) { //Apply penalty - sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * skill_area_temp[0] * 2/1000); //0.2% penalty per each. - sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * skill_area_temp[0] * 2/1000); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_JOBEXP); - } - status_set_hp(src, 1, 0); - status_set_sp(src, 0, 0); - break; - } else if (status_isdead(bl) && flag&1) { //Revive - skill_area_temp[0]++; //Count it in, then fall-through to the Resurrection code. - skilllv = 3; //Resurrection level 3 is used - } else //Invalid target, skip resurrection. - break; - - case ALL_RESURRECTION: - if (sd && (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)) { - //No reviving in WoE grounds! - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - if (!status_isdead(bl)) - break; - { - int per = 0, sper = 0; - if (tsc && tsc->data[SC_HELLPOWER]) - break; - - if (map[bl->m].flag.pvp && dstsd && dstsd->pvp_point < 0) - break; - - switch (skilllv) { - case 1: - per=10; - break; - case 2: - per=30; - break; - case 3: - per=50; - break; - case 4: - per=80; - break; - } - if (dstsd && dstsd->special_state.restart_full_recover) - per = sper = 100; - if (status_revive(bl, per, sper)) { - clif_skill_nodamage(src,bl,ALL_RESURRECTION,skilllv,1); //Both Redemptio and Res show this skill-animation. - if (sd && dstsd && battle_config.resurrection_exp > 0) { - int exp = 0,jexp = 0; - int lv = dstsd->status.base_level - sd->status.base_level, jlv = dstsd->status.job_level - sd->status.job_level; - if (lv > 0 && pc_nextbaseexp(dstsd)) { - exp = (int)((double)dstsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); - if (exp < 1) exp = 1; - } - if (jlv > 0 && pc_nextjobexp(dstsd)) { - 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, bl, exp, jexp, false); - } - } - } - break; - - case AL_DECAGI: - case MER_DECAGI: - clif_skill_nodamage(src, bl, skillid, skilllv, - sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), skilllv, skill_get_time(skillid,skilllv))); - break; - - case AL_CRUCIS: - if (flag&1) - sc_start(bl,type, 23+skilllv*4 +status_get_lv(src) -status_get_lv(bl), skilllv,skill_get_time(skillid,skilllv)); - else { - map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid, skilllv), BL_CHAR, - src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - } - break; - - case PR_LEXDIVINA: - case MER_LEXDIVINA: - if (tsce) - status_change_end(bl,type, INVALID_TIMER); - else - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - break; - - case SA_ABRACADABRA: { - int abra_skillid = 0, abra_skilllv; - do { - i = rnd() % MAX_SKILL_ABRA_DB; - abra_skillid = skill_abra_db[i].skillid; - } while (abra_skillid == 0 || - skill_abra_db[i].req_lv > skilllv || //Required lv for it to appear - rnd()%10000 >= skill_abra_db[i].per - ); - abra_skilllv = min(skilllv, skill_get_max(abra_skillid)); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - - if (sd) { - // player-casted - sd->state.abra_flag = 1; - sd->skillitem = abra_skillid; - sd->skillitemlv = abra_skilllv; - clif_item_skill(sd, abra_skillid, abra_skilllv); - } else { - // mob-casted - struct unit_data *ud = unit_bl2ud(src); - int inf = skill_get_inf(abra_skillid); - int target_id = 0; - if (!ud) break; - if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { - if (src->type == BL_PET) - bl = (struct block_list *)((TBL_PET *)src)->msd; - if (!bl) bl = src; - unit_skilluse_id(src, bl->id, abra_skillid, abra_skilllv); - } else { //Assume offensive skills - if (ud->target) - target_id = ud->target; - else switch (src->type) { - case BL_MOB: - target_id = ((TBL_MOB *)src)->target_id; - break; - case BL_PET: - target_id = ((TBL_PET *)src)->target_id; - break; - } - if (!target_id) - break; - if (skill_get_casttype(abra_skillid) == CAST_GROUND) { - bl = map_id2bl(target_id); - if (!bl) bl = src; - unit_skilluse_pos(src, bl->x, bl->y, abra_skillid, abra_skilllv); - } else - unit_skilluse_id(src, target_id, abra_skillid, abra_skilllv); - } - } - } - break; - - case SA_COMA: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time2(skillid,skilllv))); - break; - case SA_FULLRECOVERY: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (status_isimmune(bl)) - break; - status_percent_heal(bl, 100, 100); - break; - case NPC_ALLHEAL: { - int heal; - if (status_isimmune(bl)) - break; - heal = status_percent_heal(bl, 100, 0); - clif_skill_nodamage(NULL, bl, AL_HEAL, heal, 1); - if (dstmd) { - // Reset Damage Logs - memset(dstmd->dmglog, 0, sizeof(dstmd->dmglog)); - dstmd->tdmg = 0; - } - } - break; - case SA_SUMMONMONSTER: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd) mob_once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_SMALL, AI_NONE); - break; - case SA_LEVELUP: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd, NULL, pc_nextbaseexp(sd) * 10 / 100, 0, false); - break; - case SA_INSTANTDEATH: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - status_set_hp(bl,1,0); - break; - case SA_QUESTION: - case SA_GRAVITY: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case SA_CLASSCHANGE: - case SA_MONOCELL: - if (dstmd) { - int class_; - if (sd && dstmd->status.mode&MD_BOSS) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - class_ = skillid==SA_MONOCELL?1002:mob_get_random_id(4, 1, 0); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - mob_class_change(dstmd,class_); - if (tsc && dstmd->status.mode&MD_BOSS) { - const enum sc_type scs[] = { SC_QUAGMIRE, SC_PROVOKE, SC_ROKISWEIL, SC_GRAVITATION, SC_SUITON, SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC_BLADESTOP }; - for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) - if (tsc->data[i]) status_change_end(bl, (sc_type)i, INVALID_TIMER); - for (i = 0; i < ARRAYLENGTH(scs); i++) - if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); - } - } - break; - case SA_DEATH: - if (sd && dstmd && dstmd->status.mode&MD_BOSS) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - status_kill(bl); - break; - case SA_REVERSEORCISH: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid, skilllv))); - break; - case SA_FORTUNE: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd) pc_getzeny(sd,status_get_lv(bl)*100,LOG_TYPE_STEAL,NULL); - break; - case SA_TAMINGMONSTER: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd && dstmd) { - ARR_FIND(0, MAX_PET_DB, i, dstmd->class_ == pet_db[i].class_); - if (i < MAX_PET_DB) - pet_catch_process1(sd, dstmd->class_); - } - break; - - case CR_PROVIDENCE: - if (sd && dstsd) { //Check they are not another crusader [Skotlex] - if ((dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; - } - } - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - break; - - case CG_MARIONETTE: { - struct status_change *sc = status_get_sc(src); - - if (sd && dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex) { - // Cannot cast on another bard/dancer-type class of the same gender as caster - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; - } - - if (sc && tsc) { - if (!sc->data[SC_MARIONETTE] && !tsc->data[SC_MARIONETTE2]) { - sc_start(src,SC_MARIONETTE,100,bl->id,skill_get_time(skillid,skilllv)); - sc_start(bl,SC_MARIONETTE2,100,src->id,skill_get_time(skillid,skilllv)); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } else if (sc->data[SC_MARIONETTE ] && sc->data[SC_MARIONETTE ]->val1 == bl->id && - tsc->data[SC_MARIONETTE2] && tsc->data[SC_MARIONETTE2]->val1 == src->id) { - status_change_end(src, SC_MARIONETTE, INVALID_TIMER); - status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER); - } else { - if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - - map_freeblock_unlock(); - return 1; - } - } - } - break; - - case RG_CLOSECONFINE: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start4(bl,type,100,skilllv,src->id,0,0,skill_get_time(skillid,skilllv))); - 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 (dstsd) { - if (dstsd->status.weapon == W_FIST || - (dstsd->sc.count && !dstsd->sc.data[type] && - ( //Allow re-enchanting to lenghten time. [Skotlex] - dstsd->sc.data[SC_FIREWEAPON] || - dstsd->sc.data[SC_WATERWEAPON] || - dstsd->sc.data[SC_WINDWEAPON] || - dstsd->sc.data[SC_EARTHWEAPON] || - dstsd->sc.data[SC_SHADOWWEAPON] || - dstsd->sc.data[SC_GHOSTWEAPON] || - dstsd->sc.data[SC_ENCPOISON] - )) - ) { - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - clif_skill_nodamage(src,bl,skillid,skilllv,0); - break; - } - } - // 100% success rate at lv4 & 5, but lasts longer at lv5 - if (!clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,type,(60+skilllv*10),skilllv, skill_get_time(skillid,skilllv)))) { - if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - if (skill_break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) && sd && sd != dstsd) - clif_displaymessage(sd->fd, msg_txt(669)); - } - break; - - case PR_ASPERSIO: - if (sd && dstmd) { - clif_skill_nodamage(src,bl,skillid,skilllv,0); - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - break; - - case ITEM_ENCHANTARMS: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start2(bl,type,100,skilllv, - skill_get_ele(skillid,skilllv), skill_get_time(skillid,skilllv))); - break; - - case TK_SEVENWIND: - switch (skill_get_ele(skillid,skilllv)) { - case ELE_EARTH : - type = SC_EARTHWEAPON; - break; - case ELE_WIND : - type = SC_WINDWEAPON; - break; - case ELE_WATER : - type = SC_WATERWEAPON; - break; - case ELE_FIRE : - type = SC_FIREWEAPON; - break; - case ELE_GHOST : - type = SC_GHOSTWEAPON; - break; - case ELE_DARK : - type = SC_SHADOWWEAPON; - break; - case ELE_HOLY : - type = SC_ASPERSIO; - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - - sc_start(bl,SC_SEVENWIND,100,skilllv,skill_get_time(skillid,skilllv)); - - break; - - case PR_KYRIE: - case MER_KYRIE: - clif_skill_nodamage(bl,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - break; - //Passive Magnum, should had been casted on yourself. - case SM_MAGNUM: - case MS_MAGNUM: - skill_area_temp[1] = 0; - map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid, skilllv), BL_SKILL|BL_CHAR, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, skill_castend_damage_id); - clif_skill_nodamage(src,src,skillid,skilllv,1); - // Initiate 10% of your damage becomes fire element. - sc_start4(src,SC_WATK_ELEMENT,100,3,20,0,0,skill_get_time2(skillid, skilllv)); - if (sd) - skill_blockpc_start(sd, skillid, skill_get_time(skillid, skilllv)); - else if (bl->type == BL_MER) - skill_blockmerc_start((TBL_MER *)bl, skillid, skill_get_time(skillid, skilllv)); - break; - - case TK_JUMPKICK: - /* Check if the target is an enemy; if not, skill should fail so the character doesn't unit_movepos (exploitable) */ - if (battle_check_target(src, bl, BCT_ENEMY) > 0) { - if (unit_movepos(src, bl->x, bl->y, 1, 1)) { - skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); - clif_slide(src,bl->x,bl->y); - } - } else - clif_skill_fail(sd,skillid,USESKILL_FAIL,0); - break; - - case AL_INCAGI: - case AL_BLESSING: - case MER_INCAGI: - case MER_BLESSING: - if (dstsd != NULL && tsc->data[SC_CHANGEUNDEAD]) { - skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); - break; - } - case PR_SLOWPOISON: - case PR_IMPOSITIO: - case PR_LEXAETERNA: - case PR_SUFFRAGIUM: - case PR_BENEDICTIO: - case LK_BERSERK: - case MS_BERSERK: - case KN_AUTOCOUNTER: - case KN_TWOHANDQUICKEN: - case KN_ONEHAND: - case MER_QUICKEN: - case CR_SPEARQUICKEN: - case CR_REFLECTSHIELD: - case MS_REFLECTSHIELD: - case AS_POISONREACT: - case MC_LOUD: - case MG_ENERGYCOAT: - case MO_EXPLOSIONSPIRITS: - case MO_STEELBODY: - case MO_BLADESTOP: - case LK_AURABLADE: - case LK_PARRYING: - case MS_PARRYING: - case LK_CONCENTRATION: - case WS_CARTBOOST: - case SN_SIGHT: - case WS_MELTDOWN: - case WS_OVERTHRUSTMAX: - case ST_REJECTSWORD: - case HW_MAGICPOWER: - case PF_MEMORIZE: - case PA_SACRIFICE: - case ASC_EDP: - case PF_DOUBLECASTING: - case SG_SUN_COMFORT: - case SG_MOON_COMFORT: - case SG_STAR_COMFORT: - case NPC_HALLUCINATION: - case GS_MADNESSCANCEL: - case GS_ADJUSTMENT: - case GS_INCREASING: - case NJ_KASUMIKIRI: - case NJ_UTSUSEMI: - case NJ_NEN: - case NPC_DEFENDER: - case NPC_MAGICMIRROR: - case ST_PRESERVE: - case NPC_INVINCIBLE: - case NPC_INVINCIBLEOFF: - case RK_DEATHBOUND: - case AB_RENOVATIO: - case AB_EXPIATIO: - case AB_DUPLELIGHT: - case AB_SECRAMENT: - case NC_ACCELERATION: - case NC_HOVERING: - case NC_SHAPESHIFT: - case WL_RECOGNIZEDSPELL: - case GC_VENOMIMPRESS: - case SC_DEADLYINFECT: - case LG_EXEEDBREAK: - case LG_PRESTIGE: - case SR_CRESCENTELBOW: - case SR_LIGHTNINGWALK: - case SR_GENTLETOUCH_ENERGYGAIN: - case GN_CARTBOOST: - case KO_MEIKYOUSISUI: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - break; - - case SO_STRIKING: - if (sd) { - int bonus = 25 + 10 * skilllv; - bonus += (pc_checkskill(sd, SA_FLAMELAUNCHER)+pc_checkskill(sd, SA_FROSTWEAPON)+pc_checkskill(sd, SA_LIGHTNINGLOADER)+pc_checkskill(sd, SA_SEISMICWEAPON))*5; - clif_skill_nodamage(src, bl, skillid, skilllv, - battle_check_target(src,bl,BCT_PARTY) ? - sc_start2(bl, type, 100, skilllv, bonus, skill_get_time(skillid,skilllv)) : - 0 - ); - } - break; - - case NPC_STOP: - if (clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start2(bl,type,100,skilllv,src->id,skill_get_time(skillid,skilllv)))) - sc_start2(src,type,100,skilllv,bl->id,skill_get_time(skillid,skilllv)); - break; - case HP_ASSUMPTIO: - if (sd && dstmd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - else - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - break; - case MG_SIGHT: - case MER_SIGHT: - case AL_RUWACH: - case WZ_SIGHTBLASTER: - case NPC_WIDESIGHT: - case NPC_STONESKIN: - case NPC_ANTIMAGIC: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start2(bl,type,100,skilllv,skillid,skill_get_time(skillid,skilllv))); - break; - case HLIF_AVOID: - case HAMI_DEFENCE: - i = skill_get_time(skillid,skilllv); - clif_skill_nodamage(bl,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,i)); // Master - clif_skill_nodamage(src,src,skillid,skilllv,sc_start(src,type,100,skilllv,i)); // Homunc - break; - case NJ_BUNSINJYUTSU: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - status_change_end(bl, SC_NEN, INVALID_TIMER); - break; - /* Was modified to only affect targetted char. [Skotlex] - case HP_ASSUMPTIO: - if (flag&1) - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - else - { - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skillid, skilllv), BL_PC, - src, skillid, skilllv, tick, flag|BCT_ALL|1, - skill_castend_nodamage_id); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - */ - case SM_ENDURE: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - if (sd) - skill_blockpc_start(sd, skillid, skill_get_time2(skillid,skilllv)); - break; - - case AS_ENCHANTPOISON: // Prevent spamming [Valaris] - if (sd && dstsd && dstsd->sc.count) { - if (dstsd->sc.data[SC_FIREWEAPON] || - dstsd->sc.data[SC_WATERWEAPON] || - dstsd->sc.data[SC_WINDWEAPON] || - dstsd->sc.data[SC_EARTHWEAPON] || - dstsd->sc.data[SC_SHADOWWEAPON] || - dstsd->sc.data[SC_GHOSTWEAPON] - // dstsd->sc.data[SC_ENCPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex] - ) { - clif_skill_nodamage(src,bl,skillid,skilllv,0); - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - } - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - break; - - case LK_TENSIONRELAX: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start4(bl,type,100,skilllv,0,0,skill_get_time2(skillid,skilllv), - skill_get_time(skillid,skilllv))); - break; - - case MC_CHANGECART: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - - case TK_MISSION: - if (sd) { - int id; - if (sd->mission_mobid && (sd->mission_count || rnd()%100)) { //Cannot change target when already have one - clif_mission_info(sd, sd->mission_mobid, sd->mission_count); - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - id = mob_get_random_id(0,0xF, sd->status.base_level); - if (!id) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - sd->mission_mobid = id; - sd->mission_count = 0; - pc_setglobalreg(sd,"TK_MISSION_ID", id); - clif_mission_info(sd, id, 0); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case AC_CONCENTRATION: { - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - map_foreachinrange(status_change_timer_sub, src, - skill_get_splash(skillid, skilllv), BL_CHAR, - src,NULL,type,tick); - } - break; - - case SM_PROVOKE: - case SM_SELFPROVOKE: - case MER_PROVOKE: - if ((tstatus->mode&MD_BOSS) || battle_check_undead(tstatus->race,tstatus->def_ele)) { - map_freeblock_unlock(); - return 1; - } - //TODO: How much does base level affects? Dummy value of 1% per level difference used. [Skotlex] - clif_skill_nodamage(src,bl,skillid == SM_SELFPROVOKE ? SM_PROVOKE : skillid,skilllv, - (i = sc_start(bl,type, skillid == SM_SELFPROVOKE ? 100:(50 + 3*skilllv + status_get_lv(src) - status_get_lv(bl)), skilllv, skill_get_time(skillid,skilllv)))); - if (!i) { - if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; - } - unit_skillcastcancel(bl, 2); - - if (tsc && tsc->count) { - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - if (tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE) - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER); - } - - if (dstmd) { - dstmd->state.provoke_flag = src->id; - mob_target(dstmd, src, skill_get_range2(src,skillid,skilllv)); - } - break; - - case ML_DEVOTION: - case CR_DEVOTION: { - int count, lv; - if (!dstsd || (!sd && !mer)) { - // Only players can be devoted - if (sd) - clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); - break; - } - - if ((lv = status_get_lv(src) - dstsd->status.base_level) < 0) - lv = -lv; - if (lv > battle_config.devotion_level_difference || // Level difference requeriments - (dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || // Cannot Devote a player devoted from another source - (skillid == ML_DEVOTION && (!mer || mer != dstsd->md)) || // Mercenary only can devote owner - (dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER || // Crusader Cannot be devoted - (dstsd->sc.data[SC_HELLPOWER])) { // Players affected by SC_HELLPOWERR cannot be devoted. - if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; - } - - i = 0; - count = (sd)? min(skilllv,5) : 1; // Mercenary only can Devote owner - if (sd) { - // Player Devoting Player - ARR_FIND(0, count, i, sd->devotion[i] == bl->id); - if (i == count) { - ARR_FIND(0, count, i, sd->devotion[i] == 0); - if (i == count) { - // No free slots, skill Fail - clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); - map_freeblock_unlock(); - return 1; - } - } - - sd->devotion[i] = bl->id; - } else - mer->devotion_flag = 1; // Mercenary Devoting Owner - - clif_skill_nodamage(src, bl, skillid, skilllv, - sc_start4(bl, type, 100, src->id, i, skill_get_range2(src,skillid,skilllv),0, skill_get_time2(skillid, skilllv))); - clif_devotion(src, NULL); - } - break; - - case MO_CALLSPIRITS: - if (sd) { - int limit = skilllv; - if (sd->sc.data[SC_RAISINGDRAGON]) - limit += sd->sc.data[SC_RAISINGDRAGON]->val1; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - pc_addspiritball(sd,skill_get_time(skillid,skilllv),limit); - } - break; - - case CH_SOULCOLLECT: - if (sd) { - int limit = 5; - if (sd->sc.data[SC_RAISINGDRAGON]) - limit += sd->sc.data[SC_RAISINGDRAGON]->val1; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - for (i = 0; i < limit; i++) - pc_addspiritball(sd,skill_get_time(skillid,skilllv),limit); - } - break; - - case MO_KITRANSLATION: - if (dstsd && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) { - pc_addspiritball(dstsd,skill_get_time(skillid,skilllv),5); - } - break; - - case TK_TURNKICK: - case MO_BALKYOUNG: //Passive part of the attack. Splash knock-back+stun. [Skotlex] - if (skill_area_temp[1] != bl->id) { - skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),-1,0); - skill_additional_effect(src,bl,skillid,skilllv,BF_MISC,ATK_DEF,tick); //Use Misc rather than weapon to signal passive pushback - } - break; - - case MO_ABSORBSPIRITS: - i = 0; - if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) { - // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen] - i = dstsd->spiritball * 7; - pc_delspiritball(dstsd,dstsd->spiritball,0); - } else if (dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20) { - // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen] - i = 2 * dstmd->level; - mob_target(dstmd,src,0); - } - if (i) status_heal(src, 0, i, 3); - clif_skill_nodamage(src,bl,skillid,skilllv,i?1:0); - break; - - case AC_MAKINGARROW: - if (sd) { - clif_arrow_create_list(sd); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case AM_PHARMACY: - if (sd) { - clif_skill_produce_mix_list(sd,skillid,22); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case SA_CREATECON: - if (sd) { - clif_elementalconverter_list(sd); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case BS_HAMMERFALL: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,SC_STUN,(20 + 10 * skilllv),skilllv,skill_get_time2(skillid,skilllv))); - break; - case RG_RAID: - skill_area_temp[1] = 0; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skillid, skilllv), splash_target(src), - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - status_change_end(src, SC_HIDING, INVALID_TIMER); - break; - - case ASC_METEORASSAULT: - case GS_SPREADATTACK: - case RK_STORMBLAST: - case NC_AXETORNADO: - case GC_COUNTERSLASH: - case SR_SKYNETBLOW: - case SR_RAMPAGEBLASTER: - case SR_HOWLINGOFLION: - case KO_HAPPOKUNAI: - skill_area_temp[1] = 0; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - i = map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), - src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); - if (!i && (skillid == NC_AXETORNADO || skillid == SR_SKYNETBLOW || skillid == KO_HAPPOKUNAI)) - clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - break; - - case NC_EMERGENCYCOOL: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - status_change_end(src,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); - status_change_end(src,SC_OVERHEAT,INVALID_TIMER); - break; - case SR_WINDMILL: - case GN_CART_TORNADO: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - case SR_EARTHSHAKER: - case NC_INFRAREDSCAN: - case NPC_EARTHQUAKE: - case NPC_VAMPIRE_GIFT: - case NPC_HELLJUDGEMENT: - case NPC_PULSESTRIKE: - case LG_MOONSLASHER: - skill_castend_damage_id(src, src, skillid, skilllv, tick, flag); - break; - - case KN_BRANDISHSPEAR: - case ML_BRANDISH: - skill_brandishspear(src, bl, skillid, skilllv, tick, flag); - break; - - case WZ_SIGHTRASHER: - //Passive side of the attack. - status_change_end(src, SC_SIGHT, INVALID_TIMER); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_area_sub,src, - skill_get_splash(skillid, skilllv),BL_CHAR|BL_SKILL, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - break; - - case NJ_HYOUSYOURAKU: - case NJ_RAIGEKISAI: - case WZ_FROSTNOVA: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_area_temp[1] = 0; - map_foreachinrange(skill_attack_area, src, - skill_get_splash(skillid, skilllv), splash_target(src), - BF_MAGIC, src, src, skillid, skilllv, tick, flag, BCT_ENEMY); - break; - - case HVAN_EXPLOSION: //[orn] - case NPC_SELFDESTRUCTION: - //Self Destruction hits everyone in range (allies+enemies) - //Except for Summoned Marine spheres on non-versus maps, where it's just enemy. - i = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))? - BCT_ENEMY:BCT_ALL; - clif_skill_nodamage(src, src, skillid, -1, 1); - map_delblock(src); //Required to prevent chain-self-destructions hitting back. - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skillid, skilllv), splash_target(src), - src, skillid, skilllv, tick, flag|i, - skill_castend_damage_id); - map_addblock(src); - status_damage(src, src, sstatus->max_hp,0,0,1); - break; - - case AL_ANGELUS: - case PR_MAGNIFICAT: - case PR_GLORIA: - case SN_WINDWALK: - case CASH_BLESSING: - case CASH_INCAGI: - case CASH_ASSUMPTIO: - if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) - clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - else if (sd) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - break; - case MER_MAGNIFICAT: - if (mer != NULL) { - clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - if (mer->master && mer->master->status.party_id != 0 && !(flag&1)) - party_foreachsamemap(skill_area_sub, mer->master, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - else if (mer->master && !(flag&1)) - clif_skill_nodamage(src, &mer->master->bl, skillid, skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - } - break; - - case BS_ADRENALINE: - case BS_ADRENALINE2: - case BS_WEAPONPERFECT: - case BS_OVERTHRUST: - if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) { - clif_skill_nodamage(bl,bl,skillid,skilllv, - sc_start2(bl,type,100,skilllv,(src == bl)? 1:0,skill_get_time(skillid,skilllv))); - } else if (sd) { - party_foreachsamemap(skill_area_sub, - sd,skill_get_splash(skillid, skilllv), - src,skillid,skilllv,tick, flag|BCT_PARTY|1, - skill_castend_nodamage_id); - } - break; - - case BS_MAXIMIZE: - case NV_TRICKDEAD: - case CR_DEFENDER: - case ML_DEFENDER: - case CR_AUTOGUARD: - case ML_AUTOGUARD: - case TK_READYSTORM: - case TK_READYDOWN: - case TK_READYTURN: - case TK_READYCOUNTER: - case TK_DODGE: - case CR_SHRINK: - case SG_FUSION: - case GS_GATLINGFEVER: - if (tsce) { - clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, INVALID_TIMER)); - map_freeblock_unlock(); - return 0; - } - clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - break; - case SL_KAITE: - case SL_KAAHI: - case SL_KAIZEL: - case SL_KAUPE: - if (sd) { - if (!dstsd || !( - (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SOULLINKER) || - (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER || - dstsd->status.char_id == sd->status.char_id || - dstsd->status.char_id == sd->status.partner_id || - dstsd->status.char_id == sd->status.child - )) { - status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,8); - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - } - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid, skilllv))); - break; - case SM_AUTOBERSERK: - case MER_AUTOBERSERK: - if (tsce) - i = status_change_end(bl, type, INVALID_TIMER); - else - i = sc_start(bl,type,100,skilllv,60000); - clif_skill_nodamage(src,bl,skillid,skilllv,i); - break; - case TF_HIDING: - case ST_CHASEWALK: - case KO_YAMIKUMO: - if (tsce) { - clif_skill_nodamage(src,bl,skillid,-1,status_change_end(bl, type, INVALID_TIMER)); //Hide skill-scream animation. - map_freeblock_unlock(); - return 0; - } else if (tsc && tsc->option&OPTION_MADOGEAR) { - //Mado Gear cannot hide - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; - } - clif_skill_nodamage(src,bl,skillid,-1,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - break; - case TK_RUN: - if (tsce) { - clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, INVALID_TIMER)); - map_freeblock_unlock(); - return 0; - } - clif_skill_nodamage(src,bl,skillid,skilllv,sc_start4(bl,type,100,skilllv,unit_getdir(bl),0,0,0)); - if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex] - clif_walkok(sd); // So aegis has to resend the walk ok. - break; - case AS_CLOAKING: - case GC_CLOAKINGEXCEED: - case LG_FORCEOFVANGUARD: - case SC_REPRODUCE: - case SC_INVISIBILITY: - if (tsce) { - i = status_change_end(bl, type, INVALID_TIMER); - if (i) - clif_skill_nodamage(src,bl,skillid,(skillid == LG_FORCEOFVANGUARD) ? skilllv : -1,i); - else if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; - } - case RA_CAMOUFLAGE: - i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - if (i) - clif_skill_nodamage(src,bl,skillid,(skillid == LG_FORCEOFVANGUARD) ? skilllv : -1,i); - else if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - - case BD_ADAPTATION: - if (tsc && tsc->data[SC_DANCING]) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - status_change_end(bl, SC_DANCING, INVALID_TIMER); - } - break; - - case BA_FROSTJOKER: - case DC_SCREAM: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_addtimerskill(src,tick+2000,bl->id,src->x,src->y,skillid,skilllv,0,flag); - - if (md) { - // custom hack to make the mob display the skill, because these skills don't show the skill use text themselves - //NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches) - char temp[70]; - snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill_db[skillid].desc); - clif_message(&md->bl,temp); - } - break; - - case BA_PANGVOICE: - clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,SC_CONFUSION,50,7,skill_get_time(skillid,skilllv))); - break; - - case DC_WINKCHARM: - if (dstsd) - clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,SC_CONFUSION,30,7,skill_get_time2(skillid,skilllv))); - else if (dstmd) { - if (status_get_lv(src) > status_get_lv(bl) - && (tstatus->race == RC_DEMON || tstatus->race == RC_DEMIHUMAN || tstatus->race == RC_ANGEL) - && !(tstatus->mode&MD_BOSS)) - clif_skill_nodamage(src,bl,skillid,skilllv, sc_start2(bl,type,70,skilllv,src->id,skill_get_time(skillid,skilllv))); - else { - clif_skill_nodamage(src,bl,skillid,skilllv,0); - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } - } - break; - - case TF_STEAL: - if (sd) { - if (pc_steal_item(sd,bl,skilllv)) - clif_skill_nodamage(src,bl,skillid,skilllv,1); - else - clif_skill_fail(sd,skillid,USESKILL_FAIL,0); - } - break; - - case RG_STEALCOIN: - if (sd) { - if (pc_steal_coin(sd,bl)) { - dstmd->state.provoke_flag = src->id; - mob_target(dstmd, src, skill_get_range2(src,skillid,skilllv)); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - - } else - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } - break; - - case MG_STONECURSE: { - if (tstatus->mode&MD_BOSS) { - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - if (status_isimmune(bl) || !tsc) - break; - - if (tsc->data[SC_STONE]) { - status_change_end(bl, SC_STONE, INVALID_TIMER); - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - if (sc_start4(bl,SC_STONE,(skilllv*4+20), - skilllv, 0, 0, skill_get_time(skillid, skilllv), - skill_get_time2(skillid,skilllv))) - clif_skill_nodamage(src,bl,skillid,skilllv,1); - else if (sd) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - // Level 6-10 doesn't consume a red gem if it fails [celest] - if (skilllv > 5) { - // not to consume items - map_freeblock_unlock(); - return 0; - } - } - } - break; - - case NV_FIRSTAID: - clif_skill_nodamage(src,bl,skillid,5,1); - status_heal(bl,5,0,0); - break; - - case AL_CURE: - if (status_isimmune(bl)) { - clif_skill_nodamage(src,bl,skillid,skilllv,0); - break; - } - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - status_change_end(bl, SC_CONFUSION, INVALID_TIMER); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - - case TF_DETOXIFY: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - status_change_end(bl, SC_POISON, INVALID_TIMER); - status_change_end(bl, SC_DPOISON, INVALID_TIMER); - break; - - case PR_STRECOVERY: - if (status_isimmune(bl)) { - clif_skill_nodamage(src,bl,skillid,skilllv,0); - break; - } - if (tsc && tsc->opt1) { - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); - status_change_end(bl, SC_WHITEIMPRISON, INVALID_TIMER); - } - //Is this equation really right? It looks so... special. - if (battle_check_undead(tstatus->race,tstatus->def_ele)) { - status_change_start(bl, SC_BLIND, - 100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), - 1,0,0,0, - skill_get_time2(skillid, skilllv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0); - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (dstmd) - mob_unlocktarget(dstmd,tick); - break; - - // Mercenary Supportive Skills - case MER_BENEDICTION: - status_change_end(bl, SC_CURSE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case MER_COMPRESS: - status_change_end(bl, SC_BLEEDING, INVALID_TIMER); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case MER_MENTALCURE: - status_change_end(bl, SC_CONFUSION, INVALID_TIMER); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case MER_RECUPERATE: - status_change_end(bl, SC_POISON, INVALID_TIMER); - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case MER_REGAIN: - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case MER_TENDER: - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - - case MER_SCAPEGOAT: - if (mer && mer->master) { - status_heal(&mer->master->bl, mer->battle_status.hp, 0, 2); - status_damage(src, src, mer->battle_status.max_hp, 0, 0, 1); - } - break; - - case MER_ESTIMATION: - if (!mer) - break; - sd = mer->master; - case WZ_ESTIMATION: - if (sd == NULL) - break; - if (dstsd) { - // Fail on Players - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - if (dstmd && dstmd->class_ == MOBID_EMPERIUM) - break; // Cannot be Used on Emperium - - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - clif_skill_estimation(sd, bl); - if (skillid == MER_ESTIMATION) - sd = NULL; - break; - - case BS_REPAIRWEAPON: - if (sd && dstsd) - clif_item_repair_list(sd,dstsd,skilllv); - break; + struct map_session_data *sd, *dstsd; + struct mob_data *md, *dstmd; + struct homun_data *hd; + struct mercenary_data *mer; + struct status_data *sstatus, *tstatus; + struct status_change *tsc; + struct status_change_entry *tsce; + + int i = 0; + enum sc_type type; + + if(skillid > 0 && skilllv <= 0) return 0; // celest + + nullpo_retr(1, src); + nullpo_retr(1, bl); + + if (src->m != bl->m) + return 1; + + sd = BL_CAST(BL_PC, src); + hd = BL_CAST(BL_HOM, src); + md = BL_CAST(BL_MOB, src); + mer = BL_CAST(BL_MER, src); + + dstsd = BL_CAST(BL_PC, bl); + dstmd = BL_CAST(BL_MOB, bl); + + if(bl->prev == NULL) + return 1; + if(status_isdead(src)) + return 1; + + if( src != bl && status_isdead(bl) ) { + /** + * Skills that may be cast on dead targets + **/ + switch( skillid ) { + case NPC_WIDESOULDRAIN: + case PR_REDEMPTIO: + case ALL_RESURRECTION: + case WM_DEADHILLHERE: + break; + default: + return 1; + } + } - case MC_IDENTIFY: - if (sd) - clif_item_identify_list(sd); - break; + tstatus = status_get_status_data(bl); + sstatus = status_get_status_data(src); - // Weapon Refining [Celest] - case WS_WEAPONREFINE: - if (sd) - clif_item_refine_list(sd); - break; + //Check for undead skills that convert a no-damage skill into a damage one. [Skotlex] + switch (skillid) { + case HLIF_HEAL: //[orn] + if (bl->type != BL_HOM) { + if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0) ; + break ; + } + case AL_HEAL: + case ALL_RESURRECTION: + case PR_ASPERSIO: + /** + * Arch Bishop + **/ + case AB_RENOVATIO: + case AB_HIGHNESSHEAL: + //Apparently only player casted skills can be offensive like this. + if (sd && battle_check_undead(tstatus->race,tstatus->def_ele)) { + if (battle_check_target(src, bl, BCT_ENEMY) < 1) { + //Offensive heal does not works on non-enemies. [Skotlex] + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + return 0; + } + return skill_castend_damage_id (src, bl, skillid, skilllv, tick, flag); + } + break; + case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex] + return skill_castend_damage_id (src, bl, skillid, skilllv, tick, flag); + case MH_STEINWAND: { + struct block_list *s_src = battle_get_master(src); + short ret = 0; + if(!skill_check_unit_range(src, src->x, src->y, skillid, skilllv)) //prevent reiteration + ret = skill_castend_pos2(src,src->x,src->y,skillid,skilllv,tick,flag); //cast on homon + if(s_src && !skill_check_unit_range(s_src, s_src->x, s_src->y, skillid, skilllv)) + ret |= skill_castend_pos2(s_src,s_src->x,s_src->y,skillid,skilllv,tick,flag); //cast on master + if (hd) + skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + return ret; + } + break; + default: + //Skill is actually ground placed. + if (src == bl && skill_get_unit_id(skillid,0)) + return skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0); + } - case MC_VENDING: - if (sd) { - //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex] - if (!pc_can_give_items(sd)) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - else { - sd->state.prevend = 1; - clif_openvendingreq(sd,2+skilllv); - } - } - break; + type = status_skill2sc(skillid); + tsc = status_get_sc(bl); + tsce = (tsc && type != -1)?tsc->data[type]:NULL; + + if (src!=bl && type > -1 && + (i = skill_get_ele(skillid, skilllv)) > ELE_NEUTRAL && + skill_get_inf(skillid) != INF_SUPPORT_SKILL && + battle_attr_fix(NULL, NULL, 100, i, tstatus->def_ele, tstatus->ele_lv) <= 0) + return 1; //Skills that cause an status should be blocked if the target element blocks its element. + + map_freeblock_lock(); + switch(skillid) + { + case HLIF_HEAL: //[orn] + case AL_HEAL: + /** + * Arch Bishop + **/ + case AB_HIGHNESSHEAL: + { + int heal = skill_calc_heal(src, bl, (skillid == AB_HIGHNESSHEAL)?AL_HEAL:skillid, (skillid == AB_HIGHNESSHEAL)?10:skilllv, true); + int heal_get_jobexp; + //Highness Heal: starts at 1.5 boost + 0.5 for each level + if( skillid == AB_HIGHNESSHEAL ) { + heal = heal * ( 15 + 5 * skilllv ) / 10; + } + if( status_isimmune(bl) || + (dstmd && (dstmd->class_ == MOBID_EMPERIUM || mob_is_battleground(dstmd))) || + (dstsd && pc_ismadogear(dstsd)) )//Mado is immune to heal + heal=0; - case AL_TELEPORT: - if (sd) { - if (map[bl->m].flag.noteleport && skilllv <= 2) { - clif_skill_teleportmessage(sd,0); - break; - } - if (!battle_config.duel_allow_teleport && sd->duel_group && skilllv <= 2) { // duel restriction [LuzZza] - char output[128]; - sprintf(output, msg_txt(365), skill_get_name(AL_TELEPORT)); - clif_displaymessage(sd->fd, output); //"Duel: Can't use %s in duel." - break; - } + if( sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0 ) + heal = heal*2; - if (sd->state.autocast || ((sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skilllv == 1) || skilllv == 3) { - if (skilllv == 1) - pc_randomwarp(sd,CLR_TELEPORT); - else - pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - break; - } + if( tsc && tsc->count ) + { + if( tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS) ) + { //Bounce back heal + if (--tsc->data[SC_KAITE]->val2 <= 0) + status_change_end(bl, SC_KAITE, INVALID_TIMER); + if (src == bl) + heal=0; //When you try to heal yourself under Kaite, the heal is voided. + else { + bl = src; + dstsd = sd; + } + } + else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAYNIGHTFEVER] || tsc->data[SC__BLOODYLUST]) + heal = 0; //Needed so that it actually displays 0 when healing. + } + clif_skill_nodamage (src, bl, skillid, heal, 1); + if( tsc && tsc->data[SC_AKAITSUKI] && heal && skillid != HLIF_HEAL ) + heal = ~heal + 1; + heal_get_jobexp = status_heal(bl,heal,0,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) + heal_get_jobexp = 1; + pc_gainexp (sd, bl, 0, heal_get_jobexp, false); + } + } + break; + + case PR_REDEMPTIO: + if (sd && !(flag&1)) { + if (sd->status.party_id == 0) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + skill_area_temp[0] = 0; + party_foreachsamemap(skill_area_sub, + sd,skill_get_splash(skillid, skilllv), + src,skillid,skilllv,tick, flag|BCT_PARTY|1, + skill_castend_nodamage_id); + if (skill_area_temp[0] == 0) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty... + if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty) { //Apply penalty + sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * skill_area_temp[0] * 2/1000); //0.2% penalty per each. + sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * skill_area_temp[0] * 2/1000); + clif_updatestatus(sd,SP_BASEEXP); + clif_updatestatus(sd,SP_JOBEXP); + } + status_set_hp(src, 1, 0); + status_set_sp(src, 0, 0); + break; + } else if (status_isdead(bl) && flag&1) { //Revive + skill_area_temp[0]++; //Count it in, then fall-through to the Resurrection code. + skilllv = 3; //Resurrection level 3 is used + } else //Invalid target, skip resurrection. + break; + + case ALL_RESURRECTION: + if(sd && (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)) + { //No reviving in WoE grounds! + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + if (!status_isdead(bl)) + break; + { + int per = 0, sper = 0; + if (tsc && tsc->data[SC_HELLPOWER]) + break; + + if (map[bl->m].flag.pvp && dstsd && dstsd->pvp_point < 0) + break; + + switch(skilllv){ + case 1: per=10; break; + case 2: per=30; break; + case 3: per=50; break; + case 4: per=80; break; + } + if(dstsd && dstsd->special_state.restart_full_recover) + per = sper = 100; + if (status_revive(bl, per, sper)) + { + clif_skill_nodamage(src,bl,ALL_RESURRECTION,skilllv,1); //Both Redemptio and Res show this skill-animation. + if(sd && dstsd && battle_config.resurrection_exp > 0) + { + int exp = 0,jexp = 0; + int lv = dstsd->status.base_level - sd->status.base_level, jlv = dstsd->status.job_level - sd->status.job_level; + if(lv > 0 && pc_nextbaseexp(dstsd)) { + exp = (int)((double)dstsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); + if (exp < 1) exp = 1; + } + if(jlv > 0 && pc_nextjobexp(dstsd)) { + 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, bl, exp, jexp, false); + } + } + } + break; + + case AL_DECAGI: + case MER_DECAGI: + clif_skill_nodamage (src, bl, skillid, skilllv, + sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), skilllv, skill_get_time(skillid,skilllv))); + break; + + case AL_CRUCIS: + if (flag&1) + sc_start(bl,type, 23+skilllv*4 +status_get_lv(src) -status_get_lv(bl), skilllv,skill_get_time(skillid,skilllv)); + else { + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid, skilllv), BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + } + break; + + case PR_LEXDIVINA: + case MER_LEXDIVINA: + if( tsce ) + status_change_end(bl,type, INVALID_TIMER); + else + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + break; + + case SA_ABRACADABRA: + { + int abra_skillid = 0, abra_skilllv; + do { + i = rnd() % MAX_SKILL_ABRA_DB; + abra_skillid = skill_abra_db[i].skillid; + } while (abra_skillid == 0 || + skill_abra_db[i].req_lv > skilllv || //Required lv for it to appear + rnd()%10000 >= skill_abra_db[i].per + ); + abra_skilllv = min(skilllv, skill_get_max(abra_skillid)); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + + if( sd ) + {// player-casted + sd->state.abra_flag = 1; + sd->skillitem = abra_skillid; + sd->skillitemlv = abra_skilllv; + clif_item_skill(sd, abra_skillid, abra_skilllv); + } + else + {// mob-casted + struct unit_data *ud = unit_bl2ud(src); + int inf = skill_get_inf(abra_skillid); + int target_id = 0; + if (!ud) break; + if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { + if (src->type == BL_PET) + bl = (struct block_list*)((TBL_PET*)src)->msd; + if (!bl) bl = src; + unit_skilluse_id(src, bl->id, abra_skillid, abra_skilllv); + } else { //Assume offensive skills + if (ud->target) + target_id = ud->target; + else switch (src->type) { + case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; + case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; + } + if (!target_id) + break; + if (skill_get_casttype(abra_skillid) == CAST_GROUND) { + bl = map_id2bl(target_id); + if (!bl) bl = src; + unit_skilluse_pos(src, bl->x, bl->y, abra_skillid, abra_skilllv); + } else + unit_skilluse_id(src, target_id, abra_skillid, abra_skilllv); + } + } + } + break; + + case SA_COMA: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time2(skillid,skilllv))); + break; + case SA_FULLRECOVERY: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if (status_isimmune(bl)) + break; + status_percent_heal(bl, 100, 100); + break; + case NPC_ALLHEAL: + { + int heal; + if( status_isimmune(bl) ) + break; + heal = status_percent_heal(bl, 100, 0); + clif_skill_nodamage(NULL, bl, AL_HEAL, heal, 1); + if( dstmd ) + { // Reset Damage Logs + memset(dstmd->dmglog, 0, sizeof(dstmd->dmglog)); + dstmd->tdmg = 0; + } + } + break; + case SA_SUMMONMONSTER: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if (sd) mob_once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_SMALL, AI_NONE); + break; + case SA_LEVELUP: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd, NULL, pc_nextbaseexp(sd) * 10 / 100, 0, false); + break; + case SA_INSTANTDEATH: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + status_set_hp(bl,1,0); + break; + case SA_QUESTION: + case SA_GRAVITY: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + case SA_CLASSCHANGE: + case SA_MONOCELL: + if (dstmd) + { + int class_; + if ( sd && dstmd->status.mode&MD_BOSS ) + { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + class_ = skillid==SA_MONOCELL?1002:mob_get_random_id(4, 1, 0); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + mob_class_change(dstmd,class_); + if( tsc && dstmd->status.mode&MD_BOSS ) + { + const enum sc_type scs[] = { SC_QUAGMIRE, SC_PROVOKE, SC_ROKISWEIL, SC_GRAVITATION, SC_SUITON, SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC_BLADESTOP }; + for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) + if (tsc->data[i]) status_change_end(bl, (sc_type)i, INVALID_TIMER); + for (i = 0; i < ARRAYLENGTH(scs); i++) + if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); + } + } + break; + case SA_DEATH: + if ( sd && dstmd && dstmd->status.mode&MD_BOSS ) + { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + status_kill(bl); + break; + case SA_REVERSEORCISH: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid, skilllv))); + break; + case SA_FORTUNE: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(sd) pc_getzeny(sd,status_get_lv(bl)*100,LOG_TYPE_STEAL,NULL); + break; + case SA_TAMINGMONSTER: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if (sd && dstmd) { + ARR_FIND( 0, MAX_PET_DB, i, dstmd->class_ == pet_db[i].class_ ); + if( i < MAX_PET_DB ) + pet_catch_process1(sd, dstmd->class_); + } + break; + + case CR_PROVIDENCE: + if(sd && dstsd){ //Check they are not another crusader [Skotlex] + if ((dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; + } + } + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + break; + + case CG_MARIONETTE: + { + struct status_change* sc = status_get_sc(src); + + if( sd && dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex ) + {// Cannot cast on another bard/dancer-type class of the same gender as caster + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; + } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (skilllv == 1) - clif_skill_warppoint(sd,skillid,skilllv, (unsigned short)-1,0,0,0); - else - clif_skill_warppoint(sd,skillid,skilllv, (unsigned short)-1,sd->status.save_point.map,0,0); - } else - unit_warp(bl,-1,-1,-1,CLR_TELEPORT); - break; + if( sc && tsc ) + { + if( !sc->data[SC_MARIONETTE] && !tsc->data[SC_MARIONETTE2] ) + { + sc_start(src,SC_MARIONETTE,100,bl->id,skill_get_time(skillid,skilllv)); + sc_start(bl,SC_MARIONETTE2,100,src->id,skill_get_time(skillid,skilllv)); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + else + if( sc->data[SC_MARIONETTE ] && sc->data[SC_MARIONETTE ]->val1 == bl->id && + tsc->data[SC_MARIONETTE2] && tsc->data[SC_MARIONETTE2]->val1 == src->id ) + { + status_change_end(src, SC_MARIONETTE, INVALID_TIMER); + status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER); + } + else + { + if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - case NPC_EXPULSION: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - unit_warp(bl,-1,-1,-1,CLR_TELEPORT); - break; + map_freeblock_unlock(); + return 1; + } + } + } + break; + + case RG_CLOSECONFINE: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start4(bl,type,100,skilllv,src->id,0,0,skill_get_time(skillid,skilllv))); + 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 (dstsd) { + if(dstsd->status.weapon == W_FIST || + (dstsd->sc.count && !dstsd->sc.data[type] && + ( //Allow re-enchanting to lenghten time. [Skotlex] + dstsd->sc.data[SC_FIREWEAPON] || + dstsd->sc.data[SC_WATERWEAPON] || + dstsd->sc.data[SC_WINDWEAPON] || + dstsd->sc.data[SC_EARTHWEAPON] || + dstsd->sc.data[SC_SHADOWWEAPON] || + dstsd->sc.data[SC_GHOSTWEAPON] || + dstsd->sc.data[SC_ENCPOISON] + )) + ) { + if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + clif_skill_nodamage(src,bl,skillid,skilllv,0); + break; + } + } + // 100% success rate at lv4 & 5, but lasts longer at lv5 + if(!clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,type,(60+skilllv*10),skilllv, skill_get_time(skillid,skilllv)))) { + if (sd) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + if (skill_break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) && sd && sd != dstsd) + clif_displaymessage(sd->fd, msg_txt(669)); + } + break; + + case PR_ASPERSIO: + if (sd && dstmd) { + clif_skill_nodamage(src,bl,skillid,skilllv,0); + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + break; + + case ITEM_ENCHANTARMS: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start2(bl,type,100,skilllv, + skill_get_ele(skillid,skilllv), skill_get_time(skillid,skilllv))); + break; + + case TK_SEVENWIND: + switch(skill_get_ele(skillid,skilllv)) { + case ELE_EARTH : type = SC_EARTHWEAPON; break; + case ELE_WIND : type = SC_WINDWEAPON; break; + case ELE_WATER : type = SC_WATERWEAPON; break; + case ELE_FIRE : type = SC_FIREWEAPON; break; + case ELE_GHOST : type = SC_GHOSTWEAPON; break; + case ELE_DARK : type = SC_SHADOWWEAPON; break; + case ELE_HOLY : type = SC_ASPERSIO; break; + } + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + + sc_start(bl,SC_SEVENWIND,100,skilllv,skill_get_time(skillid,skilllv)); + + break; + + case PR_KYRIE: + case MER_KYRIE: + clif_skill_nodamage(bl,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + break; + //Passive Magnum, should had been casted on yourself. + case SM_MAGNUM: + case MS_MAGNUM: + skill_area_temp[1] = 0; + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid, skilllv), BL_SKILL|BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, skill_castend_damage_id); + clif_skill_nodamage (src,src,skillid,skilllv,1); + // Initiate 10% of your damage becomes fire element. + sc_start4(src,SC_WATK_ELEMENT,100,3,20,0,0,skill_get_time2(skillid, skilllv)); + if( sd ) + skill_blockpc_start(sd, skillid, skill_get_time(skillid, skilllv)); + else if( bl->type == BL_MER ) + skill_blockmerc_start((TBL_MER*)bl, skillid, skill_get_time(skillid, skilllv)); + break; + + case TK_JUMPKICK: + /* Check if the target is an enemy; if not, skill should fail so the character doesn't unit_movepos (exploitable) */ + if( battle_check_target(src, bl, BCT_ENEMY) > 0 ) + { + if( unit_movepos(src, bl->x, bl->y, 1, 1) ) + { + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + clif_slide(src,bl->x,bl->y); + } + } + else + clif_skill_fail(sd,skillid,USESKILL_FAIL,0); + break; + + case AL_INCAGI: + case AL_BLESSING: + case MER_INCAGI: + case MER_BLESSING: + if (dstsd != NULL && tsc->data[SC_CHANGEUNDEAD]) { + skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); + break; + } + case PR_SLOWPOISON: + case PR_IMPOSITIO: + case PR_LEXAETERNA: + case PR_SUFFRAGIUM: + case PR_BENEDICTIO: + case LK_BERSERK: + case MS_BERSERK: + case KN_AUTOCOUNTER: + case KN_TWOHANDQUICKEN: + case KN_ONEHAND: + case MER_QUICKEN: + case CR_SPEARQUICKEN: + case CR_REFLECTSHIELD: + case MS_REFLECTSHIELD: + case AS_POISONREACT: + case MC_LOUD: + case MG_ENERGYCOAT: + case MO_EXPLOSIONSPIRITS: + case MO_STEELBODY: + case MO_BLADESTOP: + case LK_AURABLADE: + case LK_PARRYING: + case MS_PARRYING: + case LK_CONCENTRATION: + case WS_CARTBOOST: + case SN_SIGHT: + case WS_MELTDOWN: + case WS_OVERTHRUSTMAX: + case ST_REJECTSWORD: + case HW_MAGICPOWER: + case PF_MEMORIZE: + case PA_SACRIFICE: + case ASC_EDP: + case PF_DOUBLECASTING: + case SG_SUN_COMFORT: + case SG_MOON_COMFORT: + case SG_STAR_COMFORT: + case NPC_HALLUCINATION: + case GS_MADNESSCANCEL: + case GS_ADJUSTMENT: + case GS_INCREASING: + case NJ_KASUMIKIRI: + case NJ_UTSUSEMI: + case NJ_NEN: + case NPC_DEFENDER: + case NPC_MAGICMIRROR: + case ST_PRESERVE: + case NPC_INVINCIBLE: + case NPC_INVINCIBLEOFF: + case RK_DEATHBOUND: + case AB_RENOVATIO: + case AB_EXPIATIO: + case AB_DUPLELIGHT: + case AB_SECRAMENT: + case NC_ACCELERATION: + case NC_HOVERING: + case NC_SHAPESHIFT: + case WL_RECOGNIZEDSPELL: + case GC_VENOMIMPRESS: + case SC_DEADLYINFECT: + case LG_EXEEDBREAK: + case LG_PRESTIGE: + case SR_CRESCENTELBOW: + case SR_LIGHTNINGWALK: + case SR_GENTLETOUCH_ENERGYGAIN: + case GN_CARTBOOST: + case KO_MEIKYOUSISUI: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + break; + + case SO_STRIKING: + if (sd) { + int bonus = 25 + 10 * skilllv; + bonus += (pc_checkskill(sd, SA_FLAMELAUNCHER)+pc_checkskill(sd, SA_FROSTWEAPON)+pc_checkskill(sd, SA_LIGHTNINGLOADER)+pc_checkskill(sd, SA_SEISMICWEAPON))*5; + clif_skill_nodamage( src, bl, skillid, skilllv, + battle_check_target(src,bl,BCT_PARTY) ? + sc_start2(bl, type, 100, skilllv, bonus, skill_get_time(skillid,skilllv)) : + 0 + ); + } + break; + + case NPC_STOP: + if( clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start2(bl,type,100,skilllv,src->id,skill_get_time(skillid,skilllv)) ) ) + sc_start2(src,type,100,skilllv,bl->id,skill_get_time(skillid,skilllv)); + break; + case HP_ASSUMPTIO: + if( sd && dstmd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + else + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + break; + case MG_SIGHT: + case MER_SIGHT: + case AL_RUWACH: + case WZ_SIGHTBLASTER: + case NPC_WIDESIGHT: + case NPC_STONESKIN: + case NPC_ANTIMAGIC: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start2(bl,type,100,skilllv,skillid,skill_get_time(skillid,skilllv))); + break; + case HLIF_AVOID: + case HAMI_DEFENCE: + i = skill_get_time(skillid,skilllv); + clif_skill_nodamage(bl,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,i)); // Master + clif_skill_nodamage(src,src,skillid,skilllv,sc_start(src,type,100,skilllv,i)); // Homunc + break; + case NJ_BUNSINJYUTSU: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + status_change_end(bl, SC_NEN, INVALID_TIMER); + break; +/* Was modified to only affect targetted char. [Skotlex] + case HP_ASSUMPTIO: + if (flag&1) + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + else + { + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv), BL_PC, + src, skillid, skilllv, tick, flag|BCT_ALL|1, + skill_castend_nodamage_id); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; +*/ + case SM_ENDURE: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + if (sd) + skill_blockpc_start (sd, skillid, skill_get_time2(skillid,skilllv)); + break; + + case AS_ENCHANTPOISON: // Prevent spamming [Valaris] + if (sd && dstsd && dstsd->sc.count) { + if (dstsd->sc.data[SC_FIREWEAPON] || + dstsd->sc.data[SC_WATERWEAPON] || + dstsd->sc.data[SC_WINDWEAPON] || + dstsd->sc.data[SC_EARTHWEAPON] || + dstsd->sc.data[SC_SHADOWWEAPON] || + dstsd->sc.data[SC_GHOSTWEAPON] + // dstsd->sc.data[SC_ENCPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex] + ) { + clif_skill_nodamage(src,bl,skillid,skilllv,0); + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + } + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + break; + + case LK_TENSIONRELAX: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start4(bl,type,100,skilllv,0,0,skill_get_time2(skillid,skilllv), + skill_get_time(skillid,skilllv))); + break; + + case MC_CHANGECART: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + + case TK_MISSION: + if (sd) { + int id; + if (sd->mission_mobid && (sd->mission_count || rnd()%100)) { //Cannot change target when already have one + clif_mission_info(sd, sd->mission_mobid, sd->mission_count); + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + id = mob_get_random_id(0,0xF, sd->status.base_level); + if (!id) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + sd->mission_mobid = id; + sd->mission_count = 0; + pc_setglobalreg(sd,"TK_MISSION_ID", id); + clif_mission_info(sd, id, 0); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case AC_CONCENTRATION: + { + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + map_foreachinrange( status_change_timer_sub, src, + skill_get_splash(skillid, skilllv), BL_CHAR, + src,NULL,type,tick); + } + break; + + case SM_PROVOKE: + case SM_SELFPROVOKE: + case MER_PROVOKE: + if( (tstatus->mode&MD_BOSS) || battle_check_undead(tstatus->race,tstatus->def_ele) ) + { + map_freeblock_unlock(); + return 1; + } + //TODO: How much does base level affects? Dummy value of 1% per level difference used. [Skotlex] + clif_skill_nodamage(src,bl,skillid == SM_SELFPROVOKE ? SM_PROVOKE : skillid,skilllv, + (i = sc_start(bl,type, skillid == SM_SELFPROVOKE ? 100:( 50 + 3*skilllv + status_get_lv(src) - status_get_lv(bl)), skilllv, skill_get_time(skillid,skilllv)))); + if( !i ) + { + if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } + unit_skillcastcancel(bl, 2); + + if( tsc && tsc->count ) + { + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + if( tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE ) + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER); + } + + if( dstmd ) + { + dstmd->state.provoke_flag = src->id; + mob_target(dstmd, src, skill_get_range2(src,skillid,skilllv)); + } + break; + + case ML_DEVOTION: + case CR_DEVOTION: + { + int count, lv; + if( !dstsd || (!sd && !mer) ) + { // Only players can be devoted + if( sd ) + clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); + break; + } - case AL_HOLYWATER: - if (sd) { - if (skill_produce_mix(sd, skillid, 523, 0, 0, 0, 1)) - clif_skill_nodamage(src,bl,skillid,skilllv,1); - else - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } - break; + if( (lv = status_get_lv(src) - dstsd->status.base_level) < 0 ) + lv = -lv; + if( lv > battle_config.devotion_level_difference || // Level difference requeriments + (dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || // Cannot Devote a player devoted from another source + (skillid == ML_DEVOTION && (!mer || mer != dstsd->md)) || // Mercenary only can devote owner + (dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER || // Crusader Cannot be devoted + (dstsd->sc.data[SC_HELLPOWER])) // Players affected by SC_HELLPOWERR cannot be devoted. + { + if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; + } - case TF_PICKSTONE: - if (sd) { - int eflag; - struct item item_tmp; - struct block_list tbl; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - memset(&item_tmp,0,sizeof(item_tmp)); - memset(&tbl,0,sizeof(tbl)); // [MouseJstr] - item_tmp.nameid = ITEMID_STONE; - item_tmp.identify = 1; - tbl.id = 0; - clif_takeitem(&sd->bl,&tbl); - eflag = pc_additem(sd,&item_tmp,1,LOG_TYPE_PRODUCE); - if (eflag) { - clif_additem(sd,0,0,eflag); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - break; - case ASC_CDP: - if (sd) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_produce_mix(sd, skillid, 678, 0, 0, 0, 1); //Produce a Deadly Poison Bottle. - } - break; + i = 0; + count = (sd)? min(skilllv,5) : 1; // Mercenary only can Devote owner + if( sd ) + { // Player Devoting Player + ARR_FIND(0, count, i, sd->devotion[i] == bl->id ); + if( i == count ) + { + ARR_FIND(0, count, i, sd->devotion[i] == 0 ); + if( i == count ) + { // No free slots, skill Fail + clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); + map_freeblock_unlock(); + return 1; + } + } - case RG_STRIPWEAPON: - case RG_STRIPSHIELD: - case RG_STRIPARMOR: - case RG_STRIPHELM: - case ST_FULLSTRIP: - case GC_WEAPONCRUSH: - case SC_STRIPACCESSARY: { - unsigned short location = 0; - int d = 0; - - //Rate in percent - if (skillid == ST_FULLSTRIP) { - i = 5 + 2*skilllv + (sstatus->dex - tstatus->dex)/5; - } else if (skillid == SC_STRIPACCESSARY) { - i = 12 + 2 * skilllv + (sstatus->dex - tstatus->dex)/5; - } else { - i = 5 + 5*skilllv + (sstatus->dex - tstatus->dex)/5; - } + sd->devotion[i] = bl->id; + } + else + mer->devotion_flag = 1; // Mercenary Devoting Owner + + clif_skill_nodamage(src, bl, skillid, skilllv, + sc_start4(bl, type, 100, src->id, i, skill_get_range2(src,skillid,skilllv),0, skill_get_time2(skillid, skilllv))); + clif_devotion(src, NULL); + } + break; + + case MO_CALLSPIRITS: + if(sd) { + int limit = skilllv; + if( sd->sc.data[SC_RAISINGDRAGON] ) + limit += sd->sc.data[SC_RAISINGDRAGON]->val1; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + pc_addspiritball(sd,skill_get_time(skillid,skilllv),limit); + } + break; + + case CH_SOULCOLLECT: + if(sd) { + int limit = 5; + if( sd->sc.data[SC_RAISINGDRAGON] ) + limit += sd->sc.data[SC_RAISINGDRAGON]->val1; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + for (i = 0; i < limit; i++) + pc_addspiritball(sd,skill_get_time(skillid,skilllv),limit); + } + break; + + case MO_KITRANSLATION: + if(dstsd && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) { + pc_addspiritball(dstsd,skill_get_time(skillid,skilllv),5); + } + break; + + case TK_TURNKICK: + case MO_BALKYOUNG: //Passive part of the attack. Splash knock-back+stun. [Skotlex] + if (skill_area_temp[1] != bl->id) { + skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),-1,0); + skill_additional_effect(src,bl,skillid,skilllv,BF_MISC,ATK_DEF,tick); //Use Misc rather than weapon to signal passive pushback + } + break; + + case MO_ABSORBSPIRITS: + i = 0; + if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) + { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen] + i = dstsd->spiritball * 7; + pc_delspiritball(dstsd,dstsd->spiritball,0); + } else if (dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20) + { // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen] + i = 2 * dstmd->level; + mob_target(dstmd,src,0); + } + if (i) status_heal(src, 0, i, 3); + clif_skill_nodamage(src,bl,skillid,skilllv,i?1:0); + break; + + case AC_MAKINGARROW: + if(sd) { + clif_arrow_create_list(sd); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case AM_PHARMACY: + if(sd) { + clif_skill_produce_mix_list(sd,skillid,22); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case SA_CREATECON: + if(sd) { + clif_elementalconverter_list(sd); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case BS_HAMMERFALL: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,SC_STUN,(20 + 10 * skilllv),skilllv,skill_get_time2(skillid,skilllv))); + break; + case RG_RAID: + skill_area_temp[1] = 0; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv), splash_target(src), + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); + status_change_end(src, SC_HIDING, INVALID_TIMER); + break; + + case ASC_METEORASSAULT: + case GS_SPREADATTACK: + case RK_STORMBLAST: + case NC_AXETORNADO: + case GC_COUNTERSLASH: + case SR_SKYNETBLOW: + case SR_RAMPAGEBLASTER: + case SR_HOWLINGOFLION: + case KO_HAPPOKUNAI: + skill_area_temp[1] = 0; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + i = map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), + src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); + if( !i && ( skillid == NC_AXETORNADO || skillid == SR_SKYNETBLOW || skillid == KO_HAPPOKUNAI ) ) + clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + break; + + case NC_EMERGENCYCOOL: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + status_change_end(src,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); + status_change_end(src,SC_OVERHEAT,INVALID_TIMER); + break; + case SR_WINDMILL: + case GN_CART_TORNADO: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + case SR_EARTHSHAKER: + case NC_INFRAREDSCAN: + case NPC_EARTHQUAKE: + case NPC_VAMPIRE_GIFT: + case NPC_HELLJUDGEMENT: + case NPC_PULSESTRIKE: + case LG_MOONSLASHER: + skill_castend_damage_id(src, src, skillid, skilllv, tick, flag); + break; + + case KN_BRANDISHSPEAR: + case ML_BRANDISH: + skill_brandishspear(src, bl, skillid, skilllv, tick, flag); + break; + + case WZ_SIGHTRASHER: + //Passive side of the attack. + status_change_end(src, SC_SIGHT, INVALID_TIMER); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub,src, + skill_get_splash(skillid, skilllv),BL_CHAR|BL_SKILL, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); + break; + + case NJ_HYOUSYOURAKU: + case NJ_RAIGEKISAI: + case WZ_FROSTNOVA: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_area_temp[1] = 0; + map_foreachinrange(skill_attack_area, src, + skill_get_splash(skillid, skilllv), splash_target(src), + BF_MAGIC, src, src, skillid, skilllv, tick, flag, BCT_ENEMY); + break; + + case HVAN_EXPLOSION: //[orn] + case NPC_SELFDESTRUCTION: + //Self Destruction hits everyone in range (allies+enemies) + //Except for Summoned Marine spheres on non-versus maps, where it's just enemy. + i = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))? + BCT_ENEMY:BCT_ALL; + clif_skill_nodamage(src, src, skillid, -1, 1); + map_delblock(src); //Required to prevent chain-self-destructions hitting back. + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv), splash_target(src), + src, skillid, skilllv, tick, flag|i, + skill_castend_damage_id); + map_addblock(src); + status_damage(src, src, sstatus->max_hp,0,0,1); + break; + + case AL_ANGELUS: + case PR_MAGNIFICAT: + case PR_GLORIA: + case SN_WINDWALK: + case CASH_BLESSING: + case CASH_INCAGI: + case CASH_ASSUMPTIO: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + else if( sd ) + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + break; + case MER_MAGNIFICAT: + if( mer != NULL ) + { + clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + if( mer->master && mer->master->status.party_id != 0 && !(flag&1) ) + party_foreachsamemap(skill_area_sub, mer->master, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + else if( mer->master && !(flag&1) ) + clif_skill_nodamage(src, &mer->master->bl, skillid, skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + } + break; + + case BS_ADRENALINE: + case BS_ADRENALINE2: + case BS_WEAPONPERFECT: + case BS_OVERTHRUST: + if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) { + clif_skill_nodamage(bl,bl,skillid,skilllv, + sc_start2(bl,type,100,skilllv,(src == bl)? 1:0,skill_get_time(skillid,skilllv))); + } else if (sd) { + party_foreachsamemap(skill_area_sub, + sd,skill_get_splash(skillid, skilllv), + src,skillid,skilllv,tick, flag|BCT_PARTY|1, + skill_castend_nodamage_id); + } + break; + + case BS_MAXIMIZE: + case NV_TRICKDEAD: + case CR_DEFENDER: + case ML_DEFENDER: + case CR_AUTOGUARD: + case ML_AUTOGUARD: + case TK_READYSTORM: + case TK_READYDOWN: + case TK_READYTURN: + case TK_READYCOUNTER: + case TK_DODGE: + case CR_SHRINK: + case SG_FUSION: + case GS_GATLINGFEVER: + if( tsce ) + { + clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, INVALID_TIMER)); + map_freeblock_unlock(); + return 0; + } + clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + break; + case SL_KAITE: + case SL_KAAHI: + case SL_KAIZEL: + case SL_KAUPE: + if (sd) { + if (!dstsd || !( + (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SOULLINKER) || + (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER || + dstsd->status.char_id == sd->status.char_id || + dstsd->status.char_id == sd->status.partner_id || + dstsd->status.char_id == sd->status.child + )) { + status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,8); + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + } + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid, skilllv))); + break; + case SM_AUTOBERSERK: + case MER_AUTOBERSERK: + if( tsce ) + i = status_change_end(bl, type, INVALID_TIMER); + else + i = sc_start(bl,type,100,skilllv,60000); + clif_skill_nodamage(src,bl,skillid,skilllv,i); + break; + case TF_HIDING: + case ST_CHASEWALK: + case KO_YAMIKUMO: + if (tsce) + { + clif_skill_nodamage(src,bl,skillid,-1,status_change_end(bl, type, INVALID_TIMER)); //Hide skill-scream animation. + map_freeblock_unlock(); + return 0; + } else if( tsc && tsc->option&OPTION_MADOGEAR ) { + //Mado Gear cannot hide + if( sd ) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } + clif_skill_nodamage(src,bl,skillid,-1,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + break; + case TK_RUN: + if (tsce) + { + clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, INVALID_TIMER)); + map_freeblock_unlock(); + return 0; + } + clif_skill_nodamage(src,bl,skillid,skilllv,sc_start4(bl,type,100,skilllv,unit_getdir(bl),0,0,0)); + if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex] + clif_walkok(sd); // So aegis has to resend the walk ok. + break; + case AS_CLOAKING: + case GC_CLOAKINGEXCEED: + case LG_FORCEOFVANGUARD: + case SC_REPRODUCE: + case SC_INVISIBILITY: + if (tsce) { + i = status_change_end(bl, type, INVALID_TIMER); + if( i ) + clif_skill_nodamage(src,bl,skillid,( skillid == LG_FORCEOFVANGUARD ) ? skilllv : -1,i); + else if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } + case RA_CAMOUFLAGE: + i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + if( i ) + clif_skill_nodamage(src,bl,skillid,( skillid == LG_FORCEOFVANGUARD ) ? skilllv : -1,i); + else if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + + case BD_ADAPTATION: + if(tsc && tsc->data[SC_DANCING]){ + clif_skill_nodamage(src,bl,skillid,skilllv,1); + status_change_end(bl, SC_DANCING, INVALID_TIMER); + } + break; + + case BA_FROSTJOKER: + case DC_SCREAM: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_addtimerskill(src,tick+2000,bl->id,src->x,src->y,skillid,skilllv,0,flag); + + if (md) { + // custom hack to make the mob display the skill, because these skills don't show the skill use text themselves + //NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches) + char temp[70]; + snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill_db[skillid].desc); + clif_message(&md->bl,temp); + } + break; + + case BA_PANGVOICE: + clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,SC_CONFUSION,50,7,skill_get_time(skillid,skilllv))); + break; + + case DC_WINKCHARM: + if( dstsd ) + clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,SC_CONFUSION,30,7,skill_get_time2(skillid,skilllv))); + else + if( dstmd ) + { + if( status_get_lv(src) > status_get_lv(bl) + && (tstatus->race == RC_DEMON || tstatus->race == RC_DEMIHUMAN || tstatus->race == RC_ANGEL) + && !(tstatus->mode&MD_BOSS) ) + clif_skill_nodamage(src,bl,skillid,skilllv, sc_start2(bl,type,70,skilllv,src->id,skill_get_time(skillid,skilllv))); + else + { + clif_skill_nodamage(src,bl,skillid,skilllv,0); + if(sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } + } + break; + + case TF_STEAL: + if(sd) { + if(pc_steal_item(sd,bl,skilllv)) + clif_skill_nodamage(src,bl,skillid,skilllv,1); + else + clif_skill_fail(sd,skillid,USESKILL_FAIL,0); + } + break; + + case RG_STEALCOIN: + if(sd) { + if(pc_steal_coin(sd,bl)) + { + dstmd->state.provoke_flag = src->id; + mob_target(dstmd, src, skill_get_range2(src,skillid,skilllv)); + clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (i < 5) i = 5; //Minimum rate 5% - - //Duration in ms - if (skillid == GC_WEAPONCRUSH) { - d = skill_get_time(skillid,skilllv); - if (bl->type == BL_PC) - d += skilllv * 15 + (sstatus->dex - tstatus->dex); - else - d += skilllv * 30 + (sstatus->dex - tstatus->dex) / 2; - } else - d = skill_get_time(skillid,skilllv) + (sstatus->dex - tstatus->dex)*500; - - if (d < 0) d = 0; //Minimum duration 0ms - - switch (skillid) { - case RG_STRIPWEAPON: - case GC_WEAPONCRUSH: - location = EQP_WEAPON; - break; - case RG_STRIPSHIELD: - location = EQP_SHIELD; - break; - case RG_STRIPARMOR: - location = EQP_ARMOR; - break; - case RG_STRIPHELM: - location = EQP_HELM; - break; - case ST_FULLSTRIP: - location = EQP_WEAPON|EQP_SHIELD|EQP_ARMOR|EQP_HELM; - break; - case SC_STRIPACCESSARY: - location = EQP_ACC; - break; - } + } + else + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } + break; + + case MG_STONECURSE: + { + if (tstatus->mode&MD_BOSS) { + if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + if(status_isimmune(bl) || !tsc) + break; - //Special message when trying to use strip on FCP [Jobbie] - if (sd && skillid == ST_FULLSTRIP && tsc && tsc->data[SC_CP_WEAPON] && tsc->data[SC_CP_HELM] && tsc->data[SC_CP_ARMOR] && tsc->data[SC_CP_SHIELD]) { - clif_gospel_info(sd, 0x28); - break; - } + if (tsc->data[SC_STONE]) { + status_change_end(bl, SC_STONE, INVALID_TIMER); + if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + if (sc_start4(bl,SC_STONE,(skilllv*4+20), + skilllv, 0, 0, skill_get_time(skillid, skilllv), + skill_get_time2(skillid,skilllv))) + clif_skill_nodamage(src,bl,skillid,skilllv,1); + else if(sd) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + // Level 6-10 doesn't consume a red gem if it fails [celest] + if (skilllv > 5) + { // not to consume items + map_freeblock_unlock(); + return 0; + } + } + } + break; + + case NV_FIRSTAID: + clif_skill_nodamage(src,bl,skillid,5,1); + status_heal(bl,5,0,0); + break; + + case AL_CURE: + if(status_isimmune(bl)) { + clif_skill_nodamage(src,bl,skillid,skilllv,0); + break; + } + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + status_change_end(bl, SC_CONFUSION, INVALID_TIMER); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + + case TF_DETOXIFY: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + status_change_end(bl, SC_POISON, INVALID_TIMER); + status_change_end(bl, SC_DPOISON, INVALID_TIMER); + break; + + case PR_STRECOVERY: + if(status_isimmune(bl)) { + clif_skill_nodamage(src,bl,skillid,skilllv,0); + break; + } + if (tsc && tsc->opt1) { + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + status_change_end(bl, SC_WHITEIMPRISON, INVALID_TIMER); + } + //Is this equation really right? It looks so... special. + if(battle_check_undead(tstatus->race,tstatus->def_ele)) + { + status_change_start(bl, SC_BLIND, + 100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), + 1,0,0,0, + skill_get_time2(skillid, skilllv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0); + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(dstmd) + mob_unlocktarget(dstmd,tick); + break; + + // Mercenary Supportive Skills + case MER_BENEDICTION: + status_change_end(bl, SC_CURSE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + case MER_COMPRESS: + status_change_end(bl, SC_BLEEDING, INVALID_TIMER); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + case MER_MENTALCURE: + status_change_end(bl, SC_CONFUSION, INVALID_TIMER); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + case MER_RECUPERATE: + status_change_end(bl, SC_POISON, INVALID_TIMER); + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + case MER_REGAIN: + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + case MER_TENDER: + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + + case MER_SCAPEGOAT: + if( mer && mer->master ) + { + status_heal(&mer->master->bl, mer->battle_status.hp, 0, 2); + status_damage(src, src, mer->battle_status.max_hp, 0, 0, 1); + } + break; + + case MER_ESTIMATION: + if( !mer ) + break; + sd = mer->master; + case WZ_ESTIMATION: + if( sd == NULL ) + break; + if( dstsd ) + { // Fail on Players + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) + break; // Cannot be Used on Emperium + + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + clif_skill_estimation(sd, bl); + if( skillid == MER_ESTIMATION ) + sd = NULL; + break; + + case BS_REPAIRWEAPON: + if(sd && dstsd) + clif_item_repair_list(sd,dstsd,skilllv); + break; + + case MC_IDENTIFY: + if(sd) + clif_item_identify_list(sd); + break; + + // Weapon Refining [Celest] + case WS_WEAPONREFINE: + if(sd) + clif_item_refine_list(sd); + break; + + case MC_VENDING: + if(sd) + { //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex] + if ( !pc_can_give_items(sd) ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + else { + sd->state.prevend = 1; + clif_openvendingreq(sd,2+skilllv); + } + } + break; + + case AL_TELEPORT: + if(sd) + { + if (map[bl->m].flag.noteleport && skilllv <= 2) { + clif_skill_teleportmessage(sd,0); + break; + } + if(!battle_config.duel_allow_teleport && sd->duel_group && skilllv <= 2) { // duel restriction [LuzZza] + char output[128]; sprintf(output, msg_txt(365), skill_get_name(AL_TELEPORT)); + clif_displaymessage(sd->fd, output); //"Duel: Can't use %s in duel." + break; + } - //Attempts to strip at rate i and duration d - if ((i = skill_strip_equip(bl, location, i, skilllv, d)) || (skillid != ST_FULLSTRIP && skillid != GC_WEAPONCRUSH)) - clif_skill_nodamage(src,bl,skillid,skilllv,i); + if( sd->state.autocast || ( (sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skilllv == 1 ) || skilllv == 3 ) + { + if( skilllv == 1 ) + pc_randomwarp(sd,CLR_TELEPORT); + else + pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + break; + } - //Nothing stripped. - if (sd && !i) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if( skilllv == 1 ) + clif_skill_warppoint(sd,skillid,skilllv, (unsigned short)-1,0,0,0); + else + clif_skill_warppoint(sd,skillid,skilllv, (unsigned short)-1,sd->status.save_point.map,0,0); + } else + unit_warp(bl,-1,-1,-1,CLR_TELEPORT); + break; + + case NPC_EXPULSION: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + unit_warp(bl,-1,-1,-1,CLR_TELEPORT); + break; + + case AL_HOLYWATER: + if(sd) { + if (skill_produce_mix(sd, skillid, 523, 0, 0, 0, 1)) + clif_skill_nodamage(src,bl,skillid,skilllv,1); + else + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } + break; + + case TF_PICKSTONE: + if(sd) { + int eflag; + struct item item_tmp; + struct block_list tbl; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + memset(&item_tmp,0,sizeof(item_tmp)); + memset(&tbl,0,sizeof(tbl)); // [MouseJstr] + item_tmp.nameid = ITEMID_STONE; + item_tmp.identify = 1; + tbl.id = 0; + clif_takeitem(&sd->bl,&tbl); + eflag = pc_additem(sd,&item_tmp,1,LOG_TYPE_PRODUCE); + if(eflag) { + clif_additem(sd,0,0,eflag); + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + break; + case ASC_CDP: + if(sd) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_produce_mix(sd, skillid, 678, 0, 0, 0, 1); //Produce a Deadly Poison Bottle. + } + break; + + case RG_STRIPWEAPON: + case RG_STRIPSHIELD: + case RG_STRIPARMOR: + case RG_STRIPHELM: + case ST_FULLSTRIP: + case GC_WEAPONCRUSH: + case SC_STRIPACCESSARY: { + unsigned short location = 0; + int d = 0; + + //Rate in percent + if ( skillid == ST_FULLSTRIP ) { + i = 5 + 2*skilllv + (sstatus->dex - tstatus->dex)/5; + } else if( skillid == SC_STRIPACCESSARY ) { + i = 12 + 2 * skilllv + (sstatus->dex - tstatus->dex)/5; + } else { + i = 5 + 5*skilllv + (sstatus->dex - tstatus->dex)/5; + } + + if (i < 5) i = 5; //Minimum rate 5% + + //Duration in ms + if( skillid == GC_WEAPONCRUSH){ + d = skill_get_time(skillid,skilllv); + if(bl->type == BL_PC) + d += skilllv * 15 + (sstatus->dex - tstatus->dex); + else + d += skilllv * 30 + (sstatus->dex - tstatus->dex) / 2; + }else + d = skill_get_time(skillid,skilllv) + (sstatus->dex - tstatus->dex)*500; + + if (d < 0) d = 0; //Minimum duration 0ms + + switch (skillid) { + case RG_STRIPWEAPON: + case GC_WEAPONCRUSH: + location = EQP_WEAPON; + break; + case RG_STRIPSHIELD: + location = EQP_SHIELD; + break; + case RG_STRIPARMOR: + location = EQP_ARMOR; + break; + case RG_STRIPHELM: + location = EQP_HELM; + break; + case ST_FULLSTRIP: + location = EQP_WEAPON|EQP_SHIELD|EQP_ARMOR|EQP_HELM; + break; + case SC_STRIPACCESSARY: + location = EQP_ACC; + break; + } + + //Special message when trying to use strip on FCP [Jobbie] + if( sd && skillid == ST_FULLSTRIP && tsc && tsc->data[SC_CP_WEAPON] && tsc->data[SC_CP_HELM] && tsc->data[SC_CP_ARMOR] && tsc->data[SC_CP_SHIELD]) + { + clif_gospel_info(sd, 0x28); + break; + } + + //Attempts to strip at rate i and duration d + if( (i = skill_strip_equip(bl, location, i, skilllv, d)) || (skillid != ST_FULLSTRIP && skillid != GC_WEAPONCRUSH ) ) + clif_skill_nodamage(src,bl,skillid,skilllv,i); + + //Nothing stripped. + if( sd && !i ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } - case AM_BERSERKPITCHER: - case AM_POTIONPITCHER: { - int i,x,hp = 0,sp = 0,bonus=100; - if (dstmd && dstmd->class_ == MOBID_EMPERIUM) { - map_freeblock_unlock(); - return 1; - } - if (sd) { - x = skilllv%11 - 1; - i = pc_search_inventory(sd,skill_db[skillid].itemid[x]); - if (i < 0 || skill_db[skillid].itemid[x] <= 0) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; - } - if (sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skillid].amount[x]) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; - } - if (skillid == AM_BERSERKPITCHER) { - if (dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; - } - } - potion_flag = 1; - potion_hp = potion_sp = potion_per_hp = potion_per_sp = 0; - potion_target = bl->id; - run_script(sd->inventory_data[i]->script,0,sd->bl.id,0); - potion_flag = potion_target = 0; - if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ALCHEMIST) - bonus += sd->status.base_level; - if (potion_per_hp > 0 || potion_per_sp > 0) { - hp = tstatus->max_hp * potion_per_hp / 100; - hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - if (dstsd) { - sp = dstsd->status.max_sp * potion_per_sp / 100; - sp = sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - } - } else { - if (potion_hp > 0) { - hp = potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - hp = hp * (100 + (tstatus->vit<<1)) / 100; - if (dstsd) - hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; - } - if (potion_sp > 0) { - sp = potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - sp = sp * (100 + (tstatus->int_<<1)) / 100; - if (dstsd) - sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100; - } - } + case AM_BERSERKPITCHER: + case AM_POTIONPITCHER: { + int i,x,hp = 0,sp = 0,bonus=100; + if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) { + map_freeblock_unlock(); + return 1; + } + if( sd ) { + x = skilllv%11 - 1; + i = pc_search_inventory(sd,skill_db[skillid].itemid[x]); + if( i < 0 || skill_db[skillid].itemid[x] <= 0 ) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; + } + if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skillid].amount[x]) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; + } + if( skillid == AM_BERSERKPITCHER ) { + if( dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv ) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; + } + } + potion_flag = 1; + potion_hp = potion_sp = potion_per_hp = potion_per_sp = 0; + potion_target = bl->id; + run_script(sd->inventory_data[i]->script,0,sd->bl.id,0); + potion_flag = potion_target = 0; + if( sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ALCHEMIST ) + bonus += sd->status.base_level; + if( potion_per_hp > 0 || potion_per_sp > 0 ) { + hp = tstatus->max_hp * potion_per_hp / 100; + hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + if( dstsd ) { + sp = dstsd->status.max_sp * potion_per_sp / 100; + sp = sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + } + } else { + if( potion_hp > 0 ) { + hp = potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + hp = hp * (100 + (tstatus->vit<<1)) / 100; + if( dstsd ) + hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; + } + if( potion_sp > 0 ) { + sp = potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + sp = sp * (100 + (tstatus->int_<<1)) / 100; + if( dstsd ) + sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100; + } + } - if (sd->itemgrouphealrate[IG_POTION]>0) { - hp += hp * sd->itemgrouphealrate[IG_POTION] / 100; - sp += sp * sd->itemgrouphealrate[IG_POTION] / 100; - } + if (sd->itemgrouphealrate[IG_POTION]>0) { + hp += hp * sd->itemgrouphealrate[IG_POTION] / 100; + sp += sp * sd->itemgrouphealrate[IG_POTION] / 100; + } - if ((i = pc_skillheal_bonus(sd, skillid))) { - hp += hp * i / 100; - sp += sp * i / 100; - } - } else { - hp = (1 + rnd()%400) * (100 + skilllv*10) / 100; - hp = hp * (100 + (tstatus->vit<<1)) / 100; - if (dstsd) - hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; - } - if (dstsd && (i = pc_skillheal2_bonus(dstsd, skillid))) { - hp += hp * i / 100; - sp += sp * i / 100; - } - if (tsc && tsc->count) { - if (tsc->data[SC_CRITICALWOUND]) { - hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - } - if (tsc->data[SC_DEATHHURT]) { - hp -= hp * 20 / 100; - sp -= sp * 20 / 100; - } - if (tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2) { - hp += hp / 10; - sp += sp / 10; - } - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (hp > 0 || (skillid == AM_POTIONPITCHER && sp <= 0)) - clif_skill_nodamage(NULL,bl,AL_HEAL,hp,1); - if (sp > 0) - clif_skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); + if( (i = pc_skillheal_bonus(sd, skillid)) ) { + hp += hp * i / 100; + sp += sp * i / 100; + } + } else { + hp = (1 + rnd()%400) * (100 + skilllv*10) / 100; + hp = hp * (100 + (tstatus->vit<<1)) / 100; + if( dstsd ) + hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; + } + if( dstsd && (i = pc_skillheal2_bonus(dstsd, skillid)) ) { + hp += hp * i / 100; + sp += sp * i / 100; + } + if( tsc && tsc->count ) { + if( tsc->data[SC_CRITICALWOUND] ) { + hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + } + if( tsc->data[SC_DEATHHURT] ) { + hp -= hp * 20 / 100; + sp -= sp * 20 / 100; + } + if( tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2 ) { + hp += hp / 10; + sp += sp / 10; + } + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if( hp > 0 || (skillid == AM_POTIONPITCHER && sp <= 0) ) + clif_skill_nodamage(NULL,bl,AL_HEAL,hp,1); + if( sp > 0 ) + clif_skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); #ifdef RENEWAL - if (tsc && tsc->data[SC_EXTREMITYFIST2]) - sp = 0; + if( tsc && tsc->data[SC_EXTREMITYFIST2] ) + sp = 0; #endif - status_heal(bl,hp,sp,0); - } - break; - case AM_CP_WEAPON: - case AM_CP_SHIELD: - case AM_CP_ARMOR: - case AM_CP_HELM: { - unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; - - if (sd && (bl->type != BL_PC || (dstsd && pc_checkequip(dstsd,equip[skillid - AM_CP_WEAPON]) < 0))) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); // Don't consume item requirements - return 0; - } + status_heal(bl,hp,sp,0); + } + break; + case AM_CP_WEAPON: + case AM_CP_SHIELD: + case AM_CP_ARMOR: + case AM_CP_HELM: + { + unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; + + if( sd && ( bl->type != BL_PC || ( dstsd && pc_checkequip(dstsd,equip[skillid - AM_CP_WEAPON]) < 0 ) ) ){ + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); // Don't consume item requirements + return 0; + } - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - } - break; - case AM_TWILIGHT1: - if (sd) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - //Prepare 200 White Potions. - if (!skill_produce_mix(sd, skillid, 504, 0, 0, 0, 200)) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } - break; - case AM_TWILIGHT2: - if (sd) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - //Prepare 200 Slim White Potions. - if (!skill_produce_mix(sd, skillid, 547, 0, 0, 0, 200)) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } - break; - case AM_TWILIGHT3: - if (sd) { - int ebottle = pc_search_inventory(sd,713); - if (ebottle >= 0) - ebottle = sd->status.inventory[ebottle].amount; - //check if you can produce all three, if not, then fail: - if (!skill_can_produce_mix(sd,970,-1, 100) //100 Alcohol - || !skill_can_produce_mix(sd,7136,-1, 50) //50 Acid Bottle - || !skill_can_produce_mix(sd,7135,-1, 50) //50 Flame Bottle - || ebottle < 200 //200 empty bottle are required at total. - ) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_produce_mix(sd, skillid, 970, 0, 0, 0, 100); - skill_produce_mix(sd, skillid, 7136, 0, 0, 0, 50); - skill_produce_mix(sd, skillid, 7135, 0, 0, 0, 50); - } - break; - case SA_DISPELL: - if (flag&1 || (i = skill_get_splash(skillid, skilllv)) < 1) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if ((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) - || (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_ROGUE) //Rogue's spirit defends againt dispel. - || rnd()%100 >= 50+10*skilllv - || (tsc && tsc->option&OPTION_MADOGEAR)) { //Mado Gear is immune to dispell according to bug report 49 [Ind] - if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - if (status_isimmune(bl) || !tsc || !tsc->count) - break; - for (i=0; i<SC_MAX; i++) { - if (!tsc->data[i]) - continue; - switch (i) { - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_HALLUCINATION: - 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: - case SC_COMBO: - case SC_STRFOOD: - case SC_AGIFOOD: - case SC_VITFOOD: - case SC_INTFOOD: - case SC_DEXFOOD: - case SC_LUKFOOD: - case SC_HITFOOD: - case SC_FLEEFOOD: - case SC_BATKFOOD: - case SC_WATKFOOD: - case SC_MATKFOOD: - case SC_DANCING: - case SC_EDP: - case SC_AUTOBERSERK: - case SC_CARTBOOST: - case SC_MELTDOWN: - case SC_SAFETYWALL: - case SC_SMA: - case SC_SPEEDUP0: - case SC_NOCHAT: - case SC_ANKLE: - case SC_SPIDERWEB: - case SC_JAILED: - case SC_ITEMBOOST: - case SC_EXPBOOST: - case SC_LIFEINSURANCE: - case SC_BOSSMAPINFO: - case SC_PNEUMA: - case SC_AUTOSPELL: - case SC_INCHITRATE: - case SC_INCATKRATE: - case SC_NEN: - case SC_READYSTORM: - case SC_READYDOWN: - case SC_READYTURN: - case SC_READYCOUNTER: - case SC_DODGE: - case SC_WARM: - case SC_SPEEDUP1: - case SC_AUTOTRADE: - case SC_CRITICALWOUND: - case SC_JEXPBOOST: - case SC_INVINCIBLE: - case SC_INVINCIBLEOFF: - case SC_HELLPOWER: - case SC_MANU_ATK: - case SC_MANU_DEF: - case SC_SPL_ATK: - case SC_SPL_DEF: - case SC_MANU_MATK: - case SC_SPL_MATK: - case SC_RICHMANKIM: - case SC_ETERNALCHAOS: - case SC_DRUMBATTLE: - case SC_NIBELUNGEN: - case SC_ROKISWEIL: - case SC_INTOABYSS: - case SC_SIEGFRIED: - case SC_FOOD_STR_CASH: - case SC_FOOD_AGI_CASH: - case SC_FOOD_VIT_CASH: - case SC_FOOD_DEX_CASH: - case SC_FOOD_INT_CASH: - case SC_FOOD_LUK_CASH: - case SC_SEVENWIND: - case SC_MIRACLE: - case SC_S_LIFEPOTION: - case SC_L_LIFEPOTION: - case SC_INCHEALRATE: - case SC_ELECTRICSHOCKER: - case SC__STRIPACCESSORY: - //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: case SC_MINOR_BBQ: - //case SC_SIROMA_ICE_TEA: case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: - case SC_NEUTRALBARRIER_MASTER: - case SC_NEUTRALBARRIER: - case SC_STEALTHFIELD_MASTER: - case SC_STEALTHFIELD: - case SC_GIANTGROWTH: - case SC_MILLENNIUMSHIELD: - case SC_REFRESH: - case SC_STONEHARDSKIN: - case SC_VITALITYACTIVATION: - case SC_FIGHTINGSPIRIT: - case SC_ABUNDANCE: - case SC__SHADOWFORM: - case SC_LEADERSHIP: - case SC_GLORYWOUNDS: - case SC_SOULCOLD: - case SC_HAWKEYES: - case SC_GUILDAURA: - case SC_PUSH_CART: - case SC_RAISINGDRAGON: - case SC_GT_ENERGYGAIN: - case SC_GT_CHANGE: - case SC_GT_REVITALIZE: - case SC_REFLECTDAMAGE: - case SC_INSPIRATION: - case SC_EXEEDBREAK: - case SC_FORCEOFVANGUARD: - case SC_BANDING: - case SC_DUPLELIGHT: - case SC_EXPIATIO: - case SC_LAUDAAGNUS: - case SC_LAUDARAMUS: - case SC_GATLINGFEVER: - case SC_INCREASING: - case SC_ADJUSTMENT: - case SC_MADNESSCANCEL: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + } + break; + case AM_TWILIGHT1: + if (sd) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + //Prepare 200 White Potions. + if (!skill_produce_mix(sd, skillid, 504, 0, 0, 0, 200)) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } + break; + case AM_TWILIGHT2: + if (sd) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + //Prepare 200 Slim White Potions. + if (!skill_produce_mix(sd, skillid, 547, 0, 0, 0, 200)) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } + break; + case AM_TWILIGHT3: + if (sd) { + int ebottle = pc_search_inventory(sd,713); + if( ebottle >= 0 ) + ebottle = sd->status.inventory[ebottle].amount; + //check if you can produce all three, if not, then fail: + if (!skill_can_produce_mix(sd,970,-1, 100) //100 Alcohol + || !skill_can_produce_mix(sd,7136,-1, 50) //50 Acid Bottle + || !skill_can_produce_mix(sd,7135,-1, 50) //50 Flame Bottle + || ebottle < 200 //200 empty bottle are required at total. + ) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_produce_mix(sd, skillid, 970, 0, 0, 0, 100); + skill_produce_mix(sd, skillid, 7136, 0, 0, 0, 50); + skill_produce_mix(sd, skillid, 7135, 0, 0, 0, 50); + } + break; + case SA_DISPELL: + if (flag&1 || (i = skill_get_splash(skillid, skilllv)) < 1) + { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) + || (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_ROGUE) //Rogue's spirit defends againt dispel. + || rnd()%100 >= 50+10*skilllv + || ( tsc && tsc->option&OPTION_MADOGEAR ) )//Mado Gear is immune to dispell according to bug report 49 [Ind] + { + if (sd) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + if(status_isimmune(bl) || !tsc || !tsc->count) + break; + for(i=0;i<SC_MAX;i++) + { + if (!tsc->data[i]) + continue; + switch (i) { + case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION: + 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: case SC_COMBO: + case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD: + case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD: + case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD: + case SC_WATKFOOD: case SC_MATKFOOD: case SC_DANCING: + case SC_EDP: case SC_AUTOBERSERK: + case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL: + case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT: + case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED: + case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE: + case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL: + case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN: + case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN: + case SC_READYCOUNTER: case SC_DODGE: case SC_WARM: + case SC_SPEEDUP1: case SC_AUTOTRADE: case SC_CRITICALWOUND: + case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF: + case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF: + case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK: + case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS: + case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL: + case SC_INTOABYSS: case SC_SIEGFRIED: case SC_FOOD_STR_CASH: + case SC_FOOD_AGI_CASH: case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: + case SC_FOOD_INT_CASH: case SC_FOOD_LUK_CASH: case SC_SEVENWIND: + case SC_MIRACLE: case SC_S_LIFEPOTION: case SC_L_LIFEPOTION: + case SC_INCHEALRATE: case SC_ELECTRICSHOCKER: case SC__STRIPACCESSORY: + //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: case SC_MINOR_BBQ: + //case SC_SIROMA_ICE_TEA: case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: + case SC_NEUTRALBARRIER_MASTER: case SC_NEUTRALBARRIER: case SC_STEALTHFIELD_MASTER: + case SC_STEALTHFIELD: case SC_GIANTGROWTH: case SC_MILLENNIUMSHIELD: + case SC_REFRESH: case SC_STONEHARDSKIN: case SC_VITALITYACTIVATION: + case SC_FIGHTINGSPIRIT: case SC_ABUNDANCE: case SC__SHADOWFORM: + case SC_LEADERSHIP: case SC_GLORYWOUNDS: case SC_SOULCOLD: + case SC_HAWKEYES: case SC_GUILDAURA: case SC_PUSH_CART: + case SC_RAISINGDRAGON: case SC_GT_ENERGYGAIN: case SC_GT_CHANGE: + case SC_GT_REVITALIZE: case SC_REFLECTDAMAGE: case SC_INSPIRATION: + case SC_EXEEDBREAK: case SC_FORCEOFVANGUARD: case SC_BANDING: + case SC_DUPLELIGHT: case SC_EXPIATIO: case SC_LAUDAAGNUS: + case SC_LAUDARAMUS: case SC_GATLINGFEVER: case SC_INCREASING: + case SC_ADJUSTMENT: case SC_MADNESSCANCEL: #ifdef RENEWAL - case SC_EXTREMITYFIST2: -#endif - continue; - /** - * bugreport:4888 these songs may only be dispelled if you're not in their song area anymore - **/ - case SC_WHISTLE: - case SC_ASSNCROS: - case SC_POEMBRAGI: - case SC_APPLEIDUN: - case SC_HUMMING: - case SC_DONTFORGETME: - case SC_FORTUNE: - case SC_SERVICE4U: - if (tsc->data[i]->val4) //val4 = out-of-song-area - continue; - break; - case SC_ASSUMPTIO: - if (bl->type == BL_MOB) - continue; - break; - } - if (i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. - status_change_end(bl, (sc_type)i, INVALID_TIMER); - } - break; - } - //Affect all targets on splash area. - map_foreachinrange(skill_area_sub, bl, i, BL_CHAR, - src, skillid, skilllv, tick, flag|1, - skill_castend_damage_id); - break; - - case TF_BACKSLIDING: //This is the correct implementation as per packet logging information. [Skotlex] - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),unit_getdir(bl),0); - break; - - case TK_HIGHJUMP: { - int x,y, dir = unit_getdir(src); - - //Fails on noteleport maps, except for GvG and BG maps [Skotlex] - if (map[src->m].flag.noteleport && - !(map[src->m].flag.battleground || map_flag_gvg2(src->m)) - ) { - x = src->x; - y = src->y; - } else { - x = src->x + dirx[dir]*skilllv*2; - y = src->y + diry[dir]*skilllv*2; - } - - clif_skill_nodamage(src,bl,TK_HIGHJUMP,skilllv,1); - if (!map_count_oncell(src->m,x,y,BL_PC|BL_NPC|BL_MOB) && map_getcell(src->m,x,y,CELL_CHKREACH)) { - clif_slide(src,x,y); - unit_movepos(src, x, y, 1, 0); - } - } - break; - - case SA_CASTCANCEL: - case SO_SPELLFIST: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - unit_skillcastcancel(src,1); - if (sd) { - int sp = skill_get_sp(sd->skillid_old,sd->skilllv_old); - if (skillid == SO_SPELLFIST) { - sc_start4(src,type,100,skilllv+1,skilllv,sd->skillid_old,sd->skilllv_old,skill_get_time(skillid,skilllv)); - sd->skillid_old = sd->skilllv_old = 0; - break; - } - sp = sp * (90 - (skilllv-1)*20) / 100; - if (sp < 0) sp = 0; - status_zap(src, 0, sp); - } - break; - case SA_SPELLBREAKER: { - int sp; - if (tsc && tsc->data[SC_MAGICROD]) { - sp = skill_get_sp(skillid,skilllv); - sp = sp * tsc->data[SC_MAGICROD]->val2 / 100; - if (sp < 1) sp = 1; - status_heal(bl,0,sp,2); - status_percent_damage(bl, src, 0, -20, false); //20% max SP damage. - } else { - struct unit_data *ud = unit_bl2ud(bl); - int bl_skillid=0,bl_skilllv=0,hp = 0; - if (!ud || ud->skilltimer == INVALID_TIMER) - break; //Nothing to cancel. - bl_skillid = ud->skillid; - bl_skilllv = ud->skilllv; - if (tstatus->mode & MD_BOSS) { - //Only 10% success chance against bosses. [Skotlex] - if (rnd()%100 < 90) { - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - } else if (!dstsd || map_flag_vs(bl->m)) //HP damage only on pvp-maps when against players. - hp = tstatus->max_hp/50; //Recover 2% HP [Skotlex] - - clif_skill_nodamage(src,bl,skillid,skilllv,1); - unit_skillcastcancel(bl,0); - sp = skill_get_sp(bl_skillid,bl_skilllv); - status_zap(bl, hp, sp); - - if (hp && skilllv >= 5) - hp>>=1; //Recover half damaged HP at level 5 [Skotlex] - else - hp = 0; - - if (sp) //Recover some of the SP used - sp = sp*(25*(skilllv-1))/100; - - if (hp || sp) - status_heal(src, hp, sp, 2); - } - } - break; - case SA_MAGICROD: - clif_skill_nodamage(src,src,SA_MAGICROD,skilllv,1); - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - break; - case SA_AUTOSPELL: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd) - clif_autospell(sd,skilllv); - else { - int maxlv=1,spellid=0; - static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT }; - if (skilllv >= 10) { - spellid = MG_FROSTDIVER; - // if (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SA_SAGE) - // maxlv = 10; - // else - maxlv = skilllv - 9; - } else if (skilllv >=8) { - spellid = MG_FIREBALL; - maxlv = skilllv - 7; - } else if (skilllv >=5) { - spellid = MG_SOULSTRIKE; - maxlv = skilllv - 4; - } else if (skilllv >=2) { - int i = rnd()%3; - spellid = spellarray[i]; - maxlv = skilllv - 1; - } else if (skilllv > 0) { - spellid = MG_NAPALMBEAT; - maxlv = 3; - } - if (spellid > 0) - sc_start4(src,SC_AUTOSPELL,100,skilllv,spellid,maxlv,0, - skill_get_time(SA_AUTOSPELL,skilllv)); - } - break; - - case BS_GREED: - if (sd) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_greed,bl, - skill_get_splash(skillid, skilllv),BL_ITEM,bl); - } - break; - - case SA_ELEMENTWATER: - case SA_ELEMENTFIRE: - case SA_ELEMENTGROUND: - case SA_ELEMENTWIND: - if (sd && !dstmd) //Only works on monsters. - break; - if (tstatus->mode&MD_BOSS) - break; - case NPC_ATTRICHANGE: - case NPC_CHANGEWATER: - case NPC_CHANGEGROUND: - case NPC_CHANGEFIRE: - case NPC_CHANGEWIND: - case NPC_CHANGEPOISON: - case NPC_CHANGEHOLY: - case NPC_CHANGEDARKNESS: - case NPC_CHANGETELEKINESIS: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start2(bl, type, 100, skilllv, skill_get_ele(skillid,skilllv), - skill_get_time(skillid, skilllv))); - break; - case NPC_CHANGEUNDEAD: - //This skill should fail if target is wearing bathory/evil druid card [Brainstorm] - //TO-DO This is ugly, fix it - if (tstatus->def_ele==ELE_UNDEAD || tstatus->def_ele==ELE_DARK) break; - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start2(bl, type, 100, skilllv, skill_get_ele(skillid,skilllv), - skill_get_time(skillid, skilllv))); - break; - - case NPC_PROVOCATION: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (md) mob_unlocktarget(md, tick); - break; - - case NPC_KEEPING: - case NPC_BARRIER: { - int skill_time = skill_get_time(skillid,skilllv); - struct unit_data *ud = unit_bl2ud(bl); - if (clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_time)) - && ud) { //Disable attacking/acting/moving for skill's duration. - ud->attackabletime = - ud->canact_tick = - ud->canmove_tick = tick + skill_time; - } - } - break; - - case NPC_REBIRTH: - if (md && md->state.rebirth) - break; // only works once - sc_start(bl,type,100,skilllv,-1); - break; - - case NPC_DARKBLESSING: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start2(bl,type,(50+skilllv*5),skilllv,skilllv,skill_get_time2(skillid,skilllv))); - break; - - case NPC_LICK: - status_zap(bl, 0, 100); - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,(skilllv*5),skilllv,skill_get_time2(skillid,skilllv))); - break; - - case NPC_SUICIDE: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - status_kill(src); //When suiciding, neither exp nor drops is given. - break; - - case NPC_SUMMONSLAVE: - case NPC_SUMMONMONSTER: - if (md && md->skillidx >= 0) - mob_summonslave(md,md->db->skill[md->skillidx].val,skilllv,skillid); - break; - - case NPC_CALLSLAVE: - mob_warpslave(src,MOB_SLAVEDISTANCE); - break; - - case NPC_RANDOMMOVE: - if (md) { - md->next_walktime = tick - 1; - mob_randomwalk(md,tick); - } - break; - - case NPC_SPEEDUP: { - // or does it increase casting rate? just a guess xD - int i = SC_ASPDPOTION0 + skilllv - 1; - if (i > SC_ASPDPOTION3) - i = SC_ASPDPOTION3; - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,(sc_type)i,100,skilllv,skilllv * 60000)); - } - break; - - case NPC_REVENGE: - // not really needed... but adding here anyway ^^ - if (md && md->master_id > 0) { - struct block_list *mbl, *tbl; - if ((mbl = map_id2bl(md->master_id)) == NULL || - (tbl = battle_gettargeted(mbl)) == NULL) - break; - md->state.provoke_flag = tbl->id; - mob_target(md, tbl, sstatus->rhw.range); - } - break; - - case NPC_RUN: { - const int mask[8][2] = {{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}}; - int dir = (bl == src)?unit_getdir(src):map_calc_dir(src,bl->x,bl->y); //If cast on self, run forward, else run away. - unit_stop_attack(src); - //Run skillv tiles overriding the can-move check. - if (unit_walktoxy(src, src->x + skilllv * mask[dir][0], src->y + skilllv * mask[dir][1], 2) && md) - md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the ai. - } - break; - - case NPC_TRANSFORMATION: - case NPC_METAMORPHOSIS: - if (md && md->skillidx >= 0) { - int class_ = mob_random_class(md->db->skill[md->skillidx].val,0); - if (skilllv > 1) //Multiply the rest of mobs. [Skotlex] - mob_summonslave(md,md->db->skill[md->skillidx].val,skilllv-1,skillid); - if (class_) mob_class_change(md, class_); - } - break; - - case NPC_EMOTION_ON: - case NPC_EMOTION: - //va[0] is the emotion to use. - //NPC_EMOTION & NPC_EMOTION_ON can change a mob's mode 'permanently' [Skotlex] - //val[1] 'sets' the mode - //val[2] adds to the current mode - //val[3] removes from the current mode - //val[4] if set, asks to delete the previous mode change. - if (md && md->skillidx >= 0 && tsc) { - clif_emotion(bl, md->db->skill[md->skillidx].val[0]); - if (md->db->skill[md->skillidx].val[4] && tsce) - status_change_end(bl, type, INVALID_TIMER); - - if (md->db->skill[md->skillidx].val[1] || md->db->skill[md->skillidx].val[2]) - sc_start4(src, type, 100, skilllv, - md->db->skill[md->skillidx].val[1], - md->db->skill[md->skillidx].val[2], - md->db->skill[md->skillidx].val[3], - skill_get_time(skillid, skilllv)); - } - break; - - case NPC_POWERUP: - sc_start(bl,SC_INCATKRATE,100,200,skill_get_time(skillid, skilllv)); - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,100,skill_get_time(skillid, skilllv))); - break; - - case NPC_AGIUP: - sc_start(bl,SC_SPEEDUP1,100,skilllv,skill_get_time(skillid, skilllv)); - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,100,skill_get_time(skillid, skilllv))); - break; - - case NPC_INVISIBLE: - //Have val4 passed as 6 is for "infinite cloak" (do not end on attack/skill use). - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start4(bl,type,100,skilllv,0,0,6,skill_get_time(skillid,skilllv))); - break; - - case NPC_SIEGEMODE: - // not sure what it does - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - - case WE_MALE: { - int hp_rate=(skilllv <= 0)? 0:skill_db[skillid].hp_rate[skilllv-1]; - int gain_hp= tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it costed the caster. [Skotlex] - clif_skill_nodamage(src,bl,skillid,status_heal(bl, gain_hp, 0, 0),1); - } - break; - case WE_FEMALE: { - int sp_rate=(skilllv <= 0)? 0:skill_db[skillid].sp_rate[skilllv-1]; - int gain_sp=tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it costed the caster. [Skotlex] - clif_skill_nodamage(src,bl,skillid,status_heal(bl, 0, gain_sp, 0),1); - } - break; - - // parent-baby skills - case WE_BABY: - if (sd) { - 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,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; - } - status_change_start(bl,SC_STUN,10000,skilllv,0,0,0,skill_get_time2(skillid,skilllv),8); - if (f_sd) sc_start(&f_sd->bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - if (m_sd) sc_start(&m_sd->bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - } - break; - - case PF_HPCONVERSION: { - int hp, sp; - hp = sstatus->max_hp/10; - sp = hp * 10 * skilllv / 100; - if (!status_charge(src,hp,0)) { - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - status_heal(bl,0,sp,2); - } - break; - - case MA_REMOVETRAP: - case HT_REMOVETRAP: { - struct skill_unit *su; - struct skill_unit_group *sg; - su = BL_CAST(BL_SKILL, bl); - - // Mercenaries can remove any trap - // Players can only remove their own traps or traps on Vs maps. - if (su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && (skill_get_inf2(sg->skill_id)&INF2_TRAP)) { - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - if (sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0))) { - // prevent picking up expired traps - if (battle_config.skill_removetrap_type) { - // get back all items used to deploy the trap - for (i = 0; i < 10; i++) { - if (skill_db[su->group->skill_id].itemid[i] > 0) { - int flag; - struct item item_tmp; - 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],LOG_TYPE_OTHER))) { - 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,0,0,0,0); - } - } - } - } else { - // get back 1 trap - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP; - item_tmp.identify = 1; - if (item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_OTHER))) { - clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - } - skill_delunit(su); - } else if (sd) - clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); - - } - break; - case HT_SPRINGTRAP: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - { - struct skill_unit *su=NULL; - if ((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group)) { - switch (su->group->unit_id) { - case UNT_ANKLESNARE: // 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 UNT_BLASTMINE: - case UNT_SKIDTRAP: - case UNT_LANDMINE: - case UNT_SHOCKWAVE: - case UNT_SANDMAN: - case UNT_FLASHER: - case UNT_FREEZINGTRAP: - case UNT_CLAYMORETRAP: - case UNT_TALKIEBOX: - su->group->unit_id = UNT_USED_TRAPS; - clif_changetraplook(bl, UNT_USED_TRAPS); - su->group->limit=DIFF_TICK(tick+1500,su->group->tick); - su->limit=DIFF_TICK(tick+1500,su->group->tick); - } - } - } - break; - case BD_ENCORE: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (sd) - unit_skilluse_id(src,src->id,sd->skillid_dance,sd->skilllv_dance); - break; - - case AS_SPLASHER: - if (tstatus->mode&MD_BOSS - /** - * Renewal dropped the 3/4 hp requirement - **/ -#ifndef RENEWAL - || tstatus-> hp > tstatus->max_hp*3/4 -#endif - ) { - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; - } - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start4(bl,type,100,skilllv,skillid,src->id,skill_get_time(skillid,skilllv),1000)); - if (sd) skill_blockpc_start(sd, skillid, skill_get_time(skillid, skilllv)+3000); - break; - - case PF_MINDBREAKER: { - if (tstatus->mode&MD_BOSS || battle_check_undead(tstatus->race,tstatus->def_ele)) { - map_freeblock_unlock(); - return 1; - } - - if (tsce) { - //HelloKitty2 (?) explained that this silently fails when target is - //already inflicted. [Skotlex] - map_freeblock_unlock(); - return 1; - } - - //Has a 55% + skilllv*5% success chance. - if (!clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,55+5*skilllv,skilllv,skill_get_time(skillid,skilllv)))) { - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; - } - - unit_skillcastcancel(bl,0); - - if (tsc && tsc->count) { - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - if (tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE) - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - } - - if (dstmd) - mob_target(dstmd,src,skill_get_range2(src,skillid,skilllv)); - } - break; - - case PF_SOULCHANGE: { - unsigned int sp1 = 0, sp2 = 0; - if (dstmd) { - if (dstmd->state.soul_change_flag) { - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - dstmd->state.soul_change_flag = 1; - sp2 = sstatus->max_sp * 3 /100; - status_heal(src, 0, sp2, 2); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - } - sp1 = sstatus->sp; - sp2 = tstatus->sp; -#ifdef RENEWAL - sp1 = sp1 / 2; - sp2 = sp2 / 2; - if (tsc && tsc->data[SC_EXTREMITYFIST2]) - sp1 = tstatus->sp; + case SC_EXTREMITYFIST2: #endif - status_set_sp(src, sp2, 3); - status_set_sp(bl, sp1, 3); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - // Slim Pitcher - case CR_SLIMPITCHER: - // Updated to block Slim Pitcher from working on barricades and guardian stones. - if (dstmd && (dstmd->class_ == MOBID_EMPERIUM || (dstmd->class_ >= MOBID_BARRICADE1 && dstmd->class_ <= MOBID_GUARIDAN_STONE2))) - break; - if (potion_hp || potion_sp) { - int hp = potion_hp, sp = potion_sp; - hp = hp * (100 + (tstatus->vit<<1))/100; - sp = sp * (100 + (tstatus->int_<<1))/100; - if (dstsd) { - if (hp) - hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10 + pc_skillheal2_bonus(dstsd, skillid))/100; - if (sp) - sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10 + pc_skillheal2_bonus(dstsd, skillid))/100; - } - if (tsc && tsc->count) { - if (tsc->data[SC_CRITICALWOUND]) { - hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - } - if (tsc->data[SC_DEATHHURT]) { - hp -= hp * 20 / 100; - sp -= sp * 20 / 100; - } - if (tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2) { - hp += hp / 10; - sp += sp / 10; - } - } - if (hp > 0) - clif_skill_nodamage(NULL,bl,AL_HEAL,hp,1); - if (sp > 0) - clif_skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); - status_heal(bl,hp,sp,0); - } - break; - // Full Chemical Protection - case CR_FULLPROTECTION: { - unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; - int i, s = 0, skilltime = skill_get_time(skillid,skilllv); - - for (i=0 ; i<4; i++) { - if (bl->type != BL_PC || (dstsd && pc_checkequip(dstsd,equip[i]) < 0)) - continue; - sc_start(bl,(sc_type)(SC_CP_WEAPON + i),100,skilllv,skilltime); - s++; - } - if (sd && !s) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); // Don't consume item requirements - return 0; - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case RG_CLEANER: //AppleGirl - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - - case CG_LONGINGFREEDOM: { - if (tsc && !tsce && (tsce=tsc->data[SC_DANCING]) && tsce->val4 - && (tsce->val1&0xFFFF) != CG_MOONLIT) { //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex] - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - } - } - break; - - case CG_TAROTCARD: { - int eff, count = -1; - if (rnd() % 100 > skilllv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPERIUM) || mob_is_battleground(dstmd)))) { - if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - - map_freeblock_unlock(); - return 0; - } - status_zap(src,0,skill_db[skill_get_index(skillid)].sp[skilllv]); // consume sp only if succeeded [Inkfish] - do { - eff = rnd() % 14; - clif_specialeffect(bl, 523 + eff, AREA); - switch (eff) { - case 0: // heals SP to 0 - status_percent_damage(src, bl, 0, 100, false); - break; - case 1: // matk halved - sc_start(bl,SC_INCMATKRATE,100,-50,skill_get_time2(skillid,skilllv)); - break; - case 2: // all buffs removed - status_change_clear_buffs(bl,1); - break; - case 3: { // 1000 damage, random armor destroyed - int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; - status_fix_damage(src, bl, 1000, 0); - clif_damage(src,bl,tick,0,0,1000,0,0,0); - if (!status_isdead(bl)) - skill_break_equip(bl, where[rnd()%5], 10000, BCT_ENEMY); - } - break; - case 4: // atk halved - sc_start(bl,SC_INCATKRATE,100,-50,skill_get_time2(skillid,skilllv)); - break; - case 5: // 2000HP heal, random teleported - status_heal(src, 2000, 0, 0); - if (!map_flag_vs(bl->m)) - unit_warp(bl, -1,-1,-1, CLR_TELEPORT); - break; - case 6: // random 2 other effects - if (count == -1) - count = 3; - else - count++; //Should not retrigger this one. - break; - case 7: { // stop freeze or stoned - enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE }; - sc_start(bl,sc[rnd()%3],100,skilllv,skill_get_time2(skillid,skilllv)); - } - break; - case 8: // curse coma and poison - sc_start(bl,SC_COMA,100,skilllv,skill_get_time2(skillid,skilllv)); - sc_start(bl,SC_CURSE,100,skilllv,skill_get_time2(skillid,skilllv)); - sc_start(bl,SC_POISON,100,skilllv,skill_get_time2(skillid,skilllv)); - break; - case 9: // confusion - sc_start(bl,SC_CONFUSION,100,skilllv,skill_get_time2(skillid,skilllv)); - break; - case 10: // 6666 damage, atk matk halved, cursed - status_fix_damage(src, bl, 6666, 0); - clif_damage(src,bl,tick,0,0,6666,0,0,0); - sc_start(bl,SC_INCATKRATE,100,-50,skill_get_time2(skillid,skilllv)); - sc_start(bl,SC_INCMATKRATE,100,-50,skill_get_time2(skillid,skilllv)); - sc_start(bl,SC_CURSE,skilllv,100,skill_get_time2(skillid,skilllv)); - break; - case 11: // 4444 damage - status_fix_damage(src, bl, 4444, 0); - clif_damage(src,bl,tick,0,0,4444,0,0,0); - break; - case 12: // stun - sc_start(bl,SC_STUN,100,skilllv,5000); - break; - case 13: // atk,matk,hit,flee,def reduced - sc_start(bl,SC_INCATKRATE,100,-20,skill_get_time2(skillid,skilllv)); - sc_start(bl,SC_INCMATKRATE,100,-20,skill_get_time2(skillid,skilllv)); - sc_start(bl,SC_INCHITRATE,100,-20,skill_get_time2(skillid,skilllv)); - sc_start(bl,SC_INCFLEERATE,100,-20,skill_get_time2(skillid,skilllv)); - sc_start(bl,SC_INCDEFRATE,100,-20,skill_get_time2(skillid,skilllv)); - break; - default: - break; - } - } while ((--count) > 0); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case SL_ALCHEMIST: - case SL_ASSASIN: - case SL_BARDDANCER: - case SL_BLACKSMITH: - case SL_CRUSADER: - case SL_HUNTER: - case SL_KNIGHT: - case SL_MONK: - case SL_PRIEST: - case SL_ROGUE: - case SL_SAGE: - case SL_SOULLINKER: - case SL_STAR: - case SL_SUPERNOVICE: - case SL_WIZARD: - //NOTE: here, 'type' has the value of the associated MAPID, not of the SC_SPIRIT constant. - if (sd && !(dstsd && (dstsd->class_&MAPID_UPPERMASK) == type)) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - if (skillid == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rnd()%100)) { - //Erase death count 1% of the casts - dstsd->die_counter = 0; - pc_setglobalreg(dstsd,"PC_DIE_COUNTER", 0); - clif_specialeffect(bl, 0x152, AREA); - //SC_SPIRIT invokes status_calc_pc for us. - } - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start4(bl,SC_SPIRIT,100,skilllv,skillid,0,0,skill_get_time(skillid,skilllv))); - sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA,skilllv)); - break; - case SL_HIGH: - if (sd && !(dstsd && (dstsd->class_&JOBL_UPPER) && !(dstsd->class_&JOBL_2) && dstsd->status.base_level < 70)) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start4(bl,type,100,skilllv,skillid,0,0,skill_get_time(skillid,skilllv))); - sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA,skilllv)); - break; - - case SL_SWOO: - if (tsce) { - sc_start(src,SC_STUN,100,skilllv,10000); - break; - } - case SL_SKA: // [marquis007] - case SL_SKE: - if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,10); - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - if (skillid == SL_SKE) - sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA,skilllv)); - break; - - // New guild skills [Celest] - case GD_BATTLEORDER: - if (flag&1) { - if (status_get_guild_id(src) == status_get_guild_id(bl)) - sc_start(bl,type,100,skilllv,skill_get_time(skillid, skilllv)); - } else if (status_get_guild_id(src)) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_area_sub, src, - skill_get_splash(skillid, skilllv), BL_PC, - src,skillid,skilllv,tick, flag|BCT_GUILD|1, - skill_castend_nodamage_id); - if (sd) - guild_block_skill(sd,skill_get_time2(skillid,skilllv)); - } - break; - case GD_REGENERATION: - if (flag&1) { - if (status_get_guild_id(src) == status_get_guild_id(bl)) - sc_start(bl,type,100,skilllv,skill_get_time(skillid, skilllv)); - } else if (status_get_guild_id(src)) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_area_sub, src, - skill_get_splash(skillid, skilllv), BL_PC, - src,skillid,skilllv,tick, flag|BCT_GUILD|1, - skill_castend_nodamage_id); - if (sd) - guild_block_skill(sd,skill_get_time2(skillid,skilllv)); - } - break; - case GD_RESTORE: - if (flag&1) { - if (status_get_guild_id(src) == status_get_guild_id(bl)) - clif_skill_nodamage(src,bl,AL_HEAL,status_percent_heal(bl,90,90),1); - } else if (status_get_guild_id(src)) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_area_sub, src, - skill_get_splash(skillid, skilllv), BL_PC, - src,skillid,skilllv,tick, flag|BCT_GUILD|1, - skill_castend_nodamage_id); - if (sd) - guild_block_skill(sd,skill_get_time2(skillid,skilllv)); - } - break; - case GD_EMERGENCYCALL: { - 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 j = 0; - struct guild *g = NULL; - // i don't know if it actually summons in a circle, but oh well. ;P - g = sd?sd->state.gmaster_flag:guild_search(status_get_guild_id(src)); - if (!g) - break; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - for (i = 0; i < g->max_member; i++, j++) { - if (j>8) j=0; - if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) { - if (map[dstsd->bl.m].flag.nowarp && !map_flag_gvg2(dstsd->bl.m)) - continue; - if (map_getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH)) - dx[j] = dy[j] = 0; - pc_setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN); - } - } - if (sd) - guild_block_skill(sd,skill_get_time2(skillid,skilllv)); - } - break; - - case SG_FEEL: - //AuronX reported you CAN memorize the same map as all three. [Skotlex] - if (sd) { - if (!sd->feel_map[skilllv-1].index) - clif_feel_req(sd->fd,sd, skilllv); - else - clif_feel_info(sd, skilllv-1, 1); - } - break; - - case SG_HATE: - if (sd) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (!pc_set_hate_mob(sd, skilllv-1, bl)) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } - break; - - case GS_GLITTERING: - if (sd) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (rnd()%100 < (20+10*skilllv)) - pc_addspiritball(sd,skill_get_time(skillid,skilllv),10); - else if (sd->spiritball > 0) - pc_delspiritball(sd,1,0); - } - break; - - case GS_CRACKER: - /* per official standards, this skill works on players and mobs. */ - if (sd && (dstsd || dstmd)) { - i =65 -5*distance_bl(src,bl); //Base rate - if (i < 30) i = 30; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - sc_start(bl,SC_STUN, i,skilllv,skill_get_time2(skillid,skilllv)); - } - break; - - case AM_CALLHOMUN: //[orn] - if (sd && !merc_call_homunculus(sd)) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - - case AM_REST: - if (sd) { - if (merc_hom_vaporize(sd,1)) - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - else - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } - break; - - case HAMI_CASTLE: //[orn] - if (rnd()%100 < 20*skilllv && src != bl) { - int x,y; - x = src->x; - y = src->y; - if (hd) - skill_blockhomun_start(hd, skillid, skill_get_time2(skillid,skilllv)); - - if (unit_movepos(src,bl->x,bl->y,0,0)) { - clif_skill_nodamage(src,src,skillid,skilllv,1); // Homunc - clif_slide(src,bl->x,bl->y) ; - if (unit_movepos(bl,x,y,0,0)) { - clif_skill_nodamage(bl,bl,skillid,skilllv,1); // Master - clif_slide(bl,x,y) ; - } - - //TODO: Shouldn't also players and the like switch targets? - map_foreachinrange(skill_chastle_mob_changetarget,src, - AREA_SIZE, BL_MOB, bl, src); - } - } - // Failed - else if (hd && hd->master) - clif_skill_fail(hd->master, skillid, USESKILL_FAIL_LEVEL, 0); - else if (sd) - clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); - break; - case HVAN_CHAOTIC: { //[orn] - static const int per[5][2]= {{20,50},{50,60},{25,75},{60,64},{34,67}}; - int r = rnd()%100; - i = (skilllv-1)%5; - if (r<per[i][0]) //Self - bl = src; - else if (r<per[i][1]) //Master - bl = battle_get_master(src); - else //Enemy - bl = map_id2bl(battle_gettarget(src)); - - if (!bl) bl = src; - i = skill_calc_heal(src, bl, skillid, 1+rnd()%skilllv, true); - //Eh? why double skill packet? - clif_skill_nodamage(src,bl,AL_HEAL,i,1); - clif_skill_nodamage(src,bl,skillid,i,1); - status_heal(bl, i, 0, 0); - } - break; - //Homun single-target support skills [orn] - case HAMI_BLOODLUST: - case HFLI_FLEET: - case HFLI_SPEED: - case HLIF_CHANGE: - case MH_ANGRIFFS_MODUS: - case MH_GOLDENE_FERSE: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - if (hd) - skill_blockhomun_start(hd, skillid, skill_get_time2(skillid,skilllv)); - break; - - case NPC_DRAGONFEAR: - if (flag&1) { - const enum sc_type sc[] = { SC_STUN, SC_SILENCE, SC_CONFUSION, SC_BLEEDING }; - int j; - j = i = rnd()%ARRAYLENGTH(sc); - while (!sc_start(bl,sc[i],100,skilllv,skill_get_time2(skillid,i+1))) { - i++; - if (i == ARRAYLENGTH(sc)) - i = 0; - if (i == j) - break; - } - break; - } - case NPC_WIDEBLEEDING: - case NPC_WIDECONFUSE: - case NPC_WIDECURSE: - case NPC_WIDEFREEZE: - case NPC_WIDESLEEP: - case NPC_WIDESILENCE: - case NPC_WIDESTONE: - case NPC_WIDESTUN: - case NPC_SLOWCAST: - case NPC_WIDEHELLDIGNITY: - if (flag&1) - sc_start(bl,type,100,skilllv,skill_get_time2(skillid,skilllv)); - else { - skill_area_temp[2] = 0; //For SD_PREAMBLE - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skillid, skilllv),BL_CHAR, - src,skillid,skilllv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, - skill_castend_nodamage_id); - } - break; - case NPC_WIDESOULDRAIN: - if (flag&1) - status_percent_damage(src,bl,0,((skilllv-1)%5+1)*20,false); - else { - skill_area_temp[2] = 0; //For SD_PREAMBLE - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skillid, skilllv),BL_CHAR, - src,skillid,skilllv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, - skill_castend_nodamage_id); - } - break; - case ALL_PARTYFLEE: - if (sd && !(flag&1)) { - if (!sd->status.party_id) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - } else - clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - break; - case NPC_TALK: - case ALL_WEWISH: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - case ALL_BUYING_STORE: - if (sd) { - // players only, skill allows 5 buying slots - clif_skill_nodamage(src, bl, skillid, skilllv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS)); - } - break; - case RK_ENCHANTBLADE: - clif_skill_nodamage(src,bl,skillid,skilllv,// formula not confirmed - sc_start2(bl,type,100,skilllv,100+20*skilllv/*+sstatus->int_/2+status_get_lv(bl)/10*/,skill_get_time(skillid,skilllv))); - break; - case RK_DRAGONHOWLING: - if (flag&1) - sc_start(bl,type,50 + 6 * skilllv,skilllv,skill_get_time(skillid,skilllv)); - else { - skill_area_temp[2] = 0; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_area_sub, src, - skill_get_splash(skillid,skilllv),BL_CHAR, - src,skillid,skilllv,tick,flag|BCT_ENEMY|SD_PREAMBLE|1, - skill_castend_nodamage_id); - } - break; - case RK_IGNITIONBREAK: - case LG_EARTHDRIVE: - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - i = skill_get_splash(skillid,skilllv); - if (skillid == LG_EARTHDRIVE) { - int dummy = 1; - map_foreachinarea(skill_cell_overlap, src->m, src->x-i, src->y-i, src->x+i, src->y+i, BL_SKILL, LG_EARTHDRIVE, &dummy, src); - } - map_foreachinrange(skill_area_sub, bl,i,BL_CHAR, - src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - break; - case RK_STONEHARDSKIN: - if (sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 4) { - int heal = sstatus->hp / 4; // 25% HP - if (status_charge(bl,heal,0)) - clif_skill_nodamage(src,bl,skillid,skilllv,sc_start2(bl,type,100,skilllv,heal,skill_get_time(skillid,skilllv))); - else - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } - break; - case RK_REFRESH: - if (sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 8) { - int heal = status_get_max_hp(bl) * 25 / 100; - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - status_heal(bl,heal,0,1); - status_change_clear_buffs(bl,4); - } - break; - - case RK_MILLENNIUMSHIELD: - if (sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 9) { - short shields = (rnd()%100<50) ? 4 : ((rnd()%100<80) ? 3 : 2); - sc_start4(bl,type,100,skilllv,shields,1000,0,skill_get_time(skillid,skilllv)); - clif_millenniumshield(sd,shields); - clif_skill_nodamage(src,bl,skillid,1,1); - } - break; - - case RK_GIANTGROWTH: - case RK_VITALITYACTIVATION: - case RK_ABUNDANCE: - if (sd) { - int lv = 1; // RK_GIANTGROWTH - if (skillid == RK_VITALITYACTIVATION) - lv = 2; - else if (skillid == RK_ABUNDANCE) - lv = 6; - if (pc_checkskill(sd,RK_RUNEMASTERY) >= lv) - clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - } - break; - - case RK_FIGHTINGSPIRIT: - if (flag&1) { - if (src == bl) - sc_start2(bl,type,100,skill_area_temp[5],10*(sd?pc_checkskill(sd,RK_RUNEMASTERY):10),skill_get_time(skillid,skilllv)); - else - sc_start(bl,type,100,skill_area_temp[5]/4,skill_get_time(skillid,skilllv)); - } else if (sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 5) { - if (sd->status.party_id) { - i = party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skillid,skilllv),src,skillid,skilllv,tick,BCT_PARTY,skill_area_sub_count); - skill_area_temp[5] = 7 * i; // ATK - party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skillid,skilllv),src,skillid,skilllv,tick,flag|BCT_PARTY|1,skill_castend_nodamage_id); - } else - sc_start2(bl,type,100,7,5,skill_get_time(skillid,skilllv)); - } - clif_skill_nodamage(src,bl,skillid,1,1); - break; - /** - * Guilotine Cross - **/ - case GC_ROLLINGCUTTER: { - short count = 1; - skill_area_temp[2] = 0; - map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|SD_PREAMBLE|SD_SPLASH|1,skill_castend_damage_id); - if (tsc && tsc->data[SC_ROLLINGCUTTER]) { - // Every time the skill is casted the status change is reseted adding a counter. - count += (short)tsc->data[SC_ROLLINGCUTTER]->val1; - if (count > 10) - count = 10; // Max coounter - status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); - } - sc_start(bl,SC_ROLLINGCUTTER,100,count,skill_get_time(skillid,skilllv)); - clif_skill_nodamage(src,src,skillid,skilllv,1); - } - break; + continue; + /** + * bugreport:4888 these songs may only be dispelled if you're not in their song area anymore + **/ + case SC_WHISTLE: + case SC_ASSNCROS: + case SC_POEMBRAGI: + case SC_APPLEIDUN: + case SC_HUMMING: + case SC_DONTFORGETME: + case SC_FORTUNE: + case SC_SERVICE4U: + if( tsc->data[i]->val4 ) //val4 = out-of-song-area + continue; + break; + case SC_ASSUMPTIO: + if( bl->type == BL_MOB ) + continue; + break; + } + if(i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. + status_change_end(bl, (sc_type)i, INVALID_TIMER); + } + break; + } + //Affect all targets on splash area. + map_foreachinrange(skill_area_sub, bl, i, BL_CHAR, + src, skillid, skilllv, tick, flag|1, + skill_castend_damage_id); + break; + + case TF_BACKSLIDING: //This is the correct implementation as per packet logging information. [Skotlex] + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),unit_getdir(bl),0); + break; + + case TK_HIGHJUMP: + { + int x,y, dir = unit_getdir(src); + + //Fails on noteleport maps, except for GvG and BG maps [Skotlex] + if( map[src->m].flag.noteleport && + !(map[src->m].flag.battleground || map_flag_gvg2(src->m) ) + ) { + x = src->x; + y = src->y; + } else { + x = src->x + dirx[dir]*skilllv*2; + y = src->y + diry[dir]*skilllv*2; + } - case GC_WEAPONBLOCKING: - if (tsc && tsc->data[SC_WEAPONBLOCKING]) - status_change_end(bl, SC_WEAPONBLOCKING, INVALID_TIMER); - else - sc_start(bl,SC_WEAPONBLOCKING,100,skilllv,skill_get_time(skillid,skilllv)); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; + clif_skill_nodamage(src,bl,TK_HIGHJUMP,skilllv,1); + if(!map_count_oncell(src->m,x,y,BL_PC|BL_NPC|BL_MOB) && map_getcell(src->m,x,y,CELL_CHKREACH)) { + clif_slide(src,x,y); + unit_movepos(src, x, y, 1, 0); + } + } + break; + + case SA_CASTCANCEL: + case SO_SPELLFIST: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + unit_skillcastcancel(src,1); + if(sd) { + int sp = skill_get_sp(sd->skillid_old,sd->skilllv_old); + if( skillid == SO_SPELLFIST ){ + sc_start4(src,type,100,skilllv+1,skilllv,sd->skillid_old,sd->skilllv_old,skill_get_time(skillid,skilllv)); + sd->skillid_old = sd->skilllv_old = 0; + break; + } + sp = sp * (90 - (skilllv-1)*20) / 100; + if(sp < 0) sp = 0; + status_zap(src, 0, sp); + } + break; + case SA_SPELLBREAKER: + { + int sp; + if(tsc && tsc->data[SC_MAGICROD]) { + sp = skill_get_sp(skillid,skilllv); + sp = sp * tsc->data[SC_MAGICROD]->val2 / 100; + if(sp < 1) sp = 1; + status_heal(bl,0,sp,2); + status_percent_damage(bl, src, 0, -20, false); //20% max SP damage. + } else { + struct unit_data *ud = unit_bl2ud(bl); + int bl_skillid=0,bl_skilllv=0,hp = 0; + if (!ud || ud->skilltimer == INVALID_TIMER) + break; //Nothing to cancel. + bl_skillid = ud->skillid; + bl_skilllv = ud->skilllv; + if (tstatus->mode & MD_BOSS) + { //Only 10% success chance against bosses. [Skotlex] + if (rnd()%100 < 90) + { + if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + } else if (!dstsd || map_flag_vs(bl->m)) //HP damage only on pvp-maps when against players. + hp = tstatus->max_hp/50; //Recover 2% HP [Skotlex] - case GC_CREATENEWPOISON: - if (sd) { - clif_skill_produce_mix_list(sd,skillid,25); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - } - break; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + unit_skillcastcancel(bl,0); + sp = skill_get_sp(bl_skillid,bl_skilllv); + status_zap(bl, hp, sp); - case GC_POISONINGWEAPON: - if (sd) { - clif_poison_list(sd,skilllv); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; + if (hp && skilllv >= 5) + hp>>=1; //Recover half damaged HP at level 5 [Skotlex] + else + hp = 0; - case GC_ANTIDOTE: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (tsc) { - status_change_end(bl, SC_PARALYSE, INVALID_TIMER); - status_change_end(bl, SC_PYREXIA, INVALID_TIMER); - status_change_end(bl, SC_DEATHHURT, INVALID_TIMER); - status_change_end(bl, SC_LEECHESEND, INVALID_TIMER); - status_change_end(bl, SC_VENOMBLEED, INVALID_TIMER); - status_change_end(bl, SC_MAGICMUSHROOM, INVALID_TIMER); - status_change_end(bl, SC_TOXIN, INVALID_TIMER); - status_change_end(bl, SC_OBLIVIONCURSE, INVALID_TIMER); - } - break; + if (sp) //Recover some of the SP used + sp = sp*(25*(skilllv-1))/100; - case GC_PHANTOMMENACE: - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR, - src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - break; + if(hp || sp) + status_heal(src, hp, sp, 2); + } + } + break; + case SA_MAGICROD: + clif_skill_nodamage(src,src,SA_MAGICROD,skilllv,1); + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + break; + case SA_AUTOSPELL: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(sd) + clif_autospell(sd,skilllv); + else { + int maxlv=1,spellid=0; + static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT }; + if(skilllv >= 10) { + spellid = MG_FROSTDIVER; +// if (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SA_SAGE) +// maxlv = 10; +// else + maxlv = skilllv - 9; + } + else if(skilllv >=8) { + spellid = MG_FIREBALL; + maxlv = skilllv - 7; + } + else if(skilllv >=5) { + spellid = MG_SOULSTRIKE; + maxlv = skilllv - 4; + } + else if(skilllv >=2) { + int i = rnd()%3; + spellid = spellarray[i]; + maxlv = skilllv - 1; + } + else if(skilllv > 0) { + spellid = MG_NAPALMBEAT; + maxlv = 3; + } + if(spellid > 0) + sc_start4(src,SC_AUTOSPELL,100,skilllv,spellid,maxlv,0, + skill_get_time(SA_AUTOSPELL,skilllv)); + } + break; + + case BS_GREED: + if(sd){ + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_greed,bl, + skill_get_splash(skillid, skilllv),BL_ITEM,bl); + } + break; + + case SA_ELEMENTWATER: + case SA_ELEMENTFIRE: + case SA_ELEMENTGROUND: + case SA_ELEMENTWIND: + if(sd && !dstmd) //Only works on monsters. + break; + if(tstatus->mode&MD_BOSS) + break; + case NPC_ATTRICHANGE: + case NPC_CHANGEWATER: + case NPC_CHANGEGROUND: + case NPC_CHANGEFIRE: + case NPC_CHANGEWIND: + case NPC_CHANGEPOISON: + case NPC_CHANGEHOLY: + case NPC_CHANGEDARKNESS: + case NPC_CHANGETELEKINESIS: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start2(bl, type, 100, skilllv, skill_get_ele(skillid,skilllv), + skill_get_time(skillid, skilllv))); + break; + case NPC_CHANGEUNDEAD: + //This skill should fail if target is wearing bathory/evil druid card [Brainstorm] + //TO-DO This is ugly, fix it + if(tstatus->def_ele==ELE_UNDEAD || tstatus->def_ele==ELE_DARK) break; + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start2(bl, type, 100, skilllv, skill_get_ele(skillid,skilllv), + skill_get_time(skillid, skilllv))); + break; + + case NPC_PROVOCATION: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if (md) mob_unlocktarget(md, tick); + break; + + case NPC_KEEPING: + case NPC_BARRIER: + { + int skill_time = skill_get_time(skillid,skilllv); + struct unit_data *ud = unit_bl2ud(bl); + if (clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_time)) + && ud) { //Disable attacking/acting/moving for skill's duration. + ud->attackabletime = + ud->canact_tick = + ud->canmove_tick = tick + skill_time; + } + } + break; + + case NPC_REBIRTH: + if( md && md->state.rebirth ) + break; // only works once + sc_start(bl,type,100,skilllv,-1); + break; + + case NPC_DARKBLESSING: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start2(bl,type,(50+skilllv*5),skilllv,skilllv,skill_get_time2(skillid,skilllv))); + break; + + case NPC_LICK: + status_zap(bl, 0, 100); + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,(skilllv*5),skilllv,skill_get_time2(skillid,skilllv))); + break; + + case NPC_SUICIDE: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + status_kill(src); //When suiciding, neither exp nor drops is given. + break; + + case NPC_SUMMONSLAVE: + case NPC_SUMMONMONSTER: + if(md && md->skillidx >= 0) + mob_summonslave(md,md->db->skill[md->skillidx].val,skilllv,skillid); + break; + + case NPC_CALLSLAVE: + mob_warpslave(src,MOB_SLAVEDISTANCE); + break; + + case NPC_RANDOMMOVE: + if (md) { + md->next_walktime = tick - 1; + mob_randomwalk(md,tick); + } + break; + + case NPC_SPEEDUP: + { + // or does it increase casting rate? just a guess xD + int i = SC_ASPDPOTION0 + skilllv - 1; + if (i > SC_ASPDPOTION3) + i = SC_ASPDPOTION3; + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,(sc_type)i,100,skilllv,skilllv * 60000)); + } + break; + + case NPC_REVENGE: + // not really needed... but adding here anyway ^^ + if (md && md->master_id > 0) { + struct block_list *mbl, *tbl; + if ((mbl = map_id2bl(md->master_id)) == NULL || + (tbl = battle_gettargeted(mbl)) == NULL) + break; + md->state.provoke_flag = tbl->id; + mob_target(md, tbl, sstatus->rhw.range); + } + break; + + case NPC_RUN: + { + const int mask[8][2] = {{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}}; + int dir = (bl == src)?unit_getdir(src):map_calc_dir(src,bl->x,bl->y); //If cast on self, run forward, else run away. + unit_stop_attack(src); + //Run skillv tiles overriding the can-move check. + if (unit_walktoxy(src, src->x + skilllv * mask[dir][0], src->y + skilllv * mask[dir][1], 2) && md) + md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the ai. + } + break; + + case NPC_TRANSFORMATION: + case NPC_METAMORPHOSIS: + if(md && md->skillidx >= 0) { + int class_ = mob_random_class (md->db->skill[md->skillidx].val,0); + if (skilllv > 1) //Multiply the rest of mobs. [Skotlex] + mob_summonslave(md,md->db->skill[md->skillidx].val,skilllv-1,skillid); + if (class_) mob_class_change(md, class_); + } + break; + + case NPC_EMOTION_ON: + case NPC_EMOTION: + //va[0] is the emotion to use. + //NPC_EMOTION & NPC_EMOTION_ON can change a mob's mode 'permanently' [Skotlex] + //val[1] 'sets' the mode + //val[2] adds to the current mode + //val[3] removes from the current mode + //val[4] if set, asks to delete the previous mode change. + if(md && md->skillidx >= 0 && tsc) + { + clif_emotion(bl, md->db->skill[md->skillidx].val[0]); + if(md->db->skill[md->skillidx].val[4] && tsce) + status_change_end(bl, type, INVALID_TIMER); + + if(md->db->skill[md->skillidx].val[1] || md->db->skill[md->skillidx].val[2]) + sc_start4(src, type, 100, skilllv, + md->db->skill[md->skillidx].val[1], + md->db->skill[md->skillidx].val[2], + md->db->skill[md->skillidx].val[3], + skill_get_time(skillid, skilllv)); + } + break; + + case NPC_POWERUP: + sc_start(bl,SC_INCATKRATE,100,200,skill_get_time(skillid, skilllv)); + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,100,skill_get_time(skillid, skilllv))); + break; + + case NPC_AGIUP: + sc_start(bl,SC_SPEEDUP1,100,skilllv,skill_get_time(skillid, skilllv)); + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,100,skill_get_time(skillid, skilllv))); + break; + + case NPC_INVISIBLE: + //Have val4 passed as 6 is for "infinite cloak" (do not end on attack/skill use). + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start4(bl,type,100,skilllv,0,0,6,skill_get_time(skillid,skilllv))); + break; + + case NPC_SIEGEMODE: + // not sure what it does + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + + case WE_MALE: + { + int hp_rate=(skilllv <= 0)? 0:skill_db[skillid].hp_rate[skilllv-1]; + int gain_hp= tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it costed the caster. [Skotlex] + clif_skill_nodamage(src,bl,skillid,status_heal(bl, gain_hp, 0, 0),1); + } + break; + case WE_FEMALE: + { + int sp_rate=(skilllv <= 0)? 0:skill_db[skillid].sp_rate[skilllv-1]; + int gain_sp=tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it costed the caster. [Skotlex] + clif_skill_nodamage(src,bl,skillid,status_heal(bl, 0, gain_sp, 0),1); + } + break; + + // parent-baby skills + case WE_BABY: + if(sd){ + 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,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } + status_change_start(bl,SC_STUN,10000,skilllv,0,0,0,skill_get_time2(skillid,skilllv),8); + if (f_sd) sc_start(&f_sd->bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + if (m_sd) sc_start(&m_sd->bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + } + break; + + case PF_HPCONVERSION: + { + int hp, sp; + hp = sstatus->max_hp/10; + sp = hp * 10 * skilllv / 100; + if (!status_charge(src,hp,0)) { + if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + status_heal(bl,0,sp,2); + } + break; + + case MA_REMOVETRAP: + case HT_REMOVETRAP: + { + struct skill_unit* su; + struct skill_unit_group* sg; + su = BL_CAST(BL_SKILL, bl); + + // Mercenaries can remove any trap + // Players can only remove their own traps or traps on Vs maps. + if( su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && (skill_get_inf2(sg->skill_id)&INF2_TRAP) ) + { + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) + { // prevent picking up expired traps + if( battle_config.skill_removetrap_type ) + { // get back all items used to deploy the trap + for( i = 0; i < 10; i++ ) + { + if( skill_db[su->group->skill_id].itemid[i] > 0 ) + { + int flag; + struct item item_tmp; + 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],LOG_TYPE_OTHER)) ) + { + 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,0,0,0,0); + } + } + } + } + else + { // get back 1 trap + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP; + item_tmp.identify = 1; + if( item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) ) + { + clif_additem(sd,0,0,flag); + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + } + skill_delunit(su); + }else if(sd) + clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); + + } + break; + case HT_SPRINGTRAP: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + { + struct skill_unit *su=NULL; + if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){ + switch(su->group->unit_id){ + case UNT_ANKLESNARE: // 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 UNT_BLASTMINE: + case UNT_SKIDTRAP: + case UNT_LANDMINE: + case UNT_SHOCKWAVE: + case UNT_SANDMAN: + case UNT_FLASHER: + case UNT_FREEZINGTRAP: + case UNT_CLAYMORETRAP: + case UNT_TALKIEBOX: + su->group->unit_id = UNT_USED_TRAPS; + clif_changetraplook(bl, UNT_USED_TRAPS); + su->group->limit=DIFF_TICK(tick+1500,su->group->tick); + su->limit=DIFF_TICK(tick+1500,su->group->tick); + } + } + } + break; + case BD_ENCORE: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(sd) + unit_skilluse_id(src,src->id,sd->skillid_dance,sd->skilllv_dance); + break; + + case AS_SPLASHER: + if(tstatus->mode&MD_BOSS + /** + * Renewal dropped the 3/4 hp requirement + **/ + #ifndef RENEWAL + || tstatus-> hp > tstatus->max_hp*3/4 + #endif + ) { + if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; + } + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start4(bl,type,100,skilllv,skillid,src->id,skill_get_time(skillid,skilllv),1000)); + if (sd) skill_blockpc_start (sd, skillid, skill_get_time(skillid, skilllv)+3000); + break; + + case PF_MINDBREAKER: + { + if(tstatus->mode&MD_BOSS || battle_check_undead(tstatus->race,tstatus->def_ele)) + { + map_freeblock_unlock(); + return 1; + } - case GC_HALLUCINATIONWALK: { - int heal = status_get_max_hp(bl) / 10; - if (status_get_hp(bl) < heal) { // if you haven't enough HP skill fails. - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_HP_INSUFFICIENT,0); - break; - } - if (!status_charge(bl,heal,0)) { - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_HP_INSUFFICIENT,0); - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - } - break; - /** - * Arch Bishop - **/ - case AB_ANCILLA: - if (sd) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_produce_mix(sd, skillid, ITEMID_ANCILLA, 0, 0, 0, 1); - } - break; + if (tsce) + { //HelloKitty2 (?) explained that this silently fails when target is + //already inflicted. [Skotlex] + map_freeblock_unlock(); + return 1; + } - case AB_CLEMENTIA: - case AB_CANTO: { - int bless_lv = pc_checkskill(sd,AL_BLESSING); - int agi_lv = pc_checkskill(sd,AL_INCAGI); - if (sd == NULL || sd->status.party_id == 0 || flag&1) - clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl,type,100, - (skillid == AB_CLEMENTIA)? bless_lv : (skillid == AB_CANTO)? agi_lv : skilllv, skill_get_time(skillid,skilllv))); - else if (sd) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - } - break; + //Has a 55% + skilllv*5% success chance. + if (!clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,55+5*skilllv,skilllv,skill_get_time(skillid,skilllv)))) + { + if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } - case AB_PRAEFATIO: - if (sd == NULL || sd->status.party_id == 0 || flag&1) - clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start4(bl, type, 100, skilllv, 0, 0, 1, skill_get_time(skillid, skilllv))); - else if (sd) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - break; + unit_skillcastcancel(bl,0); - case AB_CHEAL: - if (sd == NULL || sd->status.party_id == 0 || flag&1) { - if (sd && tstatus && !battle_check_undead(tstatus->race, tstatus->def_ele)) { - i = skill_calc_heal(src, bl, AL_HEAL, pc_checkskill(sd, AL_HEAL), true); + if(tsc && tsc->count){ + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + if(tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE) + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + } - if ((dstsd && pc_ismadogear(dstsd)) || status_isimmune(bl)) - i = 0; // Should heal by 0 or won't do anything?? in iRO it breaks the healing to members.. [malufett] + if(dstmd) + mob_target(dstmd,src,skill_get_range2(src,skillid,skilllv)); + } + break; + + case PF_SOULCHANGE: + { + unsigned int sp1 = 0, sp2 = 0; + if (dstmd) { + if (dstmd->state.soul_change_flag) { + if(sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + dstmd->state.soul_change_flag = 1; + sp2 = sstatus->max_sp * 3 /100; + status_heal(src, 0, sp2, 2); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + } + sp1 = sstatus->sp; + sp2 = tstatus->sp; + #ifdef RENEWAL + sp1 = sp1 / 2; + sp2 = sp2 / 2; + if( tsc && tsc->data[SC_EXTREMITYFIST2] ) + sp1 = tstatus->sp; + #endif + status_set_sp(src, sp2, 3); + status_set_sp(bl, sp1, 3); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + // Slim Pitcher + case CR_SLIMPITCHER: + // Updated to block Slim Pitcher from working on barricades and guardian stones. + if( dstmd && (dstmd->class_ == MOBID_EMPERIUM || (dstmd->class_ >= MOBID_BARRICADE1 && dstmd->class_ <= MOBID_GUARIDAN_STONE2)) ) + break; + if (potion_hp || potion_sp) { + int hp = potion_hp, sp = potion_sp; + hp = hp * (100 + (tstatus->vit<<1))/100; + sp = sp * (100 + (tstatus->int_<<1))/100; + if (dstsd) { + if (hp) + hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10 + pc_skillheal2_bonus(dstsd, skillid))/100; + if (sp) + sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10 + pc_skillheal2_bonus(dstsd, skillid))/100; + } + if( tsc && tsc->count ) { + if (tsc->data[SC_CRITICALWOUND]) { + hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + } + if (tsc->data[SC_DEATHHURT]) { + hp -= hp * 20 / 100; + sp -= sp * 20 / 100; + } + if( tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2) { + hp += hp / 10; + sp += sp / 10; + } + } + if(hp > 0) + clif_skill_nodamage(NULL,bl,AL_HEAL,hp,1); + if(sp > 0) + clif_skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); + status_heal(bl,hp,sp,0); + } + break; + // Full Chemical Protection + case CR_FULLPROTECTION: + { + unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; + int i, s = 0, skilltime = skill_get_time(skillid,skilllv); + + for (i=0 ; i<4; i++) { + if( bl->type != BL_PC || ( dstsd && pc_checkequip(dstsd,equip[i]) < 0 ) ) + continue; + sc_start(bl,(sc_type)(SC_CP_WEAPON + i),100,skilllv,skilltime); + s++; + } + if( sd && !s ){ + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); // Don't consume item requirements + return 0; + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case RG_CLEANER: //AppleGirl + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + + case CG_LONGINGFREEDOM: + { + if (tsc && !tsce && (tsce=tsc->data[SC_DANCING]) && tsce->val4 + && (tsce->val1&0xFFFF) != CG_MOONLIT) //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex] + { + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + } + } + break; - clif_skill_nodamage(bl, bl, skillid, i, 1); - if (tsc && tsc->data[SC_AKAITSUKI] && i) - i = ~i + 1; - status_heal(bl, i, 0, 0); - } - } else if (sd) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - break; + case CG_TAROTCARD: + { + int eff, count = -1; + if( rnd() % 100 > skilllv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPERIUM) || mob_is_battleground(dstmd))) ) + { + if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - case AB_ORATIO: - if (flag&1) - sc_start(bl, type, 40 + 5 * skilllv, skilllv, skill_get_time(skillid, skilllv)); - else { - map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid, skilllv), BL_CHAR, - src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - } - break; + map_freeblock_unlock(); + return 0; + } + status_zap(src,0,skill_db[skill_get_index(skillid)].sp[skilllv]); // consume sp only if succeeded [Inkfish] + do { + eff = rnd() % 14; + clif_specialeffect(bl, 523 + eff, AREA); + switch (eff) + { + case 0: // heals SP to 0 + status_percent_damage(src, bl, 0, 100, false); + break; + case 1: // matk halved + sc_start(bl,SC_INCMATKRATE,100,-50,skill_get_time2(skillid,skilllv)); + break; + case 2: // all buffs removed + status_change_clear_buffs(bl,1); + break; + case 3: // 1000 damage, random armor destroyed + { + int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; + status_fix_damage(src, bl, 1000, 0); + clif_damage(src,bl,tick,0,0,1000,0,0,0); + if( !status_isdead(bl) ) + skill_break_equip(bl, where[rnd()%5], 10000, BCT_ENEMY); + } + break; + case 4: // atk halved + sc_start(bl,SC_INCATKRATE,100,-50,skill_get_time2(skillid,skilllv)); + break; + case 5: // 2000HP heal, random teleported + status_heal(src, 2000, 0, 0); + if( !map_flag_vs(bl->m) ) + unit_warp(bl, -1,-1,-1, CLR_TELEPORT); + break; + case 6: // random 2 other effects + if (count == -1) + count = 3; + else + count++; //Should not retrigger this one. + break; + case 7: // stop freeze or stoned + { + enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE }; + sc_start(bl,sc[rnd()%3],100,skilllv,skill_get_time2(skillid,skilllv)); + } + break; + case 8: // curse coma and poison + sc_start(bl,SC_COMA,100,skilllv,skill_get_time2(skillid,skilllv)); + sc_start(bl,SC_CURSE,100,skilllv,skill_get_time2(skillid,skilllv)); + sc_start(bl,SC_POISON,100,skilllv,skill_get_time2(skillid,skilllv)); + break; + case 9: // confusion + sc_start(bl,SC_CONFUSION,100,skilllv,skill_get_time2(skillid,skilllv)); + break; + case 10: // 6666 damage, atk matk halved, cursed + status_fix_damage(src, bl, 6666, 0); + clif_damage(src,bl,tick,0,0,6666,0,0,0); + sc_start(bl,SC_INCATKRATE,100,-50,skill_get_time2(skillid,skilllv)); + sc_start(bl,SC_INCMATKRATE,100,-50,skill_get_time2(skillid,skilllv)); + sc_start(bl,SC_CURSE,skilllv,100,skill_get_time2(skillid,skilllv)); + break; + case 11: // 4444 damage + status_fix_damage(src, bl, 4444, 0); + clif_damage(src,bl,tick,0,0,4444,0,0,0); + break; + case 12: // stun + sc_start(bl,SC_STUN,100,skilllv,5000); + break; + case 13: // atk,matk,hit,flee,def reduced + sc_start(bl,SC_INCATKRATE,100,-20,skill_get_time2(skillid,skilllv)); + sc_start(bl,SC_INCMATKRATE,100,-20,skill_get_time2(skillid,skilllv)); + sc_start(bl,SC_INCHITRATE,100,-20,skill_get_time2(skillid,skilllv)); + sc_start(bl,SC_INCFLEERATE,100,-20,skill_get_time2(skillid,skilllv)); + sc_start(bl,SC_INCDEFRATE,100,-20,skill_get_time2(skillid,skilllv)); + break; + default: + break; + } + } while ((--count) > 0); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case SL_ALCHEMIST: + case SL_ASSASIN: + case SL_BARDDANCER: + case SL_BLACKSMITH: + case SL_CRUSADER: + case SL_HUNTER: + case SL_KNIGHT: + case SL_MONK: + case SL_PRIEST: + case SL_ROGUE: + case SL_SAGE: + case SL_SOULLINKER: + case SL_STAR: + case SL_SUPERNOVICE: + case SL_WIZARD: + //NOTE: here, 'type' has the value of the associated MAPID, not of the SC_SPIRIT constant. + if (sd && !(dstsd && (dstsd->class_&MAPID_UPPERMASK) == type)) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + if (skillid == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rnd()%100)) + { //Erase death count 1% of the casts + dstsd->die_counter = 0; + pc_setglobalreg(dstsd,"PC_DIE_COUNTER", 0); + clif_specialeffect(bl, 0x152, AREA); + //SC_SPIRIT invokes status_calc_pc for us. + } + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start4(bl,SC_SPIRIT,100,skilllv,skillid,0,0,skill_get_time(skillid,skilllv))); + sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA,skilllv)); + break; + case SL_HIGH: + if (sd && !(dstsd && (dstsd->class_&JOBL_UPPER) && !(dstsd->class_&JOBL_2) && dstsd->status.base_level < 70)) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start4(bl,type,100,skilllv,skillid,0,0,skill_get_time(skillid,skilllv))); + sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA,skilllv)); + break; + + case SL_SWOO: + if (tsce) { + sc_start(src,SC_STUN,100,skilllv,10000); + break; + } + case SL_SKA: // [marquis007] + case SL_SKE: + if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + status_change_start(src,SC_STUN,10000,skilllv,0,0,0,500,10); + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + if (skillid == SL_SKE) + sc_start(src,SC_SMA,100,skilllv,skill_get_time(SL_SMA,skilllv)); + break; + + // New guild skills [Celest] + case GD_BATTLEORDER: + if(flag&1) { + if (status_get_guild_id(src) == status_get_guild_id(bl)) + sc_start(bl,type,100,skilllv,skill_get_time(skillid, skilllv)); + } else if (status_get_guild_id(src)) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub, src, + skill_get_splash(skillid, skilllv), BL_PC, + src,skillid,skilllv,tick, flag|BCT_GUILD|1, + skill_castend_nodamage_id); + if (sd) + guild_block_skill(sd,skill_get_time2(skillid,skilllv)); + } + break; + case GD_REGENERATION: + if(flag&1) { + if (status_get_guild_id(src) == status_get_guild_id(bl)) + sc_start(bl,type,100,skilllv,skill_get_time(skillid, skilllv)); + } else if (status_get_guild_id(src)) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub, src, + skill_get_splash(skillid, skilllv), BL_PC, + src,skillid,skilllv,tick, flag|BCT_GUILD|1, + skill_castend_nodamage_id); + if (sd) + guild_block_skill(sd,skill_get_time2(skillid,skilllv)); + } + break; + case GD_RESTORE: + if(flag&1) { + if (status_get_guild_id(src) == status_get_guild_id(bl)) + clif_skill_nodamage(src,bl,AL_HEAL,status_percent_heal(bl,90,90),1); + } else if (status_get_guild_id(src)) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub, src, + skill_get_splash(skillid, skilllv), BL_PC, + src,skillid,skilllv,tick, flag|BCT_GUILD|1, + skill_castend_nodamage_id); + if (sd) + guild_block_skill(sd,skill_get_time2(skillid,skilllv)); + } + break; + case GD_EMERGENCYCALL: + { + 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 j = 0; + struct guild *g = NULL; + // i don't know if it actually summons in a circle, but oh well. ;P + g = sd?sd->state.gmaster_flag:guild_search(status_get_guild_id(src)); + if (!g) + break; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + for(i = 0; i < g->max_member; i++, j++) { + if (j>8) j=0; + if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) { + if (map[dstsd->bl.m].flag.nowarp && !map_flag_gvg2(dstsd->bl.m)) + continue; + if(map_getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH)) + dx[j] = dy[j] = 0; + pc_setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN); + } + } + if (sd) + guild_block_skill(sd,skill_get_time2(skillid,skilllv)); + } + break; + + case SG_FEEL: + //AuronX reported you CAN memorize the same map as all three. [Skotlex] + if (sd) { + if(!sd->feel_map[skilllv-1].index) + clif_feel_req(sd->fd,sd, skilllv); + else + clif_feel_info(sd, skilllv-1, 1); + } + break; + + case SG_HATE: + if (sd) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if (!pc_set_hate_mob(sd, skilllv-1, bl)) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } + break; + + case GS_GLITTERING: + if(sd) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if(rnd()%100 < (20+10*skilllv)) + pc_addspiritball(sd,skill_get_time(skillid,skilllv),10); + else if(sd->spiritball > 0) + pc_delspiritball(sd,1,0); + } + break; + + case GS_CRACKER: + /* per official standards, this skill works on players and mobs. */ + if (sd && (dstsd || dstmd)) + { + i =65 -5*distance_bl(src,bl); //Base rate + if (i < 30) i = 30; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + sc_start(bl,SC_STUN, i,skilllv,skill_get_time2(skillid,skilllv)); + } + break; + + case AM_CALLHOMUN: //[orn] + if (sd && !merc_call_homunculus(sd)) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + + case AM_REST: + if (sd) { + if (merc_hom_vaporize(sd,1)) + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + else + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } + break; + + case HAMI_CASTLE: //[orn] + if(rnd()%100 < 20*skilllv && src != bl) + { + int x,y; + x = src->x; + y = src->y; + if (hd) + skill_blockhomun_start(hd, skillid, skill_get_time2(skillid,skilllv)); + + if (unit_movepos(src,bl->x,bl->y,0,0)) { + clif_skill_nodamage(src,src,skillid,skilllv,1); // Homunc + clif_slide(src,bl->x,bl->y) ; + if (unit_movepos(bl,x,y,0,0)) + { + clif_skill_nodamage(bl,bl,skillid,skilllv,1); // Master + clif_slide(bl,x,y) ; + } - case AB_LAUDAAGNUS: - if (flag&1 || sd == NULL) { - if (tsc && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE] || tsc->data[SC_BLIND] || - tsc->data[SC_BURNING] || tsc->data[SC_FREEZING] || tsc->data[SC_CRYSTALIZE])) { - // Success Chance: (40 + 10 * Skill Level) % - if (rnd()%100 > 40+10*skilllv) break; - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - status_change_end(bl, SC_BURNING, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); - status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); - } else //Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets - clif_skill_nodamage(bl, bl, skillid, skilllv, - sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); - } else if (sd) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), - src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - break; + //TODO: Shouldn't also players and the like switch targets? + map_foreachinrange(skill_chastle_mob_changetarget,src, + AREA_SIZE, BL_MOB, bl, src); + } + } + // Failed + else if (hd && hd->master) + clif_skill_fail(hd->master, skillid, USESKILL_FAIL_LEVEL, 0); + else if (sd) + clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); + break; + case HVAN_CHAOTIC: //[orn] + { + static const int per[5][2]={{20,50},{50,60},{25,75},{60,64},{34,67}}; + int r = rnd()%100; + i = (skilllv-1)%5; + if(r<per[i][0]) //Self + bl = src; + else if(r<per[i][1]) //Master + bl = battle_get_master(src); + else //Enemy + bl = map_id2bl(battle_gettarget(src)); + + if (!bl) bl = src; + i = skill_calc_heal(src, bl, skillid, 1+rnd()%skilllv, true); + //Eh? why double skill packet? + clif_skill_nodamage(src,bl,AL_HEAL,i,1); + clif_skill_nodamage(src,bl,skillid,i,1); + status_heal(bl, i, 0, 0); + } + break; + //Homun single-target support skills [orn] + case HAMI_BLOODLUST: + case HFLI_FLEET: + case HFLI_SPEED: + case HLIF_CHANGE: + case MH_ANGRIFFS_MODUS: + case MH_GOLDENE_FERSE: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + if (hd) + skill_blockhomun_start(hd, skillid, skill_get_time2(skillid,skilllv)); + break; + + case NPC_DRAGONFEAR: + if (flag&1) { + const enum sc_type sc[] = { SC_STUN, SC_SILENCE, SC_CONFUSION, SC_BLEEDING }; + int j; + j = i = rnd()%ARRAYLENGTH(sc); + while ( !sc_start(bl,sc[i],100,skilllv,skill_get_time2(skillid,i+1)) ) { + i++; + if ( i == ARRAYLENGTH(sc) ) + i = 0; + if (i == j) + break; + } + break; + } + case NPC_WIDEBLEEDING: + case NPC_WIDECONFUSE: + case NPC_WIDECURSE: + case NPC_WIDEFREEZE: + case NPC_WIDESLEEP: + case NPC_WIDESILENCE: + case NPC_WIDESTONE: + case NPC_WIDESTUN: + case NPC_SLOWCAST: + case NPC_WIDEHELLDIGNITY: + if (flag&1) + sc_start(bl,type,100,skilllv,skill_get_time2(skillid,skilllv)); + else { + skill_area_temp[2] = 0; //For SD_PREAMBLE + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv),BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, + skill_castend_nodamage_id); + } + break; + case NPC_WIDESOULDRAIN: + if (flag&1) + status_percent_damage(src,bl,0,((skilllv-1)%5+1)*20,false); + else { + skill_area_temp[2] = 0; //For SD_PREAMBLE + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub, bl, + skill_get_splash(skillid, skilllv),BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, + skill_castend_nodamage_id); + } + break; + case ALL_PARTYFLEE: + if( sd && !(flag&1) ) + { + if( !sd->status.party_id ) + { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + } + else + clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + break; + case NPC_TALK: + case ALL_WEWISH: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + case ALL_BUYING_STORE: + if( sd ) + {// players only, skill allows 5 buying slots + clif_skill_nodamage(src, bl, skillid, skilllv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS)); + } + break; + case RK_ENCHANTBLADE: + clif_skill_nodamage(src,bl,skillid,skilllv,// formula not confirmed + sc_start2(bl,type,100,skilllv,100+20*skilllv/*+sstatus->int_/2+status_get_lv(bl)/10*/,skill_get_time(skillid,skilllv))); + break; + case RK_DRAGONHOWLING: + if( flag&1) + sc_start(bl,type,50 + 6 * skilllv,skilllv,skill_get_time(skillid,skilllv)); + else + { + skill_area_temp[2] = 0; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub, src, + skill_get_splash(skillid,skilllv),BL_CHAR, + src,skillid,skilllv,tick,flag|BCT_ENEMY|SD_PREAMBLE|1, + skill_castend_nodamage_id); + } + break; + case RK_IGNITIONBREAK: + case LG_EARTHDRIVE: + clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + i = skill_get_splash(skillid,skilllv); + if( skillid == LG_EARTHDRIVE ) { + int dummy = 1; + map_foreachinarea(skill_cell_overlap, src->m, src->x-i, src->y-i, src->x+i, src->y+i, BL_SKILL, LG_EARTHDRIVE, &dummy, src); + } + map_foreachinrange(skill_area_sub, bl,i,BL_CHAR, + src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + break; + case RK_STONEHARDSKIN: + if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 4 ) + { + int heal = sstatus->hp / 4; // 25% HP + if( status_charge(bl,heal,0) ) + clif_skill_nodamage(src,bl,skillid,skilllv,sc_start2(bl,type,100,skilllv,heal,skill_get_time(skillid,skilllv))); + else + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } + break; + case RK_REFRESH: + if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 8 ) + { + int heal = status_get_max_hp(bl) * 25 / 100; + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + status_heal(bl,heal,0,1); + status_change_clear_buffs(bl,2); + } + break; + + case RK_MILLENNIUMSHIELD: + if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 9 ) + { + short shields = (rnd()%100<50) ? 4 : ((rnd()%100<80) ? 3 : 2); + sc_start4(bl,type,100,skilllv,shields,1000,0,skill_get_time(skillid,skilllv)); + clif_millenniumshield(sd,shields); + clif_skill_nodamage(src,bl,skillid,1,1); + } + break; + + case RK_GIANTGROWTH: + case RK_VITALITYACTIVATION: + case RK_ABUNDANCE: + if( sd ) + { + int lv = 1; // RK_GIANTGROWTH + if( skillid == RK_VITALITYACTIVATION ) + lv = 2; + else if( skillid == RK_ABUNDANCE ) + lv = 6; + if( pc_checkskill(sd,RK_RUNEMASTERY) >= lv ) + clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + } + break; + + case RK_FIGHTINGSPIRIT: + if( flag&1 ) { + if( src == bl ) + sc_start2(bl,type,100,skill_area_temp[5],10*(sd?pc_checkskill(sd,RK_RUNEMASTERY):10),skill_get_time(skillid,skilllv)); + else + sc_start(bl,type,100,skill_area_temp[5]/4,skill_get_time(skillid,skilllv)); + } else if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 5 ) { + if( sd->status.party_id ) { + i = party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skillid,skilllv),src,skillid,skilllv,tick,BCT_PARTY,skill_area_sub_count); + skill_area_temp[5] = 7 * i; // ATK + party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skillid,skilllv),src,skillid,skilllv,tick,flag|BCT_PARTY|1,skill_castend_nodamage_id); + } else + sc_start2(bl,type,100,7,5,skill_get_time(skillid,skilllv)); + } + clif_skill_nodamage(src,bl,skillid,1,1); + break; + /** + * Guilotine Cross + **/ + case GC_ROLLINGCUTTER: + { + short count = 1; + skill_area_temp[2] = 0; + map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|SD_PREAMBLE|SD_SPLASH|1,skill_castend_damage_id); + if( tsc && tsc->data[SC_ROLLINGCUTTER] ) + { // Every time the skill is casted the status change is reseted adding a counter. + count += (short)tsc->data[SC_ROLLINGCUTTER]->val1; + if( count > 10 ) + count = 10; // Max coounter + status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); + } + sc_start(bl,SC_ROLLINGCUTTER,100,count,skill_get_time(skillid,skilllv)); + clif_skill_nodamage(src,src,skillid,skilllv,1); + } + break; + + case GC_WEAPONBLOCKING: + if( tsc && tsc->data[SC_WEAPONBLOCKING] ) + status_change_end(bl, SC_WEAPONBLOCKING, INVALID_TIMER); + else + sc_start(bl,SC_WEAPONBLOCKING,100,skilllv,skill_get_time(skillid,skilllv)); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + + case GC_CREATENEWPOISON: + if( sd ) + { + clif_skill_produce_mix_list(sd,skillid,25); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + } + break; + + case GC_POISONINGWEAPON: + if( sd ) { + clif_poison_list(sd,skilllv); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case GC_ANTIDOTE: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if( tsc ) + { + status_change_end(bl, SC_PARALYSE, INVALID_TIMER); + status_change_end(bl, SC_PYREXIA, INVALID_TIMER); + status_change_end(bl, SC_DEATHHURT, INVALID_TIMER); + status_change_end(bl, SC_LEECHESEND, INVALID_TIMER); + status_change_end(bl, SC_VENOMBLEED, INVALID_TIMER); + status_change_end(bl, SC_MAGICMUSHROOM, INVALID_TIMER); + status_change_end(bl, SC_TOXIN, INVALID_TIMER); + status_change_end(bl, SC_OBLIVIONCURSE, INVALID_TIMER); + } + break; + + case GC_PHANTOMMENACE: + clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR, + src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + break; + + case GC_HALLUCINATIONWALK: + { + int heal = status_get_max_hp(bl) / 10; + if( status_get_hp(bl) < heal ) { // if you haven't enough HP skill fails. + if( sd ) clif_skill_fail(sd,skillid,USESKILL_FAIL_HP_INSUFFICIENT,0); + break; + } + if( !status_charge(bl,heal,0) ) + { + if( sd ) clif_skill_fail(sd,skillid,USESKILL_FAIL_HP_INSUFFICIENT,0); + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv,sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + } + break; + /** + * Arch Bishop + **/ + case AB_ANCILLA: + if( sd ) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_produce_mix(sd, skillid, ITEMID_ANCILLA, 0, 0, 0, 1); + } + break; + + case AB_CLEMENTIA: + case AB_CANTO: + { + int bless_lv = pc_checkskill(sd,AL_BLESSING); + int agi_lv = pc_checkskill(sd,AL_INCAGI); + if( sd == NULL || sd->status.party_id == 0 || flag&1 ) + clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl,type,100, + (skillid == AB_CLEMENTIA)? bless_lv : (skillid == AB_CANTO)? agi_lv : skilllv, skill_get_time(skillid,skilllv))); + else if( sd ) + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + } + break; + + case AB_PRAEFATIO: + if( sd == NULL || sd->status.party_id == 0 || flag&1 ) + clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start4(bl, type, 100, skilllv, 0, 0, 1, skill_get_time(skillid, skilllv))); + else if( sd ) + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + break; + + case AB_CHEAL: + if( sd == NULL || sd->status.party_id == 0 || flag&1 ) + { + if( sd && tstatus && !battle_check_undead(tstatus->race, tstatus->def_ele) ) + { + i = skill_calc_heal(src, bl, AL_HEAL, pc_checkskill(sd, AL_HEAL), true); - case AB_LAUDARAMUS: - if (flag&1 || sd == NULL) { - if (tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] || tsc->data[SC_SILENCE])) { - // Success Chance: (40 + 10 * Skill Level) % - if (rnd()%100 > 40+10*skilllv) break; - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); - status_change_end(bl, SC_MANDRAGORA, INVALID_TIMER); - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - } else // Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets - clif_skill_nodamage(bl, bl, skillid, skilllv, - sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); - } else if (sd) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), - src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - break; + if( (dstsd && pc_ismadogear(dstsd)) || status_isimmune(bl)) + i = 0; // Should heal by 0 or won't do anything?? in iRO it breaks the healing to members.. [malufett] - case AB_CLEARANCE: - if (flag&1 || (i = skill_get_splash(skillid, skilllv)) < 1) { - //As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie] - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if ((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) || rnd()%100 >= 30 + 10 * skilllv) { - if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - if (status_isimmune(bl) || !tsc || !tsc->count) - break; - for (i=0; i<SC_MAX; i++) { - if (!tsc->data[i]) - continue; - switch (i) { - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_HALLUCINATION: - 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: - case SC_COMBO: - case SC_STRFOOD: - case SC_AGIFOOD: - case SC_VITFOOD: - case SC_INTFOOD: - case SC_DEXFOOD: - case SC_LUKFOOD: - case SC_HITFOOD: - case SC_FLEEFOOD: - case SC_BATKFOOD: - case SC_WATKFOOD: - case SC_MATKFOOD: - case SC_DANCING: - case SC_SPIRIT: - case SC_AUTOBERSERK: - case SC_CARTBOOST: - case SC_MELTDOWN: - case SC_SAFETYWALL: - case SC_SMA: - case SC_SPEEDUP0: - case SC_NOCHAT: - case SC_ANKLE: - case SC_SPIDERWEB: - case SC_JAILED: - case SC_ITEMBOOST: - case SC_EXPBOOST: - case SC_LIFEINSURANCE: - case SC_BOSSMAPINFO: - case SC_PNEUMA: - case SC_AUTOSPELL: - case SC_INCHITRATE: - case SC_INCATKRATE: - case SC_NEN: - case SC_READYSTORM: - case SC_READYDOWN: - case SC_READYTURN: - case SC_READYCOUNTER: - case SC_DODGE: - case SC_WARM: - case SC_SPEEDUP1: - case SC_AUTOTRADE: - case SC_CRITICALWOUND: - case SC_JEXPBOOST: - case SC_INVINCIBLE: - case SC_INVINCIBLEOFF: - case SC_HELLPOWER: - case SC_MANU_ATK: - case SC_MANU_DEF: - case SC_SPL_ATK: - case SC_SPL_DEF: - case SC_MANU_MATK: - case SC_SPL_MATK: - case SC_RICHMANKIM: - case SC_ETERNALCHAOS: - case SC_DRUMBATTLE: - case SC_NIBELUNGEN: - case SC_ROKISWEIL: - case SC_INTOABYSS: - case SC_SIEGFRIED: - case SC_WHISTLE: - case SC_ASSNCROS: - case SC_POEMBRAGI: - case SC_APPLEIDUN: - case SC_HUMMING: - case SC_DONTFORGETME: - case SC_FORTUNE: - case SC_SERVICE4U: - case SC_FOOD_STR_CASH: - case SC_FOOD_AGI_CASH: - case SC_FOOD_VIT_CASH: - case SC_FOOD_DEX_CASH: - case SC_FOOD_INT_CASH: - case SC_FOOD_LUK_CASH: - case SC_ELECTRICSHOCKER: - case SC_BITE: - case SC__STRIPACCESSORY: - case SC__ENERVATION: - case SC__GROOMY: - case SC__IGNORANCE: - case SC__LAZINESS: - case SC__UNLUCKY: - case SC__WEAKNESS: //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: - case SC_MAGNETICFIELD://case SC_MINOR_BBQ: case SC_SIROMA_ICE_TEA: - //case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: - case SC_NEUTRALBARRIER_MASTER: - case SC_NEUTRALBARRIER: - case SC_STEALTHFIELD_MASTER: - case SC_STEALTHFIELD: - case SC_LEADERSHIP: - case SC_GLORYWOUNDS: - case SC_SOULCOLD: - case SC_HAWKEYES: - case SC_GUILDAURA: - case SC_PUSH_CART: - case SC_PARTYFLEE: - case SC_GT_REVITALIZE: - case SC_RAISINGDRAGON: - case SC_GT_ENERGYGAIN: - case SC_GT_CHANGE: + clif_skill_nodamage(bl, bl, skillid, i, 1); + if( tsc && tsc->data[SC_AKAITSUKI] && i ) + i = ~i + 1; + status_heal(bl, i, 0, 0); + } + } + else if( sd ) + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + break; + + case AB_ORATIO: + if( flag&1 ) + sc_start(bl, type, 40 + 5 * skilllv, skilllv, skill_get_time(skillid, skilllv)); + else + { + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid, skilllv), BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + } + break; + + case AB_LAUDAAGNUS: + if( flag&1 || sd == NULL ) { + if( tsc && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE] || tsc->data[SC_BLIND] || + tsc->data[SC_BURNING] || tsc->data[SC_FREEZING] || tsc->data[SC_CRYSTALIZE])) { + // Success Chance: (40 + 10 * Skill Level) % + if( rnd()%100 > 40+10*skilllv ) break; + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + status_change_end(bl, SC_BURNING, INVALID_TIMER); + status_change_end(bl, SC_FREEZING, INVALID_TIMER); + status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); + }else //Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets + clif_skill_nodamage(bl, bl, skillid, skilllv, + sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); + } else if( sd ) + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), + src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + break; + + case AB_LAUDARAMUS: + if( flag&1 || sd == NULL ) { + if( tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] || tsc->data[SC_SILENCE]) ){ + // Success Chance: (40 + 10 * Skill Level) % + if( rnd()%100 > 40+10*skilllv ) break; + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + status_change_end(bl, SC_MANDRAGORA, INVALID_TIMER); + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + }else // Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets + clif_skill_nodamage(bl, bl, skillid, skilllv, + sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); + } else if( sd ) + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), + src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + break; + + case AB_CLEARANCE: + if( flag&1 || (i = skill_get_splash(skillid, skilllv)) < 1 ) + { //As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie] + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) || rnd()%100 >= 30 + 10 * skilllv) + { + if (sd) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + if(status_isimmune(bl) || !tsc || !tsc->count) + break; + for(i=0;i<SC_MAX;i++) + { + if (!tsc->data[i]) + continue; + switch (i) { + case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION: + 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: case SC_COMBO: + case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD: + case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD: + case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD: + case SC_WATKFOOD: case SC_MATKFOOD: case SC_DANCING: + case SC_SPIRIT: case SC_AUTOBERSERK: + case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL: + case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT: + case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED: + case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE: + case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL: + case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN: + case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN: + case SC_READYCOUNTER:case SC_DODGE: case SC_WARM: + case SC_SPEEDUP1: case SC_AUTOTRADE: case SC_CRITICALWOUND: + case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF: + case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF: + case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK: + case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS: + case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL: + case SC_INTOABYSS: case SC_SIEGFRIED: case SC_WHISTLE: + case SC_ASSNCROS: case SC_POEMBRAGI: case SC_APPLEIDUN: + case SC_HUMMING: case SC_DONTFORGETME: case SC_FORTUNE: + case SC_SERVICE4U: case SC_FOOD_STR_CASH: case SC_FOOD_AGI_CASH: + case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: case SC_FOOD_INT_CASH: + case SC_FOOD_LUK_CASH: case SC_ELECTRICSHOCKER: case SC_BITE: + case SC__STRIPACCESSORY: case SC__ENERVATION: case SC__GROOMY: + case SC__IGNORANCE: case SC__LAZINESS: case SC__UNLUCKY: + case SC__WEAKNESS: //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: + case SC_MAGNETICFIELD://case SC_MINOR_BBQ: case SC_SIROMA_ICE_TEA: + //case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: + case SC_NEUTRALBARRIER_MASTER: case SC_NEUTRALBARRIER: + case SC_STEALTHFIELD_MASTER: case SC_STEALTHFIELD: + case SC_LEADERSHIP: case SC_GLORYWOUNDS: case SC_SOULCOLD: + case SC_HAWKEYES: case SC_GUILDAURA: case SC_PUSH_CART: + case SC_PARTYFLEE: case SC_GT_REVITALIZE: + case SC_RAISINGDRAGON: case SC_GT_ENERGYGAIN: case SC_GT_CHANGE: #ifdef RENEWAL - case SC_EXTREMITYFIST2: + case SC_EXTREMITYFIST2: #endif - continue; - case SC_ASSUMPTIO: - if (bl->type == BL_MOB) - continue; - break; - } - if (i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. - status_change_end(bl,(sc_type)i,INVALID_TIMER); - } - break; - } - map_foreachinrange(skill_area_sub, bl, i, BL_CHAR, src, skillid, skilllv, tick, flag|1, skill_castend_damage_id); - break; - - case AB_SILENTIUM: - // Should the level of Lex Divina be equivalent to the level of Silentium or should the highest level learned be used? [LimitLine] - map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid, skilllv), BL_CHAR, - src, PR_LEXDIVINA, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - break; - /** - * Warlock - **/ - case WL_STASIS: - if (flag&1) - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - else { - map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid, skilllv),BL_CHAR,src,skillid,skilllv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill_castend_nodamage_id); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - } - break; - - case WL_WHITEIMPRISON: - if ((src == bl || battle_check_target(src, bl, BCT_ENEMY)) && !is_boss(bl)) { // Should not work with bosses. - int rate = (sd? sd->status.job_level : 50) / 4; - - if (src == bl) rate = 100; // Success Chance: On self, 100% - else if (bl->type == BL_PC) rate += 20 + 10 * skilllv; // On Players, (20 + 10 * Skill Level) % - else rate += 40 + 10 * skilllv; // On Monsters, (40 + 10 * Skill Level) % - - if (!(tsc && tsc->data[type])) { - i = sc_start2(bl,type,rate,skilllv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill_get_time(skillid,skilllv):skill_get_time2(skillid, skilllv)); - clif_skill_nodamage(src,bl,skillid,skilllv,i); - } - - if (sd && i) - skill_blockpc_start(sd,skillid,4000); // Reuse Delay only activated on success - else if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } else if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_TOTARGET,0); - break; - - case WL_FROSTMISTY: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinrange(skill_area_sub,bl,skill_get_splash(skillid,skilllv),BL_CHAR|BL_SKILL,src,skillid,skilllv,tick,flag|BCT_ENEMY,skill_castend_damage_id); - break; - - case WL_JACKFROST: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_foreachinshootrange(skill_area_sub,bl,skill_get_splash(skillid,skilllv),BL_CHAR|BL_SKILL,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - break; - - case WL_MARSHOFABYSS: - // Should marsh of abyss still apply half reduction to players after the 28/10 patch? [LimitLine] - clif_skill_nodamage(src, bl, skillid, skilllv, - sc_start4(bl, type, 100, skilllv, status_get_int(src), sd ? sd->status.job_level : 50, 0, - skill_get_time(skillid, skilllv))); - break; - - case WL_SIENNAEXECRATE: - if (status_isimmune(bl) || !tsc) - break; - - if (flag&1) { - if (bl->id == skill_area_temp[1]) - break; // Already work on this target - - if (tsc && tsc->data[SC_STONE]) - status_change_end(bl,SC_STONE,INVALID_TIMER); - else - status_change_start(bl,SC_STONE,10000,skilllv,0,0,1000,skill_get_time(skillid, skilllv),2); - } else { - int rate = 40 + 8 * skilllv + (sd? sd->status.job_level : 50) / 4; - // IroWiki says Rate should be reduced by target stats, but currently unknown - if (rnd()%100 < rate) { // Success on First Target - if (!tsc->data[SC_STONE]) - rate = status_change_start(bl,SC_STONE,10000,skilllv,0,0,1000,skill_get_time(skillid, skilllv),2); - else { - rate = 1; - status_change_end(bl,SC_STONE,INVALID_TIMER); - } - - if (rate) { - skill_area_temp[1] = bl->id; - map_foreachinrange(skill_area_sub,bl,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id); - } - // Doesn't send failure packet if it fails on defense. - } else if (sd) // Failure on Rate - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } - break; - - case WL_SUMMONFB: - case WL_SUMMONBL: - case WL_SUMMONWB: - case WL_SUMMONSTONE: { - short element = 0, sctype = 0, pos = -1; - struct status_change *sc = status_get_sc(src); - if (!sc) break; - - for (i = SC_SPHERE_1; i <= SC_SPHERE_5; i++) { - if (!sctype && !sc->data[i]) - sctype = i; // Take the free SC - if (sc->data[i]) - pos = max(sc->data[i]->val2,pos); - } - - if (!sctype) { - if (sd) // No free slots to put SC - clif_skill_fail(sd,skillid,USESKILL_FAIL_SUMMON,0); - break; - } - - pos++; // Used in val2 for SC. Indicates the order of this ball - switch (skillid) { - // Set val1. The SC element for this ball - case WL_SUMMONFB: - element = WLS_FIRE; - break; - case WL_SUMMONBL: - element = WLS_WIND; - break; - case WL_SUMMONWB: - element = WLS_WATER; - break; - case WL_SUMMONSTONE: - element = WLS_STONE; - break; - } - - sc_start4(src,sctype,100,element,pos,skilllv,0,skill_get_time(skillid,skilllv)); - clif_skill_nodamage(src,bl,skillid,0,0); - } - break; - - case WL_READING_SB: - if (sd) { - struct status_change *sc = status_get_sc(bl); - - for (i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) - if (sc && !sc->data[i]) - break; - if (i == SC_MAXSPELLBOOK) { - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); - break; - } - - sc_start(bl, SC_STOP, 100, skilllv, INVALID_TIMER); //Can't move while selecting a spellbook. - clif_spellbook_list(sd); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - } - break; - /** - * Ranger - **/ - case RA_FEARBREEZE: - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - clif_skill_nodamage(src, bl, skillid, skilllv, sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); - break; - - case RA_WUGMASTERY: - if (sd) { - if (!pc_iswug(sd)) - pc_setoption(sd,sd->sc.option|OPTION_WUG); - else - pc_setoption(sd,sd->sc.option&~OPTION_WUG); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case RA_WUGRIDER: - if (sd) { - if (!pc_isridingwug(sd) && pc_iswug(sd)) { - pc_setoption(sd,sd->sc.option&~OPTION_WUG); - pc_setoption(sd,sd->sc.option|OPTION_WUGRIDER); - } else if (pc_isridingwug(sd)) { - pc_setoption(sd,sd->sc.option&~OPTION_WUGRIDER); - pc_setoption(sd,sd->sc.option|OPTION_WUG); - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case RA_WUGDASH: - if (tsce) { - clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, INVALID_TIMER)); - map_freeblock_unlock(); - return 0; - } - if (sd && pc_isridingwug(sd)) { - clif_skill_nodamage(src,bl,skillid,skilllv,sc_start4(bl,type,100,skilllv,unit_getdir(bl),0,0,1)); - clif_walkok(sd); - } - break; - - case RA_SENSITIVEKEEN: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR|BL_SKILL,src,skillid,skilllv,tick,flag|BCT_ENEMY,skill_castend_damage_id); - break; - /** - * Mechanic - **/ - case NC_F_SIDESLIDE: - case NC_B_SIDESLIDE: { - int dir = (skillid == NC_F_SIDESLIDE) ? (unit_getdir(src)+4)%8 : unit_getdir(src); - skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),dir,0x1); - clif_slide(src,src->x,src->y); - clif_fixpos(src); //Aegis sent this packet - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case NC_SELFDESTRUCTION: - if (sd) { - if (pc_ismadogear(sd)) - pc_setmadogear(sd, 0); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - skill_castend_damage_id(src, src, skillid, skilllv, tick, flag); - status_set_sp(src, 0, 0); - } - break; - - case NC_ANALYZE: - clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - clif_skill_nodamage(src, bl, skillid, skilllv, - sc_start(bl,type, 30 + 12 * skilllv,skilllv,skill_get_time(skillid,skilllv))); - if (sd) pc_overheat(sd,1); - break; - - case NC_MAGNETICFIELD: - if ((i = sc_start2(bl,type,100,skilllv,src->id,skill_get_time(skillid,skilllv)))) { - map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),splash_target(src),src,skillid,skilllv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill_castend_damage_id);; - clif_skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skillid,skilllv,6); - if (sd) pc_overheat(sd,1); - } - clif_skill_nodamage(src,src,skillid,skilllv,i); - break; - - case NC_REPAIR: - if (sd) { - int heal; - if (dstsd && pc_ismadogear(dstsd)) { - heal = dstsd->status.max_hp * (3+3*skilllv) / 100; - status_heal(bl,heal,0,2); - } else { - heal = sd->status.max_hp * (3+3*skilllv) / 100; - status_heal(src,heal,0,2); - } - - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - clif_skill_nodamage(src, bl, skillid, skilllv, heal); - } - break; - - case NC_DISJOINT: { - if (bl->type != BL_MOB) break; - md = map_id2md(bl->id); - if (md && md->class_ >= MOBID_SILVERSNIPER && md->class_ <= MOBID_MAGICDECOY_WIND) - status_kill(bl); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - } - break; - case SC_AUTOSHADOWSPELL: - if (sd) { - if (sd->status.skill[sd->reproduceskill_id].id || sd->status.skill[sd->cloneskill_id].id) { - sc_start(src,SC_STOP,100,skilllv,-1);// The skilllv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] - clif_autoshadowspell_list(sd); - clif_skill_nodamage(src,bl,skillid,1,1); - } else - clif_skill_fail(sd,skillid,USESKILL_FAIL_IMITATION_SKILL_NONE,0); - } - break; - - case SC_SHADOWFORM: - if (sd && dstsd && src != bl && !dstsd->shadowform_id) { - if (clif_skill_nodamage(src,bl,skillid,skilllv,sc_start4(src,type,100,skilllv,bl->id,4+skilllv,0,skill_get_time(skillid, skilllv)))) - dstsd->shadowform_id = src->id; - } else if (sd) - clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); - break; - - case SC_BODYPAINT: - if (flag&1) { - if (tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || - tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || - tsc->data[SC__INVISIBILITY])) { - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CHASEWALK, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); - - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - sc_start(bl,SC_BLIND,53 + 2 * skilllv,skilllv,skill_get_time(skillid,skilllv)); - } - } else { - clif_skill_nodamage(src, bl, skillid, 0, 1); - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), BL_CHAR, - src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - } - break; - - case SC_ENERVATION: - case SC_GROOMY: - case SC_LAZINESS: - case SC_UNLUCKY: - case SC_WEAKNESS: - if (!(tsc && tsc->data[type])) { - //((rand(myDEX / 12, myDEX / 4) + myJobLevel + 10 * skLevel) + myLevel / 10) - (targetLevel / 10 + targetLUK / 10 + (targetMaxWeight - targetWeight) / 1000 + rand(targetAGI / 6, targetAGI / 3)) - int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skilllv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 - - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); - rate = cap_value(rate, skilllv+sstatus->dex/20, 100); - clif_skill_nodamage(src,bl,skillid,0,sc_start(bl,type,rate,skilllv,skill_get_time(skillid,skilllv))); - } else if (sd) - clif_skill_fail(sd,skillid,0,0); - break; - - case SC_IGNORANCE: - if (!(tsc && tsc->data[type])) { - int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skilllv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 - - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); - rate = cap_value(rate, skilllv+sstatus->dex/20, 100); - if (clif_skill_nodamage(src,bl,skillid,0,sc_start(bl,type,rate,skilllv,skill_get_time(skillid,skilllv)))) { - int sp = 200 * skilllv; - if (dstmd) sp = dstmd->level * 2; - if (status_zap(bl,0,sp)) - status_heal(src,0,sp/2,3); - } else if (sd) clif_skill_fail(sd,skillid,0,0); - } else if (sd) - clif_skill_fail(sd,skillid,0,0); - break; - - case LG_TRAMPLE: - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - map_foreachinrange(skill_destroy_trap,bl,skill_get_splash(skillid,skilllv),BL_SKILL,tick); - break; - - case LG_REFLECTDAMAGE: - if (tsc && tsc->data[type]) - status_change_end(bl,type,INVALID_TIMER); - else - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - break; - - case LG_SHIELDSPELL: - if (flag&1) { - int duration = (sd) ? sd->bonus.shieldmdef * 2000 : 10000; - sc_start(bl,SC_SILENCE,100,skilllv,duration); - } else if (sd) { - int opt = skilllv; - int rate = rnd()%100; - int val, brate; - switch (skilllv) { - case 1: { - struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; - if (!shield_data || shield_data->type != IT_ARMOR) { // No shield? - clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); - break; - } - brate = shield_data->def * 10; - if (rate < 50) - opt = 1; - else if (rate < 75) - opt = 2; - else - opt = 3; - - switch (opt) { - case 1: - sc_start(bl,SC_SHIELDSPELL_DEF,100,opt,-1); - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - if (rate < brate) - map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER); - break; - case 2: - val = shield_data->def / 10; // % Reflected damage. - sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 1000); - break; - case 3: - val = shield_data->def; // Attack increase. - sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 3000); - break; - } - } - break; - - case 2: - brate = sd->bonus.shieldmdef * 20; - if (rate < 30) - opt = 1; - else if (rate < 60) - opt = 2; - else - opt = 3; - switch (opt) { - case 1: - sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - if (rate < brate) - map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|2,skill_castend_damage_id); - status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER); - break; - case 2: - sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - if (rate < brate) - map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id); - break; - case 3: - if (sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->bonus.shieldmdef * 30000)) - clif_skill_nodamage(src,bl,PR_MAGNIFICAT,skilllv, - sc_start(bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000)); - break; - } - break; - - case 3: { - struct item *it = &sd->status.inventory[sd->equip_index[EQI_HAND_L]]; - if (!it) { // No shield? - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - brate = it->refine * 5; - if (rate < 25) - opt = 1; - else if (rate < 50) - opt = 2; - else - opt = 3; - switch (opt) { - case 1: - val = 105 * it->refine / 10; - sc_start2(bl,SC_SHIELDSPELL_REF,brate,opt,val,skill_get_time(skillid,skilllv)); - break; - case 2: - case 3: - if (rate < brate) { - val = sstatus->max_hp * (11 + it->refine) / 100; - status_heal(bl, val, 0, 3); - } - break; - /*case 3: - // Full protection. I need confirm what effect should be here. Moved to case 2 to until we got it. - break;*/ - } - } - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case LG_PIETY: - if (flag&1) - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - else { - skill_area_temp[2] = 0; - map_foreachinrange(skill_area_sub,bl,skill_get_splash(skillid,skilllv),BL_PC,src,skillid,skilllv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill_castend_nodamage_id); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case LG_INSPIRATION: - if (sd && !map[sd->bl.m].flag.noexppenalty && sd->status.base_level != MAX_LEVEL) { - sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * 1 / 100); // 1% penalty. - sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * 1 / 100); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_JOBEXP); - } - clif_skill_nodamage(bl,src,skillid,skilllv, - sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); - break; - case SR_CURSEDCIRCLE: - if (flag&1) { - if (is_boss(bl)) break; - if (sc_start2(bl, type, 100, skilllv, src->id, skill_get_time(skillid, skilllv))) { - if (bl->type == BL_MOB) - mob_unlocktarget((TBL_MOB *)bl,gettick()); - unit_stop_attack(bl); - clif_bladestop(src, bl->id, 1); - map_freeblock_unlock(); - return 1; - } - } else { - int count = 0; - clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - count = map_forcountinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-charactors - BL_CHAR, src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - if (sd) pc_delspiritball(sd, count, 0); - clif_skill_nodamage(src, src, skillid, skilllv, - sc_start2(src, SC_CURSEDCIRCLE_ATKER, 100, skilllv, count, skill_get_time(skillid,skilllv))); - } - break; - - case SR_RAISINGDRAGON: - if (sd) { - short max = 5 + skilllv; - sc_start(bl, SC_EXPLOSIONSPIRITS, 100, skilllv, skill_get_time(skillid, skilllv)); - for (i = 0; i < max; i++) // Don't call more than max available spheres. - pc_addspiritball(sd, skill_get_time(skillid, skilllv), max); - clif_skill_nodamage(src, bl, skillid, skilllv, sc_start(bl, type, 100, skilllv,skill_get_time(skillid, skilllv))); - } - break; - - case SR_ASSIMILATEPOWER: - if (flag&1) { - i = 0; - if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) { - i = dstsd->spiritball; //1%sp per spiritball. - pc_delspiritball(dstsd, dstsd->spiritball, 0); - } - if (i) status_percent_heal(src, 0, i); - clif_skill_nodamage(src, bl, skillid, skilllv, i ? 1:0); - } else { - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill_castend_nodamage_id); - } - break; - - case SR_POWERVELOCITY: - if (!dstsd) - break; - if (sd && dstsd->spiritball <= 5) { - for (i = 0; i <= 5; i++) { - pc_addspiritball(dstsd, skill_get_time(MO_CALLSPIRITS, pc_checkskill(sd,MO_CALLSPIRITS)), i); - pc_delspiritball(sd, sd->spiritball, 0); - } - } - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - break; - - case SR_GENTLETOUCH_CURE: { - int heal; - - if (status_isimmune(bl)) { - clif_skill_nodamage(src,bl,skillid,skilllv,0); - break; - } - - heal = 120 * skilllv + status_get_max_hp(bl) * (2 + skilllv) / 100; - status_heal(bl, heal, 0, 0); - - if ((tsc && tsc->opt1) && (rnd()%100 < ((skilllv * 5) + (status_get_dex(src) + status_get_lv(src)) / 4) - (1 + (rnd() % 10)))) { - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); - status_change_end(bl, SC_POISON, INVALID_TIMER); - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - status_change_end(bl, SC_HALLUCINATION, INVALID_TIMER); - status_change_end(bl, SC_BURNING, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); - } - - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - case SR_GENTLETOUCH_CHANGE: - case SR_GENTLETOUCH_REVITALIZE: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start2(bl,type,100,skilllv,src->id,skill_get_time(skillid,skilllv))); - break; - case WA_SWING_DANCE: - case WA_MOONLIT_SERENADE: - if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - else if (sd) { // Only shows effects on caster. - clif_skill_nodamage(src,bl,skillid,skilllv,1); - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - } - break; - - case WA_SYMPHONY_OF_LOVER: - case MI_RUSH_WINDMILL: - case MI_ECHOSONG: - if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) - sc_start4(bl,type,100,skilllv,6*skilllv,(sd?pc_checkskill(sd,WM_LESSON):0),(sd?sd->status.job_level:0),skill_get_time(skillid,skilllv)); - else if (sd) { // Only shows effects on caster. - clif_skill_nodamage(src,bl,skillid,skilllv,1); - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - } - break; - - case MI_HARMONIZE: - if (src != bl) - clif_skill_nodamage(src, src, skillid, skilllv, sc_start(src, type, 100, skilllv, skill_get_time(skillid,skilllv))); - clif_skill_nodamage(src, bl, skillid, skilllv, sc_start(bl, type, 100, skilllv, skill_get_time(skillid,skilllv))); - break; - - case WM_DEADHILLHERE: - if (bl->type == BL_PC) { - if (!status_isdead(bl)) - break; - - if (rnd()%100 < 88 + 2 * skilllv) { - int heal = tstatus->sp; - if (heal <= 0) - heal = 1; - tstatus->hp = heal; - tstatus->sp -= tstatus->sp * (120 - 20 * skilllv) / 100; - clif_skill_nodamage(src,bl,skillid,skilllv,1); - pc_revive((TBL_PC *)bl,heal,0); - clif_resurrection(bl,1); - } - } - break; - - case WM_SIRCLEOFNATURE: - flag |= BCT_SELF|BCT_PARTY|BCT_GUILD; - case WM_VOICEOFSIREN: - if (skillid != WM_SIRCLEOFNATURE) - flag &= ~BCT_SELF; - if (flag&1) { - sc_start2(bl,type,(skillid==WM_VOICEOFSIREN)?20+10*skilllv:100,skilllv,(skillid==WM_VOICEOFSIREN)?src->id:0,skill_get_time(skillid,skilllv)); - } else { - map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),(skillid==WM_VOICEOFSIREN)?BL_CHAR|BL_SKILL:BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case WM_GLOOMYDAY: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - if (dstsd && (pc_checkskill(dstsd,KN_BRANDISHSPEAR) || pc_checkskill(dstsd,LK_SPIRALPIERCE) || - pc_checkskill(dstsd,CR_SHIELDCHARGE) || pc_checkskill(dstsd,CR_SHIELDBOOMERANG) || - pc_checkskill(dstsd,PA_SHIELDCHAIN) || pc_checkskill(dstsd,LG_SHIELDPRESS))) { - sc_start(bl,SC_GLOOMYDAY_SK,100,skilllv,skill_get_time(skillid,skilllv)); - break; - } - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - break; - - case WM_SATURDAY_NIGHT_FEVER: - if (flag&1) { // Affect to all targets arround the caster and caster too. - if (!(tsc && tsc->data[type])) - sc_start(bl, type, 100, skilllv,skill_get_time(skillid, skilllv)); - } else if (flag&2) { - if (src->id != bl->id && battle_check_target(src,bl,BCT_ENEMY) > 0) - status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,0,0)); - } else if (sd) { - short chance = sstatus->int_/6 + sd->status.job_level/5 + skilllv*4; - if (!sd->status.party_id || (rnd()%100 > chance)) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_NEED_HELPER,0); - break; - } - if (map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid,skilllv), - BL_PC, src, skillid, skilllv, tick, BCT_ENEMY, skill_area_sub_count) > 7) - flag |= 2; - else - flag |= 1; - map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|BCT_SELF, skill_castend_nodamage_id); - clif_skill_nodamage(src, bl, skillid, skilllv, - sc_start(src,SC_STOP,100,skilllv,skill_get_time2(skillid,skilllv))); - if (flag&2) // Dealed here to prevent conflicts - status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,0,0)); - } - break; - - case WM_SONG_OF_MANA: - case WM_DANCE_WITH_WUG: - case WM_LERADS_DEW: - if (flag&1) { // These affect to to all party members near the caster. - struct status_change *sc = status_get_sc(src); - if (sc && sc->data[type]) { - sc_start2(bl,type,100,skilllv,sc->data[type]->val2,skill_get_time(skillid,skilllv)); - } - } else if (sd) { - short lv = (short)skilllv; - int count = skill_check_pc_partner(sd,skillid,&lv,skill_get_splash(skillid,skilllv),1); - if (sc_start2(bl,type,100,skilllv,count,skill_get_time(skillid,skilllv))) - party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skillid,skilllv),src,skillid,skilllv,tick,flag|BCT_PARTY|1,skill_castend_nodamage_id); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - - } - break; - - case WM_MELODYOFSINK: - case WM_BEYOND_OF_WARCRY: - case WM_UNLIMITED_HUMMING_VOICE: - if (flag&1) { - sc_start2(bl,type,100,skilllv,skill_area_temp[0],skill_get_time(skillid,skilllv)); - } else { // These affect to all targets arround the caster. - short lv = (short)skilllv; - skill_area_temp[0] = (sd) ? skill_check_pc_partner(sd,skillid,&lv,skill_get_splash(skillid,skilllv),1) : 50; // 50% chance in non BL_PC (clones). - map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - - case WM_RANDOMIZESPELL: { - int improv_skillid = 0, improv_skilllv; - do { - i = rnd() % MAX_SKILL_IMPROVISE_DB; - improv_skillid = skill_improvise_db[i].skillid; - } while (improv_skillid == 0 || rnd()%10000 >= skill_improvise_db[i].per); - improv_skilllv = 4 + skilllv; - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - - if (sd) { - sd->state.abra_flag = 2; - sd->skillitem = improv_skillid; - sd->skillitemlv = improv_skilllv; - clif_item_skill(sd, improv_skillid, improv_skilllv); - } else { - struct unit_data *ud = unit_bl2ud(src); - int inf = skill_get_inf(improv_skillid); - int target_id = 0; - if (!ud) break; - if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { - if (src->type == BL_PET) - bl = (struct block_list *)((TBL_PET *)src)->msd; - if (!bl) bl = src; - unit_skilluse_id(src, bl->id, improv_skillid, improv_skilllv); - } else { - if (ud->target) - target_id = ud->target; - else switch (src->type) { - case BL_MOB: - target_id = ((TBL_MOB *)src)->target_id; - break; - case BL_PET: - target_id = ((TBL_PET *)src)->target_id; - break; - } - if (!target_id) - break; - if (skill_get_casttype(improv_skillid) == CAST_GROUND) { - bl = map_id2bl(target_id); - if (!bl) bl = src; - unit_skilluse_pos(src, bl->x, bl->y, improv_skillid, improv_skilllv); - } else - unit_skilluse_id(src, target_id, improv_skillid, improv_skilllv); - } - } - } - break; - + continue; + case SC_ASSUMPTIO: + if( bl->type == BL_MOB ) + continue; + break; + } + if(i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. + status_change_end(bl,(sc_type)i,INVALID_TIMER); + } + break; + } + map_foreachinrange(skill_area_sub, bl, i, BL_CHAR, src, skillid, skilllv, tick, flag|1, skill_castend_damage_id); + break; + + case AB_SILENTIUM: + // Should the level of Lex Divina be equivalent to the level of Silentium or should the highest level learned be used? [LimitLine] + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid, skilllv), BL_CHAR, + src, PR_LEXDIVINA, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + break; + /** + * Warlock + **/ + case WL_STASIS: + if( flag&1 ) + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + else + { + map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid, skilllv),BL_CHAR,src,skillid,skilllv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill_castend_nodamage_id); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + } + break; + + case WL_WHITEIMPRISON: + if( (src == bl || battle_check_target(src, bl, BCT_ENEMY)) && !is_boss(bl) )// Should not work with bosses. + { + int rate = ( sd? sd->status.job_level : 50 ) / 4; + + if(src == bl ) rate = 100; // Success Chance: On self, 100% + else if(bl->type == BL_PC) rate += 20 + 10 * skilllv; // On Players, (20 + 10 * Skill Level) % + else rate += 40 + 10 * skilllv; // On Monsters, (40 + 10 * Skill Level) % + + if( !(tsc && tsc->data[type]) ){ + i = sc_start2(bl,type,rate,skilllv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill_get_time(skillid,skilllv):skill_get_time2(skillid, skilllv)); + clif_skill_nodamage(src,bl,skillid,skilllv,i); + } - case RETURN_TO_ELDICASTES: - case ALL_GUARDIAN_RECALL: - if (sd) { - short x, y; // Destiny position. - unsigned short mapindex; - - if (skillid == RETURN_TO_ELDICASTES) { - x = 198; - y = 187; - mapindex = mapindex_name2id(MAP_DICASTES); - } else { - x = 44; - y = 151; - mapindex = mapindex_name2id(MAP_MORA); - } + if( sd && i ) + skill_blockpc_start(sd,skillid,4000); // Reuse Delay only activated on success + else if(sd) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + }else if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_TOTARGET,0); + break; + + case WL_FROSTMISTY: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinrange(skill_area_sub,bl,skill_get_splash(skillid,skilllv),BL_CHAR|BL_SKILL,src,skillid,skilllv,tick,flag|BCT_ENEMY,skill_castend_damage_id); + break; + + case WL_JACKFROST: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_foreachinshootrange(skill_area_sub,bl,skill_get_splash(skillid,skilllv),BL_CHAR|BL_SKILL,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + break; + + case WL_MARSHOFABYSS: + // Should marsh of abyss still apply half reduction to players after the 28/10 patch? [LimitLine] + clif_skill_nodamage(src, bl, skillid, skilllv, + sc_start4(bl, type, 100, skilllv, status_get_int(src), sd ? sd->status.job_level : 50, 0, + skill_get_time(skillid, skilllv))); + break; + + case WL_SIENNAEXECRATE: + if( status_isimmune(bl) || !tsc ) + break; + + if( flag&1 ) { + if( bl->id == skill_area_temp[1] ) + break; // Already work on this target + + if( tsc && tsc->data[SC_STONE] ) + status_change_end(bl,SC_STONE,INVALID_TIMER); + else + status_change_start(bl,SC_STONE,10000,skilllv,0,0,1000,skill_get_time(skillid, skilllv),2); + } else { + int rate = 40 + 8 * skilllv + ( sd? sd->status.job_level : 50 ) / 4; + // IroWiki says Rate should be reduced by target stats, but currently unknown + if( rnd()%100 < rate ) { // Success on First Target + if( !tsc->data[SC_STONE] ) + rate = status_change_start(bl,SC_STONE,10000,skilllv,0,0,1000,skill_get_time(skillid, skilllv),2); + else { + rate = 1; + status_change_end(bl,SC_STONE,INVALID_TIMER); + } - if (!mapindex) { - //Given map not found? - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; - } - pc_setpos(sd, mapindex, x, y, CLR_TELEPORT); - } - break; + if( rate ) { + skill_area_temp[1] = bl->id; + map_foreachinrange(skill_area_sub,bl,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id); + } + // Doesn't send failure packet if it fails on defense. + } + else if( sd ) // Failure on Rate + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } + break; + + case WL_SUMMONFB: + case WL_SUMMONBL: + case WL_SUMMONWB: + case WL_SUMMONSTONE: + { + short element = 0, sctype = 0, pos = -1; + struct status_change *sc = status_get_sc(src); + if( !sc ) break; + + for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) + { + if( !sctype && !sc->data[i] ) + sctype = i; // Take the free SC + if( sc->data[i] ) + pos = max(sc->data[i]->val2,pos); + } - case GM_SANDMAN: - if (tsc) { - if (tsc->opt1 == OPT1_SLEEP) - tsc->opt1 = 0; - else - tsc->opt1 = OPT1_SLEEP; - clif_changeoption(bl); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - } - break; + if( !sctype ) + { + if( sd ) // No free slots to put SC + clif_skill_fail(sd,skillid,USESKILL_FAIL_SUMMON,0); + break; + } - case SO_ARRULLO: - if (flag&1) - sc_start2(bl, type, 88 + 2 * skilllv, skilllv, 1, skill_get_time(skillid, skilllv)); - else { - clif_skill_nodamage(src, bl, skillid, 0, 1); - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), BL_CHAR, - src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - } - break; + pos++; // Used in val2 for SC. Indicates the order of this ball + switch( skillid ) + { // Set val1. The SC element for this ball + case WL_SUMMONFB: element = WLS_FIRE; break; + case WL_SUMMONBL: element = WLS_WIND; break; + case WL_SUMMONWB: element = WLS_WATER; break; + case WL_SUMMONSTONE: element = WLS_STONE; break; + } - case SO_SUMMON_AGNI: - case SO_SUMMON_AQUA: - case SO_SUMMON_VENTUS: - case SO_SUMMON_TERA: - if (sd) { - int elemental_class = skill_get_elemental_type(skillid,skilllv); - - // Remove previous elemental fisrt. - if (sd->ed && elemental_delete(sd->ed,0)) { - clif_skill_fail(sd,skillid,0,0); - break; - } - // Summoning the new one. - if (!elemental_create(sd,elemental_class,skill_get_time(skillid,skilllv))) { - clif_skill_fail(sd,skillid,0,0); - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; + sc_start4(src,sctype,100,element,pos,skilllv,0,skill_get_time(skillid,skilllv)); + clif_skill_nodamage(src,bl,skillid,0,0); + } + break; + + case WL_READING_SB: + if( sd ) { + struct status_change *sc = status_get_sc(bl); + + for( i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) + if( sc && !sc->data[i] ) + break; + if( i == SC_MAXSPELLBOOK ) { + clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); + break; + } - case SO_EL_CONTROL: - if (sd) { - int mode = EL_MODE_PASSIVE; // Standard mode. - if (!sd->ed) { - clif_skill_fail(sd,skillid,0,0); - break; - } - if (skilllv == 4) { // At level 4 delete elementals. - if (elemental_delete(sd->ed, 0)) - clif_skill_fail(sd,skillid,0,0); - break; - } - switch (skilllv) { // Select mode bassed on skill level used. - case 1: - mode = EL_MODE_PASSIVE; - break; - case 2: - mode = EL_MODE_ASSIST; - break; - case 3: - mode = EL_MODE_AGGRESSIVE; - break; - } - if (!elemental_change_mode(sd->ed,mode)) { - clif_skill_fail(sd,skillid,0,0); - break; - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; + sc_start(bl, SC_STOP, 100, skilllv, INVALID_TIMER); //Can't move while selecting a spellbook. + clif_spellbook_list(sd); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + } + break; + /** + * Ranger + **/ + case RA_FEARBREEZE: + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + clif_skill_nodamage(src, bl, skillid, skilllv, sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); + break; + + case RA_WUGMASTERY: + if( sd ) { + if( !pc_iswug(sd) ) + pc_setoption(sd,sd->sc.option|OPTION_WUG); + else + pc_setoption(sd,sd->sc.option&~OPTION_WUG); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case RA_WUGRIDER: + if( sd ) { + if( !pc_isridingwug(sd) && pc_iswug(sd) ) { + pc_setoption(sd,sd->sc.option&~OPTION_WUG); + pc_setoption(sd,sd->sc.option|OPTION_WUGRIDER); + } else if( pc_isridingwug(sd) ) { + pc_setoption(sd,sd->sc.option&~OPTION_WUGRIDER); + pc_setoption(sd,sd->sc.option|OPTION_WUG); + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case RA_WUGDASH: + if( tsce ) { + clif_skill_nodamage(src,bl,skillid,skilllv,status_change_end(bl, type, INVALID_TIMER)); + map_freeblock_unlock(); + return 0; + } + if( sd && pc_isridingwug(sd) ) { + clif_skill_nodamage(src,bl,skillid,skilllv,sc_start4(bl,type,100,skilllv,unit_getdir(bl),0,0,1)); + clif_walkok(sd); + } + break; + + case RA_SENSITIVEKEEN: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR|BL_SKILL,src,skillid,skilllv,tick,flag|BCT_ENEMY,skill_castend_damage_id); + break; + /** + * Mechanic + **/ + case NC_F_SIDESLIDE: + case NC_B_SIDESLIDE: + { + int dir = (skillid == NC_F_SIDESLIDE) ? (unit_getdir(src)+4)%8 : unit_getdir(src); + skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),dir,0x1); + clif_slide(src,src->x,src->y); + clif_fixpos(src); //Aegis sent this packet + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case NC_SELFDESTRUCTION: + if( sd ) { + if( pc_ismadogear(sd) ) + pc_setmadogear(sd, 0); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + skill_castend_damage_id(src, src, skillid, skilllv, tick, flag); + status_set_sp(src, 0, 0); + } + break; + + case NC_ANALYZE: + clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + clif_skill_nodamage(src, bl, skillid, skilllv, + sc_start(bl,type, 30 + 12 * skilllv,skilllv,skill_get_time(skillid,skilllv))); + if( sd ) pc_overheat(sd,1); + break; + + case NC_MAGNETICFIELD: + if( (i = sc_start2(bl,type,100,skilllv,src->id,skill_get_time(skillid,skilllv))) ) + { + map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),splash_target(src),src,skillid,skilllv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill_castend_damage_id);; + clif_skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skillid,skilllv,6); + if (sd) pc_overheat(sd,1); + } + clif_skill_nodamage(src,src,skillid,skilllv,i); + break; + + case NC_REPAIR: + if( sd ) + { + int heal; + if( dstsd && pc_ismadogear(dstsd) ) + { + heal = dstsd->status.max_hp * (3+3*skilllv) / 100; + status_heal(bl,heal,0,2); + } else { + heal = sd->status.max_hp * (3+3*skilllv) / 100; + status_heal(src,heal,0,2); + } - case SO_EL_ACTION: - if (sd) { - int duration = 3000; - if (!sd->ed) - break; - elemental_action(sd->ed, bl, tick); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - switch(sd->ed->db->class_){ - case 2115:case 2124: - case 2118:case 2121: - duration = 6000; - break; - case 2116:case 2119: - case 2122:case 2125: - duration = 9000; + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + clif_skill_nodamage(src, bl, skillid, skilllv, heal); + } + break; + + case NC_DISJOINT: + { + if( bl->type != BL_MOB ) break; + md = map_id2md(bl->id); + if( md && md->class_ >= MOBID_SILVERSNIPER && md->class_ <= MOBID_MAGICDECOY_WIND ) + status_kill(bl); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + } + break; + case SC_AUTOSHADOWSPELL: + if( sd ) { + if( sd->status.skill[sd->reproduceskill_id].id || sd->status.skill[sd->cloneskill_id].id ) { + sc_start(src,SC_STOP,100,skilllv,-1);// The skilllv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] + clif_autoshadowspell_list(sd); + clif_skill_nodamage(src,bl,skillid,1,1); + } + else + clif_skill_fail(sd,skillid,USESKILL_FAIL_IMITATION_SKILL_NONE,0); + } + break; + + case SC_SHADOWFORM: + if( sd && dstsd && src != bl && !dstsd->shadowform_id ) { + if( clif_skill_nodamage(src,bl,skillid,skilllv,sc_start4(src,type,100,skilllv,bl->id,4+skilllv,0,skill_get_time(skillid, skilllv))) ) + dstsd->shadowform_id = src->id; + } + else if( sd ) + clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); + break; + + case SC_BODYPAINT: + if( flag&1 ) { + if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || + tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || + tsc->data[SC__INVISIBILITY]) ) { + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CHASEWALK, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); + + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + sc_start(bl,SC_BLIND,53 + 2 * skilllv,skilllv,skill_get_time(skillid,skilllv)); + } + } else { + clif_skill_nodamage(src, bl, skillid, 0, 1); + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + } + break; + + case SC_ENERVATION: + case SC_GROOMY: + case SC_LAZINESS: + case SC_UNLUCKY: + case SC_WEAKNESS: + if( !(tsc && tsc->data[type]) ) { + //((rand(myDEX / 12, myDEX / 4) + myJobLevel + 10 * skLevel) + myLevel / 10) - (targetLevel / 10 + targetLUK / 10 + (targetMaxWeight - targetWeight) / 1000 + rand(targetAGI / 6, targetAGI / 3)) + int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skilllv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 + - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); + rate = cap_value(rate, skilllv+sstatus->dex/20, 100); + clif_skill_nodamage(src,bl,skillid,0,sc_start(bl,type,rate,skilllv,skill_get_time(skillid,skilllv))); + } else if( sd ) + clif_skill_fail(sd,skillid,0,0); + break; + + case SC_IGNORANCE: + if( !(tsc && tsc->data[type]) ) { + int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skilllv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 + - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); + rate = cap_value(rate, skilllv+sstatus->dex/20, 100); + if (clif_skill_nodamage(src,bl,skillid,0,sc_start(bl,type,rate,skilllv,skill_get_time(skillid,skilllv)))) { + int sp = 200 * skilllv; + if( dstmd ) sp = dstmd->level * 2; + if( status_zap(bl,0,sp) ) + status_heal(src,0,sp/2,3); + } + else if( sd ) clif_skill_fail(sd,skillid,0,0); + } else if( sd ) + clif_skill_fail(sd,skillid,0,0); + break; + + case LG_TRAMPLE: + clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + map_foreachinrange(skill_destroy_trap,bl,skill_get_splash(skillid,skilllv),BL_SKILL,tick); + break; + + case LG_REFLECTDAMAGE: + if( tsc && tsc->data[type] ) + status_change_end(bl,type,INVALID_TIMER); + else + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + break; + + case LG_SHIELDSPELL: + if( flag&1 ) { + int duration = (sd) ? sd->bonus.shieldmdef * 2000 : 10000; + sc_start(bl,SC_SILENCE,100,skilllv,duration); + } else if( sd ) { + int opt = skilllv; + int rate = rnd()%100; + int val, brate; + switch( skilllv ) { + case 1: + { + struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; + if( !shield_data || shield_data->type != IT_ARMOR ) { // No shield? + clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); + break; + } + brate = shield_data->def * 10; + if( rate < 50 ) + opt = 1; + else if( rate < 75 ) + opt = 2; + else + opt = 3; + + switch( opt ) { + case 1: + sc_start(bl,SC_SHIELDSPELL_DEF,100,opt,-1); + clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + if( rate < brate ) + map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER); + break; + case 2: + val = shield_data->def / 10; // % Reflected damage. + sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 1000); + break; + case 3: + val = shield_data->def; // Attack increase. + sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 3000); + break; + } + } + break; + + case 2: + brate = sd->bonus.shieldmdef * 20; + if( rate < 30 ) + opt = 1; + else if( rate < 60 ) + opt = 2; + else + opt = 3; + switch( opt ) { + case 1: + sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); + clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + if( rate < brate ) + map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|2,skill_castend_damage_id); + status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER); + break; + case 2: + sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); + clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + if( rate < brate ) + map_foreachinrange(skill_area_sub,src,skill_get_splash(skillid,skilllv),BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id); + break; + case 3: + if( sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->bonus.shieldmdef * 30000) ) + clif_skill_nodamage(src,bl,PR_MAGNIFICAT,skilllv, + sc_start(bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000)); + break; + } + break; + + case 3: + { + struct item *it = &sd->status.inventory[sd->equip_index[EQI_HAND_L]]; + if( !it ) { // No shield? + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); break; + } + brate = it->refine * 5; + if( rate < 25 ) + opt = 1; + else if( rate < 50 ) + opt = 2; + else + opt = 3; + switch( opt ) { + case 1: + val = 105 * it->refine / 10; + sc_start2(bl,SC_SHIELDSPELL_REF,brate,opt,val,skill_get_time(skillid,skilllv)); + break; + case 2: case 3: + if( rate < brate ) + { + val = sstatus->max_hp * (11 + it->refine) / 100; + status_heal(bl, val, 0, 3); + } + break; + /*case 3: + // Full protection. I need confirm what effect should be here. Moved to case 2 to until we got it. + break;*/ + } } - skill_blockpc_start(sd, skillid, duration); - } - break; - - case SO_EL_CURE: - if (sd) { - struct elemental_data *ed = sd->ed; - int s_hp = sd->battle_status.hp * 10 / 100, s_sp = sd->battle_status.sp * 10 / 100; - int e_hp, e_sp; - if (!ed) { - clif_skill_fail(sd,skillid,0,0); - break; - } - if (!status_charge(&sd->bl,s_hp,s_sp)) { - clif_skill_fail(sd,skillid,0,0); - break; - } - e_hp = ed->battle_status.max_hp * 10 / 100; - e_sp = ed->battle_status.max_sp * 10 / 100; - status_heal(&ed->bl,e_hp,e_sp,3); - clif_skill_nodamage(src,&ed->bl,skillid,skilllv,1); - } - break; - - case GN_CHANGEMATERIAL: - case SO_EL_ANALYSIS: - if (sd) { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - clif_skill_itemlistwindow(sd,skillid,skilllv); - } - break; - - case GN_BLOOD_SUCKER: { - struct status_change *sc = status_get_sc(src); - - if (sc && sc->bs_counter < skill_get_maxcount(skillid , skilllv)) { - if (tsc && tsc->data[type]) { - (sc->bs_counter)--; - status_change_end(src, type, INVALID_TIMER); // the first one cancels and the last one will take effect resetting the timer - } - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - sc_start2(bl, type, 100, skilllv, src->id, skill_get_time(skillid,skilllv)); - (sc->bs_counter)++; - } else if (sd) { - clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); - break; - } - } - break; - - case GN_MANDRAGORA: - if (flag&1) { - if (clif_skill_nodamage(bl, src, skillid, skilllv, - sc_start(bl, type, 25 + 10 * skilllv, skilllv, skill_get_time(skillid, skilllv)))) - status_zap(bl, 0, status_get_max_sp(bl) * (25 + 5 * skilllv) / 100); - } else - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), BL_CHAR, - src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - break; - - case GN_SLINGITEM: - if (sd) { - short ammo_id; - i = sd->equip_index[EQI_AMMO]; - if (i <= 0) - break; // No ammo. - ammo_id = sd->inventory_data[i]->nameid; - if (ammo_id <= 0) - break; - sd->itemid = ammo_id; - if (itemdb_is_GNbomb(ammo_id)) { - if (battle_check_target(src,bl,BCT_ENEMY) > 0) { // Only attack if the target is an enemy. - if (ammo_id == 13263) - map_foreachincell(skill_area_sub,bl->m,bl->x,bl->y,BL_CHAR,src,GN_SLINGITEM_RANGEMELEEATK,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - else - skill_attack(BF_WEAPON,src,src,bl,GN_SLINGITEM_RANGEMELEEATK,skilllv,tick,flag); - } else //Otherwise, it fails, shows animation and removes items. - clif_skill_fail(sd,GN_SLINGITEM_RANGEMELEEATK,0xa,0); - } else if (itemdb_is_GNthrowable(ammo_id)) { - struct script_code *script = sd->inventory_data[i]->script; - if (!script) - break; - if (dstsd) - run_script(script,0,dstsd->bl.id,fake_nd->bl.id); - else - run_script(script,0,src->id,0); - } - } - clif_skill_nodamage(src,bl,skillid,skilllv,1); - clif_skill_nodamage(src,bl,skillid,skilllv,1);// This packet is received twice actually, I think it is to show the animation. - break; - - case GN_MIX_COOKING: - case GN_MAKEBOMB: - case GN_S_PHARMACY: - if (sd) { - int qty = 1; - sd->skillid_old = skillid; - sd->skilllv_old = skilllv; - if (skillid != GN_S_PHARMACY && skilllv > 1) - qty = 10; - clif_cooking_list(sd,(skillid - GN_MIX_COOKING) + 27,skillid,qty,skillid==GN_MAKEBOMB?5:6); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - } - break; - case EL_CIRCLE_OF_FIRE: - case EL_PYROTECHNIC: - case EL_HEATER: - case EL_TROPIC: - case EL_AQUAPLAY: - case EL_COOLER: - case EL_CHILLY_AIR: - case EL_GUST: - case EL_BLAST: - case EL_WILD_STORM: - case EL_PETROLOGY: - case EL_CURSED_SOIL: - case EL_UPHEAVAL: - case EL_FIRE_CLOAK: - case EL_WATER_DROP: - case EL_WIND_CURTAIN: - case EL_SOLID_SKIN: - case EL_STONE_SHIELD: - case EL_WIND_STEP: { - struct elemental_data *ele = BL_CAST(BL_ELEM, src); - if (ele) { - sc_type type2 = type-1; - struct status_change *sc = status_get_sc(&ele->bl); - - if ((sc && sc->data[type2]) || (tsc && tsc->data[type])) { - elemental_clean_single_effect(ele, skillid); - } else { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - if (skillid == EL_WIND_STEP) // There aren't telemport, just push to the master. - skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),(map_calc_dir(src,bl->x,bl->y)+4)%8,0); - sc_start(src,type2,100,skilllv,skill_get_time(skillid,skilllv)); - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); - } - } - } - break; - - case EL_FIRE_MANTLE: - case EL_WATER_BARRIER: - case EL_ZEPHYR: - case EL_POWER_OF_GAIA: - clif_skill_nodamage(src,src,skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - skill_unitsetting(src,skillid,skilllv,bl->x,bl->y,0); - break; - - case EL_WATER_SCREEN: { - struct elemental_data *ele = BL_CAST(BL_ELEM, src); - if (ele) { - struct status_change *sc = status_get_sc(&ele->bl); - sc_type type2 = type-1; - - clif_skill_nodamage(src,src,skillid,skilllv,1); - if ((sc && sc->data[type2]) || (tsc && tsc->data[type])) { - elemental_clean_single_effect(ele, skillid); - } else { - // This not heals at the end. - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - sc_start(src,type2,100,skilllv,skill_get_time(skillid,skilllv)); - sc_start(bl,type,100,src->id,skill_get_time(skillid,skilllv)); - } - } - } - break; + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case LG_PIETY: + if( flag&1 ) + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + else { + skill_area_temp[2] = 0; + map_foreachinrange(skill_area_sub,bl,skill_get_splash(skillid,skilllv),BL_PC,src,skillid,skilllv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill_castend_nodamage_id); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case LG_INSPIRATION: + if( sd && !map[sd->bl.m].flag.noexppenalty && sd->status.base_level != MAX_LEVEL ) { + sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * 1 / 100); // 1% penalty. + sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * 1 / 100); + clif_updatestatus(sd,SP_BASEEXP); + clif_updatestatus(sd,SP_JOBEXP); + } + clif_skill_nodamage(bl,src,skillid,skilllv, + sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv))); + break; + case SR_CURSEDCIRCLE: + if( flag&1 ) { + if( is_boss(bl) ) break; + if( sc_start2(bl, type, 100, skilllv, src->id, skill_get_time(skillid, skilllv))) { + if( bl->type == BL_MOB ) + mob_unlocktarget((TBL_MOB*)bl,gettick()); + unit_stop_attack(bl); + clif_bladestop(src, bl->id, 1); + map_freeblock_unlock(); + return 1; + } + } else { + int count = 0; + clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + count = map_forcountinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-charactors + BL_CHAR, src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + if( sd ) pc_delspiritball(sd, count, 0); + clif_skill_nodamage(src, src, skillid, skilllv, + sc_start2(src, SC_CURSEDCIRCLE_ATKER, 100, skilllv, count, skill_get_time(skillid,skilllv))); + } + break; + + case SR_RAISINGDRAGON: + if( sd ) { + short max = 5 + skilllv; + sc_start(bl, SC_EXPLOSIONSPIRITS, 100, skilllv, skill_get_time(skillid, skilllv)); + for( i = 0; i < max; i++ ) // Don't call more than max available spheres. + pc_addspiritball(sd, skill_get_time(skillid, skilllv), max); + clif_skill_nodamage(src, bl, skillid, skilllv, sc_start(bl, type, 100, skilllv,skill_get_time(skillid, skilllv))); + } + break; + + case SR_ASSIMILATEPOWER: + if( flag&1 ) { + i = 0; + if( dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER ) + { + i = dstsd->spiritball; //1%sp per spiritball. + pc_delspiritball(dstsd, dstsd->spiritball, 0); + } + if( i ) status_percent_heal(src, 0, i); + clif_skill_nodamage(src, bl, skillid, skilllv, i ? 1:0); + } else { + clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill_castend_nodamage_id); + } + break; + + case SR_POWERVELOCITY: + if( !dstsd ) + break; + if( sd && dstsd->spiritball <= 5 ) { + for(i = 0; i <= 5; i++) { + pc_addspiritball(dstsd, skill_get_time(MO_CALLSPIRITS, pc_checkskill(sd,MO_CALLSPIRITS)), i); + pc_delspiritball(sd, sd->spiritball, 0); + } + } + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + break; - case KO_KAHU_ENTEN: - case KO_HYOUHU_HUBUKI: - case KO_KAZEHU_SEIRAN: - case KO_DOHU_KOUKAI: - if (sd) { - int ttype = skill_get_ele(skillid, skilllv); - clif_skill_nodamage(src, bl, skillid, skilllv, 1); - pc_add_talisman(sd, skill_get_time(skillid, skilllv), 10, ttype); - } - break; + case SR_GENTLETOUCH_CURE: + { + int heal; - case KO_ZANZOU: - if (sd) { - struct mob_data *md; - - md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), 2308, "", SZ_SMALL, AI_NONE); - if (md) { - md->master_id = src->id; - md->special_state.ai = AI_ZANZOU; - if (md->deletetimer != INVALID_TIMER) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer(gettick() + skill_get_time(skillid, skilllv), mob_timer_delete, md->bl.id, 0); - mob_spawn(md); - pc_setinvincibletimer(sd,500);// unlock target lock - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),unit_getdir(bl),0); - } - } - break; + if( status_isimmune(bl) ) + { + clif_skill_nodamage(src,bl,skillid,skilllv,0); + break; + } - case KO_KYOUGAKU: - if (dstsd && tsc && !tsc->data[type] && rand()%100 < tstatus->int_/2) { - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - } else if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; + heal = 120 * skilllv + status_get_max_hp(bl) * (2 + skilllv) / 100; + status_heal(bl, heal, 0, 0); - case KO_JYUSATSU: - if (dstsd && tsc && !tsc->data[type] && - rand()%100 < ((45+5*skilllv) + skilllv*5 - status_get_int(bl)/2)) {//[(Base chance of success) + (Skill Level x 5) - (int / 2)]%. - clif_skill_nodamage(src,bl,skillid,skilllv, - status_change_start(bl,type,10000,skilllv,0,0,0,skill_get_time(skillid,skilllv),1)); - status_zap(bl, tstatus->max_hp*skilllv*5/100 , 0); - if (status_get_lv(bl) <= status_get_lv(src)) - status_change_start(bl,SC_COMA,10,skilllv,0,src->id,0,0,0); - } else if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; + if( (tsc && tsc->opt1) && (rnd()%100 < ((skilllv * 5) + (status_get_dex(src) + status_get_lv(src)) / 4) - (1 + (rnd() % 10))) ) + { + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + status_change_end(bl, SC_POISON, INVALID_TIMER); + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + status_change_end(bl, SC_HALLUCINATION, INVALID_TIMER); + status_change_end(bl, SC_BURNING, INVALID_TIMER); + status_change_end(bl, SC_FREEZING, INVALID_TIMER); + } - case KO_GENWAKU: - if (!map_flag_gvg(src->m) && (dstsd || dstmd) && battle_check_target(src,bl,BCT_ENEMY) > 0) { - int x = src->x, y = src->y; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + case SR_GENTLETOUCH_CHANGE: + case SR_GENTLETOUCH_REVITALIZE: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start2(bl,type,100,skilllv,src->id,skill_get_time(skillid,skilllv))); + break; + case WA_SWING_DANCE: + case WA_MOONLIT_SERENADE: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + else if( sd ) { // Only shows effects on caster. + clif_skill_nodamage(src,bl,skillid,skilllv,1); + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + } + break; + + case WA_SYMPHONY_OF_LOVER: + case MI_RUSH_WINDMILL: + case MI_ECHOSONG: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + sc_start4(bl,type,100,skilllv,6*skilllv,(sd?pc_checkskill(sd,WM_LESSON):0),(sd?sd->status.job_level:0),skill_get_time(skillid,skilllv)); + else if( sd ) { // Only shows effects on caster. + clif_skill_nodamage(src,bl,skillid,skilllv,1); + party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); + } + break; + + case MI_HARMONIZE: + if( src != bl ) + clif_skill_nodamage(src, src, skillid, skilllv, sc_start(src, type, 100, skilllv, skill_get_time(skillid,skilllv))); + clif_skill_nodamage(src, bl, skillid, skilllv, sc_start(bl, type, 100, skilllv, skill_get_time(skillid,skilllv))); + break; + + case WM_DEADHILLHERE: + if( bl->type == BL_PC ) { + if( !status_isdead(bl) ) + break; + + if( rnd()%100 < 88 + 2 * skilllv ) { + int heal = tstatus->sp; + if( heal <= 0 ) + heal = 1; + tstatus->hp = heal; + tstatus->sp -= tstatus->sp * ( 120 - 20 * skilllv ) / 100; + clif_skill_nodamage(src,bl,skillid,skilllv,1); + pc_revive((TBL_PC*)bl,heal,0); + clif_resurrection(bl,1); + } + } + break; + + case WM_SIRCLEOFNATURE: + flag |= BCT_SELF|BCT_PARTY|BCT_GUILD; + case WM_VOICEOFSIREN: + if( skillid != WM_SIRCLEOFNATURE ) + flag &= ~BCT_SELF; + if( flag&1 ) { + sc_start2(bl,type,(skillid==WM_VOICEOFSIREN)?20+10*skilllv:100,skilllv,(skillid==WM_VOICEOFSIREN)?src->id:0,skill_get_time(skillid,skilllv)); + } else { + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),(skillid==WM_VOICEOFSIREN)?BL_CHAR|BL_SKILL:BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case WM_GLOOMYDAY: + clif_skill_nodamage(src,bl,skillid,skilllv,1); + if( dstsd && ( pc_checkskill(dstsd,KN_BRANDISHSPEAR) || pc_checkskill(dstsd,LK_SPIRALPIERCE) || + pc_checkskill(dstsd,CR_SHIELDCHARGE) || pc_checkskill(dstsd,CR_SHIELDBOOMERANG) || + pc_checkskill(dstsd,PA_SHIELDCHAIN) || pc_checkskill(dstsd,LG_SHIELDPRESS) ) ) + { + sc_start(bl,SC_GLOOMYDAY_SK,100,skilllv,skill_get_time(skillid,skilllv)); + break; + } + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + break; + + case WM_SATURDAY_NIGHT_FEVER: + if( flag&1 ) { // Affect to all targets arround the caster and caster too. + if( !(tsc && tsc->data[type]) ) + sc_start(bl, type, 100, skilllv,skill_get_time(skillid, skilllv)); + } else if( flag&2 ) { + if( src->id != bl->id && battle_check_target(src,bl,BCT_ENEMY) > 0 ) + status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,0,0)); + } else if( sd ) { + short chance = sstatus->int_/6 + sd->status.job_level/5 + skilllv*4; + if( !sd->status.party_id || (rnd()%100 > chance)) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_NEED_HELPER,0); + break; + } + if( map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid,skilllv), + BL_PC, src, skillid, skilllv, tick, BCT_ENEMY, skill_area_sub_count) > 7 ) + flag |= 2; + else + flag |= 1; + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|BCT_SELF, skill_castend_nodamage_id); + clif_skill_nodamage(src, bl, skillid, skilllv, + sc_start(src,SC_STOP,100,skilllv,skill_get_time2(skillid,skilllv))); + if( flag&2 ) // Dealed here to prevent conflicts + status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,0,0)); + } + break; + + case WM_SONG_OF_MANA: + case WM_DANCE_WITH_WUG: + case WM_LERADS_DEW: + if( flag&1 ) { // These affect to to all party members near the caster. + struct status_change *sc = status_get_sc(src); + if( sc && sc->data[type] ) { + sc_start2(bl,type,100,skilllv,sc->data[type]->val2,skill_get_time(skillid,skilllv)); + } + } else if( sd ) { + short lv = (short)skilllv; + int count = skill_check_pc_partner(sd,skillid,&lv,skill_get_splash(skillid,skilllv),1); + if( sc_start2(bl,type,100,skilllv,count,skill_get_time(skillid,skilllv)) ) + party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skillid,skilllv),src,skillid,skilllv,tick,flag|BCT_PARTY|1,skill_castend_nodamage_id); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + + } + break; + + case WM_MELODYOFSINK: + case WM_BEYOND_OF_WARCRY: + case WM_UNLIMITED_HUMMING_VOICE: + if( flag&1 ) { + sc_start2(bl,type,100,skilllv,skill_area_temp[0],skill_get_time(skillid,skilllv)); + } else { // These affect to all targets arround the caster. + short lv = (short)skilllv; + skill_area_temp[0] = (sd) ? skill_check_pc_partner(sd,skillid,&lv,skill_get_splash(skillid,skilllv),1) : 50; // 50% chance in non BL_PC (clones). + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),BL_PC, src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case WM_RANDOMIZESPELL: { + int improv_skillid = 0, improv_skilllv; + do { + i = rnd() % MAX_SKILL_IMPROVISE_DB; + improv_skillid = skill_improvise_db[i].skillid; + } while( improv_skillid == 0 || rnd()%10000 >= skill_improvise_db[i].per ); + improv_skilllv = 4 + skilllv; + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + + if( sd ) { + sd->state.abra_flag = 2; + sd->skillitem = improv_skillid; + sd->skillitemlv = improv_skilllv; + clif_item_skill(sd, improv_skillid, improv_skilllv); + } else { + struct unit_data *ud = unit_bl2ud(src); + int inf = skill_get_inf(improv_skillid); + int target_id = 0; + if (!ud) break; + if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { + if (src->type == BL_PET) + bl = (struct block_list*)((TBL_PET*)src)->msd; + if (!bl) bl = src; + unit_skilluse_id(src, bl->id, improv_skillid, improv_skilllv); + } else { + if (ud->target) + target_id = ud->target; + else switch (src->type) { + case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; + case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; + } + if (!target_id) + break; + if (skill_get_casttype(improv_skillid) == CAST_GROUND) { + bl = map_id2bl(target_id); + if (!bl) bl = src; + unit_skilluse_pos(src, bl->x, bl->y, improv_skillid, improv_skilllv); + } else + unit_skilluse_id(src, target_id, improv_skillid, improv_skilllv); + } + } + } + break; - if (sd && rnd()%100 > ((45+5*skilllv) - status_get_int(bl)/10)) {//[(Base chance of success) - (Intelligence Objectives / 10)]%. - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - if (unit_movepos(src,bl->x,bl->y,0,0)) { - clif_skill_nodamage(src,src,skillid,skilllv,1); - clif_slide(src,bl->x,bl->y) ; - sc_start(src,SC_CONFUSION,80,skilllv,skill_get_time(skillid,skilllv)); - if (unit_movepos(bl,x,y,0,0)) { - clif_skill_damage(bl,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, -1, 6); - if (bl->type == BL_PC && pc_issit((TBL_PC *)bl)) - clif_sitting(bl); //Avoid sitting sync problem - clif_slide(bl,x,y) ; - sc_start(bl,SC_CONFUSION,80,skilllv,skill_get_time(skillid,skilllv)); - } - } - } - break; + case RETURN_TO_ELDICASTES: + case ALL_GUARDIAN_RECALL: + if( sd ) + { + short x, y; // Destiny position. + unsigned short mapindex; - case OB_AKAITSUKI: - case OB_OBOROGENSOU: - if (sd && ((skillid == OB_OBOROGENSOU && bl->type == BL_MOB) // This skill does not work on monsters. - || is_boss(bl))) { // Does not work on Boss monsters. - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - case KO_IZAYOI: - case OB_ZANGETSU: - case KG_KYOMU: - case KG_KAGEMUSYA: - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - break; + if( skillid == RETURN_TO_ELDICASTES) + { + x = 198; + y = 187; + mapindex = mapindex_name2id(MAP_DICASTES); + } + else + { + x = 44; + y = 151; + mapindex = mapindex_name2id(MAP_MORA); + } - case KG_KAGEHUMI: - if (flag&1) { - if (tsc && (tsc->option&(OPTION_CLOAK|OPTION_HIDE) || - tsc->data[SC_CAMOUFLAGE] || tsc->data[SC__SHADOWFORM] || - tsc->data[SC_MARIONETTE] || tsc->data[SC_HARMONIZE])) { - sc_start(src, type, 100, skilllv, skill_get_time(skillid, skilllv)); - sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - status_change_end(bl, SC_MARIONETTE, INVALID_TIMER); - status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - } - if (skill_area_temp[2] == 1) { - clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - sc_start(src, SC_STOP, 100, skilllv, skill_get_time(skillid, skilllv)); - } - } else { - skill_area_temp[2] = 0; - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_nodamage_id); - } - break; + if(!mapindex) + { //Given map not found? + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } + pc_setpos(sd, mapindex, x, y, CLR_TELEPORT); + } + break; + + case GM_SANDMAN: + if( tsc ) { + if( tsc->opt1 == OPT1_SLEEP ) + tsc->opt1 = 0; + else + tsc->opt1 = OPT1_SLEEP; + clif_changeoption(bl); + clif_skill_nodamage (src, bl, skillid, skilllv, 1); + } + break; + + case SO_ARRULLO: + if( flag&1 ) + sc_start2(bl, type, 88 + 2 * skilllv, skilllv, 1, skill_get_time(skillid, skilllv)); + else { + clif_skill_nodamage(src, bl, skillid, 0, 1); + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + } + break; + + case SO_SUMMON_AGNI: + case SO_SUMMON_AQUA: + case SO_SUMMON_VENTUS: + case SO_SUMMON_TERA: + if( sd ) { + int elemental_class = skill_get_elemental_type(skillid,skilllv); + + // Remove previous elemental fisrt. + if( sd->ed && elemental_delete(sd->ed,0) ) { + clif_skill_fail(sd,skillid,0,0); + break; + } + // Summoning the new one. + if( !elemental_create(sd,elemental_class,skill_get_time(skillid,skilllv)) ) { + clif_skill_fail(sd,skillid,0,0); + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case SO_EL_CONTROL: + if( sd ) { + int mode = EL_MODE_PASSIVE; // Standard mode. + if( !sd->ed ) { + clif_skill_fail(sd,skillid,0,0); + break; + } + if( skilllv == 4 ) {// At level 4 delete elementals. + if( elemental_delete(sd->ed, 0) ) + clif_skill_fail(sd,skillid,0,0); + break; + } + switch( skilllv ) {// Select mode bassed on skill level used. + case 1: mode = EL_MODE_PASSIVE; break; + case 2: mode = EL_MODE_ASSIST; break; + case 3: mode = EL_MODE_AGGRESSIVE; break; + } + if( !elemental_change_mode(sd->ed,mode) ) { + clif_skill_fail(sd,skillid,0,0); + break; + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case SO_EL_ACTION: + if( sd ) { + if( !sd->ed ) + break; + elemental_action(sd->ed, bl, tick); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + + case SO_EL_CURE: + if( sd ) { + struct elemental_data *ed = sd->ed; + int s_hp = sd->battle_status.hp * 10 / 100, s_sp = sd->battle_status.sp * 10 / 100; + int e_hp, e_sp; + if( !ed ) { + clif_skill_fail(sd,skillid,0,0); + break; + } + if( !status_charge(&sd->bl,s_hp,s_sp) ) { + clif_skill_fail(sd,skillid,0,0); + break; + } + e_hp = ed->battle_status.max_hp * 10 / 100; + e_sp = ed->battle_status.max_sp * 10 / 100; + status_heal(&ed->bl,e_hp,e_sp,3); + clif_skill_nodamage(src,&ed->bl,skillid,skilllv,1); + } + break; + + case GN_CHANGEMATERIAL: + case SO_EL_ANALYSIS: + if( sd ) { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + clif_skill_itemlistwindow(sd,skillid,skilllv); + } + break; + + case GN_BLOOD_SUCKER: + { + struct status_change *sc = status_get_sc(src); + + if( sc && sc->bs_counter < skill_get_maxcount( skillid , skilllv) ) { + if( tsc && tsc->data[type] ){ + (sc->bs_counter)--; + status_change_end(src, type, INVALID_TIMER); // the first one cancels and the last one will take effect resetting the timer + } + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + sc_start2(bl, type, 100, skilllv, src->id, skill_get_time(skillid,skilllv)); + (sc->bs_counter)++; + } else if( sd ) { + clif_skill_fail(sd, skillid, USESKILL_FAIL_LEVEL, 0); + break; + } + } + break; + + case GN_MANDRAGORA: + if( flag&1 ) { + if ( clif_skill_nodamage(bl, src, skillid, skilllv, + sc_start(bl, type, 25 + 10 * skilllv, skilllv, skill_get_time(skillid, skilllv))) ) + status_zap(bl, 0, status_get_max_sp(bl) * (25 + 5 * skilllv) / 100); + } else + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); + break; + + case GN_SLINGITEM: + if( sd ) { + short ammo_id; + i = sd->equip_index[EQI_AMMO]; + if( i <= 0 ) + break; // No ammo. + ammo_id = sd->inventory_data[i]->nameid; + if( ammo_id <= 0 ) + break; + sd->itemid = ammo_id; + if( itemdb_is_GNbomb(ammo_id) ) { + if(battle_check_target(src,bl,BCT_ENEMY) > 0) {// Only attack if the target is an enemy. + if( ammo_id == 13263 ) + map_foreachincell(skill_area_sub,bl->m,bl->x,bl->y,BL_CHAR,src,GN_SLINGITEM_RANGEMELEEATK,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + else + skill_attack(BF_WEAPON,src,src,bl,GN_SLINGITEM_RANGEMELEEATK,skilllv,tick,flag); + } else //Otherwise, it fails, shows animation and removes items. + clif_skill_fail(sd,GN_SLINGITEM_RANGEMELEEATK,0xa,0); + } else if( itemdb_is_GNthrowable(ammo_id) ){ + struct script_code *script = sd->inventory_data[i]->script; + if( !script ) + break; + if( dstsd ) + run_script(script,0,dstsd->bl.id,fake_nd->bl.id); + else + run_script(script,0,src->id,0); + } + } + clif_skill_nodamage(src,bl,skillid,skilllv,1); + clif_skill_nodamage(src,bl,skillid,skilllv,1);// This packet is received twice actually, I think it is to show the animation. + break; + + case GN_MIX_COOKING: + case GN_MAKEBOMB: + case GN_S_PHARMACY: + if( sd ) { + int qty = 1; + sd->skillid_old = skillid; + sd->skilllv_old = skilllv; + if( skillid != GN_S_PHARMACY && skilllv > 1 ) + qty = 10; + clif_cooking_list(sd,(skillid - GN_MIX_COOKING) + 27,skillid,qty,skillid==GN_MAKEBOMB?5:6); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } + break; + case EL_CIRCLE_OF_FIRE: + case EL_PYROTECHNIC: + case EL_HEATER: + case EL_TROPIC: + case EL_AQUAPLAY: + case EL_COOLER: + case EL_CHILLY_AIR: + case EL_GUST: + case EL_BLAST: + case EL_WILD_STORM: + case EL_PETROLOGY: + case EL_CURSED_SOIL: + case EL_UPHEAVAL: + case EL_FIRE_CLOAK: + case EL_WATER_DROP: + case EL_WIND_CURTAIN: + case EL_SOLID_SKIN: + case EL_STONE_SHIELD: + case EL_WIND_STEP: { + struct elemental_data *ele = BL_CAST(BL_ELEM, src); + if( ele ) { + sc_type type2 = type-1; + struct status_change *sc = status_get_sc(&ele->bl); + + if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { + elemental_clean_single_effect(ele, skillid); + } else { + clif_skill_nodamage(src,bl,skillid,skilllv,1); + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + if( skillid == EL_WIND_STEP ) // There aren't telemport, just push to the master. + skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),(map_calc_dir(src,bl->x,bl->y)+4)%8,0); + sc_start(src,type2,100,skilllv,skill_get_time(skillid,skilllv)); + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); + } + } + } + break; + + case EL_FIRE_MANTLE: + case EL_WATER_BARRIER: + case EL_ZEPHYR: + case EL_POWER_OF_GAIA: + clif_skill_nodamage(src,src,skillid,skilllv,1); + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + skill_unitsetting(src,skillid,skilllv,bl->x,bl->y,0); + break; + + case EL_WATER_SCREEN: { + struct elemental_data *ele = BL_CAST(BL_ELEM, src); + if( ele ) { + struct status_change *sc = status_get_sc(&ele->bl); + sc_type type2 = type-1; + + clif_skill_nodamage(src,src,skillid,skilllv,1); + if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { + elemental_clean_single_effect(ele, skillid); + } else { + // This not heals at the end. + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + sc_start(src,type2,100,skilllv,skill_get_time(skillid,skilllv)); + sc_start(bl,type,100,src->id,skill_get_time(skillid,skilllv)); + } + } + } + break; + + case KO_KAHU_ENTEN: + case KO_HYOUHU_HUBUKI: + case KO_KAZEHU_SEIRAN: + case KO_DOHU_KOUKAI: + if(sd) { + int ttype = skill_get_ele(skillid, skilllv); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + pc_add_talisman(sd, skill_get_time(skillid, skilllv), 10, ttype); + } + break; + + case KO_ZANZOU: + if(sd){ + struct mob_data *md; + + md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), 2308, "", SZ_SMALL, AI_NONE); + if( md ) + { + md->master_id = src->id; + md->special_state.ai = AI_ZANZOU; + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer (gettick() + skill_get_time(skillid, skilllv), mob_timer_delete, md->bl.id, 0); + mob_spawn( md ); + pc_setinvincibletimer(sd,500);// unlock target lock + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),unit_getdir(bl),0); + } + } + break; + + case KO_KYOUGAKU: + if( dstsd && tsc && !tsc->data[type] && rand()%100 < tstatus->int_/2 ){ + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + }else if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + + case KO_JYUSATSU: + if( dstsd && tsc && !tsc->data[type] && + rand()%100 < ((45+5*skilllv) + skilllv*5 - status_get_int(bl)/2) ){//[(Base chance of success) + (Skill Level x 5) - (int / 2)]%. + clif_skill_nodamage(src,bl,skillid,skilllv, + status_change_start(bl,type,10000,skilllv,0,0,0,skill_get_time(skillid,skilllv),1)); + status_zap(bl, tstatus->max_hp*skilllv*5/100 , 0); + if( status_get_lv(bl) <= status_get_lv(src) ) + status_change_start(bl,SC_COMA,10,skilllv,0,src->id,0,0,0); + }else if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + + case KO_GENWAKU: + if ( !map_flag_gvg(src->m) && ( dstsd || dstmd ) && battle_check_target(src,bl,BCT_ENEMY) > 0 ) { + int x = src->x, y = src->y; + + if( sd && rnd()%100 > ((45+5*skilllv) - status_get_int(bl)/10) ){//[(Base chance of success) - (Intelligence Objectives / 10)]%. + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } - case MH_SILENT_BREEZE: { - struct status_change *ssc = status_get_sc(src); - struct block_list *m_bl = battle_get_master(src); - const enum sc_type scs[] = { - SC_MANDRAGORA, SC_HARMONIZE, SC_DEEPSLEEP, SC_VOICEOFSIREN, SC_SLEEP, SC_CONFUSION, SC_HALLUCINATION - }; - int heal; - if (tsc) { - for (i = 0; i < ARRAYLENGTH(scs); i++) { - if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); - } - if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target + if (unit_movepos(src,bl->x,bl->y,0,0)) { + clif_skill_nodamage(src,src,skillid,skilllv,1); + clif_slide(src,bl->x,bl->y) ; + sc_start(src,SC_CONFUSION,80,skilllv,skill_get_time(skillid,skilllv)); + if (unit_movepos(bl,x,y,0,0)) + { + clif_skill_damage(bl,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, -1, 6); + if( bl->type == BL_PC && pc_issit((TBL_PC*)bl)) + clif_sitting(bl); //Avoid sitting sync problem + clif_slide(bl,x,y) ; + sc_start(bl,SC_CONFUSION,80,skilllv,skill_get_time(skillid,skilllv)); + } + } + } + break; + + case OB_AKAITSUKI: + case OB_OBOROGENSOU: + if( sd && ( (skillid == OB_OBOROGENSOU && bl->type == BL_MOB) // This skill does not work on monsters. + || is_boss(bl) ) ){ // Does not work on Boss monsters. + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + case KO_IZAYOI: + case OB_ZANGETSU: + case KG_KYOMU: + case KG_KAGEMUSYA: + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + break; + + case KG_KAGEHUMI: + if( flag&1 ){ + if(tsc && ( tsc->option&(OPTION_CLOAK|OPTION_HIDE) || + tsc->data[SC_CAMOUFLAGE] || tsc->data[SC__SHADOWFORM] || + tsc->data[SC_MARIONETTE] || tsc->data[SC_HARMONIZE])){ + sc_start(src, type, 100, skilllv, skill_get_time(skillid, skilllv)); + sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + status_change_end(bl, SC_MARIONETTE, INVALID_TIMER); + status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + } + if( skill_area_temp[2] == 1 ){ + clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + sc_start(src, SC_STOP, 100, skilllv, skill_get_time(skillid, skilllv)); + } + }else{ + skill_area_temp[2] = 0; + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_nodamage_id); + } + break; + + case MH_SILENT_BREEZE: { + struct status_change *ssc = status_get_sc(src); + struct block_list *m_bl = battle_get_master(src); + const enum sc_type scs[] = { + SC_MANDRAGORA, SC_HARMONIZE, SC_DEEPSLEEP, SC_VOICEOFSIREN, SC_SLEEP, SC_CONFUSION, SC_HALLUCINATION + }; + int heal; + if(tsc){ + for (i = 0; i < ARRAYLENGTH(scs); i++) { + if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); + } + if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target status_change_start(bl, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8); - } - heal = status_get_matk_min(src)*4; - status_heal(bl, heal, 0, 7); - - //now inflict silence on everyone - if (ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun - status_change_start(src, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8); - if (m_bl) { - struct status_change *msc = status_get_sc(m_bl); - if (msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master - status_change_start(m_bl, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8); - } - if (hd) - skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); - } - break; - case MH_OVERED_BOOST: - if (hd) { + } + heal = status_get_matk_min(src)*4; + status_heal(bl, heal, 0, 7); + + //now inflict silence on everyone + if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun + status_change_start(src, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8); + if(m_bl){ + struct status_change *msc = status_get_sc(m_bl); + if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master + status_change_start(m_bl, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8); + } + if (hd) + skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + } + break; + case MH_OVERED_BOOST: + if (hd){ struct block_list *s_bl = battle_get_master(src); - if (hd->homunculus.hunger>50) //reduce hunger + if(hd->homunculus.hunger>50) //reduce hunger hd->homunculus.hunger = hd->homunculus.hunger/2; else hd->homunculus.hunger = min(1,hd->homunculus.hunger); - if (s_bl && s_bl->type==BL_PC) { + if(s_bl && s_bl->type==BL_PC){ status_set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp clif_send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info sc_start(s_bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); //gene bonus } sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); - skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); } break; - case MH_GRANITIC_ARMOR: - case MH_PYROCLASTIC: { + case MH_GRANITIC_ARMOR: + case MH_PYROCLASTIC: { struct block_list *s_bl = battle_get_master(src); - if (s_bl) sc_start2(s_bl, type, 100, skilllv, hd->homunculus.level, skill_get_time(skillid, skilllv)); //start on master + if(s_bl) sc_start2(s_bl, type, 100, skilllv, hd->homunculus.level, skill_get_time(skillid, skilllv)); //start on master sc_start2(bl, type, 100, skilllv, hd->homunculus.level, skill_get_time(skillid, skilllv)); - if (hd) skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + if (hd) skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); } break; case MH_LIGHT_OF_REGENE: - if (hd) { - hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750) - if (sd) clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info - } - //don't break need to start status and start block timer - case MH_STYLE_CHANGE: + if(hd){ + hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750) + if(sd) clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info + } + //don't break need to start status and start block timer + case MH_STYLE_CHANGE: case MH_MAGMA_FLOW: case MH_PAIN_KILLER: - sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); - if (hd) + sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); + if (hd) skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); - break; - case MH_SUMMON_LEGION: { + break; + case MH_SUMMON_LEGION: + { int summons[5] = {1004, 1303, 1303, 1994, 1994}; int qty[5] = {3 , 3 , 4 , 4 , 5}; struct mob_data *md; int i; - for (i=0; i<qty[skilllv - 1]; i++) { //easy way + for(i=0; i<qty[skilllv - 1]; i++){ //easy way md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skilllv - 1], "", SZ_SMALL, AI_ATTACK); if (md) { md->master_id = src->id; @@ -9131,43 +8952,43 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, int sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_ASSIST, 0, 60000); } } - if (hd) - skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + if (hd) + skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); } break; - default: - ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid); - clif_skill_nodamage(src,bl,skillid,skilllv,1); - map_freeblock_unlock(); - return 1; - } - - if (skillid != SR_CURSEDCIRCLE) { - struct status_change *sc = status_get_sc(src); - if (sc && sc->data[SC_CURSEDCIRCLE_ATKER]) //Should only remove after the skill had been casted. - status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); - } - - if (dstmd) { //Mob skill event for no damage skills (damage ones are handled in battle_calc_damage) [Skotlex] - mob_log_damage(dstmd, src, 0); //Log interaction (counts as 'attacker' for the exp bonus) - mobskill_event(dstmd, src, tick, MSC_SKILLUSED|(skillid<<16)); - } - - if (sd && !(flag&1)) { - // ensure that the skill last-cast tick is recorded - sd->canskill_tick = gettick(); - - if (sd->state.arrow_atk) { - // consume arrow on last invocation to this skill. - battle_consume_ammo(sd, skillid, skilllv); - } - skill_onskillusage(sd, bl, skillid, tick); - // perform skill requirement consumption - skill_consume_requirement(sd,skillid,skilllv,2); - } - - map_freeblock_unlock(); - return 0; + default: + ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid); + clif_skill_nodamage(src,bl,skillid,skilllv,1); + map_freeblock_unlock(); + return 1; + } + + if(skillid != SR_CURSEDCIRCLE){ + struct status_change *sc = status_get_sc(src); + if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] )//Should only remove after the skill had been casted. + status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); + } + + if (dstmd) { //Mob skill event for no damage skills (damage ones are handled in battle_calc_damage) [Skotlex] + mob_log_damage(dstmd, src, 0); //Log interaction (counts as 'attacker' for the exp bonus) + mobskill_event(dstmd, src, tick, MSC_SKILLUSED|(skillid<<16)); + } + + if( sd && !(flag&1) ) + {// ensure that the skill last-cast tick is recorded + sd->canskill_tick = gettick(); + + if( sd->state.arrow_atk ) + {// consume arrow on last invocation to this skill. + battle_consume_ammo(sd, skillid, skilllv); + } + skill_onskillusage(sd, bl, skillid, tick); + // perform skill requirement consumption + skill_consume_requirement(sd,skillid,skilllv,2); + } + + map_freeblock_unlock(); + return 0; } /*========================================== @@ -9175,309 +8996,322 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, int *------------------------------------------*/ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *target, *src; - struct map_session_data *sd; - struct mob_data *md; - struct unit_data *ud; - struct status_change *sc = NULL; - int inf,inf2,flag = 0; - - src = map_id2bl(id); - if (src == NULL) { - ShowDebug("skill_castend_id: src == NULL (tid=%d, id=%d)\n", tid, id); - return 0;// not found - } - - ud = unit_bl2ud(src); - if (ud == NULL) { - ShowDebug("skill_castend_id: ud == NULL (tid=%d, id=%d)\n", tid, id); - return 0;// ??? - } - - sd = BL_CAST(BL_PC, src); - md = BL_CAST(BL_MOB, src); - - if (src->prev == NULL) { - ud->skilltimer = INVALID_TIMER; - return 0; - } - - if (ud->skillid != SA_CASTCANCEL && ud->skillid != SO_SPELLFIST) { // otherwise handled in unit_skillcastcancel() - if (ud->skilltimer != tid) { - ShowError("skill_castend_id: Timer mismatch %d!=%d!\n", ud->skilltimer, tid); - ud->skilltimer = INVALID_TIMER; - return 0; - } - - if (sd && ud->skilltimer != INVALID_TIMER && (pc_checkskill(sd,SA_FREECAST) > 0 || ud->skillid == LG_EXEEDBREAK)) { - // restore original walk speed - ud->skilltimer = INVALID_TIMER; - status_calc_bl(&sd->bl, SCB_SPEED); - } - - ud->skilltimer = INVALID_TIMER; - } - - if (ud->skilltarget == id) - target = src; - else - target = map_id2bl(ud->skilltarget); - - // Use a do so that you can break out of it when the skill fails. - do { - if (!target || target->prev==NULL) break; - - if (src->m != target->m || status_isdead(src)) break; - - switch (ud->skillid) { - //These should become skill_castend_pos - case WE_CALLPARTNER: - if (sd) clif_callpartner(sd); - case WE_CALLPARENT: - case WE_CALLBABY: - case AM_RESURRECTHOMUN: - case PF_SPIDERWEB: - //Find a random spot to place the skill. [Skotlex] - inf2 = skill_get_splash(ud->skillid, ud->skilllv); - ud->skillx = target->x + inf2; - ud->skilly = target->y + inf2; - if (inf2 && !map_random_dir(target, &ud->skillx, &ud->skilly)) { - ud->skillx = target->x; - ud->skilly = target->y; - } - ud->skilltimer=tid; - return skill_castend_pos(tid,tick,id,data); - case GN_WALLOFTHORN: - ud->skillx = target->x; - ud->skilly = target->y; - ud->skilltimer = tid; - return skill_castend_pos(tid,tick,id,data); - } - - if (ud->skillid == RG_BACKSTAP) { - int dir = map_calc_dir(src,target->x,target->y),t_dir = unit_getdir(target); - if (check_distance_bl(src, target, 0) || map_check_dir(dir,t_dir)) { - break; - } - } - - if (ud->skillid == PR_TURNUNDEAD) { - struct status_data *tstatus = status_get_status_data(target); - if (!battle_check_undead(tstatus->race, tstatus->def_ele)) - break; - } - - if (ud->skillid == RA_WUGSTRIKE) { - if (!path_search(NULL,src->m,src->x,src->y,target->x,target->y,1,CELL_CHKNOREACH)) - break; - } - - if (ud->skillid == PR_LEXDIVINA || ud->skillid == MER_LEXDIVINA) { - sc = status_get_sc(target); - if (battle_check_target(src,target, BCT_ENEMY) <= 0 && (!sc || !sc->data[SC_SILENCE])) { - //If it's not an enemy, and not silenced, you can't use the skill on them. [Skotlex] - clif_skill_nodamage(src, target, ud->skillid, ud->skilllv, 0); - break; - } - } else { - // Check target validity. - inf = skill_get_inf(ud->skillid); - inf2 = skill_get_inf2(ud->skillid); - - if (inf&INF_ATTACK_SKILL || - (inf&INF_SELF_SKILL && inf2&INF2_NO_TARGET_SELF) //Combo skills - ) // Casted through combo. - inf = BCT_ENEMY; //Offensive skill. - else if (inf2&INF2_NO_ENEMY) - inf = BCT_NOENEMY; - else - inf = 0; - - if (inf2 & (INF2_PARTY_ONLY|INF2_GUILD_ONLY) && src != target) { - inf |= - (inf2&INF2_PARTY_ONLY?BCT_PARTY:0)| - (inf2&INF2_GUILD_ONLY?BCT_GUILD:0); - //Remove neutral targets (but allow enemy if skill is designed to be so) - inf &= ~BCT_NEUTRAL; - } + struct block_list *target, *src; + struct map_session_data *sd; + struct mob_data *md; + struct unit_data *ud; + struct status_change *sc = NULL; + int inf,inf2,flag = 0; + + src = map_id2bl(id); + if( src == NULL ) + { + ShowDebug("skill_castend_id: src == NULL (tid=%d, id=%d)\n", tid, id); + return 0;// not found + } - if (ud->skillid >= SL_SKE && ud->skillid <= SL_SKA && target->type == BL_MOB) { - if (((TBL_MOB *)target)->class_ == MOBID_EMPERIUM) - break; - } else if (inf && battle_check_target(src, target, inf) <= 0) { - if (sd) clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); - break; - } + ud = unit_bl2ud(src); + if( ud == NULL ) + { + ShowDebug("skill_castend_id: ud == NULL (tid=%d, id=%d)\n", tid, id); + return 0;// ??? + } - if (inf&BCT_ENEMY && (sc = status_get_sc(target)) && - sc->data[SC_FOGWALL] && - rnd() % 100 < 75) { //Fogwall makes all offensive-type targetted skills fail at 75% - if (sd) clif_skill_fail(sd, ud->skillid, USESKILL_FAIL_LEVEL, 0); - break; - } - } + sd = BL_CAST(BL_PC, src); + md = BL_CAST(BL_MOB, src); - //Avoid doing double checks for instant-cast skills. - if (tid != INVALID_TIMER && !status_check_skilluse(src, target, ud->skillid, 1)) - break; + if( src->prev == NULL ) { + ud->skilltimer = INVALID_TIMER; + return 0; + } - if (md) { - md->last_thinktime=tick +MIN_MOBTHINKTIME; - if (md->skillidx >= 0 && md->db->skill[md->skillidx].emotion >= 0) - clif_emotion(src, md->db->skill[md->skillidx].emotion); - } - - if (src != target && battle_config.skill_add_range && - !check_distance_bl(src, target, skill_get_range2(src,ud->skillid,ud->skilllv)+battle_config.skill_add_range)) { - if (sd) { - clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); - if (battle_config.skill_out_range_consume) //Consume items anyway. [Skotlex] - skill_consume_requirement(sd,ud->skillid,ud->skilllv,3); - } - break; - } - - if (sd) { - if (!skill_check_condition_castend(sd, ud->skillid, ud->skilllv)) - break; - else - skill_consume_requirement(sd,ud->skillid,ud->skilllv,1); - } + if(ud->skillid != SA_CASTCANCEL && ud->skillid != SO_SPELLFIST) {// otherwise handled in unit_skillcastcancel() + if( ud->skilltimer != tid ) { + ShowError("skill_castend_id: Timer mismatch %d!=%d!\n", ud->skilltimer, tid); + ud->skilltimer = INVALID_TIMER; + return 0; + } + + if( sd && ud->skilltimer != INVALID_TIMER && (pc_checkskill(sd,SA_FREECAST) > 0 || ud->skillid == LG_EXEEDBREAK) ) + {// restore original walk speed + ud->skilltimer = INVALID_TIMER; + status_calc_bl(&sd->bl, SCB_SPEED); + } + + ud->skilltimer = INVALID_TIMER; + } + + if (ud->skilltarget == id) + target = src; + else + target = map_id2bl(ud->skilltarget); + + // Use a do so that you can break out of it when the skill fails. + do { + if(!target || target->prev==NULL) break; + + if(src->m != target->m || status_isdead(src)) break; + + switch (ud->skillid) { + //These should become skill_castend_pos + case WE_CALLPARTNER: + if(sd) clif_callpartner(sd); + case WE_CALLPARENT: + case WE_CALLBABY: + case AM_RESURRECTHOMUN: + case PF_SPIDERWEB: + //Find a random spot to place the skill. [Skotlex] + inf2 = skill_get_splash(ud->skillid, ud->skilllv); + ud->skillx = target->x + inf2; + ud->skilly = target->y + inf2; + if (inf2 && !map_random_dir(target, &ud->skillx, &ud->skilly)) { + ud->skillx = target->x; + ud->skilly = target->y; + } + ud->skilltimer=tid; + return skill_castend_pos(tid,tick,id,data); + case GN_WALLOFTHORN: + ud->skillx = target->x; + ud->skilly = target->y; + ud->skilltimer = tid; + return skill_castend_pos(tid,tick,id,data); + } + + if(ud->skillid == RG_BACKSTAP) { + int dir = map_calc_dir(src,target->x,target->y),t_dir = unit_getdir(target); + if(check_distance_bl(src, target, 0) || map_check_dir(dir,t_dir)) { + break; + } + } + + if( ud->skillid == PR_TURNUNDEAD ) + { + struct status_data *tstatus = status_get_status_data(target); + if( !battle_check_undead(tstatus->race, tstatus->def_ele) ) + break; + } + + if( ud->skillid == RA_WUGSTRIKE ){ + if( !path_search(NULL,src->m,src->x,src->y,target->x,target->y,1,CELL_CHKNOREACH)) + break; + } + + if( ud->skillid == PR_LEXDIVINA || ud->skillid == MER_LEXDIVINA ) + { + sc = status_get_sc(target); + if( battle_check_target(src,target, BCT_ENEMY) <= 0 && (!sc || !sc->data[SC_SILENCE]) ) + { //If it's not an enemy, and not silenced, you can't use the skill on them. [Skotlex] + clif_skill_nodamage (src, target, ud->skillid, ud->skilllv, 0); + break; + } + } + else + { // Check target validity. + inf = skill_get_inf(ud->skillid); + inf2 = skill_get_inf2(ud->skillid); + + if(inf&INF_ATTACK_SKILL || + (inf&INF_SELF_SKILL && inf2&INF2_NO_TARGET_SELF) //Combo skills + ) // Casted through combo. + inf = BCT_ENEMY; //Offensive skill. + else if(inf2&INF2_NO_ENEMY) + inf = BCT_NOENEMY; + else + inf = 0; + + if(inf2 & (INF2_PARTY_ONLY|INF2_GUILD_ONLY) && src != target) + { + inf |= + (inf2&INF2_PARTY_ONLY?BCT_PARTY:0)| + (inf2&INF2_GUILD_ONLY?BCT_GUILD:0); + //Remove neutral targets (but allow enemy if skill is designed to be so) + inf &= ~BCT_NEUTRAL; + } + + if( ud->skillid >= SL_SKE && ud->skillid <= SL_SKA && target->type == BL_MOB ) + { + if( ((TBL_MOB*)target)->class_ == MOBID_EMPERIUM ) + break; + } + else if (inf && battle_check_target(src, target, inf) <= 0){ + if (sd) clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); + break; + } + + if(inf&BCT_ENEMY && (sc = status_get_sc(target)) && + sc->data[SC_FOGWALL] && + rnd() % 100 < 75) { //Fogwall makes all offensive-type targetted skills fail at 75% + if (sd) clif_skill_fail(sd, ud->skillid, USESKILL_FAIL_LEVEL, 0); + break; + } + } + + //Avoid doing double checks for instant-cast skills. + if (tid != INVALID_TIMER && !status_check_skilluse(src, target, ud->skillid, 1)) + break; + + if(md) { + md->last_thinktime=tick +MIN_MOBTHINKTIME; + if(md->skillidx >= 0 && md->db->skill[md->skillidx].emotion >= 0) + clif_emotion(src, md->db->skill[md->skillidx].emotion); + } + + if(src != target && battle_config.skill_add_range && + !check_distance_bl(src, target, skill_get_range2(src,ud->skillid,ud->skilllv)+battle_config.skill_add_range)) + { + if (sd) { + clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); + if(battle_config.skill_out_range_consume) //Consume items anyway. [Skotlex] + skill_consume_requirement(sd,ud->skillid,ud->skilllv,3); + } + break; + } + + if( sd ) + { + if( !skill_check_condition_castend(sd, ud->skillid, ud->skilllv) ) + break; + else + skill_consume_requirement(sd,ud->skillid,ud->skilllv,1); + } #ifdef OFFICIAL_WALKPATH - if (!path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL)) - break; + if( !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) ) + break; #endif - if ((src->type == BL_MER || src->type == BL_HOM) && !skill_check_condition_mercenary(src, ud->skillid, ud->skilllv, 1)) - break; + if( (src->type == BL_MER || src->type == BL_HOM) && !skill_check_condition_mercenary(src, ud->skillid, ud->skilllv, 1) ) + break; - if (ud->state.running && ud->skillid == TK_JUMPKICK) { + if (ud->state.running && ud->skillid == TK_JUMPKICK) + { ud->state.running = 0; status_change_end(src, SC_RUN, INVALID_TIMER); - flag = 1; - } - - if (ud->walktimer != INVALID_TIMER && ud->skillid != TK_RUN && ud->skillid != RA_WUGDASH) - unit_stop_walking(src,1); - - if (!sd || sd->skillitem != ud->skillid || skill_get_delay(ud->skillid,ud->skilllv)) - ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv); //Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish] - if (sd) { //Cooldown application - int i, cooldown = skill_get_cooldown(ud->skillid, ud->skilllv); - for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses. - if (sd->skillcooldown[i].id == ud->skillid) { - cooldown += sd->skillcooldown[i].val; - break; - } - } - if(cooldown) - skill_blockpc_start(sd, ud->skillid, cooldown); - } - if (battle_config.display_status_timers && sd) - clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skillid, ud->skilllv), 0, 0, 0); - if (sd) { - switch (ud->skillid) { - case GS_DESPERADO: - sd->canequip_tick = tick + skill_get_time(ud->skillid, ud->skilllv); - break; - case CR_GRANDCROSS: - case NPC_GRANDDARKNESS: - if ((sc = status_get_sc(src)) && sc->data[SC_STRIPSHIELD]) { - const struct TimerData *timer = get_timer(sc->data[SC_STRIPSHIELD]->timer); - if (timer && timer->func == status_change_timer && DIFF_TICK(timer->tick,gettick()+skill_get_time(ud->skillid, ud->skilllv)) > 0) - break; - } - sc_start2(src, SC_STRIPSHIELD, 100, 0, 1, skill_get_time(ud->skillid, ud->skilllv)); - break; - } - } - if (skill_get_state(ud->skillid) != ST_MOVE_ENABLE) - unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill_get_walkdelay(ud->skillid, ud->skilllv), 1); - - if (battle_config.skill_log && battle_config.skill_log&src->type) - ShowInfo("Type %d, ID %d skill castend id [id =%d, lv=%d, target ID %d]\n", - src->type, src->id, ud->skillid, ud->skilllv, target->id); - - map_freeblock_lock(); - - // SC_MAGICPOWER needs to switch states before any damage is actually dealt - skill_toggle_magicpower(src, ud->skillid); - if (ud->skillid != RA_CAMOUFLAGE) // only normal attack and auto cast skills benefit from its bonuses - status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); - - if (skill_get_casttype(ud->skillid) == CAST_NODAMAGE) - skill_castend_nodamage_id(src,target,ud->skillid,ud->skilllv,tick,flag); - else - skill_castend_damage_id(src,target,ud->skillid,ud->skilllv,tick,flag); - - sc = status_get_sc(src); - if (sc && sc->count) { - if (sc->data[SC_SPIRIT] && - sc->data[SC_SPIRIT]->val2 == SL_WIZARD && - sc->data[SC_SPIRIT]->val3 == ud->skillid && - ud->skillid != WZ_WATERBALL) - sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. - - if (sc->data[SC_DANCING] && skill_get_inf2(ud->skillid)&INF2_SONG_DANCE && sd) - skill_blockpc_start(sd,BD_ADAPTATION,3000); - } - - if (sd && ud->skillid != SA_ABRACADABRA && ud->skillid != WM_RANDOMIZESPELL) // they just set the data so leave it as it is.[Inkfish] - sd->skillitem = sd->skillitemlv = 0; - - if (ud->skilltimer == INVALID_TIMER) { - if (md) md->skillidx = -1; - else ud->skillid = 0; //mobs can't clear this one as it is used for skill condition 'afterskill' - ud->skilllv = ud->skilltarget = 0; - } - map_freeblock_unlock(); - return 1; - } while (0); - - //Skill failed. - if (ud->skillid == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL])) { - //When Asura fails... (except when it fails from Fog of Wall) - //Consume SP/spheres - skill_consume_requirement(sd,ud->skillid, ud->skilllv,1); - status_set_sp(src, 0, 0); - sc = &sd->sc; - if (sc->count) { - //End states - status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); + flag = 1; + } + + if (ud->walktimer != INVALID_TIMER && ud->skillid != TK_RUN && ud->skillid != RA_WUGDASH) + unit_stop_walking(src,1); + + if( !sd || sd->skillitem != ud->skillid || skill_get_delay(ud->skillid,ud->skilllv) ) + ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv); //Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish] + if( sd && skill_get_cooldown(ud->skillid,ud->skilllv) > 0 ){ + int i, cooldown = skill_get_cooldown(ud->skillid, ud->skilllv); + for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses. + if (sd->skillcooldown[i].id == ud->skillid){ + cooldown += sd->skillcooldown[i].val; + break; + } + } + skill_blockpc_start(sd, ud->skillid, cooldown); + } + if( battle_config.display_status_timers && sd ) + clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skillid, ud->skilllv), 0, 0, 0); + if( sd ) + { + switch( ud->skillid ) + { + case GS_DESPERADO: + sd->canequip_tick = tick + skill_get_time(ud->skillid, ud->skilllv); + break; + case CR_GRANDCROSS: + case NPC_GRANDDARKNESS: + if( (sc = status_get_sc(src)) && sc->data[SC_STRIPSHIELD] ) + { + const struct TimerData *timer = get_timer(sc->data[SC_STRIPSHIELD]->timer); + if( timer && timer->func == status_change_timer && DIFF_TICK(timer->tick,gettick()+skill_get_time(ud->skillid, ud->skilllv)) > 0 ) + break; + } + sc_start2(src, SC_STRIPSHIELD, 100, 0, 1, skill_get_time(ud->skillid, ud->skilllv)); + break; + } + } + if (skill_get_state(ud->skillid) != ST_MOVE_ENABLE) + unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill_get_walkdelay(ud->skillid, ud->skilllv), 1); + + if(battle_config.skill_log && battle_config.skill_log&src->type) + ShowInfo("Type %d, ID %d skill castend id [id =%d, lv=%d, target ID %d]\n", + src->type, src->id, ud->skillid, ud->skilllv, target->id); + + map_freeblock_lock(); + + // SC_MAGICPOWER needs to switch states before any damage is actually dealt + skill_toggle_magicpower(src, ud->skillid); + if( ud->skillid != RA_CAMOUFLAGE ) // only normal attack and auto cast skills benefit from its bonuses + status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); + + if (skill_get_casttype(ud->skillid) == CAST_NODAMAGE) + skill_castend_nodamage_id(src,target,ud->skillid,ud->skilllv,tick,flag); + else + skill_castend_damage_id(src,target,ud->skillid,ud->skilllv,tick,flag); + + sc = status_get_sc(src); + if(sc && sc->count) { + if(sc->data[SC_SPIRIT] && + sc->data[SC_SPIRIT]->val2 == SL_WIZARD && + sc->data[SC_SPIRIT]->val3 == ud->skillid && + ud->skillid != WZ_WATERBALL) + sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. + + if( sc->data[SC_DANCING] && skill_get_inf2(ud->skillid)&INF2_SONG_DANCE && sd ) + skill_blockpc_start(sd,BD_ADAPTATION,3000); + } + + if( sd && ud->skillid != SA_ABRACADABRA && ud->skillid != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish] + sd->skillitem = sd->skillitemlv = 0; + + if (ud->skilltimer == INVALID_TIMER) { + if(md) md->skillidx = -1; + else ud->skillid = 0; //mobs can't clear this one as it is used for skill condition 'afterskill' + ud->skilllv = ud->skilltarget = 0; + } + map_freeblock_unlock(); + return 1; + } while(0); + + //Skill failed. + if (ud->skillid == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL])) + { //When Asura fails... (except when it fails from Fog of Wall) + //Consume SP/spheres + skill_consume_requirement(sd,ud->skillid, ud->skilllv,1); + status_set_sp(src, 0, 0); + sc = &sd->sc; + if (sc->count) + { //End states + status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); #ifdef RENEWAL - sc_start(src, SC_EXTREMITYFIST2, 100, ud->skilllv, skill_get_time(ud->skillid, ud->skilllv)); + sc_start(src, SC_EXTREMITYFIST2, 100, ud->skilllv, skill_get_time(ud->skillid, ud->skilllv)); #endif - } - if (target && target->m == src->m) { - //Move character to target anyway. - int dx,dy; - dx = target->x - src->x; - dy = target->y - src->y; - if (dx > 0) dx++; - else if (dx < 0) dx--; - if (dy > 0) dy++; - else if (dy < 0) dy--; - - if (unit_movepos(src, src->x+dx, src->y+dy, 1, 1)) { - //Display movement + animation. - clif_slide(src,src->x,src->y); - clif_skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skillid, ud->skilllv, 5); - } - clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); - } - } - - ud->skillid = ud->skilllv = ud->skilltarget = 0; - if (!sd || sd->skillitem != ud->skillid || skill_get_delay(ud->skillid,ud->skilllv)) - ud->canact_tick = tick; - //You can't place a skill failed packet here because it would be - //sent in ALL cases, even cases where skill_check_condition fails - //which would lead to double 'skill failed' messages u.u [Skotlex] - if (sd) - sd->skillitem = sd->skillitemlv = 0; - else if (md) - md->skillidx = -1; - return 0; + } + if (target && target->m == src->m) + { //Move character to target anyway. + int dx,dy; + dx = target->x - src->x; + dy = target->y - src->y; + if(dx > 0) dx++; + else if(dx < 0) dx--; + if (dy > 0) dy++; + else if(dy < 0) dy--; + + if (unit_movepos(src, src->x+dx, src->y+dy, 1, 1)) + { //Display movement + animation. + clif_slide(src,src->x,src->y); + clif_skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skillid, ud->skilllv, 5); + } + clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); + } + } + + ud->skillid = ud->skilllv = ud->skilltarget = 0; + if( !sd || sd->skillitem != ud->skillid || skill_get_delay(ud->skillid,ud->skilllv) ) + ud->canact_tick = tick; + //You can't place a skill failed packet here because it would be + //sent in ALL cases, even cases where skill_check_condition fails + //which would lead to double 'skill failed' messages u.u [Skotlex] + if(sd) + sd->skillitem = sd->skillitemlv = 0; + else if(md) + md->skillidx = -1; + return 0; } /*========================================== @@ -9485,2675 +9319,2709 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *src = map_id2bl(id); - int maxcount; - struct map_session_data *sd; - struct unit_data *ud = unit_bl2ud(src); - struct mob_data *md; - - nullpo_ret(ud); - - sd = BL_CAST(BL_PC , src); - md = BL_CAST(BL_MOB, src); - - if (src->prev == NULL) { - ud->skilltimer = INVALID_TIMER; - return 0; - } - - if (ud->skilltimer != tid) { - ShowError("skill_castend_pos: Timer mismatch %d!=%d\n", ud->skilltimer, tid); - ud->skilltimer = INVALID_TIMER; - return 0; - } - - if (sd && ud->skilltimer != INVALID_TIMER && (pc_checkskill(sd,SA_FREECAST) > 0 || ud->skillid == LG_EXEEDBREAK)) { - // restore original walk speed - ud->skilltimer = INVALID_TIMER; - status_calc_bl(&sd->bl, SCB_SPEED); - } - ud->skilltimer = INVALID_TIMER; - - do { - if (status_isdead(src)) - break; + struct block_list* src = map_id2bl(id); + int maxcount; + struct map_session_data *sd; + struct unit_data *ud = unit_bl2ud(src); + struct mob_data *md; - if (!(src->type&battle_config.skill_reiteration) && - skill_get_unit_flag(ud->skillid)&UF_NOREITERATION && - skill_check_unit_range(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv) - ) { - if (sd) clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); - break; - } - if (src->type&battle_config.skill_nofootset && - skill_get_unit_flag(ud->skillid)&UF_NOFOOTSET && - skill_check_unit_range2(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv) - ) { - if (sd) clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); - break; - } - if (src->type&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(ud->skillid, ud->skilllv)) > 0 - ) { - int i; - for (i=0; i<MAX_SKILLUNITGROUP && ud->skillunit[i] && maxcount; i++) { - if (ud->skillunit[i]->skill_id == ud->skillid) - maxcount--; - } - if (maxcount == 0) { - if (sd) clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); - break; - } - } - - if (tid != INVALID_TIMER) { - //Avoid double checks on instant cast skills. [Skotlex] - if (!status_check_skilluse(src, NULL, ud->skillid, 1)) - break; - if (battle_config.skill_add_range && - !check_distance_blxy(src, ud->skillx, ud->skilly, skill_get_range2(src,ud->skillid,ud->skilllv)+battle_config.skill_add_range)) { - if (sd && battle_config.skill_out_range_consume) //Consume items anyway. - skill_consume_requirement(sd,ud->skillid,ud->skilllv,3); - break; - } - } + nullpo_ret(ud); - if (sd) { - if (!skill_check_condition_castend(sd, ud->skillid, ud->skilllv)) - break; - else - skill_consume_requirement(sd,ud->skillid,ud->skilllv,1); - } + sd = BL_CAST(BL_PC , src); + md = BL_CAST(BL_MOB, src); - if ((src->type == BL_MER || src->type == BL_HOM) && !skill_check_condition_mercenary(src, ud->skillid, ud->skilllv, 1)) - break; + if( src->prev == NULL ) { + ud->skilltimer = INVALID_TIMER; + return 0; + } - if (md) { - md->last_thinktime=tick +MIN_MOBTHINKTIME; - if (md->skillidx >= 0 && md->db->skill[md->skillidx].emotion >= 0) - clif_emotion(src, md->db->skill[md->skillidx].emotion); - } - - if (battle_config.skill_log && battle_config.skill_log&src->type) - ShowInfo("Type %d, ID %d skill castend pos [id =%d, lv=%d, (%d,%d)]\n", - src->type, src->id, ud->skillid, ud->skilllv, ud->skillx, ud->skilly); - - if (ud->walktimer != INVALID_TIMER) - unit_stop_walking(src,1); - - if (!sd || sd->skillitem != ud->skillid || skill_get_delay(ud->skillid,ud->skilllv)) - ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv); - if (sd) { //Cooldown application - int i, cooldown = skill_get_cooldown(ud->skillid, ud->skilllv); - for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses. - if (sd->skillcooldown[i].id == ud->skillid) { - cooldown += sd->skillcooldown[i].val; - break; - } - } - if(cooldown) - skill_blockpc_start(sd, ud->skillid, cooldown); - } - if (battle_config.display_status_timers && sd) - clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skillid, ud->skilllv), 0, 0, 0); - // if( sd ) - // { - // switch( ud->skillid ) - // { - // case ????: - // sd->canequip_tick = tick + ????; - // break; - // } - // } - unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill_get_walkdelay(ud->skillid, ud->skilllv), 1); - status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);// only normal attack and auto cast skills benefit from its bonuses - map_freeblock_lock(); - skill_castend_pos2(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv,tick,0); - - if (sd && sd->skillitem != AL_WARP) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish] - sd->skillitem = sd->skillitemlv = 0; - - if (ud->skilltimer == INVALID_TIMER) { - if (md) md->skillidx = -1; - else ud->skillid = 0; //Non mobs can't clear this one as it is used for skill condition 'afterskill' - ud->skilllv = ud->skillx = ud->skilly = 0; - } - - map_freeblock_unlock(); - return 1; - } while (0); - - if (!sd || sd->skillitem != ud->skillid || skill_get_delay(ud->skillid,ud->skilllv)) - ud->canact_tick = tick; - ud->skillid = ud->skilllv = 0; - if (sd) - sd->skillitem = sd->skillitemlv = 0; - else if (md) - md->skillidx = -1; - return 0; + if( ud->skilltimer != tid ) + { + ShowError("skill_castend_pos: Timer mismatch %d!=%d\n", ud->skilltimer, tid); + ud->skilltimer = INVALID_TIMER; + return 0; + } + + if( sd && ud->skilltimer != INVALID_TIMER && ( pc_checkskill(sd,SA_FREECAST) > 0 || ud->skillid == LG_EXEEDBREAK ) ) + {// restore original walk speed + ud->skilltimer = INVALID_TIMER; + status_calc_bl(&sd->bl, SCB_SPEED); + } + ud->skilltimer = INVALID_TIMER; + + do { + if( status_isdead(src) ) + break; + + if( !(src->type&battle_config.skill_reiteration) && + skill_get_unit_flag(ud->skillid)&UF_NOREITERATION && + skill_check_unit_range(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv) + ) + { + if (sd) clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); + break; + } + if( src->type&battle_config.skill_nofootset && + skill_get_unit_flag(ud->skillid)&UF_NOFOOTSET && + skill_check_unit_range2(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv) + ) + { + if (sd) clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); + break; + } + if( src->type&battle_config.land_skill_limit && + (maxcount = skill_get_maxcount(ud->skillid, ud->skilllv)) > 0 + ) { + int i; + for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i] && maxcount;i++) { + if(ud->skillunit[i]->skill_id == ud->skillid) + maxcount--; + } + if( maxcount == 0 ) + { + if (sd) clif_skill_fail(sd,ud->skillid,USESKILL_FAIL_LEVEL,0); + break; + } + } + + if(tid != INVALID_TIMER) + { //Avoid double checks on instant cast skills. [Skotlex] + if (!status_check_skilluse(src, NULL, ud->skillid, 1)) + break; + if(battle_config.skill_add_range && + !check_distance_blxy(src, ud->skillx, ud->skilly, skill_get_range2(src,ud->skillid,ud->skilllv)+battle_config.skill_add_range)) { + if (sd && battle_config.skill_out_range_consume) //Consume items anyway. + skill_consume_requirement(sd,ud->skillid,ud->skilllv,3); + break; + } + } + + if( sd ) + { + if( !skill_check_condition_castend(sd, ud->skillid, ud->skilllv) ) + break; + else + skill_consume_requirement(sd,ud->skillid,ud->skilllv,1); + } + + if( (src->type == BL_MER || src->type == BL_HOM) && !skill_check_condition_mercenary(src, ud->skillid, ud->skilllv, 1) ) + break; + + if(md) { + md->last_thinktime=tick +MIN_MOBTHINKTIME; + if(md->skillidx >= 0 && md->db->skill[md->skillidx].emotion >= 0) + clif_emotion(src, md->db->skill[md->skillidx].emotion); + } + + if(battle_config.skill_log && battle_config.skill_log&src->type) + ShowInfo("Type %d, ID %d skill castend pos [id =%d, lv=%d, (%d,%d)]\n", + src->type, src->id, ud->skillid, ud->skilllv, ud->skillx, ud->skilly); + + if (ud->walktimer != INVALID_TIMER) + unit_stop_walking(src,1); + + if( !sd || sd->skillitem != ud->skillid || skill_get_delay(ud->skillid,ud->skilllv) ) + ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv); + if( sd && skill_get_cooldown(ud->skillid,ud->skilllv) > 0 ){ + int i, cooldown = skill_get_cooldown(ud->skillid, ud->skilllv); + for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses. + if (sd->skillcooldown[i].id == ud->skillid){ + cooldown += sd->skillcooldown[i].val; + break; + } + } + skill_blockpc_start(sd, ud->skillid, cooldown); + } + if( battle_config.display_status_timers && sd ) + clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skillid, ud->skilllv), 0, 0, 0); +// if( sd ) +// { +// switch( ud->skillid ) +// { +// case ????: +// sd->canequip_tick = tick + ????; +// break; +// } +// } + unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill_get_walkdelay(ud->skillid, ud->skilllv), 1); + status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);// only normal attack and auto cast skills benefit from its bonuses + map_freeblock_lock(); + skill_castend_pos2(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv,tick,0); + + if( sd && sd->skillitem != AL_WARP ) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish] + sd->skillitem = sd->skillitemlv = 0; + + if (ud->skilltimer == INVALID_TIMER) { + if (md) md->skillidx = -1; + else ud->skillid = 0; //Non mobs can't clear this one as it is used for skill condition 'afterskill' + ud->skilllv = ud->skillx = ud->skilly = 0; + } + + map_freeblock_unlock(); + return 1; + } while(0); + + if( !sd || sd->skillitem != ud->skillid || skill_get_delay(ud->skillid,ud->skilllv) ) + ud->canact_tick = tick; + ud->skillid = ud->skilllv = 0; + if(sd) + sd->skillitem = sd->skillitemlv = 0; + else if(md) + md->skillidx = -1; + return 0; } /*========================================== * *------------------------------------------*/ -int skill_castend_pos2(struct block_list *src, int x, int y, int skillid, int skilllv, unsigned int tick, int flag) +int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int skilllv, unsigned int tick, int flag) { - struct map_session_data *sd; - struct status_change *sc; - struct status_change_entry *sce; - struct skill_unit_group *sg; - enum sc_type type; - int i; - - //if(skilllv <= 0) return 0; - if (skillid > 0 && skilllv <= 0) return 0; // celest - - nullpo_ret(src); - - if (status_isdead(src)) - return 0; - - sd = BL_CAST(BL_PC, src); - - sc = status_get_sc(src); - type = status_skill2sc(skillid); - sce = (sc && type != -1)?sc->data[type]:NULL; - - switch (skillid) { //Skill effect. - case WZ_METEOR: - case MO_BODYRELOCATION: - case CR_CULTIVATION: - case HW_GANBANTEIN: - case LG_EARTHDRIVE: - break; //Effect is displayed on respective switch case. - default: - if (skill_get_inf(skillid)&INF_SELF_SKILL) - clif_skill_nodamage(src,src,skillid,skilllv,1); - else - clif_skill_poseffect(src,skillid,skilllv,x,y,tick); - } - - // SC_MAGICPOWER needs to switch states before any damage is actually dealt - skill_toggle_magicpower(src, skillid); - - switch (skillid) { - case PR_BENEDICTIO: - skill_area_temp[1] = src->id; - i = skill_get_splash(skillid, skilllv); - map_foreachinarea(skill_area_sub, - src->m, x-i, y-i, x+i, y+i, BL_PC, - src, skillid, skilllv, tick, flag|BCT_ALL|1, - skill_castend_nodamage_id); - map_foreachinarea(skill_area_sub, - src->m, x-i, y-i, x+i, y+i, BL_CHAR, - src, skillid, skilllv, tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - break; - - case BS_HAMMERFALL: - i = skill_get_splash(skillid, skilllv); - map_foreachinarea(skill_area_sub, - src->m, x-i, y-i, x+i, y+i, BL_CHAR, - src, skillid, skilllv, tick, flag|BCT_ENEMY|2, - skill_castend_nodamage_id); - break; - - case HT_DETECTING: - i = skill_get_splash(skillid, skilllv); - map_foreachinarea(status_change_timer_sub, - src->m, x-i, y-i, x+i,y+i,BL_CHAR, - src,NULL,SC_SIGHT,tick); - if (battle_config.traps_setting&1) - map_foreachinarea(skill_reveal_trap, - src->m, x-i, y-i, x+i,y+i,BL_SKILL); - break; - - case SR_RIDEINLIGHTNING: - i = skill_get_splash(skillid, skilllv); - map_foreachinarea(skill_area_sub, src->m, x-i, y-i, x+i, y+i, BL_CHAR, - src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id); - break; + struct map_session_data* sd; + struct status_change* sc; + struct status_change_entry *sce; + struct skill_unit_group* sg; + enum sc_type type; + int i; + + //if(skilllv <= 0) return 0; + if(skillid > 0 && skilllv <= 0) return 0; // celest + + nullpo_ret(src); + + if(status_isdead(src)) + return 0; + + sd = BL_CAST(BL_PC, src); + + sc = status_get_sc(src); + type = status_skill2sc(skillid); + sce = (sc && type != -1)?sc->data[type]:NULL; + + switch (skillid) { //Skill effect. + case WZ_METEOR: + case MO_BODYRELOCATION: + case CR_CULTIVATION: + case HW_GANBANTEIN: + case LG_EARTHDRIVE: + break; //Effect is displayed on respective switch case. + default: + if(skill_get_inf(skillid)&INF_SELF_SKILL) + clif_skill_nodamage(src,src,skillid,skilllv,1); + else + clif_skill_poseffect(src,skillid,skilllv,x,y,tick); + } - case SA_VOLCANO: - case SA_DELUGE: - case SA_VIOLENTGALE: { - //Does not consumes if the skill is already active. [Skotlex] - struct skill_unit_group *sg; - if ((sg= skill_locate_element_field(src)) != NULL && (sg->skill_id == SA_VOLCANO || sg->skill_id == SA_DELUGE || sg->skill_id == SA_VIOLENTGALE)) { - if (sg->limit - DIFF_TICK(gettick(), sg->tick) > 0) { - skill_unitsetting(src,skillid,skilllv,x,y,0); - return 0; // not to consume items - } else - sg->limit = 0; //Disable it. - } - skill_unitsetting(src,skillid,skilllv,x,y,0); - break; - } - case MG_SAFETYWALL: - case MG_FIREWALL: - case MG_THUNDERSTORM: - - case AL_PNEUMA: - case WZ_ICEWALL: - case WZ_FIREPILLAR: - case WZ_QUAGMIRE: - case WZ_VERMILION: - case WZ_STORMGUST: - case WZ_HEAVENDRIVE: - case PR_SANCTUARY: - case PR_MAGNUS: - case CR_GRANDCROSS: - case NPC_GRANDDARKNESS: - case HT_SKIDTRAP: - case MA_SKIDTRAP: - case HT_LANDMINE: - case MA_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case MA_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case AS_VENOMDUST: - case AM_DEMONSTRATION: - case PF_FOGWALL: - case PF_SPIDERWEB: - case HT_TALKIEBOX: - case WE_CALLPARTNER: - case WE_CALLPARENT: - case WE_CALLBABY: - case AC_SHOWER: //Ground-placed skill implementation. - case MA_SHOWER: - case SA_LANDPROTECTOR: - case BD_LULLABY: - case BD_RICHMANKIM: - case BD_ETERNALCHAOS: - case BD_DRUMBATTLEFIELD: - case BD_RINGNIBELUNGEN: - case BD_ROKISWEIL: - case BD_INTOABYSS: - case BD_SIEGFRIED: - case BA_DISSONANCE: - case BA_POEMBRAGI: - case BA_WHISTLE: - case BA_ASSASSINCROSS: - case BA_APPLEIDUN: - case DC_UGLYDANCE: - case DC_HUMMING: - case DC_DONTFORGETME: - case DC_FORTUNEKISS: - case DC_SERVICEFORYOU: - case CG_MOONLIT: - case GS_DESPERADO: - case NJ_KAENSIN: - case NJ_BAKUENRYU: - case NJ_SUITON: - case NJ_HYOUSYOURAKU: - case NJ_RAIGEKISAI: - case NJ_KAMAITACHI: + // SC_MAGICPOWER needs to switch states before any damage is actually dealt + skill_toggle_magicpower(src, skillid); + + switch(skillid) + { + case PR_BENEDICTIO: + skill_area_temp[1] = src->id; + i = skill_get_splash(skillid, skilllv); + map_foreachinarea(skill_area_sub, + src->m, x-i, y-i, x+i, y+i, BL_PC, + src, skillid, skilllv, tick, flag|BCT_ALL|1, + skill_castend_nodamage_id); + map_foreachinarea(skill_area_sub, + src->m, x-i, y-i, x+i, y+i, BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); + break; + + case BS_HAMMERFALL: + i = skill_get_splash(skillid, skilllv); + map_foreachinarea (skill_area_sub, + src->m, x-i, y-i, x+i, y+i, BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY|2, + skill_castend_nodamage_id); + break; + + case HT_DETECTING: + i = skill_get_splash(skillid, skilllv); + map_foreachinarea( status_change_timer_sub, + src->m, x-i, y-i, x+i,y+i,BL_CHAR, + src,NULL,SC_SIGHT,tick); + if(battle_config.traps_setting&1) + map_foreachinarea( skill_reveal_trap, + src->m, x-i, y-i, x+i,y+i,BL_SKILL); + break; + + case SR_RIDEINLIGHTNING: + i = skill_get_splash(skillid, skilllv); + map_foreachinarea(skill_area_sub, src->m, x-i, y-i, x+i, y+i, BL_CHAR, + src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id); + break; + + case SA_VOLCANO: + case SA_DELUGE: + case SA_VIOLENTGALE: + { //Does not consumes if the skill is already active. [Skotlex] + struct skill_unit_group *sg; + if ((sg= skill_locate_element_field(src)) != NULL && ( sg->skill_id == SA_VOLCANO || sg->skill_id == SA_DELUGE || sg->skill_id == SA_VIOLENTGALE )) + { + if (sg->limit - DIFF_TICK(gettick(), sg->tick) > 0) + { + skill_unitsetting(src,skillid,skilllv,x,y,0); + return 0; // not to consume items + } + else + sg->limit = 0; //Disable it. + } + skill_unitsetting(src,skillid,skilllv,x,y,0); + break; + } + case MG_SAFETYWALL: + case MG_FIREWALL: + case MG_THUNDERSTORM: + + case AL_PNEUMA: + case WZ_ICEWALL: + case WZ_FIREPILLAR: + case WZ_QUAGMIRE: + case WZ_VERMILION: + case WZ_STORMGUST: + case WZ_HEAVENDRIVE: + case PR_SANCTUARY: + case PR_MAGNUS: + case CR_GRANDCROSS: + case NPC_GRANDDARKNESS: + case HT_SKIDTRAP: + case MA_SKIDTRAP: + case HT_LANDMINE: + case MA_LANDMINE: + case HT_ANKLESNARE: + case HT_SHOCKWAVE: + case HT_SANDMAN: + case MA_SANDMAN: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + case AS_VENOMDUST: + case AM_DEMONSTRATION: + case PF_FOGWALL: + case PF_SPIDERWEB: + case HT_TALKIEBOX: + case WE_CALLPARTNER: + case WE_CALLPARENT: + case WE_CALLBABY: + case AC_SHOWER: //Ground-placed skill implementation. + case MA_SHOWER: + case SA_LANDPROTECTOR: + case BD_LULLABY: + case BD_RICHMANKIM: + case BD_ETERNALCHAOS: + case BD_DRUMBATTLEFIELD: + case BD_RINGNIBELUNGEN: + case BD_ROKISWEIL: + case BD_INTOABYSS: + case BD_SIEGFRIED: + case BA_DISSONANCE: + case BA_POEMBRAGI: + case BA_WHISTLE: + case BA_ASSASSINCROSS: + case BA_APPLEIDUN: + case DC_UGLYDANCE: + case DC_HUMMING: + case DC_DONTFORGETME: + case DC_FORTUNEKISS: + case DC_SERVICEFORYOU: + case CG_MOONLIT: + case GS_DESPERADO: + case NJ_KAENSIN: + case NJ_BAKUENRYU: + case NJ_SUITON: + case NJ_HYOUSYOURAKU: + case NJ_RAIGEKISAI: + case NJ_KAMAITACHI: #ifdef RENEWAL - case NJ_HUUMA: + case NJ_HUUMA: #endif - case NPC_EVILLAND: - case RA_ELECTRICSHOCKER: - case RA_CLUSTERBOMB: - case RA_MAGENTATRAP: - case RA_COBALTTRAP: - case RA_MAIZETRAP: - case RA_VERDURETRAP: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - case SC_MANHOLE: - case SC_DIMENSIONDOOR: - case SC_CHAOSPANIC: - case SC_MAELSTROM: - case WM_REVERBERATION: - case WM_SEVERE_RAINSTORM: - case WM_POEMOFNETHERWORLD: - case SO_PSYCHIC_WAVE: - case SO_VACUUM_EXTREME: - case GN_WALLOFTHORN: - case GN_THORNS_TRAP: - case GN_DEMONIC_FIRE: - case GN_HELLS_PLANT: - case SO_EARTHGRAVE: - case SO_DIAMONDDUST: - case SO_FIRE_INSIGNIA: - case SO_WATER_INSIGNIA: - case SO_WIND_INSIGNIA: - case SO_EARTH_INSIGNIA: - case KO_HUUMARANKA: - case KO_MUCHANAGE: - case KO_BAKURETSU: - case KO_ZENKAI: - case MH_LAVA_SLIDE: - case MH_VOLCANIC_ASH: - case MH_POISON_MIST: - case MH_STEINWAND: - case MH_XENO_SLASHER: - flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). - case GS_GROUNDDRIFT: //Ammo should be deleted right away. - 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); - flag|=1; - break; - case HP_BASILICA: - if (sc->data[SC_BASILICA]) - status_change_end(src, SC_BASILICA, INVALID_TIMER); // Cancel Basilica - else { - // Create Basilica. Start SC on caster. Unit timer start SC on others. - skill_clear_unitgroup(src); - if (skill_unitsetting(src,skillid,skilllv,x,y,0)) - sc_start4(src,type,100,skilllv,0,0,src->id,skill_get_time(skillid,skilllv)); - flag|=1; - } - break; - case CG_HERMODE: - skill_clear_unitgroup(src); - if ((sg = skill_unitsetting(src,skillid,skilllv,x,y,0))) - sc_start4(src,SC_DANCING,100, - skillid,0,skilllv,sg->group_id,skill_get_time(skillid,skilllv)); - flag|=1; - break; - case RG_CLEANER: // [Valaris] - i = skill_get_splash(skillid, skilllv); - map_foreachinarea(skill_graffitiremover,src->m,x-i,y-i,x+i,y+i,BL_SKILL); - break; - - case SO_WARMER: - flag|= 8; - case SO_CLOUD_KILL: - skill_unitsetting(src,skillid,skilllv,x,y,0); - break; - - case WZ_METEOR: { - int area = skill_get_splash(skillid, skilllv); - short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0; - - for (i = 0; i < 2 + (skilllv>>1); i++) { - // Creates a random Cell in the Splash Area - tmpx = x - area + rnd()%(area * 2 + 1); - tmpy = y - area + rnd()%(area * 2 + 1); - - if (i == 0 && path_search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL)) - clif_skill_poseffect(src,skillid,skilllv,tmpx,tmpy,tick); - - if (i > 0) - skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,(x1<<16)|y1,0); - - x1 = tmpx; - y1 = tmpy; - } - - skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,-1,0); - } - break; - - case AL_WARP: - if (sd) { - clif_skill_warppoint(sd, skillid, skilllv, sd->status.save_point.map, - (skilllv >= 2) ? sd->status.memo_point[0].map : 0, - (skilllv >= 3) ? sd->status.memo_point[1].map : 0, - (skilllv >= 4) ? sd->status.memo_point[2].map : 0 - ); - } - return 0; // not to consume item. + case NPC_EVILLAND: + case RA_ELECTRICSHOCKER: + case RA_CLUSTERBOMB: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + case SC_MANHOLE: + case SC_DIMENSIONDOOR: + case SC_CHAOSPANIC: + case SC_MAELSTROM: + case WM_REVERBERATION: + case WM_SEVERE_RAINSTORM: + case WM_POEMOFNETHERWORLD: + case SO_PSYCHIC_WAVE: + case SO_VACUUM_EXTREME: + case GN_WALLOFTHORN: + case GN_THORNS_TRAP: + case GN_DEMONIC_FIRE: + case GN_HELLS_PLANT: + case SO_EARTHGRAVE: + case SO_DIAMONDDUST: + case SO_FIRE_INSIGNIA: + case SO_WATER_INSIGNIA: + case SO_WIND_INSIGNIA: + case SO_EARTH_INSIGNIA: + case KO_HUUMARANKA: + case KO_MUCHANAGE: + case KO_BAKURETSU: + case KO_ZENKAI: + case MH_LAVA_SLIDE: + case MH_VOLCANIC_ASH: + case MH_POISON_MIST: + case MH_STEINWAND: + case MH_XENO_SLASHER: + flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). + case GS_GROUNDDRIFT: //Ammo should be deleted right away. + 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); + flag|=1; + break; + case HP_BASILICA: + if( sc->data[SC_BASILICA] ) + status_change_end(src, SC_BASILICA, INVALID_TIMER); // Cancel Basilica + else + { // Create Basilica. Start SC on caster. Unit timer start SC on others. + skill_clear_unitgroup(src); + if( skill_unitsetting(src,skillid,skilllv,x,y,0) ) + sc_start4(src,type,100,skilllv,0,0,src->id,skill_get_time(skillid,skilllv)); + flag|=1; + } + break; + case CG_HERMODE: + skill_clear_unitgroup(src); + if ((sg = skill_unitsetting(src,skillid,skilllv,x,y,0))) + sc_start4(src,SC_DANCING,100, + skillid,0,skilllv,sg->group_id,skill_get_time(skillid,skilllv)); + flag|=1; + break; + case RG_CLEANER: // [Valaris] + i = skill_get_splash(skillid, skilllv); + map_foreachinarea(skill_graffitiremover,src->m,x-i,y-i,x+i,y+i,BL_SKILL); + break; + + case SO_WARMER: + flag|= 8; + case SO_CLOUD_KILL: + skill_unitsetting(src,skillid,skilllv,x,y,0); + break; + + case WZ_METEOR: { + int area = skill_get_splash(skillid, skilllv); + short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0; + + for( i = 0; i < 2 + (skilllv>>1); i++ ) { + // Creates a random Cell in the Splash Area + tmpx = x - area + rnd()%(area * 2 + 1); + tmpy = y - area + rnd()%(area * 2 + 1); + + if( i == 0 && path_search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL) ) + clif_skill_poseffect(src,skillid,skilllv,tmpx,tmpy,tick); + + if( i > 0 ) + skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,(x1<<16)|y1,0); + + x1 = tmpx; + y1 = tmpy; + } - case MO_BODYRELOCATION: - if (unit_movepos(src, x, y, 1, 1)) { + skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skillid,skilllv,-1,0); + } + break; + + case AL_WARP: + if(sd) + { + clif_skill_warppoint(sd, skillid, skilllv, sd->status.save_point.map, + (skilllv >= 2) ? sd->status.memo_point[0].map : 0, + (skilllv >= 3) ? sd->status.memo_point[1].map : 0, + (skilllv >= 4) ? sd->status.memo_point[2].map : 0 + ); + } + return 0; // not to consume item. + + case MO_BODYRELOCATION: + if (unit_movepos(src, x, y, 1, 1)) { #if PACKETVER >= 20111005 - clif_snap(src, src->x, src->y); + clif_snap(src, src->x, src->y); #else - clif_skill_poseffect(src,skillid,skilllv,src->x,src->y,tick); + clif_skill_poseffect(src,skillid,skilllv,src->x,src->y,tick); #endif - if (sd) - skill_blockpc_start(sd, MO_EXTREMITYFIST, 2000); - } - break; - case NJ_SHADOWJUMP: - if (!map_flag_gvg(src->m) && !map[src->m].flag.battleground) { //You don't move on GVG grounds. - unit_movepos(src, x, y, 1, 0); - clif_slide(src,x,y); - } - status_change_end(src, SC_HIDING, INVALID_TIMER); - break; - case AM_SPHEREMINE: - case AM_CANNIBALIZE: { - int summons[5] = { 1589, 1579, 1575, 1555, 1590 }; - //int summons[5] = { 1020, 1068, 1118, 1500, 1368 }; - int class_ = skillid==AM_SPHEREMINE?1142:summons[skilllv-1]; - struct mob_data *md; - - // Correct info, don't change any of this! [celest] - md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE); - if (md) { - md->master_id = src->id; - md->special_state.ai = (skillid == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA; - if (md->deletetimer != INVALID_TIMER) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer(gettick() + skill_get_time(skillid,skilllv), mob_timer_delete, md->bl.id, 0); - mob_spawn(md); //Now it is ready for spawning. - } - } - break; - - // Slim Pitcher [Celest] - case CR_SLIMPITCHER: - if (sd) { - 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,USESKILL_FAIL_LEVEL,0); - return 1; - } - potion_flag = 1; - potion_hp = 0; - potion_sp = 0; - run_script(sd->inventory_data[j]->script,0,sd->bl.id,0); - potion_flag = 0; - //Apply skill bonuses - i = pc_checkskill(sd,CR_SLIMPITCHER)*10 - + pc_checkskill(sd,AM_POTIONPITCHER)*10 - + pc_checkskill(sd,AM_LEARNINGPOTION)*5 - + pc_skillheal_bonus(sd, skillid); - - potion_hp = potion_hp * (100+i)/100; - potion_sp = potion_sp * (100+i)/100; - - if (potion_hp > 0 || potion_sp > 0) { - i = skill_get_splash(skillid, skilllv); - map_foreachinarea(skill_area_sub, - src->m,x-i,y-i,x+i,y+i,BL_CHAR, - src,skillid,skilllv,tick,flag|BCT_PARTY|BCT_GUILD|1, - skill_castend_nodamage_id); - } - } else { - int i = skilllv%11 - 1; - struct item_data *item; - i = skill_db[skillid].itemid[i]; - item = itemdb_search(i); - potion_flag = 1; - potion_hp = 0; - potion_sp = 0; - run_script(item->script,0,src->id,0); - potion_flag = 0; - i = skill_get_max(CR_SLIMPITCHER)*10; - - potion_hp = potion_hp * (100+i)/100; - potion_sp = potion_sp * (100+i)/100; - - if (potion_hp > 0 || potion_sp > 0) { - i = skill_get_splash(skillid, skilllv); - map_foreachinarea(skill_area_sub, - src->m,x-i,y-i,x+i,y+i,BL_CHAR, - src,skillid,skilllv,tick,flag|BCT_PARTY|BCT_GUILD|1, - skill_castend_nodamage_id); - } - } - break; - - case HW_GANBANTEIN: - if (rnd()%100 < 80) { - int dummy = 1; - clif_skill_poseffect(src,skillid,skilllv,x,y,tick); - i = skill_get_splash(skillid, skilllv); - map_foreachinarea(skill_cell_overlap, src->m, x-i, y-i, x+i, y+i, BL_SKILL, HW_GANBANTEIN, &dummy, src); - } else { - if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - return 1; - } - break; - - case HW_GRAVITATION: - if ((sg = skill_unitsetting(src,skillid,skilllv,x,y,0))) - sc_start4(src,type,100,skilllv,0,BCT_SELF,sg->group_id,skill_get_time(skillid,skilllv)); - flag|=1; - break; - - // Plant Cultivation [Celest] - case CR_CULTIVATION: - if (sd) { - if (map_count_oncell(src->m,x,y,BL_CHAR) > 0) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - return 1; - } - clif_skill_poseffect(src,skillid,skilllv,x,y,tick); - if (rnd()%100 < 50) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - } else { - TBL_MOB *md = mob_once_spawn_sub(src, src->m, x, y, "--ja--",(skilllv < 2 ? 1084+rnd()%2 : 1078+rnd()%6),"", SZ_SMALL, AI_NONE); - int i; - if (!md) break; - if ((i = skill_get_time(skillid, skilllv)) > 0) { - if (md->deletetimer != INVALID_TIMER) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer(tick + i, mob_timer_delete, md->bl.id, 0); - } - mob_spawn(md); - } - } - break; - - case SG_SUN_WARM: - case SG_MOON_WARM: - case SG_STAR_WARM: - skill_clear_unitgroup(src); - if ((sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0))) - sc_start4(src,type,100,skilllv,0,0,sg->group_id,skill_get_time(skillid,skilllv)); - flag|=1; - break; - - case PA_GOSPEL: - if (sce && sce->val4 == BCT_SELF) { - status_change_end(src, SC_GOSPEL, INVALID_TIMER); - return 0; - } else { - sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0); - if (!sg) break; - if (sce) - status_change_end(src, type, INVALID_TIMER); //Was under someone else's Gospel. [Skotlex] - sc_start4(src,type,100,skilllv,0,sg->group_id,BCT_SELF,skill_get_time(skillid,skilllv)); - clif_skill_poseffect(src, skillid, skilllv, 0, 0, tick); // PA_GOSPEL music packet - } - break; - case NJ_TATAMIGAESHI: - if (skill_unitsetting(src,skillid,skilllv,src->x,src->y,0)) - sc_start(src,type,100,skilllv,skill_get_time2(skillid,skilllv)); - break; - - case AM_RESURRECTHOMUN: //[orn] - if (sd) { - if (!merc_resurrect_homunculus(sd, 20*skilllv, x, y)) { - clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); - break; - } - } - break; - - case NC_COLDSLOWER: - case NC_ARMSCANNON: - case RK_DRAGONBREATH: - case RK_WINDCUTTER: - case WM_LULLABY_DEEPSLEEP: - i = skill_get_splash(skillid,skilllv); - map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), - src,skillid,skilllv,tick,flag|(skillid==WM_LULLABY_DEEPSLEEP?BCT_ALL:BCT_ENEMY)|1,skill_castend_damage_id); - break; - /** - * Guilotine Cross - **/ - case GC_POISONSMOKE: - if (!(sc && sc->data[SC_POISONINGWEAPON])) { - if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL_GC_POISONINGWEAPON,0); - return 0; - } - clif_skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skillid,skilllv,6); - skill_unitsetting(src, skillid, skilllv, x, y, flag); - //status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER); // 08/31/2011 - When using poison smoke, you no longer lose the poisoning weapon effect. - break; - /** - * Arch Bishop - **/ - case AB_EPICLESIS: - if ((sg = skill_unitsetting(src, skillid, skilllv, x, y, 0))) { - i = sg->unit->range; - map_foreachinarea(skill_area_sub, src->m, x - i, y - i, x + i, y + i, BL_CHAR, src, ALL_RESURRECTION, 1, tick, flag|BCT_NOENEMY|1,skill_castend_nodamage_id); - } - break; - /** - * Warlock - **/ - case WL_COMET: - if (sc) { - sc->comet_x = x; - sc->comet_y = y; - } - i = skill_get_splash(skillid,skilllv); - map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - break; - - case WL_EARTHSTRAIN: { - int i, wave = skilllv + 4, dir = map_calc_dir(src,x,y); - int sx = x = src->x, sy = y = src->y; // Store first caster's location to avoid glitch on unit setting - - for (i = 1; i <= wave; i++) { - switch (dir) { - case 0: - case 1: - case 7: - sy = y + i; - break; - case 3: - case 4: - case 5: - sy = y - i; - break; - case 2: - sx = x - i; - break; - case 6: - sx = x + i; - break; - } - skill_addtimerskill(src,gettick() + (150 * i),0,sx,sy,skillid,skilllv,dir,flag&2); - } - } - break; - /** - * Ranger - **/ - case RA_DETONATOR: - i = skill_get_splash(skillid, skilllv); - map_foreachinarea(skill_detonator, src->m, x-i, y-i, x+i, y+i, BL_SKILL, src); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - break; - /** - * Mechanic - **/ - case NC_NEUTRALBARRIER: - case NC_STEALTHFIELD: - skill_clear_unitgroup(src); // To remove previous skills - cannot used combined - if ((sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0)) != NULL) { - sc_start2(src,skillid == NC_NEUTRALBARRIER ? SC_NEUTRALBARRIER_MASTER : SC_STEALTHFIELD_MASTER,100,skilllv,sg->group_id,skill_get_time(skillid,skilllv)); - if (sd) pc_overheat(sd,1); - } - break; - - case NC_SILVERSNIPER: { - int class_ = 2042; - struct mob_data *md; - - md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE); - if (md) { - md->master_id = src->id; - md->special_state.ai = AI_FLORA; - if (md->deletetimer != INVALID_TIMER) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer(gettick() + skill_get_time(skillid, skilllv), mob_timer_delete, md->bl.id, 0); - mob_spawn(md); - } - } - break; - - case NC_MAGICDECOY: - if (sd) clif_magicdecoy_list(sd,skilllv,x,y); - break; - - case SC_FEINTBOMB: - clif_skill_nodamage(src,src,skillid,skilllv,1); - skill_unitsetting(src,skillid,skilllv,x,y,0); // Set bomb on current Position - if (skill_blown(src,src,6,unit_getdir(src),0)) - skill_castend_nodamage_id(src,src,TF_HIDING,1,tick,0); - break; - - case LG_OVERBRAND: { - int width;//according to data from irowiki it actually is a square - for (width = 0; width < 7; width++) - for (i = 0; i < 7; i++) - map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, LG_OVERBRAND_BRANDISH, skilllv, tick, flag|BCT_ENEMY,skill_castend_damage_id); - for (width = 0; width < 7; width++) - for (i = 0; i < 7; i++) - map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY,skill_castend_damage_id); - } - break; - - case LG_BANDING: - if (sc && sc->data[SC_BANDING]) - status_change_end(src,SC_BANDING,INVALID_TIMER); - else if ((sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0)) != NULL) { - sc_start4(src,SC_BANDING,100,skilllv,0,0,sg->group_id,skill_get_time(skillid,skilllv)); - if (sd) pc_banding(sd,skilllv); - } - clif_skill_nodamage(src,src,skillid,skilllv,1); - break; - - case LG_RAYOFGENESIS: - if (status_charge(src,status_get_max_hp(src)*3*skilllv / 100,0)) { - i = skill_get_splash(skillid,skilllv); - map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), - src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - } else if (sd) - clif_skill_fail(sd,skillid,USESKILL_FAIL,0); - break; - - case WM_DOMINION_IMPULSE: - i = skill_get_splash(skillid, skilllv); - map_foreachinarea(skill_ative_reverberation, - src->m, x-i, y-i, x+i,y+i,BL_SKILL); - break; - - case WM_GREAT_ECHO: - flag|=1; // Should counsume 1 item per skill usage. - map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY, skill_castend_damage_id); - break; - case GN_CRAZYWEED: { - int area = skill_get_splash(GN_CRAZYWEED_ATK, skilllv); - short x1 = 0, y1 = 0; - - for (i = 0; i < 3 + (skilllv/2); i++) { - x1 = x - area + rnd()%(area * 2 + 1); - y1 = y - area + rnd()%(area * 2 + 1); - skill_addtimerskill(src,tick+i*150,0,x1,y1,GN_CRAZYWEED_ATK,skilllv,-1,0); - } - } - break; - case GN_FIRE_EXPANSION: { - int i; - struct unit_data *ud = unit_bl2ud(src); - - if (!ud) break; - - for (i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i]; i ++) { - if (ud->skillunit[i]->skill_id == GN_DEMONIC_FIRE && - distance_xy(x, y, ud->skillunit[i]->unit->bl.x, ud->skillunit[i]->unit->bl.y) < 4) { - switch (skilllv) { - case 3: - ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_SMOKE_POWDER; - clif_changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_SMOKE_POWDER); - break; - case 4: - ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_TEAR_GAS; - clif_changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_TEAR_GAS); - break; - case 5: - map_foreachinarea(skill_area_sub, src->m, - ud->skillunit[i]->unit->bl.x - 3, ud->skillunit[i]->unit->bl.y - 3, - ud->skillunit[i]->unit->bl.x + 3, ud->skillunit[i]->unit->bl.y + 3, BL_CHAR, - src, CR_ACIDDEMONSTRATION, sd ? pc_checkskill(sd, CR_ACIDDEMONSTRATION) : skilllv, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill_castend_damage_id); - skill_delunit(ud->skillunit[i]->unit); - break; - default: - ud->skillunit[i]->unit->val2 = skilllv; - ud->skillunit[i]->unit->group->val2 = skilllv; - break; - } - } - } - } - break; - - case SO_FIREWALK: - case SO_ELECTRICWALK: - if (sc && sc->data[type]) - status_change_end(src,type,INVALID_TIMER); - clif_skill_nodamage(src, src ,skillid, skilllv, - sc_start2(src, type, 100, skillid, skilllv, skill_get_time(skillid, skilllv))); - break; - - case SC_BLOODYLUST: //set in another group so instance will move if recasted + if (sd) + skill_blockpc_start (sd, MO_EXTREMITYFIST, 2000); + } + break; + case NJ_SHADOWJUMP: + if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground ) { //You don't move on GVG grounds. + unit_movepos(src, x, y, 1, 0); + clif_slide(src,x,y); + } + status_change_end(src, SC_HIDING, INVALID_TIMER); + break; + case AM_SPHEREMINE: + case AM_CANNIBALIZE: + { + int summons[5] = { 1589, 1579, 1575, 1555, 1590 }; + //int summons[5] = { 1020, 1068, 1118, 1500, 1368 }; + int class_ = skillid==AM_SPHEREMINE?1142:summons[skilllv-1]; + struct mob_data *md; + + // Correct info, don't change any of this! [celest] + md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE); + if (md) { + md->master_id = src->id; + md->special_state.ai = (skillid == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA; + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer (gettick() + skill_get_time(skillid,skilllv), mob_timer_delete, md->bl.id, 0); + mob_spawn (md); //Now it is ready for spawning. + } + } + break; + + // Slim Pitcher [Celest] + case CR_SLIMPITCHER: + if (sd) { + 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,USESKILL_FAIL_LEVEL,0); + return 1; + } + potion_flag = 1; + potion_hp = 0; + potion_sp = 0; + run_script(sd->inventory_data[j]->script,0,sd->bl.id,0); + potion_flag = 0; + //Apply skill bonuses + i = pc_checkskill(sd,CR_SLIMPITCHER)*10 + + pc_checkskill(sd,AM_POTIONPITCHER)*10 + + pc_checkskill(sd,AM_LEARNINGPOTION)*5 + + pc_skillheal_bonus(sd, skillid); + + potion_hp = potion_hp * (100+i)/100; + potion_sp = potion_sp * (100+i)/100; + + if(potion_hp > 0 || potion_sp > 0) { + i = skill_get_splash(skillid, skilllv); + map_foreachinarea(skill_area_sub, + src->m,x-i,y-i,x+i,y+i,BL_CHAR, + src,skillid,skilllv,tick,flag|BCT_PARTY|BCT_GUILD|1, + skill_castend_nodamage_id); + } + } else { + int i = skilllv%11 - 1; + struct item_data *item; + i = skill_db[skillid].itemid[i]; + item = itemdb_search(i); + potion_flag = 1; + potion_hp = 0; + potion_sp = 0; + run_script(item->script,0,src->id,0); + potion_flag = 0; + i = skill_get_max(CR_SLIMPITCHER)*10; + + potion_hp = potion_hp * (100+i)/100; + potion_sp = potion_sp * (100+i)/100; + + if(potion_hp > 0 || potion_sp > 0) { + i = skill_get_splash(skillid, skilllv); + map_foreachinarea(skill_area_sub, + src->m,x-i,y-i,x+i,y+i,BL_CHAR, + src,skillid,skilllv,tick,flag|BCT_PARTY|BCT_GUILD|1, + skill_castend_nodamage_id); + } + } + break; + + case HW_GANBANTEIN: + if (rnd()%100 < 80) { + int dummy = 1; + clif_skill_poseffect(src,skillid,skilllv,x,y,tick); + i = skill_get_splash(skillid, skilllv); + map_foreachinarea(skill_cell_overlap, src->m, x-i, y-i, x+i, y+i, BL_SKILL, HW_GANBANTEIN, &dummy, src); + } else { + if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + return 1; + } + break; + + case HW_GRAVITATION: + if ((sg = skill_unitsetting(src,skillid,skilllv,x,y,0))) + sc_start4(src,type,100,skilllv,0,BCT_SELF,sg->group_id,skill_get_time(skillid,skilllv)); + flag|=1; + break; + + // Plant Cultivation [Celest] + case CR_CULTIVATION: + if (sd) { + if( map_count_oncell(src->m,x,y,BL_CHAR) > 0 ) + { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + return 1; + } + clif_skill_poseffect(src,skillid,skilllv,x,y,tick); + if (rnd()%100 < 50) { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + } else { + TBL_MOB* md = mob_once_spawn_sub(src, src->m, x, y, "--ja--",(skilllv < 2 ? 1084+rnd()%2 : 1078+rnd()%6),"", SZ_SMALL, AI_NONE); + int i; + if (!md) break; + if ((i = skill_get_time(skillid, skilllv)) > 0) + { + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer (tick + i, mob_timer_delete, md->bl.id, 0); + } + mob_spawn (md); + } + } + break; + + case SG_SUN_WARM: + case SG_MOON_WARM: + case SG_STAR_WARM: + skill_clear_unitgroup(src); + if ((sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0))) + sc_start4(src,type,100,skilllv,0,0,sg->group_id,skill_get_time(skillid,skilllv)); + flag|=1; + break; + + case PA_GOSPEL: + if (sce && sce->val4 == BCT_SELF) + { + status_change_end(src, SC_GOSPEL, INVALID_TIMER); + return 0; + } + else + { + sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0); + if (!sg) break; + if (sce) + status_change_end(src, type, INVALID_TIMER); //Was under someone else's Gospel. [Skotlex] + sc_start4(src,type,100,skilllv,0,sg->group_id,BCT_SELF,skill_get_time(skillid,skilllv)); + clif_skill_poseffect(src, skillid, skilllv, 0, 0, tick); // PA_GOSPEL music packet + } + break; + case NJ_TATAMIGAESHI: + if (skill_unitsetting(src,skillid,skilllv,src->x,src->y,0)) + sc_start(src,type,100,skilllv,skill_get_time2(skillid,skilllv)); + break; + + case AM_RESURRECTHOMUN: //[orn] + if (sd) + { + if (!merc_resurrect_homunculus(sd, 20*skilllv, x, y)) + { + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + } + } + break; + + case NC_COLDSLOWER: + case NC_ARMSCANNON: + case RK_DRAGONBREATH: + case RK_WINDCUTTER: + case WM_LULLABY_DEEPSLEEP: + i = skill_get_splash(skillid,skilllv); + map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), + src,skillid,skilllv,tick,flag|(skillid==WM_LULLABY_DEEPSLEEP?BCT_ALL:BCT_ENEMY)|1,skill_castend_damage_id); + break; + /** + * Guilotine Cross + **/ + case GC_POISONSMOKE: + if( !(sc && sc->data[SC_POISONINGWEAPON]) ) { + if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_GC_POISONINGWEAPON,0); + return 0; + } + clif_skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skillid,skilllv,6); + skill_unitsetting(src, skillid, skilllv, x, y, flag); + //status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER); // 08/31/2011 - When using poison smoke, you no longer lose the poisoning weapon effect. + break; + /** + * Arch Bishop + **/ + case AB_EPICLESIS: + if( (sg = skill_unitsetting(src, skillid, skilllv, x, y, 0)) ) { + i = sg->unit->range; + map_foreachinarea(skill_area_sub, src->m, x - i, y - i, x + i, y + i, BL_CHAR, src, ALL_RESURRECTION, 1, tick, flag|BCT_NOENEMY|1,skill_castend_nodamage_id); + } + break; + /** + * Warlock + **/ + case WL_COMET: + if( sc ) { + sc->comet_x = x; + sc->comet_y = y; + } + i = skill_get_splash(skillid,skilllv); + map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + break; + + case WL_EARTHSTRAIN: + { + int i, wave = skilllv + 4, dir = map_calc_dir(src,x,y); + int sx = x = src->x, sy = y = src->y; // Store first caster's location to avoid glitch on unit setting + + for( i = 1; i <= wave; i++ ) + { + switch( dir ){ + case 0: case 1: case 7: sy = y + i; break; + case 3: case 4: case 5: sy = y - i; break; + case 2: sx = x - i; break; + case 6: sx = x + i; break; + } + skill_addtimerskill(src,gettick() + (150 * i),0,sx,sy,skillid,skilllv,dir,flag&2); + } + } + break; + /** + * Ranger + **/ + case RA_DETONATOR: + i = skill_get_splash(skillid, skilllv); + map_foreachinarea(skill_detonator, src->m, x-i, y-i, x+i, y+i, BL_SKILL, src); + clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + break; + /** + * Mechanic + **/ + case NC_NEUTRALBARRIER: + case NC_STEALTHFIELD: + skill_clear_unitgroup(src); // To remove previous skills - cannot used combined + if( (sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0)) != NULL ) { + sc_start2(src,skillid == NC_NEUTRALBARRIER ? SC_NEUTRALBARRIER_MASTER : SC_STEALTHFIELD_MASTER,100,skilllv,sg->group_id,skill_get_time(skillid,skilllv)); + if( sd ) pc_overheat(sd,1); + } + break; + + case NC_SILVERSNIPER: + { + int class_ = 2042; + struct mob_data *md; + + md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE); + if( md ) + { + md->master_id = src->id; + md->special_state.ai = AI_FLORA; + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer (gettick() + skill_get_time(skillid, skilllv), mob_timer_delete, md->bl.id, 0); + mob_spawn( md ); + } + } + break; + + case NC_MAGICDECOY: + if( sd ) clif_magicdecoy_list(sd,skilllv,x,y); + break; + + case SC_FEINTBOMB: + clif_skill_nodamage(src,src,skillid,skilllv,1); + skill_unitsetting(src,skillid,skilllv,x,y,0); // Set bomb on current Position + if( skill_blown(src,src,6,unit_getdir(src),0) ) + skill_castend_nodamage_id(src,src,TF_HIDING,1,tick,0); + break; + + case LG_OVERBRAND: + { + int width;//according to data from irowiki it actually is a square + for( width = 0; width < 7; width++ ) + for( i = 0; i < 7; i++ ) + map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, LG_OVERBRAND_BRANDISH, skilllv, tick, flag|BCT_ENEMY,skill_castend_damage_id); + for( width = 0; width < 7; width++ ) + for( i = 0; i < 7; i++ ) + map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY,skill_castend_damage_id); + } + break; + + case LG_BANDING: + if( sc && sc->data[SC_BANDING] ) + status_change_end(src,SC_BANDING,INVALID_TIMER); + else if( (sg = skill_unitsetting(src,skillid,skilllv,src->x,src->y,0)) != NULL ) { + sc_start4(src,SC_BANDING,100,skilllv,0,0,sg->group_id,skill_get_time(skillid,skilllv)); + if( sd ) pc_banding(sd,skilllv); + } + clif_skill_nodamage(src,src,skillid,skilllv,1); + break; + + case LG_RAYOFGENESIS: + if( status_charge(src,status_get_max_hp(src)*3*skilllv / 100,0) ) { + i = skill_get_splash(skillid,skilllv); + map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), + src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); + } else if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL,0); + break; + + case WM_DOMINION_IMPULSE: + i = skill_get_splash(skillid, skilllv); + map_foreachinarea( skill_ative_reverberation, + src->m, x-i, y-i, x+i,y+i,BL_SKILL); + break; + + case WM_GREAT_ECHO: + flag|=1; // Should counsume 1 item per skill usage. + map_foreachinrange(skill_area_sub, src, skill_get_splash(skillid,skilllv),splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY, skill_castend_damage_id); + break; + case GN_CRAZYWEED: { + int area = skill_get_splash(GN_CRAZYWEED_ATK, skilllv); + short x1 = 0, y1 = 0; + + for( i = 0; i < 3 + (skilllv/2); i++ ) { + x1 = x - area + rnd()%(area * 2 + 1); + y1 = y - area + rnd()%(area * 2 + 1); + skill_addtimerskill(src,tick+i*150,0,x1,y1,GN_CRAZYWEED_ATK,skilllv,-1,0); + } + } + break; + case GN_FIRE_EXPANSION: { + int i; + struct unit_data *ud = unit_bl2ud(src); + + if( !ud ) break; + + for( i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i]; i ++ ) { + if( ud->skillunit[i]->skill_id == GN_DEMONIC_FIRE && + distance_xy(x, y, ud->skillunit[i]->unit->bl.x, ud->skillunit[i]->unit->bl.y) < 4 ) { + switch( skilllv ) { + case 3: + ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_SMOKE_POWDER; + clif_changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_SMOKE_POWDER); + break; + case 4: + ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_TEAR_GAS; + clif_changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_TEAR_GAS); + break; + case 5: + map_foreachinarea(skill_area_sub, src->m, + ud->skillunit[i]->unit->bl.x - 3, ud->skillunit[i]->unit->bl.y - 3, + ud->skillunit[i]->unit->bl.x + 3, ud->skillunit[i]->unit->bl.y + 3, BL_CHAR, + src, CR_ACIDDEMONSTRATION, sd ? pc_checkskill(sd, CR_ACIDDEMONSTRATION) : skilllv, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill_castend_damage_id); + skill_delunit(ud->skillunit[i]->unit); + break; + default: + ud->skillunit[i]->unit->val2 = skilllv; + ud->skillunit[i]->unit->group->val2 = skilllv; + break; + } + } + } + } + break; + + case SO_FIREWALK: + case SO_ELECTRICWALK: + if( sc && sc->data[type] ) + status_change_end(src,type,INVALID_TIMER); + clif_skill_nodamage(src, src ,skillid, skilllv, + sc_start2(src, type, 100, skillid, skilllv, skill_get_time(skillid, skilllv))); + break; + + case SC_BLOODYLUST: //set in another group so instance will move if recasted flag |= 33; skill_unitsetting(src, skillid, skilllv, x, y, 0); break; - case KO_MAKIBISHI: - for (i = 0; i < (skilllv+2); i++) { - x = src->x - 1 + rnd()%3; - y = src->y - 1 + rnd()%3; - skill_unitsetting(src,skillid,skilllv,x,y,0); - } - break; + case KO_MAKIBISHI: + for( i = 0; i < (skilllv+2); i++ ) { + x = src->x - 1 + rnd()%3; + y = src->y - 1 + rnd()%3; + skill_unitsetting(src,skillid,skilllv,x,y,0); + } + break; - default: - ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid); - return 1; - } + default: + ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid); + return 1; + } - if (sc && sc->data[SC_CURSEDCIRCLE_ATKER]) //Should only remove after the skill has been casted. - status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); + if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] ) //Should only remove after the skill has been casted. + status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); - if (sd) { - // ensure that the skill last-cast tick is recorded - sd->canskill_tick = gettick(); + if( sd ) + {// ensure that the skill last-cast tick is recorded + sd->canskill_tick = gettick(); - if (sd->state.arrow_atk && !(flag&1)) { - // consume arrow if this is a ground skill - battle_consume_ammo(sd, skillid, skilllv); - } + if( sd->state.arrow_atk && !(flag&1) ) + {// consume arrow if this is a ground skill + battle_consume_ammo(sd, skillid, skilllv); + } - // perform skill requirement consumption - skill_consume_requirement(sd,skillid,skilllv,2); - } + // perform skill requirement consumption + skill_consume_requirement(sd,skillid,skilllv,2); + } - return 0; + return 0; } /*========================================== * *------------------------------------------*/ -int skill_castend_map(struct map_session_data *sd, short skill_num, const char *map) +int skill_castend_map (struct map_session_data *sd, short skill_num, const char *map) { - nullpo_ret(sd); + nullpo_ret(sd); - //Simplify skill_failed code. +//Simplify skill_failed code. #define skill_failed(sd) { sd->menuskill_id = sd->menuskill_val = 0; } - if (skill_num != sd->menuskill_id) - return 0; - - if (sd->bl.prev == NULL || pc_isdead(sd)) { - skill_failed(sd); - return 0; - } - - if ((sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING) || sd->sc.option&OPTION_HIDE) { - skill_failed(sd); - return 0; - } - if (sd->sc.count && ( - sd->sc.data[SC_SILENCE] || - sd->sc.data[SC_ROKISWEIL] || - sd->sc.data[SC_AUTOCOUNTER] || - sd->sc.data[SC_STEELBODY] || - (sd->sc.data[SC_DANCING] && skill_num < RK_ENCHANTBLADE && !pc_checkskill(sd, WM_LESSON)) || - sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - sd->sc.data[SC_BASILICA] || - sd->sc.data[SC_MARIONETTE] || - sd->sc.data[SC_WHITEIMPRISON] || - (sd->sc.data[SC_STASIS] && skill_block_check(&sd->bl, SC_STASIS, skill_num)) || - (sd->sc.data[SC_KAGEHUMI] && skill_block_check(&sd->bl, SC_KAGEHUMI, skill_num)) || - sd->sc.data[SC_OBLIVIONCURSE] || - sd->sc.data[SC__MANHOLE] || - (sd->sc.data[SC_ASH] && rnd()%2) //50% fail chance under ASH - )) { - skill_failed(sd); - return 0; - } - - pc_stop_attack(sd); - pc_stop_walking(sd,0); - - if (battle_config.skill_log && battle_config.skill_log&BL_PC) - ShowInfo("PC %d skill castend skill =%d map=%s\n",sd->bl.id,skill_num,map); - - if (strcmp(map,"cancel")==0) { - skill_failed(sd); - return 0; - } - - switch (skill_num) { - case AL_TELEPORT: - if (strcmp(map,"Random")==0) - pc_randomwarp(sd,CLR_TELEPORT); - else if (sd->menuskill_val > 1) //Need lv2 to be able to warp here. - pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - break; + if(skill_num != sd->menuskill_id) + return 0; - case AL_WARP: { - const struct point *p[4]; - struct skill_unit_group *group; - int i, lv, wx, wy; - int maxcount=0; - int x,y; - unsigned short mapindex; - - mapindex = mapindex_name2id((char *)map); - if (!mapindex) { //Given map not found? - clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); - skill_failed(sd); - return 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(skill_num, sd->menuskill_val)) > 0) { - for (i=0; i<MAX_SKILLUNITGROUP && sd->ud.skillunit[i] && maxcount; i++) { - if (sd->ud.skillunit[i]->skill_id == skill_num) - maxcount--; - } - if (!maxcount) { - clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); - skill_failed(sd); - return 0; - } - } + if( sd->bl.prev == NULL || pc_isdead(sd) ) { + skill_failed(sd); + return 0; + } - lv = sd->skillitem==skill_num?sd->skillitemlv:pc_checkskill(sd,skill_num); - wx = sd->menuskill_val>>16; - wy = sd->menuskill_val&0xffff; - - if (lv <= 0) return 0; - if (lv > 4) lv = 4; // crash prevention - - // check if the chosen map exists in the memo list - ARR_FIND(0, lv, i, mapindex == p[i]->map); - if (i < lv) { - x=p[i]->x; - y=p[i]->y; - } else { - skill_failed(sd); - return 0; - } + if( ( sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING ) || sd->sc.option&OPTION_HIDE ) { + skill_failed(sd); + return 0; + } + if(sd->sc.count && ( + sd->sc.data[SC_SILENCE] || + sd->sc.data[SC_ROKISWEIL] || + sd->sc.data[SC_AUTOCOUNTER] || + sd->sc.data[SC_STEELBODY] || + (sd->sc.data[SC_DANCING] && skill_num < RK_ENCHANTBLADE && !pc_checkskill(sd, WM_LESSON)) || + sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || + sd->sc.data[SC_BASILICA] || + sd->sc.data[SC_MARIONETTE] || + sd->sc.data[SC_WHITEIMPRISON] || + (sd->sc.data[SC_STASIS] && skill_block_check(&sd->bl, SC_STASIS, skill_num)) || + (sd->sc.data[SC_KAGEHUMI] && skill_block_check(&sd->bl, SC_KAGEHUMI, skill_num)) || + sd->sc.data[SC_OBLIVIONCURSE] || + sd->sc.data[SC__MANHOLE] || + (sd->sc.data[SC_ASH] && rnd()%2) //50% fail chance under ASH + )) { + skill_failed(sd); + return 0; + } - if (!skill_check_condition_castend(sd, sd->menuskill_id, lv)) { - // This checks versus skillid/skilllv... - skill_failed(sd); - return 0; - } + pc_stop_attack(sd); + pc_stop_walking(sd,0); - skill_consume_requirement(sd,sd->menuskill_id,lv,2); - sd->skillitem = sd->skillitemlv = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish] + if(battle_config.skill_log && battle_config.skill_log&BL_PC) + ShowInfo("PC %d skill castend skill =%d map=%s\n",sd->bl.id,skill_num,map); - if ((group=skill_unitsetting(&sd->bl,skill_num,lv,wx,wy,0))==NULL) { - skill_failed(sd); - return 0; - } + if(strcmp(map,"cancel")==0) { + skill_failed(sd); + return 0; + } - group->val1 = (group->val1<<16)|(short)0; - // record the destination coordinates - group->val2 = (x<<16)|y; - group->val3 = mapindex; - } - break; - } + switch(skill_num) + { + case AL_TELEPORT: + if(strcmp(map,"Random")==0) + pc_randomwarp(sd,CLR_TELEPORT); + else if (sd->menuskill_val > 1) //Need lv2 to be able to warp here. + pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + break; + + case AL_WARP: + { + const struct point *p[4]; + struct skill_unit_group *group; + int i, lv, wx, wy; + int maxcount=0; + int x,y; + unsigned short mapindex; + + mapindex = mapindex_name2id((char*)map); + if(!mapindex) { //Given map not found? + clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); + skill_failed(sd); + return 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(skill_num, sd->menuskill_val)) > 0) { + for(i=0;i<MAX_SKILLUNITGROUP && sd->ud.skillunit[i] && maxcount;i++) { + if(sd->ud.skillunit[i]->skill_id == skill_num) + maxcount--; + } + if(!maxcount) { + clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); + skill_failed(sd); + return 0; + } + } + + lv = sd->skillitem==skill_num?sd->skillitemlv:pc_checkskill(sd,skill_num); + wx = sd->menuskill_val>>16; + wy = sd->menuskill_val&0xffff; + + if( lv <= 0 ) return 0; + if( lv > 4 ) lv = 4; // crash prevention + + // check if the chosen map exists in the memo list + ARR_FIND( 0, lv, i, mapindex == p[i]->map ); + if( i < lv ) { + x=p[i]->x; + y=p[i]->y; + } else { + skill_failed(sd); + return 0; + } + + if(!skill_check_condition_castend(sd, sd->menuskill_id, lv)) + { // This checks versus skillid/skilllv... + skill_failed(sd); + return 0; + } - sd->menuskill_id = sd->menuskill_val = 0; - return 0; + skill_consume_requirement(sd,sd->menuskill_id,lv,2); + sd->skillitem = sd->skillitemlv = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish] + + if((group=skill_unitsetting(&sd->bl,skill_num,lv,wx,wy,0))==NULL) { + skill_failed(sd); + return 0; + } + + group->val1 = (group->val1<<16)|(short)0; + // record the destination coordinates + group->val2 = (x<<16)|y; + group->val3 = mapindex; + } + break; + } + + sd->menuskill_id = sd->menuskill_val = 0; + return 0; #undef skill_failed } /// transforms 'target' skill unit into dissonance (if conditions are met) -static int skill_dance_overlap_sub(struct block_list *bl, va_list ap) +static int skill_dance_overlap_sub(struct block_list* bl, va_list ap) { - struct skill_unit *target = (struct skill_unit *)bl; - struct skill_unit *src = va_arg(ap, struct skill_unit *); - int flag = va_arg(ap, int); + struct skill_unit* target = (struct skill_unit*)bl; + struct skill_unit* src = va_arg(ap, struct skill_unit*); + int flag = va_arg(ap, int); - if (src == target) - return 0; - if (!target->group || !(target->group->state.song_dance&0x1)) - return 0; - if (!(target->val2 & src->val2 & ~UF_ENSEMBLE)) //They don't match (song + dance) is valid. - return 0; + if (src == target) + return 0; + if (!target->group || !(target->group->state.song_dance&0x1)) + return 0; + if (!(target->val2 & src->val2 & ~UF_ENSEMBLE)) //They don't match (song + dance) is valid. + return 0; - if (flag) //Set dissonance - target->val2 |= UF_ENSEMBLE; //Add ensemble to signal this unit is overlapping. - else //Remove dissonance - target->val2 &= ~UF_ENSEMBLE; + if (flag) //Set dissonance + target->val2 |= UF_ENSEMBLE; //Add ensemble to signal this unit is overlapping. + else //Remove dissonance + target->val2 &= ~UF_ENSEMBLE; - clif_skill_setunit(target); //Update look of affected cell. + clif_skill_setunit(target); //Update look of affected cell. - return 1; + return 1; } //Does the song/dance overlapping -> dissonance check. [Skotlex] //When flag is 0, this unit is about to be removed, cancel the dissonance effect //When 1, this unit has been positioned, so start the cancel effect. -int skill_dance_overlap(struct skill_unit *unit, int flag) +int skill_dance_overlap(struct skill_unit* unit, int flag) { - if (!unit || !unit->group || !(unit->group->state.song_dance&0x1)) - return 0; - if (!flag && !(unit->val2&UF_ENSEMBLE)) - return 0; //Nothing to remove, this unit is not overlapped. - - if (unit->val1 != unit->group->skill_id) { - //Reset state - unit->val1 = unit->group->skill_id; - unit->val2 &= ~UF_ENSEMBLE; - } - - return map_foreachincell(skill_dance_overlap_sub, unit->bl.m,unit->bl.x,unit->bl.y,BL_SKILL, unit,flag); + if (!unit || !unit->group || !(unit->group->state.song_dance&0x1)) + return 0; + if (!flag && !(unit->val2&UF_ENSEMBLE)) + return 0; //Nothing to remove, this unit is not overlapped. + + if (unit->val1 != unit->group->skill_id) + { //Reset state + unit->val1 = unit->group->skill_id; + unit->val2 &= ~UF_ENSEMBLE; + } + + return map_foreachincell(skill_dance_overlap_sub, unit->bl.m,unit->bl.x,unit->bl.y,BL_SKILL, unit,flag); } /*========================================== * Converts this group information so that it is handled as a Dissonance or Ugly Dance cell. * Flag: 0 - Convert, 1 - Revert. *------------------------------------------*/ -static bool skill_dance_switch(struct skill_unit *unit, int flag) +static bool skill_dance_switch(struct skill_unit* unit, int flag) { - static int prevflag = 1; // by default the backup is empty - static struct skill_unit_group backup; - struct skill_unit_group *group = unit->group; - - // val2&UF_ENSEMBLE is a hack to indicate dissonance - if (!(group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE)) - return false; - - if (flag == prevflag) { - // protection against attempts to read an empty backup / write to a full backup - ShowError("skill_dance_switch: Attempted to %s (skill_id=%d, skill_lv=%d, src_id=%d).\n", - flag ? "read an empty backup" : "write to a full backup", - group->skill_id, group->skill_lv, group->src_id); - return false; - } - prevflag = flag; - - if (!flag) { - //Transform - int skillid = unit->val2&UF_SONG ? BA_DISSONANCE : DC_UGLYDANCE; - - // backup - backup.skill_id = group->skill_id; - backup.skill_lv = group->skill_lv; - backup.unit_id = group->unit_id; - backup.target_flag = group->target_flag; - backup.bl_flag = group->bl_flag; - backup.interval = group->interval; - - // replace - group->skill_id = skillid; - group->skill_lv = 1; - group->unit_id = skill_get_unit_id(skillid,0); - group->target_flag = skill_get_unit_target(skillid); - group->bl_flag = skill_get_unit_bl_target(skillid); - group->interval = skill_get_unit_interval(skillid); - } else { - //Restore - group->skill_id = backup.skill_id; - group->skill_lv = backup.skill_lv; - group->unit_id = backup.unit_id; - group->target_flag = backup.target_flag; - group->bl_flag = backup.bl_flag; - group->interval = backup.interval; - } - - return true; + static int prevflag = 1; // by default the backup is empty + static struct skill_unit_group backup; + struct skill_unit_group* group = unit->group; + + // val2&UF_ENSEMBLE is a hack to indicate dissonance + if ( !(group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE) ) + return false; + + if( flag == prevflag ) + {// protection against attempts to read an empty backup / write to a full backup + ShowError("skill_dance_switch: Attempted to %s (skill_id=%d, skill_lv=%d, src_id=%d).\n", + flag ? "read an empty backup" : "write to a full backup", + group->skill_id, group->skill_lv, group->src_id); + return false; + } + prevflag = flag; + + if( !flag ) + { //Transform + int skillid = unit->val2&UF_SONG ? BA_DISSONANCE : DC_UGLYDANCE; + + // backup + backup.skill_id = group->skill_id; + backup.skill_lv = group->skill_lv; + backup.unit_id = group->unit_id; + backup.target_flag = group->target_flag; + backup.bl_flag = group->bl_flag; + backup.interval = group->interval; + + // replace + group->skill_id = skillid; + group->skill_lv = 1; + group->unit_id = skill_get_unit_id(skillid,0); + group->target_flag = skill_get_unit_target(skillid); + group->bl_flag = skill_get_unit_bl_target(skillid); + group->interval = skill_get_unit_interval(skillid); + } + else + { //Restore + group->skill_id = backup.skill_id; + group->skill_lv = backup.skill_lv; + group->unit_id = backup.unit_id; + group->target_flag = backup.target_flag; + group->bl_flag = backup.bl_flag; + group->interval = backup.interval; + } + + return true; } /** * Upon Ice Wall cast it checks all nearby mobs to find any who may be blocked by the IW **/ -static int skill_icewall_block(struct block_list *bl,va_list ap) -{ - struct block_list *target = NULL; - struct mob_data *md = ((TBL_MOB *)bl); +static int skill_icewall_block(struct block_list *bl,va_list ap) { + struct block_list *target = NULL; + struct mob_data *md = ((TBL_MOB*)bl); - nullpo_ret(bl); - nullpo_ret(md); - if (!md->target_id || (target = map_id2bl(md->target_id)) == NULL) - return 0; + nullpo_ret(bl); + nullpo_ret(md); + if( !md->target_id || ( target = map_id2bl(md->target_id) ) == NULL ) + return 0; - if (path_search_long(NULL,bl->m,bl->x,bl->y,target->x,target->y,CELL_CHKICEWALL)) - return 0; + if( path_search_long(NULL,bl->m,bl->x,bl->y,target->x,target->y,CELL_CHKICEWALL) ) + return 0; - if (!check_distance_bl(bl, target, status_get_range(bl))) { - mob_unlocktarget(md,gettick()); - mob_stop_walking(md,1); - } + if( !check_distance_bl(bl, target, status_get_range(bl) ) ) { + mob_unlocktarget(md,gettick()); + mob_stop_walking(md,1); + } - return 0; + return 0; } /*========================================== * Initializes and sets a ground skill. * flag&1 is used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active) *------------------------------------------*/ -struct skill_unit_group *skill_unitsetting(struct block_list *src, short skillid, short skilllv, short x, short y, int flag) { - struct skill_unit_group *group; - int i,limit,val1=0,val2=0,val3=0; - int target,interval,range,unit_flag,req_item=0; - struct s_skill_unit_layout *layout; - struct map_session_data *sd; - struct status_data *status; - struct status_change *sc; - int active_flag=1; - int subunt=0; - - nullpo_retr(NULL, src); - - limit = skill_get_time(skillid,skilllv); - range = skill_get_unit_range(skillid,skilllv); - 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); - - sd = BL_CAST(BL_PC, src); - status = status_get_status_data(src); - sc = status_get_sc(src); // for traps, firewall and fogwall - celest - - switch (skillid) { - case MH_STEINWAND: - val2 = 4 + skilllv; //nb of attack blocked - break; - case MG_SAFETYWALL: -#ifdef RENEWAL - /** - * According to data provided in RE, SW life is equal to 3 times caster's health - **/ - val2 = status_get_max_hp(src) * 3; -#else - val2 = skilllv+1; -#endif - break; - case MG_FIREWALL: - if (sc && sc->data[SC_VIOLENTGALE]) - limit = limit*3/2; - val2=4+skilllv; - break; - - case AL_WARP: - val1=skilllv+6; - if (!(flag&1)) - limit=2000; - else { // previous implementation (not used anymore) - //Warp Portal morphing to active mode, extract relevant data from src. [Skotlex] - if (src->type != BL_SKILL) return NULL; - group = ((TBL_SKILL *)src)->group; - src = map_id2bl(group->src_id); - if (!src) return NULL; - val2 = group->val2; //Copy the (x,y) position you warp to - val3 = group->val3; //as well as the mapindex to warp to. - } - break; - case HP_BASILICA: - val1 = src->id; // Store caster id. - break; - - case PR_SANCTUARY: - case NPC_EVILLAND: - val1=(skilllv+3)*2; - break; +struct skill_unit_group* skill_unitsetting (struct block_list *src, short skillid, short skilllv, short x, short y, int flag) +{ + struct skill_unit_group *group; + int i,limit,val1=0,val2=0,val3=0; + int target,interval,range,unit_flag,req_item=0; + struct s_skill_unit_layout *layout; + struct map_session_data *sd; + struct status_data *status; + struct status_change *sc; + int active_flag=1; + int subunt=0; + + nullpo_retr(NULL, src); + + limit = skill_get_time(skillid,skilllv); + range = skill_get_unit_range(skillid,skilllv); + 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); + + sd = BL_CAST(BL_PC, src); + status = status_get_status_data(src); + sc = status_get_sc(src); // for traps, firewall and fogwall - celest + + switch( skillid ) { + case MH_STEINWAND: + val2 = 4 + skilllv; //nb of attack blocked + break; + case MG_SAFETYWALL: + #ifdef RENEWAL + /** + * According to data provided in RE, SW life is equal to 3 times caster's health + **/ + val2 = status_get_max_hp(src) * 3; + #else + val2 = skilllv+1; + #endif + break; + case MG_FIREWALL: + if(sc && sc->data[SC_VIOLENTGALE]) + limit = limit*3/2; + val2=4+skilllv; + break; + + case AL_WARP: + val1=skilllv+6; + if(!(flag&1)) + limit=2000; + else // previous implementation (not used anymore) + { //Warp Portal morphing to active mode, extract relevant data from src. [Skotlex] + if( src->type != BL_SKILL ) return NULL; + group = ((TBL_SKILL*)src)->group; + src = map_id2bl(group->src_id); + if( !src ) return NULL; + val2 = group->val2; //Copy the (x,y) position you warp to + val3 = group->val3; //as well as the mapindex to warp to. + } + break; + case HP_BASILICA: + val1 = src->id; // Store caster id. + break; + + case PR_SANCTUARY: + case NPC_EVILLAND: + val1=(skilllv+3)*2; + break; + + case WZ_FIREPILLAR: + if((flag&1)!=0) + limit=1000; + val1=skilllv+2; + break; + case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex] + case AM_DEMONSTRATION: + case GN_HELLS_PLANT: + if (map_flag_vs(src->m) && battle_config.vs_traps_bctall + && (src->type&battle_config.vs_traps_bctall)) + target = BCT_ALL; + break; + case HT_SHOCKWAVE: + val1=skilllv*15+10; + case HT_SANDMAN: + case MA_SANDMAN: + case HT_CLAYMORETRAP: + case HT_SKIDTRAP: + case MA_SKIDTRAP: + case HT_LANDMINE: + case MA_LANDMINE: + case HT_ANKLESNARE: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + case HT_BLASTMINE: + /** + * Ranger + **/ + case RA_ELECTRICSHOCKER: + case RA_CLUSTERBOMB: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + { + struct skill_condition req = skill_get_requirement(sd,skillid,skilllv); + ARR_FIND(0, MAX_SKILL_ITEM_REQUIRE, i, req.itemid[i] && (req.itemid[i] == ITEMID_TRAP || req.itemid[i] == ITEMID_TRAP_ALLOY)); + if( req.itemid[i] ) + req_item = req.itemid[i]; + if( map_flag_gvg(src->m) || map[src->m].flag.battleground ) + limit *= 4; // longer trap times in WOE [celest] + if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) ) + target = BCT_ALL; + } + break; + + case SA_LANDPROTECTOR: + case SA_VOLCANO: + case SA_DELUGE: + case SA_VIOLENTGALE: + { + struct skill_unit_group *old_sg; + if ((old_sg = skill_locate_element_field(src)) != NULL) + { //HelloKitty confirmed that these are interchangeable, + //so you can change element and not consume gemstones. + if (( + old_sg->skill_id == SA_VOLCANO || + old_sg->skill_id == SA_DELUGE || + old_sg->skill_id == SA_VIOLENTGALE + ) && old_sg->limit > 0) + { //Use the previous limit (minus the elapsed time) [Skotlex] + limit = old_sg->limit - DIFF_TICK(gettick(), old_sg->tick); + if (limit < 0) //This can happen... + limit = skill_get_time(skillid,skilllv); + } + skill_clear_group(src,1); + } + break; + } - case WZ_FIREPILLAR: - if ((flag&1)!=0) - limit=1000; - val1=skilllv+2; - break; - case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex] - case AM_DEMONSTRATION: - case GN_HELLS_PLANT: - if (map_flag_vs(src->m) && battle_config.vs_traps_bctall - && (src->type&battle_config.vs_traps_bctall)) - target = BCT_ALL; - break; - case HT_SHOCKWAVE: - val1=skilllv*15+10; - case HT_SANDMAN: - case MA_SANDMAN: - case HT_CLAYMORETRAP: - case HT_SKIDTRAP: - case MA_SKIDTRAP: - case HT_LANDMINE: - case MA_LANDMINE: - case HT_ANKLESNARE: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - case HT_BLASTMINE: - /** - * Ranger - **/ - case RA_ELECTRICSHOCKER: - case RA_CLUSTERBOMB: - case RA_MAGENTATRAP: - case RA_COBALTTRAP: - case RA_MAIZETRAP: - case RA_VERDURETRAP: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: { - struct skill_condition req = skill_get_requirement(sd,skillid,skilllv); - ARR_FIND(0, MAX_SKILL_ITEM_REQUIRE, i, req.itemid[i] && (req.itemid[i] == ITEMID_TRAP || req.itemid[i] == ITEMID_TRAP_ALLOY)); - if (req.itemid[i]) - req_item = req.itemid[i]; - if (map_flag_gvg(src->m) || map[src->m].flag.battleground) - limit *= 4; // longer trap times in WOE [celest] - if (battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall)) - target = BCT_ALL; - } - break; + case BA_DISSONANCE: + case DC_UGLYDANCE: + val1 = 10; //FIXME: This value is not used anywhere, what is it for? [Skotlex] + break; + case BA_WHISTLE: + val1 = skilllv +status->agi/10; // Flee increase + val2 = ((skilllv+1)/2)+status->luk/10; // Perfect dodge increase + if(sd){ + val1 += pc_checkskill(sd,BA_MUSICALLESSON); + val2 += pc_checkskill(sd,BA_MUSICALLESSON); + } + break; + case DC_HUMMING: + val1 = 2*skilllv+status->dex/10; // Hit increase + #ifdef RENEWAL + val1 *= 2; + #endif + if(sd) + val1 += pc_checkskill(sd,DC_DANCINGLESSON); + break; + case BA_POEMBRAGI: + val1 = 3*skilllv+status->dex/10; // Casting time reduction + //For some reason at level 10 the base delay reduction is 50%. + val2 = (skilllv<10?3*skilllv:50)+status->int_/5; // After-cast delay reduction + if(sd){ + val1 += 2*pc_checkskill(sd,BA_MUSICALLESSON); + val2 += 2*pc_checkskill(sd,BA_MUSICALLESSON); + } + break; + case DC_DONTFORGETME: + val1 = status->dex/10 + 3*skilllv + 5; // ASPD decrease + val2 = status->agi/10 + 3*skilllv + 5; // Movement speed adjustment. + if(sd){ + val1 += pc_checkskill(sd,DC_DANCINGLESSON); + val2 += pc_checkskill(sd,DC_DANCINGLESSON); + } + break; + case BA_APPLEIDUN: + val1 = 5+2*skilllv+status->vit/10; // MaxHP percent increase + if(sd) + val1 += pc_checkskill(sd,BA_MUSICALLESSON); + break; + case DC_SERVICEFORYOU: + val1 = 15+skilllv+(status->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed + val2 = 20+3*skilllv+(status->int_/10); // SP cost reduction + if(sd){ + val1 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO This bonus value is guessed + val2 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO Should be half this value + } + break; + case BA_ASSASSINCROSS: + val1 = 100+(10*skilllv)+(status->agi/10); // ASPD increase + if(sd) + val1 += 5*pc_checkskill(sd,BA_MUSICALLESSON); + break; + case DC_FORTUNEKISS: + val1 = 10+skilllv+(status->luk/10); // Critical increase + if(sd) + val1 += pc_checkskill(sd,DC_DANCINGLESSON); + val1*=10; //Because every 10 crit is an actual cri point. + break; + case BD_DRUMBATTLEFIELD: + #ifdef RENEWAL + val1 = (skilllv+5)*25; //Watk increase + val2 = skilllv*10; //Def increase + #else + val1 = (skilllv+1)*25; //Watk increase + val2 = (skilllv+1)*2; //Def increase + #endif + break; + case BD_RINGNIBELUNGEN: + val1 = (skilllv+2)*25; //Watk increase + break; + case BD_RICHMANKIM: + val1 = 25 + 11*skilllv; //Exp increase bonus. + break; + case BD_SIEGFRIED: + val1 = 55 + skilllv*5; //Elemental Resistance + val2 = skilllv*10; //Status ailment resistance + break; + case WE_CALLPARTNER: + if (sd) val1 = sd->status.partner_id; + break; + case WE_CALLPARENT: + if (sd) { + val1 = sd->status.father; + val2 = sd->status.mother; + } + break; + case WE_CALLBABY: + if (sd) val1 = sd->status.child; + break; + case NJ_KAENSIN: + skill_clear_group(src, 1); //Delete previous Kaensins/Suitons + val2 = (skilllv+1)/2 + 4; + break; + case NJ_SUITON: + skill_clear_group(src, 1); + break; + + case GS_GROUNDDRIFT: + { + int element[5]={ELE_WIND,ELE_DARK,ELE_POISON,ELE_WATER,ELE_FIRE}; + + val1 = status->rhw.ele; + if (!val1) + val1=element[rnd()%5]; + + switch (val1) + { + case ELE_FIRE: + subunt++; + case ELE_WATER: + subunt++; + case ELE_POISON: + subunt++; + case ELE_DARK: + subunt++; + case ELE_WIND: + break; + default: + subunt=rnd()%5; + break; + } + + break; + } + case GC_POISONSMOKE: + if( !(sc && sc->data[SC_POISONINGWEAPON]) ) + return NULL; + val2 = sc->data[SC_POISONINGWEAPON]->val2; // Type of Poison + val3 = sc->data[SC_POISONINGWEAPON]->val1; + limit = 4000 + 2000 * skilllv; + break; + case GD_LEADERSHIP: + case GD_GLORYWOUNDS: + case GD_SOULCOLD: + case GD_HAWKEYES: + limit = 1000000;//it doesn't matter + break; + case LG_BANDING: + limit = -1; + break; + case WM_REVERBERATION: + interval = limit; + val2 = 1; + case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector. + if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) + return NULL; + break; + case SO_CLOUD_KILL: + skill_clear_group(src, 4); + break; + case SO_WARMER: + skill_clear_group(src, 8); + break; + case SO_VACUUM_EXTREME: + range++; + + break; + case SC_BLOODYLUST: + skill_clear_group(src, 32); + break; + case GN_WALLOFTHORN: + if( flag&1 ) + limit = 3000; + val3 = (x<<16)|y; + break; + case KO_ZENKAI: + if( sd ){ + ARR_FIND(1, 6, i, sd->talisman[i] > 0); + if( i < 5 ){ + val1 = sd->talisman[i]; // no. of aura + val2 = i; // aura type + limit += val1 * 1000; + subunt = i - 1; + pc_del_talisman(sd, sd->talisman[i], i); + } + } + break; + } - case SA_LANDPROTECTOR: - case SA_VOLCANO: - case SA_DELUGE: - case SA_VIOLENTGALE: { - struct skill_unit_group *old_sg; - if ((old_sg = skill_locate_element_field(src)) != NULL) { - //HelloKitty confirmed that these are interchangeable, - //so you can change element and not consume gemstones. - if (( - old_sg->skill_id == SA_VOLCANO || - old_sg->skill_id == SA_DELUGE || - old_sg->skill_id == SA_VIOLENTGALE - ) && old_sg->limit > 0) { - //Use the previous limit (minus the elapsed time) [Skotlex] - limit = old_sg->limit - DIFF_TICK(gettick(), old_sg->tick); - if (limit < 0) //This can happen... - limit = skill_get_time(skillid,skilllv); - } - skill_clear_group(src,1); - } - break; - } + nullpo_retr(NULL, group=skill_initunitgroup(src,layout->count,skillid,skilllv,skill_get_unit_id(skillid,flag&1)+subunt, limit, interval)); + group->val1=val1; + group->val2=val2; + group->val3=val3; + group->target_flag=target; + group->bl_flag= skill_get_unit_bl_target(skillid); + group->state.ammo_consume = (sd && sd->state.arrow_atk && skillid != GS_GROUNDDRIFT); //Store if this skill needs to consume ammo. + group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)?1:0)|(unit_flag&UF_ENSEMBLE?2:0); //Signals if this is a song/dance/duet + group->state.guildaura = ( skillid >= GD_LEADERSHIP && skillid <= GD_HAWKEYES )?1:0; + group->item_id = req_item; + //if tick is greater than current, do not invoke onplace function just yet. [Skotlex] + if (DIFF_TICK(group->tick, gettick()) > SKILLUNITTIMER_INTERVAL) + active_flag = 0; + + if(skillid==HT_TALKIEBOX || skillid==RG_GRAFFITI){ + group->valstr=(char *) aMalloc(MESSAGE_SIZE*sizeof(char)); + if (sd) + safestrncpy(group->valstr, sd->message, MESSAGE_SIZE); + else //Eh... we have to write something here... even though mobs shouldn't use this. [Skotlex] + safestrncpy(group->valstr, "Boo!", MESSAGE_SIZE); + } - case BA_DISSONANCE: - case DC_UGLYDANCE: - val1 = 10; //FIXME: This value is not used anywhere, what is it for? [Skotlex] - break; - case BA_WHISTLE: - val1 = skilllv +status->agi/10; // Flee increase - val2 = ((skilllv+1)/2)+status->luk/10; // Perfect dodge increase - if (sd) { - val1 += pc_checkskill(sd,BA_MUSICALLESSON); - val2 += pc_checkskill(sd,BA_MUSICALLESSON); - } - break; - case DC_HUMMING: - val1 = 2*skilllv+status->dex/10; // Hit increase -#ifdef RENEWAL - val1 *= 2; -#endif - if (sd) - val1 += pc_checkskill(sd,DC_DANCINGLESSON); - break; - case BA_POEMBRAGI: - val1 = 3*skilllv+status->dex/10; // Casting time reduction - //For some reason at level 10 the base delay reduction is 50%. - val2 = (skilllv<10?3*skilllv:50)+status->int_/5; // After-cast delay reduction - if (sd) { - val1 += 2*pc_checkskill(sd,BA_MUSICALLESSON); - val2 += 2*pc_checkskill(sd,BA_MUSICALLESSON); - } - break; - case DC_DONTFORGETME: - val1 = status->dex/10 + 3*skilllv + 5; // ASPD decrease - val2 = status->agi/10 + 3*skilllv + 5; // Movement speed adjustment. - if (sd) { - val1 += pc_checkskill(sd,DC_DANCINGLESSON); - val2 += pc_checkskill(sd,DC_DANCINGLESSON); - } - break; - case BA_APPLEIDUN: - val1 = 5+2*skilllv+status->vit/10; // MaxHP percent increase - if (sd) - val1 += pc_checkskill(sd,BA_MUSICALLESSON); - break; - case DC_SERVICEFORYOU: - val1 = 15+skilllv+(status->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed - val2 = 20+3*skilllv+(status->int_/10); // SP cost reduction - if (sd) { - val1 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO This bonus value is guessed - val2 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO Should be half this value - } - break; - case BA_ASSASSINCROSS: - val1 = 100+(10*skilllv)+(status->agi/10); // ASPD increase - if (sd) - val1 += 5*pc_checkskill(sd,BA_MUSICALLESSON); - break; - case DC_FORTUNEKISS: - val1 = 10+skilllv+(status->luk/10); // Critical increase - if (sd) - val1 += pc_checkskill(sd,DC_DANCINGLESSON); - val1*=10; //Because every 10 crit is an actual cri point. - break; - case BD_DRUMBATTLEFIELD: -#ifdef RENEWAL - val1 = (skilllv+5)*25; //Watk increase - val2 = skilllv*10; //Def increase -#else - val1 = (skilllv+1)*25; //Watk increase - val2 = (skilllv+1)*2; //Def increase -#endif - break; - case BD_RINGNIBELUNGEN: - val1 = (skilllv+2)*25; //Watk increase - break; - case BD_RICHMANKIM: - val1 = 25 + 11*skilllv; //Exp increase bonus. - break; - case BD_SIEGFRIED: - val1 = 55 + skilllv*5; //Elemental Resistance - val2 = skilllv*10; //Status ailment resistance - break; - case WE_CALLPARTNER: - if (sd) val1 = sd->status.partner_id; - break; - case WE_CALLPARENT: - if (sd) { - val1 = sd->status.father; - val2 = sd->status.mother; - } - break; - case WE_CALLBABY: - if (sd) val1 = sd->status.child; - break; - case NJ_KAENSIN: - skill_clear_group(src, 1); //Delete previous Kaensins/Suitons - val2 = (skilllv+1)/2 + 4; - break; - case NJ_SUITON: - skill_clear_group(src, 1); - break; + if (group->state.song_dance) { + if(sd){ + sd->skillid_dance = skillid; + sd->skilllv_dance = skilllv; + } + if ( + sc_start4(src, SC_DANCING, 100, skillid, group->group_id, skilllv, + (group->state.song_dance&2?BCT_SELF:0), limit+1000) && + sd && group->state.song_dance&2 && skillid != CG_HERMODE //Hermod is a encore with a warp! + ) + skill_check_pc_partner(sd, skillid, &skilllv, 1, 1); + } - case GS_GROUNDDRIFT: { - int element[5]= {ELE_WIND,ELE_DARK,ELE_POISON,ELE_WATER,ELE_FIRE}; - - val1 = status->rhw.ele; - if (!val1) - val1=element[rnd()%5]; - - switch (val1) { - case ELE_FIRE: - subunt++; - case ELE_WATER: - subunt++; - case ELE_POISON: - subunt++; - case ELE_DARK: - subunt++; - case ELE_WIND: - break; - default: - subunt=rnd()%5; - break; - } + limit = group->limit; + for( i = 0; i < layout->count; i++ ) + { + struct skill_unit *unit; + int ux = x + layout->dx[i]; + int uy = y + layout->dy[i]; + int val1 = skilllv; + int val2 = 0; + int alive = 1; + + if( !group->state.song_dance && !map_getcell(src->m,ux,uy,CELL_CHKREACH) ) + continue; // don't place skill units on walls (except for songs/dances/encores) + if( battle_config.skill_wall_check && skill_get_unit_flag(skillid)&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) ) + continue; // no path between cell and center of casting. + + switch( skillid ) + { + case MG_FIREWALL: + case NJ_KAENSIN: + val2=group->val2; + break; + case WZ_ICEWALL: + val1 = (skilllv <= 1) ? 500 : 200 + 200*skilllv; + val2 = map_getcell(src->m, ux, uy, CELL_GETTYPE); + break; + case HT_LANDMINE: + case MA_LANDMINE: + case HT_ANKLESNARE: + case HT_SHOCKWAVE: + case HT_SANDMAN: + case MA_SANDMAN: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + case HT_TALKIEBOX: + case HT_SKIDTRAP: + case MA_SKIDTRAP: + case HT_CLAYMORETRAP: + case HT_BLASTMINE: + /** + * Ranger + **/ + case RA_ELECTRICSHOCKER: + case RA_CLUSTERBOMB: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + val1 = 3500; + break; + case GS_DESPERADO: + val1 = abs(layout->dx[i]); + val2 = abs(layout->dy[i]); + if (val1 < 2 || val2 < 2) { //Nearby cross, linear decrease with no diagonals + if (val2 > val1) val1 = val2; + if (val1) val1--; + val1 = 36 -12*val1; + } else //Diagonal edges + val1 = 28 -4*val1 -4*val2; + if (val1 < 1) val1 = 1; + val2 = 0; + break; + case WM_REVERBERATION: + val1 = 1 + skilllv; + break; + case GN_WALLOFTHORN: + val1 = 1000 * skilllv; // Need official value. [LimitLine] + break; + default: + if (group->state.song_dance&0x1) + val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance + break; + } + if (skill_get_unit_flag(skillid) & UF_RANGEDSINGLEUNIT && i == (layout->count / 2)) + val2 |= UF_RANGEDSINGLEUNIT; // center. + + if( range <= 0 ) + map_foreachincell(skill_cell_overlap,src->m,ux,uy,BL_SKILL,skillid, &alive, src); + if( !alive ) + continue; + + nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy,val1,val2)); + unit->limit=limit; + unit->range=range; + + if (skillid == PF_FOGWALL && alive == 2) + { //Double duration of cells on top of Deluge/Suiton + unit->limit *= 2; + group->limit = unit->limit; + } + + // execute on all targets standing on this cell + if (range==0 && active_flag) + map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1); + } - break; - } - case GC_POISONSMOKE: - if (!(sc && sc->data[SC_POISONINGWEAPON])) - return NULL; - val2 = sc->data[SC_POISONINGWEAPON]->val2; // Type of Poison - val3 = sc->data[SC_POISONINGWEAPON]->val1; - limit = 4000 + 2000 * skilllv; - break; - case GD_LEADERSHIP: - case GD_GLORYWOUNDS: - case GD_SOULCOLD: - case GD_HAWKEYES: - limit = 1000000;//it doesn't matter - break; - case LG_BANDING: - limit = -1; - break; - case WM_REVERBERATION: - interval = limit; - val2 = 1; - case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector. - if (map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR)) - return NULL; - break; - case SO_CLOUD_KILL: - skill_clear_group(src, 4); - break; - case SO_WARMER: - skill_clear_group(src, 8); - break; - case SO_VACUUM_EXTREME: - range++; + if (!group->alive_count) + { //No cells? Something that was blocked completely by Land Protector? + skill_delunitgroup(group); + return NULL; + } - break; - case SC_BLOODYLUST: - skill_clear_group(src, 32); - break; - case GN_WALLOFTHORN: - if (flag&1) - limit = 3000; - val3 = (x<<16)|y; - break; - case KO_ZENKAI: - if (sd) { - ARR_FIND(1, 6, i, sd->talisman[i] > 0); - if (i < 5) { - val1 = sd->talisman[i]; // no. of aura - val2 = i; // aura type - limit += val1 * 1000; - subunt = i - 1; - pc_del_talisman(sd, sd->talisman[i], i); - } - } - break; - } - - nullpo_retr(NULL, group=skill_initunitgroup(src,layout->count,skillid,skilllv,skill_get_unit_id(skillid,flag&1)+subunt, limit, interval)); - group->val1=val1; - group->val2=val2; - group->val3=val3; - group->target_flag=target; - group->bl_flag= skill_get_unit_bl_target(skillid); - group->state.ammo_consume = (sd && sd->state.arrow_atk && skillid != GS_GROUNDDRIFT); //Store if this skill needs to consume ammo. - group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)?1:0)|(unit_flag&UF_ENSEMBLE?2:0); //Signals if this is a song/dance/duet - group->state.guildaura = (skillid >= GD_LEADERSHIP && skillid <= GD_HAWKEYES)?1:0; - group->item_id = req_item; - //if tick is greater than current, do not invoke onplace function just yet. [Skotlex] - if (DIFF_TICK(group->tick, gettick()) > SKILLUNITTIMER_INTERVAL) - active_flag = 0; - - if (skillid==HT_TALKIEBOX || skillid==RG_GRAFFITI) { - group->valstr=(char *) aMalloc(MESSAGE_SIZE*sizeof(char)); - if (sd) - safestrncpy(group->valstr, sd->message, MESSAGE_SIZE); - else //Eh... we have to write something here... even though mobs shouldn't use this. [Skotlex] - safestrncpy(group->valstr, "Boo!", MESSAGE_SIZE); - } - - if (group->state.song_dance) { - if (sd) { - sd->skillid_dance = skillid; - sd->skilllv_dance = skilllv; - } - if ( - sc_start4(src, SC_DANCING, 100, skillid, group->group_id, skilllv, - (group->state.song_dance&2?BCT_SELF:0), limit+1000) && - sd && group->state.song_dance&2 && skillid != CG_HERMODE //Hermod is a encore with a warp! - ) - skill_check_pc_partner(sd, skillid, &skilllv, 1, 1); - } - - limit = group->limit; - for (i = 0; i < layout->count; i++) { - struct skill_unit *unit; - int ux = x + layout->dx[i]; - int uy = y + layout->dy[i]; - int val1 = skilllv; - int val2 = 0; - int alive = 1; - - if (!group->state.song_dance && !map_getcell(src->m,ux,uy,CELL_CHKREACH)) - continue; // don't place skill units on walls (except for songs/dances/encores) - if (battle_config.skill_wall_check && skill_get_unit_flag(skillid)&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL)) - continue; // no path between cell and center of casting. - - switch (skillid) { - case MG_FIREWALL: - case NJ_KAENSIN: - val2=group->val2; - break; - case WZ_ICEWALL: - val1 = (skilllv <= 1) ? 500 : 200 + 200*skilllv; - val2 = map_getcell(src->m, ux, uy, CELL_GETTYPE); - break; - case HT_LANDMINE: - case MA_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case MA_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - case HT_TALKIEBOX: - case HT_SKIDTRAP: - case MA_SKIDTRAP: - case HT_CLAYMORETRAP: - case HT_BLASTMINE: - /** - * Ranger - **/ - case RA_ELECTRICSHOCKER: - case RA_CLUSTERBOMB: - case RA_MAGENTATRAP: - case RA_COBALTTRAP: - case RA_MAIZETRAP: - case RA_VERDURETRAP: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - val1 = 3500; - break; - case GS_DESPERADO: - val1 = abs(layout->dx[i]); - val2 = abs(layout->dy[i]); - if (val1 < 2 || val2 < 2) { //Nearby cross, linear decrease with no diagonals - if (val2 > val1) val1 = val2; - if (val1) val1--; - val1 = 36 -12*val1; - } else //Diagonal edges - val1 = 28 -4*val1 -4*val2; - if (val1 < 1) val1 = 1; - val2 = 0; - break; - case WM_REVERBERATION: - val1 = 1 + skilllv; - break; - case GN_WALLOFTHORN: - val1 = 1000 * skilllv; // Need official value. [LimitLine] - break; - default: - if (group->state.song_dance&0x1) - val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance - break; - } - if (skill_get_unit_flag(skillid) & UF_RANGEDSINGLEUNIT && i == (layout->count / 2)) - val2 |= UF_RANGEDSINGLEUNIT; // center. - - if (range <= 0) - map_foreachincell(skill_cell_overlap,src->m,ux,uy,BL_SKILL,skillid, &alive, src); - if (!alive) - continue; - - nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy,val1,val2)); - unit->limit=limit; - unit->range=range; - - if (skillid == PF_FOGWALL && alive == 2) { - //Double duration of cells on top of Deluge/Suiton - unit->limit *= 2; - group->limit = unit->limit; - } - - // execute on all targets standing on this cell - if (range==0 && active_flag) - map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1); - } - - if (!group->alive_count) { - //No cells? Something that was blocked completely by Land Protector? - skill_delunitgroup(group); - return NULL; - } - - //success, unit created. - switch (skillid) { - case WZ_ICEWALL: - map_foreachinrange(skill_icewall_block, src, AREA_SIZE, BL_MOB); - break; - case NJ_TATAMIGAESHI: //Store number of tiles. - group->val1 = group->alive_count; - break; - } + //success, unit created. + switch( skillid ) { + case WZ_ICEWALL: + map_foreachinrange(skill_icewall_block, src, AREA_SIZE, BL_MOB); + break; + case NJ_TATAMIGAESHI: //Store number of tiles. + group->val1 = group->alive_count; + break; + } - return group; + return group; } /*========================================== * *------------------------------------------*/ -void ext_skill_unit_onplace(struct skill_unit *src, struct block_list *bl, unsigned int tick) -{ - skill_unit_onplace(src, bl, tick); -} -static int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, unsigned int tick) +void ext_skill_unit_onplace(struct skill_unit *src, struct block_list *bl, unsigned int tick){skill_unit_onplace(src, bl, tick);} +static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned int tick) { - struct skill_unit_group *sg; - struct block_list *ss; - struct status_change *sc; - struct status_change_entry *sce; - enum sc_type type; - int skillid; - - nullpo_ret(src); - nullpo_ret(bl); - - if (bl->prev==NULL || !src->alive || status_isdead(bl)) - return 0; - - nullpo_ret(sg=src->group); - nullpo_ret(ss=map_id2bl(sg->src_id)); - - if (skill_get_type(sg->skill_id) == BF_MAGIC && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR) - return 0; //AoE skills are ineffective. [Skotlex] - - sc = status_get_sc(bl); - - if (sc && sc->option&OPTION_HIDE && sg->skill_id != WZ_HEAVENDRIVE && sg->skill_id != WL_EARTHSTRAIN) - return 0; //Hidden characters are immune to AoE skills except to these. [Skotlex] - - type = status_skill2sc(sg->skill_id); - sce = (sc && type != -1)?sc->data[type]:NULL; - skillid = sg->skill_id; //In case the group is deleted, we need to return the correct skill id, still. - switch (sg->unit_id) { - case UNT_SPIDERWEB: - if (sc && sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1 > 0) { - // If you are fiberlocked and can't move, it will only increase your fireweakness level. [Inkfish] - sc->data[SC_SPIDERWEB]->val2++; - break; - } else if (sc) { - int sec = skill_get_time2(sg->skill_id,sg->skill_lv); - if (status_change_start(bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8)) { - const struct TimerData *td = sc->data[type]?get_timer(sc->data[type]->timer):NULL; - if (td) - sec = DIFF_TICK(td->tick, tick); - map_moveblock(bl, src->bl.x, src->bl.y, tick); - clif_fixpos(bl); - sg->val2 = bl->id; - } else - sec = 3000; //Couldn't trap it? - sg->limit = DIFF_TICK(tick,sg->tick)+sec; - } - break; - case UNT_SAFETYWALL: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit); - break; - - case UNT_PNEUMA: - case UNT_CHAOSPANIC: - case UNT_MAELSTROM: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); - break; - case UNT_BLOODYLUST: - if (sg->src_id == bl->id) - break; //Does not affect the caster. - if (!sce) { - TBL_PC *sd = BL_CAST(BL_PC, bl); //prevent fullheal exploit - if (sd && sd->bloodylust_tick && DIFF_TICK(gettick(), sd->bloodylust_tick) < skill_get_time2(SC_BLOODYLUST, 1)) - clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, - sc_start4(bl, type, 100, sg->skill_lv, 1, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv))); - else { - if (sd) sd->bloodylust_tick = gettick(); - clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, - sc_start4(bl, type, 100, sg->skill_lv, 0, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv))); - } - } - break; - - case UNT_WARP_WAITING: { - int working = sg->val1&0xffff; - - if (bl->type==BL_PC && !working) { - struct map_session_data *sd = (struct map_session_data *)bl; - if ((!sd->chatID || battle_config.chat_warpportal) - && sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) { - int x = sg->val2>>16; - int y = sg->val2&0xffff; - int count = sg->val1>>16; - unsigned short m = sg->val3; - - if (--count <= 0) - skill_delunitgroup(sg); - - if (map_mapindex2mapid(sg->val3) == sd->bl.m && x == sd->bl.x && y == sd->bl.y) - working = 1;/* we break it because officials break it, lovely stuff. */ - - sg->val1 = (count<<16)|working; - - pc_setpos(sd,m,x,y,CLR_TELEPORT); - } - } else if (bl->type == BL_MOB && battle_config.mob_warp&2) { - int m = map_mapindex2mapid(sg->val3); - if (m < 0) break; //Map not available on this map-server. - unit_warp(bl,m,sg->val2>>16,sg->val2&0xffff,CLR_TELEPORT); - } - } - break; - - case UNT_QUAGMIRE: - if (!sce && battle_check_target(&sg->unit->bl,bl,sg->target_flag) > 0) - sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); - break; - - case UNT_VOLCANO: - case UNT_DELUGE: - case UNT_VIOLENTGALE: - if (!sce) - sc_start(bl,type,100,sg->skill_lv,sg->limit); - break; - - case UNT_SUITON: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv, - map_flag_vs(bl->m) || battle_check_target(&src->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi. - 0,0,sg->limit); - break; + struct skill_unit_group *sg; + struct block_list *ss; + struct status_change *sc; + struct status_change_entry *sce; + enum sc_type type; + int skillid; + + nullpo_ret(src); + nullpo_ret(bl); + + if(bl->prev==NULL || !src->alive || status_isdead(bl)) + return 0; + + nullpo_ret(sg=src->group); + nullpo_ret(ss=map_id2bl(sg->src_id)); + + if( skill_get_type(sg->skill_id) == BF_MAGIC && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR ) + return 0; //AoE skills are ineffective. [Skotlex] + + sc = status_get_sc(bl); + + if (sc && sc->option&OPTION_HIDE && sg->skill_id != WZ_HEAVENDRIVE && sg->skill_id != WL_EARTHSTRAIN ) + return 0; //Hidden characters are immune to AoE skills except to these. [Skotlex] + + type = status_skill2sc(sg->skill_id); + sce = (sc && type != -1)?sc->data[type]:NULL; + skillid = sg->skill_id; //In case the group is deleted, we need to return the correct skill id, still. + switch (sg->unit_id) + { + case UNT_SPIDERWEB: + if( sc && sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1 > 0 ) + { // If you are fiberlocked and can't move, it will only increase your fireweakness level. [Inkfish] + sc->data[SC_SPIDERWEB]->val2++; + break; + } + else if( sc ) + { + int sec = skill_get_time2(sg->skill_id,sg->skill_lv); + if( status_change_start(bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) + { + const struct TimerData* td = sc->data[type]?get_timer(sc->data[type]->timer):NULL; + if( td ) + sec = DIFF_TICK(td->tick, tick); + map_moveblock(bl, src->bl.x, src->bl.y, tick); + clif_fixpos(bl); + sg->val2 = bl->id; + } + else + sec = 3000; //Couldn't trap it? + sg->limit = DIFF_TICK(tick,sg->tick)+sec; + } + break; + case UNT_SAFETYWALL: + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit); + break; + + case UNT_PNEUMA: + case UNT_CHAOSPANIC: + case UNT_MAELSTROM: + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); + break; + case UNT_BLOODYLUST: + if (sg->src_id == bl->id) + break; //Does not affect the caster. + if (!sce) { + TBL_PC *sd = BL_CAST(BL_PC, bl); //prevent fullheal exploit + if (sd && sd->bloodylust_tick && DIFF_TICK(gettick(), sd->bloodylust_tick) < skill_get_time2(SC_BLOODYLUST, 1)) + clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, + sc_start4(bl, type, 100, sg->skill_lv, 1, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv))); + else { + if (sd) sd->bloodylust_tick = gettick(); + clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, + sc_start4(bl, type, 100, sg->skill_lv, 0, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv))); + } + } + break; - case UNT_HERMODE: - if (sg->src_id!=bl->id && battle_check_target(&src->bl,bl,BCT_PARTY|BCT_GUILD) > 0) - status_change_clear_buffs(bl,1); //Should dispell only allies. - case UNT_RICHMANKIM: - case UNT_ETERNALCHAOS: - case UNT_DRUMBATTLEFIELD: - case UNT_RINGNIBELUNGEN: - case UNT_ROKISWEIL: - case UNT_INTOABYSS: - case UNT_SIEGFRIED: - //Needed to check when a dancer/bard leaves their ensemble area. - if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) - return skillid; - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); - break; - case UNT_WHISTLE: - case UNT_ASSASSINCROSS: - case UNT_POEMBRAGI: - case UNT_APPLEIDUN: - case UNT_HUMMING: - case UNT_DONTFORGETME: - case UNT_FORTUNEKISS: - case UNT_SERVICEFORYOU: - if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) { - if (sce) /* We have the status but we're not elegible for it, so we take it away. (bugreport:4591) */ - sce->val4 = 2; - return 0; - } - if (!sc) return 0; - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); - else if (sce->val4 == 1) { - //Readjust timers since the effect will not last long. - sce->val4 = 0; - delete_timer(sce->timer, status_change_timer); - sce->timer = add_timer(tick+sg->limit, status_change_timer, bl->id, type); - } - break; + case UNT_WARP_WAITING: { + int working = sg->val1&0xffff; - case UNT_FOGWALL: - if (!sce) { - sc_start4(bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit); - if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) - skill_additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, ATK_DEF, tick); - } - break; + if(bl->type==BL_PC && !working){ + struct map_session_data *sd = (struct map_session_data *)bl; + if((!sd->chatID || battle_config.chat_warpportal) + && sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) + { + int x = sg->val2>>16; + int y = sg->val2&0xffff; + int count = sg->val1>>16; + unsigned short m = sg->val3; - case UNT_GRAVITATION: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit); - break; + if( --count <= 0 ) + skill_delunitgroup(sg); - // officially, icewall has no problems existing on occupied cells [ultramage] - // case UNT_ICEWALL: //Destroy the cell. [Skotlex] - // src->val1 = 0; - // if(src->limit + sg->tick > tick + 700) - // src->limit = DIFF_TICK(tick+700,sg->tick); - // break; - - case UNT_MOONLIT: - //Knockback out of area if affected char isn't in Moonlit effect - if (sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT) - break; - if (ss == bl) //Also needed to prevent infinite loop crash. - break; - skill_blown(ss,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); - break; + if ( map_mapindex2mapid(sg->val3) == sd->bl.m && x == sd->bl.x && y == sd->bl.y ) + working = 1;/* we break it because officials break it, lovely stuff. */ - case UNT_WALLOFTHORN: - if (status_get_mode(bl)&MD_BOSS) - break; // iRO Wiki says that this skill don't affect to Boss monsters. - if (map_flag_vs(bl->m) || bl->id == src->bl.id || battle_check_target(&src->bl,bl, BCT_ENEMY) == 1) - skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - break; + sg->val1 = (count<<16)|working; - case UNT_VOLCANIC_ASH: - if (!sce) - sc_start(bl, SC_ASH, 100, sg->skill_lv, skill_get_time(MH_VOLCANIC_ASH, sg->skill_lv)); - break; - - case UNT_GD_LEADERSHIP: - case UNT_GD_GLORYWOUNDS: - case UNT_GD_SOULCOLD: - case UNT_GD_HAWKEYES: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,0,0,0,1000); - break; - } - return skillid; + pc_setpos(sd,m,x,y,CLR_TELEPORT); + } + } else if(bl->type == BL_MOB && battle_config.mob_warp&2) { + int m = map_mapindex2mapid(sg->val3); + if (m < 0) break; //Map not available on this map-server. + unit_warp(bl,m,sg->val2>>16,sg->val2&0xffff,CLR_TELEPORT); + } + } + break; + + case UNT_QUAGMIRE: + if( !sce && battle_check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) + sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); + break; + + case UNT_VOLCANO: + case UNT_DELUGE: + case UNT_VIOLENTGALE: + if(!sce) + sc_start(bl,type,100,sg->skill_lv,sg->limit); + break; + + case UNT_SUITON: + if(!sce) + sc_start4(bl,type,100,sg->skill_lv, + map_flag_vs(bl->m) || battle_check_target(&src->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi. + 0,0,sg->limit); + break; + + case UNT_HERMODE: + if (sg->src_id!=bl->id && battle_check_target(&src->bl,bl,BCT_PARTY|BCT_GUILD) > 0) + status_change_clear_buffs(bl,1); //Should dispell only allies. + case UNT_RICHMANKIM: + case UNT_ETERNALCHAOS: + case UNT_DRUMBATTLEFIELD: + case UNT_RINGNIBELUNGEN: + case UNT_ROKISWEIL: + case UNT_INTOABYSS: + case UNT_SIEGFRIED: + //Needed to check when a dancer/bard leaves their ensemble area. + if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) + return skillid; + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); + break; + case UNT_WHISTLE: + case UNT_ASSASSINCROSS: + case UNT_POEMBRAGI: + case UNT_APPLEIDUN: + case UNT_HUMMING: + case UNT_DONTFORGETME: + case UNT_FORTUNEKISS: + case UNT_SERVICEFORYOU: + if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) { + if( sce )/* We have the status but we're not elegible for it, so we take it away. (bugreport:4591) */ + sce->val4 = 2; + return 0; + } + if (!sc) return 0; + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); + else if (sce->val4 == 1) { + //Readjust timers since the effect will not last long. + sce->val4 = 0; + delete_timer(sce->timer, status_change_timer); + sce->timer = add_timer(tick+sg->limit, status_change_timer, bl->id, type); + } + break; + + case UNT_FOGWALL: + if (!sce) + { + sc_start4(bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit); + if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) + skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, ATK_DEF, tick); + } + break; + + case UNT_GRAVITATION: + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit); + break; + +// officially, icewall has no problems existing on occupied cells [ultramage] +// case UNT_ICEWALL: //Destroy the cell. [Skotlex] +// src->val1 = 0; +// if(src->limit + sg->tick > tick + 700) +// src->limit = DIFF_TICK(tick+700,sg->tick); +// break; + + case UNT_MOONLIT: + //Knockback out of area if affected char isn't in Moonlit effect + if (sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT) + break; + if (ss == bl) //Also needed to prevent infinite loop crash. + break; + skill_blown(ss,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); + break; + + case UNT_WALLOFTHORN: + if( status_get_mode(bl)&MD_BOSS ) + break; // iRO Wiki says that this skill don't affect to Boss monsters. + if( map_flag_vs(bl->m) || bl->id == src->bl.id || battle_check_target(&src->bl,bl, BCT_ENEMY) == 1 ) + skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + break; + + case UNT_VOLCANIC_ASH: + if (!sce) + sc_start(bl, SC_ASH, 100, sg->skill_lv, skill_get_time(MH_VOLCANIC_ASH, sg->skill_lv)); + break; + + case UNT_GD_LEADERSHIP: + case UNT_GD_GLORYWOUNDS: + case UNT_GD_SOULCOLD: + case UNT_GD_HAWKEYES: + if ( !sce ) + sc_start4(bl,type,100,sg->skill_lv,0,0,0,1000); + break; + } + return skillid; } /*========================================== * *------------------------------------------*/ -int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, unsigned int tick) +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; - TBL_PC *tsd; - struct status_data *tstatus; - struct status_change *tsc; - struct skill_unit_group_tickset *ts; - enum sc_type type; - int skillid; - int diff=0; - - nullpo_ret(src); - nullpo_ret(bl); - - if (bl->prev==NULL || !src->alive || status_isdead(bl)) - return 0; - - nullpo_ret(sg=src->group); - nullpo_ret(ss=map_id2bl(sg->src_id)); - tsd = BL_CAST(BL_PC, bl); - tsc = status_get_sc(bl); - - if (tsc && tsc->data[SC_HOVERING]) - return 0; //Under hovering characters are immune to trap and ground target skills. - - tstatus = status_get_status_data(bl); - type = status_skill2sc(sg->skill_id); - skillid = sg->skill_id; - - if (sg->interval == -1) { - switch (sg->unit_id) { - case UNT_ANKLESNARE: //These happen when a trap is splash-triggered by multiple targets on the same cell. - case UNT_FIREPILLAR_ACTIVE: - case UNT_ELECTRICSHOCKER: - case UNT_MANHOLE: - return 0; - default: - ShowError("skill_unit_onplace_timer: interval error (unit id %x)\n", sg->unit_id); - return 0; - } - } - - if ((ts = skill_unitgrouptickset_search(bl,sg,tick))) { - //Not all have it, eg: Traps don't have it even though they can be hit by Heaven's Drive [Skotlex] - diff = DIFF_TICK(tick,ts->tick); - if (diff < 0) - return 0; - ts->tick = tick+sg->interval; - - if ((skillid==CR_GRANDCROSS || skillid==NPC_GRANDDARKNESS) && !battle_config.gx_allhit) - ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y,BL_CHAR)-1); - } - - switch (sg->unit_id) { - case UNT_FIREWALL: - case UNT_KAEN: { - int count=0; - const int x = bl->x, y = bl->y; - - if (sg->skill_id == GN_WALLOFTHORN && !map_flag_vs(bl->m)) - break; - - //Take into account these hit more times than the timer interval can handle. - do - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0); - while (--src->val2 && x == bl->x && y == bl->y && - ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl)); - - if (src->val2<=0) - skill_delunit(src); - } - break; - - case UNT_SANCTUARY: - if (battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race==RC_DEMON) { - //Only damage enemies with offensive Sanctuary. [Skotlex] - if (battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 && skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0)) - sg->val1 -= 2; // reduce healing count if this was meant for damaging [hekate] - } else { - int heal = skill_calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true); - struct mob_data *md = BL_CAST(BL_MOB, bl); -#ifdef RENEWAL - if (md && md->class_ == MOBID_EMPERIUM) - break; -#endif - if (md && mob_is_battleground(md)) - break; - if (tstatus->hp >= tstatus->max_hp) - break; - if (status_isimmune(bl)) - heal = 0; - clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); - if (tsc && tsc->data[SC_AKAITSUKI] && heal) - heal = ~heal + 1; - status_heal(bl, heal, 0, 0); - if (diff >= 500) - sg->val1--; - } - if (sg->val1 <= 0) - skill_delunitgroup(sg); - break; + struct skill_unit_group *sg; + struct block_list *ss; + TBL_PC* tsd; + struct status_data *tstatus; + struct status_change *tsc; + struct skill_unit_group_tickset *ts; + enum sc_type type; + int skillid; + int diff=0; + + nullpo_ret(src); + nullpo_ret(bl); + + if (bl->prev==NULL || !src->alive || status_isdead(bl)) + return 0; + + nullpo_ret(sg=src->group); + nullpo_ret(ss=map_id2bl(sg->src_id)); + tsd = BL_CAST(BL_PC, bl); + tsc = status_get_sc(bl); + + if ( tsc && tsc->data[SC_HOVERING] ) + return 0; //Under hovering characters are immune to trap and ground target skills. + + tstatus = status_get_status_data(bl); + type = status_skill2sc(sg->skill_id); + skillid = sg->skill_id; + + if (sg->interval == -1) { + switch (sg->unit_id) { + case UNT_ANKLESNARE: //These happen when a trap is splash-triggered by multiple targets on the same cell. + case UNT_FIREPILLAR_ACTIVE: + case UNT_ELECTRICSHOCKER: + case UNT_MANHOLE: + return 0; + default: + ShowError("skill_unit_onplace_timer: interval error (unit id %x)\n", sg->unit_id); + return 0; + } + } - case UNT_EVILLAND: - //Will heal demon and undead element monsters, but not players. - if ((bl->type == BL_PC) || (!battle_check_undead(tstatus->race, tstatus->def_ele) && tstatus->race!=RC_DEMON)) { - //Damage enemies - if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) - skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - } else { - int heal = skill_calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true); - if (tstatus->hp >= tstatus->max_hp) - break; - if (status_isimmune(bl)) - heal = 0; - clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); - status_heal(bl, heal, 0, 0); - } - break; + if ((ts = skill_unitgrouptickset_search(bl,sg,tick))) + { //Not all have it, eg: Traps don't have it even though they can be hit by Heaven's Drive [Skotlex] + diff = DIFF_TICK(tick,ts->tick); + if (diff < 0) + return 0; + ts->tick = tick+sg->interval; - case UNT_MAGNUS: - if (!battle_check_undead(tstatus->race,tstatus->def_ele) && tstatus->race!=RC_DEMON) - break; - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; + if ((skillid==CR_GRANDCROSS || skillid==NPC_GRANDDARKNESS) && !battle_config.gx_allhit) + ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y,BL_CHAR)-1); + } - case UNT_DUMMYSKILL: - switch (sg->skill_id) { - case SG_SUN_WARM: //SG skills [Komurka] - case SG_MOON_WARM: - case SG_STAR_WARM: { - int count = 0; - const int x = bl->x, y = bl->y; - - //If target isn't knocked back it should hit every "interval" ms [Playtester] - do { - if (bl->type == BL_PC) - status_zap(bl, 0, 15); // sp damage to players - else // mobs - if (status_charge(ss, 0, 2)) { // costs 2 SP per hit - if (!skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0)) - status_charge(ss, 0, 8); //costs additional 8 SP if miss - } else { - //should end when out of sp. - sg->limit = DIFF_TICK(tick,sg->tick); - break; - } - } while (x == bl->x && y == bl->y && - ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl)); - } - break; - /** - * The storm gust counter was dropped in renewal - **/ -#ifndef RENEWAL - case WZ_STORMGUST: //SG counter does not reset per stormgust. IE: One hit from a SG and two hits from another will freeze you. - if (tsc) - tsc->sg_counter++; //SG hit counter. - if (skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc) - tsc->sg_counter=0; //Attack absorbed. - break; + switch (sg->unit_id) + { + case UNT_FIREWALL: + case UNT_KAEN: + { + int count=0; + const int x = bl->x, y = bl->y; + + if( sg->skill_id == GN_WALLOFTHORN && !map_flag_vs(bl->m) ) + break; + + //Take into account these hit more times than the timer interval can handle. + do + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0); + while(--src->val2 && x == bl->x && y == bl->y && + ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl)); + + if (src->val2<=0) + skill_delunit(src); + } + break; + + case UNT_SANCTUARY: + if( battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race==RC_DEMON ) + { //Only damage enemies with offensive Sanctuary. [Skotlex] + if( battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 && skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0) ) + sg->val1 -= 2; // reduce healing count if this was meant for damaging [hekate] + } + else + { + int heal = skill_calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true); + struct mob_data *md = BL_CAST(BL_MOB, bl); +#ifdef RENEWAL + if( md && md->class_ == MOBID_EMPERIUM ) + break; #endif - case GS_DESPERADO: - if (rnd()%100 < src->val1) - skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; - case GN_CRAZYWEED_ATK: - if (bl->type == BL_SKILL) { - struct skill_unit *su = (struct skill_unit *)bl; - if (su && !(skill_get_inf2(su->group->skill_id)&INF2_TRAP)) - break; - } - default: - skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - } - break; - - case UNT_FIREPILLAR_WAITING: - skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1); - skill_delunit(src); - break; - - case UNT_SKIDTRAP: { - skill_blown(&src->bl,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); - sg->unit_id = UNT_USED_TRAPS; - clif_changetraplook(&src->bl, UNT_USED_TRAPS); - sg->limit=DIFF_TICK(tick,sg->tick)+1500; - } - break; - - case UNT_ANKLESNARE: - case UNT_MANHOLE: - if (sg->val2 == 0 && tsc && (sg->unit_id == UNT_ANKLESNARE || bl->id != sg->src_id)) { - int sec = skill_get_time2(sg->skill_id,sg->skill_lv); - if (status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8)) { - const struct TimerData *td = tsc->data[type]?get_timer(tsc->data[type]->timer):NULL; - if (td) - sec = DIFF_TICK(td->tick, tick); - unit_movepos(bl, src->bl.x, src->bl.y, 0, 0); - clif_fixpos(bl); - sg->val2 = bl->id; - } else - sec = 3000; //Couldn't trap it? - if (sg->unit_id == UNT_ANKLESNARE) { - clif_skillunit_update(&src->bl); - /** - * If you're snared from a trap that was invisible this makes the trap be - * visible again -- being you stepped on it (w/o this the trap remains invisible and you go "WTF WHY I CANT MOVE") - * bugreport:3961 - **/ - clif_changetraplook(&src->bl, UNT_ANKLESNARE); - } - sg->limit = DIFF_TICK(tick,sg->tick)+sec; - sg->interval = -1; - src->range = 0; - } - break; - - case UNT_ELECTRICSHOCKER: - if (bl->id != ss->id) { - if (status_get_mode(bl)&MD_BOSS) - break; - if (status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id, sg->skill_lv), 8)) { - - map_moveblock(bl, src->bl.x, src->bl.y, tick); - clif_fixpos(bl); - - } - - map_foreachinrange(skill_trap_splash, &src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick); - sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again. - } - break; + if( md && mob_is_battleground(md) ) + break; + if( tstatus->hp >= tstatus->max_hp ) + break; + if( status_isimmune(bl) ) + heal = 0; + clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); + if( tsc && tsc->data[SC_AKAITSUKI] && heal ) + heal = ~heal + 1; + status_heal(bl, heal, 0, 0); + if( diff >= 500 ) + sg->val1--; + } + if( sg->val1 <= 0 ) + skill_delunitgroup(sg); + break; + + case UNT_EVILLAND: + //Will heal demon and undead element monsters, but not players. + if ((bl->type == BL_PC) || (!battle_check_undead(tstatus->race, tstatus->def_ele) && tstatus->race!=RC_DEMON)) + { //Damage enemies + if(battle_check_target(&src->bl,bl,BCT_ENEMY)>0) + skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + } else { + int heal = skill_calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true); + if (tstatus->hp >= tstatus->max_hp) + break; + if (status_isimmune(bl)) + heal = 0; + clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); + status_heal(bl, heal, 0, 0); + } + break; - case UNT_VENOMDUST: - if (tsc && !tsc->data[type]) - status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - break; + case UNT_MAGNUS: + if (!battle_check_undead(tstatus->race,tstatus->def_ele) && tstatus->race!=RC_DEMON) + break; + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + case UNT_DUMMYSKILL: + switch (sg->skill_id) + { + case SG_SUN_WARM: //SG skills [Komurka] + case SG_MOON_WARM: + case SG_STAR_WARM: + { + int count = 0; + const int x = bl->x, y = bl->y; + + //If target isn't knocked back it should hit every "interval" ms [Playtester] + do + { + if( bl->type == BL_PC ) + status_zap(bl, 0, 15); // sp damage to players + else // mobs + if( status_charge(ss, 0, 2) ) // costs 2 SP per hit + { + if( !skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0) ) + status_charge(ss, 0, 8); //costs additional 8 SP if miss + } + else + { //should end when out of sp. + sg->limit = DIFF_TICK(tick,sg->tick); + break; + } + } while( x == bl->x && y == bl->y && + ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl) ); + } + break; + /** + * The storm gust counter was dropped in renewal + **/ + #ifndef RENEWAL + case WZ_STORMGUST: //SG counter does not reset per stormgust. IE: One hit from a SG and two hits from another will freeze you. + if (tsc) + tsc->sg_counter++; //SG hit counter. + if (skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc) + tsc->sg_counter=0; //Attack absorbed. + break; + #endif + case GS_DESPERADO: + if (rnd()%100 < src->val1) + skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + case GN_CRAZYWEED_ATK: + if( bl->type == BL_SKILL ){ + struct skill_unit *su = (struct skill_unit *)bl; + if( su && !(skill_get_inf2(su->group->skill_id)&INF2_TRAP) ) + break; + } + default: + skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + } + break; - case UNT_MAGENTATRAP: - case UNT_COBALTTRAP: - case UNT_MAIZETRAP: - case UNT_VERDURETRAP: - if (bl->type == BL_PC) // it won't work on players - break; - case UNT_FIRINGTRAP: - case UNT_ICEBOUNDTRAP: - case UNT_CLUSTERBOMB: - if (bl->id == ss->id) // it won't trigger on caster - break; - case UNT_LANDMINE: - case UNT_CLAYMORETRAP: - case UNT_BLASTMINE: - case UNT_SHOCKWAVE: - case UNT_SANDMAN: - case UNT_FLASHER: - case UNT_FREEZINGTRAP: - case UNT_FIREPILLAR_ACTIVE: - map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); - if (sg->unit_id != UNT_FIREPILLAR_ACTIVE) - clif_changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); - sg->limit=DIFF_TICK(tick,sg->tick)+1500 + - (sg->unit_id== UNT_CLUSTERBOMB || sg->unit_id== UNT_ICEBOUNDTRAP?1000:0);// Cluster Bomb/Icebound has 1s to disappear once activated. - sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again. - break; + case UNT_FIREPILLAR_WAITING: + skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1); + skill_delunit(src); + break; - case UNT_TALKIEBOX: - if (sg->src_id == bl->id) - break; - if (sg->val2 == 0) { - clif_talkiebox(&src->bl, sg->valstr); - sg->unit_id = UNT_USED_TRAPS; - clif_changetraplook(&src->bl, UNT_USED_TRAPS); - sg->limit = DIFF_TICK(tick, sg->tick) + 5000; - sg->val2 = -1; - } - break; + case UNT_SKIDTRAP: + { + skill_blown(&src->bl,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); + sg->unit_id = UNT_USED_TRAPS; + clif_changetraplook(&src->bl, UNT_USED_TRAPS); + sg->limit=DIFF_TICK(tick,sg->tick)+1500; + } + break; + + case UNT_ANKLESNARE: + case UNT_MANHOLE: + if( sg->val2 == 0 && tsc && (sg->unit_id == UNT_ANKLESNARE || bl->id != sg->src_id) ) { + int sec = skill_get_time2(sg->skill_id,sg->skill_lv); + if( status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8) ) { + const struct TimerData* td = tsc->data[type]?get_timer(tsc->data[type]->timer):NULL; + if( td ) + sec = DIFF_TICK(td->tick, tick); + unit_movepos(bl, src->bl.x, src->bl.y, 0, 0); + clif_fixpos(bl); + sg->val2 = bl->id; + } else + sec = 3000; //Couldn't trap it? + if( sg->unit_id == UNT_ANKLESNARE ) { + clif_skillunit_update(&src->bl); + /** + * If you're snared from a trap that was invisible this makes the trap be + * visible again -- being you stepped on it (w/o this the trap remains invisible and you go "WTF WHY I CANT MOVE") + * bugreport:3961 + **/ + clif_changetraplook(&src->bl, UNT_ANKLESNARE); + } + sg->limit = DIFF_TICK(tick,sg->tick)+sec; + sg->interval = -1; + src->range = 0; + } + break; - case UNT_LULLABY: - if (ss->id == bl->id) - break; - skill_additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_LONG|BF_SKILL|BF_MISC, ATK_DEF, tick); - break; + case UNT_ELECTRICSHOCKER: + if( bl->id != ss->id ) { + if( status_get_mode(bl)&MD_BOSS ) + break; + if( status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id, sg->skill_lv), 8) ) { - case UNT_UGLYDANCE: //Ugly Dance [Skotlex] - if (ss->id != bl->id) - skill_additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_LONG|BF_SKILL|BF_MISC, ATK_DEF, tick); - break; + map_moveblock(bl, src->bl.x, src->bl.y, tick); + clif_fixpos(bl); - case UNT_DISSONANCE: - skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - break; + } - case UNT_APPLEIDUN: { //Apple of Idun [Skotlex] - int heal; + map_foreachinrange(skill_trap_splash, &src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick); + sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again. + } + break; + + case UNT_VENOMDUST: + if(tsc && !tsc->data[type]) + status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); + break; + + + case UNT_MAGENTATRAP: + case UNT_COBALTTRAP: + case UNT_MAIZETRAP: + case UNT_VERDURETRAP: + if( bl->type == BL_PC )// it won't work on players + break; + case UNT_FIRINGTRAP: + case UNT_ICEBOUNDTRAP: + case UNT_CLUSTERBOMB: + if( bl->id == ss->id )// it won't trigger on caster + break; + case UNT_LANDMINE: + case UNT_CLAYMORETRAP: + case UNT_BLASTMINE: + case UNT_SHOCKWAVE: + case UNT_SANDMAN: + case UNT_FLASHER: + case UNT_FREEZINGTRAP: + case UNT_FIREPILLAR_ACTIVE: + map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); + if (sg->unit_id != UNT_FIREPILLAR_ACTIVE) + clif_changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); + sg->limit=DIFF_TICK(tick,sg->tick)+1500 + + (sg->unit_id== UNT_CLUSTERBOMB || sg->unit_id== UNT_ICEBOUNDTRAP?1000:0);// Cluster Bomb/Icebound has 1s to disappear once activated. + sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again. + break; + + case UNT_TALKIEBOX: + if (sg->src_id == bl->id) + break; + if (sg->val2 == 0){ + clif_talkiebox(&src->bl, sg->valstr); + sg->unit_id = UNT_USED_TRAPS; + clif_changetraplook(&src->bl, UNT_USED_TRAPS); + sg->limit = DIFF_TICK(tick, sg->tick) + 5000; + sg->val2 = -1; + } + break; + + case UNT_LULLABY: + if (ss->id == bl->id) + break; + skill_additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_LONG|BF_SKILL|BF_MISC, ATK_DEF, tick); + break; + + case UNT_UGLYDANCE: //Ugly Dance [Skotlex] + if (ss->id != bl->id) + skill_additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_LONG|BF_SKILL|BF_MISC, ATK_DEF, tick); + break; + + case UNT_DISSONANCE: + skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + break; + + case UNT_APPLEIDUN: //Apple of Idun [Skotlex] + { + int heal; #ifdef RENEWAL - struct mob_data *md = BL_CAST(BL_MOB, bl); - if (md && md->class_ == MOBID_EMPERIUM) - break; + struct mob_data *md = BL_CAST(BL_MOB, bl); + if( md && md->class_ == MOBID_EMPERIUM ) + break; #endif - if (sg->src_id == bl->id && !(tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) - break; // affects self only when soullinked - heal = skill_calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true); - if (tsc->data[SC_AKAITSUKI] && heal) - heal = ~heal + 1; - clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); - status_heal(bl, heal, 0, 0); - break; - } - - case UNT_TATAMIGAESHI: - case UNT_DEMONSTRATION: - skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; - - case UNT_GOSPEL: - if (rnd()%100 > sg->skill_lv*10 || ss == bl) - break; - if (battle_check_target(ss,bl,BCT_PARTY)>0) { - // Support Effect only on party, not guild - int heal; - int i = rnd()%13; // Positive buff count - int time = skill_get_time2(sg->skill_id, sg->skill_lv); //Duration - switch (i) { - case 0: // Heal 1~9999 HP - heal = rnd() %9999+1; - clif_skill_nodamage(ss,bl,AL_HEAL,heal,1); - status_heal(bl,heal,0,0); - break; - case 1: // End all negative status - status_change_clear_buffs(bl,6); - if (tsd) clif_gospel_info(tsd, 0x15); - break; - case 2: // Immunity to all status - sc_start(bl,SC_SCRESIST,100,100,time); - if (tsd) clif_gospel_info(tsd, 0x16); - break; - case 3: // MaxHP +100% - sc_start(bl,SC_INCMHPRATE,100,100,time); - if (tsd) clif_gospel_info(tsd, 0x17); - break; - case 4: // MaxSP +100% - sc_start(bl,SC_INCMSPRATE,100,100,time); - if (tsd) clif_gospel_info(tsd, 0x18); - break; - case 5: // All stats +20 - sc_start(bl,SC_INCALLSTATUS,100,20,time); - if (tsd) clif_gospel_info(tsd, 0x19); - break; - case 6: // Level 10 Blessing - sc_start(bl,SC_BLESSING,100,10,time); - break; - case 7: // Level 10 Increase AGI - sc_start(bl,SC_INCREASEAGI,100,10,time); - break; - case 8: // Enchant weapon with Holy element - sc_start(bl,SC_ASPERSIO,100,1,time); - if (tsd) clif_gospel_info(tsd, 0x1c); - break; - case 9: // Enchant armor with Holy element - sc_start(bl,SC_BENEDICTIO,100,1,time); - if (tsd) clif_gospel_info(tsd, 0x1d); - break; - case 10: // DEF +25% - sc_start(bl,SC_INCDEFRATE,100,25,time); - if (tsd) clif_gospel_info(tsd, 0x1e); - break; - case 11: // ATK +100% - sc_start(bl,SC_INCATKRATE,100,100,time); - if (tsd) clif_gospel_info(tsd, 0x1f); - break; - case 12: // HIT/Flee +50 - sc_start(bl,SC_INCHIT,100,50,time); - sc_start(bl,SC_INCFLEE,100,50,time); - if (tsd) clif_gospel_info(tsd, 0x20); - break; - } - } else if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) { - // Offensive Effect - int i = rnd()%9; // Negative buff count - int time = skill_get_time2(sg->skill_id, sg->skill_lv); - switch (i) { - case 0: // Deal 1~9999 damage - skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; - case 1: // Curse - sc_start(bl,SC_CURSE,100,1,time); - break; - case 2: // Blind - sc_start(bl,SC_BLIND,100,1,time); - break; - case 3: // Poison - sc_start(bl,SC_POISON,100,1,time); - break; - case 4: // Level 10 Provoke - sc_start(bl,SC_PROVOKE,100,10,time); - break; - case 5: // DEF -100% - sc_start(bl,SC_INCDEFRATE,100,-100,time); - break; - case 6: // ATK -100% - sc_start(bl,SC_INCATKRATE,100,-100,time); - break; - case 7: // Flee -100% - sc_start(bl,SC_INCFLEERATE,100,-100,time); - break; - case 8: // Speed/ASPD -25% - sc_start4(bl,SC_GOSPEL,100,1,0,0,BCT_ENEMY,time); - break; - } - } - break; - - case UNT_BASILICA: { - int i = battle_check_target(&src->bl, bl, BCT_ENEMY); - if (i > 0 && !(status_get_mode(bl)&MD_BOSS)) { - // knock-back any enemy except Boss - skill_blown(&src->bl, bl, 2, unit_getdir(bl), 0); - clif_fixpos(bl); - } - - if (sg->src_id != bl->id && i <= 0) - sc_start4(bl, type, 100, 0, 0, 0, src->bl.id, sg->interval + 100); - } - break; - - case UNT_GRAVITATION: - case UNT_EARTHSTRAIN: - case UNT_FIREWALK: - case UNT_ELECTRICWALK: - case UNT_PSYCHIC_WAVE: - skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; - - case UNT_GROUNDDRIFT_WIND: - case UNT_GROUNDDRIFT_DARK: - case UNT_GROUNDDRIFT_POISON: - case UNT_GROUNDDRIFT_WATER: - case UNT_GROUNDDRIFT_FIRE: - map_foreachinrange(skill_trap_splash,&src->bl, - skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, - &src->bl,tick); - sg->unit_id = UNT_USED_TRAPS; - //clif_changetraplook(&src->bl, UNT_FIREPILLAR_ACTIVE); - sg->limit=DIFF_TICK(tick,sg->tick)+1500; - break; - /** - * 3rd stuff - **/ - case UNT_POISONSMOKE: - if (battle_check_target(ss,bl,BCT_ENEMY) > 0 && !(tsc && tsc->data[sg->val2]) && rnd()%100 < 20) - sc_start(bl,sg->val2,100,sg->val3,skill_get_time2(GC_POISONINGWEAPON, 1)); - break; - - case UNT_EPICLESIS: - if (bl->type == BL_PC && !battle_check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON) { - if (++sg->val2 % 3 == 0) { - int hp, sp; - switch (sg->skill_lv) { - case 1: - case 2: - hp = 3; - sp = 2; - break; - case 3: - case 4: - hp = 4; - sp = 3; - break; - case 5: - default: - hp = 5; - sp = 4; - break; - } - hp = tstatus->max_hp * hp / 100; - sp = tstatus->max_sp * sp / 100; - status_heal(bl, hp, sp, 2); - sc_start(bl, type, 100, sg->skill_lv, (sg->interval * 3) + 100); - } - // Reveal hidden players every 5 seconds. - if (sg->val2 % 5 == 0) { - // TODO: check if other hidden status can be removed. - status_change_end(bl,SC_HIDING,INVALID_TIMER); - status_change_end(bl,SC_CLOAKING,INVALID_TIMER); - } - } - /* Enable this if kRO fix the current skill. Currently no damage on undead and demon monster. [Jobbie] - else if( battle_check_target(ss, bl, BCT_ENEMY) > 0 && battle_check_undead(tstatus->race, tstatus->def_ele) ) - skill_castend_damage_id(&src->bl, bl, sg->skill_id, sg->skill_lv, 0, 0);*/ - break; - - case UNT_STEALTHFIELD: - if (bl->id == sg->src_id) - break; // Dont work on Self (video shows that) - case UNT_NEUTRALBARRIER: - sc_start(bl,type,100,sg->skill_lv,sg->interval + 100); - break; - - case UNT_DIMENSIONDOOR: - if (tsd && !map[bl->m].flag.noteleport) - pc_randomwarp(tsd,3); - else if (bl->type == BL_MOB && battle_config.mob_warp&8) - unit_warp(bl,-1,-1,-1,3); - break; - - case UNT_REVERBERATION: - clif_changetraplook(&src->bl,UNT_USED_TRAPS); - map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); - sg->limit = DIFF_TICK(tick,sg->tick)+1000; - sg->unit_id = UNT_USED_TRAPS; - break; - - case UNT_SEVERE_RAINSTORM: - if (battle_check_target(&src->bl, bl, BCT_ENEMY)) - skill_attack(BF_WEAPON,ss,&src->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0); - break; - case UNT_NETHERWORLD: - if (!(status_get_mode(bl)&MD_BOSS) && ss != bl && battle_check_target(&src->bl, bl, BCT_PARTY)) { - if (!(tsc && tsc->data[type])) { - sc_start(bl, type, 100, sg->skill_lv, skill_get_time2(sg->skill_id,sg->skill_lv)); - sg->limit = DIFF_TICK(tick,sg->tick); - sg->unit_id = UNT_USED_TRAPS; - } - } - break; - case UNT_THORNS_TRAP: - if (tsc) { - if (!sg->val2) { - int sec = skill_get_time2(sg->skill_id, sg->skill_lv); - if (sc_start(bl, type, 100, sg->skill_lv, sec)) { - const struct TimerData *td = tsc->data[type]?get_timer(tsc->data[type]->timer):NULL; - if (td) - sec = DIFF_TICK(td->tick, tick); - ///map_moveblock(bl, src->bl.x, src->bl.y, tick); // in official server it doesn't behave like this. [malufett] - clif_fixpos(bl); - sg->val2 = bl->id; - } else - sec = 3000; // Couldn't trap it? - sg->limit = DIFF_TICK(tick, sg->tick) + sec; - } else if (tsc->data[SC_THORNSTRAP] && bl->id == sg->val2) - skill_attack(skill_get_type(GN_THORNS_TRAP), ss, ss, bl, sg->skill_id, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION); - } - break; - - case UNT_DEMONIC_FIRE: { - TBL_PC *sd = BL_CAST(BL_PC, ss); - switch (sg->val2) { - case 1: - case 2: - default: - sc_start(bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, - skill_get_time2(sg->skill_id, sg->skill_lv)); - skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, - sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0); - break; - case 3: - skill_attack(skill_get_type(CR_ACIDDEMONSTRATION), ss, &src->bl, bl, - CR_ACIDDEMONSTRATION, sd ? pc_checkskill(sd, CR_ACIDDEMONSTRATION) : sg->skill_lv, tick, 0); - break; - - } - } - break; - - case UNT_FIRE_EXPANSION_SMOKE_POWDER: - sc_start(bl, status_skill2sc(GN_FIRE_EXPANSION_SMOKE_POWDER), 100, sg->skill_lv, 1000); - break; - - case UNT_FIRE_EXPANSION_TEAR_GAS: - sc_start(bl, status_skill2sc(GN_FIRE_EXPANSION_TEAR_GAS), 100, sg->skill_lv, 1000); - break; - - case UNT_HELLS_PLANT: - if (battle_check_target(&src->bl,bl,BCT_ENEMY) > 0) - skill_attack(skill_get_type(GN_HELLS_PLANT_ATK), ss, &src->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0); - if (ss != bl) //The caster is the only one who can step on the Plants, without destroying them - sg->limit = DIFF_TICK(tick, sg->tick) + 100; - break; - - case UNT_CLOUD_KILL: - if (tsc && !tsc->data[type]) - status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),8); - skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; - - case UNT_WARMER: - if (bl->type == BL_PC && !battle_check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON) { - int hp = 125 * sg->skill_lv; // Officially is 125 * skill_lv. - struct status_change *ssc = status_get_sc(ss); - if (ssc && ssc->data[SC_HEATER_OPTION]) - hp += hp * ssc->data[SC_HEATER_OPTION]->val3 / 100; - if (tstatus->hp != tstatus->max_hp) - clif_skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0); - if (tsc && tsc->data[SC_AKAITSUKI] && hp) - hp = ~hp + 1; - status_heal(bl, hp, 0, 0); - sc_start(bl, SC_WARMER, 100, sg->skill_lv, skill_get_time2(sg->skill_id,sg->skill_lv)); - } - break; - - case UNT_FIRE_INSIGNIA: - case UNT_WATER_INSIGNIA: - case UNT_WIND_INSIGNIA: - case UNT_EARTH_INSIGNIA: - case UNT_ZEPHYR: - sc_start(bl,type, 100, sg->skill_lv, sg->interval); - if (sg->unit_id != UNT_ZEPHYR && !battle_check_undead(tstatus->race, tstatus->def_ele)) { - int hp = tstatus->max_hp / 100; //+1% each 5s - if ((sg->val3) % 5) { //each 5s - if (tstatus->def_ele == skill_get_ele(sg->skill_id,sg->skill_lv)) { - status_heal(bl, hp, 0, 2); - } else if ((sg->unit_id == UNT_FIRE_INSIGNIA && tstatus->def_ele == ELE_EARTH) - ||(sg->unit_id == UNT_WATER_INSIGNIA && tstatus->def_ele == ELE_FIRE) - ||(sg->unit_id == UNT_WIND_INSIGNIA && tstatus->def_ele == ELE_WATER) - ||(sg->unit_id == UNT_EARTH_INSIGNIA && tstatus->def_ele == ELE_WIND) - ) { - status_heal(bl, -hp, 0, 0); - } - } - sg->val3++; //timer - if (sg->val3 > 5) sg->val3 = 0; - } - break; - - case UNT_VACUUM_EXTREME: { - // TODO: official behavior in gvg area. [malufett] - int sec = sg->limit - DIFF_TICK(tick, sg->tick); - int range = skill_get_unit_range(sg->skill_id, sg->skill_lv); + if( sg->src_id == bl->id && !(tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_BARDDANCER) ) + break; // affects self only when soullinked + heal = skill_calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true); + if( tsc->data[SC_AKAITSUKI] && heal ) + heal = ~heal + 1; + clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); + status_heal(bl, heal, 0, 0); + break; + } + + case UNT_TATAMIGAESHI: + case UNT_DEMONSTRATION: + skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + + case UNT_GOSPEL: + if (rnd()%100 > sg->skill_lv*10 || ss == bl) + break; + if (battle_check_target(ss,bl,BCT_PARTY)>0) + { // Support Effect only on party, not guild + int heal; + int i = rnd()%13; // Positive buff count + int time = skill_get_time2(sg->skill_id, sg->skill_lv); //Duration + switch (i) + { + case 0: // Heal 1~9999 HP + heal = rnd() %9999+1; + clif_skill_nodamage(ss,bl,AL_HEAL,heal,1); + status_heal(bl,heal,0,0); + break; + case 1: // End all negative status + status_change_clear_buffs(bl,2); + if (tsd) clif_gospel_info(tsd, 0x15); + break; + case 2: // Immunity to all status + sc_start(bl,SC_SCRESIST,100,100,time); + if (tsd) clif_gospel_info(tsd, 0x16); + break; + case 3: // MaxHP +100% + sc_start(bl,SC_INCMHPRATE,100,100,time); + if (tsd) clif_gospel_info(tsd, 0x17); + break; + case 4: // MaxSP +100% + sc_start(bl,SC_INCMSPRATE,100,100,time); + if (tsd) clif_gospel_info(tsd, 0x18); + break; + case 5: // All stats +20 + sc_start(bl,SC_INCALLSTATUS,100,20,time); + if (tsd) clif_gospel_info(tsd, 0x19); + break; + case 6: // Level 10 Blessing + sc_start(bl,SC_BLESSING,100,10,time); + break; + case 7: // Level 10 Increase AGI + sc_start(bl,SC_INCREASEAGI,100,10,time); + break; + case 8: // Enchant weapon with Holy element + sc_start(bl,SC_ASPERSIO,100,1,time); + if (tsd) clif_gospel_info(tsd, 0x1c); + break; + case 9: // Enchant armor with Holy element + sc_start(bl,SC_BENEDICTIO,100,1,time); + if (tsd) clif_gospel_info(tsd, 0x1d); + break; + case 10: // DEF +25% + sc_start(bl,SC_INCDEFRATE,100,25,time); + if (tsd) clif_gospel_info(tsd, 0x1e); + break; + case 11: // ATK +100% + sc_start(bl,SC_INCATKRATE,100,100,time); + if (tsd) clif_gospel_info(tsd, 0x1f); + break; + case 12: // HIT/Flee +50 + sc_start(bl,SC_INCHIT,100,50,time); + sc_start(bl,SC_INCFLEE,100,50,time); + if (tsd) clif_gospel_info(tsd, 0x20); + break; + } + } + else if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) + { // Offensive Effect + int i = rnd()%9; // Negative buff count + int time = skill_get_time2(sg->skill_id, sg->skill_lv); + switch (i) + { + case 0: // Deal 1~9999 damage + skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + case 1: // Curse + sc_start(bl,SC_CURSE,100,1,time); + break; + case 2: // Blind + sc_start(bl,SC_BLIND,100,1,time); + break; + case 3: // Poison + sc_start(bl,SC_POISON,100,1,time); + break; + case 4: // Level 10 Provoke + sc_start(bl,SC_PROVOKE,100,10,time); + break; + case 5: // DEF -100% + sc_start(bl,SC_INCDEFRATE,100,-100,time); + break; + case 6: // ATK -100% + sc_start(bl,SC_INCATKRATE,100,-100,time); + break; + case 7: // Flee -100% + sc_start(bl,SC_INCFLEERATE,100,-100,time); + break; + case 8: // Speed/ASPD -25% + sc_start4(bl,SC_GOSPEL,100,1,0,0,BCT_ENEMY,time); + break; + } + } + break; - if (tsc && !tsc->data[type] && - distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) <= range)// don't consider outer bounderies - sc_start(bl, type, 100, sg->skill_lv, sec); + case UNT_BASILICA: + { + int i = battle_check_target(&src->bl, bl, BCT_ENEMY); + if( i > 0 && !(status_get_mode(bl)&MD_BOSS) ) + { // knock-back any enemy except Boss + skill_blown(&src->bl, bl, 2, unit_getdir(bl), 0); + clif_fixpos(bl); + } - if (unit_is_walking(bl) && // wait until target stop walking - (tsc && tsc->data[type] && tsc->data[type]->val4 >= tsc->data[type]->val3-range)) - break; + if( sg->src_id != bl->id && i <= 0 ) + sc_start4(bl, type, 100, 0, 0, 0, src->bl.id, sg->interval + 100); + } + break; + + case UNT_GRAVITATION: + case UNT_EARTHSTRAIN: + case UNT_FIREWALK: + case UNT_ELECTRICWALK: + case UNT_PSYCHIC_WAVE: + skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + + case UNT_GROUNDDRIFT_WIND: + case UNT_GROUNDDRIFT_DARK: + case UNT_GROUNDDRIFT_POISON: + case UNT_GROUNDDRIFT_WATER: + case UNT_GROUNDDRIFT_FIRE: + map_foreachinrange(skill_trap_splash,&src->bl, + skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, + &src->bl,tick); + sg->unit_id = UNT_USED_TRAPS; + //clif_changetraplook(&src->bl, UNT_FIREPILLAR_ACTIVE); + sg->limit=DIFF_TICK(tick,sg->tick)+1500; + break; + /** + * 3rd stuff + **/ + case UNT_POISONSMOKE: + if( battle_check_target(ss,bl,BCT_ENEMY) > 0 && !(tsc && tsc->data[sg->val2]) && rnd()%100 < 20 ) + sc_start(bl,sg->val2,100,sg->val3,skill_get_time2(GC_POISONINGWEAPON, 1)); + break; + + case UNT_EPICLESIS: + if( bl->type == BL_PC && !battle_check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON ) + { + if( ++sg->val2 % 3 == 0 ) { + int hp, sp; + switch( sg->skill_lv ) + { + case 1: case 2: hp = 3; sp = 2; break; + case 3: case 4: hp = 4; sp = 3; break; + case 5: default: hp = 5; sp = 4; break; + } + hp = tstatus->max_hp * hp / 100; + sp = tstatus->max_sp * sp / 100; + status_heal(bl, hp, sp, 2); + sc_start(bl, type, 100, sg->skill_lv, (sg->interval * 3) + 100); + } + // Reveal hidden players every 5 seconds. + if( sg->val2 % 5 == 0 ) { + // TODO: check if other hidden status can be removed. + status_change_end(bl,SC_HIDING,INVALID_TIMER); + status_change_end(bl,SC_CLOAKING,INVALID_TIMER); + } + } + /* Enable this if kRO fix the current skill. Currently no damage on undead and demon monster. [Jobbie] + else if( battle_check_target(ss, bl, BCT_ENEMY) > 0 && battle_check_undead(tstatus->race, tstatus->def_ele) ) + skill_castend_damage_id(&src->bl, bl, sg->skill_id, sg->skill_lv, 0, 0);*/ + break; + + case UNT_STEALTHFIELD: + if( bl->id == sg->src_id ) + break; // Dont work on Self (video shows that) + case UNT_NEUTRALBARRIER: + sc_start(bl,type,100,sg->skill_lv,sg->interval + 100); + break; + + case UNT_DIMENSIONDOOR: + if( tsd && !map[bl->m].flag.noteleport ) + pc_randomwarp(tsd,3); + else if( bl->type == BL_MOB && battle_config.mob_warp&8 ) + unit_warp(bl,-1,-1,-1,3); + break; + + case UNT_REVERBERATION: + clif_changetraplook(&src->bl,UNT_USED_TRAPS); + map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); + sg->limit = DIFF_TICK(tick,sg->tick)+1000; + sg->unit_id = UNT_USED_TRAPS; + break; + + case UNT_SEVERE_RAINSTORM: + if( battle_check_target(&src->bl, bl, BCT_ENEMY) ) + skill_attack(BF_WEAPON,ss,&src->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0); + break; + case UNT_NETHERWORLD: + if( !(status_get_mode(bl)&MD_BOSS) && ss != bl && battle_check_target(&src->bl, bl, BCT_PARTY) ) { + if( !(tsc && tsc->data[type]) ){ + sc_start(bl, type, 100, sg->skill_lv, skill_get_time2(sg->skill_id,sg->skill_lv)); + sg->limit = DIFF_TICK(tick,sg->tick); + sg->unit_id = UNT_USED_TRAPS; + } + } + break; + case UNT_THORNS_TRAP: + if( tsc ) { + if( !sg->val2 ) { + int sec = skill_get_time2(sg->skill_id, sg->skill_lv); + if( sc_start(bl, type, 100, sg->skill_lv, sec) ) { + const struct TimerData* td = tsc->data[type]?get_timer(tsc->data[type]->timer):NULL; + if( td ) + sec = DIFF_TICK(td->tick, tick); + ///map_moveblock(bl, src->bl.x, src->bl.y, tick); // in official server it doesn't behave like this. [malufett] + clif_fixpos(bl); + sg->val2 = bl->id; + } else + sec = 3000; // Couldn't trap it? + sg->limit = DIFF_TICK(tick, sg->tick) + sec; + } else if( tsc->data[SC_THORNSTRAP] && bl->id == sg->val2 ) + skill_attack(skill_get_type(GN_THORNS_TRAP), ss, ss, bl, sg->skill_id, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION); + } + break; + + case UNT_DEMONIC_FIRE: { + TBL_PC* sd = BL_CAST(BL_PC, ss); + switch( sg->val2 ) { + case 1: + case 2: + default: + sc_start(bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, + skill_get_time2(sg->skill_id, sg->skill_lv)); + skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, + sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0); + break; + case 3: + skill_attack(skill_get_type(CR_ACIDDEMONSTRATION), ss, &src->bl, bl, + CR_ACIDDEMONSTRATION, sd ? pc_checkskill(sd, CR_ACIDDEMONSTRATION) : sg->skill_lv, tick, 0); + break; - if (tsc && (!tsc->data[type] || (tsc->data[type] && tsc->data[type]->val4 < 1))) - break; + } + } + break; + + case UNT_FIRE_EXPANSION_SMOKE_POWDER: + sc_start(bl, status_skill2sc(GN_FIRE_EXPANSION_SMOKE_POWDER), 100, sg->skill_lv, 1000); + break; + + case UNT_FIRE_EXPANSION_TEAR_GAS: + sc_start(bl, status_skill2sc(GN_FIRE_EXPANSION_TEAR_GAS), 100, sg->skill_lv, 1000); + break; + + case UNT_HELLS_PLANT: + if( battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 ) + skill_attack(skill_get_type(GN_HELLS_PLANT_ATK), ss, &src->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0); + if( ss != bl) //The caster is the only one who can step on the Plants, without destroying them + sg->limit = DIFF_TICK(tick, sg->tick) + 100; + break; + + case UNT_CLOUD_KILL: + if(tsc && !tsc->data[type]) + status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),8); + skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + + case UNT_WARMER: + if( bl->type == BL_PC && !battle_check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON ) { + int hp = 125 * sg->skill_lv; // Officially is 125 * skill_lv. + struct status_change *ssc = status_get_sc(ss); + if( ssc && ssc->data[SC_HEATER_OPTION] ) + hp += hp * ssc->data[SC_HEATER_OPTION]->val3 / 100; + if( tstatus->hp != tstatus->max_hp ) + clif_skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0); + if( tsc && tsc->data[SC_AKAITSUKI] && hp ) + hp = ~hp + 1; + status_heal(bl, hp, 0, 0); + sc_start(bl, SC_WARMER, 100, sg->skill_lv, skill_get_time2(sg->skill_id,sg->skill_lv)); + } + break; + + case UNT_FIRE_INSIGNIA: + case UNT_WATER_INSIGNIA: + case UNT_WIND_INSIGNIA: + case UNT_EARTH_INSIGNIA: + case UNT_ZEPHYR: + sc_start(bl,type, 100, sg->skill_lv, sg->interval); + if (sg->unit_id != UNT_ZEPHYR && !battle_check_undead(tstatus->race, tstatus->def_ele)) { + int hp = tstatus->max_hp / 100; //+1% each 5s + if ((sg->val3) % 5) { //each 5s + if (tstatus->def_ele == skill_get_ele(sg->skill_id,sg->skill_lv)){ + status_heal(bl, hp, 0, 2); + } else if((sg->unit_id == UNT_FIRE_INSIGNIA && tstatus->def_ele == ELE_EARTH) + ||(sg->unit_id == UNT_WATER_INSIGNIA && tstatus->def_ele == ELE_FIRE) + ||(sg->unit_id == UNT_WIND_INSIGNIA && tstatus->def_ele == ELE_WATER) + ||(sg->unit_id == UNT_EARTH_INSIGNIA && tstatus->def_ele == ELE_WIND) + ){ + status_heal(bl, -hp, 0, 0); + } + } + sg->val3++; //timer + if (sg->val3 > 5) sg->val3 = 0; + } + break; - if (unit_is_walking(bl) && - distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) > range) // going outside of boundaries? then force it to stop - unit_stop_walking(bl,1); + case UNT_VACUUM_EXTREME: + {// TODO: official behavior in gvg area. [malufett] + int sec = sg->limit - DIFF_TICK(tick, sg->tick); + int range = skill_get_unit_range(sg->skill_id, sg->skill_lv); - if (!unit_is_walking(bl) && - distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) <= range && // only snap if the target is inside the range or - src->bl.x != bl->x && src->bl.y != bl->y) { // diagonal position parallel to VE's center - unit_movepos(bl, src->bl.x, src->bl.y, 0, 0); - clif_fixpos(bl); - } - } - break; + if( tsc && !tsc->data[type] && + distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) <= range)// don't consider outer bounderies + sc_start(bl, type, 100, sg->skill_lv, sec); - case UNT_FIRE_MANTLE: - if (battle_check_target(&src->bl, bl, BCT_ENEMY)) - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; + if( unit_is_walking(bl) && // wait until target stop walking + ( tsc && tsc->data[type] && tsc->data[type]->val4 >= tsc->data[type]->val3-range )) + break; - case UNT_ZENKAI_WATER: - case UNT_ZENKAI_LAND: - case UNT_ZENKAI_FIRE: - case UNT_ZENKAI_WIND: - if (battle_check_target(&src->bl,bl,BCT_ENEMY) > 0) { - switch (sg->unit_id) { - case UNT_ZENKAI_WATER: - sc_start(bl, SC_CRYSTALIZE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_FREEZING, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - break; - case UNT_ZENKAI_LAND: - sc_start(bl, SC_STONE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_POISON, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - break; - case UNT_ZENKAI_FIRE: - sc_start(bl, SC_BURNING, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - break; - case UNT_ZENKAI_WIND: - sc_start(bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_DEEPSLEEP, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - break; - } - } else - sc_start2(bl,type,100,sg->val1,sg->val2,skill_get_time2(sg->skill_id, sg->skill_lv)); - break; + if( tsc && ( !tsc->data[type] || (tsc->data[type] && tsc->data[type]->val4 < 1 ) ) ) + break; - case UNT_MAKIBISHI: - skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - sg->limit = DIFF_TICK(tick, sg->tick); - sg->unit_id = UNT_USED_TRAPS; - break; + if( unit_is_walking(bl) && + distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) > range )// going outside of boundaries? then force it to stop + unit_stop_walking(bl,1); - case UNT_LAVA_SLIDE: - skill_attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - if (++sg->val1 > 4) //after 5 stop hit and destroy me - sg->limit = DIFF_TICK(tick, sg->tick); - break; - case UNT_POISON_MIST: - skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - status_change_start(bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), 2|8); - break; - } + if( !unit_is_walking(bl) && + distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) <= range && // only snap if the target is inside the range or + src->bl.x != bl->x && src->bl.y != bl->y){// diagonal position parallel to VE's center + unit_movepos(bl, src->bl.x, src->bl.y, 0, 0); + clif_fixpos(bl); + } + } + break; + + case UNT_FIRE_MANTLE: + if( battle_check_target(&src->bl, bl, BCT_ENEMY) ) + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + + case UNT_ZENKAI_WATER: + case UNT_ZENKAI_LAND: + case UNT_ZENKAI_FIRE: + case UNT_ZENKAI_WIND: + if( battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 ){ + switch( sg->unit_id ){ + case UNT_ZENKAI_WATER: + sc_start(bl, SC_CRYSTALIZE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_FREEZING, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + break; + case UNT_ZENKAI_LAND: + sc_start(bl, SC_STONE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_POISON, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + break; + case UNT_ZENKAI_FIRE: + sc_start(bl, SC_BURNING, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + break; + case UNT_ZENKAI_WIND: + sc_start(bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_DEEPSLEEP, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + break; + } + }else + sc_start2(bl,type,100,sg->val1,sg->val2,skill_get_time2(sg->skill_id, sg->skill_lv)); + break; + + case UNT_MAKIBISHI: + skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + sg->limit = DIFF_TICK(tick, sg->tick); + sg->unit_id = UNT_USED_TRAPS; + break; + + case UNT_LAVA_SLIDE: + skill_attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + if(++sg->val1 > 4) //after 5 stop hit and destroy me + sg->limit = DIFF_TICK(tick, sg->tick); + break; + case UNT_POISON_MIST: + skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + status_change_start(bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), 2|8); + break; + } - if (bl->type == BL_MOB && ss != bl) - mobskill_event((TBL_MOB *)bl, ss, tick, MSC_SKILLUSED|(skillid<<16)); + if (bl->type == BL_MOB && ss != bl) + mobskill_event((TBL_MOB*)bl, ss, tick, MSC_SKILLUSED|(skillid<<16)); - return skillid; + return skillid; } /*========================================== * Triggered when a char steps out of a skill cell *------------------------------------------*/ -int skill_unit_onout(struct skill_unit *src, struct block_list *bl, unsigned int tick) +int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned int tick) { - struct skill_unit_group *sg; - struct status_change *sc; - struct status_change_entry *sce; - enum sc_type type; - - nullpo_ret(src); - nullpo_ret(bl); - nullpo_ret(sg=src->group); - sc = status_get_sc(bl); - type = status_skill2sc(sg->skill_id); - sce = (sc && type != -1)?sc->data[type]:NULL; - - if (bl->prev==NULL || - (status_isdead(bl) && sg->unit_id != UNT_ANKLESNARE && sg->unit_id != UNT_SPIDERWEB)) //Need to delete the trap if the source died. - return 0; - - switch (sg->unit_id) { - case UNT_SAFETYWALL: - case UNT_PNEUMA: - case UNT_EPICLESIS://Arch Bishop - case UNT_NEUTRALBARRIER: - case UNT_STEALTHFIELD: - if (sce) - status_change_end(bl, type, INVALID_TIMER); - break; - - case UNT_BASILICA: - if (sce && sce->val4 == src->bl.id) - status_change_end(bl, type, INVALID_TIMER); - break; - case UNT_HERMODE: //Clear Hermode if the owner moved. - if (sce && sce->val3 == BCT_SELF && sce->val4 == sg->group_id) - status_change_end(bl, type, INVALID_TIMER); - break; - - case UNT_SPIDERWEB: { - struct block_list *target = map_id2bl(sg->val2); - if (target && target==bl) { - if (sce && sce->val3 == sg->group_id) - status_change_end(bl, type, INVALID_TIMER); - sg->limit = DIFF_TICK(tick,sg->tick)+1000; - } - break; - } - } - return sg->skill_id; + struct skill_unit_group *sg; + struct status_change *sc; + struct status_change_entry *sce; + enum sc_type type; + + nullpo_ret(src); + nullpo_ret(bl); + nullpo_ret(sg=src->group); + sc = status_get_sc(bl); + type = status_skill2sc(sg->skill_id); + sce = (sc && type != -1)?sc->data[type]:NULL; + + if( bl->prev==NULL || + (status_isdead(bl) && sg->unit_id != UNT_ANKLESNARE && sg->unit_id != UNT_SPIDERWEB) ) //Need to delete the trap if the source died. + return 0; + + switch(sg->unit_id){ + case UNT_SAFETYWALL: + case UNT_PNEUMA: + case UNT_EPICLESIS://Arch Bishop + case UNT_NEUTRALBARRIER: + case UNT_STEALTHFIELD: + if (sce) + status_change_end(bl, type, INVALID_TIMER); + break; + + case UNT_BASILICA: + if( sce && sce->val4 == src->bl.id ) + status_change_end(bl, type, INVALID_TIMER); + break; + case UNT_HERMODE: //Clear Hermode if the owner moved. + if (sce && sce->val3 == BCT_SELF && sce->val4 == sg->group_id) + status_change_end(bl, type, INVALID_TIMER); + break; + + case UNT_SPIDERWEB: + { + struct block_list *target = map_id2bl(sg->val2); + if (target && target==bl) + { + if (sce && sce->val3 == sg->group_id) + status_change_end(bl, type, INVALID_TIMER); + sg->limit = DIFF_TICK(tick,sg->tick)+1000; + } + break; + } + } + return sg->skill_id; } /*========================================== * Triggered when a char steps out of a skill group (entirely) [Skotlex] *------------------------------------------*/ -static int skill_unit_onleft(int skill_id, struct block_list *bl, unsigned int tick) +static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int tick) { - struct status_change *sc; - struct status_change_entry *sce; - enum sc_type type; - - sc = status_get_sc(bl); - if (sc && !sc->count) - sc = NULL; - - type = status_skill2sc(skill_id); - sce = (sc && type != -1)?sc->data[type]:NULL; - - switch (skill_id) { - case WZ_QUAGMIRE: - if (bl->type==BL_MOB) - break; - if (sce) - status_change_end(bl, type, INVALID_TIMER); - break; - - case BD_LULLABY: - case BD_RICHMANKIM: - case BD_ETERNALCHAOS: - case BD_DRUMBATTLEFIELD: - case BD_RINGNIBELUNGEN: - case BD_ROKISWEIL: - case BD_INTOABYSS: - case BD_SIEGFRIED: - if (sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == skill_id) { - //Check if you just stepped out of your ensemble skill to cancel dancing. [Skotlex] - //We don't check for SC_LONGING because someone could always have knocked you back and out of the song/dance. - //FIXME: This code is not perfect, it doesn't checks for the real ensemble's owner, - //it only checks if you are doing the same ensemble. So if there's two chars doing an ensemble - //which overlaps, by stepping outside of the other parther's ensemble will cause you to cancel - //your own. Let's pray that scenario is pretty unlikely and noone will complain too much about it. - status_change_end(bl, SC_DANCING, INVALID_TIMER); - } - case MH_STEINWAND: - case MG_SAFETYWALL: - case AL_PNEUMA: - case SA_VOLCANO: - case SA_DELUGE: - case SA_VIOLENTGALE: - case CG_HERMODE: - case HW_GRAVITATION: - case NJ_SUITON: - case SC_MAELSTROM: - case EL_WATER_BARRIER: - case EL_ZEPHYR: - case EL_POWER_OF_GAIA: - case SO_FIRE_INSIGNIA: - case SO_WATER_INSIGNIA: - case SO_WIND_INSIGNIA: - case SO_EARTH_INSIGNIA: - if (sce) - status_change_end(bl, type, INVALID_TIMER); - break; - case SC_BLOODYLUST: - if (sce) { - status_change_end(bl, type, INVALID_TIMER); - status_set_sp(bl, 0, 0); //set sp to 0 when quitting zone - } - break; - - case BA_POEMBRAGI: - case BA_WHISTLE: - case BA_ASSASSINCROSS: - case BA_APPLEIDUN: - case DC_HUMMING: - case DC_DONTFORGETME: - case DC_FORTUNEKISS: - case DC_SERVICEFORYOU: - if (sce) { - if (sce->val4 == 2) { /* We have the status but we're not elegible for it, so we take it away. (bugreport:4591) */ - if (!(sc && sc->data[SC_DANCING] && sc->data[SC_DANCING]->val2)) /* check if we're still in the skill */ - status_change_end(bl,type,INVALID_TIMER); - } else { - delete_timer(sce->timer, status_change_timer); - //NOTE: It'd be nice if we could get the skill_lv for a more accurate extra time, but alas... - //not possible on our current implementation. - sce->val4 = 1; //Store the fact that this is a "reduced" duration effect. - sce->timer = add_timer(tick+skill_get_time2(skill_id,1), status_change_timer, bl->id, type); - } - } - break; - case PF_FOGWALL: - if (sce) { - status_change_end(bl, type, INVALID_TIMER); - if ((sce=sc->data[SC_BLIND])) { - if (bl->type == BL_PC) //Players get blind ended inmediately, others have it still for 30 secs. [Skotlex] - status_change_end(bl, SC_BLIND, INVALID_TIMER); - else { - delete_timer(sce->timer, status_change_timer); - sce->timer = add_timer(30000+tick, status_change_timer, bl->id, SC_BLIND); - } - } - } - break; - case GD_LEADERSHIP: - case GD_GLORYWOUNDS: - case GD_SOULCOLD: - case GD_HAWKEYES: - if (!(sce && sce->val4)) - status_change_end(bl, type, INVALID_TIMER); - break; - } + struct status_change *sc; + struct status_change_entry *sce; + enum sc_type type; + + sc = status_get_sc(bl); + if (sc && !sc->count) + sc = NULL; + + type = status_skill2sc(skill_id); + sce = (sc && type != -1)?sc->data[type]:NULL; + + switch (skill_id) + { + case WZ_QUAGMIRE: + if (bl->type==BL_MOB) + break; + if (sce) + status_change_end(bl, type, INVALID_TIMER); + break; + + case BD_LULLABY: + case BD_RICHMANKIM: + case BD_ETERNALCHAOS: + case BD_DRUMBATTLEFIELD: + case BD_RINGNIBELUNGEN: + case BD_ROKISWEIL: + case BD_INTOABYSS: + case BD_SIEGFRIED: + if(sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == skill_id) + { //Check if you just stepped out of your ensemble skill to cancel dancing. [Skotlex] + //We don't check for SC_LONGING because someone could always have knocked you back and out of the song/dance. + //FIXME: This code is not perfect, it doesn't checks for the real ensemble's owner, + //it only checks if you are doing the same ensemble. So if there's two chars doing an ensemble + //which overlaps, by stepping outside of the other parther's ensemble will cause you to cancel + //your own. Let's pray that scenario is pretty unlikely and noone will complain too much about it. + status_change_end(bl, SC_DANCING, INVALID_TIMER); + } + case MH_STEINWAND: + case MG_SAFETYWALL: + case AL_PNEUMA: + case SA_VOLCANO: + case SA_DELUGE: + case SA_VIOLENTGALE: + case CG_HERMODE: + case HW_GRAVITATION: + case NJ_SUITON: + case SC_MAELSTROM: + case EL_WATER_BARRIER: + case EL_ZEPHYR: + case EL_POWER_OF_GAIA: + case SO_FIRE_INSIGNIA: + case SO_WATER_INSIGNIA: + case SO_WIND_INSIGNIA: + case SO_EARTH_INSIGNIA: + if (sce) + status_change_end(bl, type, INVALID_TIMER); + break; + case SC_BLOODYLUST: + if (sce) { + status_change_end(bl, type, INVALID_TIMER); + status_set_sp(bl, 0, 0); //set sp to 0 when quitting zone + } + break; + + case BA_POEMBRAGI: + case BA_WHISTLE: + case BA_ASSASSINCROSS: + case BA_APPLEIDUN: + case DC_HUMMING: + case DC_DONTFORGETME: + case DC_FORTUNEKISS: + case DC_SERVICEFORYOU: + if (sce) { + if( sce->val4 == 2 ) {/* We have the status but we're not elegible for it, so we take it away. (bugreport:4591) */ + if( !( sc && sc->data[SC_DANCING] && sc->data[SC_DANCING]->val2 ) )/* check if we're still in the skill */ + status_change_end(bl,type,INVALID_TIMER); + } else { + delete_timer(sce->timer, status_change_timer); + //NOTE: It'd be nice if we could get the skill_lv for a more accurate extra time, but alas... + //not possible on our current implementation. + sce->val4 = 1; //Store the fact that this is a "reduced" duration effect. + sce->timer = add_timer(tick+skill_get_time2(skill_id,1), status_change_timer, bl->id, type); + } + } + break; + case PF_FOGWALL: + if (sce) + { + status_change_end(bl, type, INVALID_TIMER); + if ((sce=sc->data[SC_BLIND])) + { + if (bl->type == BL_PC) //Players get blind ended inmediately, others have it still for 30 secs. [Skotlex] + status_change_end(bl, SC_BLIND, INVALID_TIMER); + else { + delete_timer(sce->timer, status_change_timer); + sce->timer = add_timer(30000+tick, status_change_timer, bl->id, SC_BLIND); + } + } + } + break; + case GD_LEADERSHIP: + case GD_GLORYWOUNDS: + case GD_SOULCOLD: + case GD_HAWKEYES: + if( !(sce && sce->val4) ) + status_change_end(bl, type, INVALID_TIMER); + break; + } - return skill_id; + return skill_id; } /*========================================== @@ -12162,1059 +12030,1040 @@ static int skill_unit_onleft(int skill_id, struct block_list *bl, unsigned int t * flag&1: Invoke onplace function (otherwise invoke onout) * flag&4: Invoke a onleft call (the unit might be scheduled for deletion) *------------------------------------------*/ -static int skill_unit_effect(struct block_list *bl, va_list ap) +static int skill_unit_effect (struct block_list* bl, va_list ap) { - struct skill_unit *unit = va_arg(ap,struct skill_unit *); - struct skill_unit_group *group = unit->group; - unsigned int tick = va_arg(ap,unsigned int); - unsigned int flag = va_arg(ap,unsigned int); - int skill_id; - bool dissonance; - - if ((!unit->alive && !(flag&4)) || bl->prev == NULL) - return 0; - - nullpo_ret(group); - - dissonance = skill_dance_switch(unit, 0); - - //Necessary in case the group is deleted after calling on_place/on_out [Skotlex] - skill_id = group->skill_id; - - //Target-type check. - if (!(group->bl_flag&bl->type && battle_check_target(&unit->bl,bl,group->target_flag)>0)) { - if (flag&4 && ((group->src_id == bl->id && group->state.song_dance&0x2) || skill_get_inf2(skill_id)&INF2_SONG_DANCE)) - skill_unit_onleft(skill_id, bl, tick);//Ensemble check to terminate it. - } else { - if (flag&1) - skill_unit_onplace(unit,bl,tick); - else - skill_unit_onout(unit,bl,tick); - - if (flag&4) - skill_unit_onleft(skill_id, bl, tick); - } + struct skill_unit* unit = va_arg(ap,struct skill_unit*); + struct skill_unit_group* group = unit->group; + unsigned int tick = va_arg(ap,unsigned int); + unsigned int flag = va_arg(ap,unsigned int); + int skill_id; + bool dissonance; + + if( (!unit->alive && !(flag&4)) || bl->prev == NULL ) + return 0; + + nullpo_ret(group); + + dissonance = skill_dance_switch(unit, 0); + + //Necessary in case the group is deleted after calling on_place/on_out [Skotlex] + skill_id = group->skill_id; + + //Target-type check. + if( !(group->bl_flag&bl->type && battle_check_target(&unit->bl,bl,group->target_flag)>0) ) { + if( flag&4 && ((group->src_id == bl->id && group->state.song_dance&0x2) || skill_get_inf2(skill_id)&INF2_SONG_DANCE) ) + skill_unit_onleft(skill_id, bl, tick);//Ensemble check to terminate it. + } else { + if( flag&1 ) + skill_unit_onplace(unit,bl,tick); + else + skill_unit_onout(unit,bl,tick); + + if( flag&4 ) + skill_unit_onleft(skill_id, bl, tick); + } - if (dissonance) skill_dance_switch(unit, 1); + if( dissonance ) skill_dance_switch(unit, 1); - return 0; + return 0; } /*========================================== * *------------------------------------------*/ -int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, int damage, unsigned int tick) +int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int damage, unsigned int tick) { - struct skill_unit_group *sg; - - nullpo_ret(src); - nullpo_ret(sg=src->group); - - switch (sg->unit_id) { - case UNT_BLASTMINE: - case UNT_SKIDTRAP: - case UNT_LANDMINE: - case UNT_SHOCKWAVE: - case UNT_SANDMAN: - case UNT_FLASHER: - case UNT_CLAYMORETRAP: - case UNT_FREEZINGTRAP: - case UNT_TALKIEBOX: - case UNT_ANKLESNARE: - case UNT_ICEWALL: - case UNT_REVERBERATION: - case UNT_WALLOFTHORN: - src->val1-=damage; - break; - default: - damage = 0; - break; - } - return damage; + struct skill_unit_group *sg; + + nullpo_ret(src); + nullpo_ret(sg=src->group); + + switch( sg->unit_id ) { + case UNT_BLASTMINE: + case UNT_SKIDTRAP: + case UNT_LANDMINE: + case UNT_SHOCKWAVE: + case UNT_SANDMAN: + case UNT_FLASHER: + case UNT_CLAYMORETRAP: + case UNT_FREEZINGTRAP: + case UNT_TALKIEBOX: + case UNT_ANKLESNARE: + case UNT_ICEWALL: + case UNT_REVERBERATION: + case UNT_WALLOFTHORN: + src->val1-=damage; + break; + default: + damage = 0; + break; + } + return damage; } /*========================================== * *------------------------------------------*/ -static int skill_check_condition_char_sub(struct block_list *bl, va_list ap) +static int skill_check_condition_char_sub (struct block_list *bl, va_list ap) { - int *c, skillid; - struct block_list *src; - struct map_session_data *sd; - struct map_session_data *tsd; - int *p_sd; //Contains the list of characters found. - - nullpo_ret(bl); - nullpo_ret(tsd=(struct map_session_data *)bl); - nullpo_ret(src=va_arg(ap,struct block_list *)); - nullpo_ret(sd=(struct map_session_data *)src); - - c=va_arg(ap,int *); - p_sd = va_arg(ap, int *); - skillid = va_arg(ap,int); - - if (((skillid != PR_BENEDICTIO && *c >=1) || *c >=2) && !(skill_get_inf2(skillid)&INF2_CHORUS_SKILL)) - return 0; //Partner found for ensembles, or the two companions for Benedictio. [Skotlex] - - if (bl == src) - return 0; - - if (pc_isdead(tsd)) - return 0; - - if (tsd->sc.data[SC_SILENCE] || (tsd->sc.opt1 && tsd->sc.opt1 != OPT1_BURNING)) - return 0; - - if (skill_get_inf2(skillid)&INF2_CHORUS_SKILL) { - if (tsd->status.party_id == sd->status.party_id && (tsd->class_&MAPID_THIRDMASK) == MAPID_MINSTRELWANDERER) - p_sd[(*c)++] = tsd->bl.id; - return 1; - } else { - - switch (skillid) { - case PR_BENEDICTIO: { - int dir = map_calc_dir(&sd->bl,tsd->bl.x,tsd->bl.y); - dir = (unit_getdir(&sd->bl) + dir)%8; //This adjusts dir to account for the direction the sd is facing. - if ((tsd->class_&MAPID_BASEMASK) == MAPID_ACOLYTE && (dir == 2 || dir == 6) //Must be standing to the left/right of Priest. - && sd->status.sp >= 10) - p_sd[(*c)++]=tsd->bl.id; - return 1; - } - case AB_ADORAMUS: - // Adoramus does not consume Blue Gemstone when there is at least 1 Priest class next to the caster - if ((tsd->class_&MAPID_UPPERMASK) == MAPID_PRIEST) - p_sd[(*c)++] = tsd->bl.id; - return 1; - case WL_COMET: - // Comet does not consume Red Gemstones when there is at least 1 Warlock class next to the caster - if ((sd->class_&MAPID_THIRDMASK) == MAPID_WARLOCK) - p_sd[(*c)++] = tsd->bl.id; - return 1; - case LG_RAYOFGENESIS: - if (tsd->status.party_id == sd->status.party_id && (tsd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD && - tsd->sc.data[SC_BANDING]) - p_sd[(*c)++] = tsd->bl.id; - return 1; - default: { //Warning: Assuming Ensemble Dance/Songs for code speed. [Skotlex] - int skilllv; - if (pc_issit(tsd) || !unit_can_move(&tsd->bl)) - return 0; - if (sd->status.sex != tsd->status.sex && - (tsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && - (skilllv = pc_checkskill(tsd, skillid)) > 0 && - (tsd->weapontype1==W_MUSICAL || tsd->weapontype1==W_WHIP) && - sd->status.party_id && tsd->status.party_id && - sd->status.party_id == tsd->status.party_id && - !tsd->sc.data[SC_DANCING]) { - p_sd[(*c)++]=tsd->bl.id; - return skilllv; - } else { - return 0; - } - } - break; - } + int *c, skillid; + struct block_list *src; + struct map_session_data *sd; + struct map_session_data *tsd; + int *p_sd; //Contains the list of characters found. + + nullpo_ret(bl); + nullpo_ret(tsd=(struct map_session_data*)bl); + nullpo_ret(src=va_arg(ap,struct block_list *)); + nullpo_ret(sd=(struct map_session_data*)src); + + c=va_arg(ap,int *); + p_sd = va_arg(ap, int *); + skillid = va_arg(ap,int); + + if ( ((skillid != PR_BENEDICTIO && *c >=1) || *c >=2) && !(skill_get_inf2(skillid)&INF2_CHORUS_SKILL) ) + return 0; //Partner found for ensembles, or the two companions for Benedictio. [Skotlex] + + if (bl == src) + return 0; + + if(pc_isdead(tsd)) + return 0; + + if (tsd->sc.data[SC_SILENCE] || ( tsd->sc.opt1 && tsd->sc.opt1 != OPT1_BURNING )) + return 0; + + if( skill_get_inf2(skillid)&INF2_CHORUS_SKILL ) { + if( tsd->status.party_id == sd->status.party_id && (tsd->class_&MAPID_THIRDMASK) == MAPID_MINSTRELWANDERER ) + p_sd[(*c)++] = tsd->bl.id; + return 1; + } else { + + switch(skillid) { + case PR_BENEDICTIO: { + int dir = map_calc_dir(&sd->bl,tsd->bl.x,tsd->bl.y); + dir = (unit_getdir(&sd->bl) + dir)%8; //This adjusts dir to account for the direction the sd is facing. + if ((tsd->class_&MAPID_BASEMASK) == MAPID_ACOLYTE && (dir == 2 || dir == 6) //Must be standing to the left/right of Priest. + && sd->status.sp >= 10) + p_sd[(*c)++]=tsd->bl.id; + return 1; + } + case AB_ADORAMUS: + // Adoramus does not consume Blue Gemstone when there is at least 1 Priest class next to the caster + if( (tsd->class_&MAPID_UPPERMASK) == MAPID_PRIEST ) + p_sd[(*c)++] = tsd->bl.id; + return 1; + case WL_COMET: + // Comet does not consume Red Gemstones when there is at least 1 Warlock class next to the caster + if( ( sd->class_&MAPID_THIRDMASK ) == MAPID_WARLOCK ) + p_sd[(*c)++] = tsd->bl.id; + return 1; + case LG_RAYOFGENESIS: + if( tsd->status.party_id == sd->status.party_id && (tsd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD && + tsd->sc.data[SC_BANDING] ) + p_sd[(*c)++] = tsd->bl.id; + return 1; + default: //Warning: Assuming Ensemble Dance/Songs for code speed. [Skotlex] + { + int skilllv; + if(pc_issit(tsd) || !unit_can_move(&tsd->bl)) + return 0; + if (sd->status.sex != tsd->status.sex && + (tsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && + (skilllv = pc_checkskill(tsd, skillid)) > 0 && + (tsd->weapontype1==W_MUSICAL || tsd->weapontype1==W_WHIP) && + sd->status.party_id && tsd->status.party_id && + sd->status.party_id == tsd->status.party_id && + !tsd->sc.data[SC_DANCING]) + { + p_sd[(*c)++]=tsd->bl.id; + return skilllv; + } else { + return 0; + } + } + break; + } - } - return 0; + } + return 0; } /*========================================== * Checks and stores partners for ensemble skills [Skotlex] *------------------------------------------*/ -int skill_check_pc_partner(struct map_session_data *sd, short skill_id, short *skill_lv, int range, int cast_flag) +int skill_check_pc_partner (struct map_session_data *sd, short skill_id, short* skill_lv, int range, int cast_flag) { - static int c=0; - static int p_sd[2] = { 0, 0 }; - int i; - bool is_chorus = (skill_get_inf2(skill_id)&INF2_CHORUS_SKILL); - - if (!battle_config.player_skill_partner_check || pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL)) - return is_chorus ? MAX_PARTY : 99; //As if there were infinite partners. - - if (cast_flag) { //Execute the skill on the partners. - struct map_session_data *tsd; - switch (skill_id) { - case PR_BENEDICTIO: - for (i = 0; i < c; i++) { - if ((tsd = map_id2sd(p_sd[i])) != NULL) - status_charge(&tsd->bl, 0, 10); - } - return c; - case AB_ADORAMUS: - if (c > 0 && (tsd = map_id2sd(p_sd[0])) != NULL) { - i = 2 * (*skill_lv); - status_charge(&tsd->bl, 0, i); - } - break; - case WM_GREAT_ECHO: - for (i = 0; i < c; i++) { - if ((tsd = map_id2sd(p_sd[i])) != NULL) - status_zap(&tsd->bl,0,skill_get_sp(skill_id,*skill_lv)/c); - } - break; - default: //Warning: Assuming Ensemble skills here (for speed) - if (is_chorus) - break;//Chorus skills are not to be parsed as ensambles - if (c > 0 && sd->sc.data[SC_DANCING] && (tsd = map_id2sd(p_sd[0])) != NULL) { - sd->sc.data[SC_DANCING]->val4 = tsd->bl.id; - sc_start4(&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING]->val2,*skill_lv,sd->bl.id,skill_get_time(skill_id,*skill_lv)+1000); - clif_skill_nodamage(&tsd->bl, &sd->bl, skill_id, *skill_lv, 1); - tsd->skillid_dance = skill_id; - tsd->skilllv_dance = *skill_lv; - } - return c; - } - } - - //Else: new search for partners. - c = 0; - memset(p_sd, 0, sizeof(p_sd)); - if (is_chorus) - i = party_foreachsamemap(skill_check_condition_char_sub,sd,AREA_SIZE,&sd->bl, &c, &p_sd, skill_id, *skill_lv); - else - i = map_foreachinrange(skill_check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id); - - if (skill_id != PR_BENEDICTIO && skill_id != AB_ADORAMUS && skill_id != WL_COMET) //Apply the average lv to encore skills. - *skill_lv = (i+(*skill_lv))/(c+1); //I know c should be one, but this shows how it could be used for the average of n partners. - return c; + static int c=0; + static int p_sd[2] = { 0, 0 }; + int i; + bool is_chorus = ( skill_get_inf2(skill_id)&INF2_CHORUS_SKILL ); + + if (!battle_config.player_skill_partner_check || pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL)) + return is_chorus ? MAX_PARTY : 99; //As if there were infinite partners. + + if (cast_flag) { //Execute the skill on the partners. + struct map_session_data* tsd; + switch (skill_id) { + case PR_BENEDICTIO: + for (i = 0; i < c; i++) { + if ((tsd = map_id2sd(p_sd[i])) != NULL) + status_charge(&tsd->bl, 0, 10); + } + return c; + case AB_ADORAMUS: + if( c > 0 && (tsd = map_id2sd(p_sd[0])) != NULL ) { + i = 2 * (*skill_lv); + status_charge(&tsd->bl, 0, i); + } + break; + case WM_GREAT_ECHO: + for( i = 0; i < c; i++ ) { + if( (tsd = map_id2sd(p_sd[i])) != NULL ) + status_zap(&tsd->bl,0,skill_get_sp(skill_id,*skill_lv)/c); + } + break; + default: //Warning: Assuming Ensemble skills here (for speed) + if( is_chorus ) + break;//Chorus skills are not to be parsed as ensambles + if (c > 0 && sd->sc.data[SC_DANCING] && (tsd = map_id2sd(p_sd[0])) != NULL) { + sd->sc.data[SC_DANCING]->val4 = tsd->bl.id; + sc_start4(&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING]->val2,*skill_lv,sd->bl.id,skill_get_time(skill_id,*skill_lv)+1000); + clif_skill_nodamage(&tsd->bl, &sd->bl, skill_id, *skill_lv, 1); + tsd->skillid_dance = skill_id; + tsd->skilllv_dance = *skill_lv; + } + return c; + } + } + + //Else: new search for partners. + c = 0; + memset (p_sd, 0, sizeof(p_sd)); + if( is_chorus ) + i = party_foreachsamemap(skill_check_condition_char_sub,sd,AREA_SIZE,&sd->bl, &c, &p_sd, skill_id, *skill_lv); + else + i = map_foreachinrange(skill_check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id); + + if ( skill_id != PR_BENEDICTIO && skill_id != AB_ADORAMUS && skill_id != WL_COMET ) //Apply the average lv to encore skills. + *skill_lv = (i+(*skill_lv))/(c+1); //I know c should be one, but this shows how it could be used for the average of n partners. + return c; } /*========================================== * *------------------------------------------*/ -static int skill_check_condition_mob_master_sub(struct block_list *bl, va_list ap) +static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap) { - int *c,src_id,mob_class,skill; - struct mob_data *md; + int *c,src_id,mob_class,skill; + struct mob_data *md; - md=(struct mob_data *)bl; - src_id=va_arg(ap,int); - mob_class=va_arg(ap,int); - skill=va_arg(ap,int); - c=va_arg(ap,int *); + md=(struct mob_data*)bl; + src_id=va_arg(ap,int); + mob_class=va_arg(ap,int); + skill=va_arg(ap,int); + c=va_arg(ap,int *); - if (md->master_id != src_id || md->special_state.ai != (unsigned)(skill == AM_SPHEREMINE?2:skill == KO_ZANZOU?4:3)) - return 0; //Non alchemist summoned mobs have nothing to do here. + if( md->master_id != src_id || md->special_state.ai != (unsigned)(skill == AM_SPHEREMINE?2:skill == KO_ZANZOU?4:3) ) + return 0; //Non alchemist summoned mobs have nothing to do here. - if (md->class_==mob_class) - (*c)++; + if(md->class_==mob_class) + (*c)++; - return 1; + return 1; } /*========================================== * Determines if a given skill should be made to consume ammo * when used by the player. [Skotlex] *------------------------------------------*/ -int skill_isammotype(struct map_session_data *sd, int skill) +int skill_isammotype (struct map_session_data *sd, int skill) { - return ( - battle_config.arrow_decrement==2 && - (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) && - skill != HT_PHANTASMIC && - skill_get_type(skill) == BF_WEAPON && - !(skill_get_nk(skill)&NK_NO_DAMAGE) && - !skill_get_spiritball(skill,1) //Assume spirit spheres are used as ammo instead. - ); + return ( + battle_config.arrow_decrement==2 && + (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) && + skill != HT_PHANTASMIC && + skill_get_type(skill) == BF_WEAPON && + !(skill_get_nk(skill)&NK_NO_DAMAGE) && + !skill_get_spiritball(skill,1) //Assume spirit spheres are used as ammo instead. + ); } -int skill_check_condition_castbegin(struct map_session_data *sd, short skill, short lv) -{ - struct status_data *status; - struct status_change *sc; - struct skill_condition require; - int i; - - nullpo_ret(sd); - - if (lv <= 0 || sd->chatID) return 0; - - if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill) { - //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex] - sd->state.arrow_atk = skill_get_ammotype(skill)?1:0; //Need to do arrow state check. - sd->spiritball_old = sd->spiritball; //Need to do Spiritball check. - return 1; - } - - switch (sd->menuskill_id) { - case AM_PHARMACY: - switch (skill) { - case AM_PHARMACY: - case AC_MAKINGARROW: - case BS_REPAIRWEAPON: - case AM_TWILIGHT1: - case AM_TWILIGHT2: - case AM_TWILIGHT3: - return 0; - } - break; - case GN_MIX_COOKING: - case GN_MAKEBOMB: - case GN_S_PHARMACY: - case GN_CHANGEMATERIAL: - if (sd->menuskill_id != skill) - return 0; - break; - } - status = &sd->battle_status; - sc = &sd->sc; - if (!sc->count) - sc = NULL; - - if (sd->skillitem == skill) { - if (sd->state.abra_flag) // Hocus-Pocus was used. [Inkfish] - sd->state.abra_flag = 0; - else { - // When a target was selected, consume items that were skipped in pc_use_item [Skotlex] - if ((i = sd->itemindex) == -1 || - sd->status.inventory[i].nameid != sd->itemid || - sd->inventory_data[i] == NULL || - !sd->inventory_data[i]->flag.delay_consume || - sd->status.inventory[i].amount < 1 - ) { - //Something went wrong, item exploit? - sd->itemid = sd->itemindex = -1; - return 0; - } - //Consume - sd->itemid = sd->itemindex = -1; - if (skill == WZ_EARTHSPIKE && sc && sc->data[SC_EARTHSCROLL] && rnd()%100 > sc->data[SC_EARTHSCROLL]->val2) // [marquis007] - ; //Do not consume item. - else if (sd->status.inventory[i].expire_time == 0) - pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); // Rental usable items are not consumed until expiration - } - return 1; - } - - if (pc_is90overweight(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_WEIGHTOVER,0); - return 0; - } - - if (sc && (sc->data[SC__SHADOWFORM] || sc->data[SC__IGNORANCE])) - return 0; - - switch (skill) { // Turn off check. - case BS_MAXIMIZE: - case NV_TRICKDEAD: - case TF_HIDING: - case AS_CLOAKING: - case CR_AUTOGUARD: - case ML_AUTOGUARD: - case CR_DEFENDER: - case ML_DEFENDER: - case ST_CHASEWALK: - case PA_GOSPEL: - case CR_SHRINK: - case TK_RUN: - case GS_GATLINGFEVER: - case TK_READYCOUNTER: - case TK_READYDOWN: - case TK_READYSTORM: - case TK_READYTURN: - case SG_FUSION: - case RA_WUGDASH: - case KO_YAMIKUMO: - if (sc && sc->data[status_skill2sc(skill)]) - return 1; - } - - // Check the skills that can be used while mounted on a warg - if (pc_isridingwug(sd)) { - switch (skill) { - 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 HT_SPRINGTRAP: - case RA_DETONATOR: - case RA_CLUSTERBOMB: - case HT_TALKIEBOX: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - case RA_WUGDASH: - case RA_WUGRIDER: - case RA_WUGSTRIKE: - break; - default: // in official there is no message. - return 0; - } - - } - if (pc_ismadogear(sd)) { - switch (skill) { //None Mado skills are unusable when Mado is equipped. [Jobbie] - case BS_REPAIRWEAPON: - case WS_MELTDOWN: - case BS_HAMMERFALL: - case WS_CARTBOOST: - case BS_ADRENALINE: - case WS_WEAPONREFINE: - case BS_WEAPONPERFECT: - case WS_CARTTERMINATION: - case BS_OVERTHRUST: - case WS_OVERTHRUSTMAX: - case BS_MAXIMIZE: - case NC_AXEBOOMERANG: - case BS_ADRENALINE2: - case NC_POWERSWING: - case BS_UNFAIRLYTRICK: - case NC_AXETORNADO: - case BS_GREED: - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - default: //Only Mechanic exlcusive skill can be used. - break; - } - } - if (lv < 1 || lv > MAX_SKILL_LEVEL) - return 0; - - require = skill_get_requirement(sd,skill,lv); - - //Can only update state when weapon/arrow info is checked. - sd->state.arrow_atk = require.ammo?1:0; - - // perform skill-specific checks (and actions) - switch (skill) { - case SO_SPELLFIST: - if (sd->skillid_old != MG_FIREBOLT && sd->skillid_old != MG_COLDBOLT && sd->skillid_old != MG_LIGHTNINGBOLT) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - case SA_CASTCANCEL: - if (sd->ud.skilltimer == INVALID_TIMER) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case AL_WARP: - if (!battle_config.duel_allow_teleport && sd->duel_group) { // duel restriction [LuzZza] - char output[128]; - sprintf(output, msg_txt(365), skill_get_name(AL_WARP)); - clif_displaymessage(sd->fd, output); //"Duel: Can't use %s in duel." - return 0; - } - break; - case MO_CALLSPIRITS: - if (sc && sc->data[SC_RAISINGDRAGON]) - lv += sc->data[SC_RAISINGDRAGON]->val1; - if (sd->spiritball >= lv) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case MO_FINGEROFFENSIVE: - case GS_FLING: - case SR_RAMPAGEBLASTER: - case SR_RIDEINLIGHTNING: - if (sd->spiritball > 0 && sd->spiritball < require.spiritball) - sd->spiritball_old = require.spiritball = sd->spiritball; - else - sd->spiritball_old = require.spiritball; - break; - case MO_CHAINCOMBO: - if (!sc) - return 0; - if (sc->data[SC_BLADESTOP]) - break; - if (sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_TRIPLEATTACK) - break; - return 0; - case MO_COMBOFINISH: - if (!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_CHAINCOMBO)) - return 0; - break; - case CH_TIGERFIST: - if (!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_COMBOFINISH)) - return 0; - break; - case CH_CHAINCRUSH: - if (!(sc && sc->data[SC_COMBO])) - return 0; - if (sc->data[SC_COMBO]->val1 != MO_COMBOFINISH && sc->data[SC_COMBO]->val1 != CH_TIGERFIST) - return 0; - break; - case MO_EXTREMITYFIST: - // if(sc && sc->data[SC_EXTREMITYFIST]) //To disable Asura during the 5 min skill block uncomment this... - // return 0; - if (sc && (sc->data[SC_BLADESTOP] || sc->data[SC_CURSEDCIRCLE_ATKER])) - break; - if (sc && sc->data[SC_COMBO]) { - switch (sc->data[SC_COMBO]->val1) { - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - break; - default: - return 0; - } - } else if (!unit_can_move(&sd->bl)) { - //Placed here as ST_MOVE_ENABLE should not apply if rooted or on a combo. [Skotlex] - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; +int skill_check_condition_castbegin(struct map_session_data* sd, short skill, short lv) { + struct status_data *status; + struct status_change *sc; + struct skill_condition require; + int i; - case TK_MISSION: - if ((sd->class_&MAPID_UPPERMASK) != MAPID_TAEKWON) { - // Cannot be used by Non-Taekwon classes - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; + nullpo_ret(sd); - case TK_READYCOUNTER: - case TK_READYDOWN: - case TK_READYSTORM: - case TK_READYTURN: - case TK_JUMPKICK: - if ((sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) { - // Soul Linkers cannot use this skill - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; + if (lv <= 0 || sd->chatID) return 0; - case TK_TURNKICK: - case TK_STORMKICK: - case TK_DOWNKICK: - case TK_COUNTER: - if ((sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) - return 0; //Anti-Soul Linker check in case you job-changed with Stances active. - if (!(sc && sc->data[SC_COMBO]) || sc->data[SC_COMBO]->val1 == TK_JUMPKICK) - return 0; //Combo needs to be ready - - if (sc->data[SC_COMBO]->val3) { //Kick chain - //Do not repeat a kick. - if (sc->data[SC_COMBO]->val3 != skill) - break; - status_change_end(&sd->bl, SC_COMBO, INVALID_TIMER); - return 0; - } - if (sc->data[SC_COMBO]->val1 != skill && !(sd && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON))) { //Cancel combo wait. - unit_cancel_combo(&sd->bl); - return 0; - } - break; //Combo ready. - case BD_ADAPTATION: { - int time; - if (!(sc && sc->data[SC_DANCING])) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - time = 1000*(sc->data[SC_DANCING]->val3>>16); - if (skill_get_time( - (sc->data[SC_DANCING]->val1&0xFFFF), //Dance Skill ID - (sc->data[SC_DANCING]->val1>>16)) //Dance Skill LV - - time < skill_get_time2(skill,lv)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - } - break; + if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill ) + { //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex] + sd->state.arrow_atk = skill_get_ammotype(skill)?1:0; //Need to do arrow state check. + sd->spiritball_old = sd->spiritball; //Need to do Spiritball check. + return 1; + } - case PR_BENEDICTIO: - if (skill_check_pc_partner(sd, skill, &lv, 1, 0) < 2) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; + switch( sd->menuskill_id ) { + case AM_PHARMACY: + switch( skill ) { + case AM_PHARMACY: + case AC_MAKINGARROW: + case BS_REPAIRWEAPON: + case AM_TWILIGHT1: + case AM_TWILIGHT2: + case AM_TWILIGHT3: + return 0; + } + break; + case GN_MIX_COOKING: + case GN_MAKEBOMB: + case GN_S_PHARMACY: + case GN_CHANGEMATERIAL: + if( sd->menuskill_id != skill ) + return 0; + break; + } + status = &sd->battle_status; + sc = &sd->sc; + if( !sc->count ) + sc = NULL; + + if( sd->skillitem == skill ) + { + if( sd->state.abra_flag ) // Hocus-Pocus was used. [Inkfish] + sd->state.abra_flag = 0; + else + { // When a target was selected, consume items that were skipped in pc_use_item [Skotlex] + if( (i = sd->itemindex) == -1 || + sd->status.inventory[i].nameid != sd->itemid || + sd->inventory_data[i] == NULL || + !sd->inventory_data[i]->flag.delay_consume || + sd->status.inventory[i].amount < 1 + ) + { //Something went wrong, item exploit? + sd->itemid = sd->itemindex = -1; + return 0; + } + //Consume + sd->itemid = sd->itemindex = -1; + if( skill == WZ_EARTHSPIKE && sc && sc->data[SC_EARTHSCROLL] && rnd()%100 > sc->data[SC_EARTHSCROLL]->val2 ) // [marquis007] + ; //Do not consume item. + else if( sd->status.inventory[i].expire_time == 0 ) + pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); // Rental usable items are not consumed until expiration + } + return 1; + } - case SL_SMA: - if (!(sc && sc->data[SC_SMA])) - return 0; - break; + if( pc_is90overweight(sd) ) + { + clif_skill_fail(sd,skill,USESKILL_FAIL_WEIGHTOVER,0); + return 0; + } - case HT_POWER: - if (!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill)) - return 0; - break; + if( sc && ( sc->data[SC__SHADOWFORM] || sc->data[SC__IGNORANCE] ) ) + return 0; - case CG_HERMODE: - if (!npc_check_areanpc(1,sd->bl.m,sd->bl.x,sd->bl.y,skill_get_splash(skill, lv))) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case CG_MOONLIT: { //Check there's no wall in the range+1 area around the caster. [Skotlex] - int i,x,y,range = skill_get_splash(skill, lv)+1; - int size = range*2+1; - for (i=0; i<size*size; i++) { - x = sd->bl.x+(i%size-range); - y = sd->bl.y+(i/size-range); - if (map_getcell(sd->bl.m,x,y,CELL_CHKWALL)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - } - } - break; - case PR_REDEMPTIO: { - int exp; - if (((exp = pc_nextbaseexp(sd)) > 0 && get_percentage(sd->status.base_exp, exp) < 1) || - ((exp = pc_nextjobexp(sd)) > 0 && get_percentage(sd->status.job_exp, exp) < 1)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); //Not enough exp. - return 0; - } - break; - } - case AM_TWILIGHT2: - case AM_TWILIGHT3: - if (!party_skill_check(sd, sd->status.party_id, skill, lv)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case SG_SUN_WARM: - case SG_MOON_WARM: - case SG_STAR_WARM: - if (sc && sc->data[SC_MIRACLE]) - break; - i = skill-SG_SUN_WARM; - if (sd->bl.m == sd->feel_map[i].m) - break; - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - break; - case SG_SUN_COMFORT: - case SG_MOON_COMFORT: - case SG_STAR_COMFORT: - if (sc && sc->data[SC_MIRACLE]) - break; - i = skill-SG_SUN_COMFORT; - if (sd->bl.m == sd->feel_map[i].m && - (battle_config.allow_skill_without_day || sg_info[i].day_func())) - break; - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - case SG_FUSION: - if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_STAR) - break; - //Auron insists we should implement SP consumption when you are not Soul Linked. [Skotlex] - //Only invoke on skill begin cast (instant cast skill). [Kevin] - if (require.sp > 0) { - if (status->sp < (unsigned int)require.sp) - clif_skill_fail(sd,skill,USESKILL_FAIL_SP_INSUFFICIENT,0); - else - status_zap(&sd->bl, 0, require.sp); - } - return 0; - case GD_BATTLEORDER: - case GD_REGENERATION: - case GD_RESTORE: - if (!map_flag_gvg2(sd->bl.m)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - case GD_EMERGENCYCALL: - // other checks were already done in skillnotok() - if (!sd->status.guild_id || !sd->state.gmaster_flag) - return 0; - break; + switch( skill ) { // Turn off check. + case BS_MAXIMIZE: case NV_TRICKDEAD: case TF_HIDING: case AS_CLOAKING: case CR_AUTOGUARD: + case ML_AUTOGUARD: case CR_DEFENDER: case ML_DEFENDER: case ST_CHASEWALK: case PA_GOSPEL: + case CR_SHRINK: case TK_RUN: case GS_GATLINGFEVER: case TK_READYCOUNTER: case TK_READYDOWN: + case TK_READYSTORM: case TK_READYTURN: case SG_FUSION: case RA_WUGDASH: case KO_YAMIKUMO: + if( sc && sc->data[status_skill2sc(skill)] ) + return 1; + } - case GS_GLITTERING: - if (sd->spiritball >= 10) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; + // Check the skills that can be used while mounted on a warg + if( pc_isridingwug(sd) ) { + switch( skill ) { + 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 HT_SPRINGTRAP: case RA_DETONATOR: case RA_CLUSTERBOMB: + case HT_TALKIEBOX: case RA_FIRINGTRAP: case RA_ICEBOUNDTRAP: + case RA_WUGDASH: case RA_WUGRIDER: case RA_WUGSTRIKE: + break; + default: // in official there is no message. + return 0; + } - case NJ_ISSEN: - if (status->hp < 2) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - case NJ_BUNSINJYUTSU: - if (!(sc && sc->data[SC_NEN])) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; + } + if( pc_ismadogear(sd) ) { + switch( skill ) { //None Mado skills are unusable when Mado is equipped. [Jobbie] + case BS_REPAIRWEAPON: case WS_MELTDOWN: + case BS_HAMMERFALL: case WS_CARTBOOST: + case BS_ADRENALINE: case WS_WEAPONREFINE: + case BS_WEAPONPERFECT: case WS_CARTTERMINATION: + case BS_OVERTHRUST: case WS_OVERTHRUSTMAX: + case BS_MAXIMIZE: case NC_AXEBOOMERANG: + case BS_ADRENALINE2: case NC_POWERSWING: + case BS_UNFAIRLYTRICK: case NC_AXETORNADO: + case BS_GREED: + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + default: //Only Mechanic exlcusive skill can be used. + break; + } + } + if( lv < 1 || lv > MAX_SKILL_LEVEL ) + return 0; - case NJ_ZENYNAGE: - case KO_MUCHANAGE: - if (sd->status.zeny < require.zeny) { - clif_skill_fail(sd,skill,USESKILL_FAIL_MONEY,0); - return 0; - } - break; - case PF_HPCONVERSION: - if (status->sp == status->max_sp) - return 0; //Unusable when at full SP. - break; - case AM_CALLHOMUN: //Can't summon if a hom is already out - if (sd->status.hom_id && sd->hd && !sd->hd->homunculus.vaporize) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case AM_REST: //Can't vapo homun if you don't have an active homunc or it's hp is < 80% - if (!merc_is_hom_active(sd->hd) || sd->hd->battle_status.hp < (sd->hd->battle_status.max_hp*80/100)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - /** - * Arch Bishop - **/ - case AB_ANCILLA: { - int count = 0; - for (i = 0; i < MAX_INVENTORY; i ++) - if (sd->status.inventory[i].nameid == ITEMID_ANCILLA) - count += sd->status.inventory[i].amount; - if (count >= 3) { - clif_skill_fail(sd, skill, USESKILL_FAIL_ANCILLA_NUMOVER, 0); - return 0; - } - } - break; - /** - * Keeping as a note: - * Bug Report #17 provides a link to a sep-2011 changelog that shows this requirement was removed - **/ - //case AB_LAUDAAGNUS: - //case AB_LAUDARAMUS: - // if( !sd->status.party_id ) { - // clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - // return 0; - // } - // break; - - case AB_ADORAMUS: - /** - * Warlock - **/ - case WL_COMET: - if (skill_check_pc_partner(sd,skill,&lv,1,0) <= 0 && ((i = pc_search_inventory(sd,require.itemid[0])) < 0 || sd->status.inventory[i].amount < require.amount[0])) { - //clif_skill_fail(sd,skill,USESKILL_FAIL_NEED_ITEM,require.amount[0],require.itemid[0]); - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case WL_SUMMONFB: - case WL_SUMMONBL: - case WL_SUMMONWB: - case WL_SUMMONSTONE: - if (sc) { - ARR_FIND(SC_SPHERE_1,SC_SPHERE_5+1,i,!sc->data[i]); - if (i == SC_SPHERE_5+1) { - // No more free slots - clif_skill_fail(sd,skill,USESKILL_FAIL_SUMMON,0); - return 0; - } - } - break; - /** - * Guilotine Cross - **/ - case GC_HALLUCINATIONWALK: - if (sc && (sc->data[SC_HALLUCINATIONWALK] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY])) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case GC_COUNTERSLASH: - case GC_WEAPONCRUSH: - if (!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == GC_WEAPONBLOCKING)) { - clif_skill_fail(sd, skill, USESKILL_FAIL_GC_WEAPONBLOCKING, 0); - return 0; - } - break; - /** - * Ranger - **/ - case RA_WUGMASTERY: - if (pc_isfalcon(sd) || pc_isridingwug(sd) || sd->sc.data[SC__GROOMY]) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case RA_WUGSTRIKE: - if (!pc_iswug(sd) && !pc_isridingwug(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case RA_WUGRIDER: - if (pc_isfalcon(sd) || (!pc_isridingwug(sd) && !pc_iswug(sd))) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case RA_WUGDASH: - if (!pc_isridingwug(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - /** - * Royal Guard - **/ - case LG_BANDING: - if (sc && sc->data[SC_INSPIRATION]) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case LG_PRESTIGE: - if (sc && (sc->data[SC_BANDING] || sc->data[SC_INSPIRATION])) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case LG_RAGEBURST: - if (sd->spiritball == 0) { - clif_skill_fail(sd,skill,USESKILL_FAIL_SKILLINTERVAL,0); - return 0; - } - sd->spiritball_old = require.spiritball = sd->spiritball; - break; - case LG_RAYOFGENESIS: - if (sc && sc->data[SC_INSPIRATION]) - return 1; // Don't check for partner. - if (!(sc && sc->data[SC_BANDING])) { - clif_skill_fail(sd,skill,USESKILL_FAIL,0); - return 0; - } else if (skill_check_pc_partner(sd,skill,&lv,skill_get_range(skill,lv),0) < 1) - return 0; // Just fails, no msg here. - break; - case LG_HESPERUSLIT: - if (!sc || !sc->data[SC_BANDING]) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case SR_FALLENEMPIRE: - if (!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_DRAGONCOMBO)) - return 0; - break; + require = skill_get_requirement(sd,skill,lv); - case SR_CRESCENTELBOW: - if (sc && sc->data[SC_CRESCENTELBOW]) { - clif_skill_fail(sd, skill, USESKILL_FAIL_DUPLICATE, 0); - return 0; - } - break; - case SR_CURSEDCIRCLE: - if (map_flag_gvg(sd->bl.m)) { - if (map_foreachinrange(mob_count_sub, &sd->bl, skill_get_splash(skill, lv), BL_MOB, - MOBID_EMPERIUM, MOBID_GUARIDAN_STONE1, MOBID_GUARIDAN_STONE2)) { - char output[128]; - sprintf(output, "You're too close to a stone or emperium to do this skill"); - clif_colormes(sd, COLOR_RED, output); - return 0; - } - } - if (sd->spiritball > 0) - sd->spiritball_old = require.spiritball = sd->spiritball; - else { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case SR_GATEOFHELL: - if (sd->spiritball > 0) - sd->spiritball_old = require.spiritball; - break; - case SC_MANHOLE: - case SC_DIMENSIONDOOR: - if (sc && sc->data[SC_MAGNETICFIELD]) { - clif_skill_fail(sd,skill,0,0); - return 0; - } - break; - case WM_GREAT_ECHO: { - int count; - count = skill_check_pc_partner(sd, skill, &lv, skill_get_splash(skill,lv), 0); - if (count < 1) { - clif_skill_fail(sd,skill,USESKILL_FAIL_NEED_HELPER,0); - return 0; - } else - require.sp -= require.sp * 20 * count / 100; // -20% each W/M in the party. - } - break; - case SO_FIREWALK: - case SO_ELECTRICWALK: // Can't be casted until you've walked all cells. - if (sc && sc->data[SC_PROPERTYWALK] && - sc->data[SC_PROPERTYWALK]->val3 < skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2)) { - clif_skill_fail(sd,skill,0x0,0); - return 0; - } - break; - case SO_EL_CONTROL: - if (!sd->status.ele_id || !sd->ed) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case RETURN_TO_ELDICASTES: - if (pc_ismadogear(sd)) { //Cannot be used if Mado is equipped. - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case LG_REFLECTDAMAGE: - case CR_REFLECTSHIELD: - if (sc && sc->data[SC_KYOMU] && rand()%100 < 30) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case KO_KAHU_ENTEN: - case KO_HYOUHU_HUBUKI: - case KO_KAZEHU_SEIRAN: - case KO_DOHU_KOUKAI: { - int ttype = skill_get_ele(skill, lv); - ARR_FIND(1, 5, i, sd->talisman[i] > 0 && i != ttype); - if ((i < 5 && i != ttype) || sd->talisman[ttype] >= 10) { - clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0); - return 0; - } - } - break; - case KO_KAIHOU: - case KO_ZENKAI: - ARR_FIND(1, 6, i, sd->talisman[i] > 0); - if (i > 4) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - } + //Can only update state when weapon/arrow info is checked. + sd->state.arrow_atk = require.ammo?1:0; - switch (require.state) { - case ST_HIDING: - if (!(sc && sc->option&OPTION_HIDE)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_CLOAKING: - if (!pc_iscloaking(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_HIDDEN: - if (!pc_ishiding(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_RIDING: - if (!pc_isriding(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_FALCON: - if (!pc_isfalcon(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_CARTBOOST: - if (!(sc && sc->data[SC_CARTBOOST])) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - case ST_CART: - if (!pc_iscarton(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_SHIELD: - if (sd->status.shield <= 0) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_SIGHT: - if (!(sc && sc->data[SC_SIGHT])) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_EXPLOSIONSPIRITS: - if (!(sc && sc->data[SC_EXPLOSIONSPIRITS])) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_RECOV_WEIGHT_RATE: - if (battle_config.natural_heal_weight_rate <= 100 && sd->weight*100/sd->max_weight >= (unsigned int)battle_config.natural_heal_weight_rate) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_MOVE_ENABLE: - if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill) - sd->ud.canmove_tick = gettick(); //When using a combo, cancel the can't move delay to enable the skill. [Skotlex] + // perform skill-specific checks (and actions) + switch( skill ) { + case SO_SPELLFIST: + if(sd->skillid_old != MG_FIREBOLT && sd->skillid_old != MG_COLDBOLT && sd->skillid_old != MG_LIGHTNINGBOLT){ + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + case SA_CASTCANCEL: + if(sd->ud.skilltimer == INVALID_TIMER) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case AL_WARP: + if(!battle_config.duel_allow_teleport && sd->duel_group) { // duel restriction [LuzZza] + char output[128]; sprintf(output, msg_txt(365), skill_get_name(AL_WARP)); + clif_displaymessage(sd->fd, output); //"Duel: Can't use %s in duel." + return 0; + } + break; + case MO_CALLSPIRITS: + if(sc && sc->data[SC_RAISINGDRAGON]) + lv += sc->data[SC_RAISINGDRAGON]->val1; + if(sd->spiritball >= lv) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case MO_FINGEROFFENSIVE: + case GS_FLING: + case SR_RAMPAGEBLASTER: + case SR_RIDEINLIGHTNING: + if( sd->spiritball > 0 && sd->spiritball < require.spiritball ) + sd->spiritball_old = require.spiritball = sd->spiritball; + else + sd->spiritball_old = require.spiritball; + break; + case MO_CHAINCOMBO: + if(!sc) + return 0; + if(sc->data[SC_BLADESTOP]) + break; + if(sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_TRIPLEATTACK) + break; + return 0; + case MO_COMBOFINISH: + if(!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_CHAINCOMBO)) + return 0; + break; + case CH_TIGERFIST: + if(!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_COMBOFINISH)) + return 0; + break; + case CH_CHAINCRUSH: + if(!(sc && sc->data[SC_COMBO])) + return 0; + if(sc->data[SC_COMBO]->val1 != MO_COMBOFINISH && sc->data[SC_COMBO]->val1 != CH_TIGERFIST) + return 0; + break; + case MO_EXTREMITYFIST: + // if(sc && sc->data[SC_EXTREMITYFIST]) //To disable Asura during the 5 min skill block uncomment this... + // return 0; + if( sc && (sc->data[SC_BLADESTOP] || sc->data[SC_CURSEDCIRCLE_ATKER]) ) + break; + if( sc && sc->data[SC_COMBO] ) + { + switch(sc->data[SC_COMBO]->val1) { + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + break; + default: + return 0; + } + } + else if( !unit_can_move(&sd->bl) ) + { //Placed here as ST_MOVE_ENABLE should not apply if rooted or on a combo. [Skotlex] + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; - if (!unit_can_move(&sd->bl)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_WATER: - if (sc && (sc->data[SC_DELUGE] || sc->data[SC_SUITON])) - break; - if (map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER)) - break; - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - /** - * Rune Knight - **/ - case ST_RIDINGDRAGON: - if (!pc_isridingdragon(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - /** - * Wug - **/ - case ST_WUG: - if (!pc_iswug(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - /** - * Riding Wug - **/ - case ST_RIDINGWUG: - if (!pc_isridingwug(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - /** - * Mechanic - **/ - case ST_MADO: - if (!pc_ismadogear(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - /** - * Sorcerer - **/ - case ST_ELEMENTALSPIRIT: - if (!sd->ed) { - clif_skill_fail(sd,skill,USESKILL_FAIL_EL_SUMMON,0); - return 0; - } - break; + case TK_MISSION: + if( (sd->class_&MAPID_UPPERMASK) != MAPID_TAEKWON ) + {// Cannot be used by Non-Taekwon classes + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + + case TK_READYCOUNTER: + case TK_READYDOWN: + case TK_READYSTORM: + case TK_READYTURN: + case TK_JUMPKICK: + if( (sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER ) + {// Soul Linkers cannot use this skill + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + + case TK_TURNKICK: + case TK_STORMKICK: + case TK_DOWNKICK: + case TK_COUNTER: + if ((sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) + return 0; //Anti-Soul Linker check in case you job-changed with Stances active. + if(!(sc && sc->data[SC_COMBO]) || sc->data[SC_COMBO]->val1 == TK_JUMPKICK) + return 0; //Combo needs to be ready + + if (sc->data[SC_COMBO]->val3) { //Kick chain + //Do not repeat a kick. + if (sc->data[SC_COMBO]->val3 != skill) + break; + status_change_end(&sd->bl, SC_COMBO, INVALID_TIMER); + return 0; + } + if(sc->data[SC_COMBO]->val1 != skill && !( sd && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) )) { //Cancel combo wait. + unit_cancel_combo(&sd->bl); + return 0; + } + break; //Combo ready. + case BD_ADAPTATION: + { + int time; + if(!(sc && sc->data[SC_DANCING])) + { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + time = 1000*(sc->data[SC_DANCING]->val3>>16); + if (skill_get_time( + (sc->data[SC_DANCING]->val1&0xFFFF), //Dance Skill ID + (sc->data[SC_DANCING]->val1>>16)) //Dance Skill LV + - time < skill_get_time2(skill,lv)) + { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + } + break; + + case PR_BENEDICTIO: + if (skill_check_pc_partner(sd, skill, &lv, 1, 0) < 2) + { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + + case SL_SMA: + if(!(sc && sc->data[SC_SMA])) + return 0; + break; + + case HT_POWER: + if(!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill)) + return 0; + break; + + case CG_HERMODE: + if(!npc_check_areanpc(1,sd->bl.m,sd->bl.x,sd->bl.y,skill_get_splash(skill, lv))) + { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case CG_MOONLIT: //Check there's no wall in the range+1 area around the caster. [Skotlex] + { + int i,x,y,range = skill_get_splash(skill, lv)+1; + int size = range*2+1; + for (i=0;i<size*size;i++) { + x = sd->bl.x+(i%size-range); + y = sd->bl.y+(i/size-range); + if (map_getcell(sd->bl.m,x,y,CELL_CHKWALL)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + } + } + break; + case PR_REDEMPTIO: + { + int exp; + if( ((exp = pc_nextbaseexp(sd)) > 0 && get_percentage(sd->status.base_exp, exp) < 1) || + ((exp = pc_nextjobexp(sd)) > 0 && get_percentage(sd->status.job_exp, exp) < 1)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); //Not enough exp. + return 0; + } + break; + } + case AM_TWILIGHT2: + case AM_TWILIGHT3: + if (!party_skill_check(sd, sd->status.party_id, skill, lv)) + { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case SG_SUN_WARM: + case SG_MOON_WARM: + case SG_STAR_WARM: + if (sc && sc->data[SC_MIRACLE]) + break; + i = skill-SG_SUN_WARM; + if (sd->bl.m == sd->feel_map[i].m) + break; + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + break; + case SG_SUN_COMFORT: + case SG_MOON_COMFORT: + case SG_STAR_COMFORT: + if (sc && sc->data[SC_MIRACLE]) + break; + i = skill-SG_SUN_COMFORT; + if (sd->bl.m == sd->feel_map[i].m && + (battle_config.allow_skill_without_day || sg_info[i].day_func())) + break; + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + case SG_FUSION: + if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_STAR) + break; + //Auron insists we should implement SP consumption when you are not Soul Linked. [Skotlex] + //Only invoke on skill begin cast (instant cast skill). [Kevin] + if( require.sp > 0 ) + { + if (status->sp < (unsigned int)require.sp) + clif_skill_fail(sd,skill,USESKILL_FAIL_SP_INSUFFICIENT,0); + else + status_zap(&sd->bl, 0, require.sp); + } + return 0; + case GD_BATTLEORDER: + case GD_REGENERATION: + case GD_RESTORE: + if (!map_flag_gvg2(sd->bl.m)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + case GD_EMERGENCYCALL: + // other checks were already done in skillnotok() + if (!sd->status.guild_id || !sd->state.gmaster_flag) + return 0; + break; + + case GS_GLITTERING: + if(sd->spiritball >= 10) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + + case NJ_ISSEN: + if (status->hp < 2) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + case NJ_BUNSINJYUTSU: + if (!(sc && sc->data[SC_NEN])) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + + case NJ_ZENYNAGE: + case KO_MUCHANAGE: + if(sd->status.zeny < require.zeny) { + clif_skill_fail(sd,skill,USESKILL_FAIL_MONEY,0); + return 0; + } + break; + case PF_HPCONVERSION: + if (status->sp == status->max_sp) + return 0; //Unusable when at full SP. + break; + case AM_CALLHOMUN: //Can't summon if a hom is already out + if (sd->status.hom_id && sd->hd && !sd->hd->homunculus.vaporize) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case AM_REST: //Can't vapo homun if you don't have an active homunc or it's hp is < 80% + if (!merc_is_hom_active(sd->hd) || sd->hd->battle_status.hp < (sd->hd->battle_status.max_hp*80/100)) + { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + /** + * Arch Bishop + **/ + case AB_ANCILLA: + { + int count = 0; + for( i = 0; i < MAX_INVENTORY; i ++ ) + if( sd->status.inventory[i].nameid == ITEMID_ANCILLA ) + count += sd->status.inventory[i].amount; + if( count >= 3 ) { + clif_skill_fail(sd, skill, USESKILL_FAIL_ANCILLA_NUMOVER, 0); + return 0; + } + } + break; + /** + * Keeping as a note: + * Bug Report #17 provides a link to a sep-2011 changelog that shows this requirement was removed + **/ + //case AB_LAUDAAGNUS: + //case AB_LAUDARAMUS: + // if( !sd->status.party_id ) { + // clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + // return 0; + // } + // break; + + case AB_ADORAMUS: + /** + * Warlock + **/ + case WL_COMET: + if( skill_check_pc_partner(sd,skill,&lv,1,0) <= 0 && ((i = pc_search_inventory(sd,require.itemid[0])) < 0 || sd->status.inventory[i].amount < require.amount[0]) ) + { + //clif_skill_fail(sd,skill,USESKILL_FAIL_NEED_ITEM,require.amount[0],require.itemid[0]); + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case WL_SUMMONFB: + case WL_SUMMONBL: + case WL_SUMMONWB: + case WL_SUMMONSTONE: + if( sc ) + { + ARR_FIND(SC_SPHERE_1,SC_SPHERE_5+1,i,!sc->data[i]); + if( i == SC_SPHERE_5+1 ) + { // No more free slots + clif_skill_fail(sd,skill,USESKILL_FAIL_SUMMON,0); + return 0; + } + } + break; + /** + * Guilotine Cross + **/ + case GC_HALLUCINATIONWALK: + if( sc && (sc->data[SC_HALLUCINATIONWALK] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY]) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case GC_COUNTERSLASH: + case GC_WEAPONCRUSH: + if( !(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == GC_WEAPONBLOCKING) ) { + clif_skill_fail(sd, skill, USESKILL_FAIL_GC_WEAPONBLOCKING, 0); + return 0; + } + break; + /** + * Ranger + **/ + case RA_WUGMASTERY: + if( pc_isfalcon(sd) || pc_isridingwug(sd) || sd->sc.data[SC__GROOMY]) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case RA_WUGSTRIKE: + if( !pc_iswug(sd) && !pc_isridingwug(sd) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case RA_WUGRIDER: + if( pc_isfalcon(sd) || ( !pc_isridingwug(sd) && !pc_iswug(sd) ) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case RA_WUGDASH: + if(!pc_isridingwug(sd)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + /** + * Royal Guard + **/ + case LG_BANDING: + if( sc && sc->data[SC_INSPIRATION] ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case LG_PRESTIGE: + if( sc && (sc->data[SC_BANDING] || sc->data[SC_INSPIRATION]) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case LG_RAGEBURST: + if( sd->spiritball == 0 ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_SKILLINTERVAL,0); + return 0; + } + sd->spiritball_old = require.spiritball = sd->spiritball; + break; + case LG_RAYOFGENESIS: + if( sc && sc->data[SC_INSPIRATION] ) + return 1; // Don't check for partner. + if( !(sc && sc->data[SC_BANDING]) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL,0); + return 0; + } else if( skill_check_pc_partner(sd,skill,&lv,skill_get_range(skill,lv),0) < 1 ) + return 0; // Just fails, no msg here. + break; + case LG_HESPERUSLIT: + if( !sc || !sc->data[SC_BANDING] ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case SR_FALLENEMPIRE: + if( !(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_DRAGONCOMBO) ) + return 0; + break; + + case SR_CRESCENTELBOW: + if( sc && sc->data[SC_CRESCENTELBOW] ) { + clif_skill_fail(sd, skill, USESKILL_FAIL_DUPLICATE, 0); + return 0; + } + break; + case SR_CURSEDCIRCLE: + if (map_flag_gvg(sd->bl.m)) { + if (map_foreachinrange(mob_count_sub, &sd->bl, skill_get_splash(skill, lv), BL_MOB, + MOBID_EMPERIUM, MOBID_GUARIDAN_STONE1, MOBID_GUARIDAN_STONE2)) { + char output[128]; + sprintf(output, "You're too close to a stone or emperium to do this skill"); + clif_colormes(sd, COLOR_RED, output); + return 0; + } + } + if( sd->spiritball > 0 ) + sd->spiritball_old = require.spiritball = sd->spiritball; + else { + clif_skill_fail(sd,skill,0,0); + return 0; + } + break; + case SR_GATEOFHELL: + if( sd->spiritball > 0 ) + sd->spiritball_old = require.spiritball; + break; + case SC_MANHOLE: + case SC_DIMENSIONDOOR: + if( sc && sc->data[SC_MAGNETICFIELD] ) { + clif_skill_fail(sd,skill,0,0); + return 0; + } + break; + case WM_GREAT_ECHO: { + int count; + count = skill_check_pc_partner(sd, skill, &lv, skill_get_splash(skill,lv), 0); + if( count < 1 ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_NEED_HELPER,0); + return 0; + } else + require.sp -= require.sp * 20 * count / 100; // -20% each W/M in the party. + } + break; + case SO_FIREWALK: + case SO_ELECTRICWALK: // Can't be casted until you've walked all cells. + if( sc && sc->data[SC_PROPERTYWALK] && + sc->data[SC_PROPERTYWALK]->val3 < skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) { + clif_skill_fail(sd,skill,0x0,0); + return 0; + } + break; + case SO_EL_CONTROL: + if( !sd->status.ele_id || !sd->ed ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case RETURN_TO_ELDICASTES: + if( pc_ismadogear(sd) ) { //Cannot be used if Mado is equipped. + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case LG_REFLECTDAMAGE: + case CR_REFLECTSHIELD: + if( sc && sc->data[SC_KYOMU] && rand()%100 < 30){ + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case KO_KAHU_ENTEN: + case KO_HYOUHU_HUBUKI: + case KO_KAZEHU_SEIRAN: + case KO_DOHU_KOUKAI: + { + int ttype = skill_get_ele(skill, lv); + ARR_FIND(1, 5, i, sd->talisman[i] > 0 && i != ttype); + if( (i < 5 && i != ttype) || sd->talisman[ttype] >= 10 ){ + clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0); + return 0; + } + } + break; + case KO_KAIHOU: + case KO_ZENKAI: + ARR_FIND(1, 6, i, sd->talisman[i] > 0); + if( i > 4 ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + } + + switch(require.state) { + case ST_HIDING: + if(!(sc && sc->option&OPTION_HIDE)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_CLOAKING: + if(!pc_iscloaking(sd)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_HIDDEN: + if(!pc_ishiding(sd)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_RIDING: + if(!pc_isriding(sd)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_FALCON: + if(!pc_isfalcon(sd)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_CARTBOOST: + if(!(sc && sc->data[SC_CARTBOOST])) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + case ST_CART: + if(!pc_iscarton(sd)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_SHIELD: + if(sd->status.shield <= 0) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_SIGHT: + if(!(sc && sc->data[SC_SIGHT])) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_EXPLOSIONSPIRITS: + if(!(sc && sc->data[SC_EXPLOSIONSPIRITS])) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_RECOV_WEIGHT_RATE: + if(battle_config.natural_heal_weight_rate <= 100 && sd->weight*100/sd->max_weight >= (unsigned int)battle_config.natural_heal_weight_rate) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_MOVE_ENABLE: + if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill) + sd->ud.canmove_tick = gettick(); //When using a combo, cancel the can't move delay to enable the skill. [Skotlex] + + if (!unit_can_move(&sd->bl)) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_WATER: + if (sc && (sc->data[SC_DELUGE] || sc->data[SC_SUITON])) + break; + if (map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER)) + break; + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + /** + * Rune Knight + **/ + case ST_RIDINGDRAGON: + if( !pc_isridingdragon(sd) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + /** + * Wug + **/ + case ST_WUG: + if( !pc_iswug(sd) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + /** + * Riding Wug + **/ + case ST_RIDINGWUG: + if( !pc_isridingwug(sd) ){ + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + /** + * Mechanic + **/ + case ST_MADO: + if( !pc_ismadogear(sd) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + /** + * Sorcerer + **/ + case ST_ELEMENTALSPIRIT: + if(!sd->ed) { + clif_skill_fail(sd,skill,USESKILL_FAIL_EL_SUMMON,0); + return 0; + } + break; case ST_POISONINGWEAPON: if (!(sc && sc->data[SC_POISONINGWEAPON])) { clif_skill_fail(sd, skill, USESKILL_FAIL_GC_POISONINGWEAPON, 0); @@ -13227,1470 +13076,1470 @@ int skill_check_condition_castbegin(struct map_session_data *sd, short skill, sh return 0; } break; - } - - if (require.mhp > 0 && get_percentage(status->hp, status->max_hp) > require.mhp) { - //mhp is the max-hp-requirement, that is, - //you must have this % or less of HP to cast it. - clif_skill_fail(sd,skill,USESKILL_FAIL_HP_INSUFFICIENT,0); - return 0; - } - - if (require.weapon && !pc_check_weapontype(sd,require.weapon)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_THIS_WEAPON,0); - return 0; - } - - if (require.sp > 0 && status->sp < (unsigned int)require.sp) { - clif_skill_fail(sd,skill,USESKILL_FAIL_SP_INSUFFICIENT,0); - return 0; - } - - if (require.zeny > 0 && sd->status.zeny < require.zeny) { - clif_skill_fail(sd,skill,USESKILL_FAIL_MONEY,0); - return 0; - } - - if (require.spiritball > 0 && sd->spiritball < require.spiritball) { - clif_skill_fail(sd,skill,USESKILL_FAIL_SPIRITS,require.spiritball); - return 0; - } - - return 1; + } + + if(require.mhp > 0 && get_percentage(status->hp, status->max_hp) > require.mhp) { + //mhp is the max-hp-requirement, that is, + //you must have this % or less of HP to cast it. + clif_skill_fail(sd,skill,USESKILL_FAIL_HP_INSUFFICIENT,0); + return 0; + } + + if( require.weapon && !pc_check_weapontype(sd,require.weapon) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_THIS_WEAPON,0); + return 0; + } + + if( require.sp > 0 && status->sp < (unsigned int)require.sp) { + clif_skill_fail(sd,skill,USESKILL_FAIL_SP_INSUFFICIENT,0); + return 0; + } + + if( require.zeny > 0 && sd->status.zeny < require.zeny ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_MONEY,0); + return 0; + } + + if( require.spiritball > 0 && sd->spiritball < require.spiritball) { + clif_skill_fail(sd,skill,USESKILL_FAIL_SPIRITS,require.spiritball); + return 0; + } + + return 1; } -int skill_check_condition_castend(struct map_session_data *sd, short skill, short lv) +int skill_check_condition_castend(struct map_session_data* sd, short skill, short lv) { - struct skill_condition require; - struct status_data *status; - int i; - int index[MAX_SKILL_ITEM_REQUIRE]; - - nullpo_ret(sd); - - if (lv <= 0 || sd->chatID) - return 0; - - if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill) { - //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex] - sd->state.arrow_atk = skill_get_ammotype(skill)?1:0; //Need to do arrow state check. - sd->spiritball_old = sd->spiritball; //Need to do Spiritball check. - return 1; - } - - switch (sd->menuskill_id) { // Cast start or cast end?? - case AM_PHARMACY: - switch (skill) { - case AM_PHARMACY: - case AC_MAKINGARROW: - case BS_REPAIRWEAPON: - case AM_TWILIGHT1: - case AM_TWILIGHT2: - case AM_TWILIGHT3: - return 0; - } - break; - case GN_MIX_COOKING: - case GN_MAKEBOMB: - case GN_S_PHARMACY: - case GN_CHANGEMATERIAL: - if (sd->menuskill_id != skill) - return 0; - break; - } + struct skill_condition require; + struct status_data *status; + int i; + int index[MAX_SKILL_ITEM_REQUIRE]; - if (sd->skillitem == skill) // Casting finished (Item skill or Hocus-Pocus) - return 1; + nullpo_ret(sd); - if (pc_is90overweight(sd)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_WEIGHTOVER,0); - return 0; - } + if( lv <= 0 || sd->chatID ) + return 0; - // perform skill-specific checks (and actions) - switch (skill) { - case PR_BENEDICTIO: - skill_check_pc_partner(sd, skill, &lv, 1, 1); - break; - case AM_CANNIBALIZE: - case AM_SPHEREMINE: { - int c=0; - int summons[5] = { 1589, 1579, 1575, 1555, 1590 }; - //int summons[5] = { 1020, 1068, 1118, 1500, 1368 }; - int maxcount = (skill==AM_CANNIBALIZE)? 6-lv : skill_get_maxcount(skill,lv); - int mob_class = (skill==AM_CANNIBALIZE)? summons[lv-1] :1142; - if (battle_config.land_skill_limit && maxcount>0 && (battle_config.land_skill_limit&BL_PC)) { - i = map_foreachinmap(skill_check_condition_mob_master_sub ,sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill, &c); - if (c >= maxcount || - (skill==AM_CANNIBALIZE && c != i && battle_config.summon_flora&2)) { - //Fails when: exceed max limit. There are other plant types already out. - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - } - break; - } - case NC_SILVERSNIPER: - case NC_MAGICDECOY: { - int c = 0, j; - int maxcount = skill_get_maxcount(skill,lv); - int mob_class = 2042; - if (skill == NC_MAGICDECOY) - mob_class = 2043; - - if (battle_config.land_skill_limit && maxcount > 0 && (battle_config.land_skill_limit&BL_PC)) { - if (skill == NC_MAGICDECOY) { - for (j = mob_class; j <= 2046; j++) - map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, j, skill, &c); - } else - map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill, &c); - if (c >= maxcount) { - clif_skill_fail(sd , skill, USESKILL_FAIL_LEVEL, 0); - return 0; - } - } - } - break; - case KO_ZANZOU: { - int c = 0; - i = map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, 2308, skill, &c); - if (c >= skill_get_maxcount(skill,lv) || c != i) { - clif_skill_fail(sd , skill, USESKILL_FAIL_LEVEL, 0); - return 0; - } - } - break; - } - - status = &sd->battle_status; - - require = skill_get_requirement(sd,skill,lv); - - if (require.hp > 0 && status->hp <= (unsigned int)require.hp) { - clif_skill_fail(sd,skill,USESKILL_FAIL_HP_INSUFFICIENT,0); - return 0; - } - - if (require.weapon && !pc_check_weapontype(sd,require.weapon)) { - clif_skill_fail(sd,skill,USESKILL_FAIL_THIS_WEAPON,0); - return 0; - } - - if (require.ammo) { //Skill requires stuff equipped in the arrow slot. - if ((i=sd->equip_index[EQI_AMMO]) < 0 || !sd->inventory_data[i]) { - clif_arrow_fail(sd,0); - return 0; - } else if (sd->status.inventory[i].amount < require.ammo_qty) { - char e_msg[100]; - sprintf(e_msg,"Skill Failed. [%s] requires %dx %s.", - skill_get_desc(skill), - require.ammo_qty, - itemdb_jname(sd->status.inventory[i].nameid)); - clif_colormes(sd,COLOR_RED,e_msg); - return 0; - } - if (!(require.ammo&1<<sd->inventory_data[i]->look)) { //Ammo type check. Send the "wrong weapon type" message - //which is the closest we have to wrong ammo type. [Skotlex] - clif_arrow_fail(sd,0); //Haplo suggested we just send the equip-arrows message instead. [Skotlex] - //clif_skill_fail(sd,skill,USESKILL_FAIL_THIS_WEAPON,0); - return 0; - } - } - - for (i = 0; i < MAX_SKILL_ITEM_REQUIRE; ++i) { - if (!require.itemid[i]) - continue; - index[i] = pc_search_inventory(sd,require.itemid[i]); - if (index[i] < 0 || sd->status.inventory[index[i]].amount < require.amount[i]) { - if (require.itemid[i] == ITEMID_RED_GEMSTONE) - clif_skill_fail(sd,skill,USESKILL_FAIL_REDJAMSTONE,0);// red gemstone required - else if (require.itemid[i] == ITEMID_BLUE_GEMSTONE) - clif_skill_fail(sd,skill,USESKILL_FAIL_BLUEJAMSTONE,0);// blue gemstone required - else - clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); - return 0; - } - } - - return 1; + if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill ) { + //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex] + sd->state.arrow_atk = skill_get_ammotype(skill)?1:0; //Need to do arrow state check. + sd->spiritball_old = sd->spiritball; //Need to do Spiritball check. + return 1; + } + + switch( sd->menuskill_id ) { // Cast start or cast end?? + case AM_PHARMACY: + switch( skill ) { + case AM_PHARMACY: + case AC_MAKINGARROW: + case BS_REPAIRWEAPON: + case AM_TWILIGHT1: + case AM_TWILIGHT2: + case AM_TWILIGHT3: + return 0; + } + break; + case GN_MIX_COOKING: + case GN_MAKEBOMB: + case GN_S_PHARMACY: + case GN_CHANGEMATERIAL: + if( sd->menuskill_id != skill ) + return 0; + break; + } + + if( sd->skillitem == skill ) // Casting finished (Item skill or Hocus-Pocus) + return 1; + + if( pc_is90overweight(sd) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_WEIGHTOVER,0); + return 0; + } + + // perform skill-specific checks (and actions) + switch( skill ) { + case PR_BENEDICTIO: + skill_check_pc_partner(sd, skill, &lv, 1, 1); + break; + case AM_CANNIBALIZE: + case AM_SPHEREMINE: { + int c=0; + int summons[5] = { 1589, 1579, 1575, 1555, 1590 }; + //int summons[5] = { 1020, 1068, 1118, 1500, 1368 }; + int maxcount = (skill==AM_CANNIBALIZE)? 6-lv : skill_get_maxcount(skill,lv); + int mob_class = (skill==AM_CANNIBALIZE)? summons[lv-1] :1142; + if(battle_config.land_skill_limit && maxcount>0 && (battle_config.land_skill_limit&BL_PC)) { + i = map_foreachinmap(skill_check_condition_mob_master_sub ,sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill, &c); + if(c >= maxcount || + (skill==AM_CANNIBALIZE && c != i && battle_config.summon_flora&2)) + { //Fails when: exceed max limit. There are other plant types already out. + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + } + break; + } + case NC_SILVERSNIPER: + case NC_MAGICDECOY: { + int c = 0, j; + int maxcount = skill_get_maxcount(skill,lv); + int mob_class = 2042; + if( skill == NC_MAGICDECOY ) + mob_class = 2043; + + if( battle_config.land_skill_limit && maxcount > 0 && ( battle_config.land_skill_limit&BL_PC ) ) { + if( skill == NC_MAGICDECOY ) { + for( j = mob_class; j <= 2046; j++ ) + map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, j, skill, &c); + } else + map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill, &c); + if( c >= maxcount ) { + clif_skill_fail(sd , skill, USESKILL_FAIL_LEVEL, 0); + return 0; + } + } + } + break; + case KO_ZANZOU: { + int c = 0; + i = map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, 2308, skill, &c); + if( c >= skill_get_maxcount(skill,lv) || c != i) + { + clif_skill_fail(sd , skill, USESKILL_FAIL_LEVEL, 0); + return 0; + } + } + break; + } + + status = &sd->battle_status; + + require = skill_get_requirement(sd,skill,lv); + + if( require.hp > 0 && status->hp <= (unsigned int)require.hp) { + clif_skill_fail(sd,skill,USESKILL_FAIL_HP_INSUFFICIENT,0); + return 0; + } + + if( require.weapon && !pc_check_weapontype(sd,require.weapon) ) { + clif_skill_fail(sd,skill,USESKILL_FAIL_THIS_WEAPON,0); + return 0; + } + + if( require.ammo ) { //Skill requires stuff equipped in the arrow slot. + if((i=sd->equip_index[EQI_AMMO]) < 0 || !sd->inventory_data[i] ) { + clif_arrow_fail(sd,0); + return 0; + } else if( sd->status.inventory[i].amount < require.ammo_qty ) { + char e_msg[100]; + sprintf(e_msg,"Skill Failed. [%s] requires %dx %s.", + skill_get_desc(skill), + require.ammo_qty, + itemdb_jname(sd->status.inventory[i].nameid)); + clif_colormes(sd,COLOR_RED,e_msg); + return 0; + } + if (!(require.ammo&1<<sd->inventory_data[i]->look)) { //Ammo type check. Send the "wrong weapon type" message + //which is the closest we have to wrong ammo type. [Skotlex] + clif_arrow_fail(sd,0); //Haplo suggested we just send the equip-arrows message instead. [Skotlex] + //clif_skill_fail(sd,skill,USESKILL_FAIL_THIS_WEAPON,0); + return 0; + } + } + + for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; ++i ) { + if( !require.itemid[i] ) + continue; + index[i] = pc_search_inventory(sd,require.itemid[i]); + if( index[i] < 0 || sd->status.inventory[index[i]].amount < require.amount[i] ) { + if( require.itemid[i] == ITEMID_RED_GEMSTONE ) + clif_skill_fail(sd,skill,USESKILL_FAIL_REDJAMSTONE,0);// red gemstone required + else if( require.itemid[i] == ITEMID_BLUE_GEMSTONE ) + clif_skill_fail(sd,skill,USESKILL_FAIL_BLUEJAMSTONE,0);// blue gemstone required + else + clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); + return 0; + } + } + + return 1; } // type&2: consume items (after skill was used) // type&1: consume the others (before skill was used) -int skill_consume_requirement(struct map_session_data *sd, short skill, short lv, short type) +int skill_consume_requirement( struct map_session_data *sd, short skill, short lv, short type) { - struct skill_condition req; + struct skill_condition req; + + nullpo_ret(sd); + + req = skill_get_requirement(sd,skill,lv); + + if( type&1 ) + { + if( skill == CG_TAROTCARD || sd->state.autocast ) + req.sp = 0; // TarotCard will consume sp in skill_cast_nodamage_id [Inkfish] + if(req.hp || req.sp) + status_zap(&sd->bl, req.hp, req.sp); + + if(req.spiritball > 0) + pc_delspiritball(sd,req.spiritball,0); + + if(req.zeny > 0) + { + if( skill == NJ_ZENYNAGE ) + req.zeny = 0; //Zeny is reduced on skill_attack. + if( sd->status.zeny < req.zeny ) + req.zeny = sd->status.zeny; + pc_payzeny(sd,req.zeny,LOG_TYPE_CONSUME,NULL); + } + } - nullpo_ret(sd); + if( type&2 ) + { + struct status_change *sc = &sd->sc; + int n,i; - req = skill_get_requirement(sd,skill,lv); + if( !sc->count ) + sc = NULL; - if (type&1) { - if (skill == CG_TAROTCARD || sd->state.autocast) - req.sp = 0; // TarotCard will consume sp in skill_cast_nodamage_id [Inkfish] - if (req.hp || req.sp) - status_zap(&sd->bl, req.hp, req.sp); + for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; ++i ) + { + if( !req.itemid[i] ) + continue; - if (req.spiritball > 0) - pc_delspiritball(sd,req.spiritball,0); + if( itemid_isgemstone(req.itemid[i]) && skill != HW_GANBANTEIN && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_WIZARD ) + continue; //Gemstones are checked, but not substracted from inventory. - if (req.zeny > 0) { - if (skill == NJ_ZENYNAGE) - req.zeny = 0; //Zeny is reduced on skill_attack. - if (sd->status.zeny < req.zeny) - req.zeny = sd->status.zeny; - pc_payzeny(sd,req.zeny,LOG_TYPE_CONSUME,NULL); - } - } + if( (n = pc_search_inventory(sd,req.itemid[i])) >= 0 ) + pc_delitem(sd,n,req.amount[i],0,1,LOG_TYPE_CONSUME); + } + } - if (type&2) { - struct status_change *sc = &sd->sc; - int n,i; + return 1; +} - if (!sc->count) - sc = NULL; +struct skill_condition skill_get_requirement(struct map_session_data* sd, short skill, short lv) +{ + struct skill_condition req; + struct status_data *status; + struct status_change *sc; + int i,j,hp_rate,sp_rate, sp_skill_rate_bonus = 100; + + memset(&req,0,sizeof(req)); + + if( !sd ) + return req; + + if( sd->skillitem == skill ) + return req; // Item skills and Hocus-Pocus don't have requirements.[Inkfish] + + sc = &sd->sc; + if( !sc->count ) + sc = NULL; + + switch( skill ) + { // Turn off check. + case BS_MAXIMIZE: case NV_TRICKDEAD: case TF_HIDING: case AS_CLOAKING: case CR_AUTOGUARD: + case ML_AUTOGUARD: case CR_DEFENDER: case ML_DEFENDER: case ST_CHASEWALK: case PA_GOSPEL: + case CR_SHRINK: case TK_RUN: case GS_GATLINGFEVER: case TK_READYCOUNTER: case TK_READYDOWN: + case TK_READYSTORM: case TK_READYTURN: case SG_FUSION: case KO_YAMIKUMO: + if( sc && sc->data[status_skill2sc(skill)] ) + return req; + } - for (i = 0; i < MAX_SKILL_ITEM_REQUIRE; ++i) { - if (!req.itemid[i]) - continue; + j = skill_get_index(skill); + if( j == 0 ) // invalid skill id + return req; + if( lv < 1 || lv > MAX_SKILL_LEVEL ) + return req; + + status = &sd->battle_status; + + req.hp = skill_db[j].hp[lv-1]; + hp_rate = skill_db[j].hp_rate[lv-1]; + if(hp_rate > 0) + req.hp += (status->hp * hp_rate)/100; + else + req.hp += (status->max_hp * (-hp_rate))/100; + + req.sp = skill_db[j].sp[lv-1]; + if((sd->skillid_old == BD_ENCORE) && skill == sd->skillid_dance) + req.sp /= 2; + sp_rate = skill_db[j].sp_rate[lv-1]; + if(sp_rate > 0) + req.sp += (status->sp * sp_rate)/100; + else + req.sp += (status->max_sp * (-sp_rate))/100; + if( sd->dsprate != 100 ) + req.sp = req.sp * sd->dsprate / 100; + + ARR_FIND(0, ARRAYLENGTH(sd->skillusesprate), i, sd->skillusesprate[i].id == skill); + if( i < ARRAYLENGTH(sd->skillusesprate) ) + sp_skill_rate_bonus += sd->skillusesprate[i].val; + ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == skill); + if( i < ARRAYLENGTH(sd->skillusesp) ) + req.sp -= sd->skillusesp[i].val; + + req.sp = cap_value(req.sp * sp_skill_rate_bonus / 100, 0, SHRT_MAX); + + if( sc ) { + if( sc->data[SC__LAZINESS] ) + req.sp += req.sp + sc->data[SC__LAZINESS]->val1 * 10; + if (sc->data[SC_UNLIMITEDHUMMINGVOICE]) + req.sp += req.sp * sc->data[SC_UNLIMITEDHUMMINGVOICE]->val2 / 100; + if( sc->data[SC_RECOGNIZEDSPELL] ) + req.sp += req.sp / 4; + } - if (itemid_isgemstone(req.itemid[i]) && skill != HW_GANBANTEIN && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_WIZARD) - continue; //Gemstones are checked, but not substracted from inventory. + req.zeny = skill_db[j].zeny[lv-1]; - if ((n = pc_search_inventory(sd,req.itemid[i])) >= 0) - pc_delitem(sd,n,req.amount[i],0,1,LOG_TYPE_CONSUME); - } - } + if( sc && sc->data[SC__UNLUCKY] ) + req.zeny += sc->data[SC__UNLUCKY]->val1 * 500; - return 1; -} + req.spiritball = skill_db[j].spiritball[lv-1]; -struct skill_condition skill_get_requirement(struct map_session_data *sd, short skill, short lv) { - struct skill_condition req; - struct status_data *status; - struct status_change *sc; - int i,j,hp_rate,sp_rate, sp_skill_rate_bonus = 100; - - memset(&req,0,sizeof(req)); - - if (!sd) - return req; - - if (sd->skillitem == skill) - return req; // Item skills and Hocus-Pocus don't have requirements.[Inkfish] - - sc = &sd->sc; - if (!sc->count) - sc = NULL; - - switch (skill) { - // Turn off check. - case BS_MAXIMIZE: - case NV_TRICKDEAD: - case TF_HIDING: - case AS_CLOAKING: - case CR_AUTOGUARD: - case ML_AUTOGUARD: - case CR_DEFENDER: - case ML_DEFENDER: - case ST_CHASEWALK: - case PA_GOSPEL: - case CR_SHRINK: - case TK_RUN: - case GS_GATLINGFEVER: - case TK_READYCOUNTER: - case TK_READYDOWN: - case TK_READYSTORM: - case TK_READYTURN: - case SG_FUSION: - case KO_YAMIKUMO: - if (sc && sc->data[status_skill2sc(skill)]) - return req; - } - - j = skill_get_index(skill); - if (j == 0) // invalid skill id - return req; - if (lv < 1 || lv > MAX_SKILL_LEVEL) - return req; - - status = &sd->battle_status; - - req.hp = skill_db[j].hp[lv-1]; - hp_rate = skill_db[j].hp_rate[lv-1]; - if (hp_rate > 0) - req.hp += (status->hp *hp_rate)/100; - else - req.hp += (status->max_hp * (-hp_rate))/100; - - req.sp = skill_db[j].sp[lv-1]; - if ((sd->skillid_old == BD_ENCORE) && skill == sd->skillid_dance) - req.sp /= 2; - sp_rate = skill_db[j].sp_rate[lv-1]; - if (sp_rate > 0) - req.sp += (status->sp *sp_rate)/100; - else - req.sp += (status->max_sp * (-sp_rate))/100; - if (sd->dsprate != 100) - req.sp = req.sp *sd->dsprate / 100; - - ARR_FIND(0, ARRAYLENGTH(sd->skillusesprate), i, sd->skillusesprate[i].id == skill); - if (i < ARRAYLENGTH(sd->skillusesprate)) - sp_skill_rate_bonus += sd->skillusesprate[i].val; - ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == skill); - if (i < ARRAYLENGTH(sd->skillusesp)) - req.sp -= sd->skillusesp[i].val; - - req.sp = cap_value(req.sp *sp_skill_rate_bonus / 100, 0, SHRT_MAX); - - if (sc) { - if (sc->data[SC__LAZINESS]) - req.sp += req.sp + sc->data[SC__LAZINESS]->val1 * 10; - if (sc->data[SC_UNLIMITEDHUMMINGVOICE]) - req.sp += req.sp * sc->data[SC_UNLIMITEDHUMMINGVOICE]->val2 / 100; - if (sc->data[SC_RECOGNIZEDSPELL]) - req.sp += req.sp / 4; - } - - req.zeny = skill_db[j].zeny[lv-1]; - - if (sc && sc->data[SC__UNLUCKY]) - req.zeny += sc->data[SC__UNLUCKY]->val1 * 500; - - req.spiritball = skill_db[j].spiritball[lv-1]; - - req.state = skill_db[j].state; - - req.mhp = skill_db[j].mhp[lv-1]; - - req.weapon = skill_db[j].weapon; - - req.ammo_qty = skill_db[j].ammo_qty[lv-1]; - if (req.ammo_qty) - req.ammo = skill_db[j].ammo; - - if (!req.ammo && skill && skill_isammotype(sd, skill)) { - //Assume this skill is using the weapon, therefore it requires arrows. - req.ammo = 0xFFFFFFFF; //Enable use on all ammo types. - req.ammo_qty = 1; - } - - for (i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++) { - if ((skill == AM_POTIONPITCHER || skill == CR_SLIMPITCHER || skill == CR_CULTIVATION) && i != lv%11 - 1) - continue; - - switch (skill) { - case AM_CALLHOMUN: - if (sd->status.hom_id) //Don't delete items when hom is already out. - continue; - break; - case NC_SHAPESHIFT: - if (i < 4) - continue; - break; - case WZ_FIREPILLAR: // celest - if (lv <= 5) // no gems required at level 1-5 - continue; - break; - case AB_ADORAMUS: - if (itemid_isgemstone(skill_db[j].itemid[i]) && skill_check_pc_partner(sd,skill,&lv, 1, 2)) - continue; - break; - case WL_COMET: - if (itemid_isgemstone(skill_db[j].itemid[i]) && skill_check_pc_partner(sd,skill,&lv, 1, 0)) - continue; - break; - case GN_FIRE_EXPANSION: - if (i < 5) - continue; - break; - case SO_SUMMON_AGNI: - case SO_SUMMON_AQUA: - case SO_SUMMON_VENTUS: - case SO_SUMMON_TERA: - case SO_WATER_INSIGNIA: - case SO_FIRE_INSIGNIA: - case SO_WIND_INSIGNIA: - case SO_EARTH_INSIGNIA: - if (i < 3) - continue; - break; - } - - req.itemid[i] = skill_db[j].itemid[i]; - req.amount[i] = skill_db[j].amount[i]; - - if (itemid_isgemstone(req.itemid[i]) && skill != HW_GANBANTEIN) { - if (sd->special_state.no_gemstone) { - //Make it substract 1 gem rather than skipping the cost. - if (--req.amount[i] < 1) - req.itemid[i] = 0; - } - if (sc && sc->data[SC_INTOABYSS]) { - if (skill != SA_ABRACADABRA) - req.itemid[i] = req.amount[i] = 0; - else if (--req.amount[i] < 1) - req.amount[i] = 1; // Hocus Pocus allways use at least 1 gem - } - } - if (skill >= HT_SKIDTRAP && skill <= HT_TALKIEBOX && pc_checkskill(sd, RA_RESEARCHTRAP) > 0) { - if ((j=pc_search_inventory(sd,req.itemid[i])) < 0 || (j >= 0 && sd->status.inventory[j].amount < req.amount[i])) { - req.itemid[i] = ITEMID_TRAP_ALLOY; - req.amount[i] = 1; - } - break; - } - } - - /* requirements are level-dependent */ - switch (skill) { - case NC_SHAPESHIFT: - case GN_FIRE_EXPANSION: - case SO_SUMMON_AGNI: - case SO_SUMMON_AQUA: - case SO_SUMMON_VENTUS: - case SO_SUMMON_TERA: - case SO_WATER_INSIGNIA: - case SO_FIRE_INSIGNIA: - case SO_WIND_INSIGNIA: - case SO_EARTH_INSIGNIA: - req.itemid[lv-1] = skill_db[j].itemid[lv-1]; - req.amount[lv-1] = skill_db[j].amount[lv-1]; - break; - } + req.state = skill_db[j].state; - // Check for cost reductions due to skills & SCs - switch (skill) { - case MC_MAMMONITE: - if (pc_checkskill(sd,BS_UNFAIRLYTRICK)>0) - req.zeny -= req.zeny*10/100; - break; - case AL_HOLYLIGHT: - if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_PRIEST) - req.sp *= 5; - break; - case SL_SMA: - case SL_STUN: - case SL_STIN: { - int kaina_lv = pc_checkskill(sd,SL_KAINA); - - if (kaina_lv==0 || sd->status.base_level<70) - break; - if (sd->status.base_level>=90) - req.sp -= req.sp*7*kaina_lv/100; - else if (sd->status.base_level>=80) - req.sp -= req.sp*5*kaina_lv/100; - else if (sd->status.base_level>=70) - req.sp -= req.sp*3*kaina_lv/100; - } - break; - case MO_TRIPLEATTACK: - case MO_CHAINCOMBO: - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) - req.sp -= req.sp*25/100; //FIXME: Need real data. this is a custom value. - break; - case MO_BODYRELOCATION: - if (sc && sc->data[SC_EXPLOSIONSPIRITS]) - req.spiritball = 0; - break; - case MO_EXTREMITYFIST: - if (sc) { - if (sc->data[SC_BLADESTOP]) - req.spiritball--; - else if (sc->data[SC_COMBO]) { - switch (sc->data[SC_COMBO]->val1) { - case MO_COMBOFINISH: - req.spiritball = 4; - break; - case CH_TIGERFIST: - req.spiritball = 3; - break; - case CH_CHAINCRUSH: //It should consume whatever is left as long as it's at least 1. - req.spiritball = sd->spiritball?sd->spiritball:1; - break; - } - } else if (sc->data[SC_RAISINGDRAGON] && sd->spiritball > 5) - req.spiritball = sd->spiritball; // must consume all regardless of the amount required - } - break; - case SR_RAMPAGEBLASTER: - req.spiritball = sd->spiritball?sd->spiritball:15; - break; - case SR_GATEOFHELL: - if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) - req.sp -= req.sp * 10 / 100; - break; - case SO_SUMMON_AGNI: - case SO_SUMMON_AQUA: - case SO_SUMMON_VENTUS: - case SO_SUMMON_TERA: - req.sp -= req.sp * (5 + 5 * pc_checkskill(sd,SO_EL_SYMPATHY)) / 100; - break; - } + req.mhp = skill_db[j].mhp[lv-1]; + + req.weapon = skill_db[j].weapon; + + req.ammo_qty = skill_db[j].ammo_qty[lv-1]; + if (req.ammo_qty) + req.ammo = skill_db[j].ammo; - return req; + if (!req.ammo && skill && skill_isammotype(sd, skill)) + { //Assume this skill is using the weapon, therefore it requires arrows. + req.ammo = 0xFFFFFFFF; //Enable use on all ammo types. + req.ammo_qty = 1; + } + + for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++ ) { + if( (skill == AM_POTIONPITCHER || skill == CR_SLIMPITCHER || skill == CR_CULTIVATION) && i != lv%11 - 1 ) + continue; + + switch( skill ) { + case AM_CALLHOMUN: + if (sd->status.hom_id) //Don't delete items when hom is already out. + continue; + break; + case NC_SHAPESHIFT: + if( i < 4 ) + continue; + break; + case WZ_FIREPILLAR: // celest + if (lv <= 5) // no gems required at level 1-5 + continue; + break; + case AB_ADORAMUS: + if( itemid_isgemstone(skill_db[j].itemid[i]) && skill_check_pc_partner(sd,skill,&lv, 1, 2) ) + continue; + break; + case WL_COMET: + if( itemid_isgemstone(skill_db[j].itemid[i]) && skill_check_pc_partner(sd,skill,&lv, 1, 0) ) + continue; + break; + case GN_FIRE_EXPANSION: + if( i < 5 ) + continue; + break; + case SO_SUMMON_AGNI: + case SO_SUMMON_AQUA: + case SO_SUMMON_VENTUS: + case SO_SUMMON_TERA: + case SO_WATER_INSIGNIA: + case SO_FIRE_INSIGNIA: + case SO_WIND_INSIGNIA: + case SO_EARTH_INSIGNIA: + if( i < 3 ) + continue; + break; + } + + req.itemid[i] = skill_db[j].itemid[i]; + req.amount[i] = skill_db[j].amount[i]; + + if( itemid_isgemstone(req.itemid[i]) && skill != HW_GANBANTEIN ) + { + if( sd->special_state.no_gemstone ) + { //Make it substract 1 gem rather than skipping the cost. + if( --req.amount[i] < 1 ) + req.itemid[i] = 0; + } + if(sc && sc->data[SC_INTOABYSS]) + { + if( skill != SA_ABRACADABRA ) + req.itemid[i] = req.amount[i] = 0; + else if( --req.amount[i] < 1 ) + req.amount[i] = 1; // Hocus Pocus allways use at least 1 gem + } + } + if( skill >= HT_SKIDTRAP && skill <= HT_TALKIEBOX && pc_checkskill(sd, RA_RESEARCHTRAP) > 0){ + if( (j=pc_search_inventory(sd,req.itemid[i])) < 0 || ( j >= 0 && sd->status.inventory[j].amount < req.amount[i] ) ){ + req.itemid[i] = ITEMID_TRAP_ALLOY; + req.amount[i] = 1; + } + break; + } + } + + /* requirements are level-dependent */ + switch( skill ) { + case NC_SHAPESHIFT: + case GN_FIRE_EXPANSION: + case SO_SUMMON_AGNI: + case SO_SUMMON_AQUA: + case SO_SUMMON_VENTUS: + case SO_SUMMON_TERA: + case SO_WATER_INSIGNIA: + case SO_FIRE_INSIGNIA: + case SO_WIND_INSIGNIA: + case SO_EARTH_INSIGNIA: + req.itemid[lv-1] = skill_db[j].itemid[lv-1]; + req.amount[lv-1] = skill_db[j].amount[lv-1]; + break; + } + + // Check for cost reductions due to skills & SCs + switch(skill) { + case MC_MAMMONITE: + if(pc_checkskill(sd,BS_UNFAIRLYTRICK)>0) + req.zeny -= req.zeny*10/100; + break; + case AL_HOLYLIGHT: + if(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_PRIEST) + req.sp *= 5; + break; + case SL_SMA: + case SL_STUN: + case SL_STIN: + { + int kaina_lv = pc_checkskill(sd,SL_KAINA); + + if(kaina_lv==0 || sd->status.base_level<70) + break; + if(sd->status.base_level>=90) + req.sp -= req.sp*7*kaina_lv/100; + else if(sd->status.base_level>=80) + req.sp -= req.sp*5*kaina_lv/100; + else if(sd->status.base_level>=70) + req.sp -= req.sp*3*kaina_lv/100; + } + break; + case MO_TRIPLEATTACK: + case MO_CHAINCOMBO: + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + if(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) + req.sp -= req.sp*25/100; //FIXME: Need real data. this is a custom value. + break; + case MO_BODYRELOCATION: + if( sc && sc->data[SC_EXPLOSIONSPIRITS] ) + req.spiritball = 0; + break; + case MO_EXTREMITYFIST: + if( sc ) + { + if( sc->data[SC_BLADESTOP] ) + req.spiritball--; + else if( sc->data[SC_COMBO] ) + { + switch( sc->data[SC_COMBO]->val1 ) + { + case MO_COMBOFINISH: + req.spiritball = 4; + break; + case CH_TIGERFIST: + req.spiritball = 3; + break; + case CH_CHAINCRUSH: //It should consume whatever is left as long as it's at least 1. + req.spiritball = sd->spiritball?sd->spiritball:1; + break; + } + }else if( sc->data[SC_RAISINGDRAGON] && sd->spiritball > 5) + req.spiritball = sd->spiritball; // must consume all regardless of the amount required + } + break; + case SR_RAMPAGEBLASTER: + req.spiritball = sd->spiritball?sd->spiritball:15; + break; + case SR_GATEOFHELL: + if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) + req.sp -= req.sp * 10 / 100; + break; + case SO_SUMMON_AGNI: + case SO_SUMMON_AQUA: + case SO_SUMMON_VENTUS: + case SO_SUMMON_TERA: + req.sp -= req.sp * (5 + 5 * pc_checkskill(sd,SO_EL_SYMPATHY)) / 100; + break; + } + + return req; } /*========================================== * Does cast-time reductions based on dex, item bonuses and config setting *------------------------------------------*/ -int skill_castfix(struct block_list *bl, int skill_id, int skill_lv) -{ - int time = skill_get_cast(skill_id, skill_lv); +int skill_castfix (struct block_list *bl, int skill_id, int skill_lv) { + int time = skill_get_cast(skill_id, skill_lv); - nullpo_ret(bl); + nullpo_ret(bl); #ifndef RENEWAL_CAST - { - struct map_session_data *sd; - - sd = BL_CAST(BL_PC, bl); - - // calculate base cast time (reduced by dex) - if (!(skill_get_castnodex(skill_id, skill_lv)&1)) { - int scale = battle_config.castrate_dex_scale - status_get_dex(bl); - if (scale > 0) // not instant cast - time = time * scale / battle_config.castrate_dex_scale; - else - return 0; // instant cast - } - - // calculate cast time reduced by item/card bonuses - if (!(skill_get_castnodex(skill_id, skill_lv)&4) && sd) { - int i; - if (sd->castrate != 100) - time = time * sd->castrate / 100; - for (i = 0; i < ARRAYLENGTH(sd->skillcast) && sd->skillcast[i].id; i++) { - if (sd->skillcast[i].id == skill_id) { - time+= time * sd->skillcast[i].val / 100; - break; - } - } - } + { + struct map_session_data *sd; + + sd = BL_CAST(BL_PC, bl); + + // calculate base cast time (reduced by dex) + if( !(skill_get_castnodex(skill_id, skill_lv)&1) ) { + int scale = battle_config.castrate_dex_scale - status_get_dex(bl); + if( scale > 0 ) // not instant cast + time = time * scale / battle_config.castrate_dex_scale; + else + return 0; // instant cast + } + + // calculate cast time reduced by item/card bonuses + if( !(skill_get_castnodex(skill_id, skill_lv)&4) && sd ) + { + int i; + if( sd->castrate != 100 ) + time = time * sd->castrate / 100; + for( i = 0; i < ARRAYLENGTH(sd->skillcast) && sd->skillcast[i].id; i++ ) + { + if( sd->skillcast[i].id == skill_id ) + { + time+= time * sd->skillcast[i].val / 100; + break; + } + } + } - } + } #endif - // config cast time multiplier - if (battle_config.cast_rate != 100) - time = time * battle_config.cast_rate / 100; - // return final cast time - time = max(time, 0); - - // ShowInfo("Castime castfix = %d\n",time); - return time; + // config cast time multiplier + if (battle_config.cast_rate != 100) + time = time * battle_config.cast_rate / 100; + // return final cast time + time = max(time, 0); + +// ShowInfo("Castime castfix = %d\n",time); + return time; } /*========================================== * Does cast-time reductions based on sc data. *------------------------------------------*/ -int skill_castfix_sc(struct block_list *bl, int time) +int skill_castfix_sc (struct block_list *bl, int time) { - struct status_change *sc = status_get_sc(bl); + struct status_change *sc = status_get_sc(bl); - if (time < 0) - return 0; + if( time < 0 ) + return 0; - if (sc && sc->count) { - if (sc->data[SC_SLOWCAST]) - time += time * sc->data[SC_SLOWCAST]->val2 / 100; + if (sc && sc->count) { + if (sc->data[SC_SLOWCAST]) + time += time * sc->data[SC_SLOWCAST]->val2 / 100; if (sc->data[SC_PARALYSIS]) time += sc->data[SC_PARALYSIS]->val3; - if (sc->data[SC_SUFFRAGIUM]) { - time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100; - status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER); - } - if (sc->data[SC_MEMORIZE]) { - time>>=1; - if ((--sc->data[SC_MEMORIZE]->val2) <= 0) - status_change_end(bl, SC_MEMORIZE, INVALID_TIMER); - } - if (sc->data[SC_POEMBRAGI]) - time -= time * sc->data[SC_POEMBRAGI]->val2 / 100; - if (sc->data[SC_IZAYOI]) - time -= time * 50 / 100; - } - time = max(time, 0); - - // ShowInfo("Castime castfix_sc = %d\n",time); - return time; + if (sc->data[SC_SUFFRAGIUM]) { + time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100; + status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER); + } + if (sc->data[SC_MEMORIZE]) { + time>>=1; + if ((--sc->data[SC_MEMORIZE]->val2) <= 0) + status_change_end(bl, SC_MEMORIZE, INVALID_TIMER); + } + if (sc->data[SC_POEMBRAGI]) + time -= time * sc->data[SC_POEMBRAGI]->val2 / 100; + if (sc->data[SC_IZAYOI]) + time -= time * 50 / 100; + } + time = max(time, 0); + +// ShowInfo("Castime castfix_sc = %d\n",time); + return time; } #ifdef RENEWAL_CAST -int skill_vfcastfix(struct block_list *bl, double time, int skill_id, int skill_lv) +int skill_vfcastfix (struct block_list *bl, double time, int skill_id, int skill_lv) { - struct status_change *sc = status_get_sc(bl); - struct map_session_data *sd = BL_CAST(BL_PC,bl); - int fixed = skill_get_fixed_cast(skill_id, skill_lv), fixcast_r = 0, varcast_r = 0, i = 0; - - if (time < 0) - return 0; - - if (fixed == 0) { - fixed = (int)time * 20 / 100; // fixed time - time = time * 80 / 100; // variable time - } else if (fixed < 0) // no fixed cast time - fixed = 0; - - if (sd && !(skill_get_castnodex(skill_id, skill_lv)&4)) { // Increases/Decreases fixed/variable cast time of a skill by item/card bonuses. - if (sd->bonus.varcastrate < 0) - VARCAST_REDUCTION(sd->bonus.varcastrate); - for (i = 0; i < ARRAYLENGTH(sd->skillfixcast) && sd->skillfixcast[i].id; i++) - if (sd->skillfixcast[i].id == skill_id) { // bonus2 bSkillFixedCast - fixed += sd->skillfixcast[i].val; - break; - } - for (i = 0; i < ARRAYLENGTH(sd->skillvarcast) && sd->skillvarcast[i].id; i++) - if (sd->skillvarcast[i].id == skill_id) { // bonus2 bSkillVariableCast - time += sd->skillvarcast[i].val; - break; - } - for (i = 0; i < ARRAYLENGTH(sd->skillcast) && sd->skillcast[i].id; i++) - if (sd->skillcast[i].id == skill_id) { // bonus2 bVariableCastrate - if ((i=sd->skillcast[i].val) < 0) - VARCAST_REDUCTION(i); - break; - } - } - - if (sc && sc->count && !(skill_get_castnodex(skill_id, skill_lv)&2)) { - // All variable cast additive bonuses must come first - if (sc->data[SC_SLOWCAST]) - VARCAST_REDUCTION(-sc->data[SC_SLOWCAST]->val2); - - // Variable cast reduction bonuses - if (sc->data[SC_SUFFRAGIUM]) { - VARCAST_REDUCTION(sc->data[SC_SUFFRAGIUM]->val2); - status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER); - } - if (sc->data[SC_MEMORIZE]) { - VARCAST_REDUCTION(50); - if ((--sc->data[SC_MEMORIZE]->val2) <= 0) - status_change_end(bl, SC_MEMORIZE, INVALID_TIMER); - } - if (sc->data[SC_POEMBRAGI]) - VARCAST_REDUCTION(sc->data[SC_POEMBRAGI]->val2); - if (sc->data[SC_IZAYOI]) - VARCAST_REDUCTION(50); - if (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3 && (skill_get_ele(skill_id, skill_lv) == ELE_WATER)) - VARCAST_REDUCTION(30); //Reduces 30% Variable Cast Time of Water spells. - // Fixed cast reduction bonuses - if (sc->data[SC__LAZINESS]) - fixcast_r = max(fixcast_r, sc->data[SC__LAZINESS]->val2); - if (sc->data[SC_SECRAMENT]) - fixcast_r = max(fixcast_r, sc->data[SC_SECRAMENT]->val2); - if (sd && (skill_lv = pc_checkskill(sd, WL_RADIUS)) && skill_id >= WL_WHITEIMPRISON && skill_id <= WL_FREEZE_SP) - fixcast_r = max(fixcast_r, 5 + skill_lv * 5); - // Fixed cast non percentage bonuses - if (sc->data[SC_MANDRAGORA] && (skill_id >= SM_BASH && skill_id <= RETURN_TO_ELDICASTES)) - fixed += sc->data[SC_MANDRAGORA]->val1 * 1000 / 2; - if (sc->data[SC_IZAYOI] && (skill_id >= NJ_TOBIDOUGU && skill_id <= NJ_ISSEN)) - fixed = 0; - } - - if (sd && !(skill_get_castnodex(skill_id, skill_lv)&4)) { - VARCAST_REDUCTION(max(sd->bonus.varcastrate, 0) + max(i, 0)); - fixcast_r = max(fixcast_r, sd->bonus.fixcastrate) + min(sd->bonus.fixcastrate,0); - } - - if (varcast_r < 0) // now compute overall factors - time = time * (1 - (float)varcast_r / 100); - if (!(skill_get_castnodex(skill_id, skill_lv)&1)) // reduction from status point - time = (1 - sqrt(((float)(status_get_dex(bl)*2 + status_get_int(bl)) / battle_config.vcast_stat_scale))) * time; - // underflow checking/capping - time = max(time, 0) + (1 - (float)min(fixcast_r, 100) / 100) * fixed; - - // ShowInfo("Casttime vfcastfix = %d\n",time); - return (int)time; + struct status_change *sc = status_get_sc(bl); + struct map_session_data *sd = BL_CAST(BL_PC,bl); + int fixed = skill_get_fixed_cast(skill_id, skill_lv), fixcast_r = 0, varcast_r = 0, i = 0; + + if( time < 0 ) + return 0; + + if( fixed == 0 ){ + fixed = (int)time * 20 / 100; // fixed time + time = time * 80 / 100; // variable time + }else if( fixed < 0 ) // no fixed cast time + fixed = 0; + + if(sd && !(skill_get_castnodex(skill_id, skill_lv)&4) ){ // Increases/Decreases fixed/variable cast time of a skill by item/card bonuses. + if( sd->bonus.varcastrate < 0 ) + VARCAST_REDUCTION(sd->bonus.varcastrate); + for (i = 0; i < ARRAYLENGTH(sd->skillfixcast) && sd->skillfixcast[i].id; i++) + if (sd->skillfixcast[i].id == skill_id){ // bonus2 bSkillFixedCast + fixed += sd->skillfixcast[i].val; + break; + } + for( i = 0; i < ARRAYLENGTH(sd->skillvarcast) && sd->skillvarcast[i].id; i++ ) + if( sd->skillvarcast[i].id == skill_id ){ // bonus2 bSkillVariableCast + time += sd->skillvarcast[i].val; + break; + } + for( i = 0; i < ARRAYLENGTH(sd->skillcast) && sd->skillcast[i].id; i++ ) + if( sd->skillcast[i].id == skill_id ){ // bonus2 bVariableCastrate + if( (i=sd->skillcast[i].val) < 0) + VARCAST_REDUCTION(i); + break; + } + } + + if (sc && sc->count && !(skill_get_castnodex(skill_id, skill_lv)&2) ) { + // All variable cast additive bonuses must come first + if (sc->data[SC_SLOWCAST]) + VARCAST_REDUCTION(-sc->data[SC_SLOWCAST]->val2); + + // Variable cast reduction bonuses + if (sc->data[SC_SUFFRAGIUM]) { + VARCAST_REDUCTION(sc->data[SC_SUFFRAGIUM]->val2); + status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER); + } + if (sc->data[SC_MEMORIZE]) { + VARCAST_REDUCTION(50); + if ((--sc->data[SC_MEMORIZE]->val2) <= 0) + status_change_end(bl, SC_MEMORIZE, INVALID_TIMER); + } + if (sc->data[SC_POEMBRAGI]) + VARCAST_REDUCTION(sc->data[SC_POEMBRAGI]->val2); + if (sc->data[SC_IZAYOI]) + VARCAST_REDUCTION(50); + if (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3 && (skill_get_ele(skill_id, skill_lv) == ELE_WATER)) + VARCAST_REDUCTION(30); //Reduces 30% Variable Cast Time of Water spells. + // Fixed cast reduction bonuses + if( sc->data[SC__LAZINESS] ) + fixcast_r = max(fixcast_r, sc->data[SC__LAZINESS]->val2); + if( sc->data[SC_SECRAMENT] ) + fixcast_r = max(fixcast_r, sc->data[SC_SECRAMENT]->val2); + if( sd && ( skill_lv = pc_checkskill(sd, WL_RADIUS) ) && skill_id >= WL_WHITEIMPRISON && skill_id <= WL_FREEZE_SP ) + fixcast_r = max(fixcast_r, 5 + skill_lv * 5); + // Fixed cast non percentage bonuses + if( sc->data[SC_MANDRAGORA] && (skill_id >= SM_BASH && skill_id <= RETURN_TO_ELDICASTES) ) + fixed += sc->data[SC_MANDRAGORA]->val1 * 1000 / 2; + if (sc->data[SC_IZAYOI] && (skill_id >= NJ_TOBIDOUGU && skill_id <= NJ_ISSEN)) + fixed = 0; + } + + if( sd && !(skill_get_castnodex(skill_id, skill_lv)&4) ){ + VARCAST_REDUCTION( max(sd->bonus.varcastrate, 0) + max(i, 0) ); + fixcast_r = max(fixcast_r, sd->bonus.fixcastrate) + min(sd->bonus.fixcastrate,0); + } + + if( varcast_r < 0 ) // now compute overall factors + time = time * (1 - (float)varcast_r / 100); + if( !(skill_get_castnodex(skill_id, skill_lv)&1) )// reduction from status point + time = (1 - sqrt( ((float)(status_get_dex(bl)*2 + status_get_int(bl)) / battle_config.vcast_stat_scale) )) * time; + // underflow checking/capping + time = max(time, 0) + (1 - (float)min(fixcast_r, 100) / 100) * fixed; + + // ShowInfo("Casttime vfcastfix = %d\n",time); + return (int)time; } #endif /*========================================== * Does delay reductions based on dex/agi, sc data, item bonuses, ... *------------------------------------------*/ -int skill_delayfix(struct block_list *bl, int skill_id, int skill_lv) +int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv) { - int delaynodex = skill_get_delaynodex(skill_id, skill_lv); - int time = skill_get_delay(skill_id, skill_lv); - struct map_session_data *sd; - struct status_change *sc = status_get_sc(bl); - - nullpo_ret(bl); - sd = BL_CAST(BL_PC, bl); - - if (skill_id == SA_ABRACADABRA || skill_id == WM_RANDOMIZESPELL) - return 0; //Will use picked skill's delay. - - if (bl->type&battle_config.no_skill_delay) - return battle_config.min_skill_delay_limit; - - if (time < 0) - time = -time + status_get_amotion(bl); // If set to <0, add to attack motion. - - // Delay reductions - switch (skill_id) { //Monk combo skills have their delay reduced by agi/dex. - case MO_TRIPLEATTACK: - case MO_CHAINCOMBO: - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - case SR_DRAGONCOMBO: - case SR_FALLENEMPIRE: - time -= 4*status_get_agi(bl) - 2*status_get_dex(bl); - break; - case HP_BASILICA: - if (sc && !sc->data[SC_BASILICA]) - time = 0; // There is no Delay on Basilica creation, only on cancel - break; - default: - if (battle_config.delay_dependon_dex && !(delaynodex&1)) { - // if skill delay is allowed to be reduced by dex - int scale = battle_config.castrate_dex_scale - status_get_dex(bl); - if (scale > 0) - time = time * scale / battle_config.castrate_dex_scale; - else //To be capped later to minimum. - time = 0; - } - if (battle_config.delay_dependon_agi && !(delaynodex&1)) { - // if skill delay is allowed to be reduced by agi - int scale = battle_config.castrate_dex_scale - status_get_agi(bl); - if (scale > 0) - time = time * scale / battle_config.castrate_dex_scale; - else //To be capped later to minimum. - time = 0; - } - } - - if (sc && sc->data[SC_SPIRIT]) { - switch (skill_id) { - case CR_SHIELDBOOMERANG: - if (sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) - time /= 2; - break; - case AS_SONICBLOW: - if (!map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN) - time /= 2; - break; - } - } - - if (!(delaynodex&2)) { - if (sc && sc->count) { - if (sc->data[SC_POEMBRAGI]) - time -= time * sc->data[SC_POEMBRAGI]->val3 / 100; - if (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 3 && (skill_get_ele(skill_id, skill_lv) == ELE_WIND)) - time /= 2; // After Delay of Wind element spells reduced by 50%. - } - - } - - if (!(delaynodex&4) && sd && sd->delayrate != 100) - time = time * sd->delayrate / 100; - - if (battle_config.delay_rate != 100) - time = time * battle_config.delay_rate / 100; - - //min delay - time = max(time, status_get_amotion(bl)); // Delay can never be below amotion [Playtester] - time = max(time, battle_config.min_skill_delay_limit); - - // ShowInfo("Delay delayfix = %d\n",time); - return time; + int delaynodex = skill_get_delaynodex(skill_id, skill_lv); + int time = skill_get_delay(skill_id, skill_lv); + struct map_session_data *sd; + struct status_change *sc = status_get_sc(bl); + + nullpo_ret(bl); + sd = BL_CAST(BL_PC, bl); + + if (skill_id == SA_ABRACADABRA || skill_id == WM_RANDOMIZESPELL) + return 0; //Will use picked skill's delay. + + if (bl->type&battle_config.no_skill_delay) + return battle_config.min_skill_delay_limit; + + if (time < 0) + time = -time + status_get_amotion(bl); // If set to <0, add to attack motion. + + // Delay reductions + switch (skill_id) { //Monk combo skills have their delay reduced by agi/dex. + case MO_TRIPLEATTACK: + case MO_CHAINCOMBO: + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + case SR_DRAGONCOMBO: + case SR_FALLENEMPIRE: + time -= 4*status_get_agi(bl) - 2*status_get_dex(bl); + break; + case HP_BASILICA: + if( sc && !sc->data[SC_BASILICA] ) + time = 0; // There is no Delay on Basilica creation, only on cancel + break; + default: + if (battle_config.delay_dependon_dex && !(delaynodex&1)) + { // if skill delay is allowed to be reduced by dex + int scale = battle_config.castrate_dex_scale - status_get_dex(bl); + if (scale > 0) + time = time * scale / battle_config.castrate_dex_scale; + else //To be capped later to minimum. + time = 0; + } + if (battle_config.delay_dependon_agi && !(delaynodex&1)) + { // if skill delay is allowed to be reduced by agi + int scale = battle_config.castrate_dex_scale - status_get_agi(bl); + if (scale > 0) + time = time * scale / battle_config.castrate_dex_scale; + else //To be capped later to minimum. + time = 0; + } + } + + if ( sc && sc->data[SC_SPIRIT] ) + { + switch (skill_id) { + case CR_SHIELDBOOMERANG: + if (sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) + time /= 2; + break; + case AS_SONICBLOW: + if (!map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN) + time /= 2; + break; + } + } + + if (!(delaynodex&2)) + { + if (sc && sc->count) { + if (sc->data[SC_POEMBRAGI]) + time -= time * sc->data[SC_POEMBRAGI]->val3 / 100; + if (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 3 && (skill_get_ele(skill_id, skill_lv) == ELE_WIND)) + time /= 2; // After Delay of Wind element spells reduced by 50%. + } + + } + + if( !(delaynodex&4) && sd && sd->delayrate != 100 ) + time = time * sd->delayrate / 100; + + if (battle_config.delay_rate != 100) + time = time * battle_config.delay_rate / 100; + + //min delay + time = max(time, status_get_amotion(bl)); // Delay can never be below amotion [Playtester] + time = max(time, battle_config.min_skill_delay_limit); + +// ShowInfo("Delay delayfix = %d\n",time); + return time; } /*========================================= * *-----------------------------------------*/ struct square { - int val1[5]; - int val2[5]; + int val1[5]; + int val2[5]; }; -static void skill_brandishspear_first(struct square *tc, int dir, int x, int y) +static void skill_brandishspear_first (struct square *tc, int dir, int x, int y) { - nullpo_retv(tc); - - if (dir == 0) { - tc->val1[0]=x-2; - tc->val1[1]=x-1; - tc->val1[2]=x; - tc->val1[3]=x+1; - tc->val1[4]=x+2; - tc->val2[0]= - tc->val2[1]= - tc->val2[2]= - tc->val2[3]= - tc->val2[4]=y-1; - } else if (dir==2) { - tc->val1[0]= - tc->val1[1]= - tc->val1[2]= - tc->val1[3]= - tc->val1[4]=x+1; - tc->val2[0]=y+2; - tc->val2[1]=y+1; - tc->val2[2]=y; - tc->val2[3]=y-1; - tc->val2[4]=y-2; - } else if (dir==4) { - tc->val1[0]=x-2; - tc->val1[1]=x-1; - tc->val1[2]=x; - tc->val1[3]=x+1; - tc->val1[4]=x+2; - tc->val2[0]= - tc->val2[1]= - tc->val2[2]= - tc->val2[3]= - tc->val2[4]=y+1; - } else if (dir==6) { - tc->val1[0]= - tc->val1[1]= - tc->val1[2]= - tc->val1[3]= - tc->val1[4]=x-1; - tc->val2[0]=y+2; - tc->val2[1]=y+1; - tc->val2[2]=y; - tc->val2[3]=y-1; - tc->val2[4]=y-2; - } else if (dir==1) { - tc->val1[0]=x-1; - tc->val1[1]=x; - tc->val1[2]=x+1; - tc->val1[3]=x+2; - tc->val1[4]=x+3; - tc->val2[0]=y-4; - tc->val2[1]=y-3; - tc->val2[2]=y-1; - tc->val2[3]=y; - tc->val2[4]=y+1; - } else if (dir==3) { - tc->val1[0]=x+3; - tc->val1[1]=x+2; - tc->val1[2]=x+1; - tc->val1[3]=x; - tc->val1[4]=x-1; - tc->val2[0]=y-1; - tc->val2[1]=y; - tc->val2[2]=y+1; - tc->val2[3]=y+2; - tc->val2[4]=y+3; - } else if (dir==5) { - tc->val1[0]=x+1; - tc->val1[1]=x; - tc->val1[2]=x-1; - tc->val1[3]=x-2; - tc->val1[4]=x-3; - tc->val2[0]=y+3; - tc->val2[1]=y+2; - tc->val2[2]=y+1; - tc->val2[3]=y; - tc->val2[4]=y-1; - } else if (dir==7) { - tc->val1[0]=x-3; - tc->val1[1]=x-2; - tc->val1[2]=x-1; - tc->val1[3]=x; - tc->val1[4]=x+1; - tc->val2[1]=y; - tc->val2[0]=y+1; - tc->val2[2]=y-1; - tc->val2[3]=y-2; - tc->val2[4]=y-3; - } + nullpo_retv(tc); + + if(dir == 0){ + tc->val1[0]=x-2; + tc->val1[1]=x-1; + tc->val1[2]=x; + tc->val1[3]=x+1; + tc->val1[4]=x+2; + tc->val2[0]= + tc->val2[1]= + tc->val2[2]= + tc->val2[3]= + tc->val2[4]=y-1; + } + else if(dir==2){ + tc->val1[0]= + tc->val1[1]= + tc->val1[2]= + tc->val1[3]= + tc->val1[4]=x+1; + tc->val2[0]=y+2; + tc->val2[1]=y+1; + tc->val2[2]=y; + tc->val2[3]=y-1; + tc->val2[4]=y-2; + } + else if(dir==4){ + tc->val1[0]=x-2; + tc->val1[1]=x-1; + tc->val1[2]=x; + tc->val1[3]=x+1; + tc->val1[4]=x+2; + tc->val2[0]= + tc->val2[1]= + tc->val2[2]= + tc->val2[3]= + tc->val2[4]=y+1; + } + else if(dir==6){ + tc->val1[0]= + tc->val1[1]= + tc->val1[2]= + tc->val1[3]= + tc->val1[4]=x-1; + tc->val2[0]=y+2; + tc->val2[1]=y+1; + tc->val2[2]=y; + tc->val2[3]=y-1; + tc->val2[4]=y-2; + } + else if(dir==1){ + tc->val1[0]=x-1; + tc->val1[1]=x; + tc->val1[2]=x+1; + tc->val1[3]=x+2; + tc->val1[4]=x+3; + tc->val2[0]=y-4; + tc->val2[1]=y-3; + tc->val2[2]=y-1; + tc->val2[3]=y; + tc->val2[4]=y+1; + } + else if(dir==3){ + tc->val1[0]=x+3; + tc->val1[1]=x+2; + tc->val1[2]=x+1; + tc->val1[3]=x; + tc->val1[4]=x-1; + tc->val2[0]=y-1; + tc->val2[1]=y; + tc->val2[2]=y+1; + tc->val2[3]=y+2; + tc->val2[4]=y+3; + } + else if(dir==5){ + tc->val1[0]=x+1; + tc->val1[1]=x; + tc->val1[2]=x-1; + tc->val1[3]=x-2; + tc->val1[4]=x-3; + tc->val2[0]=y+3; + tc->val2[1]=y+2; + tc->val2[2]=y+1; + tc->val2[3]=y; + tc->val2[4]=y-1; + } + else if(dir==7){ + tc->val1[0]=x-3; + tc->val1[1]=x-2; + tc->val1[2]=x-1; + tc->val1[3]=x; + tc->val1[4]=x+1; + tc->val2[1]=y; + tc->val2[0]=y+1; + tc->val2[2]=y-1; + tc->val2[3]=y-2; + tc->val2[4]=y-3; + } } -static void skill_brandishspear_dir(struct square *tc, int dir, int are) +static void skill_brandishspear_dir (struct square* tc, int dir, int are) { - int c; - nullpo_retv(tc); - - for (c = 0; c < 5; c++) { - switch (dir) { - case 0: - tc->val2[c]+=are; - break; - case 1: - tc->val1[c]-=are; - tc->val2[c]+=are; - break; - case 2: - tc->val1[c]-=are; - break; - case 3: - tc->val1[c]-=are; - tc->val2[c]-=are; - break; - case 4: - tc->val2[c]-=are; - break; - case 5: - tc->val1[c]+=are; - tc->val2[c]-=are; - break; - case 6: - tc->val1[c]+=are; - break; - case 7: - tc->val1[c]+=are; - tc->val2[c]+=are; - break; - } - } + int c; + nullpo_retv(tc); + + for( c = 0; c < 5; c++ ) + { + switch( dir ) + { + case 0: tc->val2[c]+=are; break; + case 1: tc->val1[c]-=are; tc->val2[c]+=are; break; + case 2: tc->val1[c]-=are; break; + case 3: tc->val1[c]-=are; tc->val2[c]-=are; break; + case 4: tc->val2[c]-=are; break; + case 5: tc->val1[c]+=are; tc->val2[c]-=are; break; + case 6: tc->val1[c]+=are; break; + case 7: tc->val1[c]+=are; tc->val2[c]+=are; break; + } + } } -void skill_brandishspear(struct block_list *src, struct block_list *bl, int skillid, int skilllv, unsigned int tick, int flag) +void skill_brandishspear(struct block_list* src, struct block_list* bl, int skillid, int skilllv, unsigned int tick, int flag) { - int c,n=4; - int dir = map_calc_dir(src,bl->x,bl->y); - struct square tc; - int x=bl->x,y=bl->y; - skill_brandishspear_first(&tc,dir,x,y); - skill_brandishspear_dir(&tc,dir,4); - skill_area_temp[1] = bl->id; - - if (skilllv > 9) { - for (c=1; c<4; c++) { - map_foreachincell(skill_area_sub, - bl->m,tc.val1[c],tc.val2[c],BL_CHAR, - src,skillid,skilllv,tick, flag|BCT_ENEMY|n, - skill_castend_damage_id); - } - } - if (skilllv > 6) { - skill_brandishspear_dir(&tc,dir,-1); - n--; - } else { - skill_brandishspear_dir(&tc,dir,-2); - n-=2; - } - - if (skilllv > 3) { - for (c=0; c<5; c++) { - map_foreachincell(skill_area_sub, - bl->m,tc.val1[c],tc.val2[c],BL_CHAR, - src,skillid,skilllv,tick, flag|BCT_ENEMY|n, - skill_castend_damage_id); - if (skilllv > 6 && n==3 && c==4) { - skill_brandishspear_dir(&tc,dir,-1); - n--; - c=-1; - } - } - } - for (c=0; c<10; c++) { - if (c==0||c==5) skill_brandishspear_dir(&tc,dir,-1); - map_foreachincell(skill_area_sub, - bl->m,tc.val1[c%5],tc.val2[c%5],BL_CHAR, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - } + int c,n=4; + int dir = map_calc_dir(src,bl->x,bl->y); + struct square tc; + int x=bl->x,y=bl->y; + skill_brandishspear_first(&tc,dir,x,y); + skill_brandishspear_dir(&tc,dir,4); + skill_area_temp[1] = bl->id; + + if(skilllv > 9){ + for(c=1;c<4;c++){ + map_foreachincell(skill_area_sub, + bl->m,tc.val1[c],tc.val2[c],BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|n, + skill_castend_damage_id); + } + } + if(skilllv > 6){ + skill_brandishspear_dir(&tc,dir,-1); + n--; + }else{ + skill_brandishspear_dir(&tc,dir,-2); + n-=2; + } + + if(skilllv > 3){ + for(c=0;c<5;c++){ + map_foreachincell(skill_area_sub, + bl->m,tc.val1[c],tc.val2[c],BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|n, + skill_castend_damage_id); + if(skilllv > 6 && n==3 && c==4){ + skill_brandishspear_dir(&tc,dir,-1); + n--;c=-1; + } + } + } + for(c=0;c<10;c++){ + if(c==0||c==5) skill_brandishspear_dir(&tc,dir,-1); + map_foreachincell(skill_area_sub, + bl->m,tc.val1[c%5],tc.val2[c%5],BL_CHAR, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); + } } /*========================================== * Weapon Repair [Celest/DracoRPG] *------------------------------------------*/ -void skill_repairweapon(struct map_session_data *sd, int idx) -{ - int material; - int materials[4] = { 1002, 998, 999, 756 }; - struct item *item; - struct map_session_data *target_sd; +void skill_repairweapon (struct map_session_data *sd, int idx) { + int material; + int materials[4] = { 1002, 998, 999, 756 }; + struct item *item; + struct map_session_data *target_sd; - nullpo_retv(sd); + nullpo_retv(sd); - if (!(target_sd = map_id2sd(sd->menuskill_val))) //Failed.... - return; + if ( !( target_sd = map_id2sd(sd->menuskill_val) ) ) //Failed.... + return; - if (idx == 0xFFFF) // No item selected ('Cancel' clicked) - return; - if (idx < 0 || idx >= MAX_INVENTORY) - return; //Invalid index?? + if( idx == 0xFFFF ) // No item selected ('Cancel' clicked) + return; + if( idx < 0 || idx >= MAX_INVENTORY ) + return; //Invalid index?? - item = &target_sd->status.inventory[idx]; - if (item->nameid <= 0 || item->attribute == 0) - return; //Again invalid item.... + item = &target_sd->status.inventory[idx]; + if( item->nameid <= 0 || item->attribute == 0 ) + return; //Again invalid item.... - if (sd != target_sd && !battle_check_range(&sd->bl,&target_sd->bl, skill_get_range2(&sd->bl, sd->menuskill_id,sd->menuskill_val2))) { - clif_item_repaireffect(sd,idx,1); - return; - } + if( sd != target_sd && !battle_check_range(&sd->bl,&target_sd->bl, skill_get_range2(&sd->bl, sd->menuskill_id,sd->menuskill_val2) ) ){ + clif_item_repaireffect(sd,idx,1); + return; + } - if (target_sd->inventory_data[idx]->type == IT_WEAPON) - material = materials [ target_sd->inventory_data[idx]->wlv - 1 ]; // Lv1/2/3/4 weapons consume 1 Iron Ore/Iron/Steel/Rough Oridecon - else - material = materials [2]; // Armors consume 1 Steel - if (pc_search_inventory(sd,material) < 0) { - clif_skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0); - return; - } + if ( target_sd->inventory_data[idx]->type == IT_WEAPON ) + material = materials [ target_sd->inventory_data[idx]->wlv - 1 ]; // Lv1/2/3/4 weapons consume 1 Iron Ore/Iron/Steel/Rough Oridecon + else + material = materials [2]; // Armors consume 1 Steel + if ( pc_search_inventory(sd,material) < 0 ) { + clif_skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0); + return; + } - clif_skill_nodamage(&sd->bl,&target_sd->bl,sd->menuskill_id,1,1); + clif_skill_nodamage(&sd->bl,&target_sd->bl,sd->menuskill_id,1,1); - item->attribute = 0;/* clear broken state */ + item->attribute = 0;/* clear broken state */ - clif_equiplist(target_sd); + clif_equiplist(target_sd); - pc_delitem(sd,pc_search_inventory(sd,material),1,0,0,LOG_TYPE_CONSUME); + pc_delitem(sd,pc_search_inventory(sd,material),1,0,0,LOG_TYPE_CONSUME); - clif_item_repaireffect(sd,idx,0); + clif_item_repaireffect(sd,idx,0); - if (sd != target_sd) - clif_item_repaireffect(target_sd,idx,0); + if( sd != target_sd ) + clif_item_repaireffect(target_sd,idx,0); } /*========================================== * Item Appraisal *------------------------------------------*/ -void skill_identify(struct map_session_data *sd, int idx) +void skill_identify (struct map_session_data *sd, int idx) { - int flag=1; + int flag=1; - nullpo_retv(sd); + nullpo_retv(sd); - if (idx >= 0 && idx < MAX_INVENTORY) { - if (sd->status.inventory[idx].nameid > 0 && sd->status.inventory[idx].identify == 0) { - flag=0; - sd->status.inventory[idx].identify=1; - } - } - clif_item_identified(sd,idx,flag); + if(idx >= 0 && idx < MAX_INVENTORY) { + if(sd->status.inventory[idx].nameid > 0 && sd->status.inventory[idx].identify == 0 ){ + flag=0; + sd->status.inventory[idx].identify=1; + } + } + clif_item_identified(sd,idx,flag); } /*========================================== * Weapon Refine [Celest] *------------------------------------------*/ -void skill_weaponrefine(struct map_session_data *sd, int idx) +void skill_weaponrefine (struct map_session_data *sd, int idx) { - nullpo_retv(sd); - - if (idx >= 0 && idx < MAX_INVENTORY) { - int i = 0, ep = 0, per; - int material[5] = { 0, 1010, 1011, 984, 984 }; - struct item *item; - struct item_data *ditem = sd->inventory_data[idx]; - item = &sd->status.inventory[idx]; - - if (item->nameid > 0 && ditem->type == IT_WEAPON) { - if (item->refine >= sd->menuskill_val - || item->refine >= 10 // if it's no longer refineable - || ditem->flag.no_refine // if the item isn't refinable - || (i = pc_search_inventory(sd, material [ditem->wlv])) < 0) { - clif_skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0); - return; - } + nullpo_retv(sd); + + if (idx >= 0 && idx < MAX_INVENTORY) + { + int i = 0, ep = 0, per; + int material[5] = { 0, 1010, 1011, 984, 984 }; + struct item *item; + struct item_data *ditem = sd->inventory_data[idx]; + item = &sd->status.inventory[idx]; + + if(item->nameid > 0 && ditem->type == IT_WEAPON) + { + if( item->refine >= sd->menuskill_val + || item->refine >= 10 // if it's no longer refineable + || ditem->flag.no_refine // if the item isn't refinable + || (i = pc_search_inventory(sd, material [ditem->wlv])) < 0 ) + { + clif_skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0); + return; + } - per = status_get_refine_chance(ditem->wlv, (int)item->refine); - per += (((signed int)sd->status.job_level)-50)/2; //Updated per the new kro descriptions. [Skotlex] - - pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); - if (per > rnd() % 100) { - log_pick_pc(sd, LOG_TYPE_OTHER, -1, item); - item->refine++; - log_pick_pc(sd, LOG_TYPE_OTHER, 1, item); - if (item->equip) { - ep = item->equip; - pc_unequipitem(sd,idx,3); - } - clif_refine(sd->fd,0,idx,item->refine); - clif_delitem(sd,idx,1,3); - clif_additem(sd,idx,1,0); - if (ep) - pc_equipitem(sd,idx,ep); - clif_misceffect(&sd->bl,3); - if (item->refine == 10 && - item->card[0] == CARD0_FORGE && - (int)MakeDWord(item->card[2],item->card[3]) == sd->status.char_id) { - // Fame point system [DracoRPG] - switch (ditem->wlv) { - case 1: - pc_addfame(sd,1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point - break; - case 2: - pc_addfame(sd,25); // Success to refine to +10 a lv2 weapon you forged = +25 fame point - break; - case 3: - pc_addfame(sd,1000); // Success to refine to +10 a lv3 weapon you forged = +1000 fame point - break; - } - } - } else { - item->refine = 0; - if (item->equip) - pc_unequipitem(sd,idx,3); - clif_refine(sd->fd,1,idx,item->refine); - pc_delitem(sd,idx,1,0,2, LOG_TYPE_OTHER); - clif_misceffect(&sd->bl,2); - clif_emotion(&sd->bl, E_OMG); - } - } - } + per = status_get_refine_chance(ditem->wlv, (int)item->refine); + per += (((signed int)sd->status.job_level)-50)/2; //Updated per the new kro descriptions. [Skotlex] + + pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); + if (per > rnd() % 100) { + log_pick_pc(sd, LOG_TYPE_OTHER, -1, item); + item->refine++; + log_pick_pc(sd, LOG_TYPE_OTHER, 1, item); + if(item->equip) { + ep = item->equip; + pc_unequipitem(sd,idx,3); + } + clif_refine(sd->fd,0,idx,item->refine); + clif_delitem(sd,idx,1,3); + clif_additem(sd,idx,1,0); + if (ep) + pc_equipitem(sd,idx,ep); + clif_misceffect(&sd->bl,3); + if(item->refine == 10 && + item->card[0] == CARD0_FORGE && + (int)MakeDWord(item->card[2],item->card[3]) == sd->status.char_id) + { // Fame point system [DracoRPG] + switch(ditem->wlv){ + case 1: + pc_addfame(sd,1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point + break; + case 2: + pc_addfame(sd,25); // Success to refine to +10 a lv2 weapon you forged = +25 fame point + break; + case 3: + pc_addfame(sd,1000); // Success to refine to +10 a lv3 weapon you forged = +1000 fame point + break; + } + } + } else { + item->refine = 0; + if(item->equip) + pc_unequipitem(sd,idx,3); + clif_refine(sd->fd,1,idx,item->refine); + pc_delitem(sd,idx,1,0,2, LOG_TYPE_OTHER); + clif_misceffect(&sd->bl,2); + clif_emotion(&sd->bl, E_OMG); + } + } + } } /*========================================== * *------------------------------------------*/ -int skill_autospell(struct map_session_data *sd, int skillid) +int skill_autospell (struct map_session_data *sd, int skillid) { - int skilllv; - int maxlv=1,lv; - - nullpo_ret(sd); - - skilllv = sd->menuskill_val; - lv=pc_checkskill(sd,skillid); - - if (skilllv <= 0 || !lv) return 0; // Player must learn the skill before doing auto-spell [Lance] - - if (skillid==MG_NAPALMBEAT) maxlv=3; - else if (skillid==MG_COLDBOLT || skillid==MG_FIREBOLT || skillid==MG_LIGHTNINGBOLT) { - if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SAGE) - maxlv =10; //Soul Linker bonus. [Skotlex] - else if (skilllv==2) maxlv=1; - else if (skilllv==3) maxlv=2; - else if (skilllv>=4) maxlv=3; - } else if (skillid==MG_SOULSTRIKE) { - if (skilllv==5) maxlv=1; - else if (skilllv==6) maxlv=2; - else if (skilllv>=7) maxlv=3; - } else if (skillid==MG_FIREBALL) { - if (skilllv==8) maxlv=1; - else if (skilllv>=9) maxlv=2; - } else if (skillid==MG_FROSTDIVER) maxlv=1; - else return 0; - - if (maxlv > lv) - maxlv = lv; - - sc_start4(&sd->bl,SC_AUTOSPELL,100,skilllv,skillid,maxlv,0, - skill_get_time(SA_AUTOSPELL,skilllv)); - return 0; + int skilllv; + int maxlv=1,lv; + + nullpo_ret(sd); + + skilllv = sd->menuskill_val; + lv=pc_checkskill(sd,skillid); + + if(skilllv <= 0 || !lv) return 0; // Player must learn the skill before doing auto-spell [Lance] + + if(skillid==MG_NAPALMBEAT) maxlv=3; + else if(skillid==MG_COLDBOLT || skillid==MG_FIREBOLT || skillid==MG_LIGHTNINGBOLT){ + if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SAGE) + maxlv =10; //Soul Linker bonus. [Skotlex] + else if(skilllv==2) maxlv=1; + else if(skilllv==3) maxlv=2; + else if(skilllv>=4) maxlv=3; + } + else if(skillid==MG_SOULSTRIKE){ + if(skilllv==5) maxlv=1; + else if(skilllv==6) maxlv=2; + else if(skilllv>=7) maxlv=3; + } + else if(skillid==MG_FIREBALL){ + if(skilllv==8) maxlv=1; + else if(skilllv>=9) maxlv=2; + } + else if(skillid==MG_FROSTDIVER) maxlv=1; + else return 0; + + if(maxlv > lv) + maxlv = lv; + + sc_start4(&sd->bl,SC_AUTOSPELL,100,skilllv,skillid,maxlv,0, + skill_get_time(SA_AUTOSPELL,skilllv)); + return 0; } /*========================================== * Sitting skills functions. *------------------------------------------*/ -static int skill_sit_count(struct block_list *bl, va_list ap) +static int skill_sit_count (struct block_list *bl, va_list ap) { - struct map_session_data *sd; - int type =va_arg(ap,int); - sd=(struct map_session_data *)bl; + struct map_session_data *sd; + int type =va_arg(ap,int); + sd=(struct map_session_data*)bl; - if (!pc_issit(sd)) - return 0; + if(!pc_issit(sd)) + return 0; - if (type&1 && pc_checkskill(sd,RG_GANGSTER) > 0) - return 1; + if(type&1 && pc_checkskill(sd,RG_GANGSTER) > 0) + return 1; - if (type&2 && (pc_checkskill(sd,TK_HPTIME) > 0 || pc_checkskill(sd,TK_SPTIME) > 0)) - return 1; + if(type&2 && (pc_checkskill(sd,TK_HPTIME) > 0 || pc_checkskill(sd,TK_SPTIME) > 0)) + return 1; - return 0; + return 0; } -static int skill_sit_in(struct block_list *bl, va_list ap) +static int skill_sit_in (struct block_list *bl, va_list ap) { - struct map_session_data *sd; - int type =va_arg(ap,int); + struct map_session_data *sd; + int type =va_arg(ap,int); - sd=(struct map_session_data *)bl; + sd=(struct map_session_data*)bl; - if (!pc_issit(sd)) - return 0; + if(!pc_issit(sd)) + return 0; - if (type&1 && pc_checkskill(sd,RG_GANGSTER) > 0) - sd->state.gangsterparadise=1; + if(type&1 && pc_checkskill(sd,RG_GANGSTER) > 0) + sd->state.gangsterparadise=1; - if (type&2 && (pc_checkskill(sd,TK_HPTIME) > 0 || pc_checkskill(sd,TK_SPTIME) > 0)) { - sd->state.rest=1; - status_calc_regen(bl, &sd->battle_status, &sd->regen); - status_calc_regen_rate(bl, &sd->regen, &sd->sc); - } + if(type&2 && (pc_checkskill(sd,TK_HPTIME) > 0 || pc_checkskill(sd,TK_SPTIME) > 0 )) + { + sd->state.rest=1; + status_calc_regen(bl, &sd->battle_status, &sd->regen); + status_calc_regen_rate(bl, &sd->regen, &sd->sc); + } - return 0; + return 0; } -static int skill_sit_out(struct block_list *bl, va_list ap) +static int skill_sit_out (struct block_list *bl, va_list ap) { - struct map_session_data *sd; - int type =va_arg(ap,int); - sd=(struct map_session_data *)bl; - if (sd->state.gangsterparadise && type&1) - sd->state.gangsterparadise=0; - if (sd->state.rest && type&2) { - sd->state.rest=0; - status_calc_regen(bl, &sd->battle_status, &sd->regen); - status_calc_regen_rate(bl, &sd->regen, &sd->sc); - } - return 0; + struct map_session_data *sd; + int type =va_arg(ap,int); + sd=(struct map_session_data*)bl; + if(sd->state.gangsterparadise && type&1) + sd->state.gangsterparadise=0; + if(sd->state.rest && type&2) { + sd->state.rest=0; + status_calc_regen(bl, &sd->battle_status, &sd->regen); + status_calc_regen_rate(bl, &sd->regen, &sd->sc); + } + return 0; } -int skill_sit(struct map_session_data *sd, int type) +int skill_sit (struct map_session_data *sd, int type) { - int flag = 0; - int range = 0, lv; - nullpo_ret(sd); - - - if ((lv = pc_checkskill(sd,RG_GANGSTER)) > 0) { - flag|=1; - range = skill_get_splash(RG_GANGSTER, lv); - } - if ((lv = pc_checkskill(sd,TK_HPTIME)) > 0) { - flag|=2; - range = skill_get_splash(TK_HPTIME, lv); - } else if ((lv = pc_checkskill(sd,TK_SPTIME)) > 0) { - flag|=2; - range = skill_get_splash(TK_SPTIME, lv); - } - - if (type) { - clif_status_load(&sd->bl,SI_SIT,1); - } else { - clif_status_load(&sd->bl,SI_SIT,0); - } - - if (!flag) return 0; - - if (type) { - if (map_foreachinrange(skill_sit_count,&sd->bl, range, BL_PC, flag) > 1) - map_foreachinrange(skill_sit_in,&sd->bl, range, BL_PC, flag); - } else { - if (map_foreachinrange(skill_sit_count,&sd->bl, range, BL_PC, flag) < 2) - map_foreachinrange(skill_sit_out,&sd->bl, range, BL_PC, flag); - } - return 0; + int flag = 0; + int range = 0, lv; + nullpo_ret(sd); + + + if((lv = pc_checkskill(sd,RG_GANGSTER)) > 0) { + flag|=1; + range = skill_get_splash(RG_GANGSTER, lv); + } + if((lv = pc_checkskill(sd,TK_HPTIME)) > 0) { + flag|=2; + range = skill_get_splash(TK_HPTIME, lv); + } + else if ((lv = pc_checkskill(sd,TK_SPTIME)) > 0) { + flag|=2; + range = skill_get_splash(TK_SPTIME, lv); + } + + if( type ) { + clif_status_load(&sd->bl,SI_SIT,1); + } else { + clif_status_load(&sd->bl,SI_SIT,0); + } + + if (!flag) return 0; + + if(type) { + if (map_foreachinrange(skill_sit_count,&sd->bl, range, BL_PC, flag) > 1) + map_foreachinrange(skill_sit_in,&sd->bl, range, BL_PC, flag); + } else { + if (map_foreachinrange(skill_sit_count,&sd->bl, range, BL_PC, flag) < 2) + map_foreachinrange(skill_sit_out,&sd->bl, range, BL_PC, flag); + } + return 0; } /*========================================== * *------------------------------------------*/ -int skill_frostjoke_scream(struct block_list *bl, va_list ap) +int skill_frostjoke_scream (struct block_list *bl, va_list ap) { - struct block_list *src; - int skillnum,skilllv; - unsigned int tick; - - nullpo_ret(bl); - nullpo_ret(src=va_arg(ap,struct block_list *)); - - skillnum=va_arg(ap,int); - skilllv=va_arg(ap,int); - if (skilllv <= 0) return 0; - tick=va_arg(ap,unsigned int); - - if (src == bl || status_isdead(bl)) - return 0; - if (bl->type == BL_PC) { - struct map_session_data *sd = (struct map_session_data *)bl; - if (sd && sd->sc.option&(OPTION_INVISIBLE|OPTION_MADOGEAR)) - return 0;//Frost Joke / Scream cannot target invisible or MADO Gear characters [Ind] - } - //It has been reported that Scream/Joke works the same regardless of woe-setting. [Skotlex] - if (battle_check_target(src,bl,BCT_ENEMY) > 0) - skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,ATK_DEF,tick); - else if (battle_check_target(src,bl,BCT_PARTY) > 0 && rnd()%100 < 10) - skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,ATK_DEF,tick); - - return 0; + struct block_list *src; + int skillnum,skilllv; + unsigned int tick; + + nullpo_ret(bl); + nullpo_ret(src=va_arg(ap,struct block_list*)); + + skillnum=va_arg(ap,int); + skilllv=va_arg(ap,int); + if(skilllv <= 0) return 0; + tick=va_arg(ap,unsigned int); + + if (src == bl || status_isdead(bl)) + return 0; + if (bl->type == BL_PC) { + struct map_session_data *sd = (struct map_session_data *)bl; + if ( sd && sd->sc.option&(OPTION_INVISIBLE|OPTION_MADOGEAR) ) + return 0;//Frost Joke / Scream cannot target invisible or MADO Gear characters [Ind] + } + //It has been reported that Scream/Joke works the same regardless of woe-setting. [Skotlex] + if(battle_check_target(src,bl,BCT_ENEMY) > 0) + skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,ATK_DEF,tick); + else if(battle_check_target(src,bl,BCT_PARTY) > 0 && rnd()%100 < 10) + skill_additional_effect(src,bl,skillnum,skilllv,BF_MISC,ATK_DEF,tick); + + return 0; } /*========================================== * *------------------------------------------*/ -static void skill_unitsetmapcell(struct skill_unit *src, int skill_num, int skill_lv, cell_t cell, bool flag) +static void skill_unitsetmapcell (struct skill_unit *src, int skill_num, int skill_lv, cell_t cell, bool flag) { - int range = skill_get_unit_range(skill_num,skill_lv); - int x,y; + int range = skill_get_unit_range(skill_num,skill_lv); + int x,y; - for (y = src->bl.y - range; y <= src->bl.y + range; ++y) - for (x = src->bl.x - range; x <= src->bl.x + range; ++x) - map_setcell(src->bl.m, x, y, cell, flag); + for( y = src->bl.y - range; y <= src->bl.y + range; ++y ) + for( x = src->bl.x - range; x <= src->bl.x + range; ++x ) + map_setcell(src->bl.m, x, y, cell, flag); } /*========================================== * *------------------------------------------*/ -int skill_attack_area(struct block_list *bl, va_list ap) +int skill_attack_area (struct block_list *bl, va_list ap) { - struct block_list *src,*dsrc; - int atk_type,skillid,skilllv,flag,type; - unsigned int tick; - - if (status_isdead(bl)) - return 0; - - atk_type = va_arg(ap,int); - src=va_arg(ap,struct block_list *); - dsrc=va_arg(ap,struct block_list *); - skillid=va_arg(ap,int); - skilllv=va_arg(ap,int); - tick=va_arg(ap,unsigned int); - flag=va_arg(ap,int); - type=va_arg(ap,int); - - - if (skill_area_temp[1] == bl->id) //This is the target of the skill, do a full attack and skip target checks. - return skill_attack(atk_type,src,dsrc,bl,skillid,skilllv,tick,flag); - - if (battle_check_target(dsrc,bl,type) <= 0 || - !status_check_skilluse(NULL, bl, skillid, 2)) - return 0; - - - switch (skillid) { - case WZ_FROSTNOVA: //Skills that don't require the animation to be removed - case NPC_ACIDBREATH: - case NPC_DARKNESSBREATH: - case NPC_FIREBREATH: - case NPC_ICEBREATH: - case NPC_THUNDERBREATH: - return skill_attack(atk_type,src,dsrc,bl,skillid,skilllv,tick,flag); - default: - //Area-splash, disable skill animation. - return skill_attack(atk_type,src,dsrc,bl,skillid,skilllv,tick,flag|SD_ANIMATION); - } + struct block_list *src,*dsrc; + int atk_type,skillid,skilllv,flag,type; + unsigned int tick; + + if(status_isdead(bl)) + return 0; + + atk_type = va_arg(ap,int); + src=va_arg(ap,struct block_list*); + dsrc=va_arg(ap,struct block_list*); + skillid=va_arg(ap,int); + skilllv=va_arg(ap,int); + tick=va_arg(ap,unsigned int); + flag=va_arg(ap,int); + type=va_arg(ap,int); + + + if (skill_area_temp[1] == bl->id) //This is the target of the skill, do a full attack and skip target checks. + return skill_attack(atk_type,src,dsrc,bl,skillid,skilllv,tick,flag); + + if(battle_check_target(dsrc,bl,type) <= 0 || + !status_check_skilluse(NULL, bl, skillid, 2)) + return 0; + + + switch (skillid) { + case WZ_FROSTNOVA: //Skills that don't require the animation to be removed + case NPC_ACIDBREATH: + case NPC_DARKNESSBREATH: + case NPC_FIREBREATH: + case NPC_ICEBREATH: + case NPC_THUNDERBREATH: + return skill_attack(atk_type,src,dsrc,bl,skillid,skilllv,tick,flag); + default: + //Area-splash, disable skill animation. + return skill_attack(atk_type,src,dsrc,bl,skillid,skilllv,tick,flag|SD_ANIMATION); + } } /*========================================== * *------------------------------------------*/ -int skill_clear_group(struct block_list *bl, int flag) +int skill_clear_group (struct block_list *bl, int flag) { - struct unit_data *ud = unit_bl2ud(bl); - struct skill_unit_group *group[MAX_SKILLUNITGROUP]; - int i, count=0; - - nullpo_ret(bl); - if (!ud) return 0; - - //All groups to be deleted are first stored on an array since the array elements shift around when you delete them. [Skotlex] - for (i=0; i<MAX_SKILLUNITGROUP && ud->skillunit[i]; i++) { - switch (ud->skillunit[i]->skill_id) { - case SA_DELUGE: - case SA_VOLCANO: - case SA_VIOLENTGALE: - case SA_LANDPROTECTOR: - case NJ_SUITON: - case NJ_KAENSIN: - if (flag&1) - group[count++]= ud->skillunit[i]; - break; - case SO_WARMER: - if (flag&8) - group[count++]= ud->skillunit[i]; - break; - case SC_BLOODYLUST: - if (flag & 32) - group[count++] = ud->skillunit[i]; - break; - default: - if (flag&2 && skill_get_inf2(ud->skillunit[i]->skill_id)&INF2_TRAP) - group[count++]= ud->skillunit[i]; - break; - } - - } - for (i=0; i<count; i++) - skill_delunitgroup(group[i]); - return count; + struct unit_data *ud = unit_bl2ud(bl); + struct skill_unit_group *group[MAX_SKILLUNITGROUP]; + int i, count=0; + + nullpo_ret(bl); + if (!ud) return 0; + + //All groups to be deleted are first stored on an array since the array elements shift around when you delete them. [Skotlex] + for (i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) + { + switch (ud->skillunit[i]->skill_id) { + case SA_DELUGE: + case SA_VOLCANO: + case SA_VIOLENTGALE: + case SA_LANDPROTECTOR: + case NJ_SUITON: + case NJ_KAENSIN: + if (flag&1) + group[count++]= ud->skillunit[i]; + break; + case SO_WARMER: + if( flag&8 ) + group[count++]= ud->skillunit[i]; + break; + case SC_BLOODYLUST: + if (flag & 32) + group[count++] = ud->skillunit[i]; + break; + default: + if (flag&2 && skill_get_inf2(ud->skillunit[i]->skill_id)&INF2_TRAP) + group[count++]= ud->skillunit[i]; + break; + } + + } + for (i=0;i<count;i++) + skill_delunitgroup(group[i]); + return count; } /*========================================== * Returns the first element field found [Skotlex] *------------------------------------------*/ -struct skill_unit_group *skill_locate_element_field(struct block_list *bl) { - struct unit_data *ud = unit_bl2ud(bl); - int i; - nullpo_ret(bl); - if (!ud) return NULL; - - for (i=0; i<MAX_SKILLUNITGROUP && ud->skillunit[i]; i++) { - switch (ud->skillunit[i]->skill_id) { - case SA_DELUGE: - case SA_VOLCANO: - case SA_VIOLENTGALE: - case SA_LANDPROTECTOR: - case NJ_SUITON: - case SO_WARMER: - case SC_BLOODYLUST: - return ud->skillunit[i]; - } - } - return NULL; +struct skill_unit_group *skill_locate_element_field(struct block_list *bl) +{ + struct unit_data *ud = unit_bl2ud(bl); + int i; + nullpo_ret(bl); + if (!ud) return NULL; + + for (i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) { + switch (ud->skillunit[i]->skill_id) { + case SA_DELUGE: + case SA_VOLCANO: + case SA_VIOLENTGALE: + case SA_LANDPROTECTOR: + case NJ_SUITON: + case SO_WARMER: + case SC_BLOODYLUST: + return ud->skillunit[i]; + } + } + return NULL; } // for graffiti cleaner [Valaris] -int skill_graffitiremover(struct block_list *bl, va_list ap) +int skill_graffitiremover (struct block_list *bl, va_list ap) { - struct skill_unit *unit=NULL; + struct skill_unit *unit=NULL; - nullpo_ret(bl); - nullpo_ret(ap); + nullpo_ret(bl); + nullpo_ret(ap); - if (bl->type!=BL_SKILL || (unit=(struct skill_unit *)bl) == NULL) - return 0; + if(bl->type!=BL_SKILL || (unit=(struct skill_unit *)bl) == NULL) + return 0; - if ((unit->group) && (unit->group->unit_id == UNT_GRAFFITI)) - skill_delunit(unit); + if((unit->group) && (unit->group->unit_id == UNT_GRAFFITI)) + skill_delunit(unit); - return 0; + return 0; } -int skill_greed(struct block_list *bl, va_list ap) +int skill_greed (struct block_list *bl, va_list ap) { - struct block_list *src; - struct map_session_data *sd=NULL; - struct flooritem_data *fitem=NULL; + struct block_list *src; + struct map_session_data *sd=NULL; + struct flooritem_data *fitem=NULL; - nullpo_ret(bl); - nullpo_ret(src = va_arg(ap, struct block_list *)); + nullpo_ret(bl); + nullpo_ret(src = va_arg(ap, struct block_list *)); - if (src->type == BL_PC && (sd=(struct map_session_data *)src) && bl->type==BL_ITEM && (fitem=(struct flooritem_data *)bl)) - pc_takeitem(sd, fitem); + if(src->type == BL_PC && (sd=(struct map_session_data *)src) && bl->type==BL_ITEM && (fitem=(struct flooritem_data *)bl)) + pc_takeitem(sd, fitem); - return 0; + return 0; } //For Ranger's Detonator [Jobbie/3CeAM] int skill_detonator(struct block_list *bl, va_list ap) { - struct skill_unit *unit=NULL; - struct block_list *src; - int unit_id; - - nullpo_ret(bl); - nullpo_ret(ap); - src = va_arg(ap,struct block_list *); - - if (bl->type != BL_SKILL || (unit = (struct skill_unit *)bl) == NULL || !unit->group) - return 0; - if (unit->group->src_id != src->id) - return 0; - - unit_id = unit->group->unit_id; - switch (unit_id) { - //List of Hunter and Ranger Traps that can be detonate. - case UNT_BLASTMINE: - case UNT_SANDMAN: - case UNT_CLAYMORETRAP: - case UNT_TALKIEBOX: - case UNT_CLUSTERBOMB: - case UNT_FIRINGTRAP: - case UNT_ICEBOUNDTRAP: - if (unit_id == UNT_TALKIEBOX) { - clif_talkiebox(bl,unit->group->valstr); - unit->group->val2 = -1; - } else - map_foreachinrange(skill_trap_splash,bl,skill_get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag,bl,unit->group->tick); - - clif_changetraplook(bl,unit_id == UNT_FIRINGTRAP ? UNT_DUMMYSKILL : UNT_USED_TRAPS); - unit->group->unit_id = UNT_USED_TRAPS; - unit->group->limit = DIFF_TICK(gettick(),unit->group->tick) + - (unit_id == UNT_TALKIEBOX ? 5000 : (unit_id == UNT_CLUSTERBOMB || unit_id == UNT_ICEBOUNDTRAP? 2500 : 1500)); - break; - } - return 0; + struct skill_unit *unit=NULL; + struct block_list *src; + int unit_id; + + nullpo_ret(bl); + nullpo_ret(ap); + src = va_arg(ap,struct block_list *); + + if( bl->type != BL_SKILL || (unit = (struct skill_unit *)bl) == NULL || !unit->group ) + return 0; + if( unit->group->src_id != src->id ) + return 0; + + unit_id = unit->group->unit_id; + switch( unit_id ) + { //List of Hunter and Ranger Traps that can be detonate. + case UNT_BLASTMINE: + case UNT_SANDMAN: + case UNT_CLAYMORETRAP: + case UNT_TALKIEBOX: + case UNT_CLUSTERBOMB: + case UNT_FIRINGTRAP: + case UNT_ICEBOUNDTRAP: + if( unit_id == UNT_TALKIEBOX ) + { + clif_talkiebox(bl,unit->group->valstr); + unit->group->val2 = -1; + } + else + map_foreachinrange(skill_trap_splash,bl,skill_get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag,bl,unit->group->tick); + + clif_changetraplook(bl,unit_id == UNT_FIRINGTRAP ? UNT_DUMMYSKILL : UNT_USED_TRAPS); + unit->group->unit_id = UNT_USED_TRAPS; + unit->group->limit = DIFF_TICK(gettick(),unit->group->tick) + + (unit_id == UNT_TALKIEBOX ? 5000 : (unit_id == UNT_CLUSTERBOMB || unit_id == UNT_ICEBOUNDTRAP? 2500 : 1500) ); + break; + } + return 0; } /*========================================== @@ -14698,103 +14547,104 @@ int skill_detonator(struct block_list *bl, va_list ap) *------------------------------------------*/ static int skill_cell_overlap(struct block_list *bl, va_list ap) { - int skillid; - int *alive; - struct skill_unit *unit; - - skillid = va_arg(ap,int); - alive = va_arg(ap,int *); - unit = (struct skill_unit *)bl; - - if (unit == NULL || unit->group == NULL || (*alive) == 0) - return 0; - - switch (skillid) { - case SA_LANDPROTECTOR: - if (unit->group->skill_id == SA_LANDPROTECTOR) { //Check for offensive Land Protector to delete both. [Skotlex] - (*alive) = 0; - skill_delunit(unit); - return 1; - } - if (!(skill_get_inf2(unit->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP))) { //It deletes everything except songs/dances and traps - skill_delunit(unit); - return 1; - } - break; - case HW_GANBANTEIN: - case LG_EARTHDRIVE: - if (!(unit->group->state.song_dance&0x1)) { // Don't touch song/dance. - skill_delunit(unit); - return 1; - } - break; - case SA_VOLCANO: - case SA_DELUGE: - case SA_VIOLENTGALE: - // The official implementation makes them fail to appear when casted on top of ANYTHING - // but I wonder if they didn't actually meant to fail when casted on top of each other? - // hence, I leave the alternate implementation here, commented. [Skotlex] - if (unit->range <= 0) { - (*alive) = 0; - return 1; - } - /* - switch (unit->group->skill_id) - { //These cannot override each other. - case SA_VOLCANO: - case SA_DELUGE: - case SA_VIOLENTGALE: - (*alive) = 0; - return 1; - } - */ - break; - case PF_FOGWALL: - switch (unit->group->skill_id) { - case SA_VOLCANO: //Can't be placed on top of these - case SA_VIOLENTGALE: - (*alive) = 0; - return 1; - case SA_DELUGE: - case NJ_SUITON: - //Cheap 'hack' to notify the calling function that duration should be doubled [Skotlex] - (*alive) = 2; - break; - } - break; - case HP_BASILICA: - if (unit->group->skill_id == HP_BASILICA) { - //Basilica can't be placed on top of itself to avoid map-cell stacking problems. [Skotlex] - (*alive) = 0; - return 1; - } - break; - case GN_CRAZYWEED_ATK: - switch (unit->group->unit_id) { //TODO: look for other ground skills that are affected. - case UNT_WALLOFTHORN: - case UNT_THORNS_TRAP: - case UNT_BLOODYLUST: - case UNT_CHAOSPANIC: - case UNT_MAELSTROM: - case UNT_FIREPILLAR_ACTIVE: - case UNT_LANDPROTECTOR: - case UNT_VOLCANO: - case UNT_DELUGE: - case UNT_VIOLENTGALE: - case UNT_SAFETYWALL: - case UNT_PNEUMA: - skill_delunit(unit); - return 1; - } - break; - } + int skillid; + int *alive; + struct skill_unit *unit; + + skillid = va_arg(ap,int); + alive = va_arg(ap,int *); + unit = (struct skill_unit *)bl; + + if (unit == NULL || unit->group == NULL || (*alive) == 0) + return 0; + + switch (skillid) { + case SA_LANDPROTECTOR: + if( unit->group->skill_id == SA_LANDPROTECTOR ) {//Check for offensive Land Protector to delete both. [Skotlex] + (*alive) = 0; + skill_delunit(unit); + return 1; + } + if( !(skill_get_inf2(unit->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) ) { //It deletes everything except songs/dances and traps + skill_delunit(unit); + return 1; + } + break; + case HW_GANBANTEIN: + case LG_EARTHDRIVE: + if( !(unit->group->state.song_dance&0x1) ) {// Don't touch song/dance. + skill_delunit(unit); + return 1; + } + break; + case SA_VOLCANO: + case SA_DELUGE: + case SA_VIOLENTGALE: +// The official implementation makes them fail to appear when casted on top of ANYTHING +// but I wonder if they didn't actually meant to fail when casted on top of each other? +// hence, I leave the alternate implementation here, commented. [Skotlex] + if (unit->range <= 0) + { + (*alive) = 0; + return 1; + } +/* + switch (unit->group->skill_id) + { //These cannot override each other. + case SA_VOLCANO: + case SA_DELUGE: + case SA_VIOLENTGALE: + (*alive) = 0; + return 1; + } +*/ + break; + case PF_FOGWALL: + switch(unit->group->skill_id) { + case SA_VOLCANO: //Can't be placed on top of these + case SA_VIOLENTGALE: + (*alive) = 0; + return 1; + case SA_DELUGE: + case NJ_SUITON: + //Cheap 'hack' to notify the calling function that duration should be doubled [Skotlex] + (*alive) = 2; + break; + } + break; + case HP_BASILICA: + if (unit->group->skill_id == HP_BASILICA) + { //Basilica can't be placed on top of itself to avoid map-cell stacking problems. [Skotlex] + (*alive) = 0; + return 1; + } + break; + case GN_CRAZYWEED_ATK: + switch(unit->group->unit_id){ //TODO: look for other ground skills that are affected. + case UNT_WALLOFTHORN: + case UNT_THORNS_TRAP: + case UNT_BLOODYLUST: + case UNT_CHAOSPANIC: + case UNT_MAELSTROM: + case UNT_FIREPILLAR_ACTIVE: + case UNT_LANDPROTECTOR: + case UNT_VOLCANO: + case UNT_DELUGE: + case UNT_VIOLENTGALE: + case UNT_SAFETYWALL: + case UNT_PNEUMA: + skill_delunit(unit); + return 1; + } + break; + } - if (unit->group->skill_id == SA_LANDPROTECTOR && !(skill_get_inf2(skillid)&(INF2_SONG_DANCE|INF2_TRAP))) { //It deletes everything except songs/dances/traps - (*alive) = 0; - return 1; - } + if (unit->group->skill_id == SA_LANDPROTECTOR && !(skill_get_inf2(skillid)&(INF2_SONG_DANCE|INF2_TRAP))) { //It deletes everything except songs/dances/traps + (*alive) = 0; + return 1; + } - return 0; + return 0; } /*========================================== @@ -14802,315 +14652,325 @@ static int skill_cell_overlap(struct block_list *bl, va_list ap) *------------------------------------------*/ int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap) { - struct mob_data *md; - struct unit_data *ud = unit_bl2ud(bl); - struct block_list *from_bl; - struct block_list *to_bl; - md = (struct mob_data *)bl; - from_bl = va_arg(ap,struct block_list *); - to_bl = va_arg(ap,struct block_list *); - - if (ud && ud->target == from_bl->id) - ud->target = to_bl->id; - - if (md->bl.type == BL_MOB && md->target_id == from_bl->id) - md->target_id = to_bl->id; - return 0; + struct mob_data* md; + struct unit_data*ud = unit_bl2ud(bl); + struct block_list *from_bl; + struct block_list *to_bl; + md = (struct mob_data*)bl; + from_bl = va_arg(ap,struct block_list *); + to_bl = va_arg(ap,struct block_list *); + + if(ud && ud->target == from_bl->id) + ud->target = to_bl->id; + + if(md->bl.type == BL_MOB && md->target_id == from_bl->id) + md->target_id = to_bl->id; + return 0; } /*========================================== * *------------------------------------------*/ -static int skill_trap_splash(struct block_list *bl, va_list ap) +static int skill_trap_splash (struct block_list *bl, va_list ap) { - struct block_list *src; - int tick; - struct skill_unit *unit; - struct skill_unit_group *sg; - struct block_list *ss; - src = va_arg(ap,struct block_list *); - unit = (struct skill_unit *)src; - tick = va_arg(ap,int); - - if (!unit->alive || bl->prev == NULL) - return 0; - - nullpo_ret(sg = unit->group); - nullpo_ret(ss = map_id2bl(sg->src_id)); - - if (battle_check_target(src,bl,sg->target_flag) <= 0) - return 0; - - switch (sg->unit_id) { - case UNT_SHOCKWAVE: - case UNT_SANDMAN: - case UNT_FLASHER: - skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,ATK_DEF,tick); - break; - case UNT_GROUNDDRIFT_WIND: - if (skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_STUN,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); - break; - case UNT_GROUNDDRIFT_DARK: - if (skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_BLIND,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); - break; - case UNT_GROUNDDRIFT_POISON: - if (skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_POISON,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); - break; - case UNT_GROUNDDRIFT_WATER: - if (skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_FREEZE,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); - break; - case UNT_GROUNDDRIFT_FIRE: - if (skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - skill_blown(src,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),-1,0); - break; - case UNT_ELECTRICSHOCKER: - clif_skill_damage(src,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,5); - break; - case UNT_FIRINGTRAP: - case UNT_ICEBOUNDTRAP: - case UNT_CLUSTERBOMB: - if (ss != bl) - skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1|SD_LEVEL); - break; - case UNT_MAGENTATRAP: - case UNT_COBALTTRAP: - case UNT_MAIZETRAP: - case UNT_VERDURETRAP: - if (bl->type != BL_PC && !is_boss(bl)) - sc_start2(bl,SC_ELEMENTALCHANGE,100,sg->skill_lv,skill_get_ele(sg->skill_id,sg->skill_lv),skill_get_time2(sg->skill_id,sg->skill_lv)); - break; - case UNT_REVERBERATION: - skill_addtimerskill(ss,tick+50,bl->id,0,0,WM_REVERBERATION_MELEE,sg->skill_lv,BF_WEAPON,0); // for proper skill delay animation when use with Dominion Impulse - skill_addtimerskill(ss,tick+250,bl->id,0,0,WM_REVERBERATION_MAGIC,sg->skill_lv,BF_MAGIC,0); - break; - default: - skill_attack(skill_get_type(sg->skill_id),ss,src,bl,sg->skill_id,sg->skill_lv,tick,0); - break; - } - return 1; + struct block_list *src; + int tick; + struct skill_unit *unit; + struct skill_unit_group *sg; + struct block_list *ss; + src = va_arg(ap,struct block_list *); + unit = (struct skill_unit *)src; + tick = va_arg(ap,int); + + if( !unit->alive || bl->prev == NULL ) + return 0; + + nullpo_ret(sg = unit->group); + nullpo_ret(ss = map_id2bl(sg->src_id)); + + if(battle_check_target(src,bl,sg->target_flag) <= 0) + return 0; + + switch(sg->unit_id){ + case UNT_SHOCKWAVE: + case UNT_SANDMAN: + case UNT_FLASHER: + skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,ATK_DEF,tick); + break; + case UNT_GROUNDDRIFT_WIND: + if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) + sc_start(bl,SC_STUN,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); + break; + case UNT_GROUNDDRIFT_DARK: + if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) + sc_start(bl,SC_BLIND,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); + break; + case UNT_GROUNDDRIFT_POISON: + if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) + sc_start(bl,SC_POISON,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); + break; + case UNT_GROUNDDRIFT_WATER: + if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) + sc_start(bl,SC_FREEZE,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); + break; + case UNT_GROUNDDRIFT_FIRE: + if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) + skill_blown(src,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),-1,0); + break; + case UNT_ELECTRICSHOCKER: + clif_skill_damage(src,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,5); + break; + case UNT_FIRINGTRAP: + case UNT_ICEBOUNDTRAP: + case UNT_CLUSTERBOMB: + if( ss != bl ) + skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1|SD_LEVEL); + break; + case UNT_MAGENTATRAP: + case UNT_COBALTTRAP: + case UNT_MAIZETRAP: + case UNT_VERDURETRAP: + if( bl->type != BL_PC && !is_boss(bl) ) + sc_start2(bl,SC_ELEMENTALCHANGE,100,sg->skill_lv,skill_get_ele(sg->skill_id,sg->skill_lv),skill_get_time2(sg->skill_id,sg->skill_lv)); + break; + case UNT_REVERBERATION: + skill_addtimerskill(ss,tick+50,bl->id,0,0,WM_REVERBERATION_MELEE,sg->skill_lv,BF_WEAPON,0); // for proper skill delay animation when use with Dominion Impulse + skill_addtimerskill(ss,tick+250,bl->id,0,0,WM_REVERBERATION_MAGIC,sg->skill_lv,BF_MAGIC,0); + break; + default: + skill_attack(skill_get_type(sg->skill_id),ss,src,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + } + return 1; } /*========================================== * *------------------------------------------*/ -int skill_enchant_elemental_end(struct block_list *bl, int type) +int skill_enchant_elemental_end (struct block_list *bl, int type) { - struct status_change *sc; - const enum sc_type scs[] = { SC_ENCPOISON, SC_ASPERSIO, SC_FIREWEAPON, SC_WATERWEAPON, SC_WINDWEAPON, SC_EARTHWEAPON, SC_SHADOWWEAPON, SC_GHOSTWEAPON, SC_ENCHANTARMS, SC_EXEEDBREAK }; - int i; - nullpo_ret(bl); - nullpo_ret(sc= status_get_sc(bl)); + struct status_change *sc; + const enum sc_type scs[] = { SC_ENCPOISON, SC_ASPERSIO, SC_FIREWEAPON, SC_WATERWEAPON, SC_WINDWEAPON, SC_EARTHWEAPON, SC_SHADOWWEAPON, SC_GHOSTWEAPON, SC_ENCHANTARMS, SC_EXEEDBREAK }; + int i; + nullpo_ret(bl); + nullpo_ret(sc= status_get_sc(bl)); - if (!sc->count) return 0; + if (!sc->count) return 0; - for (i = 0; i < ARRAYLENGTH(scs); i++) - if (type != scs[i] && sc->data[scs[i]]) - status_change_end(bl, scs[i], INVALID_TIMER); + for (i = 0; i < ARRAYLENGTH(scs); i++) + if (type != scs[i] && sc->data[scs[i]]) + status_change_end(bl, scs[i], INVALID_TIMER); - return 0; + return 0; } bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce) { - static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1}; - static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1}; - bool wall = true; - - if ((bl->type == BL_PC && battle_config.pc_cloak_check_type&1) - || (bl->type != BL_PC && battle_config.monster_cloak_check_type&1)) { - //Check for walls. - int i; - ARR_FIND(0, 8, i, map_getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0); - if (i == 8) - wall = false; - } - - if (sce) { - if (!wall) { - if (sce->val1 < 3) //End cloaking. - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - else if (sce->val4&1) { - //Remove wall bonus - sce->val4&=~1; - status_calc_bl(bl,SCB_SPEED); - } - } else { - if (!(sce->val4&1)) { - //Add wall speed bonus - sce->val4|=1; - status_calc_bl(bl,SCB_SPEED); - } - } - } + static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1}; + static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1}; + bool wall = true; + + if( (bl->type == BL_PC && battle_config.pc_cloak_check_type&1) + || (bl->type != BL_PC && battle_config.monster_cloak_check_type&1) ) + { //Check for walls. + int i; + ARR_FIND( 0, 8, i, map_getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 ); + if( i == 8 ) + wall = false; + } + + if( sce ) + { + if( !wall ) + { + if( sce->val1 < 3 ) //End cloaking. + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + else + if( sce->val4&1 ) + { //Remove wall bonus + sce->val4&=~1; + status_calc_bl(bl,SCB_SPEED); + } + } + else + { + if( !(sce->val4&1) ) + { //Add wall speed bonus + sce->val4|=1; + status_calc_bl(bl,SCB_SPEED); + } + } + } - return wall; + return wall; } bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *sce) { - static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1}; - static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1}; - bool wall = true; - - if (bl->type == BL_PC) { - //Check for walls. - int i; - ARR_FIND(0, 8, i, map_getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0); - if (i == 8) - wall = false; - } - - if (sce) { - if (!wall) { - if (sce->val1 < 3) //End camouflage. - status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); - else if (sce->val3&1) { - //Remove wall bonus - sce->val3&=~1; - status_calc_bl(bl,SCB_SPEED); - } - } - } + static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1}; + static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1}; + bool wall = true; + + if( bl->type == BL_PC ) + { //Check for walls. + int i; + ARR_FIND( 0, 8, i, map_getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 ); + if( i == 8 ) + wall = false; + } + + if( sce ) + { + if( !wall ) + { + if( sce->val1 < 3 ) //End camouflage. + status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); + else + if( sce->val3&1 ) + { //Remove wall bonus + sce->val3&=~1; + status_calc_bl(bl,SCB_SPEED); + } + } + } - return wall; + return wall; } /*========================================== * *------------------------------------------*/ -struct skill_unit *skill_initunit(struct skill_unit_group *group, int idx, int x, int y, int val1, int val2) { - struct skill_unit *unit; - - nullpo_retr(NULL, group); - nullpo_retr(NULL, group->unit); // crash-protection against poor coding - nullpo_retr(NULL, unit=&group->unit[idx]); - - if (!unit->alive) - group->alive_count++; - - unit->bl.id=map_get_new_object_id(); - unit->bl.type=BL_SKILL; - unit->bl.m=group->map; - unit->bl.x=x; - unit->bl.y=y; - unit->group=group; - unit->alive=1; - unit->val1=val1; - unit->val2=val2; - - idb_put(skillunit_db, unit->bl.id, unit); - map_addiddb(&unit->bl); - map_addblock(&unit->bl); - - // perform oninit actions - switch (group->skill_id) { - case WZ_ICEWALL: - map_setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,5); - clif_changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,5,AREA); - skill_unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,true); - map[unit->bl.m].icewall_num++; - break; - case SA_LANDPROTECTOR: - skill_unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,true); - break; - case HP_BASILICA: - skill_unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,true); - break; - case SC_MAELSTROM: - skill_unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,true); - break; - default: - if (group->state.song_dance&0x1) //Check for dissonance. - skill_dance_overlap(unit, 1); - break; - } +struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2) +{ + struct skill_unit *unit; + + nullpo_retr(NULL, group); + nullpo_retr(NULL, group->unit); // crash-protection against poor coding + nullpo_retr(NULL, unit=&group->unit[idx]); + + if(!unit->alive) + group->alive_count++; + + unit->bl.id=map_get_new_object_id(); + unit->bl.type=BL_SKILL; + unit->bl.m=group->map; + unit->bl.x=x; + unit->bl.y=y; + unit->group=group; + unit->alive=1; + unit->val1=val1; + unit->val2=val2; + + idb_put(skillunit_db, unit->bl.id, unit); + map_addiddb(&unit->bl); + map_addblock(&unit->bl); + + // perform oninit actions + switch (group->skill_id) { + case WZ_ICEWALL: + map_setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,5); + clif_changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,5,AREA); + skill_unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,true); + map[unit->bl.m].icewall_num++; + break; + case SA_LANDPROTECTOR: + skill_unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,true); + break; + case HP_BASILICA: + skill_unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,true); + break; + case SC_MAELSTROM: + skill_unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,true); + break; + default: + if (group->state.song_dance&0x1) //Check for dissonance. + skill_dance_overlap(unit, 1); + break; + } - clif_skill_setunit(unit); + clif_skill_setunit(unit); - return unit; + return unit; } /*========================================== * *------------------------------------------*/ -int skill_delunit(struct skill_unit *unit) +int skill_delunit (struct skill_unit* unit) { - struct skill_unit_group *group; + struct skill_unit_group *group; - nullpo_ret(unit); - if (!unit->alive) - return 0; - unit->alive=0; + nullpo_ret(unit); + if( !unit->alive ) + return 0; + unit->alive=0; - nullpo_ret(group=unit->group); + nullpo_ret(group=unit->group); - if (group->state.song_dance&0x1) //Cancel dissonance effect. - skill_dance_overlap(unit, 0); + if( group->state.song_dance&0x1 ) //Cancel dissonance effect. + skill_dance_overlap(unit, 0); - // invoke onout event - if (!unit->range) - map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),4); + // invoke onout event + if( !unit->range ) + map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),4); - // perform ondelete actions - switch (group->skill_id) { - case HT_ANKLESNARE: { - struct block_list *target = map_id2bl(group->val2); - if (target) - status_change_end(target, SC_ANKLE, INVALID_TIMER); - } - break; - case WZ_ICEWALL: - map_setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,unit->val2); - clif_changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug - skill_unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false); - map[unit->bl.m].icewall_num--; - break; - case SA_LANDPROTECTOR: - skill_unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,false); - break; - case HP_BASILICA: - skill_unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,false); - break; - case RA_ELECTRICSHOCKER: { - struct block_list *target = map_id2bl(group->val2); - if (target) - status_change_end(target, SC_ELECTRICSHOCKER, INVALID_TIMER); - } - break; - case SC_MAELSTROM: - skill_unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,false); - break; - case SC_MANHOLE: // Note : Removing the unit don't remove the status (official info) - if (group->val2) { // Someone Traped - struct status_change *tsc = status_get_sc(map_id2bl(group->val2)); - if (tsc && tsc->data[SC__MANHOLE]) - tsc->data[SC__MANHOLE]->val4 = 0; // Remove the Unit ID - } - break; - } + // perform ondelete actions + switch (group->skill_id) { + case HT_ANKLESNARE: { + struct block_list* target = map_id2bl(group->val2); + if( target ) + status_change_end(target, SC_ANKLE, INVALID_TIMER); + } + break; + case WZ_ICEWALL: + map_setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,unit->val2); + clif_changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug + skill_unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false); + map[unit->bl.m].icewall_num--; + break; + case SA_LANDPROTECTOR: + skill_unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,false); + break; + case HP_BASILICA: + skill_unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,false); + break; + case RA_ELECTRICSHOCKER: { + struct block_list* target = map_id2bl(group->val2); + if( target ) + status_change_end(target, SC_ELECTRICSHOCKER, INVALID_TIMER); + } + break; + case SC_MAELSTROM: + skill_unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,false); + break; + case SC_MANHOLE: // Note : Removing the unit don't remove the status (official info) + if( group->val2 ) { // Someone Traped + struct status_change *tsc = status_get_sc( map_id2bl(group->val2)); + if( tsc && tsc->data[SC__MANHOLE] ) + tsc->data[SC__MANHOLE]->val4 = 0; // Remove the Unit ID + } + break; + } - clif_skill_delunit(unit); + clif_skill_delunit(unit); - unit->group=NULL; - map_delblock(&unit->bl); // don't free yet - map_deliddb(&unit->bl); - idb_remove(skillunit_db, unit->bl.id); - if (--group->alive_count==0) - skill_delunitgroup(group); + unit->group=NULL; + map_delblock(&unit->bl); // don't free yet + map_deliddb(&unit->bl); + idb_remove(skillunit_db, unit->bl.id); + if(--group->alive_count==0) + skill_delunitgroup(group); - return 0; + return 0; } /*========================================== * *------------------------------------------*/ -static DBMap *group_db = NULL;// int group_id -> struct skill_unit_group* +static DBMap* group_db = NULL;// int group_id -> struct skill_unit_group* /// Returns the target skill_unit_group or NULL if not found. -struct skill_unit_group *skill_id2group(int group_id) { - return (struct skill_unit_group *)idb_get(group_db, group_id); +struct skill_unit_group* skill_id2group(int group_id) +{ + return (struct skill_unit_group*)idb_get(group_db, group_id); } @@ -15120,286 +14980,298 @@ static int skill_unit_group_newid = MAX_SKILL_DB; /// Fatal error if nothing is available. static int skill_get_new_group_id(void) { - if (skill_unit_group_newid >= MAX_SKILL_DB && skill_id2group(skill_unit_group_newid) == NULL) - return skill_unit_group_newid++;// available - { - // find next id - int base_id = skill_unit_group_newid; - while (base_id != ++skill_unit_group_newid) { - if (skill_unit_group_newid < MAX_SKILL_DB) - skill_unit_group_newid = MAX_SKILL_DB; - if (skill_id2group(skill_unit_group_newid) == NULL) - return skill_unit_group_newid++;// available - } - // full loop, nothing available - ShowFatalError("skill_get_new_group_id: All ids are taken. Exiting..."); - exit(1); - } + if( skill_unit_group_newid >= MAX_SKILL_DB && skill_id2group(skill_unit_group_newid) == NULL ) + return skill_unit_group_newid++;// available + {// find next id + int base_id = skill_unit_group_newid; + while( base_id != ++skill_unit_group_newid ) + { + if( skill_unit_group_newid < MAX_SKILL_DB ) + skill_unit_group_newid = MAX_SKILL_DB; + if( skill_id2group(skill_unit_group_newid) == NULL ) + return skill_unit_group_newid++;// available + } + // full loop, nothing available + ShowFatalError("skill_get_new_group_id: All ids are taken. Exiting..."); + exit(1); + } } -struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count, short skillid, short skilllv, int unit_id, int limit, int interval) { - struct unit_data *ud = unit_bl2ud(src); - struct skill_unit_group *group; - int i; - - if (skillid <= 0 || skilllv <= 0) return 0; - - nullpo_retr(NULL, src); - nullpo_retr(NULL, ud); - - // find a free spot to store the new unit group - ARR_FIND(0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == NULL); - if (i == MAX_SKILLUNITGROUP) { - // array is full, make room by discarding oldest group - int j=0; - unsigned maxdiff=0,x,tick=gettick(); - for (i=0; i<MAX_SKILLUNITGROUP && ud->skillunit[i]; i++) - if ((x=DIFF_TICK(tick,ud->skillunit[i]->tick))>maxdiff) { - maxdiff=x; - j=i; - } - skill_delunitgroup(ud->skillunit[j]); - //Since elements must have shifted, we use the last slot. - i = MAX_SKILLUNITGROUP-1; - } - - group = ers_alloc(skill_unit_ers, struct skill_unit_group); - group->src_id = src->id; - group->party_id = status_get_party_id(src); - group->guild_id = status_get_guild_id(src); - group->bg_id = bg_team_get_id(src); - group->group_id = skill_get_new_group_id(); - group->unit = (struct skill_unit *)aCalloc(count,sizeof(struct skill_unit)); - group->unit_count = count; - group->alive_count = 0; - group->val1 = 0; - group->val2 = 0; - group->val3 = 0; - group->skill_id = skillid; - group->skill_lv = skilllv; - group->unit_id = unit_id; - group->map = src->m; - group->limit = limit; - group->interval = interval; - group->tick = gettick(); - group->valstr = NULL; - - ud->skillunit[i] = group; - - if (skillid == PR_SANCTUARY) //Sanctuary starts healing +1500ms after casted. [Skotlex] - group->tick += 1500; - - idb_put(group_db, group->group_id, group); - return group; +struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, short skillid, short skilllv, int unit_id, int limit, int interval) +{ + struct unit_data* ud = unit_bl2ud( src ); + struct skill_unit_group* group; + int i; + + if(skillid <= 0 || skilllv <= 0) return 0; + + nullpo_retr(NULL, src); + nullpo_retr(NULL, ud); + + // find a free spot to store the new unit group + ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == NULL ); + if(i == MAX_SKILLUNITGROUP) + { + // array is full, make room by discarding oldest group + int j=0; + unsigned maxdiff=0,x,tick=gettick(); + for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) + if((x=DIFF_TICK(tick,ud->skillunit[i]->tick))>maxdiff){ + maxdiff=x; + j=i; + } + skill_delunitgroup(ud->skillunit[j]); + //Since elements must have shifted, we use the last slot. + i = MAX_SKILLUNITGROUP-1; + } + + group = ers_alloc(skill_unit_ers, struct skill_unit_group); + group->src_id = src->id; + group->party_id = status_get_party_id(src); + group->guild_id = status_get_guild_id(src); + group->bg_id = bg_team_get_id(src); + group->group_id = skill_get_new_group_id(); + group->unit = (struct skill_unit *)aCalloc(count,sizeof(struct skill_unit)); + group->unit_count = count; + group->alive_count = 0; + group->val1 = 0; + group->val2 = 0; + group->val3 = 0; + group->skill_id = skillid; + group->skill_lv = skilllv; + group->unit_id = unit_id; + group->map = src->m; + group->limit = limit; + group->interval = interval; + group->tick = gettick(); + group->valstr = NULL; + + ud->skillunit[i] = group; + + if (skillid == PR_SANCTUARY) //Sanctuary starts healing +1500ms after casted. [Skotlex] + group->tick += 1500; + + idb_put(group_db, group->group_id, group); + return group; } /*========================================== * *------------------------------------------*/ -int skill_delunitgroup_(struct skill_unit_group *group, const char *file, int line, const char *func) +int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int line, const char* func) { - struct block_list *src; - struct unit_data *ud; - int i,j; - - if (group == NULL) { - ShowDebug("skill_delunitgroup: group is NULL (source=%s:%d, %s)! Please report this! (#3504)\n", file, line, func); - return 0; - } - - src=map_id2bl(group->src_id); - ud = unit_bl2ud(src); - if (!src || !ud) { - ShowError("skill_delunitgroup: Group's source not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id); - return 0; - } - - if (!status_isdead(src) && ((TBL_PC *)src)->state.warping && !((TBL_PC *)src)->state.changemap) { - switch (group->skill_id) { - case BA_DISSONANCE: - case BA_POEMBRAGI: - case BA_WHISTLE: - case BA_ASSASSINCROSS: - case BA_APPLEIDUN: - case DC_UGLYDANCE: - case DC_HUMMING: - case DC_DONTFORGETME: - case DC_FORTUNEKISS: - case DC_SERVICEFORYOU: - skill_usave_add(((TBL_PC *)src), group->skill_id, group->skill_lv); - break; - } - } - - if (skill_get_unit_flag(group->skill_id)&(UF_DANCE|UF_SONG|UF_ENSEMBLE)) { - struct status_change *sc = status_get_sc(src); - if (sc && sc->data[SC_DANCING]) { - sc->data[SC_DANCING]->val2 = 0 ; //This prevents status_change_end attempting to redelete the group. [Skotlex] - status_change_end(src, SC_DANCING, INVALID_TIMER); - } - } - - // end Gospel's status change on 'src' - // (needs to be done when the group is deleted by other means than skill deactivation) - if (group->unit_id == UNT_GOSPEL) { - struct status_change *sc = status_get_sc(src); - if (sc && sc->data[SC_GOSPEL]) { - sc->data[SC_GOSPEL]->val3 = 0; //Remove reference to this group. [Skotlex] - status_change_end(src, SC_GOSPEL, INVALID_TIMER); - } - } - - switch (group->skill_id) { - case SG_SUN_WARM: - case SG_MOON_WARM: - case SG_STAR_WARM: { - struct status_change *sc = NULL; - if ((sc = status_get_sc(src)) != NULL && sc->data[SC_WARM]) { - sc->data[SC_WARM]->val4 = 0; - status_change_end(src, SC_WARM, INVALID_TIMER); - } - } - break; - case NC_NEUTRALBARRIER: { - struct status_change *sc = NULL; - if ((sc = status_get_sc(src)) != NULL && sc->data[SC_NEUTRALBARRIER_MASTER]) { - sc->data[SC_NEUTRALBARRIER_MASTER]->val2 = 0; - status_change_end(src,SC_NEUTRALBARRIER_MASTER,INVALID_TIMER); - } - } - break; - case NC_STEALTHFIELD: { - struct status_change *sc = NULL; - if ((sc = status_get_sc(src)) != NULL && sc->data[SC_STEALTHFIELD_MASTER]) { - sc->data[SC_STEALTHFIELD_MASTER]->val2 = 0; - status_change_end(src,SC_STEALTHFIELD_MASTER,INVALID_TIMER); - } - } - break; - case LG_BANDING: { - struct status_change *sc = NULL; - if ((sc = status_get_sc(src)) && sc->data[SC_BANDING]) { - sc->data[SC_BANDING]->val4 = 0; - status_change_end(src,SC_BANDING,INVALID_TIMER); - } - } - break; - } - - if (src->type==BL_PC && group->state.ammo_consume) - battle_consume_ammo((TBL_PC *)src, group->skill_id, group->skill_lv); - - group->alive_count=0; - - // remove all unit cells - if (group->unit != NULL) - for (i = 0; i < group->unit_count; i++) - skill_delunit(&group->unit[i]); - - // clear Talkie-box string - if (group->valstr != NULL) { - aFree(group->valstr); - group->valstr = NULL; - } - - idb_remove(group_db, group->group_id); - map_freeblock(&group->unit->bl); // schedules deallocation of whole array (HACK) - group->unit=NULL; - group->group_id=0; - group->unit_count=0; - - // locate this group, swap with the last entry and delete it - ARR_FIND(0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == group); - ARR_FIND(i, MAX_SKILLUNITGROUP, j, ud->skillunit[j] == NULL); - j--; - if (i < MAX_SKILLUNITGROUP) { - ud->skillunit[i] = ud->skillunit[j]; - ud->skillunit[j] = NULL; - ers_free(skill_unit_ers, group); - } else - ShowError("skill_delunitgroup: Group not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id); - - return 1; + struct block_list* src; + struct unit_data *ud; + int i,j; + + if( group == NULL ) + { + ShowDebug("skill_delunitgroup: group is NULL (source=%s:%d, %s)! Please report this! (#3504)\n", file, line, func); + return 0; + } + + src=map_id2bl(group->src_id); + ud = unit_bl2ud(src); + if(!src || !ud) { + ShowError("skill_delunitgroup: Group's source not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id); + return 0; + } + + if( !status_isdead(src) && ((TBL_PC*)src)->state.warping && !((TBL_PC*)src)->state.changemap ) { + switch( group->skill_id ) { + case BA_DISSONANCE: + case BA_POEMBRAGI: + case BA_WHISTLE: + case BA_ASSASSINCROSS: + case BA_APPLEIDUN: + case DC_UGLYDANCE: + case DC_HUMMING: + case DC_DONTFORGETME: + case DC_FORTUNEKISS: + case DC_SERVICEFORYOU: + skill_usave_add(((TBL_PC*)src), group->skill_id, group->skill_lv); + break; + } + } + + if (skill_get_unit_flag(group->skill_id)&(UF_DANCE|UF_SONG|UF_ENSEMBLE)) + { + struct status_change* sc = status_get_sc(src); + if (sc && sc->data[SC_DANCING]) + { + sc->data[SC_DANCING]->val2 = 0 ; //This prevents status_change_end attempting to redelete the group. [Skotlex] + status_change_end(src, SC_DANCING, INVALID_TIMER); + } + } + + // end Gospel's status change on 'src' + // (needs to be done when the group is deleted by other means than skill deactivation) + if (group->unit_id == UNT_GOSPEL) { + struct status_change *sc = status_get_sc(src); + if(sc && sc->data[SC_GOSPEL]) { + sc->data[SC_GOSPEL]->val3 = 0; //Remove reference to this group. [Skotlex] + status_change_end(src, SC_GOSPEL, INVALID_TIMER); + } + } + + switch( group->skill_id ) { + case SG_SUN_WARM: + case SG_MOON_WARM: + case SG_STAR_WARM: + { + struct status_change *sc = NULL; + if( (sc = status_get_sc(src)) != NULL && sc->data[SC_WARM] ) { + sc->data[SC_WARM]->val4 = 0; + status_change_end(src, SC_WARM, INVALID_TIMER); + } + } + break; + case NC_NEUTRALBARRIER: + { + struct status_change *sc = NULL; + if( (sc = status_get_sc(src)) != NULL && sc->data[SC_NEUTRALBARRIER_MASTER] ) { + sc->data[SC_NEUTRALBARRIER_MASTER]->val2 = 0; + status_change_end(src,SC_NEUTRALBARRIER_MASTER,INVALID_TIMER); + } + } + break; + case NC_STEALTHFIELD: + { + struct status_change *sc = NULL; + if( (sc = status_get_sc(src)) != NULL && sc->data[SC_STEALTHFIELD_MASTER] ) { + sc->data[SC_STEALTHFIELD_MASTER]->val2 = 0; + status_change_end(src,SC_STEALTHFIELD_MASTER,INVALID_TIMER); + } + } + break; + case LG_BANDING: + { + struct status_change *sc = NULL; + if( (sc = status_get_sc(src)) && sc->data[SC_BANDING] ) { + sc->data[SC_BANDING]->val4 = 0; + status_change_end(src,SC_BANDING,INVALID_TIMER); + } + } + break; + } + + if (src->type==BL_PC && group->state.ammo_consume) + battle_consume_ammo((TBL_PC*)src, group->skill_id, group->skill_lv); + + group->alive_count=0; + + // remove all unit cells + if(group->unit != NULL) + for( i = 0; i < group->unit_count; i++ ) + skill_delunit(&group->unit[i]); + + // clear Talkie-box string + if( group->valstr != NULL ) + { + aFree(group->valstr); + group->valstr = NULL; + } + + idb_remove(group_db, group->group_id); + map_freeblock(&group->unit->bl); // schedules deallocation of whole array (HACK) + group->unit=NULL; + group->group_id=0; + group->unit_count=0; + + // locate this group, swap with the last entry and delete it + ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == group ); + ARR_FIND( i, MAX_SKILLUNITGROUP, j, ud->skillunit[j] == NULL ); j--; + if( i < MAX_SKILLUNITGROUP ) + { + ud->skillunit[i] = ud->skillunit[j]; + ud->skillunit[j] = NULL; + ers_free(skill_unit_ers, group); + } + else + ShowError("skill_delunitgroup: Group not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id); + + return 1; } /*========================================== * *------------------------------------------*/ -int skill_clear_unitgroup(struct block_list *src) +int skill_clear_unitgroup (struct block_list *src) { - struct unit_data *ud = unit_bl2ud(src); + struct unit_data *ud = unit_bl2ud(src); - nullpo_ret(ud); + nullpo_ret(ud); - while (ud->skillunit[0]) - skill_delunitgroup(ud->skillunit[0]); + while (ud->skillunit[0]) + skill_delunitgroup(ud->skillunit[0]); - return 1; + return 1; } /*========================================== * *------------------------------------------*/ -struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl, struct skill_unit_group *group, int tick) { - int i,j=-1,k,s,id; - struct unit_data *ud; - struct skill_unit_group_tickset *set; - - nullpo_ret(bl); - if (group->interval==-1) - return NULL; - - ud = unit_bl2ud(bl); - if (!ud) return NULL; - - set = ud->skillunittick; - - if (skill_get_unit_flag(group->skill_id)&UF_NOOVERLAP) - id = s = group->skill_id; - else - id = s = group->group_id; - - 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 (j == -1) { - ShowWarning("skill_unitgrouptickset_search: tickset is full\n"); - j = id % MAX_SKILLUNITGROUPTICKSET; - } - - set[j].id = id; - set[j].tick = tick; - return &set[j]; +struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_list *bl, struct skill_unit_group *group, int tick) +{ + int i,j=-1,k,s,id; + struct unit_data *ud; + struct skill_unit_group_tickset *set; + + nullpo_ret(bl); + if (group->interval==-1) + return NULL; + + ud = unit_bl2ud(bl); + if (!ud) return NULL; + + set = ud->skillunittick; + + if (skill_get_unit_flag(group->skill_id)&UF_NOOVERLAP) + id = s = group->skill_id; + else + id = s = group->group_id; + + 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 (j == -1) { + ShowWarning ("skill_unitgrouptickset_search: tickset is full\n"); + j = id % MAX_SKILLUNITGROUPTICKSET; + } + + set[j].id = id; + set[j].tick = tick; + return &set[j]; } /*========================================== * *------------------------------------------*/ -int skill_unit_timer_sub_onplace(struct block_list *bl, va_list ap) +int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) { - struct skill_unit *unit = va_arg(ap,struct skill_unit *); - struct skill_unit_group *group = unit->group; - unsigned int tick = va_arg(ap,unsigned int); + struct skill_unit* unit = va_arg(ap,struct skill_unit *); + struct skill_unit_group* group = unit->group; + unsigned int tick = va_arg(ap,unsigned int); - if (!unit->alive || bl->prev == NULL) - return 0; + if( !unit->alive || bl->prev == NULL ) + return 0; - nullpo_ret(group); + nullpo_ret(group); - if (!(skill_get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR)) - return 0; //AoE skills are ineffective. [Skotlex] + if( !(skill_get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) ) + return 0; //AoE skills are ineffective. [Skotlex] - if (battle_check_target(&unit->bl,bl,group->target_flag) <= 0) - return 0; + if( battle_check_target(&unit->bl,bl,group->target_flag) <= 0 ) + return 0; - skill_unit_onplace_timer(unit,bl,tick); + skill_unit_onplace_timer(unit,bl,tick); - return 1; + return 1; } /** @@ -15407,327 +15279,344 @@ int skill_unit_timer_sub_onplace(struct block_list *bl, va_list ap) */ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { - struct skill_unit *unit = db_data2ptr(data); - struct skill_unit_group *group = unit->group; - unsigned int tick = va_arg(ap,unsigned int); - bool dissonance; - struct block_list *bl = &unit->bl; - - if (!unit->alive) - return 0; - - nullpo_ret(group); - - // check for expiration - if (!group->state.guildaura && (DIFF_TICK(tick,group->tick) >= group->limit || DIFF_TICK(tick,group->tick) >= unit->limit)) { - // skill unit expired (inlined from skill_unit_onlimit()) - switch (group->unit_id) { - case UNT_BLASTMINE: + struct skill_unit* unit = db_data2ptr(data); + struct skill_unit_group* group = unit->group; + unsigned int tick = va_arg(ap,unsigned int); + bool dissonance; + struct block_list* bl = &unit->bl; + + if( !unit->alive ) + return 0; + + nullpo_ret(group); + + // check for expiration + if( !group->state.guildaura && (DIFF_TICK(tick,group->tick) >= group->limit || DIFF_TICK(tick,group->tick) >= unit->limit) ) + {// skill unit expired (inlined from skill_unit_onlimit()) + switch( group->unit_id ) + { + case UNT_BLASTMINE: #ifdef RENEWAL - case UNT_CLAYMORETRAP: + case UNT_CLAYMORETRAP: #endif - case UNT_GROUNDDRIFT_WIND: - case UNT_GROUNDDRIFT_DARK: - case UNT_GROUNDDRIFT_POISON: - case UNT_GROUNDDRIFT_WATER: - case UNT_GROUNDDRIFT_FIRE: - group->unit_id = UNT_USED_TRAPS; - //clif_changetraplook(bl, UNT_FIREPILLAR_ACTIVE); - group->limit=DIFF_TICK(tick+1500,group->tick); - unit->limit=DIFF_TICK(tick+1500,group->tick); - break; - - case UNT_ANKLESNARE: - case UNT_ELECTRICSHOCKER: - if (group->val2 > 0) { - // Used Trap don't returns back to item - skill_delunit(unit); - break; - } - case UNT_SKIDTRAP: - case UNT_LANDMINE: - case UNT_SHOCKWAVE: - case UNT_SANDMAN: - case UNT_FLASHER: - case UNT_FREEZINGTRAP: + case UNT_GROUNDDRIFT_WIND: + case UNT_GROUNDDRIFT_DARK: + case UNT_GROUNDDRIFT_POISON: + case UNT_GROUNDDRIFT_WATER: + case UNT_GROUNDDRIFT_FIRE: + group->unit_id = UNT_USED_TRAPS; + //clif_changetraplook(bl, UNT_FIREPILLAR_ACTIVE); + group->limit=DIFF_TICK(tick+1500,group->tick); + unit->limit=DIFF_TICK(tick+1500,group->tick); + break; + + case UNT_ANKLESNARE: + case UNT_ELECTRICSHOCKER: + if( group->val2 > 0 ) { + // Used Trap don't returns back to item + skill_delunit(unit); + break; + } + case UNT_SKIDTRAP: + case UNT_LANDMINE: + case UNT_SHOCKWAVE: + case UNT_SANDMAN: + case UNT_FLASHER: + case UNT_FREEZINGTRAP: #ifndef RENEWAL - case UNT_CLAYMORETRAP: + case UNT_CLAYMORETRAP: #endif - case UNT_TALKIEBOX: - case UNT_CLUSTERBOMB: - case UNT_MAGENTATRAP: - case UNT_COBALTTRAP: - case UNT_MAIZETRAP: - case UNT_VERDURETRAP: - case UNT_FIRINGTRAP: - case UNT_ICEBOUNDTRAP: - - { - struct block_list *src; - if (unit->val1 > 0 && (src = map_id2bl(group->src_id)) != NULL && src->type == BL_PC) { - // revert unit back into a trap - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = group->item_id?group->item_id:ITEMID_TRAP; - item_tmp.identify = 1; - map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0); - } - skill_delunit(unit); - } - break; - - case UNT_WARP_ACTIVE: - // warp portal opens (morph to a UNT_WARP_WAITING cell) - group->unit_id = skill_get_unit_id(group->skill_id, 1); // UNT_WARP_WAITING - clif_changelook(&unit->bl, LOOK_BASE, group->unit_id); - // restart timers - group->limit = skill_get_time(group->skill_id,group->skill_lv); - unit->limit = skill_get_time(group->skill_id,group->skill_lv); - // apply effect to all units standing on it - map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1); - break; - - case UNT_CALLFAMILY: { - struct map_session_data *sd = NULL; - if (group->val1) { - sd = map_charid2sd(group->val1); - group->val1 = 0; - if (sd && !map[sd->bl.m].flag.nowarp) - pc_setpos(sd,map_id2index(unit->bl.m),unit->bl.x,unit->bl.y,CLR_TELEPORT); - } - if (group->val2) { - sd = map_charid2sd(group->val2); - group->val2 = 0; - if (sd && !map[sd->bl.m].flag.nowarp) - pc_setpos(sd,map_id2index(unit->bl.m),unit->bl.x,unit->bl.y,CLR_TELEPORT); - } - skill_delunit(unit); - } - break; + case UNT_TALKIEBOX: + case UNT_CLUSTERBOMB: + case UNT_MAGENTATRAP: + case UNT_COBALTTRAP: + case UNT_MAIZETRAP: + case UNT_VERDURETRAP: + case UNT_FIRINGTRAP: + case UNT_ICEBOUNDTRAP: - case UNT_REVERBERATION: - if (unit->val1 <= 0) { // If it was deactivated. - skill_delunit(unit); - break; - } - clif_changetraplook(bl,UNT_USED_TRAPS); - map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); - group->limit = DIFF_TICK(tick,group->tick)+1000; - unit->limit = DIFF_TICK(tick,group->tick)+1000; - group->unit_id = UNT_USED_TRAPS; - break; - - case UNT_FEINTBOMB: { - struct block_list *src = map_id2bl(group->src_id); - if (src) - map_foreachinrange(skill_area_sub, &group->unit->bl, unit->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill_castend_damage_id); - skill_delunit(unit); - break; - } + { + struct block_list* src; + if( unit->val1 > 0 && (src = map_id2bl(group->src_id)) != NULL && src->type == BL_PC ) + { // revert unit back into a trap + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = group->item_id?group->item_id:ITEMID_TRAP; + item_tmp.identify = 1; + map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0); + } + skill_delunit(unit); + } + break; + + case UNT_WARP_ACTIVE: + // warp portal opens (morph to a UNT_WARP_WAITING cell) + group->unit_id = skill_get_unit_id(group->skill_id, 1); // UNT_WARP_WAITING + clif_changelook(&unit->bl, LOOK_BASE, group->unit_id); + // restart timers + group->limit = skill_get_time(group->skill_id,group->skill_lv); + unit->limit = skill_get_time(group->skill_id,group->skill_lv); + // apply effect to all units standing on it + map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1); + break; + + case UNT_CALLFAMILY: + { + struct map_session_data *sd = NULL; + if(group->val1) { + sd = map_charid2sd(group->val1); + group->val1 = 0; + if (sd && !map[sd->bl.m].flag.nowarp) + pc_setpos(sd,map_id2index(unit->bl.m),unit->bl.x,unit->bl.y,CLR_TELEPORT); + } + if(group->val2) { + sd = map_charid2sd(group->val2); + group->val2 = 0; + if (sd && !map[sd->bl.m].flag.nowarp) + pc_setpos(sd,map_id2index(unit->bl.m),unit->bl.x,unit->bl.y,CLR_TELEPORT); + } + skill_delunit(unit); + } + break; - case UNT_BANDING: { - struct block_list *src = map_id2bl(group->src_id); - struct status_change *sc; - if (!src || (sc = status_get_sc(src)) == NULL || !sc->data[SC_BANDING]) { - skill_delunit(unit); - break; - } - // This unit isn't removed while SC_BANDING is active. - group->limit = DIFF_TICK(tick+group->interval,group->tick); - unit->limit = DIFF_TICK(tick+group->interval,group->tick); - } - break; - - default: - skill_delunit(unit); - } - } else { - // skill unit is still active - switch (group->unit_id) { - case UNT_ICEWALL: - // icewall loses 50 hp every second - unit->val1 -= SKILLUNITTIMER_INTERVAL/20; // trap's hp - if (unit->val1 <= 0 && unit->limit + group->tick > tick + 700) - unit->limit = DIFF_TICK(tick+700,group->tick); - break; - case UNT_BLASTMINE: - case UNT_SKIDTRAP: - case UNT_LANDMINE: - case UNT_SHOCKWAVE: - case UNT_SANDMAN: - case UNT_FLASHER: - case UNT_CLAYMORETRAP: - case UNT_FREEZINGTRAP: - case UNT_TALKIEBOX: - case UNT_ANKLESNARE: - if (unit->val1 <= 0) { - if (group->unit_id == UNT_ANKLESNARE && group->val2 > 0) - skill_delunit(unit); - else { - clif_changetraplook(bl, group->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); - group->limit = DIFF_TICK(tick, group->tick) + 1500; - group->unit_id = UNT_USED_TRAPS; - } - } - break; - case UNT_REVERBERATION: - if (unit->val1 <= 0) { - clif_changetraplook(bl,UNT_USED_TRAPS); - map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); - group->limit = DIFF_TICK(tick,group->tick)+1000; - unit->limit = DIFF_TICK(tick,group->tick)+1000; - group->unit_id = UNT_USED_TRAPS; - } - break; - case UNT_WALLOFTHORN: - if (unit->val1 <= 0) { - group->unit_id = UNT_USED_TRAPS; - group->limit = DIFF_TICK(tick, group->tick) + 1500; - } - break; - } - } - - //Don't continue if unit or even group is expired and has been deleted. - if (!group || !unit->alive) - return 0; - - dissonance = skill_dance_switch(unit, 0); - - if (unit->range >= 0 && group->interval != -1) { - if (battle_config.skill_wall_check) - map_foreachinshootrange(skill_unit_timer_sub_onplace, bl, unit->range, group->bl_flag, bl,tick); - else - map_foreachinrange(skill_unit_timer_sub_onplace, bl, unit->range, group->bl_flag, bl,tick); - - if (unit->range == -1) //Unit disabled, but it should not be deleted yet. - group->unit_id = UNT_USED_TRAPS; - - if (group->unit_id == UNT_TATAMIGAESHI) { - unit->range = -1; //Disable processed cell. - if (--group->val1 <= 0) { // number of live cells - //All tiles were processed, disable skill. - group->target_flag=BCT_NOONE; - group->bl_flag= BL_NUL; - } - } - } + case UNT_REVERBERATION: + if( unit->val1 <= 0 ) { // If it was deactivated. + skill_delunit(unit); + break; + } + clif_changetraplook(bl,UNT_USED_TRAPS); + map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); + group->limit = DIFF_TICK(tick,group->tick)+1000; + unit->limit = DIFF_TICK(tick,group->tick)+1000; + group->unit_id = UNT_USED_TRAPS; + break; + + case UNT_FEINTBOMB: { + struct block_list *src = map_id2bl(group->src_id); + if( src ) + map_foreachinrange(skill_area_sub, &group->unit->bl, unit->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill_castend_damage_id); + skill_delunit(unit); + break; + } - if (dissonance) skill_dance_switch(unit, 1); + case UNT_BANDING: + { + struct block_list *src = map_id2bl(group->src_id); + struct status_change *sc; + if( !src || (sc = status_get_sc(src)) == NULL || !sc->data[SC_BANDING] ) + { + skill_delunit(unit); + break; + } + // This unit isn't removed while SC_BANDING is active. + group->limit = DIFF_TICK(tick+group->interval,group->tick); + unit->limit = DIFF_TICK(tick+group->interval,group->tick); + } + break; + + default: + skill_delunit(unit); + } + } + else + {// skill unit is still active + switch( group->unit_id ) + { + case UNT_ICEWALL: + // icewall loses 50 hp every second + unit->val1 -= SKILLUNITTIMER_INTERVAL/20; // trap's hp + if( unit->val1 <= 0 && unit->limit + group->tick > tick + 700 ) + unit->limit = DIFF_TICK(tick+700,group->tick); + break; + case UNT_BLASTMINE: + case UNT_SKIDTRAP: + case UNT_LANDMINE: + case UNT_SHOCKWAVE: + case UNT_SANDMAN: + case UNT_FLASHER: + case UNT_CLAYMORETRAP: + case UNT_FREEZINGTRAP: + case UNT_TALKIEBOX: + case UNT_ANKLESNARE: + if( unit->val1 <= 0 ) { + if( group->unit_id == UNT_ANKLESNARE && group->val2 > 0 ) + skill_delunit(unit); + else { + clif_changetraplook(bl, group->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); + group->limit = DIFF_TICK(tick, group->tick) + 1500; + group->unit_id = UNT_USED_TRAPS; + } + } + break; + case UNT_REVERBERATION: + if( unit->val1 <= 0 ){ + clif_changetraplook(bl,UNT_USED_TRAPS); + map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); + group->limit = DIFF_TICK(tick,group->tick)+1000; + unit->limit = DIFF_TICK(tick,group->tick)+1000; + group->unit_id = UNT_USED_TRAPS; + } + break; + case UNT_WALLOFTHORN: + if( unit->val1 <= 0 ) { + group->unit_id = UNT_USED_TRAPS; + group->limit = DIFF_TICK(tick, group->tick) + 1500; + } + break; + } + } + + //Don't continue if unit or even group is expired and has been deleted. + if( !group || !unit->alive ) + return 0; + + dissonance = skill_dance_switch(unit, 0); + + if( unit->range >= 0 && group->interval != -1 ) + { + if( battle_config.skill_wall_check ) + map_foreachinshootrange(skill_unit_timer_sub_onplace, bl, unit->range, group->bl_flag, bl,tick); + else + map_foreachinrange(skill_unit_timer_sub_onplace, bl, unit->range, group->bl_flag, bl,tick); + + if(unit->range == -1) //Unit disabled, but it should not be deleted yet. + group->unit_id = UNT_USED_TRAPS; + + if( group->unit_id == UNT_TATAMIGAESHI ) + { + unit->range = -1; //Disable processed cell. + if (--group->val1 <= 0) // number of live cells + { //All tiles were processed, disable skill. + group->target_flag=BCT_NOONE; + group->bl_flag= BL_NUL; + } + } + } - return 0; + if( dissonance ) skill_dance_switch(unit, 1); + + return 0; } /*========================================== * Executes on all skill units every SKILLUNITTIMER_INTERVAL miliseconds. *------------------------------------------*/ int skill_unit_timer(int tid, unsigned int tick, int id, intptr_t data) { - map_freeblock_lock(); + map_freeblock_lock(); - skillunit_db->foreach(skillunit_db, skill_unit_timer_sub, tick); + skillunit_db->foreach(skillunit_db, skill_unit_timer_sub, tick); - map_freeblock_unlock(); + map_freeblock_unlock(); - return 0; + return 0; } static int skill_unit_temp[20]; // temporary storage for tracking skill unit skill ids as players move in/out of them /*========================================== * *------------------------------------------*/ -int skill_unit_move_sub(struct block_list *bl, va_list ap) +int skill_unit_move_sub (struct block_list* bl, va_list ap) { - struct skill_unit *unit = (struct skill_unit *)bl; - struct skill_unit_group *group = unit->group; - - struct block_list *target = va_arg(ap,struct block_list *); - unsigned int tick = va_arg(ap,unsigned int); - int flag = va_arg(ap,int); - - bool dissonance; - int skill_id; - int i; - - nullpo_ret(group); - - if (!unit->alive || target->prev == NULL) - return 0; - - if (flag&1 && (unit->group->skill_id == PF_SPIDERWEB || unit->group->skill_id == GN_THORNS_TRAP)) - return 0; // Fiberlock is never supposed to trigger on skill_unit_move. [Inkfish] - - dissonance = skill_dance_switch(unit, 0); - - //Necessary in case the group is deleted after calling on_place/on_out [Skotlex] - skill_id = unit->group->skill_id; - - if (unit->group->interval != -1 && !(skill_get_unit_flag(skill_id)&UF_DUALMODE) && skill_id != BD_LULLABY) { //Lullaby is the exception, bugreport:411 - //Non-dualmode unit skills with a timer don't trigger when walking, so just return - if (dissonance) skill_dance_switch(unit, 1); - return 0; - } - - //Target-type check. - if (!(group->bl_flag&target->type && battle_check_target(&unit->bl,target,group->target_flag) > 0)) { - if (group->src_id == target->id && group->state.song_dance&0x2) { - //Ensemble check to see if they went out/in of the area [Skotlex] - if (flag&1) { - if (flag&2) { - //Clear this skill id. - ARR_FIND(0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == skill_id); - if (i < ARRAYLENGTH(skill_unit_temp)) - skill_unit_temp[i] = 0; - } - } else { - if (flag&2) { - //Store this skill id. - ARR_FIND(0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == 0); - if (i < ARRAYLENGTH(skill_unit_temp)) - skill_unit_temp[i] = skill_id; - else - ShowError("skill_unit_move_sub: Reached limit of unit objects per cell!\n"); - } + struct skill_unit* unit = (struct skill_unit *)bl; + struct skill_unit_group* group = unit->group; - } + struct block_list* target = va_arg(ap,struct block_list*); + unsigned int tick = va_arg(ap,unsigned int); + int flag = va_arg(ap,int); - if (flag&4) - skill_unit_onleft(skill_id,target,tick); - } - - if (dissonance) skill_dance_switch(unit, 1); - - return 0; - } else { - if (flag&1) { - int result = skill_unit_onplace(unit,target,tick); - if (flag&2 && result) { - //Clear skill ids we have stored in onout. - ARR_FIND(0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == result); - if (i < ARRAYLENGTH(skill_unit_temp)) - skill_unit_temp[i] = 0; - } - } else { - int result = skill_unit_onout(unit,target,tick); - if (flag&2 && result) { - //Store this unit id. - ARR_FIND(0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == 0); - if (i < ARRAYLENGTH(skill_unit_temp)) - skill_unit_temp[i] = skill_id; - else - ShowError("skill_unit_move_sub: Reached limit of unit objects per cell!\n"); - } - } + bool dissonance; + int skill_id; + int i; + + nullpo_ret(group); + + if( !unit->alive || target->prev == NULL ) + return 0; + + if( flag&1 && ( unit->group->skill_id == PF_SPIDERWEB || unit->group->skill_id == GN_THORNS_TRAP ) ) + return 0; // Fiberlock is never supposed to trigger on skill_unit_move. [Inkfish] - //TODO: Normally, this is dangerous since the unit and group could be freed - //inside the onout/onplace functions. Currently it is safe because we know song/dance - //cells do not get deleted within them. [Skotlex] - if (dissonance) skill_dance_switch(unit, 1); + dissonance = skill_dance_switch(unit, 0); - if (flag&4) - skill_unit_onleft(skill_id,target,tick); + //Necessary in case the group is deleted after calling on_place/on_out [Skotlex] + skill_id = unit->group->skill_id; - return 1; - } + if( unit->group->interval != -1 && !(skill_get_unit_flag(skill_id)&UF_DUALMODE) && skill_id != BD_LULLABY ) //Lullaby is the exception, bugreport:411 + { //Non-dualmode unit skills with a timer don't trigger when walking, so just return + if( dissonance ) skill_dance_switch(unit, 1); + return 0; + } + + //Target-type check. + if( !(group->bl_flag&target->type && battle_check_target(&unit->bl,target,group->target_flag) > 0) ) + { + if( group->src_id == target->id && group->state.song_dance&0x2 ) + { //Ensemble check to see if they went out/in of the area [Skotlex] + if( flag&1 ) + { + if( flag&2 ) + { //Clear this skill id. + ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == skill_id ); + if( i < ARRAYLENGTH(skill_unit_temp) ) + skill_unit_temp[i] = 0; + } + } + else + { + if( flag&2 ) + { //Store this skill id. + ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == 0 ); + if( i < ARRAYLENGTH(skill_unit_temp) ) + skill_unit_temp[i] = skill_id; + else + ShowError("skill_unit_move_sub: Reached limit of unit objects per cell!\n"); + } + + } + + if( flag&4 ) + skill_unit_onleft(skill_id,target,tick); + } + + if( dissonance ) skill_dance_switch(unit, 1); + + return 0; + } + else + { + if( flag&1 ) + { + int result = skill_unit_onplace(unit,target,tick); + if( flag&2 && result ) + { //Clear skill ids we have stored in onout. + ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == result ); + if( i < ARRAYLENGTH(skill_unit_temp) ) + skill_unit_temp[i] = 0; + } + } + else + { + int result = skill_unit_onout(unit,target,tick); + if( flag&2 && result ) + { //Store this unit id. + ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == 0 ); + if( i < ARRAYLENGTH(skill_unit_temp) ) + skill_unit_temp[i] = skill_id; + else + ShowError("skill_unit_move_sub: Reached limit of unit objects per cell!\n"); + } + } + + //TODO: Normally, this is dangerous since the unit and group could be freed + //inside the onout/onplace functions. Currently it is safe because we know song/dance + //cells do not get deleted within them. [Skotlex] + if( dissonance ) skill_dance_switch(unit, 1); + + if( flag&4 ) + skill_unit_onleft(skill_id,target,tick); + + return 1; + } } /*========================================== @@ -15738,1199 +15627,1156 @@ int skill_unit_move_sub(struct block_list *bl, va_list ap) * units to figure out when they have left a group. * flag&4: Force a onleft event (triggered when the bl is killed, for example) *------------------------------------------*/ -int skill_unit_move(struct block_list *bl, unsigned int tick, int flag) +int skill_unit_move (struct block_list *bl, unsigned int tick, int flag) { - nullpo_ret(bl); + nullpo_ret(bl); - if (bl->prev == NULL) - return 0; + if( bl->prev == NULL ) + return 0; - if (flag&2 && !(flag&1)) { - //Onout, clear data - memset(skill_unit_temp, 0, sizeof(skill_unit_temp)); - } + if( flag&2 && !(flag&1) ) + { //Onout, clear data + memset(skill_unit_temp, 0, sizeof(skill_unit_temp)); + } - map_foreachincell(skill_unit_move_sub,bl->m,bl->x,bl->y,BL_SKILL,bl,tick,flag); + map_foreachincell(skill_unit_move_sub,bl->m,bl->x,bl->y,BL_SKILL,bl,tick,flag); - if (flag&2 && flag&1) { - //Onplace, check any skill units you have left. - int i; - for (i = 0; i < ARRAYLENGTH(skill_unit_temp); i++) - if (skill_unit_temp[i]) - skill_unit_onleft(skill_unit_temp[i], bl, tick); - } + if( flag&2 && flag&1 ) + { //Onplace, check any skill units you have left. + int i; + for( i = 0; i < ARRAYLENGTH(skill_unit_temp); i++ ) + if( skill_unit_temp[i] ) + skill_unit_onleft(skill_unit_temp[i], bl, tick); + } - return 0; + return 0; } /*========================================== * *------------------------------------------*/ -int skill_unit_move_unit_group(struct skill_unit_group *group, int m, int dx, int dy) +int skill_unit_move_unit_group (struct skill_unit_group *group, int m, int dx, int dy) { - int i,j; - unsigned int tick = gettick(); - int *m_flag; - struct skill_unit *unit1; - struct skill_unit *unit2; - - if (group == NULL) - return 0; - if (group->unit_count<=0) - return 0; - if (group->unit==NULL) - return 0; - - if (skill_get_unit_flag(group->skill_id)&UF_ENSEMBLE) - return 0; //Ensembles may not be moved around. - - if (group->unit_id == UNT_ICEWALL || group->unit_id == UNT_WALLOFTHORN) - return 0; //Icewalls and Wall of Thorns don't get knocked back - - m_flag = (int *) aCalloc(group->unit_count, sizeof(int)); - // m_flag - // 0: Neither of the following (skill_unit_onplace & skill_unit_onout are needed) - // 1: Unit will move to a slot that had another unit of the same group (skill_unit_onplace not needed) - // 2: Another unit from same group will end up positioned on this unit (skill_unit_onout not needed) - // 3: Both 1+2. - 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) { - m_flag[i] |= 0x1; - } - if (unit1->bl.x-dx==unit2->bl.x && unit1->bl.y-dy==unit2->bl.y) { - m_flag[i] |= 0x2; - } - } - } - j = 0; - for (i=0; i<group->unit_count; i++) { - unit1=&group->unit[i]; - if (!unit1->alive) - continue; - if (!(m_flag[i]&0x2)) { - if (group->state.song_dance&0x1) //Cancel dissonance effect. - skill_dance_overlap(unit1, 0); - map_foreachincell(skill_unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,4); - } - //Move Cell using "smart" criteria (avoid useless moving around) - switch (m_flag[i]) { - case 0: - //Cell moves independently, safely move it. - map_moveblock(&unit1->bl, unit1->bl.x+dx, unit1->bl.y+dy, tick); - break; - case 1: - //Cell moves unto another cell, look for a replacement cell that won't collide - //and has no cell moving into it (flag == 2) - for (; j<group->unit_count; j++) { - if (m_flag[j]!=2 || !group->unit[j].alive) - continue; - //Move to where this cell would had moved. - unit2 = &group->unit[j]; - map_moveblock(&unit1->bl, unit2->bl.x+dx, unit2->bl.y+dy, tick); - j++; //Skip this cell as we have used it. - break; - } - break; - case 2: - case 3: - break; //Don't move the cell as a cell will end on this tile anyway. - } - if (!(m_flag[i]&0x2)) { //We only moved the cell in 0-1 - if (group->state.song_dance&0x1) //Check for dissonance effect. - skill_dance_overlap(unit1, 1); - clif_skill_setunit(unit1); - map_foreachincell(skill_unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,1); - } - } - aFree(m_flag); - return 0; + int i,j; + unsigned int tick = gettick(); + int *m_flag; + struct skill_unit *unit1; + struct skill_unit *unit2; + + if (group == NULL) + return 0; + if (group->unit_count<=0) + return 0; + if (group->unit==NULL) + return 0; + + if (skill_get_unit_flag(group->skill_id)&UF_ENSEMBLE) + return 0; //Ensembles may not be moved around. + + if( group->unit_id == UNT_ICEWALL || group->unit_id == UNT_WALLOFTHORN ) + return 0; //Icewalls and Wall of Thorns don't get knocked back + + m_flag = (int *) aCalloc(group->unit_count, sizeof(int)); + // m_flag + // 0: Neither of the following (skill_unit_onplace & skill_unit_onout are needed) + // 1: Unit will move to a slot that had another unit of the same group (skill_unit_onplace not needed) + // 2: Another unit from same group will end up positioned on this unit (skill_unit_onout not needed) + // 3: Both 1+2. + 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){ + m_flag[i] |= 0x1; + } + if (unit1->bl.x-dx==unit2->bl.x && unit1->bl.y-dy==unit2->bl.y){ + m_flag[i] |= 0x2; + } + } + } + j = 0; + for (i=0;i<group->unit_count;i++) { + unit1=&group->unit[i]; + if (!unit1->alive) + continue; + if (!(m_flag[i]&0x2)) { + if (group->state.song_dance&0x1) //Cancel dissonance effect. + skill_dance_overlap(unit1, 0); + map_foreachincell(skill_unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,4); + } + //Move Cell using "smart" criteria (avoid useless moving around) + switch(m_flag[i]) + { + case 0: + //Cell moves independently, safely move it. + map_moveblock(&unit1->bl, unit1->bl.x+dx, unit1->bl.y+dy, tick); + break; + case 1: + //Cell moves unto another cell, look for a replacement cell that won't collide + //and has no cell moving into it (flag == 2) + for(;j<group->unit_count;j++) + { + if(m_flag[j]!=2 || !group->unit[j].alive) + continue; + //Move to where this cell would had moved. + unit2 = &group->unit[j]; + map_moveblock(&unit1->bl, unit2->bl.x+dx, unit2->bl.y+dy, tick); + j++; //Skip this cell as we have used it. + break; + } + break; + case 2: + case 3: + break; //Don't move the cell as a cell will end on this tile anyway. + } + if (!(m_flag[i]&0x2)) { //We only moved the cell in 0-1 + if (group->state.song_dance&0x1) //Check for dissonance effect. + skill_dance_overlap(unit1, 1); + clif_skill_setunit(unit1); + map_foreachincell(skill_unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,1); + } + } + aFree(m_flag); + return 0; } /*========================================== * *------------------------------------------*/ -int skill_can_produce_mix(struct map_session_data *sd, int nameid, int trigger, int qty) +int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger, int qty) { - int i,j; - - nullpo_ret(sd); - - if (nameid<=0) - return 0; + int i,j; + + nullpo_ret(sd); + + if(nameid<=0) + return 0; + + for(i=0;i<MAX_SKILL_PRODUCE_DB;i++){ + if(skill_produce_db[i].nameid == nameid ){ + if((j=skill_produce_db[i].req_skill)>0 && + pc_checkskill(sd,j) < skill_produce_db[i].req_skill_lv) + continue; // must iterate again to check other skills that produce it. [malufett] + if( j > 0 && sd->menuskill_id > 0 && sd->menuskill_id != j ) + continue; // special case + break; + } + } - for (i=0; i<MAX_SKILL_PRODUCE_DB; i++) { - if (skill_produce_db[i].nameid == nameid) { - if ((j=skill_produce_db[i].req_skill)>0 && - pc_checkskill(sd,j) < skill_produce_db[i].req_skill_lv) - continue; // must iterate again to check other skills that produce it. [malufett] - if (j > 0 && sd->menuskill_id > 0 && sd->menuskill_id != j) - continue; // special case - break; - } - } + if( i >= MAX_SKILL_PRODUCE_DB ) + return 0; - if (i >= MAX_SKILL_PRODUCE_DB) - return 0; + if( pc_checkadditem(sd, nameid, qty) == ADDITEM_OVERAMOUNT ) + {// cannot carry the produced stuff + return 0; + } - if (pc_checkadditem(sd, nameid, qty) == ADDITEM_OVERAMOUNT) { - // cannot carry the produced stuff - return 0; - } + if(trigger>=0){ + if(trigger>20) { // Non-weapon, non-food item (itemlv must match) + if(skill_produce_db[i].itemlv!=trigger) + return 0; + } else if(trigger>10) { // Food (any item level between 10 and 20 will do) + if(skill_produce_db[i].itemlv<=10 || skill_produce_db[i].itemlv>20) + return 0; + } else { // Weapon (itemlv must be higher or equal) + if(skill_produce_db[i].itemlv>trigger) + return 0; + } + } - if (trigger>=0) { - if (trigger>20) { // Non-weapon, non-food item (itemlv must match) - if (skill_produce_db[i].itemlv!=trigger) - return 0; - } else if (trigger>10) { // Food (any item level between 10 and 20 will do) - if (skill_produce_db[i].itemlv<=10 || skill_produce_db[i].itemlv>20) - return 0; - } else { // Weapon (itemlv must be higher or equal) - if (skill_produce_db[i].itemlv>trigger) - return 0; - } - } - - for (j=0; j<MAX_PRODUCE_RESOURCE; j++) { - int id,x,y; - if ((id=skill_produce_db[i].mat_id[j]) <= 0) - continue; - if (skill_produce_db[i].mat_amount[j] <= 0) { - if (pc_search_inventory(sd,id) < 0) - return 0; - } else { - for (y=0,x=0; y<MAX_INVENTORY; y++) - if (sd->status.inventory[y].nameid == id) - x+=sd->status.inventory[y].amount; - if (x<qty*skill_produce_db[i].mat_amount[j]) - return 0; - } - } - return i+1; + for(j=0;j<MAX_PRODUCE_RESOURCE;j++){ + int id,x,y; + if( (id=skill_produce_db[i].mat_id[j]) <= 0 ) + continue; + if(skill_produce_db[i].mat_amount[j] <= 0) { + if(pc_search_inventory(sd,id) < 0) + return 0; + } + else { + for(y=0,x=0;y<MAX_INVENTORY;y++) + if( sd->status.inventory[y].nameid == id ) + x+=sd->status.inventory[y].amount; + if(x<qty*skill_produce_db[i].mat_amount[j]) + return 0; + } + } + return i+1; } /*========================================== * *------------------------------------------*/ -int skill_produce_mix(struct map_session_data *sd, int skill_id, int nameid, int slot1, int slot2, int slot3, int qty) +int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, int slot1, int slot2, int slot3, int qty) { - int slot[3]; - int i,sc,ele,idx,equip,wlv,make_per = 0,flag = 0,skilllv = 0; - int num = -1; // exclude the recipe - struct status_data *status; - struct item_data *data; - - nullpo_ret(sd); - status = status_get_status_data(&sd->bl); - - if (sd->skillid_old == skill_id) - skilllv = sd->skilllv_old; - - if (!(idx=skill_can_produce_mix(sd,nameid,-1, qty))) - return 0; - idx--; - - if (qty < 1) - qty = 1; - - if (!skill_id) //A skill can be specified for some override cases. - skill_id = skill_produce_db[idx].req_skill; - - if (skill_id == GC_RESEARCHNEWPOISON) - skill_id = GC_CREATENEWPOISON; - - slot[0]=slot1; - slot[1]=slot2; - slot[2]=slot3; - - for (i=0,sc=0,ele=0; i<3; i++) { //Note that qty should always be one if you are using these! - int j; - if (slot[i]<=0) - continue; - j = pc_search_inventory(sd,slot[i]); - if (j < 0) - continue; - if (slot[i]==1000) { /* Star Crumb */ - pc_delitem(sd,j,1,1,0,LOG_TYPE_PRODUCE); - sc++; - } - if (slot[i]>=994 && slot[i]<=997 && ele==0) { /* Flame Heart . . . Great Nature */ - static const int ele_table[4]= {3,1,4,2}; - pc_delitem(sd,j,1,1,0,LOG_TYPE_PRODUCE); - ele=ele_table[slot[i]-994]; - } - } - - if (skill_id == RK_RUNEMASTERY) { - int temp_qty, skill_lv = pc_checkskill(sd,skill_id); - data = itemdb_search(nameid); - - if (skill_lv == 10) temp_qty = 1 + rnd()%3; - else if (skill_lv > 5) temp_qty = 1 + rnd()%2; - else temp_qty = 1; - - if (data->stack.inventory) { - for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].nameid == nameid) { - if (sd->status.inventory[i].amount >= data->stack.amount) { - clif_msgtable(sd->fd,0x61b); - return 0; - } else { - /** - * the amount fits, say we got temp_qty 4 and 19 runes, we trim temp_qty to 1. - **/ - if (temp_qty + sd->status.inventory[i].amount >= data->stack.amount) - temp_qty = data->stack.amount - sd->status.inventory[i].amount; - } - break; - } - } - } - qty = temp_qty; - } - - for (i=0; i<MAX_PRODUCE_RESOURCE; i++) { - int j,id,x; - if ((id=skill_produce_db[idx].mat_id[i]) <= 0) - continue; - num++; - x=(skill_id == RK_RUNEMASTERY ? 1 : qty)*skill_produce_db[idx].mat_amount[i]; - do { - int y=0; - j = pc_search_inventory(sd,id); - - if (j >= 0) { - y = sd->status.inventory[j].amount; - if (y>x)y=x; - pc_delitem(sd,j,y,0,0,LOG_TYPE_PRODUCE); - } else - ShowError("skill_produce_mix: material item error\n"); - - x-=y; - } while (j>=0 && x>0); - } - - if ((equip = (itemdb_isequip(nameid) && skill_id != GN_CHANGEMATERIAL && skill_id != GN_MAKEBOMB))) - wlv = itemdb_wlv(nameid); - if (!equip) { - switch (skill_id) { - case BS_IRON: - case BS_STEEL: - case BS_ENCHANTEDSTONE: - // Ores & Metals Refining - skill bonuses are straight from kRO website [DracoRPG] - i = pc_checkskill(sd,skill_id); - make_per = sd->status.job_level*20 + status->dex*10 + status->luk*10; //Base chance - switch (nameid) { - case 998: // Iron - make_per += 4000+i*500; // Temper Iron bonus: +26/+32/+38/+44/+50 - break; - case 999: // Steel - make_per += 3000+i*500; // Temper Steel bonus: +35/+40/+45/+50/+55 - break; - case 1000: //Star Crumb - make_per = 100000; // Star Crumbs are 100% success crafting rate? (made 1000% so it succeeds even after penalties) [Skotlex] - break; - default: // Enchanted Stones - make_per += 1000+i*500; // Enchantedstone Craft bonus: +15/+20/+25/+30/+35 - break; - } - break; - case ASC_CDP: - make_per = (2000 + 40*status->dex + 20*status->luk); - break; - case AL_HOLYWATER: - /** - * Arch Bishop - **/ - case AB_ANCILLA: - make_per = 100000; //100% success - break; - case AM_PHARMACY: // Potion Preparation - reviewed with the help of various Ragnainfo sources [DracoRPG] - case AM_TWILIGHT1: - case AM_TWILIGHT2: - case AM_TWILIGHT3: - make_per = pc_checkskill(sd,AM_LEARNINGPOTION)*50 - + pc_checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20 - + (status->int_/2)*10 + status->dex*10+status->luk*10; - if (merc_is_hom_active(sd->hd)) { //Player got a homun - int skill; - if ((skill=merc_hom_checkskill(sd->hd,HVAN_INSTRUCT)) > 0) //His homun is a vanil with instruction change - make_per += skill*100; //+1% bonus per level - } - switch (nameid) { - case 501: // Red Potion - case 503: // Yellow Potion - case 504: // White Potion - make_per += (1+rnd()%100)*10 + 2000; - break; - case 970: // Alcohol - make_per += (1+rnd()%100)*10 + 1000; - break; - case 7135: // Bottle Grenade - case 7136: // Acid Bottle - case 7137: // Plant Bottle - case 7138: // Marine Sphere Bottle - make_per += (1+rnd()%100)*10; - break; - case 546: // Condensed Yellow Potion - make_per -= (1+rnd()%50)*10; - break; - case 547: // Condensed White Potion - case 7139: // Glistening Coat - make_per -= (1+rnd()%100)*10; - break; - //Common items, recieve no bonus or penalty, listed just because they are commonly produced - case 505: // Blue Potion - case 545: // Condensed Red Potion - case 605: // Anodyne - case 606: // Aloevera - default: - break; - } - if (battle_config.pp_rate != 100) - make_per = make_per * battle_config.pp_rate / 100; - break; - case SA_CREATECON: // Elemental Converter Creation - make_per = 100000; // should be 100% success rate - break; - /** - * Rune Knight - **/ - case RK_RUNEMASTERY: { - int A = 100 * (51 + 2 * pc_checkskill(sd, skill_id)); - int B = 100 * status->dex / 30 + 10 * (status->luk + sd->status.job_level); - int C = 100 * cap_value(sd->itemid,0,100); //itemid depend on makerune() - int D = 0; - switch (nameid) { //rune rank it_diff 9 craftable rune - case ITEMID_BERKANA: - D = -2000; - break; //Rank S - case ITEMID_NAUTHIZ: - case ITEMID_URUZ: - D = -1500; - break; //Rank A - case ITEMID_ISA: - case ITEMID_WYRD: - D = -1000; - break; //Rank B - case ITEMID_RAIDO: - case ITEMID_THURISAZ: - case ITEMID_HAGALAZ: - case ITEMID_OTHILA: - D = -500; - break; //Rank C - default: - D = -1500; - break; //not specified =-15% - } - make_per = A + B + C + D; - break; - } - /** - * Guilotine Cross - **/ - case GC_CREATENEWPOISON: - make_per = 3000 + 500 * pc_checkskill(sd,GC_RESEARCHNEWPOISON); - qty = 1+rnd()%pc_checkskill(sd,GC_RESEARCHNEWPOISON); - break; - case GN_CHANGEMATERIAL: - for (i=0; i<MAX_SKILL_PRODUCE_DB; i++) - if (skill_changematerial_db[i].itemid == nameid) { - make_per = skill_changematerial_db[i].rate * 10; - break; - } - break; - case GN_S_PHARMACY: { - int difficulty = 0; - - difficulty = (620 - 20 * skilllv);// (620 - 20 * Skill Level) - - make_per = status->int_ + status->dex/2 + status->luk + sd->status.job_level + (30+rnd()%120) + // (Caster?s INT) + (Caster?s DEX / 2) + (Caster?s LUK) + (Caster?s Job Level) + Random number between (30 ~ 150) + - (sd->status.base_level-100) + pc_checkskill(sd, AM_LEARNINGPOTION) + pc_checkskill(sd, CR_FULLPROTECTION)*(4+rnd()%6); // (Caster?s Base Level - 100) + (Potion Research x 5) + (Full Chemical Protection Skill Level) x (Random number between 4 ~ 10) - - switch (nameid) { // difficulty factor - case 12422: - case 12425: - case 12428: - difficulty += 10; - break; - case 6212: - case 12426: - difficulty += 15; - break; - case 13264: - case 12423: - case 12427: - case 12436: - difficulty += 20; - break; - case 6210: - case 6211: - case 12437: - difficulty += 30; - break; - case 12424: - case 12475: - difficulty += 40; - break; - } + int slot[3]; + int i,sc,ele,idx,equip,wlv,make_per = 0,flag = 0,skilllv = 0; + int num = -1; // exclude the recipe + struct status_data *status; + struct item_data* data; + + nullpo_ret(sd); + status = status_get_status_data(&sd->bl); + + if( sd->skillid_old == skill_id ) + skilllv = sd->skilllv_old; + + if( !(idx=skill_can_produce_mix(sd,nameid,-1, qty)) ) + return 0; + idx--; + + if (qty < 1) + qty = 1; + + if (!skill_id) //A skill can be specified for some override cases. + skill_id = skill_produce_db[idx].req_skill; + + if( skill_id == GC_RESEARCHNEWPOISON ) + skill_id = GC_CREATENEWPOISON; + + slot[0]=slot1; + slot[1]=slot2; + slot[2]=slot3; + + for(i=0,sc=0,ele=0;i<3;i++){ //Note that qty should always be one if you are using these! + int j; + if( slot[i]<=0 ) + continue; + j = pc_search_inventory(sd,slot[i]); + if(j < 0) + continue; + if(slot[i]==1000){ /* Star Crumb */ + pc_delitem(sd,j,1,1,0,LOG_TYPE_PRODUCE); + sc++; + } + if(slot[i]>=994 && slot[i]<=997 && ele==0){ /* Flame Heart . . . Great Nature */ + static const int ele_table[4]={3,1,4,2}; + pc_delitem(sd,j,1,1,0,LOG_TYPE_PRODUCE); + ele=ele_table[slot[i]-994]; + } + } - if (make_per >= 400 && make_per > difficulty) - qty = 10; - else if (make_per >= 300 && make_per > difficulty) - qty = 7; - else if (make_per >= 100 && make_per > difficulty) - qty = 6; - else if (make_per >= 1 && make_per > difficulty) - qty = 5; - else - qty = 4; - make_per = 10000; - } - break; - case GN_MAKEBOMB: - case GN_MIX_COOKING: { - int difficulty = 30 + rnd()%120; // Random number between (30 ~ 150) - - make_per = sd->status.job_level / 4 + status->luk / 2 + status->dex / 3; // (Caster?s Job Level / 4) + (Caster?s LUK / 2) + (Caster?s DEX / 3) - qty = ~(5 + rnd()%5) + 1; - - switch (nameid) { // difficulty factor - case 13260: - difficulty += 5; - break; - case 13261: - case 13262: - difficulty += 10; - break; - case 12429: - case 12430: - case 12431: - case 12432: - case 12433: - case 12434: - case 13263: - difficulty += 15; - break; - case 13264: - difficulty += 20; - break; - } + if( skill_id == RK_RUNEMASTERY ) { + int temp_qty, skill_lv = pc_checkskill(sd,skill_id); + data = itemdb_search(nameid); + + if( skill_lv == 10 ) temp_qty = 1 + rnd()%3; + else if( skill_lv > 5 ) temp_qty = 1 + rnd()%2; + else temp_qty = 1; + + if (data->stack.inventory) { + for( i = 0; i < MAX_INVENTORY; i++ ) { + if( sd->status.inventory[i].nameid == nameid ) { + if( sd->status.inventory[i].amount >= data->stack.amount ) { + clif_msgtable(sd->fd,0x61b); + return 0; + } else { + /** + * the amount fits, say we got temp_qty 4 and 19 runes, we trim temp_qty to 1. + **/ + if( temp_qty + sd->status.inventory[i].amount >= data->stack.amount ) + temp_qty = data->stack.amount - sd->status.inventory[i].amount; + } + break; + } + } + } + qty = temp_qty; + } - if (make_per >= 30 && make_per > difficulty) - qty = 10 + rnd()%2; - else if (make_per >= 10 && make_per > difficulty) - qty = 10; - else if (make_per == 10 && make_per > difficulty) - qty = 8; - else if ((make_per >= 50 || make_per < 30) && make_per < difficulty) - ;// Food/Bomb creation fails. - else if (make_per >= 30 && make_per < difficulty) - qty = 5; - - if (qty < 0 || (skilllv == 1 && make_per < difficulty)) { - qty = ~qty + 1; - make_per = 0; - } else - make_per = 10000; - qty = (skilllv > 1 ? qty : 1); - } - break; - default: - if (sd->menuskill_id == AM_PHARMACY && - sd->menuskill_val > 10 && sd->menuskill_val <= 20) { - //Assume Cooking Dish - if (sd->menuskill_val >= 15) //Legendary Cooking Set. - make_per = 10000; //100% Success - else - make_per = 1200 * (sd->menuskill_val - 10) - + 20 * (sd->status.base_level + 1) - + 20 * (status->dex + 1) - + 100 * (rnd()%(30+5*(sd->cook_mastery/400) - (6+sd->cook_mastery/80)) + (6+sd->cook_mastery/80)) - - 400 * (skill_produce_db[idx].itemlv - 11 + 1) - - 10 * (100 - status->luk + 1) - - 500 * (num - 1) - - 100 * (rnd()%4 + 1); - break; - } - make_per = 5000; - break; - } - } else { // Weapon Forging - skill bonuses are straight from kRO website, other things from a jRO calculator [DracoRPG] - make_per = 5000 + sd->status.job_level*20 + status->dex*10 + status->luk*10; // Base - make_per += pc_checkskill(sd,skill_id)*500; // Smithing skills bonus: +5/+10/+15 - make_per += pc_checkskill(sd,BS_WEAPONRESEARCH)*100 +((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100:0); // Weaponry Research bonus: +1/+2/+3/+4/+5/+6/+7/+8/+9/+10, Oridecon Research bonus (custom): +1/+2/+3/+4/+5 - make_per -= (ele?2000:0) + sc*1500 + (wlv>1?wlv*1000:0); // Element Stone: -20%, Star Crumb: -15% each, Weapon level malus: -0/-20/-30 - if (pc_search_inventory(sd,989) > 0) make_per+= 1000; // Emperium Anvil: +10 - else if (pc_search_inventory(sd,988) > 0) make_per+= 500; // Golden Anvil: +5 - else if (pc_search_inventory(sd,987) > 0) make_per+= 300; // Oridecon Anvil: +3 - else if (pc_search_inventory(sd,986) > 0) make_per+= 0; // Anvil: +0? - if (battle_config.wp_rate != 100) - make_per = make_per * battle_config.wp_rate / 100; - } - - if (sd->class_&JOBL_BABY) //if it's a Baby Class - make_per = (make_per * 50) / 100; //Baby penalty is 50% (bugreport:4847) - - if (make_per < 1) make_per = 1; - - - if (rnd()%10000 < make_per || qty > 1) { //Success, or crafting multiple items. - struct item tmp_item; - memset(&tmp_item,0,sizeof(tmp_item)); - tmp_item.nameid=nameid; - tmp_item.amount=1; - tmp_item.identify=1; - if (equip) { - tmp_item.card[0]=CARD0_FORGE; - tmp_item.card[1]=((sc*5)<<8)+ele; - tmp_item.card[2]=GetWord(sd->status.char_id,0); // CharId - tmp_item.card[3]=GetWord(sd->status.char_id,1); - } else { - //Flag is only used on the end, so it can be used here. [Skotlex] - switch (skill_id) { - case BS_DAGGER: - case BS_SWORD: - case BS_TWOHANDSWORD: - case BS_AXE: - case BS_MACE: - case BS_KNUCKLE: - case BS_SPEAR: - flag = battle_config.produce_item_name_input&0x1; - break; - case AM_PHARMACY: - case AM_TWILIGHT1: - case AM_TWILIGHT2: - case AM_TWILIGHT3: - flag = battle_config.produce_item_name_input&0x2; - break; - case AL_HOLYWATER: - /** - * Arch Bishop - **/ - case AB_ANCILLA: - flag = battle_config.produce_item_name_input&0x8; - break; - case ASC_CDP: - flag = battle_config.produce_item_name_input&0x10; - break; - default: - flag = battle_config.produce_item_name_input&0x80; - break; - } - if (flag) { - tmp_item.card[0]=CARD0_CREATE; - tmp_item.card[1]=0; - tmp_item.card[2]=GetWord(sd->status.char_id,0); // CharId - tmp_item.card[3]=GetWord(sd->status.char_id,1); - } - } - - // if(log_config.produce > 0) - // log_produce(sd,nameid,slot1,slot2,slot3,1); - //TODO update PICKLOG - - if (equip) { - clif_produceeffect(sd,0,nameid); - clif_misceffect(&sd->bl,3); - if (itemdb_wlv(nameid) >= 3 && ((ele? 1 : 0) + sc) >= 3) // Fame point system [DracoRPG] - pc_addfame(sd,10); // Success to forge a lv3 weapon with 3 additional ingredients = +10 fame point - } else { - int fame = 0; - tmp_item.amount = 0; - - for (i=0; i< qty; i++) { //Apply quantity modifiers. - if ((skill_id == GN_MIX_COOKING || skill_id == GN_MAKEBOMB || skill_id == GN_S_PHARMACY) && make_per > 1) { - tmp_item.amount = qty; - break; - } - if (rnd()%10000 < make_per || qty == 1) { //Success - tmp_item.amount++; - if (nameid < 545 || nameid > 547) - continue; - if (skill_id != AM_PHARMACY && - skill_id != AM_TWILIGHT1 && - skill_id != AM_TWILIGHT2 && - skill_id != AM_TWILIGHT3) - continue; - //Add fame as needed. - switch (++sd->potion_success_counter) { - case 3: - fame+=1; // Success to prepare 3 Condensed Potions in a row - break; - case 5: - fame+=3; // Success to prepare 5 Condensed Potions in a row - break; - case 7: - fame+=10; // Success to prepare 7 Condensed Potions in a row - break; - case 10: - fame+=50; // Success to prepare 10 Condensed Potions in a row - sd->potion_success_counter = 0; - break; - } - } else //Failure - sd->potion_success_counter = 0; - } + for(i=0;i<MAX_PRODUCE_RESOURCE;i++){ + int j,id,x; + if( (id=skill_produce_db[idx].mat_id[i]) <= 0 ) + continue; + num++; + x=( skill_id == RK_RUNEMASTERY ? 1 : qty)*skill_produce_db[idx].mat_amount[i]; + do{ + int y=0; + j = pc_search_inventory(sd,id); + + if(j >= 0){ + y = sd->status.inventory[j].amount; + if(y>x)y=x; + pc_delitem(sd,j,y,0,0,LOG_TYPE_PRODUCE); + } else + ShowError("skill_produce_mix: material item error\n"); + + x-=y; + }while( j>=0 && x>0 ); + } - if (fame) - pc_addfame(sd,fame); - //Visual effects and the like. - switch (skill_id) { - case AM_PHARMACY: - case AM_TWILIGHT1: - case AM_TWILIGHT2: - case AM_TWILIGHT3: - case ASC_CDP: - clif_produceeffect(sd,2,nameid); - clif_misceffect(&sd->bl,5); - break; - case BS_IRON: - case BS_STEEL: - case BS_ENCHANTEDSTONE: - clif_produceeffect(sd,0,nameid); - clif_misceffect(&sd->bl,3); - break; - case RK_RUNEMASTERY: - case GC_CREATENEWPOISON: - clif_produceeffect(sd,2,nameid); - clif_misceffect(&sd->bl,5); - break; - default: //Those that don't require a skill? - if (skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20) { - //Cooking items. - clif_specialeffect(&sd->bl, 608, AREA); - if (sd->cook_mastery < 1999) - pc_setglobalreg(sd, "COOK_MASTERY",sd->cook_mastery + (1 << ((skill_produce_db[idx].itemlv - 11) / 2)) * 5); - } - break; - } - } - if (skill_id == GN_CHANGEMATERIAL && tmp_item.amount) { //Success - int j, k = 0; - for (i=0; i<MAX_SKILL_PRODUCE_DB; i++) - if (skill_changematerial_db[i].itemid == nameid) { - for (j=0; j<5; j++) { - if (rnd()%1000 < skill_changematerial_db[i].qty_rate[j]) { - tmp_item.amount = qty * skill_changematerial_db[i].qty[j]; - if ((flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) { - clif_additem(sd,0,0,flag); - map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - k++; - } - } - break; - } - if (k) { - clif_msg_skill(sd,skill_id,0x627); - return 1; - } - } else if (tmp_item.amount) { //Success - if ((flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) { - clif_additem(sd,0,0,flag); - map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - if (skill_id == GN_MIX_COOKING || skill_id == GN_MAKEBOMB || skill_id == GN_S_PHARMACY) - clif_msg_skill(sd,skill_id,0x627); - return 1; - } - } - //Failure - // if(log_config.produce) - // log_produce(sd,nameid,slot1,slot2,slot3,0); - //TODO update PICKLOG - - if (equip) { - clif_produceeffect(sd,1,nameid); - clif_misceffect(&sd->bl,2); - } else { - switch (skill_id) { - case ASC_CDP: //25% Damage yourself, and display same effect as failed potion. - status_percent_damage(NULL, &sd->bl, -25, 0, true); - case AM_PHARMACY: - case AM_TWILIGHT1: - case AM_TWILIGHT2: - case AM_TWILIGHT3: - clif_produceeffect(sd,3,nameid); - clif_misceffect(&sd->bl,6); - sd->potion_success_counter = 0; // Fame point system [DracoRPG] - break; - case BS_IRON: - case BS_STEEL: - case BS_ENCHANTEDSTONE: - clif_produceeffect(sd,1,nameid); - clif_misceffect(&sd->bl,2); - break; - case RK_RUNEMASTERY: - case GC_CREATENEWPOISON: - clif_produceeffect(sd,3,nameid); - clif_misceffect(&sd->bl,6); - break; - case GN_MIX_COOKING: { - struct item tmp_item; - const int compensation[5] = {13265, 13266, 13267, 12435, 13268}; - int rate = rnd()%500; - memset(&tmp_item,0,sizeof(tmp_item)); - if (rate < 50) i = 4; - else if (rate < 100) i = 2+rnd()%1; - else if (rate < 250) i = 1; - else if (rate < 500) i = 0; - tmp_item.nameid = compensation[i]; - tmp_item.amount = qty; - tmp_item.identify = 1; - if (pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE)) { - clif_additem(sd,0,0,flag); - map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - clif_msg_skill(sd,skill_id,0x628); - } - break; - case GN_MAKEBOMB: - case GN_S_PHARMACY: - case GN_CHANGEMATERIAL: - clif_msg_skill(sd,skill_id,0x628); - break; - default: - if (skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20) { - //Cooking items. - clif_specialeffect(&sd->bl, 609, AREA); - if (sd->cook_mastery > 0) - pc_setglobalreg(sd, "COOK_MASTERY", sd->cook_mastery - (1 << ((skill_produce_db[idx].itemlv - 11) / 2)) - (((1 << ((skill_produce_db[idx].itemlv - 11) / 2)) >> 1) * 3)); - } - } - } - return 0; -} + if( (equip = (itemdb_isequip(nameid) && skill_id != GN_CHANGEMATERIAL && skill_id != GN_MAKEBOMB )) ) + wlv = itemdb_wlv(nameid); + if(!equip) { + switch(skill_id){ + case BS_IRON: + case BS_STEEL: + case BS_ENCHANTEDSTONE: + // Ores & Metals Refining - skill bonuses are straight from kRO website [DracoRPG] + i = pc_checkskill(sd,skill_id); + make_per = sd->status.job_level*20 + status->dex*10 + status->luk*10; //Base chance + switch(nameid){ + case 998: // Iron + make_per += 4000+i*500; // Temper Iron bonus: +26/+32/+38/+44/+50 + break; + case 999: // Steel + make_per += 3000+i*500; // Temper Steel bonus: +35/+40/+45/+50/+55 + break; + case 1000: //Star Crumb + make_per = 100000; // Star Crumbs are 100% success crafting rate? (made 1000% so it succeeds even after penalties) [Skotlex] + break; + default: // Enchanted Stones + make_per += 1000+i*500; // Enchantedstone Craft bonus: +15/+20/+25/+30/+35 + break; + } + break; + case ASC_CDP: + make_per = (2000 + 40*status->dex + 20*status->luk); + break; + case AL_HOLYWATER: + /** + * Arch Bishop + **/ + case AB_ANCILLA: + make_per = 100000; //100% success + break; + case AM_PHARMACY: // Potion Preparation - reviewed with the help of various Ragnainfo sources [DracoRPG] + case AM_TWILIGHT1: + case AM_TWILIGHT2: + case AM_TWILIGHT3: + make_per = pc_checkskill(sd,AM_LEARNINGPOTION)*50 + + pc_checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20 + + (status->int_/2)*10 + status->dex*10+status->luk*10; + if(merc_is_hom_active(sd->hd)) {//Player got a homun + int skill; + if((skill=merc_hom_checkskill(sd->hd,HVAN_INSTRUCT)) > 0) //His homun is a vanil with instruction change + make_per += skill*100; //+1% bonus per level + } + switch(nameid){ + case 501: // Red Potion + case 503: // Yellow Potion + case 504: // White Potion + make_per += (1+rnd()%100)*10 + 2000; + break; + case 970: // Alcohol + make_per += (1+rnd()%100)*10 + 1000; + break; + case 7135: // Bottle Grenade + case 7136: // Acid Bottle + case 7137: // Plant Bottle + case 7138: // Marine Sphere Bottle + make_per += (1+rnd()%100)*10; + break; + case 546: // Condensed Yellow Potion + make_per -= (1+rnd()%50)*10; + break; + case 547: // Condensed White Potion + case 7139: // Glistening Coat + make_per -= (1+rnd()%100)*10; + break; + //Common items, recieve no bonus or penalty, listed just because they are commonly produced + case 505: // Blue Potion + case 545: // Condensed Red Potion + case 605: // Anodyne + case 606: // Aloevera + default: + break; + } + if(battle_config.pp_rate != 100) + make_per = make_per * battle_config.pp_rate / 100; + break; + case SA_CREATECON: // Elemental Converter Creation + make_per = 100000; // should be 100% success rate + break; + /** + * Rune Knight + **/ + case RK_RUNEMASTERY: + { + int A = 100 * (51 + 2 * pc_checkskill(sd, skill_id)); + int B = 100 * status->dex / 30 + 10 * (status->luk + sd->status.job_level); + int C = 100 * cap_value(sd->itemid,0,100); //itemid depend on makerune() + int D = 0; + switch (nameid) { //rune rank it_diff 9 craftable rune + case ITEMID_BERKANA: + D = -2000; + break; //Rank S + case ITEMID_NAUTHIZ: + case ITEMID_URUZ: + D = -1500; + break; //Rank A + case ITEMID_ISA: + case ITEMID_WYRD: + D = -1000; + break; //Rank B + case ITEMID_RAIDO: + case ITEMID_THURISAZ: + case ITEMID_HAGALAZ: + case ITEMID_OTHILA: + D = -500; + break; //Rank C + default: D = -1500; + break; //not specified =-15% + } + make_per = A + B + C + D; + break; + } + /** + * Guilotine Cross + **/ + case GC_CREATENEWPOISON: + make_per = 3000 + 500 * pc_checkskill(sd,GC_RESEARCHNEWPOISON); + qty = 1+rnd()%pc_checkskill(sd,GC_RESEARCHNEWPOISON); + break; + case GN_CHANGEMATERIAL: + for(i=0; i<MAX_SKILL_PRODUCE_DB; i++) + if( skill_changematerial_db[i].itemid == nameid ){ + make_per = skill_changematerial_db[i].rate * 10; + break; + } + break; + case GN_S_PHARMACY: + { + int difficulty = 0; + + difficulty = (620 - 20 * skilllv);// (620 - 20 * Skill Level) + + make_per = status->int_ + status->dex/2 + status->luk + sd->status.job_level + (30+rnd()%120) + // (Caster?s INT) + (Caster?s DEX / 2) + (Caster?s LUK) + (Caster?s Job Level) + Random number between (30 ~ 150) + + (sd->status.base_level-100) + pc_checkskill(sd, AM_LEARNINGPOTION) + pc_checkskill(sd, CR_FULLPROTECTION)*(4+rnd()%6); // (Caster?s Base Level - 100) + (Potion Research x 5) + (Full Chemical Protection Skill Level) x (Random number between 4 ~ 10) + + switch(nameid){// difficulty factor + case 12422: case 12425: + case 12428: + difficulty += 10; + break; + case 6212: case 12426: + difficulty += 15; + break; + case 13264: case 12423: + case 12427: case 12436: + difficulty += 20; + break; + case 6210: case 6211: + case 12437: + difficulty += 30; + break; + case 12424: case 12475: + difficulty += 40; + break; + } + + if( make_per >= 400 && make_per > difficulty) + qty = 10; + else if( make_per >= 300 && make_per > difficulty) + qty = 7; + else if( make_per >= 100 && make_per > difficulty) + qty = 6; + else if( make_per >= 1 && make_per > difficulty) + qty = 5; + else + qty = 4; + make_per = 10000; + } + break; + case GN_MAKEBOMB: + case GN_MIX_COOKING: + { + int difficulty = 30 + rnd()%120; // Random number between (30 ~ 150) + + make_per = sd->status.job_level / 4 + status->luk / 2 + status->dex / 3; // (Caster?s Job Level / 4) + (Caster?s LUK / 2) + (Caster?s DEX / 3) + qty = ~(5 + rnd()%5) + 1; + + switch(nameid){// difficulty factor + case 13260: + difficulty += 5; + break; + case 13261: case 13262: + difficulty += 10; + break; + case 12429: case 12430: case 12431: + case 12432: case 12433: case 12434: + case 13263: + difficulty += 15; + break; + case 13264: + difficulty += 20; + break; + } + + if( make_per >= 30 && make_per > difficulty) + qty = 10 + rnd()%2; + else if( make_per >= 10 && make_per > difficulty) + qty = 10; + else if( make_per == 10 && make_per > difficulty) + qty = 8; + else if( (make_per >= 50 || make_per < 30) && make_per < difficulty) + ;// Food/Bomb creation fails. + else if( make_per >= 30 && make_per < difficulty) + qty = 5; + + if( qty < 0 || (skilllv == 1 && make_per < difficulty)){ + qty = ~qty + 1; + make_per = 0; + }else + make_per = 10000; + qty = (skilllv > 1 ? qty : 1); + } + break; + default: + if (sd->menuskill_id == AM_PHARMACY && + sd->menuskill_val > 10 && sd->menuskill_val <= 20) + { //Assume Cooking Dish + if (sd->menuskill_val >= 15) //Legendary Cooking Set. + make_per = 10000; //100% Success + else + make_per = 1200 * (sd->menuskill_val - 10) + + 20 * (sd->status.base_level + 1) + + 20 * (status->dex + 1) + + 100 * (rnd()%(30+5*(sd->cook_mastery/400) - (6+sd->cook_mastery/80)) + (6+sd->cook_mastery/80)) + - 400 * (skill_produce_db[idx].itemlv - 11 + 1) + - 10 * (100 - status->luk + 1) + - 500 * (num - 1) + - 100 * (rnd()%4 + 1); + break; + } + make_per = 5000; + break; + } + } else { // Weapon Forging - skill bonuses are straight from kRO website, other things from a jRO calculator [DracoRPG] + make_per = 5000 + sd->status.job_level*20 + status->dex*10 + status->luk*10; // Base + make_per += pc_checkskill(sd,skill_id)*500; // Smithing skills bonus: +5/+10/+15 + make_per += pc_checkskill(sd,BS_WEAPONRESEARCH)*100 +((wlv >= 3)? pc_checkskill(sd,BS_ORIDEOCON)*100:0); // Weaponry Research bonus: +1/+2/+3/+4/+5/+6/+7/+8/+9/+10, Oridecon Research bonus (custom): +1/+2/+3/+4/+5 + make_per -= (ele?2000:0) + sc*1500 + (wlv>1?wlv*1000:0); // Element Stone: -20%, Star Crumb: -15% each, Weapon level malus: -0/-20/-30 + if(pc_search_inventory(sd,989) > 0) make_per+= 1000; // Emperium Anvil: +10 + else if(pc_search_inventory(sd,988) > 0) make_per+= 500; // Golden Anvil: +5 + else if(pc_search_inventory(sd,987) > 0) make_per+= 300; // Oridecon Anvil: +3 + else if(pc_search_inventory(sd,986) > 0) make_per+= 0; // Anvil: +0? + if(battle_config.wp_rate != 100) + make_per = make_per * battle_config.wp_rate / 100; + } -int skill_arrow_create(struct map_session_data *sd, int nameid) -{ - int i,j,flag,index=-1; - struct item tmp_item; + if (sd->class_&JOBL_BABY) //if it's a Baby Class + make_per = (make_per * 50) / 100; //Baby penalty is 50% (bugreport:4847) + + if(make_per < 1) make_per = 1; + + + if(rnd()%10000 < make_per || qty > 1){ //Success, or crafting multiple items. + struct item tmp_item; + memset(&tmp_item,0,sizeof(tmp_item)); + tmp_item.nameid=nameid; + tmp_item.amount=1; + tmp_item.identify=1; + if(equip){ + tmp_item.card[0]=CARD0_FORGE; + tmp_item.card[1]=((sc*5)<<8)+ele; + tmp_item.card[2]=GetWord(sd->status.char_id,0); // CharId + tmp_item.card[3]=GetWord(sd->status.char_id,1); + } else { + //Flag is only used on the end, so it can be used here. [Skotlex] + switch (skill_id) { + case BS_DAGGER: + case BS_SWORD: + case BS_TWOHANDSWORD: + case BS_AXE: + case BS_MACE: + case BS_KNUCKLE: + case BS_SPEAR: + flag = battle_config.produce_item_name_input&0x1; + break; + case AM_PHARMACY: + case AM_TWILIGHT1: + case AM_TWILIGHT2: + case AM_TWILIGHT3: + flag = battle_config.produce_item_name_input&0x2; + break; + case AL_HOLYWATER: + /** + * Arch Bishop + **/ + case AB_ANCILLA: + flag = battle_config.produce_item_name_input&0x8; + break; + case ASC_CDP: + flag = battle_config.produce_item_name_input&0x10; + break; + default: + flag = battle_config.produce_item_name_input&0x80; + break; + } + if (flag) { + tmp_item.card[0]=CARD0_CREATE; + tmp_item.card[1]=0; + tmp_item.card[2]=GetWord(sd->status.char_id,0); // CharId + tmp_item.card[3]=GetWord(sd->status.char_id,1); + } + } + +// if(log_config.produce > 0) +// log_produce(sd,nameid,slot1,slot2,slot3,1); +//TODO update PICKLOG + + if(equip){ + clif_produceeffect(sd,0,nameid); + clif_misceffect(&sd->bl,3); + if(itemdb_wlv(nameid) >= 3 && ((ele? 1 : 0) + sc) >= 3) // Fame point system [DracoRPG] + pc_addfame(sd,10); // Success to forge a lv3 weapon with 3 additional ingredients = +10 fame point + } else { + int fame = 0; + tmp_item.amount = 0; + + for (i=0; i< qty; i++) { //Apply quantity modifiers. + if( (skill_id == GN_MIX_COOKING || skill_id == GN_MAKEBOMB || skill_id == GN_S_PHARMACY) && make_per > 1){ + tmp_item.amount = qty; + break; + } + if (rnd()%10000 < make_per || qty == 1) { //Success + tmp_item.amount++; + if(nameid < 545 || nameid > 547) + continue; + if( skill_id != AM_PHARMACY && + skill_id != AM_TWILIGHT1 && + skill_id != AM_TWILIGHT2 && + skill_id != AM_TWILIGHT3 ) + continue; + //Add fame as needed. + switch(++sd->potion_success_counter) { + case 3: + fame+=1; // Success to prepare 3 Condensed Potions in a row + break; + case 5: + fame+=3; // Success to prepare 5 Condensed Potions in a row + break; + case 7: + fame+=10; // Success to prepare 7 Condensed Potions in a row + break; + case 10: + fame+=50; // Success to prepare 10 Condensed Potions in a row + sd->potion_success_counter = 0; + break; + } + } else //Failure + sd->potion_success_counter = 0; + } - nullpo_ret(sd); + if (fame) + pc_addfame(sd,fame); + //Visual effects and the like. + switch (skill_id) { + case AM_PHARMACY: + case AM_TWILIGHT1: + case AM_TWILIGHT2: + case AM_TWILIGHT3: + case ASC_CDP: + clif_produceeffect(sd,2,nameid); + clif_misceffect(&sd->bl,5); + break; + case BS_IRON: + case BS_STEEL: + case BS_ENCHANTEDSTONE: + clif_produceeffect(sd,0,nameid); + clif_misceffect(&sd->bl,3); + break; + case RK_RUNEMASTERY: + case GC_CREATENEWPOISON: + clif_produceeffect(sd,2,nameid); + clif_misceffect(&sd->bl,5); + break; + default: //Those that don't require a skill? + if( skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20) + { //Cooking items. + clif_specialeffect(&sd->bl, 608, AREA); + if( sd->cook_mastery < 1999 ) + pc_setglobalreg(sd, "COOK_MASTERY",sd->cook_mastery + ( 1 << ( (skill_produce_db[idx].itemlv - 11) / 2 ) ) * 5); + } + break; + } + } + if ( skill_id == GN_CHANGEMATERIAL && tmp_item.amount) { //Success + int j, k = 0; + for(i=0; i<MAX_SKILL_PRODUCE_DB; i++) + if( skill_changematerial_db[i].itemid == nameid ){ + for(j=0; j<5; j++){ + if( rnd()%1000 < skill_changematerial_db[i].qty_rate[j] ){ + tmp_item.amount = qty * skill_changematerial_db[i].qty[j]; + if((flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) { + clif_additem(sd,0,0,flag); + map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + k++; + } + } + break; + } + if( k ){ + clif_msg_skill(sd,skill_id,0x627); + return 1; + } + } else if (tmp_item.amount) { //Success + if((flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) { + clif_additem(sd,0,0,flag); + map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + if( skill_id == GN_MIX_COOKING || skill_id == GN_MAKEBOMB || skill_id == GN_S_PHARMACY ) + clif_msg_skill(sd,skill_id,0x627); + return 1; + } + } + //Failure +// if(log_config.produce) +// log_produce(sd,nameid,slot1,slot2,slot3,0); +//TODO update PICKLOG + + if(equip){ + clif_produceeffect(sd,1,nameid); + clif_misceffect(&sd->bl,2); + } else { + switch (skill_id) { + case ASC_CDP: //25% Damage yourself, and display same effect as failed potion. + status_percent_damage(NULL, &sd->bl, -25, 0, true); + case AM_PHARMACY: + case AM_TWILIGHT1: + case AM_TWILIGHT2: + case AM_TWILIGHT3: + clif_produceeffect(sd,3,nameid); + clif_misceffect(&sd->bl,6); + sd->potion_success_counter = 0; // Fame point system [DracoRPG] + break; + case BS_IRON: + case BS_STEEL: + case BS_ENCHANTEDSTONE: + clif_produceeffect(sd,1,nameid); + clif_misceffect(&sd->bl,2); + break; + case RK_RUNEMASTERY: + case GC_CREATENEWPOISON: + clif_produceeffect(sd,3,nameid); + clif_misceffect(&sd->bl,6); + break; + case GN_MIX_COOKING: { + struct item tmp_item; + const int compensation[5] = {13265, 13266, 13267, 12435, 13268}; + int rate = rnd()%500; + memset(&tmp_item,0,sizeof(tmp_item)); + if( rate < 50) i = 4; + else if( rate < 100) i = 2+rnd()%1; + else if( rate < 250 ) i = 1; + else if( rate < 500 ) i = 0; + tmp_item.nameid = compensation[i]; + tmp_item.amount = qty; + tmp_item.identify = 1; + if( pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE) ) { + clif_additem(sd,0,0,flag); + map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + clif_msg_skill(sd,skill_id,0x628); + } + break; + case GN_MAKEBOMB: + case GN_S_PHARMACY: + case GN_CHANGEMATERIAL: + clif_msg_skill(sd,skill_id,0x628); + break; + default: + if( skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20 ) + { //Cooking items. + clif_specialeffect(&sd->bl, 609, AREA); + if( sd->cook_mastery > 0 ) + pc_setglobalreg(sd, "COOK_MASTERY", sd->cook_mastery - ( 1 << ((skill_produce_db[idx].itemlv - 11) / 2) ) - ( ( ( 1 << ((skill_produce_db[idx].itemlv - 11) / 2) ) >> 1 ) * 3 )); + } + } + } + return 0; +} - if (nameid <= 0) - return 1; +int skill_arrow_create (struct map_session_data *sd, int nameid) +{ + int i,j,flag,index=-1; + struct item tmp_item; + + nullpo_ret(sd); + + if(nameid <= 0) + return 1; + + for(i=0;i<MAX_SKILL_ARROW_DB;i++) + if(nameid == skill_arrow_db[i].nameid) { + index = i; + break; + } + + if(index < 0 || (j = pc_search_inventory(sd,nameid)) < 0) + return 1; + + pc_delitem(sd,j,1,0,0,LOG_TYPE_PRODUCE); + for(i=0;i<MAX_ARROW_RESOURCE;i++) { + memset(&tmp_item,0,sizeof(tmp_item)); + tmp_item.identify = 1; + tmp_item.nameid = skill_arrow_db[index].cre_id[i]; + tmp_item.amount = skill_arrow_db[index].cre_amount[i]; + if(battle_config.produce_item_name_input&0x4) { + tmp_item.card[0]=CARD0_CREATE; + tmp_item.card[1]=0; + tmp_item.card[2]=GetWord(sd->status.char_id,0); // CharId + tmp_item.card[3]=GetWord(sd->status.char_id,1); + } + if(tmp_item.nameid <= 0 || tmp_item.amount <= 0) + continue; + if((flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) { + clif_additem(sd,0,0,flag); + map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } - for (i=0; i<MAX_SKILL_ARROW_DB; i++) - if (nameid == skill_arrow_db[i].nameid) { - index = i; - break; - } - - if (index < 0 || (j = pc_search_inventory(sd,nameid)) < 0) - return 1; - - pc_delitem(sd,j,1,0,0,LOG_TYPE_PRODUCE); - for (i=0; i<MAX_ARROW_RESOURCE; i++) { - memset(&tmp_item,0,sizeof(tmp_item)); - tmp_item.identify = 1; - tmp_item.nameid = skill_arrow_db[index].cre_id[i]; - tmp_item.amount = skill_arrow_db[index].cre_amount[i]; - if (battle_config.produce_item_name_input&0x4) { - tmp_item.card[0]=CARD0_CREATE; - tmp_item.card[1]=0; - tmp_item.card[2]=GetWord(sd->status.char_id,0); // CharId - tmp_item.card[3]=GetWord(sd->status.char_id,1); - } - if (tmp_item.nameid <= 0 || tmp_item.amount <= 0) - continue; - if ((flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) { - clif_additem(sd,0,0,flag); - map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - - return 0; + return 0; } -int skill_poisoningweapon(struct map_session_data *sd, int nameid) -{ - sc_type type; - int chance, i; - nullpo_ret(sd); - if (nameid <= 0 || (i = pc_search_inventory(sd,nameid)) < 0 || pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME)) { - clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); - return 0; - } - switch (nameid) { - // t_lv used to take duration from skill_get_time2 - case PO_PARALYSE: - type = SC_PARALYSE; - break; - case PO_PYREXIA: - type = SC_PYREXIA; - break; - case PO_DEATHHURT: - type = SC_DEATHHURT; - break; - case PO_LEECHESEND: - type = SC_LEECHESEND; - break; - case PO_VENOMBLEED: - type = SC_VENOMBLEED; - break; - case PO_TOXIN: - type = SC_TOXIN; - break; - case PO_MAGICMUSHROOM: - type = SC_MAGICMUSHROOM; - break; - case PO_OBLIVIONCURSE: - type = SC_OBLIVIONCURSE; - break; - default: - clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); - return 0; - } +int skill_poisoningweapon( struct map_session_data *sd, int nameid) { + sc_type type; + int chance, i; + nullpo_ret(sd); + if( nameid <= 0 || (i = pc_search_inventory(sd,nameid)) < 0 || pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) ) { + clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); + return 0; + } + switch( nameid ) + { // t_lv used to take duration from skill_get_time2 + case PO_PARALYSE: type = SC_PARALYSE; break; + case PO_PYREXIA: type = SC_PYREXIA; break; + case PO_DEATHHURT: type = SC_DEATHHURT; break; + case PO_LEECHESEND: type = SC_LEECHESEND; break; + case PO_VENOMBLEED: type = SC_VENOMBLEED; break; + case PO_TOXIN: type = SC_TOXIN; break; + case PO_MAGICMUSHROOM: type = SC_MAGICMUSHROOM; break; + case PO_OBLIVIONCURSE: type = SC_OBLIVIONCURSE; break; + default: + clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); + return 0; + } - chance = 2 + 2 * sd->menuskill_val; // 2 + 2 * skill_lv - sc_start4(&sd->bl, SC_POISONINGWEAPON, 100, pc_checkskill(sd, GC_RESEARCHNEWPOISON), //in Aegis it store the level of GC_RESEARCHNEWPOISON in val1 - type, chance, 0, skill_get_time(GC_POISONINGWEAPON, sd->menuskill_val)); + chance = 2 + 2 * sd->menuskill_val; // 2 + 2 * skill_lv + sc_start4(&sd->bl, SC_POISONINGWEAPON, 100, pc_checkskill(sd, GC_RESEARCHNEWPOISON), //in Aegis it store the level of GC_RESEARCHNEWPOISON in val1 + type, chance, 0, skill_get_time(GC_POISONINGWEAPON, sd->menuskill_val)); - return 0; + return 0; } static void skill_toggle_magicpower(struct block_list *bl, short skillid) { - struct status_change *sc = status_get_sc(bl); - - // non-offensive and non-magic skills do not affect the status - if (skill_get_nk(skillid)&NK_NO_DAMAGE || !(skill_get_type(skillid)&BF_MAGIC)) - return; - - if (sc && sc->count && sc->data[SC_MAGICPOWER]) { - if (sc->data[SC_MAGICPOWER]->val4) { - status_change_end(bl, SC_MAGICPOWER, INVALID_TIMER); - } else { - sc->data[SC_MAGICPOWER]->val4 = 1; - status_calc_bl(bl, status_sc2scb_flag(SC_MAGICPOWER)); -#ifndef RENEWAL - if(bl->type == BL_PC){// update current display. - clif_updatestatus(((TBL_PC *)bl),SP_MATK1); - clif_updatestatus(((TBL_PC *)bl),SP_MATK2); - } -#endif - } - } + struct status_change *sc = status_get_sc(bl); + + // non-offensive and non-magic skills do not affect the status + if (skill_get_nk(skillid)&NK_NO_DAMAGE || !(skill_get_type(skillid)&BF_MAGIC)) + return; + + if (sc && sc->count && sc->data[SC_MAGICPOWER]) + { + if (sc->data[SC_MAGICPOWER]->val4) + { + status_change_end(bl, SC_MAGICPOWER, INVALID_TIMER); + } + else + { + sc->data[SC_MAGICPOWER]->val4 = 1; + status_calc_bl(bl, status_sc2scb_flag(SC_MAGICPOWER)); + } + } } -int skill_magicdecoy(struct map_session_data *sd, int nameid) -{ - int x, y, i, class_, skill; - struct mob_data *md; - nullpo_ret(sd); - skill = sd->menuskill_val; - - if (nameid <= 0 || !itemdb_is_element(nameid) || (i = pc_search_inventory(sd,nameid)) < 0 || !skill || pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME)) { - clif_skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0); - return 0; - } - - // Spawn Position - pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); - x = sd->sc.comet_x; - y = sd->sc.comet_y; - sd->sc.comet_x = sd->sc.comet_y = 0; - sd->menuskill_val = 0; - - class_ = (nameid == 990 || nameid == 991) ? 2043 + nameid - 990 : (nameid == 992) ? 2046 : 2045; - - - md = mob_once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE); - if (md) { - md->master_id = sd->bl.id; - md->special_state.ai = AI_FLORA; - if (md->deletetimer != INVALID_TIMER) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer(gettick() + skill_get_time(NC_MAGICDECOY,skill), mob_timer_delete, md->bl.id, 0); - mob_spawn(md); - md->status.matk_min = md->status.matk_max = 250 + (50 * skill); - } - - return 0; +int skill_magicdecoy(struct map_session_data *sd, int nameid) { + int x, y, i, class_, skill; + struct mob_data *md; + nullpo_ret(sd); + skill = sd->menuskill_val; + + if( nameid <= 0 || !itemdb_is_element(nameid) || (i = pc_search_inventory(sd,nameid)) < 0 || !skill || pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) ) + { + clif_skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0); + return 0; + } + + // Spawn Position + pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); + x = sd->sc.comet_x; + y = sd->sc.comet_y; + sd->sc.comet_x = sd->sc.comet_y = 0; + sd->menuskill_val = 0; + + class_ = (nameid == 990 || nameid == 991) ? 2043 + nameid - 990 : (nameid == 992) ? 2046 : 2045; + + + md = mob_once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE); + if( md ) { + md->master_id = sd->bl.id; + md->special_state.ai = AI_FLORA; + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer (gettick() + skill_get_time(NC_MAGICDECOY,skill), mob_timer_delete, md->bl.id, 0); + mob_spawn(md); + md->status.matk_min = md->status.matk_max = 250 + (50 * skill); + } + + return 0; } // Warlock Spellbooks. [LimitLine/3CeAM] -int skill_spellbook(struct map_session_data *sd, int nameid) -{ - int i, max_preserve, skill_id, point; - struct status_change *sc; - - nullpo_ret(sd); - - sc = status_get_sc(&sd->bl); - status_change_end(&sd->bl, SC_STOP, INVALID_TIMER); - - for (i=SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) if (sc && !sc->data[i]) break; - if (i > SC_MAXSPELLBOOK) { - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); - return 0; - } - - ARR_FIND(0,MAX_SKILL_SPELLBOOK_DB,i,skill_spellbook_db[i].nameid == nameid); // Search for information of this item - if (i == MAX_SKILL_SPELLBOOK_DB) return 0; - - if (!pc_checkskill(sd, (skill_id = skill_spellbook_db[i].skillid))) { - // User don't know the skill - sc_start(&sd->bl, SC_SLEEP, 100, 1, skill_get_time(WL_READING_SB, pc_checkskill(sd,WL_READING_SB))); - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0); - return 0; - } - - max_preserve = 4 * pc_checkskill(sd, WL_FREEZE_SP) + status_get_int(&sd->bl) / 10 + sd->status.base_level / 10; - point = skill_spellbook_db[i].point; - - if (sc && sc->data[SC_READING_SB]) { - if ((sc->data[SC_READING_SB]->val2 + point) > max_preserve) { - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT, 0); - return 0; - } - for (i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) { // This is how official saves spellbook. [malufett] - if (!sc->data[i]) { - sc->data[SC_READING_SB]->val2 += point; // increase points - sc_start4(&sd->bl, (sc_type)i, 100, skill_id, pc_checkskill(sd,skill_id), point, 0, INVALID_TIMER); - break; - } - } - } else { - sc_start2(&sd->bl, SC_READING_SB, 100, 0, point, INVALID_TIMER); - sc_start4(&sd->bl, SC_MAXSPELLBOOK, 100, skill_id, pc_checkskill(sd,skill_id), point, 0, INVALID_TIMER); - } +int skill_spellbook (struct map_session_data *sd, int nameid) { + int i, max_preserve, skill_id, point; + struct status_change *sc; + + nullpo_ret(sd); + + sc = status_get_sc(&sd->bl); + status_change_end(&sd->bl, SC_STOP, INVALID_TIMER); + + for(i=SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) if( sc && !sc->data[i] ) break; + if( i > SC_MAXSPELLBOOK ) + { + clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); + return 0; + } + + ARR_FIND(0,MAX_SKILL_SPELLBOOK_DB,i,skill_spellbook_db[i].nameid == nameid); // Search for information of this item + if( i == MAX_SKILL_SPELLBOOK_DB ) return 0; - return 1; + if( !pc_checkskill(sd, (skill_id = skill_spellbook_db[i].skillid)) ) + { // User don't know the skill + sc_start(&sd->bl, SC_SLEEP, 100, 1, skill_get_time(WL_READING_SB, pc_checkskill(sd,WL_READING_SB))); + clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0); + return 0; + } + + max_preserve = 4 * pc_checkskill(sd, WL_FREEZE_SP) + status_get_int(&sd->bl) / 10 + sd->status.base_level / 10; + point = skill_spellbook_db[i].point; + + if( sc && sc->data[SC_READING_SB] ){ + if( (sc->data[SC_READING_SB]->val2 + point) > max_preserve ) + { + clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT, 0); + return 0; + } + for(i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--){ // This is how official saves spellbook. [malufett] + if( !sc->data[i] ){ + sc->data[SC_READING_SB]->val2 += point; // increase points + sc_start4(&sd->bl, (sc_type)i, 100, skill_id, pc_checkskill(sd,skill_id), point, 0, INVALID_TIMER); + break; + } + } + }else{ + sc_start2(&sd->bl, SC_READING_SB, 100, 0, point, INVALID_TIMER); + sc_start4(&sd->bl, SC_MAXSPELLBOOK, 100, skill_id, pc_checkskill(sd,skill_id), point, 0, INVALID_TIMER); + } + + return 1; } -int skill_select_menu(struct map_session_data *sd,int skill_id) -{ - int id, lv, prob, aslvl = 0; - nullpo_ret(sd); - - if (sd->sc.data[SC_STOP]) { - aslvl = sd->sc.data[SC_STOP]->val1; - status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); - } - - if (skill_id >= GS_GLITTERING || skill_get_type(skill_id) != BF_MAGIC || - (id = sd->status.skill[skill_id].id) == 0 || sd->status.skill[skill_id].flag != SKILL_FLAG_PLAGIARIZED) { - clif_skill_fail(sd,SC_AUTOSHADOWSPELL,0,0); - return 0; - } - - lv = (aslvl + 1) / 2; // The level the skill will be autocasted - lv = min(lv,sd->status.skill[skill_id].lv); - prob = (aslvl == 10) ? 15 : (32 - 2 * aslvl); // Probability at level 10 was increased to 15. - sc_start4(&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill_get_time(SC_AUTOSHADOWSPELL,aslvl)); - return 0; +int skill_select_menu(struct map_session_data *sd,int skill_id) { + int id, lv, prob, aslvl = 0; + nullpo_ret(sd); + + if (sd->sc.data[SC_STOP]) { + aslvl = sd->sc.data[SC_STOP]->val1; + status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); + } + + if( skill_id >= GS_GLITTERING || skill_get_type(skill_id) != BF_MAGIC || + (id = sd->status.skill[skill_id].id) == 0 || sd->status.skill[skill_id].flag != SKILL_FLAG_PLAGIARIZED ) { + clif_skill_fail(sd,SC_AUTOSHADOWSPELL,0,0); + return 0; + } + + lv = (aslvl + 1) / 2; // The level the skill will be autocasted + lv = min(lv,sd->status.skill[skill_id].lv); + prob = (aslvl == 10) ? 15 : (32 - 2 * aslvl); // Probability at level 10 was increased to 15. + sc_start4(&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill_get_time(SC_AUTOSHADOWSPELL,aslvl)); + return 0; } -int skill_elementalanalysis(struct map_session_data *sd, int n, int skill_lv, unsigned short *item_list) -{ - int i; - - nullpo_ret(sd); - nullpo_ret(item_list); - - if (n <= 0) - return 1; - - for (i = 0; i < n; i++) { - int nameid, add_amount, del_amount, idx, product, flag; - struct item tmp_item; - - idx = item_list[i*2+0]-2; - del_amount = item_list[i*2+1]; - - if (skill_lv == 2) - del_amount -= (del_amount % 10); - add_amount = (skill_lv == 1) ? del_amount * (5 + rnd()%5) : del_amount / 10 ; - - if ((nameid = sd->status.inventory[idx].nameid) <= 0 || del_amount > sd->status.inventory[idx].amount) { - clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); - return 1; - } - - switch (nameid) { - // Level 1 - case 994: - product = 990; - break; // Flame Heart -> Red Blood. - case 995: - product = 991; - break; // Mystic Frozen -> Crystal Blue. - case 996: - product = 992; - break; // Rough Wind -> Wind of Verdure. - case 997: - product = 993; - break; // Great Nature -> Green Live. - // Level 2 - case 990: - product = 994; - break; // Red Blood -> Flame Heart. - case 991: - product = 995; - break; // Crystal Blue -> Mystic Frozen. - case 992: - product = 996; - break; // Wind of Verdure -> Rough Wind. - case 993: - product = 997; - break; // Green Live -> Great Nature. - default: - clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); - return 1; - } - - if (pc_delitem(sd,idx,del_amount,0,1,LOG_TYPE_CONSUME)) { - clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); - return 1; - } - - if (skill_lv == 2 && rnd()%100 < 25) { // At level 2 have a fail chance. You loose your items if it fails. - clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); - return 1; - } - - - memset(&tmp_item,0,sizeof(tmp_item)); - tmp_item.nameid = product; - tmp_item.amount = add_amount; - tmp_item.identify = 1; - - if (tmp_item.amount) { - if ((flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_CONSUME))) { - clif_additem(sd,0,0,flag); - map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } +int skill_elementalanalysis(struct map_session_data* sd, int n, int skill_lv, unsigned short* item_list) { + int i; + + nullpo_ret(sd); + nullpo_ret(item_list); + + if( n <= 0 ) + return 1; + + for( i = 0; i < n; i++ ) { + int nameid, add_amount, del_amount, idx, product, flag; + struct item tmp_item; + + idx = item_list[i*2+0]-2; + del_amount = item_list[i*2+1]; + + if( skill_lv == 2 ) + del_amount -= (del_amount % 10); + add_amount = (skill_lv == 1) ? del_amount * (5 + rnd()%5) : del_amount / 10 ; + + if( (nameid = sd->status.inventory[idx].nameid) <= 0 || del_amount > sd->status.inventory[idx].amount ) { + clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); + return 1; + } + + switch( nameid ) { + // Level 1 + case 994: product = 990; break; // Flame Heart -> Red Blood. + case 995: product = 991; break; // Mystic Frozen -> Crystal Blue. + case 996: product = 992; break; // Rough Wind -> Wind of Verdure. + case 997: product = 993; break; // Great Nature -> Green Live. + // Level 2 + case 990: product = 994; break; // Red Blood -> Flame Heart. + case 991: product = 995; break; // Crystal Blue -> Mystic Frozen. + case 992: product = 996; break; // Wind of Verdure -> Rough Wind. + case 993: product = 997; break; // Green Live -> Great Nature. + default: + clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); + return 1; + } + + if( pc_delitem(sd,idx,del_amount,0,1,LOG_TYPE_CONSUME) ) { + clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); + return 1; + } + + if( skill_lv == 2 && rnd()%100 < 25 ) { // At level 2 have a fail chance. You loose your items if it fails. + clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); + return 1; + } + + + memset(&tmp_item,0,sizeof(tmp_item)); + tmp_item.nameid = product; + tmp_item.amount = add_amount; + tmp_item.identify = 1; + + if( tmp_item.amount ) { + if( (flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_CONSUME)) ) { + clif_additem(sd,0,0,flag); + map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } - } + } - return 0; + return 0; } -int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list) -{ - int i, j, k, c, p = 0, nameid, amount; - - nullpo_ret(sd); - nullpo_ret(item_list); - - // Search for objects that can be created. - for (i = 0; i < MAX_SKILL_PRODUCE_DB; i++) { - if (skill_produce_db[i].itemlv == 26) { - p = 0; - do { - c = 0; - // Verification of overlap between the objects required and the list submitted. - for (j = 0; j < MAX_PRODUCE_RESOURCE; j++) { - if (skill_produce_db[i].mat_id[j] > 0) { - for (k = 0; k < n; k++) { - int idx = item_list[k*2+0]-2; - nameid = sd->status.inventory[idx].nameid; - amount = item_list[k*2+1]; - if (nameid > 0 && sd->status.inventory[idx].identify == 0) { - clif_msg_skill(sd,GN_CHANGEMATERIAL,0x62D); - return 0; - } - if (nameid == skill_produce_db[i].mat_id[j] && (amount-p*skill_produce_db[i].mat_amount[j]) >= skill_produce_db[i].mat_amount[j] - && (amount-p*skill_produce_db[i].mat_amount[j])%skill_produce_db[i].mat_amount[j] == 0) // must be in exact amount - c++; // match - } - } else - break; // No more items required - } - p++; - } while (n == j && c == n); - p--; - if (p > 0) { - skill_produce_mix(sd,GN_CHANGEMATERIAL,skill_produce_db[i].nameid,0,0,0,p); - return 1; - } - } - } +int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list) { + int i, j, k, c, p = 0, nameid, amount; + + nullpo_ret(sd); + nullpo_ret(item_list); + + // Search for objects that can be created. + for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) { + if( skill_produce_db[i].itemlv == 26 ) { + p = 0; + do { + c = 0; + // Verification of overlap between the objects required and the list submitted. + for( j = 0; j < MAX_PRODUCE_RESOURCE; j++ ) { + if( skill_produce_db[i].mat_id[j] > 0 ) { + for( k = 0; k < n; k++ ) { + int idx = item_list[k*2+0]-2; + nameid = sd->status.inventory[idx].nameid; + amount = item_list[k*2+1]; + if( nameid > 0 && sd->status.inventory[idx].identify == 0 ){ + clif_msg_skill(sd,GN_CHANGEMATERIAL,0x62D); + return 0; + } + if( nameid == skill_produce_db[i].mat_id[j] && (amount-p*skill_produce_db[i].mat_amount[j]) >= skill_produce_db[i].mat_amount[j] + && (amount-p*skill_produce_db[i].mat_amount[j])%skill_produce_db[i].mat_amount[j] == 0 ) // must be in exact amount + c++; // match + } + } + else + break; // No more items required + } + p++; + } while(n == j && c == n); + p--; + if ( p > 0 ) { + skill_produce_mix(sd,GN_CHANGEMATERIAL,skill_produce_db[i].nameid,0,0,0,p); + return 1; + } + } + } - if (p == 0) - clif_msg_skill(sd,GN_CHANGEMATERIAL,0x623); + if( p == 0) + clif_msg_skill(sd,GN_CHANGEMATERIAL,0x623); - return 0; + return 0; } /** * for Royal Guard's LG_TRAMPLE **/ -static int skill_destroy_trap(struct block_list *bl, va_list ap) -{ - struct skill_unit *su = (struct skill_unit *)bl; - struct skill_unit_group *sg; - unsigned int tick; - - nullpo_ret(su); - tick = va_arg(ap, unsigned int); - - if (su->alive && (sg = su->group) && skill_get_inf2(sg->skill_id)&INF2_TRAP) { - switch (sg->unit_id) { - case UNT_LANDMINE: - case UNT_CLAYMORETRAP: - case UNT_BLASTMINE: - case UNT_SHOCKWAVE: - case UNT_SANDMAN: - case UNT_FLASHER: - case UNT_FREEZINGTRAP: - case UNT_CLUSTERBOMB: - case UNT_FIRINGTRAP: - case UNT_ICEBOUNDTRAP: - map_foreachinrange(skill_trap_splash,&su->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick); - break; - } - // Traps aren't recovered. - skill_delunit(su); - } - return 0; +static int skill_destroy_trap( struct block_list *bl, va_list ap ) { + struct skill_unit *su = (struct skill_unit *)bl; + struct skill_unit_group *sg; + unsigned int tick; + + nullpo_ret(su); + tick = va_arg(ap, unsigned int); + + if (su->alive && (sg = su->group) && skill_get_inf2(sg->skill_id)&INF2_TRAP) { + switch( sg->unit_id ) { + case UNT_LANDMINE: + case UNT_CLAYMORETRAP: + case UNT_BLASTMINE: + case UNT_SHOCKWAVE: + case UNT_SANDMAN: + case UNT_FLASHER: + case UNT_FREEZINGTRAP: + case UNT_CLUSTERBOMB: + case UNT_FIRINGTRAP: + case UNT_ICEBOUNDTRAP: + map_foreachinrange(skill_trap_splash,&su->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick); + break; + } + // Traps aren't recovered. + skill_delunit(su); + } + return 0; } /*========================================== * *------------------------------------------*/ int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd = map_id2sd(id); - struct skill_cd *cd = NULL; - - if (data <= 0 || data >= MAX_SKILL) - return 0; - if (!sd) return 0; - if (sd->blockskill[data] != (0x1|(tid&0xFE))) return 0; - - if ((cd = idb_get(skillcd_db,sd->status.char_id))) { - int i,cursor; - ARR_FIND(0, cd->cursor+1, cursor, cd->skidx[cursor] == data); - cd->duration[cursor] = 0; - cd->skidx[cursor] = 0; - cd->nameid[cursor] = 0; - // compact the cool down list - for (i = 0, cursor = 0; i < cd->cursor; i++) { - if (cd->duration[i] == 0) - continue; - if (cursor != i) { - cd->duration[cursor] = cd->duration[i]; - cd->skidx[cursor] = cd->skidx[i]; - cd->nameid[cursor] = cd->nameid[i]; - } - cursor++; - } - if (cursor == 0) - idb_remove(skillcd_db,sd->status.char_id); - else - cd->cursor = cursor; - } - - sd->blockskill[data] = 0; - return 1; + struct map_session_data *sd = map_id2sd(id); + struct skill_cd * cd = NULL; + + if (data <= 0 || data >= MAX_SKILL) + return 0; + if (!sd) return 0; + if (sd->blockskill[data] != (0x1|(tid&0xFE))) return 0; + + if( ( cd = idb_get(skillcd_db,sd->status.char_id) ) ) { + int i,cursor; + ARR_FIND( 0, cd->cursor+1, cursor, cd->skidx[cursor] == data ); + cd->duration[cursor] = 0; + cd->skidx[cursor] = 0; + cd->nameid[cursor] = 0; + // compact the cool down list + for( i = 0, cursor = 0; i < cd->cursor; i++ ) { + if( cd->duration[i] == 0 ) + continue; + if( cursor != i ) { + cd->duration[cursor] = cd->duration[i]; + cd->skidx[cursor] = cd->skidx[i]; + cd->nameid[cursor] = cd->nameid[i]; + } + cursor++; + } + if( cursor == 0 ) + idb_remove(skillcd_db,sd->status.char_id); + else + cd->cursor = cursor; + } + + sd->blockskill[data] = 0; + return 1; } /** @@ -16943,675 +16789,565 @@ int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) */ int skill_blockpc_start_(struct map_session_data *sd, int skillid, int tick, bool load) { - int oskillid = skillid; - struct skill_cd *cd = NULL; - - nullpo_retr(-1, sd); - - skillid = skill_get_index(skillid); - if (skillid == 0) - return -1; - - if (tick < 1) { - sd->blockskill[skillid] = 0; - return -1; - } - - if (battle_config.display_status_timers) - clif_skill_cooldown(sd, skillid, tick); - - if (!load) { - // not being loaded initially so ensure the skill delay is recorded - if (!(cd = idb_get(skillcd_db,sd->status.char_id))) { - // create a new skill cooldown object for map storage - CREATE(cd, struct skill_cd, 1); - idb_put(skillcd_db, sd->status.char_id, cd); - } - - // record the skill duration in the database map - cd->duration[cd->cursor] = tick; - cd->skidx[cd->cursor] = skillid; - cd->nameid[cd->cursor] = oskillid; - cd->cursor++; - } - - sd->blockskill[skillid] = 0x1|(0xFE&add_timer(gettick()+tick,skill_blockpc_end,sd->bl.id,skillid)); - return 0; + int oskillid = skillid; + struct skill_cd* cd = NULL; + + nullpo_retr (-1, sd); + + skillid = skill_get_index(skillid); + if (skillid == 0) + return -1; + + if (tick < 1) { + sd->blockskill[skillid] = 0; + return -1; + } + + if( battle_config.display_status_timers ) + clif_skill_cooldown(sd, skillid, tick); + + if( !load ) + {// not being loaded initially so ensure the skill delay is recorded + if( !(cd = idb_get(skillcd_db,sd->status.char_id)) ) + {// create a new skill cooldown object for map storage + CREATE( cd, struct skill_cd, 1 ); + idb_put( skillcd_db, sd->status.char_id, cd ); + } + + // record the skill duration in the database map + cd->duration[cd->cursor] = tick; + cd->skidx[cd->cursor] = skillid; + cd->nameid[cd->cursor] = oskillid; + cd->cursor++; + } + + sd->blockskill[skillid] = 0x1|(0xFE&add_timer(gettick()+tick,skill_blockpc_end,sd->bl.id,skillid)); + return 0; } -int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) //[orn] +int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) //[orn] { - struct homun_data *hd = (TBL_HOM *) map_id2bl(id); - if (data <= 0 || data >= MAX_SKILL) - return 0; - if (hd) hd->blockskill[data] = 0; + struct homun_data *hd = (TBL_HOM*) map_id2bl(id); + if (data <= 0 || data >= MAX_SKILL) + return 0; + if (hd) hd->blockskill[data] = 0; - return 1; + return 1; } -int skill_blockhomun_start(struct homun_data *hd, int skillid, int tick) //[orn] +int skill_blockhomun_start(struct homun_data *hd, int skillid, int tick) //[orn] { - nullpo_retr(-1, hd); - - skillid = skill_get_index(skillid); - if (skillid == 0) - return -1; - - if (tick < 1) { - hd->blockskill[skillid] = 0; - return -1; - } - hd->blockskill[skillid] = 1; - return add_timer(gettick() + tick, skill_blockhomun_end, hd->bl.id, skillid); + nullpo_retr (-1, hd); + + skillid = skill_get_index(skillid); + if (skillid == 0) + return -1; + + if (tick < 1) { + hd->blockskill[skillid] = 0; + return -1; + } + hd->blockskill[skillid] = 1; + return add_timer(gettick() + tick, skill_blockhomun_end, hd->bl.id, skillid); } -int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr_t data) //[orn] +int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr_t data) //[orn] { - struct mercenary_data *md = (TBL_MER *)map_id2bl(id); - if (data <= 0 || data >= MAX_SKILL) - return 0; - if (md) md->blockskill[data] = 0; + struct mercenary_data *md = (TBL_MER*)map_id2bl(id); + if( data <= 0 || data >= MAX_SKILL ) + return 0; + if( md ) md->blockskill[data] = 0; - return 1; + return 1; } int skill_blockmerc_start(struct mercenary_data *md, int skillid, int tick) { - nullpo_retr(-1, md); - - if ((skillid = skill_get_index(skillid)) == 0) - return -1; - if (tick < 1) { - md->blockskill[skillid] = 0; - return -1; - } - md->blockskill[skillid] = 1; - return add_timer(gettick() + tick, skill_blockmerc_end, md->bl.id, skillid); + nullpo_retr (-1, md); + + if( (skillid = skill_get_index(skillid)) == 0 ) + return -1; + if( tick < 1 ) + { + md->blockskill[skillid] = 0; + return -1; + } + md->blockskill[skillid] = 1; + return add_timer(gettick() + tick, skill_blockmerc_end, md->bl.id, skillid); } /** * Adds a new skill unit entry for this player to recast after map load **/ -void skill_usave_add(struct map_session_data *sd, int skill_num, int skill_lv) -{ - struct skill_usave *sus = NULL; +void skill_usave_add(struct map_session_data * sd, int skill_num, int skill_lv) { + struct skill_usave * sus = NULL; - if (idb_exists(skillusave_db,sd->status.char_id)) { - idb_remove(skillusave_db,sd->status.char_id); - } + if( idb_exists(skillusave_db,sd->status.char_id) ) { + idb_remove(skillusave_db,sd->status.char_id); + } - CREATE(sus, struct skill_usave, 1); - idb_put(skillusave_db, sd->status.char_id, sus); + CREATE( sus, struct skill_usave, 1 ); + idb_put( skillusave_db, sd->status.char_id, sus ); - sus->skill_num = skill_num; - sus->skill_lv = skill_lv; + sus->skill_num = skill_num; + sus->skill_lv = skill_lv; - return; + return; } -void skill_usave_trigger(struct map_session_data *sd) -{ - struct skill_usave *sus = NULL; +void skill_usave_trigger(struct map_session_data *sd) { + struct skill_usave * sus = NULL; - if (!(sus = idb_get(skillusave_db,sd->status.char_id))) { - return; - } + if( ! (sus = idb_get(skillusave_db,sd->status.char_id)) ) { + return; + } - skill_unitsetting(&sd->bl,sus->skill_num,sus->skill_lv,sd->bl.x,sd->bl.y,0); + skill_unitsetting(&sd->bl,sus->skill_num,sus->skill_lv,sd->bl.x,sd->bl.y,0); - idb_remove(skillusave_db,sd->status.char_id); + idb_remove(skillusave_db,sd->status.char_id); - return; + return; } /* * */ -int skill_split_str(char *str, char **val, int num) +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; - } + int i; + + for( i = 0; i < num && str; i++ ) + { + val[i] = str; + str = strchr(str,','); + if( str ) + *str++=0; + } - return i; + return i; } /* * */ -int skill_split_atoi(char *str, int *val) +int skill_split_atoi (char *str, int *val) { - int i, j, diff, step = 1; - - for (i=0; i<MAX_SKILL_LEVEL; i++) { - if (!str) break; - val[i] = atoi(str); - str = strchr(str,':'); - if (str) - *str++=0; - } - if (i==0) //No data found. - return 0; - if (i==1) { - //Single value, have the whole range have the same value. - for (; i < MAX_SKILL_LEVEL; i++) - val[i] = val[i-1]; - return i; - } - //Check for linear change with increasing steps until we reach half of the data acquired. - for (step = 1; step <= i/2; step++) { - diff = val[i-1] - val[i-step-1]; - for (j = i-1; j >= step; j--) - if ((val[j]-val[j-step]) != diff) - break; - - if (j>=step) //No match, try next step. - continue; - - for (; i < MAX_SKILL_LEVEL; i++) { - //Apply linear increase - val[i] = val[i-step]+diff; - if (val[i] < 1 && val[i-1] >=0) { //Check if we have switched from + to -, cap the decrease to 0 in said cases. - val[i] = 1; - diff = 0; - step = 1; - } - } - return i; - } - //Okay.. we can't figure this one out, just fill out the stuff with the previous value. - for (; i<MAX_SKILL_LEVEL; i++) - val[i] = val[i-1]; - return i; + int i, j, diff, step = 1; + + for (i=0; i<MAX_SKILL_LEVEL; i++) { + if (!str) break; + val[i] = atoi(str); + str = strchr(str,':'); + if (str) + *str++=0; + } + if(i==0) //No data found. + return 0; + if(i==1) + { //Single value, have the whole range have the same value. + for (; i < MAX_SKILL_LEVEL; i++) + val[i] = val[i-1]; + return i; + } + //Check for linear change with increasing steps until we reach half of the data acquired. + for (step = 1; step <= i/2; step++) + { + diff = val[i-1] - val[i-step-1]; + for(j = i-1; j >= step; j--) + if ((val[j]-val[j-step]) != diff) + break; + + if (j>=step) //No match, try next step. + continue; + + for(; i < MAX_SKILL_LEVEL; i++) + { //Apply linear increase + val[i] = val[i-step]+diff; + if (val[i] < 1 && val[i-1] >=0) //Check if we have switched from + to -, cap the decrease to 0 in said cases. + { val[i] = 1; diff = 0; step = 1; } + } + return i; + } + //Okay.. we can't figure this one out, just fill out the stuff with the previous value. + for (;i<MAX_SKILL_LEVEL; i++) + val[i] = val[i-1]; + return i; } /* * */ -void skill_init_unit_layout(void) +void skill_init_unit_layout (void) { - int i,j,size,pos = 0; - - memset(skill_unit_layout,0,sizeof(skill_unit_layout)); - - // standard square layouts go first - 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); - } - } - - // afterwards add special ones - pos = i; - for (i=0; i<MAX_SKILL_DB; i++) { - if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1) - continue; - if (i >= HM_SKILLRANGEMIN && i <= EL_SKILLRANGEMAX) { - int skill = i; - - if (i >= EL_SKILLRANGEMIN && i <= EL_SKILLRANGEMAX) { - skill -= EL_SKILLRANGEMIN; - skill += EL_SKILLBASE; - } - if (skill == EL_FIRE_MANTLE) { - static const int dx[] = {-1, 0, 1, 1, 1, 0,-1,-1}; - static const int dy[] = { 1, 1, 1, 0,-1,-1,-1, 0}; - skill_unit_layout[pos].count = 8; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - } else { - switch (i) { - case MG_FIREWALL: - case WZ_ICEWALL: - case WL_EARTHSTRAIN://Warlock - // these will be handled later - break; - case PR_SANCTUARY: - case NPC_EVILLAND: { - 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 MH_POISON_MIST: - 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_GRANDDARKNESS: { - 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; - case NJ_KAENSIN: { - static const int dx[] = {-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; - static const int dy[] = { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2}; - skill_unit_layout[pos].count = 24; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - case NJ_TATAMIGAESHI: { - //Level 1 (count 4, cross of 3x3) - static const int dx1[] = {-1, 1, 0, 0}; - static const int dy1[] = { 0, 0,-1, 1}; - //Level 2-3 (count 8, cross of 5x5) - static const int dx2[] = {-2,-1, 1, 2, 0, 0, 0, 0}; - static const int dy2[] = { 0, 0, 0, 0,-2,-1, 1, 2}; - //Level 4-5 (count 12, cross of 7x7 - static const int dx3[] = {-3,-2,-1, 1, 2, 3, 0, 0, 0, 0, 0, 0}; - static const int dy3[] = { 0, 0, 0, 0, 0, 0,-3,-2,-1, 1, 2, 3}; - //lv1 - j = 0; - skill_unit_layout[pos].count = 4; - memcpy(skill_unit_layout[pos].dx,dx1,sizeof(dx1)); - memcpy(skill_unit_layout[pos].dy,dy1,sizeof(dy1)); - skill_db[i].unit_layout_type[j] = pos; - //lv2/3 - j++; - pos++; - skill_unit_layout[pos].count = 8; - memcpy(skill_unit_layout[pos].dx,dx2,sizeof(dx2)); - memcpy(skill_unit_layout[pos].dy,dy2,sizeof(dy2)); - skill_db[i].unit_layout_type[j] = pos; - skill_db[i].unit_layout_type[++j] = pos; - //lv4/5 - j++; - pos++; - skill_unit_layout[pos].count = 12; - memcpy(skill_unit_layout[pos].dx,dx3,sizeof(dx3)); - memcpy(skill_unit_layout[pos].dy,dy3,sizeof(dy3)); - skill_db[i].unit_layout_type[j] = pos; - skill_db[i].unit_layout_type[++j] = pos; - //Fill in the rest using lv 5. - for (; j<MAX_SKILL_LEVEL; j++) - skill_db[i].unit_layout_type[j] = pos; - //Skip, this way the check below will fail and continue to the next skill. - pos++; - } - break; - case GN_WALLOFTHORN: { - static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0}; - static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2}; - skill_unit_layout[pos].count = 16; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - default: - ShowError("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++; - } - - // firewall and icewall have 8 layouts (direction-dependent) - firewall_unit_pos = pos; - for (i=0; i<8; i++) { - if (i&1) { - 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 { - 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 { - 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++; - } - icewall_unit_pos = pos; - for (i=0; i<8; i++) { - skill_unit_layout[pos].count = 5; - if (i&1) { - 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 { - 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 { - 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++; - } - earthstrain_unit_pos = pos; - for (i = 0; i < 8; i++) { - // For each Direction - skill_unit_layout[pos].count = 15; - switch (i) { - case 0: - case 1: - case 3: - case 4: - case 5: - case 7: { - int dx[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}; - int dy[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - case 2: - case 6: { - int dx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - int dy[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - } - pos++; - } + int i,j,size,pos = 0; + + memset(skill_unit_layout,0,sizeof(skill_unit_layout)); + + // standard square layouts go first + 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); + } + } + + // afterwards add special ones + pos = i; + for (i=0;i<MAX_SKILL_DB;i++) { + if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1) + continue; + if( i >= HM_SKILLRANGEMIN && i <= EL_SKILLRANGEMAX ) { + int skill = i; + + if( i >= EL_SKILLRANGEMIN && i <= EL_SKILLRANGEMAX ) { + skill -= EL_SKILLRANGEMIN; + skill += EL_SKILLBASE; + } + if( skill == EL_FIRE_MANTLE ) { + static const int dx[] = {-1, 0, 1, 1, 1, 0,-1,-1}; + static const int dy[] = { 1, 1, 1, 0,-1,-1,-1, 0}; + skill_unit_layout[pos].count = 8; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } else { + switch (i) { + case MG_FIREWALL: + case WZ_ICEWALL: + case WL_EARTHSTRAIN://Warlock + // these will be handled later + break; + case PR_SANCTUARY: + case NPC_EVILLAND: { + 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 MH_POISON_MIST: + 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_GRANDDARKNESS: { + 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; + case NJ_KAENSIN: { + static const int dx[] = {-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; + static const int dy[] = { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2}; + skill_unit_layout[pos].count = 24; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + case NJ_TATAMIGAESHI: { + //Level 1 (count 4, cross of 3x3) + static const int dx1[] = {-1, 1, 0, 0}; + static const int dy1[] = { 0, 0,-1, 1}; + //Level 2-3 (count 8, cross of 5x5) + static const int dx2[] = {-2,-1, 1, 2, 0, 0, 0, 0}; + static const int dy2[] = { 0, 0, 0, 0,-2,-1, 1, 2}; + //Level 4-5 (count 12, cross of 7x7 + static const int dx3[] = {-3,-2,-1, 1, 2, 3, 0, 0, 0, 0, 0, 0}; + static const int dy3[] = { 0, 0, 0, 0, 0, 0,-3,-2,-1, 1, 2, 3}; + //lv1 + j = 0; + skill_unit_layout[pos].count = 4; + memcpy(skill_unit_layout[pos].dx,dx1,sizeof(dx1)); + memcpy(skill_unit_layout[pos].dy,dy1,sizeof(dy1)); + skill_db[i].unit_layout_type[j] = pos; + //lv2/3 + j++; + pos++; + skill_unit_layout[pos].count = 8; + memcpy(skill_unit_layout[pos].dx,dx2,sizeof(dx2)); + memcpy(skill_unit_layout[pos].dy,dy2,sizeof(dy2)); + skill_db[i].unit_layout_type[j] = pos; + skill_db[i].unit_layout_type[++j] = pos; + //lv4/5 + j++; + pos++; + skill_unit_layout[pos].count = 12; + memcpy(skill_unit_layout[pos].dx,dx3,sizeof(dx3)); + memcpy(skill_unit_layout[pos].dy,dy3,sizeof(dy3)); + skill_db[i].unit_layout_type[j] = pos; + skill_db[i].unit_layout_type[++j] = pos; + //Fill in the rest using lv 5. + for (;j<MAX_SKILL_LEVEL;j++) + skill_db[i].unit_layout_type[j] = pos; + //Skip, this way the check below will fail and continue to the next skill. + pos++; + } + break; + case GN_WALLOFTHORN: { + static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0}; + static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2}; + skill_unit_layout[pos].count = 16; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + default: + ShowError("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++; + } + + // firewall and icewall have 8 layouts (direction-dependent) + firewall_unit_pos = pos; + for (i=0;i<8;i++) { + if (i&1) { + 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 { + 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 { + 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++; + } + icewall_unit_pos = pos; + for (i=0;i<8;i++) { + skill_unit_layout[pos].count = 5; + if (i&1) { + 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 { + 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 { + 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++; + } + earthstrain_unit_pos = pos; + for( i = 0; i < 8; i++ ) + { // For each Direction + skill_unit_layout[pos].count = 15; + switch( i ) + { + case 0: case 1: case 3: case 4: case 5: case 7: + { + int dx[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}; + int dy[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + case 2: + case 6: + { + int dx[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int dy[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + } + pos++; + } } -int skill_block_check(struct block_list *bl, sc_type type , int skillid) -{ - int inf = 0; - struct status_change *sc = status_get_sc(bl); - - if (!sc || !bl || skillid < 1) - return 0; // Can do it - - switch (type) { - case SC_STASIS: - inf = skill_get_inf2(skillid); - if (inf == INF2_SONG_DANCE || /*skill_get_inf2(skillid) == INF2_CHORUS_SKILL ||*/ inf == INF2_SPIRIT_SKILL) - return 1; // Can't do it. - switch (skillid) { - case NV_FIRSTAID: - case TF_HIDING: - case AS_CLOAKING: - case WZ_SIGHTRASHER: - case RG_STRIPWEAPON: - case RG_STRIPSHIELD: - case RG_STRIPARMOR: - case WZ_METEOR: - case RG_STRIPHELM: - case SC_STRIPACCESSARY: - case ST_FULLSTRIP: - case WZ_SIGHTBLASTER: - case ST_CHASEWALK: - case SC_ENERVATION: - case SC_GROOMY: - case WZ_ICEWALL: - case SC_IGNORANCE: - case SC_LAZINESS: - case SC_UNLUCKY: - case WZ_STORMGUST: - case SC_WEAKNESS: - case AL_RUWACH: - case AL_PNEUMA: - case WZ_JUPITEL: - case AL_HEAL: - case AL_BLESSING: - case AL_INCAGI: - case WZ_VERMILION: - case AL_TELEPORT: - case AL_WARP: - case AL_HOLYWATER: - case WZ_EARTHSPIKE: - case AL_HOLYLIGHT: - case PR_IMPOSITIO: - case PR_ASPERSIO: - case WZ_HEAVENDRIVE: - case PR_SANCTUARY: - case PR_STRECOVERY: - case PR_MAGNIFICAT: - case WZ_QUAGMIRE: - case ALL_RESURRECTION: - case PR_LEXDIVINA: - case PR_LEXAETERNA: - case HW_GRAVITATION: - case PR_MAGNUS: - case PR_TURNUNDEAD: - case MG_SRECOVERY: - case HW_MAGICPOWER: - case MG_SIGHT: - case MG_NAPALMBEAT: - case MG_SAFETYWALL: - case HW_GANBANTEIN: - case MG_SOULSTRIKE: - case MG_COLDBOLT: - case MG_FROSTDIVER: - case WL_DRAINLIFE: - case MG_STONECURSE: - case MG_FIREBALL: - case MG_FIREWALL: - case WL_SOULEXPANSION: - case MG_FIREBOLT: - case MG_LIGHTNINGBOLT: - case MG_THUNDERSTORM: - case MG_ENERGYCOAT: - case WL_WHITEIMPRISON: - case WL_SUMMONFB: - case WL_SUMMONBL: - case WL_SUMMONWB: - case WL_SUMMONSTONE: - case WL_SIENNAEXECRATE: - case WL_RELEASE: - case WL_EARTHSTRAIN: - case WL_RECOGNIZEDSPELL: - case WL_READING_SB: - case SA_MAGICROD: - case SA_SPELLBREAKER: - case SA_DISPELL: - case SA_FLAMELAUNCHER: - case SA_FROSTWEAPON: - case SA_LIGHTNINGLOADER: - case SA_SEISMICWEAPON: - case SA_VOLCANO: - case SA_DELUGE: - case SA_VIOLENTGALE: - case SA_LANDPROTECTOR: - case PF_HPCONVERSION: - case PF_SOULCHANGE: - case PF_SPIDERWEB: - case PF_FOGWALL: - case TK_RUN: - case TK_HIGHJUMP: - case TK_SEVENWIND: - case SL_KAAHI: - case SL_KAUPE: - case SL_KAITE: - - // Skills that need to be confirmed. - case SO_FIREWALK: - case SO_ELECTRICWALK: - case SO_SPELLFIST: - case SO_EARTHGRAVE: - case SO_DIAMONDDUST: - case SO_POISON_BUSTER: - case SO_PSYCHIC_WAVE: - case SO_CLOUD_KILL: - case SO_STRIKING: - case SO_WARMER: - case SO_VACUUM_EXTREME: - case SO_VARETYR_SPEAR: - case SO_ARRULLO: - return 1; // Can't do it. - } - break; - case SC_KAGEHUMI: - switch (skillid) { - case TF_HIDING: - case AS_CLOAKING: - case GC_CLOAKINGEXCEED: - case SC_SHADOWFORM: - case MI_HARMONIZE: - case CG_MARIONETTE: - case AL_TELEPORT: - case TF_BACKSLIDING: - case RA_CAMOUFLAGE: - case ST_CHASEWALK: - case GD_EMERGENCYCALL: - return 1; // needs more info - } - break; - } +int skill_block_check(struct block_list *bl, sc_type type , int skillid) { + int inf = 0; + struct status_change *sc = status_get_sc(bl); + + if( !sc || !bl || skillid < 1 ) + return 0; // Can do it + + switch(type){ + case SC_STASIS: + inf = skill_get_inf2(skillid); + if( inf == INF2_SONG_DANCE || /*skill_get_inf2(skillid) == INF2_CHORUS_SKILL ||*/ inf == INF2_SPIRIT_SKILL ) + return 1; // Can't do it. + switch( skillid ) + { + case NV_FIRSTAID: case TF_HIDING: case AS_CLOAKING: case WZ_SIGHTRASHER: + case RG_STRIPWEAPON: case RG_STRIPSHIELD: case RG_STRIPARMOR: case WZ_METEOR: + case RG_STRIPHELM: case SC_STRIPACCESSARY: case ST_FULLSTRIP: case WZ_SIGHTBLASTER: + case ST_CHASEWALK: case SC_ENERVATION: case SC_GROOMY: case WZ_ICEWALL: + case SC_IGNORANCE: case SC_LAZINESS: case SC_UNLUCKY: case WZ_STORMGUST: + case SC_WEAKNESS: case AL_RUWACH: case AL_PNEUMA: case WZ_JUPITEL: + case AL_HEAL: case AL_BLESSING: case AL_INCAGI: case WZ_VERMILION: + case AL_TELEPORT: case AL_WARP: case AL_HOLYWATER: case WZ_EARTHSPIKE: + case AL_HOLYLIGHT: case PR_IMPOSITIO: case PR_ASPERSIO: case WZ_HEAVENDRIVE: + case PR_SANCTUARY: case PR_STRECOVERY: case PR_MAGNIFICAT: case WZ_QUAGMIRE: + case ALL_RESURRECTION: case PR_LEXDIVINA: case PR_LEXAETERNA: case HW_GRAVITATION: + case PR_MAGNUS: case PR_TURNUNDEAD: case MG_SRECOVERY: case HW_MAGICPOWER: + case MG_SIGHT: case MG_NAPALMBEAT: case MG_SAFETYWALL: case HW_GANBANTEIN: + case MG_SOULSTRIKE: case MG_COLDBOLT: case MG_FROSTDIVER: case WL_DRAINLIFE: + case MG_STONECURSE: case MG_FIREBALL: case MG_FIREWALL: case WL_SOULEXPANSION: + case MG_FIREBOLT: case MG_LIGHTNINGBOLT: case MG_THUNDERSTORM: case MG_ENERGYCOAT: + case WL_WHITEIMPRISON: case WL_SUMMONFB: case WL_SUMMONBL: case WL_SUMMONWB: + case WL_SUMMONSTONE: case WL_SIENNAEXECRATE: case WL_RELEASE: case WL_EARTHSTRAIN: + case WL_RECOGNIZEDSPELL: case WL_READING_SB: case SA_MAGICROD: case SA_SPELLBREAKER: + case SA_DISPELL: case SA_FLAMELAUNCHER: case SA_FROSTWEAPON: case SA_LIGHTNINGLOADER: + case SA_SEISMICWEAPON: case SA_VOLCANO: case SA_DELUGE: case SA_VIOLENTGALE: + case SA_LANDPROTECTOR: case PF_HPCONVERSION: case PF_SOULCHANGE: case PF_SPIDERWEB: + case PF_FOGWALL: case TK_RUN: case TK_HIGHJUMP: case TK_SEVENWIND: + case SL_KAAHI: case SL_KAUPE: case SL_KAITE: + + // Skills that need to be confirmed. + case SO_FIREWALK: case SO_ELECTRICWALK: case SO_SPELLFIST: case SO_EARTHGRAVE: + case SO_DIAMONDDUST: case SO_POISON_BUSTER: case SO_PSYCHIC_WAVE: case SO_CLOUD_KILL: + case SO_STRIKING: case SO_WARMER: case SO_VACUUM_EXTREME: case SO_VARETYR_SPEAR: + case SO_ARRULLO: + return 1; // Can't do it. + } + break; + case SC_KAGEHUMI: + switch(skillid){ + case TF_HIDING: case AS_CLOAKING: case GC_CLOAKINGEXCEED: case SC_SHADOWFORM: + case MI_HARMONIZE: case CG_MARIONETTE: case AL_TELEPORT: case TF_BACKSLIDING: + case RA_CAMOUFLAGE: case ST_CHASEWALK: case GD_EMERGENCYCALL: + return 1; // needs more info + } + break; + } - return 0; + return 0; } -int skill_get_elemental_type(int skill_id , int skill_lv) -{ - int type = 0; +int skill_get_elemental_type( int skill_id , int skill_lv ) { + int type = 0; - switch (skill_id) { - case SO_SUMMON_AGNI: - type = 2114; - break; - case SO_SUMMON_AQUA: - type = 2117; - break; - case SO_SUMMON_VENTUS: - type = 2120; - break; - case SO_SUMMON_TERA: - type = 2123; - break; - } + switch( skill_id ) { + case SO_SUMMON_AGNI: type = 2114; break; + case SO_SUMMON_AQUA: type = 2117; break; + case SO_SUMMON_VENTUS: type = 2120; break; + case SO_SUMMON_TERA: type = 2123; break; + } - type += skill_lv - 1; + type += skill_lv - 1; - return type; + return type; } /** * reload stored skill cooldowns when a player logs in. * @param sd the affected player structure */ -void skill_cooldown_load(struct map_session_data *sd) +void skill_cooldown_load(struct map_session_data * sd) { - int i; - struct skill_cd *cd = NULL; - - // always check to make sure the session properly exists - nullpo_retv(sd); - - if (!(cd = idb_get(skillcd_db, sd->status.char_id))) { - // no skill cooldown is associated with this character - return; - } - - // process each individual cooldown associated with the character - for (i = 0; i < cd->cursor; i++) { - // block the skill from usage but ensure it is not recorded (load = true) - skill_blockpc_start_(sd, cd->nameid[i], cd->duration[i], true); - } + int i; + struct skill_cd* cd = NULL; + + // always check to make sure the session properly exists + nullpo_retv(sd); + + if( !(cd = idb_get(skillcd_db, sd->status.char_id)) ) + {// no skill cooldown is associated with this character + return; + } + + // process each individual cooldown associated with the character + for( i = 0; i < cd->cursor; i++ ) + { + // block the skill from usage but ensure it is not recorded (load = true) + skill_blockpc_start_( sd, cd->nameid[i], cd->duration[i], true ); + } } /*========================================== @@ -17619,405 +17355,406 @@ void skill_cooldown_load(struct map_session_data *sd) * skill_db.txt *------------------------------------------*/ -static bool skill_parse_row_skilldb(char *split[], int columns, int current) -{ - // id,range,hit,inf,element,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count,name,description - int id = atoi(split[0]); - int i; - if ((id >= GD_SKILLRANGEMIN && id <= GD_SKILLRANGEMAX) - || (id >= HM_SKILLRANGEMIN && id <= HM_SKILLRANGEMAX) - || (id >= MC_SKILLRANGEMIN && id <= MC_SKILLRANGEMAX) - || (id >= EL_SKILLRANGEMIN && id <= EL_SKILLRANGEMAX)) { - ShowWarning("skill_parse_row_skilldb: Skill id %d is forbidden (interferes with guild/homun/mercenary skill mapping)!\n", id); - return false; - } - - i = skill_get_index(id); - if (!i) // invalid skill id - return false; - - skill_split_atoi(split[1],skill_db[i].range); - skill_db[i].hit = atoi(split[2]); - skill_db[i].inf = atoi(split[3]); - skill_split_atoi(split[4],skill_db[i].element); - skill_db[i].nk = (int)strtol(split[5], NULL, 0); - skill_split_atoi(split[6],skill_db[i].splash); - skill_db[i].max = atoi(split[7]); - skill_split_atoi(split[8],skill_db[i].num); - - if (strcmpi(split[9],"yes") == 0) - skill_db[i].castcancel = 1; - else - skill_db[i].castcancel = 0; - skill_db[i].cast_def_rate = atoi(split[10]); - skill_db[i].inf2 = (int)strtol(split[11], NULL, 0); - skill_split_atoi(split[12],skill_db[i].maxcount); - if (strcmpi(split[13],"weapon") == 0) - skill_db[i].skill_type = BF_WEAPON; - else if (strcmpi(split[13],"magic") == 0) - skill_db[i].skill_type = BF_MAGIC; - else if (strcmpi(split[13],"misc") == 0) - skill_db[i].skill_type = BF_MISC; - else - skill_db[i].skill_type = 0; - skill_split_atoi(split[14],skill_db[i].blewcount); - safestrncpy(skill_db[i].name, trim(split[15]), sizeof(skill_db[i].name)); - safestrncpy(skill_db[i].desc, trim(split[16]), sizeof(skill_db[i].desc)); - strdb_iput(skilldb_name2id, skill_db[i].name, id); - - return true; +static bool skill_parse_row_skilldb(char* split[], int columns, int current) +{// id,range,hit,inf,element,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count,name,description + int id = atoi(split[0]); + int i; + if( (id >= GD_SKILLRANGEMIN && id <= GD_SKILLRANGEMAX) + || (id >= HM_SKILLRANGEMIN && id <= HM_SKILLRANGEMAX) + || (id >= MC_SKILLRANGEMIN && id <= MC_SKILLRANGEMAX) + || (id >= EL_SKILLRANGEMIN && id <= EL_SKILLRANGEMAX) ) { + ShowWarning("skill_parse_row_skilldb: Skill id %d is forbidden (interferes with guild/homun/mercenary skill mapping)!\n", id); + return false; + } + + i = skill_get_index(id); + if( !i ) // invalid skill id + return false; + + skill_split_atoi(split[1],skill_db[i].range); + skill_db[i].hit = atoi(split[2]); + skill_db[i].inf = atoi(split[3]); + skill_split_atoi(split[4],skill_db[i].element); + skill_db[i].nk = (int)strtol(split[5], NULL, 0); + skill_split_atoi(split[6],skill_db[i].splash); + skill_db[i].max = atoi(split[7]); + skill_split_atoi(split[8],skill_db[i].num); + + if( strcmpi(split[9],"yes") == 0 ) + skill_db[i].castcancel = 1; + else + skill_db[i].castcancel = 0; + skill_db[i].cast_def_rate = atoi(split[10]); + skill_db[i].inf2 = (int)strtol(split[11], NULL, 0); + skill_split_atoi(split[12],skill_db[i].maxcount); + if( strcmpi(split[13],"weapon") == 0 ) + skill_db[i].skill_type = BF_WEAPON; + else if( strcmpi(split[13],"magic") == 0 ) + skill_db[i].skill_type = BF_MAGIC; + else if( strcmpi(split[13],"misc") == 0 ) + skill_db[i].skill_type = BF_MISC; + else + skill_db[i].skill_type = 0; + skill_split_atoi(split[14],skill_db[i].blewcount); + safestrncpy(skill_db[i].name, trim(split[15]), sizeof(skill_db[i].name)); + safestrncpy(skill_db[i].desc, trim(split[16]), sizeof(skill_db[i].desc)); + strdb_iput(skilldb_name2id, skill_db[i].name, id); + + return true; } -static bool skill_parse_row_requiredb(char *split[], int columns, int current) -{ - // SkillID,HPCost,MaxHPTrigger,SPCost,HPRateCost,SPRateCost,ZenyCost,RequiredWeapons,RequiredAmmoTypes,RequiredAmmoAmount,RequiredState,SpiritSphereCost,RequiredItemID1,RequiredItemAmount1,RequiredItemID2,RequiredItemAmount2,RequiredItemID3,RequiredItemAmount3,RequiredItemID4,RequiredItemAmount4,RequiredItemID5,RequiredItemAmount5,RequiredItemID6,RequiredItemAmount6,RequiredItemID7,RequiredItemAmount7,RequiredItemID8,RequiredItemAmount8,RequiredItemID9,RequiredItemAmount9,RequiredItemID10,RequiredItemAmount10 - char *p; - int j; - - int i = atoi(split[0]); - i = skill_get_index(i); - if (!i) // invalid skill id - return false; - - 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); +static bool skill_parse_row_requiredb(char* split[], int columns, int current) +{// SkillID,HPCost,MaxHPTrigger,SPCost,HPRateCost,SPRateCost,ZenyCost,RequiredWeapons,RequiredAmmoTypes,RequiredAmmoAmount,RequiredState,SpiritSphereCost,RequiredItemID1,RequiredItemAmount1,RequiredItemID2,RequiredItemAmount2,RequiredItemID3,RequiredItemAmount3,RequiredItemID4,RequiredItemAmount4,RequiredItemID5,RequiredItemAmount5,RequiredItemID6,RequiredItemAmount6,RequiredItemID7,RequiredItemAmount7,RequiredItemID8,RequiredItemAmount8,RequiredItemID9,RequiredItemAmount9,RequiredItemID10,RequiredItemAmount10 + char* p; + int j; + + int i = atoi(split[0]); + i = skill_get_index(i); + if( !i ) // invalid skill id + return false; + + 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); //Wich weapon type are required, see doc/item_db for types - p = split[7]; - for (j = 0; j < 32; j++) { - int l = atoi(p); - if (l == 99) { // Any weapon - skill_db[i].weapon = 0; - break; - } else - skill_db[i].weapon |= 1<<l; - p = strchr(p,':'); - if (!p) - break; - p++; - } - - //FIXME: document this - p = split[8]; - for (j = 0; j < 32; j++) { - int l = atoi(p); - if (l == 99) { // Any ammo type - skill_db[i].ammo = 0xFFFFFFFF; - break; - } else if (l) // 0 stands for no requirement - skill_db[i].ammo |= 1<<l; - p = strchr(p,':'); - if (!p) - break; - p++; - } - skill_split_atoi(split[9],skill_db[i].ammo_qty); - - if (strcmpi(split[10],"hiding")==0) skill_db[i].state = ST_HIDING; - else if (strcmpi(split[10],"cloaking")==0) skill_db[i].state = ST_CLOAKING; - else if (strcmpi(split[10],"hidden")==0) skill_db[i].state = ST_HIDDEN; - else if (strcmpi(split[10],"riding")==0) skill_db[i].state = ST_RIDING; - else if (strcmpi(split[10],"falcon")==0) skill_db[i].state = ST_FALCON; - else if (strcmpi(split[10],"cart")==0) skill_db[i].state = ST_CART; - else if (strcmpi(split[10],"shield")==0) skill_db[i].state = ST_SHIELD; - else if (strcmpi(split[10],"sight")==0) skill_db[i].state = ST_SIGHT; - else if (strcmpi(split[10],"explosionspirits")==0) skill_db[i].state = ST_EXPLOSIONSPIRITS; - else if (strcmpi(split[10],"cartboost")==0) skill_db[i].state = ST_CARTBOOST; - else if (strcmpi(split[10],"recover_weight_rate")==0) skill_db[i].state = ST_RECOV_WEIGHT_RATE; - else if (strcmpi(split[10],"move_enable")==0) skill_db[i].state = ST_MOVE_ENABLE; - else if (strcmpi(split[10],"water")==0) skill_db[i].state = ST_WATER; - /** - * New States - **/ - else if (strcmpi(split[10],"dragon")==0) skill_db[i].state = ST_RIDINGDRAGON; - else if (strcmpi(split[10],"warg")==0) skill_db[i].state = ST_WUG; - else if (strcmpi(split[10],"ridingwarg")==0) skill_db[i].state = ST_RIDINGWUG; - else if (strcmpi(split[10],"mado")==0) skill_db[i].state = ST_MADO; - else if (strcmpi(split[10],"elementalspirit")==0) skill_db[i].state = ST_ELEMENTALSPIRIT; - else if (strcmpi(split[10], "poisonweapon") == 0) skill_db[i].state = ST_POISONINGWEAPON; - else if (strcmpi(split[10], "rollingcutter") == 0) skill_db[i].state = ST_ROLLINGCUTTER; - - /** - * Unknown or no state - **/ - else skill_db[i].state = ST_NONE; - - skill_split_atoi(split[11],skill_db[i].spiritball); - for (j = 0; j < MAX_SKILL_ITEM_REQUIRE; j++) { - skill_db[i].itemid[j] = atoi(split[12+ 2*j]); - skill_db[i].amount[j] = atoi(split[13+ 2*j]); - } - - return true; + p = split[7]; + for( j = 0; j < 32; j++ ) + { + int l = atoi(p); + if( l == 99 ) // Any weapon + { + skill_db[i].weapon = 0; + break; + } + else + skill_db[i].weapon |= 1<<l; + p = strchr(p,':'); + if(!p) + break; + p++; + } + + //FIXME: document this + p = split[8]; + for( j = 0; j < 32; j++ ) + { + int l = atoi(p); + if( l == 99 ) // Any ammo type + { + skill_db[i].ammo = 0xFFFFFFFF; + break; + } + else if( l ) // 0 stands for no requirement + skill_db[i].ammo |= 1<<l; + p = strchr(p,':'); + if( !p ) + break; + p++; + } + skill_split_atoi(split[9],skill_db[i].ammo_qty); + + if( strcmpi(split[10],"hiding")==0 ) skill_db[i].state = ST_HIDING; + else if( strcmpi(split[10],"cloaking")==0 ) skill_db[i].state = ST_CLOAKING; + else if( strcmpi(split[10],"hidden")==0 ) skill_db[i].state = ST_HIDDEN; + else if( strcmpi(split[10],"riding")==0 ) skill_db[i].state = ST_RIDING; + else if( strcmpi(split[10],"falcon")==0 ) skill_db[i].state = ST_FALCON; + else if( strcmpi(split[10],"cart")==0 ) skill_db[i].state = ST_CART; + else if( strcmpi(split[10],"shield")==0 ) skill_db[i].state = ST_SHIELD; + else if( strcmpi(split[10],"sight")==0 ) skill_db[i].state = ST_SIGHT; + else if( strcmpi(split[10],"explosionspirits")==0 ) skill_db[i].state = ST_EXPLOSIONSPIRITS; + else if( strcmpi(split[10],"cartboost")==0 ) skill_db[i].state = ST_CARTBOOST; + else if( strcmpi(split[10],"recover_weight_rate")==0 ) skill_db[i].state = ST_RECOV_WEIGHT_RATE; + else if( strcmpi(split[10],"move_enable")==0 ) skill_db[i].state = ST_MOVE_ENABLE; + else if( strcmpi(split[10],"water")==0 ) skill_db[i].state = ST_WATER; + /** + * New States + **/ + else if( strcmpi(split[10],"dragon")==0 ) skill_db[i].state = ST_RIDINGDRAGON; + else if( strcmpi(split[10],"warg")==0 ) skill_db[i].state = ST_WUG; + else if( strcmpi(split[10],"ridingwarg")==0 ) skill_db[i].state = ST_RIDINGWUG; + else if( strcmpi(split[10],"mado")==0 ) skill_db[i].state = ST_MADO; + else if( strcmpi(split[10],"elementalspirit")==0 ) skill_db[i].state = ST_ELEMENTALSPIRIT; + else if (strcmpi(split[10], "poisonweapon") == 0) skill_db[i].state = ST_POISONINGWEAPON; + else if (strcmpi(split[10], "rollingcutter") == 0) skill_db[i].state = ST_ROLLINGCUTTER; + + /** + * Unknown or no state + **/ + else skill_db[i].state = ST_NONE; + + skill_split_atoi(split[11],skill_db[i].spiritball); + for( j = 0; j < MAX_SKILL_ITEM_REQUIRE; j++ ) { + skill_db[i].itemid[j] = atoi(split[12+ 2*j]); + skill_db[i].amount[j] = atoi(split[13+ 2*j]); + } + + return true; } -static bool skill_parse_row_castdb(char *split[], int columns, int current) -{ - // SkillID,CastingTime,AfterCastActDelay,AfterCastWalkDelay,Duration1,Duration2 - int i = atoi(split[0]); - i = skill_get_index(i); - if (!i) // invalid skill id - return false; - - 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].walkdelay); - skill_split_atoi(split[4],skill_db[i].upkeep_time); - skill_split_atoi(split[5],skill_db[i].upkeep_time2); - skill_split_atoi(split[6],skill_db[i].cooldown); +static bool skill_parse_row_castdb(char* split[], int columns, int current) +{// SkillID,CastingTime,AfterCastActDelay,AfterCastWalkDelay,Duration1,Duration2 + int i = atoi(split[0]); + i = skill_get_index(i); + if( !i ) // invalid skill id + return false; + + 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].walkdelay); + skill_split_atoi(split[4],skill_db[i].upkeep_time); + skill_split_atoi(split[5],skill_db[i].upkeep_time2); + skill_split_atoi(split[6],skill_db[i].cooldown); #ifdef RENEWAL_CAST - skill_split_atoi(split[7],skill_db[i].fixed_cast); + skill_split_atoi(split[7],skill_db[i].fixed_cast); #endif - return true; + return true; } -static bool skill_parse_row_castnodexdb(char *split[], int columns, int current) -{ - // Skill id,Cast,Delay (optional) - int i = atoi(split[0]); - i = skill_get_index(i); - if (!i) // invalid skill id - return false; +static bool skill_parse_row_castnodexdb(char* split[], int columns, int current) +{// Skill id,Cast,Delay (optional) + int i = atoi(split[0]); + i = skill_get_index(i); + if( !i ) // invalid skill id + return false; - skill_split_atoi(split[1],skill_db[i].castnodex); - if (split[2]) // optional column - skill_split_atoi(split[2],skill_db[i].delaynodex); + skill_split_atoi(split[1],skill_db[i].castnodex); + if( split[2] ) // optional column + skill_split_atoi(split[2],skill_db[i].delaynodex); - return true; + return true; } -static bool skill_parse_row_nocastdb(char *split[], int columns, int current) -{ - // SkillID,Flag - int i = atoi(split[0]); - i = skill_get_index(i); - if (!i) // invalid skill id - return false; +static bool skill_parse_row_nocastdb(char* split[], int columns, int current) +{// SkillID,Flag + int i = atoi(split[0]); + i = skill_get_index(i); + if( !i ) // invalid skill id + return false; - skill_db[i].nocast |= atoi(split[1]); + skill_db[i].nocast |= atoi(split[1]); - return true; + return true; } -static bool skill_parse_row_unitdb(char *split[], int columns, int current) -{ - // ID,unit ID,unit ID 2,layout,range,interval,target,flag - int i = atoi(split[0]); - i = skill_get_index(i); - if (!i) // invalid skill id - return false; - - 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_split_atoi(split[4],skill_db[i].unit_range); - 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],"ally")==0) skill_db[i].unit_target = BCT_PARTY|BCT_GUILD; - else if (strcmpi(split[6],"guild")==0) skill_db[i].unit_target = BCT_GUILD; - 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 if (strcmpi(split[6],"noone")==0) skill_db[i].unit_target = BCT_NOONE; - else skill_db[i].unit_target = strtol(split[6],NULL,16); - - skill_db[i].unit_flag = strtol(split[7],NULL,16); - - if (skill_db[i].unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) - skill_db[i].unit_target = BCT_NOENEMY; - - //By default, target just characters. - skill_db[i].unit_target |= BL_CHAR; - if (skill_db[i].unit_flag&UF_NOPC) - skill_db[i].unit_target &= ~BL_PC; - if (skill_db[i].unit_flag&UF_NOMOB) - skill_db[i].unit_target &= ~BL_MOB; - if (skill_db[i].unit_flag&UF_SKILL) - skill_db[i].unit_target |= BL_SKILL; - - return true; +static bool skill_parse_row_unitdb(char* split[], int columns, int current) +{// ID,unit ID,unit ID 2,layout,range,interval,target,flag + int i = atoi(split[0]); + i = skill_get_index(i); + if( !i ) // invalid skill id + return false; + + 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_split_atoi(split[4],skill_db[i].unit_range); + 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],"ally")==0 ) skill_db[i].unit_target = BCT_PARTY|BCT_GUILD; + else if( strcmpi(split[6],"guild")==0 ) skill_db[i].unit_target = BCT_GUILD; + 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 if( strcmpi(split[6],"noone")==0 ) skill_db[i].unit_target = BCT_NOONE; + else skill_db[i].unit_target = strtol(split[6],NULL,16); + + skill_db[i].unit_flag = strtol(split[7],NULL,16); + + if (skill_db[i].unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) + skill_db[i].unit_target = BCT_NOENEMY; + + //By default, target just characters. + skill_db[i].unit_target |= BL_CHAR; + if (skill_db[i].unit_flag&UF_NOPC) + skill_db[i].unit_target &= ~BL_PC; + if (skill_db[i].unit_flag&UF_NOMOB) + skill_db[i].unit_target &= ~BL_MOB; + if (skill_db[i].unit_flag&UF_SKILL) + skill_db[i].unit_target |= BL_SKILL; + + return true; } -static bool skill_parse_row_producedb(char *split[], int columns, int current) -{ - // ProduceItemID,ItemLV,RequireSkill,RequireSkillLv,MaterialID1,MaterialAmount1,...... - int x,y; +static bool skill_parse_row_producedb(char* split[], int columns, int current) +{// ProduceItemID,ItemLV,RequireSkill,RequireSkillLv,MaterialID1,MaterialAmount1,...... + int x,y; - int i = atoi(split[0]); - if (!i) - return false; + int i = atoi(split[0]); + if( !i ) + return false; - skill_produce_db[current].nameid = i; - skill_produce_db[current].itemlv = atoi(split[1]); - skill_produce_db[current].req_skill = atoi(split[2]); - skill_produce_db[current].req_skill_lv = atoi(split[3]); + skill_produce_db[current].nameid = i; + skill_produce_db[current].itemlv = atoi(split[1]); + skill_produce_db[current].req_skill = atoi(split[2]); + skill_produce_db[current].req_skill_lv = atoi(split[3]); - for (x = 4, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_PRODUCE_RESOURCE; x += 2, y++) { - skill_produce_db[current].mat_id[y] = atoi(split[x]); - skill_produce_db[current].mat_amount[y] = atoi(split[x+1]); - } + for( x = 4, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_PRODUCE_RESOURCE; x += 2, y++ ) + { + skill_produce_db[current].mat_id[y] = atoi(split[x]); + skill_produce_db[current].mat_amount[y] = atoi(split[x+1]); + } - return true; + return true; } -static bool skill_parse_row_createarrowdb(char *split[], int columns, int current) -{ - // SourceID,MakeID1,MakeAmount1,...,MakeID5,MakeAmount5 - int x,y; +static bool skill_parse_row_createarrowdb(char* split[], int columns, int current) +{// SourceID,MakeID1,MakeAmount1,...,MakeID5,MakeAmount5 + int x,y; - int i = atoi(split[0]); - if (!i) - return false; + int i = atoi(split[0]); + if( !i ) + return false; - skill_arrow_db[current].nameid = i; + skill_arrow_db[current].nameid = i; - for (x = 1, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_ARROW_RESOURCE; x += 2, y++) { - skill_arrow_db[current].cre_id[y] = atoi(split[x]); - skill_arrow_db[current].cre_amount[y] = atoi(split[x+1]); - } + for( x = 1, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_ARROW_RESOURCE; x += 2, y++ ) + { + skill_arrow_db[current].cre_id[y] = atoi(split[x]); + skill_arrow_db[current].cre_amount[y] = atoi(split[x+1]); + } - return true; + return true; } -static bool skill_parse_row_spellbookdb(char *split[], int columns, int current) -{ - // SkillID,PreservePoints - - int skillid = atoi(split[0]), - points = atoi(split[1]), - nameid = atoi(split[2]); - - if (!skill_get_index(skillid) || !skill_get_max(skillid)) - ShowError("spellbook_db: Invalid skill ID %d\n", skillid); - if (!skill_get_inf(skillid)) - ShowError("spellbook_db: Passive skills cannot be memorized (%d/%s)\n", skillid, skill_get_name(skillid)); - if (points < 1) - ShowError("spellbook_db: PreservePoints have to be 1 or above! (%d/%s)\n", skillid, skill_get_name(skillid)); - else { - skill_spellbook_db[current].skillid = skillid; - skill_spellbook_db[current].point = points; - skill_spellbook_db[current].nameid = nameid; - - return true; - } - - return false; +static bool skill_parse_row_spellbookdb(char* split[], int columns, int current) +{// SkillID,PreservePoints + + int skillid = atoi(split[0]), + points = atoi(split[1]), + nameid = atoi(split[2]); + + if( !skill_get_index(skillid) || !skill_get_max(skillid) ) + ShowError("spellbook_db: Invalid skill ID %d\n", skillid); + if ( !skill_get_inf(skillid) ) + ShowError("spellbook_db: Passive skills cannot be memorized (%d/%s)\n", skillid, skill_get_name(skillid)); + if( points < 1 ) + ShowError("spellbook_db: PreservePoints have to be 1 or above! (%d/%s)\n", skillid, skill_get_name(skillid)); + else + { + skill_spellbook_db[current].skillid = skillid; + skill_spellbook_db[current].point = points; + skill_spellbook_db[current].nameid = nameid; + + return true; + } + + return false; } -static bool skill_parse_row_improvisedb(char *split[], int columns, int current) -{ - // SkillID - int i = atoi(split[0]); - short j = atoi(split[1]); - - if (!skill_get_index(i) || !skill_get_max(i)) { - ShowError("skill_improvise_db: Invalid skill ID %d\n", i); - return false; - } - if (!skill_get_inf(i)) { - ShowError("skill_improvise_db: Passive skills cannot be casted (%d/%s)\n", i, skill_get_name(i)); - return false; - } - if (j < 1) { - ShowError("skill_improvise_db: Chances have to be 1 or above! (%d/%s)\n", i, skill_get_name(i)); - return false; - } - if (current >= MAX_SKILL_IMPROVISE_DB) { - ShowError("skill_improvise_db: Maximum amount of entries reached (%d), increase MAX_SKILL_IMPROVISE_DB\n",MAX_SKILL_IMPROVISE_DB); - } - skill_improvise_db[current].skillid = i; - skill_improvise_db[current].per = j; // Still need confirm it. - - return true; +static bool skill_parse_row_improvisedb(char* split[], int columns, int current) +{// SkillID + int i = atoi(split[0]); + short j = atoi(split[1]); + + if( !skill_get_index(i) || !skill_get_max(i) ) { + ShowError("skill_improvise_db: Invalid skill ID %d\n", i); + return false; + } + if ( !skill_get_inf(i) ) { + ShowError("skill_improvise_db: Passive skills cannot be casted (%d/%s)\n", i, skill_get_name(i)); + return false; + } + if( j < 1 ) { + ShowError("skill_improvise_db: Chances have to be 1 or above! (%d/%s)\n", i, skill_get_name(i)); + return false; + } + if( current >= MAX_SKILL_IMPROVISE_DB ) { + ShowError("skill_improvise_db: Maximum amount of entries reached (%d), increase MAX_SKILL_IMPROVISE_DB\n",MAX_SKILL_IMPROVISE_DB); + } + skill_improvise_db[current].skillid = i; + skill_improvise_db[current].per = j; // Still need confirm it. + + return true; } -static bool skill_parse_row_magicmushroomdb(char *split[], int column, int current) +static bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) { - int i = atoi(split[0]); + int i = atoi(split[0]); - if (!skill_get_index(i) || !skill_get_max(i)) { - ShowError("magicmushroom_db: Invalid skill ID %d\n", i); - return false; - } - if (!skill_get_inf(i)) { - ShowError("magicmushroom_db: Passive skills cannot be casted (%d/%s)\n", i, skill_get_name(i)); - return false; - } + if( !skill_get_index(i) || !skill_get_max(i) ) + { + ShowError("magicmushroom_db: Invalid skill ID %d\n", i); + return false; + } + if ( !skill_get_inf(i) ) + { + ShowError("magicmushroom_db: Passive skills cannot be casted (%d/%s)\n", i, skill_get_name(i)); + return false; + } - skill_magicmushroom_db[current].skillid = i; + skill_magicmushroom_db[current].skillid = i; - return true; + return true; } -static bool skill_parse_row_reproducedb(char *split[], int column, int current) -{ - int skillid = atoi(split[0]); +static bool skill_parse_row_reproducedb(char* split[], int column, int current) { + int skillid = atoi(split[0]); - skillid = skill_get_index(skillid); - if (!skillid) - return false; + skillid = skill_get_index(skillid); + if( !skillid ) + return false; - skill_reproduce_db[skillid] = true; + skill_reproduce_db[skillid] = true; - return true; + return true; } -static bool skill_parse_row_abradb(char *split[], int columns, int current) -{ - // SkillID,DummyName,RequiredHocusPocusLevel,Rate - int i = atoi(split[0]); - if (!skill_get_index(i) || !skill_get_max(i)) { - ShowError("abra_db: Invalid skill ID %d\n", i); - return false; - } - if (!skill_get_inf(i)) { - ShowError("abra_db: Passive skills cannot be casted (%d/%s)\n", i, skill_get_name(i)); - return false; - } - - skill_abra_db[current].skillid = i; - skill_abra_db[current].req_lv = atoi(split[2]); - skill_abra_db[current].per = atoi(split[3]); - - return true; +static bool skill_parse_row_abradb(char* split[], int columns, int current) +{// SkillID,DummyName,RequiredHocusPocusLevel,Rate + int i = atoi(split[0]); + if( !skill_get_index(i) || !skill_get_max(i) ) + { + ShowError("abra_db: Invalid skill ID %d\n", i); + return false; + } + if ( !skill_get_inf(i) ) + { + ShowError("abra_db: Passive skills cannot be casted (%d/%s)\n", i, skill_get_name(i)); + return false; + } + + skill_abra_db[current].skillid = i; + skill_abra_db[current].req_lv = atoi(split[2]); + skill_abra_db[current].per = atoi(split[3]); + + return true; } -static bool skill_parse_row_changematerialdb(char *split[], int columns, int current) -{ - // SkillID - int i = atoi(split[0]); - short j = atoi(split[1]); - int x,y; - - for (x=0; x<MAX_SKILL_PRODUCE_DB; x++) { - if (skill_produce_db[x].nameid == i) - if (skill_produce_db[x].req_skill == GN_CHANGEMATERIAL) - break; - } - - if (x >= MAX_SKILL_PRODUCE_DB) { - ShowError("changematerial_db: Not supported item ID(%d) for Change Material. \n", i); - return false; - } - - if (current >= MAX_SKILL_PRODUCE_DB) { - ShowError("skill_changematerial_db: Maximum amount of entries reached (%d), increase MAX_SKILL_PRODUCE_DB\n",MAX_SKILL_PRODUCE_DB); - } - - skill_changematerial_db[current].itemid = i; - skill_changematerial_db[current].rate = j; - - for (x = 2, y = 0; x+1 < columns && split[x] && split[x+1] && y < 5; x += 2, y++) { - skill_changematerial_db[current].qty[y] = atoi(split[x]); - skill_changematerial_db[current].qty_rate[y] = atoi(split[x+1]); - } - - return true; +static bool skill_parse_row_changematerialdb(char* split[], int columns, int current) +{// SkillID + int i = atoi(split[0]); + short j = atoi(split[1]); + int x,y; + + for(x=0; x<MAX_SKILL_PRODUCE_DB; x++){ + if( skill_produce_db[x].nameid == i ) + if( skill_produce_db[x].req_skill == GN_CHANGEMATERIAL ) + break; + } + + if( x >= MAX_SKILL_PRODUCE_DB ){ + ShowError("changematerial_db: Not supported item ID(%d) for Change Material. \n", i); + return false; + } + + if( current >= MAX_SKILL_PRODUCE_DB ) { + ShowError("skill_changematerial_db: Maximum amount of entries reached (%d), increase MAX_SKILL_PRODUCE_DB\n",MAX_SKILL_PRODUCE_DB); + } + + skill_changematerial_db[current].itemid = i; + skill_changematerial_db[current].rate = j; + + for( x = 2, y = 0; x+1 < columns && split[x] && split[x+1] && y < 5; x += 2, y++ ) + { + skill_changematerial_db[current].qty[y] = atoi(split[x]); + skill_changematerial_db[current].qty_rate[y] = atoi(split[x+1]); + } + + return true; } /*=============================== @@ -18034,94 +17771,93 @@ static bool skill_parse_row_changematerialdb(char *split[], int columns, int cur *------------------------------*/ static void skill_readdb(void) { - // init skill db structures - db_clear(skilldb_name2id); - memset(skill_db,0,sizeof(skill_db)); - memset(skill_produce_db,0,sizeof(skill_produce_db)); - memset(skill_arrow_db,0,sizeof(skill_arrow_db)); - memset(skill_abra_db,0,sizeof(skill_abra_db)); - memset(skill_spellbook_db,0,sizeof(skill_spellbook_db)); - memset(skill_magicmushroom_db,0,sizeof(skill_magicmushroom_db)); - memset(skill_reproduce_db,0,sizeof(skill_reproduce_db)); - memset(skill_changematerial_db,0,sizeof(skill_changematerial_db)); - - // load skill databases - safestrncpy(skill_db[0].name, "UNKNOWN_SKILL", sizeof(skill_db[0].name)); - safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc)); - - sv_readdb(db_path, DBPATH"skill_db.txt" , ',', 17, 17, MAX_SKILL_DB, skill_parse_row_skilldb); - sv_readdb(db_path, DBPATH"skill_require_db.txt" , ',', 32, 32, MAX_SKILL_DB, skill_parse_row_requiredb); + // init skill db structures + db_clear(skilldb_name2id); + memset(skill_db,0,sizeof(skill_db)); + memset(skill_produce_db,0,sizeof(skill_produce_db)); + memset(skill_arrow_db,0,sizeof(skill_arrow_db)); + memset(skill_abra_db,0,sizeof(skill_abra_db)); + memset(skill_spellbook_db,0,sizeof(skill_spellbook_db)); + memset(skill_magicmushroom_db,0,sizeof(skill_magicmushroom_db)); + memset(skill_reproduce_db,0,sizeof(skill_reproduce_db)); + memset(skill_changematerial_db,0,sizeof(skill_changematerial_db)); + + // load skill databases + safestrncpy(skill_db[0].name, "UNKNOWN_SKILL", sizeof(skill_db[0].name)); + safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc)); + + sv_readdb(db_path, DBPATH"skill_db.txt" , ',', 17, 17, MAX_SKILL_DB, skill_parse_row_skilldb); + sv_readdb(db_path, DBPATH"skill_require_db.txt" , ',', 32, 32, MAX_SKILL_DB, skill_parse_row_requiredb); #ifdef RENEWAL_CAST - sv_readdb(db_path, "re/skill_cast_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill_parse_row_castdb); + sv_readdb(db_path, "re/skill_cast_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill_parse_row_castdb); #else - sv_readdb(db_path, "pre-re/skill_cast_db.txt" , ',', 7, 7, MAX_SKILL_DB, skill_parse_row_castdb); + sv_readdb(db_path, "pre-re/skill_cast_db.txt" , ',', 7, 7, MAX_SKILL_DB, skill_parse_row_castdb); #endif - sv_readdb(db_path, DBPATH"skill_castnodex_db.txt", ',', 2, 3, MAX_SKILL_DB, skill_parse_row_castnodexdb); - sv_readdb(db_path, DBPATH"skill_unit_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill_parse_row_unitdb); - - sv_readdb(db_path, DBPATH"skill_nocast_db.txt" , ',', 2, 2, MAX_SKILL_DB, skill_parse_row_nocastdb); - - skill_init_unit_layout(); - sv_readdb(db_path, "produce_db.txt" , ',', 4, 4+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill_parse_row_producedb); - sv_readdb(db_path, "create_arrow_db.txt" , ',', 1+2, 1+2*MAX_ARROW_RESOURCE, MAX_SKILL_ARROW_DB, skill_parse_row_createarrowdb); - sv_readdb(db_path, "abra_db.txt" , ',', 4, 4, MAX_SKILL_ABRA_DB, skill_parse_row_abradb); - //Warlock - sv_readdb(db_path, "spellbook_db.txt" , ',', 3, 3, MAX_SKILL_SPELLBOOK_DB, skill_parse_row_spellbookdb); - //Guillotine Cross - sv_readdb(db_path, "magicmushroom_db.txt" , ',', 1, 1, MAX_SKILL_MAGICMUSHROOM_DB, skill_parse_row_magicmushroomdb); - sv_readdb(db_path, "skill_reproduce_db.txt", ',', 1, 1, MAX_SKILL_DB, skill_parse_row_reproducedb); - sv_readdb(db_path, "skill_improvise_db.txt" , ',', 2, 2, MAX_SKILL_IMPROVISE_DB, skill_parse_row_improvisedb); - sv_readdb(db_path, "skill_changematerial_db.txt" , ',', 4, 4+2*5, MAX_SKILL_PRODUCE_DB, skill_parse_row_changematerialdb); + sv_readdb(db_path, DBPATH"skill_castnodex_db.txt", ',', 2, 3, MAX_SKILL_DB, skill_parse_row_castnodexdb); + sv_readdb(db_path, DBPATH"skill_unit_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill_parse_row_unitdb); + + sv_readdb(db_path, DBPATH"skill_nocast_db.txt" , ',', 2, 2, MAX_SKILL_DB, skill_parse_row_nocastdb); + + skill_init_unit_layout(); + sv_readdb(db_path, "produce_db.txt" , ',', 4, 4+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill_parse_row_producedb); + sv_readdb(db_path, "create_arrow_db.txt" , ',', 1+2, 1+2*MAX_ARROW_RESOURCE, MAX_SKILL_ARROW_DB, skill_parse_row_createarrowdb); + sv_readdb(db_path, "abra_db.txt" , ',', 4, 4, MAX_SKILL_ABRA_DB, skill_parse_row_abradb); + //Warlock + sv_readdb(db_path, "spellbook_db.txt" , ',', 3, 3, MAX_SKILL_SPELLBOOK_DB, skill_parse_row_spellbookdb); + //Guillotine Cross + sv_readdb(db_path, "magicmushroom_db.txt" , ',', 1, 1, MAX_SKILL_MAGICMUSHROOM_DB, skill_parse_row_magicmushroomdb); + sv_readdb(db_path, "skill_reproduce_db.txt", ',', 1, 1, MAX_SKILL_DB, skill_parse_row_reproducedb); + sv_readdb(db_path, "skill_improvise_db.txt" , ',', 2, 2, MAX_SKILL_IMPROVISE_DB, skill_parse_row_improvisedb); + sv_readdb(db_path, "skill_changematerial_db.txt" , ',', 4, 4+2*5, MAX_SKILL_PRODUCE_DB, skill_parse_row_changematerialdb); } -void skill_reload(void) -{ - struct s_mapiterator *iter; - struct map_session_data *sd; - skill_readdb(); - /* lets update all players skill tree : so that if any skill modes were changed they're properly updated */ - iter = mapit_getallusers(); - for (sd = (TBL_PC *)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC *)mapit_next(iter)) - clif_skillinfoblock(sd); - mapit_free(iter); +void skill_reload (void) { + struct s_mapiterator *iter; + struct map_session_data *sd; + skill_readdb(); + /* lets update all players skill tree : so that if any skill modes were changed they're properly updated */ + iter = mapit_getallusers(); + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + clif_skillinfoblock(sd); + mapit_free(iter); } /*========================================== * *------------------------------------------*/ -int do_init_skill(void) +int do_init_skill (void) { - skilldb_name2id = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0); - skill_readdb(); + skilldb_name2id = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0); + skill_readdb(); - group_db = idb_alloc(DB_OPT_BASE); - skillunit_db = idb_alloc(DB_OPT_BASE); - skillcd_db = idb_alloc(DB_OPT_RELEASE_DATA); - skillusave_db = idb_alloc(DB_OPT_RELEASE_DATA); - skill_unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_NONE); - skill_timer_ers = ers_new(sizeof(struct skill_timerskill),"skill.c::skill_timer_ers",ERS_OPT_NONE); + group_db = idb_alloc(DB_OPT_BASE); + skillunit_db = idb_alloc(DB_OPT_BASE); + skillcd_db = idb_alloc(DB_OPT_RELEASE_DATA); + skillusave_db = idb_alloc(DB_OPT_RELEASE_DATA); + skill_unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_NONE); + skill_timer_ers = ers_new(sizeof(struct skill_timerskill),"skill.c::skill_timer_ers",ERS_OPT_NONE); - 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_blockpc_end, "skill_blockpc_end"); + 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_blockpc_end, "skill_blockpc_end"); - add_timer_interval(gettick()+SKILLUNITTIMER_INTERVAL,skill_unit_timer,0,0,SKILLUNITTIMER_INTERVAL); + add_timer_interval(gettick()+SKILLUNITTIMER_INTERVAL,skill_unit_timer,0,0,SKILLUNITTIMER_INTERVAL); - return 0; + return 0; } int do_final_skill(void) { - db_destroy(skilldb_name2id); - db_destroy(group_db); - db_destroy(skillunit_db); - db_destroy(skillcd_db); - db_destroy(skillusave_db); - ers_destroy(skill_unit_ers); - ers_destroy(skill_timer_ers); - return 0; + db_destroy(skilldb_name2id); + db_destroy(group_db); + db_destroy(skillunit_db); + db_destroy(skillcd_db); + db_destroy(skillusave_db); + ers_destroy(skill_unit_ers); + ers_destroy(skill_timer_ers); + return 0; } diff --git a/src/map/skill.h b/src/map/skill.h index 90ebfc8be..265f2c7aa 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -12,210 +12,214 @@ struct skill_unit; struct skill_unit_group; struct status_change_entry; -#define MAX_SKILL_DB MAX_SKILL -#define MAX_SKILL_PRODUCE_DB 270 -#define MAX_PRODUCE_RESOURCE 12 -#define MAX_SKILL_ARROW_DB 150 -#define MAX_ARROW_RESOURCE 5 -#define MAX_SKILL_ABRA_DB 350 +#define MAX_SKILL_DB MAX_SKILL +#define MAX_SKILL_PRODUCE_DB 270 +#define MAX_PRODUCE_RESOURCE 12 +#define MAX_SKILL_ARROW_DB 150 +#define MAX_ARROW_RESOURCE 5 +#define MAX_SKILL_ABRA_DB 350 #define MAX_SKILL_IMPROVISE_DB 50 #define MAX_SKILL_LEVEL 100 //Constants to identify the skill's inf value: -enum e_skill_inf { - INF_ATTACK_SKILL = 0x01, - INF_GROUND_SKILL = 0x02, - INF_SELF_SKILL = 0x04, // Skills casted on self where target is automatically chosen - // 0x08 not assigned - INF_SUPPORT_SKILL = 0x10, - INF_TARGET_TRAP = 0x20, +enum e_skill_inf +{ + INF_ATTACK_SKILL = 0x01, + INF_GROUND_SKILL = 0x02, + INF_SELF_SKILL = 0x04, // Skills casted on self where target is automatically chosen + // 0x08 not assigned + INF_SUPPORT_SKILL = 0x10, + INF_TARGET_TRAP = 0x20, }; //Constants to identify a skill's nk value (damage properties) //The NK value applies only to non INF_GROUND_SKILL skills //when determining skill castend function to invoke. -enum e_skill_nk { - NK_NO_DAMAGE = 0x01, - NK_SPLASH = 0x02|0x04, // 0x4 = splash & split - NK_SPLASHSPLIT = 0x04, - NK_NO_CARDFIX_ATK = 0x08, - NK_NO_ELEFIX = 0x10, - NK_IGNORE_DEF = 0x20, - NK_IGNORE_FLEE = 0x40, - NK_NO_CARDFIX_DEF = 0x80, +enum e_skill_nk +{ + NK_NO_DAMAGE = 0x01, + NK_SPLASH = 0x02|0x04, // 0x4 = splash & split + NK_SPLASHSPLIT = 0x04, + NK_NO_CARDFIX_ATK = 0x08, + NK_NO_ELEFIX = 0x10, + NK_IGNORE_DEF = 0x20, + NK_IGNORE_FLEE = 0x40, + NK_NO_CARDFIX_DEF = 0x80, }; //A skill with 3 would be no damage + splash: area of effect. //Constants to identify a skill's inf2 value. -enum e_skill_inf2 { - INF2_QUEST_SKILL = 0x0001, - INF2_NPC_SKILL = 0x0002, //NPC skills are those that players can't have in their skill tree. - INF2_WEDDING_SKILL = 0x0004, - INF2_SPIRIT_SKILL = 0x0008, - INF2_GUILD_SKILL = 0x0010, - INF2_SONG_DANCE = 0x0020, - INF2_ENSEMBLE_SKILL = 0x0040, - INF2_TRAP = 0x0080, - INF2_TARGET_SELF = 0x0100, //Refers to ground placed skills that will target the caster as well (like Grandcross) - INF2_NO_TARGET_SELF = 0x0200, - INF2_PARTY_ONLY = 0x0400, - INF2_GUILD_ONLY = 0x0800, - INF2_NO_ENEMY = 0x1000, - INF2_NOLP = 0x2000, // Spells that can ignore Land Protector - INF2_CHORUS_SKILL = 0x4000, // Chorus skill +enum e_skill_inf2 +{ + INF2_QUEST_SKILL = 0x0001, + INF2_NPC_SKILL = 0x0002, //NPC skills are those that players can't have in their skill tree. + INF2_WEDDING_SKILL = 0x0004, + INF2_SPIRIT_SKILL = 0x0008, + INF2_GUILD_SKILL = 0x0010, + INF2_SONG_DANCE = 0x0020, + INF2_ENSEMBLE_SKILL = 0x0040, + INF2_TRAP = 0x0080, + INF2_TARGET_SELF = 0x0100, //Refers to ground placed skills that will target the caster as well (like Grandcross) + INF2_NO_TARGET_SELF = 0x0200, + INF2_PARTY_ONLY = 0x0400, + INF2_GUILD_ONLY = 0x0800, + INF2_NO_ENEMY = 0x1000, + INF2_NOLP = 0x2000, // Spells that can ignore Land Protector + INF2_CHORUS_SKILL = 0x4000, // Chorus skill }; //Walk intervals at which chase-skills are attempted to be triggered. #define WALK_SKILL_INTERVAL 5 // Flags passed to skill_attack/skill_area_sub -enum e_skill_display { - SD_LEVEL = 0x1000, // skill_attack will send -1 instead of skill level (affects display of some skills) - SD_ANIMATION = 0x2000, // skill_attack will use '5' instead of the skill's 'type' (this makes skills show an animation) - SD_SPLASH = 0x4000, // skill_area_sub will count targets in skill_area_temp[2] - SD_PREAMBLE = 0x8000, // skill_area_sub will transmit a 'magic' damage packet (-30000 dmg) for the first target selected +enum e_skill_display +{ + SD_LEVEL = 0x1000, // skill_attack will send -1 instead of skill level (affects display of some skills) + SD_ANIMATION = 0x2000, // skill_attack will use '5' instead of the skill's 'type' (this makes skills show an animation) + SD_SPLASH = 0x4000, // skill_area_sub will count targets in skill_area_temp[2] + SD_PREAMBLE = 0x8000, // skill_area_sub will transmit a 'magic' damage packet (-30000 dmg) for the first target selected }; -#define MAX_SKILL_ITEM_REQUIRE 10 +#define MAX_SKILL_ITEM_REQUIRE 10 struct skill_condition { - int weapon,ammo,ammo_qty,hp,sp,zeny,spiritball,mhp,state; - int itemid[MAX_SKILL_ITEM_REQUIRE],amount[MAX_SKILL_ITEM_REQUIRE]; + int weapon,ammo,ammo_qty,hp,sp,zeny,spiritball,mhp,state; + int itemid[MAX_SKILL_ITEM_REQUIRE],amount[MAX_SKILL_ITEM_REQUIRE]; }; // Database skills struct s_skill_db { - char name[NAME_LENGTH]; - char desc[40]; - int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max; - int num[MAX_SKILL_LEVEL]; - int cast[MAX_SKILL_LEVEL],walkdelay[MAX_SKILL_LEVEL],delay[MAX_SKILL_LEVEL]; + char name[NAME_LENGTH]; + char desc[40]; + int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max; + int num[MAX_SKILL_LEVEL]; + int cast[MAX_SKILL_LEVEL],walkdelay[MAX_SKILL_LEVEL],delay[MAX_SKILL_LEVEL]; #ifdef RENEWAL_CAST - int fixed_cast[MAX_SKILL_LEVEL]; + int fixed_cast[MAX_SKILL_LEVEL]; #endif - int upkeep_time[MAX_SKILL_LEVEL],upkeep_time2[MAX_SKILL_LEVEL],cooldown[MAX_SKILL_LEVEL]; - int castcancel,cast_def_rate; - int inf2,maxcount[MAX_SKILL_LEVEL],skill_type; - int blewcount[MAX_SKILL_LEVEL]; - int hp[MAX_SKILL_LEVEL],sp[MAX_SKILL_LEVEL],mhp[MAX_SKILL_LEVEL],hp_rate[MAX_SKILL_LEVEL],sp_rate[MAX_SKILL_LEVEL],zeny[MAX_SKILL_LEVEL]; - int weapon,ammo,ammo_qty[MAX_SKILL_LEVEL],state,spiritball[MAX_SKILL_LEVEL]; - int itemid[MAX_SKILL_ITEM_REQUIRE],amount[MAX_SKILL_ITEM_REQUIRE]; - int castnodex[MAX_SKILL_LEVEL], delaynodex[MAX_SKILL_LEVEL]; - int nocast; - int unit_id[2]; - int unit_layout_type[MAX_SKILL_LEVEL]; - int unit_range[MAX_SKILL_LEVEL]; - int unit_interval; - int unit_target; - int unit_flag; + int upkeep_time[MAX_SKILL_LEVEL],upkeep_time2[MAX_SKILL_LEVEL],cooldown[MAX_SKILL_LEVEL]; + int castcancel,cast_def_rate; + int inf2,maxcount[MAX_SKILL_LEVEL],skill_type; + int blewcount[MAX_SKILL_LEVEL]; + int hp[MAX_SKILL_LEVEL],sp[MAX_SKILL_LEVEL],mhp[MAX_SKILL_LEVEL],hp_rate[MAX_SKILL_LEVEL],sp_rate[MAX_SKILL_LEVEL],zeny[MAX_SKILL_LEVEL]; + int weapon,ammo,ammo_qty[MAX_SKILL_LEVEL],state,spiritball[MAX_SKILL_LEVEL]; + int itemid[MAX_SKILL_ITEM_REQUIRE],amount[MAX_SKILL_ITEM_REQUIRE]; + int castnodex[MAX_SKILL_LEVEL], delaynodex[MAX_SKILL_LEVEL]; + int nocast; + int unit_id[2]; + int unit_layout_type[MAX_SKILL_LEVEL]; + int unit_range[MAX_SKILL_LEVEL]; + int unit_interval; + int unit_target; + int unit_flag; }; extern struct s_skill_db skill_db[MAX_SKILL_DB]; -#define MAX_SKILL_UNIT_LAYOUT 50 -#define MAX_SQUARE_LAYOUT 5 // 11*11 Placement of a maximum unit +#define MAX_SKILL_UNIT_LAYOUT 50 +#define MAX_SQUARE_LAYOUT 5 // 11*11 Placement of a maximum unit #define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1)) struct s_skill_unit_layout { - int count; - int dx[MAX_SKILL_UNIT_COUNT]; - int dy[MAX_SKILL_UNIT_COUNT]; + int count; + int dx[MAX_SKILL_UNIT_COUNT]; + int dy[MAX_SKILL_UNIT_COUNT]; }; #define MAX_SKILLTIMERSKILL 15 struct skill_timerskill { - int timer; - int src_id; - int target_id; - int map; - short x,y; - short skill_id,skill_lv; - int type; // a BF_ type (NOTE: some places use this as general-purpose storage...) - int flag; + int timer; + int src_id; + int target_id; + int map; + short x,y; + short skill_id,skill_lv; + int type; // a BF_ type (NOTE: some places use this as general-purpose storage...) + int flag; }; #define MAX_SKILLUNITGROUP 25 struct skill_unit_group { - int src_id; - int party_id; - int guild_id; - int bg_id; - int map; - int target_flag; //Holds BCT_* flag for battle_check_target - int bl_flag; //Holds BL_* flag for map_foreachin* functions - unsigned int tick; - int limit,interval; - - short skill_id,skill_lv; - int val1,val2,val3; - char *valstr; - int unit_id; - int group_id; - int unit_count,alive_count; - int item_id; //store item used. - struct skill_unit *unit; - struct { - unsigned ammo_consume : 1; - unsigned song_dance : 2; //0x1 Song/Dance, 0x2 Ensemble - unsigned guildaura : 1; - } state; + int src_id; + int party_id; + int guild_id; + int bg_id; + int map; + int target_flag; //Holds BCT_* flag for battle_check_target + int bl_flag; //Holds BL_* flag for map_foreachin* functions + unsigned int tick; + int limit,interval; + + short skill_id,skill_lv; + int val1,val2,val3; + char *valstr; + int unit_id; + int group_id; + int unit_count,alive_count; + int item_id; //store item used. + struct skill_unit *unit; + struct { + unsigned ammo_consume : 1; + unsigned song_dance : 2; //0x1 Song/Dance, 0x2 Ensemble + unsigned guildaura : 1; + } state; }; struct skill_unit { - struct block_list bl; + struct block_list bl; - struct skill_unit_group *group; + struct skill_unit_group *group; - int limit; - int val1,val2; - short alive,range; + int limit; + int val1,val2; + short alive,range; }; #define MAX_SKILLUNITGROUPTICKSET 25 struct skill_unit_group_tickset { - unsigned int tick; - int id; + unsigned int tick; + int id; }; enum { - UF_DEFNOTENEMY = 0x0001, // If 'defunit_not_enemy' is set, the target is changed to 'friend' - UF_NOREITERATION = 0x0002, // Spell cannot be stacked - UF_NOFOOTSET = 0x0004, // Spell cannot be cast near/on targets - UF_NOOVERLAP = 0x0008, // Spell effects do not overlap - UF_PATHCHECK = 0x0010, // Only cells with a shootable path will be placed - UF_NOPC = 0x0020, // May not target players - UF_NOMOB = 0x0040, // May not target mobs - UF_SKILL = 0x0080, // May target skills - UF_DANCE = 0x0100, // Dance - UF_ENSEMBLE = 0x0200, // Duet - UF_SONG = 0x0400, // Song - UF_DUALMODE = 0x0800, // Spells should trigger both ontimer and onplace/onout/onleft effects. + UF_DEFNOTENEMY = 0x0001, // If 'defunit_not_enemy' is set, the target is changed to 'friend' + UF_NOREITERATION = 0x0002, // Spell cannot be stacked + UF_NOFOOTSET = 0x0004, // Spell cannot be cast near/on targets + UF_NOOVERLAP = 0x0008, // Spell effects do not overlap + UF_PATHCHECK = 0x0010, // Only cells with a shootable path will be placed + UF_NOPC = 0x0020, // May not target players + UF_NOMOB = 0x0040, // May not target mobs + UF_SKILL = 0x0080, // May target skills + UF_DANCE = 0x0100, // Dance + UF_ENSEMBLE = 0x0200, // Duet + UF_SONG = 0x0400, // Song + UF_DUALMODE = 0x0800, // Spells should trigger both ontimer and onplace/onout/onleft effects. UF_RANGEDSINGLEUNIT = 0x2000 // hack for ranged layout, only display center }; // Create Database item struct s_skill_produce_db { - int nameid, trigger; - int req_skill,req_skill_lv,itemlv; - int mat_id[MAX_PRODUCE_RESOURCE],mat_amount[MAX_PRODUCE_RESOURCE]; + int nameid, trigger; + int req_skill,req_skill_lv,itemlv; + int mat_id[MAX_PRODUCE_RESOURCE],mat_amount[MAX_PRODUCE_RESOURCE]; }; extern struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB]; // Creating database arrow struct s_skill_arrow_db { - int nameid, trigger; - int cre_id[MAX_ARROW_RESOURCE],cre_amount[MAX_ARROW_RESOURCE]; + int nameid, trigger; + int cre_id[MAX_ARROW_RESOURCE],cre_amount[MAX_ARROW_RESOURCE]; }; extern struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB]; // Abracadabra database struct s_skill_abra_db { - int skillid; - int req_lv; - int per; + int skillid; + int req_lv; + int per; }; extern struct s_skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB]; @@ -231,67 +235,67 @@ int skill_get_casttype(int id); //[Skotlex] // Accessor to the skills database // -int skill_get_index(int id); -int skill_get_type(int id); -int skill_get_hit(int id); -int skill_get_inf(int id); -int skill_get_ele(int id , int lv); -int skill_get_nk(int id); -int skill_get_max(int id); -int skill_get_range(int id , int lv); -int skill_get_range2(struct block_list *bl, int id, int lv); -int skill_get_splash(int id , int lv); -int skill_get_hp(int id ,int lv); -int skill_get_mhp(int id ,int lv); -int skill_get_sp(int id ,int lv); -int skill_get_state(int id); -int skill_get_zeny(int id ,int lv); -int skill_get_num(int id ,int lv); -int skill_get_cast(int id ,int lv); -int skill_get_delay(int id ,int lv); -int skill_get_walkdelay(int id ,int lv); -int skill_get_time(int id ,int lv); -int skill_get_time2(int id ,int lv); -int skill_get_castnodex(int id ,int lv); -int skill_get_castdef(int id); -int skill_get_weapontype(int id); -int skill_get_ammotype(int id); -int skill_get_ammo_qty(int id, int lv); -int skill_get_nocast(int id); -int skill_get_unit_id(int id,int flag); -int skill_get_inf2(int id); -int skill_get_castcancel(int id); -int skill_get_maxcount(int id ,int lv); -int skill_get_blewcount(int id ,int lv); -int skill_get_unit_flag(int id); -int skill_get_unit_target(int id); -int skill_tree_get_max(int id, int b_class); // Celest -const char *skill_get_name(int id); // [Skotlex] -const char *skill_get_desc(int id); // [Skotlex] - -int skill_name2id(const char *name); +int skill_get_index( int id ); +int skill_get_type( int id ); +int skill_get_hit( int id ); +int skill_get_inf( int id ); +int skill_get_ele( int id , int lv ); +int skill_get_nk( int id ); +int skill_get_max( int id ); +int skill_get_range( int id , int lv ); +int skill_get_range2(struct block_list *bl, int id, int lv); +int skill_get_splash( int id , int lv ); +int skill_get_hp( int id ,int lv ); +int skill_get_mhp( int id ,int lv ); +int skill_get_sp( int id ,int lv ); +int skill_get_state(int id); +int skill_get_zeny( int id ,int lv ); +int skill_get_num( int id ,int lv ); +int skill_get_cast( int id ,int lv ); +int skill_get_delay( int id ,int lv ); +int skill_get_walkdelay( int id ,int lv ); +int skill_get_time( int id ,int lv ); +int skill_get_time2( int id ,int lv ); +int skill_get_castnodex( int id ,int lv ); +int skill_get_castdef( int id ); +int skill_get_weapontype( int id ); +int skill_get_ammotype( int id ); +int skill_get_ammo_qty( int id, int lv ); +int skill_get_nocast( int id ); +int skill_get_unit_id(int id,int flag); +int skill_get_inf2( int id ); +int skill_get_castcancel( int id ); +int skill_get_maxcount( int id ,int lv ); +int skill_get_blewcount( int id ,int lv ); +int skill_get_unit_flag( int id ); +int skill_get_unit_target( int id ); +int skill_tree_get_max( int id, int b_class ); // Celest +const char* skill_get_name( int id ); // [Skotlex] +const char* skill_get_desc( int id ); // [Skotlex] + +int skill_name2id(const char* name); int skill_isammotype(struct map_session_data *sd, int skill); int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data); int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data); -int skill_castend_map(struct map_session_data *sd,short skill_num, const char *map); +int skill_castend_map( struct map_session_data *sd,short skill_num, const char *map); int skill_cleartimerskill(struct block_list *src); int skill_addtimerskill(struct block_list *src,unsigned int tick,int target,int x,int y,int skill_id,int skill_lv,int type,int flag); // Results? Added -int skill_additional_effect(struct block_list *src, struct block_list *bl,int skillid,int skilllv,int attack_type,int dmg_lv,unsigned int tick); -int skill_counter_additional_effect(struct block_list *src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick); -int skill_blown(struct block_list *src, struct block_list *target, int count, int direction, int flag); +int skill_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,int dmg_lv,unsigned int tick); +int skill_counter_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick); +int skill_blown(struct block_list* src, struct block_list* target, int count, int direction, int flag); int skill_break_equip(struct block_list *bl, unsigned short where, int rate, int flag); int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time); // Skills unit -struct skill_unit_group *skill_id2group(int group_id); -struct skill_unit_group *skill_unitsetting(struct block_list *src, short skillid, short skilllv, short x, short y, int flag); -struct skill_unit *skill_initunit(struct skill_unit_group *group, int idx, int x, int y, int val1, int val2); +struct skill_unit_group* skill_id2group(int group_id); +struct skill_unit_group *skill_unitsetting(struct block_list* src, short skillid, short skilllv, short x, short y, int flag); +struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2); int skill_delunit(struct skill_unit *unit); -struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count, short skillid, short skilllv, int unit_id, int limit, int interval); -int skill_delunitgroup_(struct skill_unit_group *group, const char *file, int line, const char *func); +struct skill_unit_group *skill_initunitgroup(struct block_list* src, int count, short skillid, short skilllv, int unit_id, int limit, int interval); +int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int line, const char* func); #define skill_delunitgroup(group) skill_delunitgroup_(group,__FILE__,__LINE__,__func__) int skill_clear_unitgroup(struct block_list *src); int skill_clear_group(struct block_list *bl, int flag); @@ -299,12 +303,12 @@ void ext_skill_unit_onplace(struct skill_unit *src, struct block_list *bl, unsig int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,int damage,unsigned int tick); -int skill_castfix(struct block_list *bl, int skill_id, int skill_lv); -int skill_castfix_sc(struct block_list *bl, int time); +int skill_castfix( struct block_list *bl, int skill_id, int skill_lv); +int skill_castfix_sc( struct block_list *bl, int time); #ifdef RENEWAL_CAST -int skill_vfcastfix(struct block_list *bl, double time, int skill_id, int skill_lv); +int skill_vfcastfix( struct block_list *bl, double time, int skill_id, int skill_lv); #endif -int skill_delayfix(struct block_list *bl, int skill_id, int skill_lv); +int skill_delayfix( struct block_list *bl, int skill_id, int skill_lv); // Skill conditions check and remove [Inkfish] int skill_check_condition_castbegin(struct map_session_data *sd, short skill, short lv); @@ -312,23 +316,23 @@ int skill_check_condition_castend(struct map_session_data *sd, short skill, shor int skill_consume_requirement(struct map_session_data *sd, short skill, short lv, short type); struct skill_condition skill_get_requirement(struct map_session_data *sd, short skill, short lv); -int skill_check_pc_partner(struct map_session_data *sd, short skill_id, short *skill_lv, int range, int cast_flag); -// -- moonsoul (added skill_check_unit_cell) +int skill_check_pc_partner(struct map_session_data *sd, short skill_id, short* skill_lv, int range, int cast_flag); +// -- 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_out_all( 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); +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); +struct skill_unit_group *skill_check_dancing( struct block_list *src ); // Guild skills [celest] -int skill_guildaura_sub(struct map_session_data *sd, int id, int strvit, int agidex); +int skill_guildaura_sub (struct map_session_data* sd, int id, int strvit, int agidex); // Chant canceled int skill_castcancel(struct block_list *bl,int type); -int skill_sit(struct map_session_data *sd, int type); -void skill_brandishspear(struct block_list *src, struct block_list *bl, int skillid, int skilllv, unsigned int tick, int flag); +int skill_sit (struct map_session_data *sd, int type); +void skill_brandishspear(struct block_list* src, struct block_list* bl, int skillid, int skilllv, unsigned int tick, int flag); void skill_repairweapon(struct map_session_data *sd, int idx); void skill_identify(struct map_session_data *sd,int idx); void skill_weaponrefine(struct map_session_data *sd,int idx); // [Celest] @@ -347,1479 +351,1479 @@ int skillnotok_mercenary(int skillid, struct mercenary_data *md); int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap); // Item creation -int skill_can_produce_mix(struct map_session_data *sd, int nameid, int trigger, int qty); -int skill_produce_mix(struct map_session_data *sd, int skill_id, int nameid, int slot1, int slot2, int slot3, int qty); +int skill_can_produce_mix( struct map_session_data *sd, int nameid, int trigger, int qty); +int skill_produce_mix( struct map_session_data *sd, int skill_id, int nameid, int slot1, int slot2, int slot3, int qty ); -int skill_arrow_create(struct map_session_data *sd,int nameid); +int skill_arrow_create( struct map_session_data *sd,int nameid); // skills for the mob -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_damage_id(struct block_list *src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag); -int skill_castend_pos2(struct block_list *src, int x,int y,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 ); +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_pos2( struct block_list *src, int x,int y,int skillid,int skilllv,unsigned int tick,int flag); -int skill_blockpc_start_(struct map_session_data *, int, int, bool); -int skill_blockhomun_start(struct homun_data *,int,int); -int skill_blockmerc_start(struct mercenary_data *,int,int); +int skill_blockpc_start_(struct map_session_data*, int, int, bool); +int skill_blockhomun_start (struct homun_data*,int,int); +int skill_blockmerc_start (struct mercenary_data*,int,int); #define skill_blockpc_start(sd, skillid, tick) skill_blockpc_start_( sd, skillid, tick, false ) // (Epoque:) To-do: replace this macro with some sort of skill tree check (rather than hard-coded skill names) #define skill_ischangesex(id) ( \ - ((id) >= BD_ADAPTATION && (id) <= DC_SERVICEFORYOU) || ((id) >= CG_ARROWVULCAN && (id) <= CG_MARIONETTE) || \ - ((id) >= CG_LONGINGFREEDOM && (id) <= CG_TAROTCARD) || ((id) >= WA_SWING_DANCE && (id) <= WM_UNLIMITED_HUMMING_VOICE)) + ((id) >= BD_ADAPTATION && (id) <= DC_SERVICEFORYOU) || ((id) >= CG_ARROWVULCAN && (id) <= CG_MARIONETTE) || \ + ((id) >= CG_LONGINGFREEDOM && (id) <= CG_TAROTCARD) || ((id) >= WA_SWING_DANCE && (id) <= WM_UNLIMITED_HUMMING_VOICE)) // Skill action, (return dmg,heal) -int skill_attack(int attack_type, struct block_list *src, struct block_list *dsrc,struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag); +int skill_attack( int attack_type, struct block_list* src, struct block_list *dsrc,struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag ); void skill_reload(void); enum { - ST_NONE, - ST_HIDING, - ST_CLOAKING, - ST_HIDDEN, - ST_RIDING, - ST_FALCON, - ST_CART, - ST_SHIELD, - ST_SIGHT, - ST_EXPLOSIONSPIRITS, - ST_CARTBOOST, - ST_RECOV_WEIGHT_RATE, - ST_MOVE_ENABLE, - ST_WATER, - /** - * 3rd States - **/ - ST_RIDINGDRAGON, - ST_WUG, - ST_RIDINGWUG, - ST_MADO, - ST_ELEMENTALSPIRIT, - ST_POISONINGWEAPON, - ST_ROLLINGCUTTER, + ST_NONE, + ST_HIDING, + ST_CLOAKING, + ST_HIDDEN, + ST_RIDING, + ST_FALCON, + ST_CART, + ST_SHIELD, + ST_SIGHT, + ST_EXPLOSIONSPIRITS, + ST_CARTBOOST, + ST_RECOV_WEIGHT_RATE, + ST_MOVE_ENABLE, + ST_WATER, + /** + * 3rd States + **/ + ST_RIDINGDRAGON, + ST_WUG, + ST_RIDINGWUG, + ST_MADO, + ST_ELEMENTALSPIRIT, + ST_POISONINGWEAPON, + ST_ROLLINGCUTTER, }; enum e_skill { - NV_BASIC = 1, - - SM_SWORD, - SM_TWOHAND, - SM_RECOVERY, - SM_BASH, - SM_PROVOKE, - SM_MAGNUM, - SM_ENDURE, - - MG_SRECOVERY, - MG_SIGHT, - MG_NAPALMBEAT, - MG_SAFETYWALL, - MG_SOULSTRIKE, - MG_COLDBOLT, - MG_FROSTDIVER, - MG_STONECURSE, - MG_FIREBALL, - MG_FIREWALL, - MG_FIREBOLT, - MG_LIGHTNINGBOLT, - MG_THUNDERSTORM, - - AL_DP, - AL_DEMONBANE, - AL_RUWACH, - AL_PNEUMA, - AL_TELEPORT, - AL_WARP, - AL_HEAL, - AL_INCAGI, - AL_DECAGI, - AL_HOLYWATER, - AL_CRUCIS, - AL_ANGELUS, - AL_BLESSING, - AL_CURE, - - MC_INCCARRY, - MC_DISCOUNT, - MC_OVERCHARGE, - MC_PUSHCART, - MC_IDENTIFY, - MC_VENDING, - MC_MAMMONITE, - - AC_OWL, - AC_VULTURE, - AC_CONCENTRATION, - AC_DOUBLE, - AC_SHOWER, - - TF_DOUBLE, - TF_MISS, - TF_STEAL, - TF_HIDING, - TF_POISON, - TF_DETOXIFY, - - ALL_RESURRECTION, - - KN_SPEARMASTERY, - KN_PIERCE, - KN_BRANDISHSPEAR, - KN_SPEARSTAB, - KN_SPEARBOOMERANG, - KN_TWOHANDQUICKEN, - KN_AUTOCOUNTER, - KN_BOWLINGBASH, - KN_RIDING, - KN_CAVALIERMASTERY, - - PR_MACEMASTERY, - PR_IMPOSITIO, - PR_SUFFRAGIUM, - PR_ASPERSIO, - PR_BENEDICTIO, - PR_SANCTUARY, - PR_SLOWPOISON, - PR_STRECOVERY, - PR_KYRIE, - PR_MAGNIFICAT, - PR_GLORIA, - PR_LEXDIVINA, - PR_TURNUNDEAD, - PR_LEXAETERNA, - PR_MAGNUS, - - WZ_FIREPILLAR, - WZ_SIGHTRASHER, - WZ_FIREIVY, - WZ_METEOR, - WZ_JUPITEL, - WZ_VERMILION, - WZ_WATERBALL, - WZ_ICEWALL, - WZ_FROSTNOVA, - WZ_STORMGUST, - WZ_EARTHSPIKE, - WZ_HEAVENDRIVE, - WZ_QUAGMIRE, - WZ_ESTIMATION, - - BS_IRON, - BS_STEEL, - BS_ENCHANTEDSTONE, - BS_ORIDEOCON, - BS_DAGGER, - BS_SWORD, - BS_TWOHANDSWORD, - BS_AXE, - BS_MACE, - BS_KNUCKLE, - BS_SPEAR, - BS_HILTBINDING, - BS_FINDINGORE, - BS_WEAPONRESEARCH, - BS_REPAIRWEAPON, - BS_SKINTEMPER, - BS_HAMMERFALL, - BS_ADRENALINE, - BS_WEAPONPERFECT, - BS_OVERTHRUST, - BS_MAXIMIZE, - - HT_SKIDTRAP, - HT_LANDMINE, - HT_ANKLESNARE, - HT_SHOCKWAVE, - HT_SANDMAN, - HT_FLASHER, - HT_FREEZINGTRAP, - HT_BLASTMINE, - HT_CLAYMORETRAP, - HT_REMOVETRAP, - HT_TALKIEBOX, - HT_BEASTBANE, - HT_FALCON, - HT_STEELCROW, - HT_BLITZBEAT, - HT_DETECTING, - HT_SPRINGTRAP, - - AS_RIGHT, - AS_LEFT, - AS_KATAR, - AS_CLOAKING, - AS_SONICBLOW, - AS_GRIMTOOTH, - AS_ENCHANTPOISON, - AS_POISONREACT, - AS_VENOMDUST, - AS_SPLASHER, - - NV_FIRSTAID, - NV_TRICKDEAD, - SM_MOVINGRECOVERY, - SM_FATALBLOW, - SM_AUTOBERSERK, - AC_MAKINGARROW, - AC_CHARGEARROW, - TF_SPRINKLESAND, - TF_BACKSLIDING, - TF_PICKSTONE, - TF_THROWSTONE, - MC_CARTREVOLUTION, - MC_CHANGECART, - MC_LOUD, - AL_HOLYLIGHT, - MG_ENERGYCOAT, - - NPC_PIERCINGATT, - NPC_MENTALBREAKER, - NPC_RANGEATTACK, - NPC_ATTRICHANGE, - NPC_CHANGEWATER, - NPC_CHANGEGROUND, - NPC_CHANGEFIRE, - NPC_CHANGEWIND, - NPC_CHANGEPOISON, - NPC_CHANGEHOLY, - NPC_CHANGEDARKNESS, - NPC_CHANGETELEKINESIS, - NPC_CRITICALSLASH, - NPC_COMBOATTACK, - NPC_GUIDEDATTACK, - NPC_SELFDESTRUCTION, - NPC_SPLASHATTACK, - NPC_SUICIDE, - NPC_POISON, - NPC_BLINDATTACK, - NPC_SILENCEATTACK, - NPC_STUNATTACK, - NPC_PETRIFYATTACK, - NPC_CURSEATTACK, - NPC_SLEEPATTACK, - NPC_RANDOMATTACK, - NPC_WATERATTACK, - NPC_GROUNDATTACK, - NPC_FIREATTACK, - NPC_WINDATTACK, - NPC_POISONATTACK, - NPC_HOLYATTACK, - NPC_DARKNESSATTACK, - NPC_TELEKINESISATTACK, - NPC_MAGICALATTACK, - NPC_METAMORPHOSIS, - NPC_PROVOCATION, - NPC_SMOKING, - NPC_SUMMONSLAVE, - NPC_EMOTION, - NPC_TRANSFORMATION, - NPC_BLOODDRAIN, - NPC_ENERGYDRAIN, - NPC_KEEPING, - NPC_DARKBREATH, - NPC_DARKBLESSING, - NPC_BARRIER, - NPC_DEFENDER, - NPC_LICK, - NPC_HALLUCINATION, - NPC_REBIRTH, - NPC_SUMMONMONSTER, - - RG_SNATCHER, - RG_STEALCOIN, - RG_BACKSTAP, - RG_TUNNELDRIVE, - RG_RAID, - RG_STRIPWEAPON, - RG_STRIPSHIELD, - RG_STRIPARMOR, - RG_STRIPHELM, - RG_INTIMIDATE, - RG_GRAFFITI, - RG_FLAGGRAFFITI, - RG_CLEANER, - RG_GANGSTER, - RG_COMPULSION, - RG_PLAGIARISM, - - AM_AXEMASTERY, - AM_LEARNINGPOTION, - AM_PHARMACY, - AM_DEMONSTRATION, - AM_ACIDTERROR, - AM_POTIONPITCHER, - AM_CANNIBALIZE, - AM_SPHEREMINE, - AM_CP_WEAPON, - AM_CP_SHIELD, - AM_CP_ARMOR, - AM_CP_HELM, - AM_BIOETHICS, - AM_BIOTECHNOLOGY, - AM_CREATECREATURE, - AM_CULTIVATION, - AM_FLAMECONTROL, - AM_CALLHOMUN, - AM_REST, - AM_DRILLMASTER, - AM_HEALHOMUN, - AM_RESURRECTHOMUN, - - CR_TRUST, - CR_AUTOGUARD, - CR_SHIELDCHARGE, - CR_SHIELDBOOMERANG, - CR_REFLECTSHIELD, - CR_HOLYCROSS, - CR_GRANDCROSS, - CR_DEVOTION, - CR_PROVIDENCE, - CR_DEFENDER, - CR_SPEARQUICKEN, - - MO_IRONHAND, - MO_SPIRITSRECOVERY, - MO_CALLSPIRITS, - MO_ABSORBSPIRITS, - MO_TRIPLEATTACK, - MO_BODYRELOCATION, - MO_DODGE, - MO_INVESTIGATE, - MO_FINGEROFFENSIVE, - MO_STEELBODY, - MO_BLADESTOP, - MO_EXPLOSIONSPIRITS, - MO_EXTREMITYFIST, - MO_CHAINCOMBO, - MO_COMBOFINISH, - - SA_ADVANCEDBOOK, - SA_CASTCANCEL, - SA_MAGICROD, - SA_SPELLBREAKER, - SA_FREECAST, - SA_AUTOSPELL, - SA_FLAMELAUNCHER, - SA_FROSTWEAPON, - SA_LIGHTNINGLOADER, - SA_SEISMICWEAPON, - SA_DRAGONOLOGY, - SA_VOLCANO, - SA_DELUGE, - SA_VIOLENTGALE, - SA_LANDPROTECTOR, - SA_DISPELL, - SA_ABRACADABRA, - SA_MONOCELL, - SA_CLASSCHANGE, - SA_SUMMONMONSTER, - SA_REVERSEORCISH, - SA_DEATH, - SA_FORTUNE, - SA_TAMINGMONSTER, - SA_QUESTION, - SA_GRAVITY, - SA_LEVELUP, - SA_INSTANTDEATH, - SA_FULLRECOVERY, - SA_COMA, - - BD_ADAPTATION, - BD_ENCORE, - BD_LULLABY, - BD_RICHMANKIM, - BD_ETERNALCHAOS, - BD_DRUMBATTLEFIELD, - BD_RINGNIBELUNGEN, - BD_ROKISWEIL, - BD_INTOABYSS, - BD_SIEGFRIED, - BD_RAGNAROK, - - BA_MUSICALLESSON, - BA_MUSICALSTRIKE, - BA_DISSONANCE, - BA_FROSTJOKER, - BA_WHISTLE, - BA_ASSASSINCROSS, - BA_POEMBRAGI, - BA_APPLEIDUN, - - DC_DANCINGLESSON, - DC_THROWARROW, - DC_UGLYDANCE, - DC_SCREAM, - DC_HUMMING, - DC_DONTFORGETME, - DC_FORTUNEKISS, - DC_SERVICEFORYOU, - - NPC_RANDOMMOVE, - NPC_SPEEDUP, - NPC_REVENGE, - - WE_MALE, - WE_FEMALE, - WE_CALLPARTNER, - - ITM_TOMAHAWK, - - NPC_DARKCROSS, - NPC_GRANDDARKNESS, - NPC_DARKSTRIKE, - NPC_DARKTHUNDER, - NPC_STOP, - NPC_WEAPONBRAKER, - NPC_ARMORBRAKE, - NPC_HELMBRAKE, - NPC_SHIELDBRAKE, - NPC_UNDEADATTACK, - NPC_CHANGEUNDEAD, - NPC_POWERUP, - NPC_AGIUP, - NPC_SIEGEMODE, - NPC_CALLSLAVE, - NPC_INVISIBLE, - NPC_RUN, - - LK_AURABLADE, - LK_PARRYING, - LK_CONCENTRATION, - LK_TENSIONRELAX, - LK_BERSERK, - LK_FURY, - HP_ASSUMPTIO, - HP_BASILICA, - HP_MEDITATIO, - HW_SOULDRAIN, - HW_MAGICCRASHER, - HW_MAGICPOWER, - PA_PRESSURE, - PA_SACRIFICE, - PA_GOSPEL, - CH_PALMSTRIKE, - CH_TIGERFIST, - CH_CHAINCRUSH, - PF_HPCONVERSION, - PF_SOULCHANGE, - PF_SOULBURN, - ASC_KATAR, - ASC_HALLUCINATION, - ASC_EDP, - ASC_BREAKER, - SN_SIGHT, - SN_FALCONASSAULT, - SN_SHARPSHOOTING, - SN_WINDWALK, - WS_MELTDOWN, - WS_CREATECOIN, - WS_CREATENUGGET, - WS_CARTBOOST, - WS_SYSTEMCREATE, - ST_CHASEWALK, - ST_REJECTSWORD, - ST_STEALBACKPACK, - CR_ALCHEMY, - CR_SYNTHESISPOTION, - CG_ARROWVULCAN, - CG_MOONLIT, - CG_MARIONETTE, - LK_SPIRALPIERCE, - LK_HEADCRUSH, - LK_JOINTBEAT, - HW_NAPALMVULCAN, - CH_SOULCOLLECT, - PF_MINDBREAKER, - PF_MEMORIZE, - PF_FOGWALL, - PF_SPIDERWEB, - ASC_METEORASSAULT, - ASC_CDP, - WE_BABY, - WE_CALLPARENT, - WE_CALLBABY, - - TK_RUN, - TK_READYSTORM, - TK_STORMKICK, - TK_READYDOWN, - TK_DOWNKICK, - TK_READYTURN, - TK_TURNKICK, - TK_READYCOUNTER, - TK_COUNTER, - TK_DODGE, - TK_JUMPKICK, - TK_HPTIME, - TK_SPTIME, - TK_POWER, - TK_SEVENWIND, - TK_HIGHJUMP, - - SG_FEEL, - SG_SUN_WARM, - SG_MOON_WARM, - SG_STAR_WARM, - SG_SUN_COMFORT, - SG_MOON_COMFORT, - SG_STAR_COMFORT, - SG_HATE, - SG_SUN_ANGER, - SG_MOON_ANGER, - SG_STAR_ANGER, - SG_SUN_BLESS, - SG_MOON_BLESS, - SG_STAR_BLESS, - SG_DEVIL, - SG_FRIEND, - SG_KNOWLEDGE, - SG_FUSION, - - SL_ALCHEMIST, - AM_BERSERKPITCHER, - SL_MONK, - SL_STAR, - SL_SAGE, - SL_CRUSADER, - SL_SUPERNOVICE, - SL_KNIGHT, - SL_WIZARD, - SL_PRIEST, - SL_BARDDANCER, - SL_ROGUE, - SL_ASSASIN, - SL_BLACKSMITH, - BS_ADRENALINE2, - SL_HUNTER, - SL_SOULLINKER, - SL_KAIZEL, - SL_KAAHI, - SL_KAUPE, - SL_KAITE, - SL_KAINA, - SL_STIN, - SL_STUN, - SL_SMA, - SL_SWOO, - SL_SKE, - SL_SKA, - - SM_SELFPROVOKE, - NPC_EMOTION_ON, - ST_PRESERVE, - ST_FULLSTRIP, - WS_WEAPONREFINE, - CR_SLIMPITCHER, - CR_FULLPROTECTION, - PA_SHIELDCHAIN, - HP_MANARECHARGE, - PF_DOUBLECASTING, - HW_GANBANTEIN, - HW_GRAVITATION, - WS_CARTTERMINATION, - WS_OVERTHRUSTMAX, - CG_LONGINGFREEDOM, - CG_HERMODE, - CG_TAROTCARD, - CR_ACIDDEMONSTRATION, - CR_CULTIVATION, - ITEM_ENCHANTARMS, - TK_MISSION, - SL_HIGH, - KN_ONEHAND, - AM_TWILIGHT1, - AM_TWILIGHT2, - AM_TWILIGHT3, - HT_POWER, - - GS_GLITTERING, - GS_FLING, - GS_TRIPLEACTION, - GS_BULLSEYE, - GS_MADNESSCANCEL, - GS_ADJUSTMENT, - GS_INCREASING, - GS_MAGICALBULLET, - GS_CRACKER, - GS_SINGLEACTION, - GS_SNAKEEYE, - GS_CHAINACTION, - GS_TRACKING, - GS_DISARM, - GS_PIERCINGSHOT, - GS_RAPIDSHOWER, - GS_DESPERADO, - GS_GATLINGFEVER, - GS_DUST, - GS_FULLBUSTER, - GS_SPREADATTACK, - GS_GROUNDDRIFT, - - NJ_TOBIDOUGU, - NJ_SYURIKEN, - NJ_KUNAI, - NJ_HUUMA, - NJ_ZENYNAGE, - NJ_TATAMIGAESHI, - NJ_KASUMIKIRI, - NJ_SHADOWJUMP, - NJ_KIRIKAGE, - NJ_UTSUSEMI, - NJ_BUNSINJYUTSU, - NJ_NINPOU, - NJ_KOUENKA, - NJ_KAENSIN, - NJ_BAKUENRYU, - NJ_HYOUSENSOU, - NJ_SUITON, - NJ_HYOUSYOURAKU, - NJ_HUUJIN, - NJ_RAIGEKISAI, - NJ_KAMAITACHI, - NJ_NEN, - NJ_ISSEN, - - MB_FIGHTING, - MB_NEUTRAL, - MB_TAIMING_PUTI, - MB_WHITEPOTION, - MB_MENTAL, - MB_CARDPITCHER, - MB_PETPITCHER, - MB_BODYSTUDY, - MB_BODYALTER, - MB_PETMEMORY, - MB_M_TELEPORT, - MB_B_GAIN, - MB_M_GAIN, - MB_MISSION, - MB_MUNAKKNOWLEDGE, - MB_MUNAKBALL, - MB_SCROLL, - MB_B_GATHERING, - MB_M_GATHERING, - MB_B_EXCLUDE, - MB_B_DRIFT, - MB_B_WALLRUSH, - MB_M_WALLRUSH, - MB_B_WALLSHIFT, - MB_M_WALLCRASH, - MB_M_REINCARNATION, - MB_B_EQUIP, - - SL_DEATHKNIGHT, - SL_COLLECTOR, - SL_NINJA, - SL_GUNNER, - AM_TWILIGHT4, - DA_RESET, - DE_BERSERKAIZER, - DA_DARKPOWER, - - DE_PASSIVE, - DE_PATTACK, - DE_PSPEED, - DE_PDEFENSE, - DE_PCRITICAL, - DE_PHP, - DE_PSP, - DE_RESET, - DE_RANKING, - DE_PTRIPLE, - DE_ENERGY, - DE_NIGHTMARE, - DE_SLASH, - DE_COIL, - DE_WAVE, - DE_REBIRTH, - DE_AURA, - DE_FREEZER, - DE_CHANGEATTACK, - DE_PUNISH, - DE_POISON, - DE_INSTANT, - DE_WARNING, - DE_RANKEDKNIFE, - DE_RANKEDGRADIUS, - DE_GAUGE, - DE_GTIME, - DE_GPAIN, - DE_GSKILL, - DE_GKILL, - DE_ACCEL, - DE_BLOCKDOUBLE, - DE_BLOCKMELEE, - DE_BLOCKFAR, - DE_FRONTATTACK, - DE_DANGERATTACK, - DE_TWINATTACK, - DE_WINDATTACK, - DE_WATERATTACK, - - DA_ENERGY, - DA_CLOUD, - DA_FIRSTSLOT, - DA_HEADDEF, - DA_SPACE, - DA_TRANSFORM, - DA_EXPLOSION, - DA_REWARD, - DA_CRUSH, - DA_ITEMREBUILD, - DA_ILLUSION, - DA_NUETRALIZE, - DA_RUNNER, - DA_TRANSFER, - DA_WALL, - DA_ZENY, - DA_REVENGE, - DA_EARPLUG, - DA_CONTRACT, - DA_BLACK, - DA_DREAM, - DA_MAGICCART, - DA_COPY, - DA_CRYSTAL, - DA_EXP, - DA_CARTSWING, - DA_REBUILD, - DA_JOBCHANGE, - DA_EDARKNESS, - DA_EGUARDIAN, - DA_TIMEOUT, - ALL_TIMEIN, - DA_ZENYRANK, - DA_ACCESSORYMIX, - - NPC_EARTHQUAKE, - NPC_FIREBREATH, - NPC_ICEBREATH, - NPC_THUNDERBREATH, - NPC_ACIDBREATH, - NPC_DARKNESSBREATH, - NPC_DRAGONFEAR, - NPC_BLEEDING, - NPC_PULSESTRIKE, - NPC_HELLJUDGEMENT, - NPC_WIDESILENCE, - NPC_WIDEFREEZE, - NPC_WIDEBLEEDING, - NPC_WIDESTONE, - NPC_WIDECONFUSE, - NPC_WIDESLEEP, - NPC_WIDESIGHT, - NPC_EVILLAND, - NPC_MAGICMIRROR, - NPC_SLOWCAST, - NPC_CRITICALWOUND, - NPC_EXPULSION, - NPC_STONESKIN, - NPC_ANTIMAGIC, - NPC_WIDECURSE, - NPC_WIDESTUN, - NPC_VAMPIRE_GIFT, - NPC_WIDESOULDRAIN, - - ALL_INCCARRY, - NPC_TALK, - NPC_HELLPOWER, - NPC_WIDEHELLDIGNITY, - NPC_INVINCIBLE, - NPC_INVINCIBLEOFF, - NPC_ALLHEAL, - GM_SANDMAN, - CASH_BLESSING, - CASH_INCAGI, - CASH_ASSUMPTIO, - ALL_CATCRY, - ALL_PARTYFLEE, - ALL_ANGEL_PROTECT, - ALL_DREAM_SUMMERNIGHT, - NPC_CHANGEUNDEAD2, - ALL_REVERSEORCISH, - ALL_WEWISH, - ALL_SONKRAN, - NPC_WIDEHEALTHFEAR, - NPC_WIDEBODYBURNNING, - NPC_WIDEFROSTMISTY, - NPC_WIDECOLD, - NPC_WIDE_DEEP_SLEEP, - NPC_WIDESIREN, - NPC_VENOMFOG, - NPC_MILLENNIUMSHIELD, - NPC_COMET, - - KN_CHARGEATK = 1001, - CR_SHRINK, - AS_SONICACCEL, - AS_VENOMKNIFE, - RG_CLOSECONFINE, - WZ_SIGHTBLASTER, - SA_CREATECON, - SA_ELEMENTWATER, - HT_PHANTASMIC, - BA_PANGVOICE, - DC_WINKCHARM, - BS_UNFAIRLYTRICK, - BS_GREED, - PR_REDEMPTIO, - MO_KITRANSLATION, - MO_BALKYOUNG, - SA_ELEMENTGROUND, - SA_ELEMENTFIRE, - SA_ELEMENTWIND, - - RK_ENCHANTBLADE = 2001, - RK_SONICWAVE, - RK_DEATHBOUND, - RK_HUNDREDSPEAR, - RK_WINDCUTTER, - RK_IGNITIONBREAK, - RK_DRAGONTRAINING, - RK_DRAGONBREATH, - RK_DRAGONHOWLING, - RK_RUNEMASTERY, - RK_MILLENNIUMSHIELD, - RK_CRUSHSTRIKE, - RK_REFRESH, - RK_GIANTGROWTH, - RK_STONEHARDSKIN, - RK_VITALITYACTIVATION, - RK_STORMBLAST, - RK_FIGHTINGSPIRIT, - RK_ABUNDANCE, - RK_PHANTOMTHRUST, - - GC_VENOMIMPRESS, - GC_CROSSIMPACT, - GC_DARKILLUSION, - GC_RESEARCHNEWPOISON, - GC_CREATENEWPOISON, - GC_ANTIDOTE, - GC_POISONINGWEAPON, - GC_WEAPONBLOCKING, - GC_COUNTERSLASH, - GC_WEAPONCRUSH, - GC_VENOMPRESSURE, - GC_POISONSMOKE, - GC_CLOAKINGEXCEED, - GC_PHANTOMMENACE, - GC_HALLUCINATIONWALK, - GC_ROLLINGCUTTER, - GC_CROSSRIPPERSLASHER, - - AB_JUDEX, - AB_ANCILLA, - AB_ADORAMUS, - AB_CLEMENTIA, - AB_CANTO, - AB_CHEAL, - AB_EPICLESIS, - AB_PRAEFATIO, - AB_ORATIO, - AB_LAUDAAGNUS, - AB_LAUDARAMUS, - AB_EUCHARISTICA, - AB_RENOVATIO, - AB_HIGHNESSHEAL, - AB_CLEARANCE, - AB_EXPIATIO, - AB_DUPLELIGHT, - AB_DUPLELIGHT_MELEE, - AB_DUPLELIGHT_MAGIC, - AB_SILENTIUM, - - WL_WHITEIMPRISON = 2201, - WL_SOULEXPANSION, - WL_FROSTMISTY, - WL_JACKFROST, - WL_MARSHOFABYSS, - WL_RECOGNIZEDSPELL, - WL_SIENNAEXECRATE, - WL_RADIUS, - WL_STASIS, - WL_DRAINLIFE, - WL_CRIMSONROCK, - WL_HELLINFERNO, - WL_COMET, - WL_CHAINLIGHTNING, - WL_CHAINLIGHTNING_ATK, - WL_EARTHSTRAIN, - WL_TETRAVORTEX, - WL_TETRAVORTEX_FIRE, - WL_TETRAVORTEX_WATER, - WL_TETRAVORTEX_WIND, - WL_TETRAVORTEX_GROUND, - WL_SUMMONFB, - WL_SUMMONBL, - WL_SUMMONWB, - WL_SUMMON_ATK_FIRE, - WL_SUMMON_ATK_WIND, - WL_SUMMON_ATK_WATER, - WL_SUMMON_ATK_GROUND, - WL_SUMMONSTONE, - WL_RELEASE, - WL_READING_SB, - WL_FREEZE_SP, - - RA_ARROWSTORM, - RA_FEARBREEZE, - RA_RANGERMAIN, - RA_AIMEDBOLT, - RA_DETONATOR, - RA_ELECTRICSHOCKER, - RA_CLUSTERBOMB, - RA_WUGMASTERY, - RA_WUGRIDER, - RA_WUGDASH, - RA_WUGSTRIKE, - RA_WUGBITE, - RA_TOOTHOFWUG, - RA_SENSITIVEKEEN, - RA_CAMOUFLAGE, - RA_RESEARCHTRAP, - RA_MAGENTATRAP, - RA_COBALTTRAP, - RA_MAIZETRAP, - RA_VERDURETRAP, - RA_FIRINGTRAP, - RA_ICEBOUNDTRAP, - - NC_MADOLICENCE, - NC_BOOSTKNUCKLE, - NC_PILEBUNKER, - NC_VULCANARM, - NC_FLAMELAUNCHER, - NC_COLDSLOWER, - NC_ARMSCANNON, - NC_ACCELERATION, - NC_HOVERING, - NC_F_SIDESLIDE, - NC_B_SIDESLIDE, - NC_MAINFRAME, - NC_SELFDESTRUCTION, - NC_SHAPESHIFT, - NC_EMERGENCYCOOL, - NC_INFRAREDSCAN, - NC_ANALYZE, - NC_MAGNETICFIELD, - NC_NEUTRALBARRIER, - NC_STEALTHFIELD, - NC_REPAIR, - NC_TRAININGAXE, - NC_RESEARCHFE, - NC_AXEBOOMERANG, - NC_POWERSWING, - NC_AXETORNADO, - NC_SILVERSNIPER, - NC_MAGICDECOY, - NC_DISJOINT, - - SC_FATALMENACE, - SC_REPRODUCE, - SC_AUTOSHADOWSPELL, - SC_SHADOWFORM, - SC_TRIANGLESHOT, - SC_BODYPAINT, - SC_INVISIBILITY, - SC_DEADLYINFECT, - SC_ENERVATION, - SC_GROOMY, - SC_IGNORANCE, - SC_LAZINESS, - SC_UNLUCKY, - SC_WEAKNESS, - SC_STRIPACCESSARY, - SC_MANHOLE, - SC_DIMENSIONDOOR, - SC_CHAOSPANIC, - SC_MAELSTROM, - SC_BLOODYLUST, - SC_FEINTBOMB, - - LG_CANNONSPEAR = 2307, - LG_BANISHINGPOINT, - LG_TRAMPLE, - LG_SHIELDPRESS, - LG_REFLECTDAMAGE, - LG_PINPOINTATTACK, - LG_FORCEOFVANGUARD, - LG_RAGEBURST, - LG_SHIELDSPELL, - LG_EXEEDBREAK, - LG_OVERBRAND, - LG_PRESTIGE, - LG_BANDING, - LG_MOONSLASHER, - LG_RAYOFGENESIS, - LG_PIETY, - LG_EARTHDRIVE, - LG_HESPERUSLIT, - LG_INSPIRATION, - - SR_DRAGONCOMBO, - SR_SKYNETBLOW, - SR_EARTHSHAKER, - SR_FALLENEMPIRE, - SR_TIGERCANNON, - SR_HELLGATE, - SR_RAMPAGEBLASTER, - SR_CRESCENTELBOW, - SR_CURSEDCIRCLE, - SR_LIGHTNINGWALK, - SR_KNUCKLEARROW, - SR_WINDMILL, - SR_RAISINGDRAGON, - SR_GENTLETOUCH, - SR_ASSIMILATEPOWER, - SR_POWERVELOCITY, - SR_CRESCENTELBOW_AUTOSPELL, - SR_GATEOFHELL, - SR_GENTLETOUCH_QUIET, - SR_GENTLETOUCH_CURE, - SR_GENTLETOUCH_ENERGYGAIN, - SR_GENTLETOUCH_CHANGE, - SR_GENTLETOUCH_REVITALIZE, - - WA_SWING_DANCE = 2350, - WA_SYMPHONY_OF_LOVER, - WA_MOONLIT_SERENADE, - - MI_RUSH_WINDMILL = 2381, - MI_ECHOSONG, - MI_HARMONIZE, - - WM_LESSON = 2412, - WM_METALICSOUND, - WM_REVERBERATION, - WM_REVERBERATION_MELEE, - WM_REVERBERATION_MAGIC, - WM_DOMINION_IMPULSE, - WM_SEVERE_RAINSTORM, - WM_POEMOFNETHERWORLD, - WM_VOICEOFSIREN, - WM_DEADHILLHERE, - WM_LULLABY_DEEPSLEEP, - WM_SIRCLEOFNATURE, - WM_RANDOMIZESPELL, - WM_GLOOMYDAY, - WM_GREAT_ECHO, - WM_SONG_OF_MANA, - WM_DANCE_WITH_WUG, - WM_SOUND_OF_DESTRUCTION, - WM_SATURDAY_NIGHT_FEVER, - WM_LERADS_DEW, - WM_MELODYOFSINK, - WM_BEYOND_OF_WARCRY, - WM_UNLIMITED_HUMMING_VOICE, - - SO_FIREWALK = 2443, - SO_ELECTRICWALK, - SO_SPELLFIST, - SO_EARTHGRAVE, - SO_DIAMONDDUST, - SO_POISON_BUSTER, - SO_PSYCHIC_WAVE, - SO_CLOUD_KILL, - SO_STRIKING, - SO_WARMER, - SO_VACUUM_EXTREME, - SO_VARETYR_SPEAR, - SO_ARRULLO, - SO_EL_CONTROL, - SO_SUMMON_AGNI, - SO_SUMMON_AQUA, - SO_SUMMON_VENTUS, - SO_SUMMON_TERA, - SO_EL_ACTION, - SO_EL_ANALYSIS, - SO_EL_SYMPATHY, - SO_EL_CURE, - SO_FIRE_INSIGNIA, - SO_WATER_INSIGNIA, - SO_WIND_INSIGNIA, - SO_EARTH_INSIGNIA, - - GN_TRAINING_SWORD = 2474, - GN_REMODELING_CART, - GN_CART_TORNADO, - GN_CARTCANNON, - GN_CARTBOOST, - GN_THORNS_TRAP, - GN_BLOOD_SUCKER, - GN_SPORE_EXPLOSION, - GN_WALLOFTHORN, - GN_CRAZYWEED, - GN_CRAZYWEED_ATK, - GN_DEMONIC_FIRE, - GN_FIRE_EXPANSION, - GN_FIRE_EXPANSION_SMOKE_POWDER, - GN_FIRE_EXPANSION_TEAR_GAS, - GN_FIRE_EXPANSION_ACID, - GN_HELLS_PLANT, - GN_HELLS_PLANT_ATK, - GN_MANDRAGORA, - GN_SLINGITEM, - GN_CHANGEMATERIAL, - GN_MIX_COOKING, - GN_MAKEBOMB, - GN_S_PHARMACY, - GN_SLINGITEM_RANGEMELEEATK, - - AB_SECRAMENT = 2515, - WM_SEVERE_RAINSTORM_MELEE, - SR_HOWLINGOFLION, - SR_RIDEINLIGHTNING, - LG_OVERBRAND_BRANDISH, - LG_OVERBRAND_PLUSATK, - - ALL_ODINS_RECALL = 2533, - RETURN_TO_ELDICASTES, - ALL_BUYING_STORE, - ALL_GUARDIAN_RECALL, - ALL_ODINS_POWER, - BEER_BOTTLE_CAP, - NPC_ASSASSINCROSS, - NPC_DISSONANCE, - NPC_UGLYDANCE, - ALL_TETANY, - ALL_RAY_OF_PROTECTION, - MC_CARTDECORATE, - - KO_YAMIKUMO = 3001, - KO_RIGHT, - KO_LEFT, - KO_JYUMONJIKIRI, - KO_SETSUDAN, - KO_BAKURETSU, - KO_HAPPOKUNAI, - KO_MUCHANAGE, - KO_HUUMARANKA, - KO_MAKIBISHI, - KO_MEIKYOUSISUI, - KO_ZANZOU, - KO_KYOUGAKU, - KO_JYUSATSU, - KO_KAHU_ENTEN, - KO_HYOUHU_HUBUKI, - KO_KAZEHU_SEIRAN, - KO_DOHU_KOUKAI, - KO_KAIHOU, - KO_ZENKAI, - KO_GENWAKU, - KO_IZAYOI, - KG_KAGEHUMI, - KG_KYOMU, - KG_KAGEMUSYA, - OB_ZANGETSU, - OB_OBOROGENSOU, - OB_OBOROGENSOU_TRANSITION_ATK, - OB_AKAITSUKI, - - ECL_SNOWFLIP = 3031, - ECL_PEONYMAMY, - ECL_SADAGUI, - ECL_SEQUOIADUST, - ECLAGE_RECALL, - - HLIF_HEAL = 8001, - HLIF_AVOID, - HLIF_BRAIN, - HLIF_CHANGE, - HAMI_CASTLE, - HAMI_DEFENCE, - HAMI_SKIN, - HAMI_BLOODLUST, - HFLI_MOON, - HFLI_FLEET, - HFLI_SPEED, - HFLI_SBR44, - HVAN_CAPRICE, - HVAN_CHAOTIC, - HVAN_INSTRUCT, - HVAN_EXPLOSION, - MUTATION_BASEJOB, - MH_SUMMON_LEGION, - MH_NEEDLE_OF_PARALYZE, - MH_POISON_MIST, - MH_PAIN_KILLER, - MH_LIGHT_OF_REGENE, - MH_OVERED_BOOST, - MH_ERASER_CUTTER, - MH_XENO_SLASHER, - MH_SILENT_BREEZE, - MH_STYLE_CHANGE, - MH_SONIC_CRAW, - MH_SILVERVEIN_RUSH, - MH_MIDNIGHT_FRENZY, - MH_STAHL_HORN, - MH_GOLDENE_FERSE, - MH_STEINWAND, - MH_HEILIGE_STANGE, - MH_ANGRIFFS_MODUS, - MH_TINDER_BREAKER, - MH_CBC, - MH_EQC, - MH_MAGMA_FLOW, - MH_GRANITIC_ARMOR, - MH_LAVA_SLIDE, - MH_PYROCLASTIC, - MH_VOLCANIC_ASH, - - MS_BASH = 8201, - MS_MAGNUM, - MS_BOWLINGBASH, - MS_PARRYING, - MS_REFLECTSHIELD, - MS_BERSERK, - MA_DOUBLE, - MA_SHOWER, - MA_SKIDTRAP, - MA_LANDMINE, - MA_SANDMAN, - MA_FREEZINGTRAP, - MA_REMOVETRAP, - MA_CHARGEARROW, - MA_SHARPSHOOTING, - ML_PIERCE, - ML_BRANDISH, - ML_SPIRALPIERCE, - ML_DEFENDER, - ML_AUTOGUARD, - ML_DEVOTION, - MER_MAGNIFICAT, - MER_QUICKEN, - MER_SIGHT, - MER_CRASH, - MER_REGAIN, - MER_TENDER, - MER_BENEDICTION, - MER_RECUPERATE, - MER_MENTALCURE, - MER_COMPRESS, - MER_PROVOKE, - MER_AUTOBERSERK, - MER_DECAGI, - MER_SCAPEGOAT, - MER_LEXDIVINA, - MER_ESTIMATION, - MER_KYRIE, - MER_BLESSING, - MER_INCAGI, - - EL_CIRCLE_OF_FIRE = 8401, - EL_FIRE_CLOAK, - EL_FIRE_MANTLE, - EL_WATER_SCREEN, - EL_WATER_DROP, - EL_WATER_BARRIER, - EL_WIND_STEP, - EL_WIND_CURTAIN, - EL_ZEPHYR, - EL_SOLID_SKIN, - EL_STONE_SHIELD, - EL_POWER_OF_GAIA, - EL_PYROTECHNIC, - EL_HEATER, - EL_TROPIC, - EL_AQUAPLAY, - EL_COOLER, - EL_CHILLY_AIR, - EL_GUST, - EL_BLAST, - EL_WILD_STORM, - EL_PETROLOGY, - EL_CURSED_SOIL, - EL_UPHEAVAL, - EL_FIRE_ARROW, - EL_FIRE_BOMB, - EL_FIRE_BOMB_ATK, - EL_FIRE_WAVE, - EL_FIRE_WAVE_ATK, - EL_ICE_NEEDLE, - EL_WATER_SCREW, - EL_WATER_SCREW_ATK, - EL_TIDAL_WEAPON, - EL_WIND_SLASH, - EL_HURRICANE, - EL_HURRICANE_ATK, - EL_TYPOON_MIS, - EL_TYPOON_MIS_ATK, - EL_STONE_HAMMER, - EL_ROCK_CRUSHER, - EL_ROCK_CRUSHER_ATK, - EL_STONE_RAIN, + NV_BASIC = 1, + + SM_SWORD, + SM_TWOHAND, + SM_RECOVERY, + SM_BASH, + SM_PROVOKE, + SM_MAGNUM, + SM_ENDURE, + + MG_SRECOVERY, + MG_SIGHT, + MG_NAPALMBEAT, + MG_SAFETYWALL, + MG_SOULSTRIKE, + MG_COLDBOLT, + MG_FROSTDIVER, + MG_STONECURSE, + MG_FIREBALL, + MG_FIREWALL, + MG_FIREBOLT, + MG_LIGHTNINGBOLT, + MG_THUNDERSTORM, + + AL_DP, + AL_DEMONBANE, + AL_RUWACH, + AL_PNEUMA, + AL_TELEPORT, + AL_WARP, + AL_HEAL, + AL_INCAGI, + AL_DECAGI, + AL_HOLYWATER, + AL_CRUCIS, + AL_ANGELUS, + AL_BLESSING, + AL_CURE, + + MC_INCCARRY, + MC_DISCOUNT, + MC_OVERCHARGE, + MC_PUSHCART, + MC_IDENTIFY, + MC_VENDING, + MC_MAMMONITE, + + AC_OWL, + AC_VULTURE, + AC_CONCENTRATION, + AC_DOUBLE, + AC_SHOWER, + + TF_DOUBLE, + TF_MISS, + TF_STEAL, + TF_HIDING, + TF_POISON, + TF_DETOXIFY, + + ALL_RESURRECTION, + + KN_SPEARMASTERY, + KN_PIERCE, + KN_BRANDISHSPEAR, + KN_SPEARSTAB, + KN_SPEARBOOMERANG, + KN_TWOHANDQUICKEN, + KN_AUTOCOUNTER, + KN_BOWLINGBASH, + KN_RIDING, + KN_CAVALIERMASTERY, + + PR_MACEMASTERY, + PR_IMPOSITIO, + PR_SUFFRAGIUM, + PR_ASPERSIO, + PR_BENEDICTIO, + PR_SANCTUARY, + PR_SLOWPOISON, + PR_STRECOVERY, + PR_KYRIE, + PR_MAGNIFICAT, + PR_GLORIA, + PR_LEXDIVINA, + PR_TURNUNDEAD, + PR_LEXAETERNA, + PR_MAGNUS, + + WZ_FIREPILLAR, + WZ_SIGHTRASHER, + WZ_FIREIVY, + WZ_METEOR, + WZ_JUPITEL, + WZ_VERMILION, + WZ_WATERBALL, + WZ_ICEWALL, + WZ_FROSTNOVA, + WZ_STORMGUST, + WZ_EARTHSPIKE, + WZ_HEAVENDRIVE, + WZ_QUAGMIRE, + WZ_ESTIMATION, + + BS_IRON, + BS_STEEL, + BS_ENCHANTEDSTONE, + BS_ORIDEOCON, + BS_DAGGER, + BS_SWORD, + BS_TWOHANDSWORD, + BS_AXE, + BS_MACE, + BS_KNUCKLE, + BS_SPEAR, + BS_HILTBINDING, + BS_FINDINGORE, + BS_WEAPONRESEARCH, + BS_REPAIRWEAPON, + BS_SKINTEMPER, + BS_HAMMERFALL, + BS_ADRENALINE, + BS_WEAPONPERFECT, + BS_OVERTHRUST, + BS_MAXIMIZE, + + HT_SKIDTRAP, + HT_LANDMINE, + HT_ANKLESNARE, + HT_SHOCKWAVE, + HT_SANDMAN, + HT_FLASHER, + HT_FREEZINGTRAP, + HT_BLASTMINE, + HT_CLAYMORETRAP, + HT_REMOVETRAP, + HT_TALKIEBOX, + HT_BEASTBANE, + HT_FALCON, + HT_STEELCROW, + HT_BLITZBEAT, + HT_DETECTING, + HT_SPRINGTRAP, + + AS_RIGHT, + AS_LEFT, + AS_KATAR, + AS_CLOAKING, + AS_SONICBLOW, + AS_GRIMTOOTH, + AS_ENCHANTPOISON, + AS_POISONREACT, + AS_VENOMDUST, + AS_SPLASHER, + + NV_FIRSTAID, + NV_TRICKDEAD, + SM_MOVINGRECOVERY, + SM_FATALBLOW, + SM_AUTOBERSERK, + AC_MAKINGARROW, + AC_CHARGEARROW, + TF_SPRINKLESAND, + TF_BACKSLIDING, + TF_PICKSTONE, + TF_THROWSTONE, + MC_CARTREVOLUTION, + MC_CHANGECART, + MC_LOUD, + AL_HOLYLIGHT, + MG_ENERGYCOAT, + + NPC_PIERCINGATT, + NPC_MENTALBREAKER, + NPC_RANGEATTACK, + NPC_ATTRICHANGE, + NPC_CHANGEWATER, + NPC_CHANGEGROUND, + NPC_CHANGEFIRE, + NPC_CHANGEWIND, + NPC_CHANGEPOISON, + NPC_CHANGEHOLY, + NPC_CHANGEDARKNESS, + NPC_CHANGETELEKINESIS, + NPC_CRITICALSLASH, + NPC_COMBOATTACK, + NPC_GUIDEDATTACK, + NPC_SELFDESTRUCTION, + NPC_SPLASHATTACK, + NPC_SUICIDE, + NPC_POISON, + NPC_BLINDATTACK, + NPC_SILENCEATTACK, + NPC_STUNATTACK, + NPC_PETRIFYATTACK, + NPC_CURSEATTACK, + NPC_SLEEPATTACK, + NPC_RANDOMATTACK, + NPC_WATERATTACK, + NPC_GROUNDATTACK, + NPC_FIREATTACK, + NPC_WINDATTACK, + NPC_POISONATTACK, + NPC_HOLYATTACK, + NPC_DARKNESSATTACK, + NPC_TELEKINESISATTACK, + NPC_MAGICALATTACK, + NPC_METAMORPHOSIS, + NPC_PROVOCATION, + NPC_SMOKING, + NPC_SUMMONSLAVE, + NPC_EMOTION, + NPC_TRANSFORMATION, + NPC_BLOODDRAIN, + NPC_ENERGYDRAIN, + NPC_KEEPING, + NPC_DARKBREATH, + NPC_DARKBLESSING, + NPC_BARRIER, + NPC_DEFENDER, + NPC_LICK, + NPC_HALLUCINATION, + NPC_REBIRTH, + NPC_SUMMONMONSTER, + + RG_SNATCHER, + RG_STEALCOIN, + RG_BACKSTAP, + RG_TUNNELDRIVE, + RG_RAID, + RG_STRIPWEAPON, + RG_STRIPSHIELD, + RG_STRIPARMOR, + RG_STRIPHELM, + RG_INTIMIDATE, + RG_GRAFFITI, + RG_FLAGGRAFFITI, + RG_CLEANER, + RG_GANGSTER, + RG_COMPULSION, + RG_PLAGIARISM, + + AM_AXEMASTERY, + AM_LEARNINGPOTION, + AM_PHARMACY, + AM_DEMONSTRATION, + AM_ACIDTERROR, + AM_POTIONPITCHER, + AM_CANNIBALIZE, + AM_SPHEREMINE, + AM_CP_WEAPON, + AM_CP_SHIELD, + AM_CP_ARMOR, + AM_CP_HELM, + AM_BIOETHICS, + AM_BIOTECHNOLOGY, + AM_CREATECREATURE, + AM_CULTIVATION, + AM_FLAMECONTROL, + AM_CALLHOMUN, + AM_REST, + AM_DRILLMASTER, + AM_HEALHOMUN, + AM_RESURRECTHOMUN, + + CR_TRUST, + CR_AUTOGUARD, + CR_SHIELDCHARGE, + CR_SHIELDBOOMERANG, + CR_REFLECTSHIELD, + CR_HOLYCROSS, + CR_GRANDCROSS, + CR_DEVOTION, + CR_PROVIDENCE, + CR_DEFENDER, + CR_SPEARQUICKEN, + + MO_IRONHAND, + MO_SPIRITSRECOVERY, + MO_CALLSPIRITS, + MO_ABSORBSPIRITS, + MO_TRIPLEATTACK, + MO_BODYRELOCATION, + MO_DODGE, + MO_INVESTIGATE, + MO_FINGEROFFENSIVE, + MO_STEELBODY, + MO_BLADESTOP, + MO_EXPLOSIONSPIRITS, + MO_EXTREMITYFIST, + MO_CHAINCOMBO, + MO_COMBOFINISH, + + SA_ADVANCEDBOOK, + SA_CASTCANCEL, + SA_MAGICROD, + SA_SPELLBREAKER, + SA_FREECAST, + SA_AUTOSPELL, + SA_FLAMELAUNCHER, + SA_FROSTWEAPON, + SA_LIGHTNINGLOADER, + SA_SEISMICWEAPON, + SA_DRAGONOLOGY, + SA_VOLCANO, + SA_DELUGE, + SA_VIOLENTGALE, + SA_LANDPROTECTOR, + SA_DISPELL, + SA_ABRACADABRA, + SA_MONOCELL, + SA_CLASSCHANGE, + SA_SUMMONMONSTER, + SA_REVERSEORCISH, + SA_DEATH, + SA_FORTUNE, + SA_TAMINGMONSTER, + SA_QUESTION, + SA_GRAVITY, + SA_LEVELUP, + SA_INSTANTDEATH, + SA_FULLRECOVERY, + SA_COMA, + + BD_ADAPTATION, + BD_ENCORE, + BD_LULLABY, + BD_RICHMANKIM, + BD_ETERNALCHAOS, + BD_DRUMBATTLEFIELD, + BD_RINGNIBELUNGEN, + BD_ROKISWEIL, + BD_INTOABYSS, + BD_SIEGFRIED, + BD_RAGNAROK, + + BA_MUSICALLESSON, + BA_MUSICALSTRIKE, + BA_DISSONANCE, + BA_FROSTJOKER, + BA_WHISTLE, + BA_ASSASSINCROSS, + BA_POEMBRAGI, + BA_APPLEIDUN, + + DC_DANCINGLESSON, + DC_THROWARROW, + DC_UGLYDANCE, + DC_SCREAM, + DC_HUMMING, + DC_DONTFORGETME, + DC_FORTUNEKISS, + DC_SERVICEFORYOU, + + NPC_RANDOMMOVE, + NPC_SPEEDUP, + NPC_REVENGE, + + WE_MALE, + WE_FEMALE, + WE_CALLPARTNER, + + ITM_TOMAHAWK, + + NPC_DARKCROSS, + NPC_GRANDDARKNESS, + NPC_DARKSTRIKE, + NPC_DARKTHUNDER, + NPC_STOP, + NPC_WEAPONBRAKER, + NPC_ARMORBRAKE, + NPC_HELMBRAKE, + NPC_SHIELDBRAKE, + NPC_UNDEADATTACK, + NPC_CHANGEUNDEAD, + NPC_POWERUP, + NPC_AGIUP, + NPC_SIEGEMODE, + NPC_CALLSLAVE, + NPC_INVISIBLE, + NPC_RUN, + + LK_AURABLADE, + LK_PARRYING, + LK_CONCENTRATION, + LK_TENSIONRELAX, + LK_BERSERK, + LK_FURY, + HP_ASSUMPTIO, + HP_BASILICA, + HP_MEDITATIO, + HW_SOULDRAIN, + HW_MAGICCRASHER, + HW_MAGICPOWER, + PA_PRESSURE, + PA_SACRIFICE, + PA_GOSPEL, + CH_PALMSTRIKE, + CH_TIGERFIST, + CH_CHAINCRUSH, + PF_HPCONVERSION, + PF_SOULCHANGE, + PF_SOULBURN, + ASC_KATAR, + ASC_HALLUCINATION, + ASC_EDP, + ASC_BREAKER, + SN_SIGHT, + SN_FALCONASSAULT, + SN_SHARPSHOOTING, + SN_WINDWALK, + WS_MELTDOWN, + WS_CREATECOIN, + WS_CREATENUGGET, + WS_CARTBOOST, + WS_SYSTEMCREATE, + ST_CHASEWALK, + ST_REJECTSWORD, + ST_STEALBACKPACK, + CR_ALCHEMY, + CR_SYNTHESISPOTION, + CG_ARROWVULCAN, + CG_MOONLIT, + CG_MARIONETTE, + LK_SPIRALPIERCE, + LK_HEADCRUSH, + LK_JOINTBEAT, + HW_NAPALMVULCAN, + CH_SOULCOLLECT, + PF_MINDBREAKER, + PF_MEMORIZE, + PF_FOGWALL, + PF_SPIDERWEB, + ASC_METEORASSAULT, + ASC_CDP, + WE_BABY, + WE_CALLPARENT, + WE_CALLBABY, + + TK_RUN, + TK_READYSTORM, + TK_STORMKICK, + TK_READYDOWN, + TK_DOWNKICK, + TK_READYTURN, + TK_TURNKICK, + TK_READYCOUNTER, + TK_COUNTER, + TK_DODGE, + TK_JUMPKICK, + TK_HPTIME, + TK_SPTIME, + TK_POWER, + TK_SEVENWIND, + TK_HIGHJUMP, + + SG_FEEL, + SG_SUN_WARM, + SG_MOON_WARM, + SG_STAR_WARM, + SG_SUN_COMFORT, + SG_MOON_COMFORT, + SG_STAR_COMFORT, + SG_HATE, + SG_SUN_ANGER, + SG_MOON_ANGER, + SG_STAR_ANGER, + SG_SUN_BLESS, + SG_MOON_BLESS, + SG_STAR_BLESS, + SG_DEVIL, + SG_FRIEND, + SG_KNOWLEDGE, + SG_FUSION, + + SL_ALCHEMIST, + AM_BERSERKPITCHER, + SL_MONK, + SL_STAR, + SL_SAGE, + SL_CRUSADER, + SL_SUPERNOVICE, + SL_KNIGHT, + SL_WIZARD, + SL_PRIEST, + SL_BARDDANCER, + SL_ROGUE, + SL_ASSASIN, + SL_BLACKSMITH, + BS_ADRENALINE2, + SL_HUNTER, + SL_SOULLINKER, + SL_KAIZEL, + SL_KAAHI, + SL_KAUPE, + SL_KAITE, + SL_KAINA, + SL_STIN, + SL_STUN, + SL_SMA, + SL_SWOO, + SL_SKE, + SL_SKA, + + SM_SELFPROVOKE, + NPC_EMOTION_ON, + ST_PRESERVE, + ST_FULLSTRIP, + WS_WEAPONREFINE, + CR_SLIMPITCHER, + CR_FULLPROTECTION, + PA_SHIELDCHAIN, + HP_MANARECHARGE, + PF_DOUBLECASTING, + HW_GANBANTEIN, + HW_GRAVITATION, + WS_CARTTERMINATION, + WS_OVERTHRUSTMAX, + CG_LONGINGFREEDOM, + CG_HERMODE, + CG_TAROTCARD, + CR_ACIDDEMONSTRATION, + CR_CULTIVATION, + ITEM_ENCHANTARMS, + TK_MISSION, + SL_HIGH, + KN_ONEHAND, + AM_TWILIGHT1, + AM_TWILIGHT2, + AM_TWILIGHT3, + HT_POWER, + + GS_GLITTERING, + GS_FLING, + GS_TRIPLEACTION, + GS_BULLSEYE, + GS_MADNESSCANCEL, + GS_ADJUSTMENT, + GS_INCREASING, + GS_MAGICALBULLET, + GS_CRACKER, + GS_SINGLEACTION, + GS_SNAKEEYE, + GS_CHAINACTION, + GS_TRACKING, + GS_DISARM, + GS_PIERCINGSHOT, + GS_RAPIDSHOWER, + GS_DESPERADO, + GS_GATLINGFEVER, + GS_DUST, + GS_FULLBUSTER, + GS_SPREADATTACK, + GS_GROUNDDRIFT, + + NJ_TOBIDOUGU, + NJ_SYURIKEN, + NJ_KUNAI, + NJ_HUUMA, + NJ_ZENYNAGE, + NJ_TATAMIGAESHI, + NJ_KASUMIKIRI, + NJ_SHADOWJUMP, + NJ_KIRIKAGE, + NJ_UTSUSEMI, + NJ_BUNSINJYUTSU, + NJ_NINPOU, + NJ_KOUENKA, + NJ_KAENSIN, + NJ_BAKUENRYU, + NJ_HYOUSENSOU, + NJ_SUITON, + NJ_HYOUSYOURAKU, + NJ_HUUJIN, + NJ_RAIGEKISAI, + NJ_KAMAITACHI, + NJ_NEN, + NJ_ISSEN, + + MB_FIGHTING, + MB_NEUTRAL, + MB_TAIMING_PUTI, + MB_WHITEPOTION, + MB_MENTAL, + MB_CARDPITCHER, + MB_PETPITCHER, + MB_BODYSTUDY, + MB_BODYALTER, + MB_PETMEMORY, + MB_M_TELEPORT, + MB_B_GAIN, + MB_M_GAIN, + MB_MISSION, + MB_MUNAKKNOWLEDGE, + MB_MUNAKBALL, + MB_SCROLL, + MB_B_GATHERING, + MB_M_GATHERING, + MB_B_EXCLUDE, + MB_B_DRIFT, + MB_B_WALLRUSH, + MB_M_WALLRUSH, + MB_B_WALLSHIFT, + MB_M_WALLCRASH, + MB_M_REINCARNATION, + MB_B_EQUIP, + + SL_DEATHKNIGHT, + SL_COLLECTOR, + SL_NINJA, + SL_GUNNER, + AM_TWILIGHT4, + DA_RESET, + DE_BERSERKAIZER, + DA_DARKPOWER, + + DE_PASSIVE, + DE_PATTACK, + DE_PSPEED, + DE_PDEFENSE, + DE_PCRITICAL, + DE_PHP, + DE_PSP, + DE_RESET, + DE_RANKING, + DE_PTRIPLE, + DE_ENERGY, + DE_NIGHTMARE, + DE_SLASH, + DE_COIL, + DE_WAVE, + DE_REBIRTH, + DE_AURA, + DE_FREEZER, + DE_CHANGEATTACK, + DE_PUNISH, + DE_POISON, + DE_INSTANT, + DE_WARNING, + DE_RANKEDKNIFE, + DE_RANKEDGRADIUS, + DE_GAUGE, + DE_GTIME, + DE_GPAIN, + DE_GSKILL, + DE_GKILL, + DE_ACCEL, + DE_BLOCKDOUBLE, + DE_BLOCKMELEE, + DE_BLOCKFAR, + DE_FRONTATTACK, + DE_DANGERATTACK, + DE_TWINATTACK, + DE_WINDATTACK, + DE_WATERATTACK, + + DA_ENERGY, + DA_CLOUD, + DA_FIRSTSLOT, + DA_HEADDEF, + DA_SPACE, + DA_TRANSFORM, + DA_EXPLOSION, + DA_REWARD, + DA_CRUSH, + DA_ITEMREBUILD, + DA_ILLUSION, + DA_NUETRALIZE, + DA_RUNNER, + DA_TRANSFER, + DA_WALL, + DA_ZENY, + DA_REVENGE, + DA_EARPLUG, + DA_CONTRACT, + DA_BLACK, + DA_DREAM, + DA_MAGICCART, + DA_COPY, + DA_CRYSTAL, + DA_EXP, + DA_CARTSWING, + DA_REBUILD, + DA_JOBCHANGE, + DA_EDARKNESS, + DA_EGUARDIAN, + DA_TIMEOUT, + ALL_TIMEIN, + DA_ZENYRANK, + DA_ACCESSORYMIX, + + NPC_EARTHQUAKE, + NPC_FIREBREATH, + NPC_ICEBREATH, + NPC_THUNDERBREATH, + NPC_ACIDBREATH, + NPC_DARKNESSBREATH, + NPC_DRAGONFEAR, + NPC_BLEEDING, + NPC_PULSESTRIKE, + NPC_HELLJUDGEMENT, + NPC_WIDESILENCE, + NPC_WIDEFREEZE, + NPC_WIDEBLEEDING, + NPC_WIDESTONE, + NPC_WIDECONFUSE, + NPC_WIDESLEEP, + NPC_WIDESIGHT, + NPC_EVILLAND, + NPC_MAGICMIRROR, + NPC_SLOWCAST, + NPC_CRITICALWOUND, + NPC_EXPULSION, + NPC_STONESKIN, + NPC_ANTIMAGIC, + NPC_WIDECURSE, + NPC_WIDESTUN, + NPC_VAMPIRE_GIFT, + NPC_WIDESOULDRAIN, + + ALL_INCCARRY, + NPC_TALK, + NPC_HELLPOWER, + NPC_WIDEHELLDIGNITY, + NPC_INVINCIBLE, + NPC_INVINCIBLEOFF, + NPC_ALLHEAL, + GM_SANDMAN, + CASH_BLESSING, + CASH_INCAGI, + CASH_ASSUMPTIO, + ALL_CATCRY, + ALL_PARTYFLEE, + ALL_ANGEL_PROTECT, + ALL_DREAM_SUMMERNIGHT, + NPC_CHANGEUNDEAD2, + ALL_REVERSEORCISH, + ALL_WEWISH, + ALL_SONKRAN, + NPC_WIDEHEALTHFEAR, + NPC_WIDEBODYBURNNING, + NPC_WIDEFROSTMISTY, + NPC_WIDECOLD, + NPC_WIDE_DEEP_SLEEP, + NPC_WIDESIREN, + NPC_VENOMFOG, + NPC_MILLENNIUMSHIELD, + NPC_COMET, + + KN_CHARGEATK = 1001, + CR_SHRINK, + AS_SONICACCEL, + AS_VENOMKNIFE, + RG_CLOSECONFINE, + WZ_SIGHTBLASTER, + SA_CREATECON, + SA_ELEMENTWATER, + HT_PHANTASMIC, + BA_PANGVOICE, + DC_WINKCHARM, + BS_UNFAIRLYTRICK, + BS_GREED, + PR_REDEMPTIO, + MO_KITRANSLATION, + MO_BALKYOUNG, + SA_ELEMENTGROUND, + SA_ELEMENTFIRE, + SA_ELEMENTWIND, + + RK_ENCHANTBLADE = 2001, + RK_SONICWAVE, + RK_DEATHBOUND, + RK_HUNDREDSPEAR, + RK_WINDCUTTER, + RK_IGNITIONBREAK, + RK_DRAGONTRAINING, + RK_DRAGONBREATH, + RK_DRAGONHOWLING, + RK_RUNEMASTERY, + RK_MILLENNIUMSHIELD, + RK_CRUSHSTRIKE, + RK_REFRESH, + RK_GIANTGROWTH, + RK_STONEHARDSKIN, + RK_VITALITYACTIVATION, + RK_STORMBLAST, + RK_FIGHTINGSPIRIT, + RK_ABUNDANCE, + RK_PHANTOMTHRUST, + + GC_VENOMIMPRESS, + GC_CROSSIMPACT, + GC_DARKILLUSION, + GC_RESEARCHNEWPOISON, + GC_CREATENEWPOISON, + GC_ANTIDOTE, + GC_POISONINGWEAPON, + GC_WEAPONBLOCKING, + GC_COUNTERSLASH, + GC_WEAPONCRUSH, + GC_VENOMPRESSURE, + GC_POISONSMOKE, + GC_CLOAKINGEXCEED, + GC_PHANTOMMENACE, + GC_HALLUCINATIONWALK, + GC_ROLLINGCUTTER, + GC_CROSSRIPPERSLASHER, + + AB_JUDEX, + AB_ANCILLA, + AB_ADORAMUS, + AB_CLEMENTIA, + AB_CANTO, + AB_CHEAL, + AB_EPICLESIS, + AB_PRAEFATIO, + AB_ORATIO, + AB_LAUDAAGNUS, + AB_LAUDARAMUS, + AB_EUCHARISTICA, + AB_RENOVATIO, + AB_HIGHNESSHEAL, + AB_CLEARANCE, + AB_EXPIATIO, + AB_DUPLELIGHT, + AB_DUPLELIGHT_MELEE, + AB_DUPLELIGHT_MAGIC, + AB_SILENTIUM, + + WL_WHITEIMPRISON = 2201, + WL_SOULEXPANSION, + WL_FROSTMISTY, + WL_JACKFROST, + WL_MARSHOFABYSS, + WL_RECOGNIZEDSPELL, + WL_SIENNAEXECRATE, + WL_RADIUS, + WL_STASIS, + WL_DRAINLIFE, + WL_CRIMSONROCK, + WL_HELLINFERNO, + WL_COMET, + WL_CHAINLIGHTNING, + WL_CHAINLIGHTNING_ATK, + WL_EARTHSTRAIN, + WL_TETRAVORTEX, + WL_TETRAVORTEX_FIRE, + WL_TETRAVORTEX_WATER, + WL_TETRAVORTEX_WIND, + WL_TETRAVORTEX_GROUND, + WL_SUMMONFB, + WL_SUMMONBL, + WL_SUMMONWB, + WL_SUMMON_ATK_FIRE, + WL_SUMMON_ATK_WIND, + WL_SUMMON_ATK_WATER, + WL_SUMMON_ATK_GROUND, + WL_SUMMONSTONE, + WL_RELEASE, + WL_READING_SB, + WL_FREEZE_SP, + + RA_ARROWSTORM, + RA_FEARBREEZE, + RA_RANGERMAIN, + RA_AIMEDBOLT, + RA_DETONATOR, + RA_ELECTRICSHOCKER, + RA_CLUSTERBOMB, + RA_WUGMASTERY, + RA_WUGRIDER, + RA_WUGDASH, + RA_WUGSTRIKE, + RA_WUGBITE, + RA_TOOTHOFWUG, + RA_SENSITIVEKEEN, + RA_CAMOUFLAGE, + RA_RESEARCHTRAP, + RA_MAGENTATRAP, + RA_COBALTTRAP, + RA_MAIZETRAP, + RA_VERDURETRAP, + RA_FIRINGTRAP, + RA_ICEBOUNDTRAP, + + NC_MADOLICENCE, + NC_BOOSTKNUCKLE, + NC_PILEBUNKER, + NC_VULCANARM, + NC_FLAMELAUNCHER, + NC_COLDSLOWER, + NC_ARMSCANNON, + NC_ACCELERATION, + NC_HOVERING, + NC_F_SIDESLIDE, + NC_B_SIDESLIDE, + NC_MAINFRAME, + NC_SELFDESTRUCTION, + NC_SHAPESHIFT, + NC_EMERGENCYCOOL, + NC_INFRAREDSCAN, + NC_ANALYZE, + NC_MAGNETICFIELD, + NC_NEUTRALBARRIER, + NC_STEALTHFIELD, + NC_REPAIR, + NC_TRAININGAXE, + NC_RESEARCHFE, + NC_AXEBOOMERANG, + NC_POWERSWING, + NC_AXETORNADO, + NC_SILVERSNIPER, + NC_MAGICDECOY, + NC_DISJOINT, + + SC_FATALMENACE, + SC_REPRODUCE, + SC_AUTOSHADOWSPELL, + SC_SHADOWFORM, + SC_TRIANGLESHOT, + SC_BODYPAINT, + SC_INVISIBILITY, + SC_DEADLYINFECT, + SC_ENERVATION, + SC_GROOMY, + SC_IGNORANCE, + SC_LAZINESS, + SC_UNLUCKY, + SC_WEAKNESS, + SC_STRIPACCESSARY, + SC_MANHOLE, + SC_DIMENSIONDOOR, + SC_CHAOSPANIC, + SC_MAELSTROM, + SC_BLOODYLUST, + SC_FEINTBOMB, + + LG_CANNONSPEAR = 2307, + LG_BANISHINGPOINT, + LG_TRAMPLE, + LG_SHIELDPRESS, + LG_REFLECTDAMAGE, + LG_PINPOINTATTACK, + LG_FORCEOFVANGUARD, + LG_RAGEBURST, + LG_SHIELDSPELL, + LG_EXEEDBREAK, + LG_OVERBRAND, + LG_PRESTIGE, + LG_BANDING, + LG_MOONSLASHER, + LG_RAYOFGENESIS, + LG_PIETY, + LG_EARTHDRIVE, + LG_HESPERUSLIT, + LG_INSPIRATION, + + SR_DRAGONCOMBO, + SR_SKYNETBLOW, + SR_EARTHSHAKER, + SR_FALLENEMPIRE, + SR_TIGERCANNON, + SR_HELLGATE, + SR_RAMPAGEBLASTER, + SR_CRESCENTELBOW, + SR_CURSEDCIRCLE, + SR_LIGHTNINGWALK, + SR_KNUCKLEARROW, + SR_WINDMILL, + SR_RAISINGDRAGON, + SR_GENTLETOUCH, + SR_ASSIMILATEPOWER, + SR_POWERVELOCITY, + SR_CRESCENTELBOW_AUTOSPELL, + SR_GATEOFHELL, + SR_GENTLETOUCH_QUIET, + SR_GENTLETOUCH_CURE, + SR_GENTLETOUCH_ENERGYGAIN, + SR_GENTLETOUCH_CHANGE, + SR_GENTLETOUCH_REVITALIZE, + + WA_SWING_DANCE = 2350, + WA_SYMPHONY_OF_LOVER, + WA_MOONLIT_SERENADE, + + MI_RUSH_WINDMILL = 2381, + MI_ECHOSONG, + MI_HARMONIZE, + + WM_LESSON = 2412, + WM_METALICSOUND, + WM_REVERBERATION, + WM_REVERBERATION_MELEE, + WM_REVERBERATION_MAGIC, + WM_DOMINION_IMPULSE, + WM_SEVERE_RAINSTORM, + WM_POEMOFNETHERWORLD, + WM_VOICEOFSIREN, + WM_DEADHILLHERE, + WM_LULLABY_DEEPSLEEP, + WM_SIRCLEOFNATURE, + WM_RANDOMIZESPELL, + WM_GLOOMYDAY, + WM_GREAT_ECHO, + WM_SONG_OF_MANA, + WM_DANCE_WITH_WUG, + WM_SOUND_OF_DESTRUCTION, + WM_SATURDAY_NIGHT_FEVER, + WM_LERADS_DEW, + WM_MELODYOFSINK, + WM_BEYOND_OF_WARCRY, + WM_UNLIMITED_HUMMING_VOICE, + + SO_FIREWALK = 2443, + SO_ELECTRICWALK, + SO_SPELLFIST, + SO_EARTHGRAVE, + SO_DIAMONDDUST, + SO_POISON_BUSTER, + SO_PSYCHIC_WAVE, + SO_CLOUD_KILL, + SO_STRIKING, + SO_WARMER, + SO_VACUUM_EXTREME, + SO_VARETYR_SPEAR, + SO_ARRULLO, + SO_EL_CONTROL, + SO_SUMMON_AGNI, + SO_SUMMON_AQUA, + SO_SUMMON_VENTUS, + SO_SUMMON_TERA, + SO_EL_ACTION, + SO_EL_ANALYSIS, + SO_EL_SYMPATHY, + SO_EL_CURE, + SO_FIRE_INSIGNIA, + SO_WATER_INSIGNIA, + SO_WIND_INSIGNIA, + SO_EARTH_INSIGNIA, + + GN_TRAINING_SWORD = 2474, + GN_REMODELING_CART, + GN_CART_TORNADO, + GN_CARTCANNON, + GN_CARTBOOST, + GN_THORNS_TRAP, + GN_BLOOD_SUCKER, + GN_SPORE_EXPLOSION, + GN_WALLOFTHORN, + GN_CRAZYWEED, + GN_CRAZYWEED_ATK, + GN_DEMONIC_FIRE, + GN_FIRE_EXPANSION, + GN_FIRE_EXPANSION_SMOKE_POWDER, + GN_FIRE_EXPANSION_TEAR_GAS, + GN_FIRE_EXPANSION_ACID, + GN_HELLS_PLANT, + GN_HELLS_PLANT_ATK, + GN_MANDRAGORA, + GN_SLINGITEM, + GN_CHANGEMATERIAL, + GN_MIX_COOKING, + GN_MAKEBOMB, + GN_S_PHARMACY, + GN_SLINGITEM_RANGEMELEEATK, + + AB_SECRAMENT = 2515, + WM_SEVERE_RAINSTORM_MELEE, + SR_HOWLINGOFLION, + SR_RIDEINLIGHTNING, + LG_OVERBRAND_BRANDISH, + LG_OVERBRAND_PLUSATK, + + ALL_ODINS_RECALL = 2533, + RETURN_TO_ELDICASTES, + ALL_BUYING_STORE, + ALL_GUARDIAN_RECALL, + ALL_ODINS_POWER, + BEER_BOTTLE_CAP, + NPC_ASSASSINCROSS, + NPC_DISSONANCE, + NPC_UGLYDANCE, + ALL_TETANY, + ALL_RAY_OF_PROTECTION, + MC_CARTDECORATE, + + KO_YAMIKUMO = 3001, + KO_RIGHT, + KO_LEFT, + KO_JYUMONJIKIRI, + KO_SETSUDAN, + KO_BAKURETSU, + KO_HAPPOKUNAI, + KO_MUCHANAGE, + KO_HUUMARANKA, + KO_MAKIBISHI, + KO_MEIKYOUSISUI, + KO_ZANZOU, + KO_KYOUGAKU, + KO_JYUSATSU, + KO_KAHU_ENTEN, + KO_HYOUHU_HUBUKI, + KO_KAZEHU_SEIRAN, + KO_DOHU_KOUKAI, + KO_KAIHOU, + KO_ZENKAI, + KO_GENWAKU, + KO_IZAYOI, + KG_KAGEHUMI, + KG_KYOMU, + KG_KAGEMUSYA, + OB_ZANGETSU, + OB_OBOROGENSOU, + OB_OBOROGENSOU_TRANSITION_ATK, + OB_AKAITSUKI, + + ECL_SNOWFLIP = 3031, + ECL_PEONYMAMY, + ECL_SADAGUI, + ECL_SEQUOIADUST, + ECLAGE_RECALL, + + HLIF_HEAL = 8001, + HLIF_AVOID, + HLIF_BRAIN, + HLIF_CHANGE, + HAMI_CASTLE, + HAMI_DEFENCE, + HAMI_SKIN, + HAMI_BLOODLUST, + HFLI_MOON, + HFLI_FLEET, + HFLI_SPEED, + HFLI_SBR44, + HVAN_CAPRICE, + HVAN_CHAOTIC, + HVAN_INSTRUCT, + HVAN_EXPLOSION, + MUTATION_BASEJOB, + MH_SUMMON_LEGION, + MH_NEEDLE_OF_PARALYZE, + MH_POISON_MIST, + MH_PAIN_KILLER, + MH_LIGHT_OF_REGENE, + MH_OVERED_BOOST, + MH_ERASER_CUTTER, + MH_XENO_SLASHER, + MH_SILENT_BREEZE, + MH_STYLE_CHANGE, + MH_SONIC_CRAW, + MH_SILVERVEIN_RUSH, + MH_MIDNIGHT_FRENZY, + MH_STAHL_HORN, + MH_GOLDENE_FERSE, + MH_STEINWAND, + MH_HEILIGE_STANGE, + MH_ANGRIFFS_MODUS, + MH_TINDER_BREAKER, + MH_CBC, + MH_EQC, + MH_MAGMA_FLOW, + MH_GRANITIC_ARMOR, + MH_LAVA_SLIDE, + MH_PYROCLASTIC, + MH_VOLCANIC_ASH, + + MS_BASH = 8201, + MS_MAGNUM, + MS_BOWLINGBASH, + MS_PARRYING, + MS_REFLECTSHIELD, + MS_BERSERK, + MA_DOUBLE, + MA_SHOWER, + MA_SKIDTRAP, + MA_LANDMINE, + MA_SANDMAN, + MA_FREEZINGTRAP, + MA_REMOVETRAP, + MA_CHARGEARROW, + MA_SHARPSHOOTING, + ML_PIERCE, + ML_BRANDISH, + ML_SPIRALPIERCE, + ML_DEFENDER, + ML_AUTOGUARD, + ML_DEVOTION, + MER_MAGNIFICAT, + MER_QUICKEN, + MER_SIGHT, + MER_CRASH, + MER_REGAIN, + MER_TENDER, + MER_BENEDICTION, + MER_RECUPERATE, + MER_MENTALCURE, + MER_COMPRESS, + MER_PROVOKE, + MER_AUTOBERSERK, + MER_DECAGI, + MER_SCAPEGOAT, + MER_LEXDIVINA, + MER_ESTIMATION, + MER_KYRIE, + MER_BLESSING, + MER_INCAGI, + + EL_CIRCLE_OF_FIRE = 8401, + EL_FIRE_CLOAK, + EL_FIRE_MANTLE, + EL_WATER_SCREEN, + EL_WATER_DROP, + EL_WATER_BARRIER, + EL_WIND_STEP, + EL_WIND_CURTAIN, + EL_ZEPHYR, + EL_SOLID_SKIN, + EL_STONE_SHIELD, + EL_POWER_OF_GAIA, + EL_PYROTECHNIC, + EL_HEATER, + EL_TROPIC, + EL_AQUAPLAY, + EL_COOLER, + EL_CHILLY_AIR, + EL_GUST, + EL_BLAST, + EL_WILD_STORM, + EL_PETROLOGY, + EL_CURSED_SOIL, + EL_UPHEAVAL, + EL_FIRE_ARROW, + EL_FIRE_BOMB, + EL_FIRE_BOMB_ATK, + EL_FIRE_WAVE, + EL_FIRE_WAVE_ATK, + EL_ICE_NEEDLE, + EL_WATER_SCREW, + EL_WATER_SCREW_ATK, + EL_TIDAL_WEAPON, + EL_WIND_SLASH, + EL_HURRICANE, + EL_HURRICANE_ATK, + EL_TYPOON_MIS, + EL_TYPOON_MIS_ATK, + EL_STONE_HAMMER, + EL_ROCK_CRUSHER, + EL_ROCK_CRUSHER_ATK, + EL_STONE_RAIN, }; /// The client view ids for land skills. enum { - UNT_SAFETYWALL = 0x7e, - UNT_FIREWALL, - UNT_WARP_WAITING, - UNT_WARP_ACTIVE, - UNT_BENEDICTIO, //TODO - UNT_SANCTUARY, - UNT_MAGNUS, - UNT_PNEUMA, - UNT_DUMMYSKILL, //These show no effect on the client - UNT_FIREPILLAR_WAITING, - UNT_FIREPILLAR_ACTIVE, - UNT_HIDDEN_TRAP, //TODO - UNT_TRAP, //TODO - UNT_HIDDEN_WARP_NPC, //TODO - UNT_USED_TRAPS, - UNT_ICEWALL, - UNT_QUAGMIRE, - UNT_BLASTMINE, - UNT_SKIDTRAP, - UNT_ANKLESNARE, - UNT_VENOMDUST, - UNT_LANDMINE, - UNT_SHOCKWAVE, - UNT_SANDMAN, - UNT_FLASHER, - UNT_FREEZINGTRAP, - UNT_CLAYMORETRAP, - UNT_TALKIEBOX, - UNT_VOLCANO, - UNT_DELUGE, - UNT_VIOLENTGALE, - UNT_LANDPROTECTOR, - UNT_LULLABY, - UNT_RICHMANKIM, - UNT_ETERNALCHAOS, - UNT_DRUMBATTLEFIELD, - UNT_RINGNIBELUNGEN, - UNT_ROKISWEIL, - UNT_INTOABYSS, - UNT_SIEGFRIED, - UNT_DISSONANCE, - UNT_WHISTLE, - UNT_ASSASSINCROSS, - UNT_POEMBRAGI, - UNT_APPLEIDUN, - UNT_UGLYDANCE, - UNT_HUMMING, - UNT_DONTFORGETME, - UNT_FORTUNEKISS, - UNT_SERVICEFORYOU, - UNT_GRAFFITI, - UNT_DEMONSTRATION, - UNT_CALLFAMILY, - UNT_GOSPEL, - UNT_BASILICA, - UNT_MOONLIT, - UNT_FOGWALL, - UNT_SPIDERWEB, - UNT_GRAVITATION, - UNT_HERMODE, - UNT_KAENSIN, //TODO - UNT_SUITON, - UNT_TATAMIGAESHI, - UNT_KAEN, - UNT_GROUNDDRIFT_WIND, - UNT_GROUNDDRIFT_DARK, - UNT_GROUNDDRIFT_POISON, - UNT_GROUNDDRIFT_WATER, - UNT_GROUNDDRIFT_FIRE, - UNT_DEATHWAVE, //TODO - UNT_WATERATTACK, //TODO - UNT_WINDATTACK, //TODO - UNT_EARTHQUAKE, //TODO - UNT_EVILLAND, - UNT_DARK_RUNNER, //TODO - UNT_DARK_TRANSFER, //TODO - UNT_EPICLESIS, - UNT_EARTHSTRAIN, - UNT_MANHOLE, - UNT_DIMENSIONDOOR, - UNT_CHAOSPANIC, - UNT_MAELSTROM, - UNT_BLOODYLUST, - UNT_FEINTBOMB, - UNT_MAGENTATRAP, - UNT_COBALTTRAP, - UNT_MAIZETRAP, - UNT_VERDURETRAP, - UNT_FIRINGTRAP, - UNT_ICEBOUNDTRAP, - UNT_ELECTRICSHOCKER, - UNT_CLUSTERBOMB, - UNT_REVERBERATION, - UNT_SEVERE_RAINSTORM, - UNT_FIREWALK, - UNT_ELECTRICWALK, - UNT_NETHERWORLD, - UNT_PSYCHIC_WAVE, - UNT_CLOUD_KILL, - UNT_POISONSMOKE, - UNT_NEUTRALBARRIER, - UNT_STEALTHFIELD, - UNT_WARMER, - UNT_THORNS_TRAP, - UNT_WALLOFTHORN, - UNT_DEMONIC_FIRE, - UNT_FIRE_EXPANSION_SMOKE_POWDER, - UNT_FIRE_EXPANSION_TEAR_GAS, - UNT_HELLS_PLANT, - UNT_VACUUM_EXTREME, - UNT_BANDING, - UNT_FIRE_MANTLE, - UNT_WATER_BARRIER, - UNT_ZEPHYR, - UNT_POWER_OF_GAIA, - UNT_FIRE_INSIGNIA, - UNT_WATER_INSIGNIA, - UNT_WIND_INSIGNIA, - UNT_EARTH_INSIGNIA, - UNT_POISON_MIST, - UNT_LAVA_SLIDE, - UNT_VOLCANIC_ASH, - UNT_ZENKAI_WATER, - UNT_ZENKAI_LAND, - UNT_ZENKAI_FIRE, - UNT_ZENKAI_WIND, - UNT_MAKIBISHI, - UNT_VENOMFOG, - - /** - * Guild Auras - **/ - UNT_GD_LEADERSHIP = 0xc1, - UNT_GD_GLORYWOUNDS = 0xc2, - UNT_GD_SOULCOLD = 0xc3, - UNT_GD_HAWKEYES = 0xc4, - - UNT_MAX = 0x190 + UNT_SAFETYWALL = 0x7e, + UNT_FIREWALL, + UNT_WARP_WAITING, + UNT_WARP_ACTIVE, + UNT_BENEDICTIO, //TODO + UNT_SANCTUARY, + UNT_MAGNUS, + UNT_PNEUMA, + UNT_DUMMYSKILL, //These show no effect on the client + UNT_FIREPILLAR_WAITING, + UNT_FIREPILLAR_ACTIVE, + UNT_HIDDEN_TRAP, //TODO + UNT_TRAP, //TODO + UNT_HIDDEN_WARP_NPC, //TODO + UNT_USED_TRAPS, + UNT_ICEWALL, + UNT_QUAGMIRE, + UNT_BLASTMINE, + UNT_SKIDTRAP, + UNT_ANKLESNARE, + UNT_VENOMDUST, + UNT_LANDMINE, + UNT_SHOCKWAVE, + UNT_SANDMAN, + UNT_FLASHER, + UNT_FREEZINGTRAP, + UNT_CLAYMORETRAP, + UNT_TALKIEBOX, + UNT_VOLCANO, + UNT_DELUGE, + UNT_VIOLENTGALE, + UNT_LANDPROTECTOR, + UNT_LULLABY, + UNT_RICHMANKIM, + UNT_ETERNALCHAOS, + UNT_DRUMBATTLEFIELD, + UNT_RINGNIBELUNGEN, + UNT_ROKISWEIL, + UNT_INTOABYSS, + UNT_SIEGFRIED, + UNT_DISSONANCE, + UNT_WHISTLE, + UNT_ASSASSINCROSS, + UNT_POEMBRAGI, + UNT_APPLEIDUN, + UNT_UGLYDANCE, + UNT_HUMMING, + UNT_DONTFORGETME, + UNT_FORTUNEKISS, + UNT_SERVICEFORYOU, + UNT_GRAFFITI, + UNT_DEMONSTRATION, + UNT_CALLFAMILY, + UNT_GOSPEL, + UNT_BASILICA, + UNT_MOONLIT, + UNT_FOGWALL, + UNT_SPIDERWEB, + UNT_GRAVITATION, + UNT_HERMODE, + UNT_KAENSIN, //TODO + UNT_SUITON, + UNT_TATAMIGAESHI, + UNT_KAEN, + UNT_GROUNDDRIFT_WIND, + UNT_GROUNDDRIFT_DARK, + UNT_GROUNDDRIFT_POISON, + UNT_GROUNDDRIFT_WATER, + UNT_GROUNDDRIFT_FIRE, + UNT_DEATHWAVE, //TODO + UNT_WATERATTACK, //TODO + UNT_WINDATTACK, //TODO + UNT_EARTHQUAKE, //TODO + UNT_EVILLAND, + UNT_DARK_RUNNER, //TODO + UNT_DARK_TRANSFER, //TODO + UNT_EPICLESIS, + UNT_EARTHSTRAIN, + UNT_MANHOLE, + UNT_DIMENSIONDOOR, + UNT_CHAOSPANIC, + UNT_MAELSTROM, + UNT_BLOODYLUST, + UNT_FEINTBOMB, + UNT_MAGENTATRAP, + UNT_COBALTTRAP, + UNT_MAIZETRAP, + UNT_VERDURETRAP, + UNT_FIRINGTRAP, + UNT_ICEBOUNDTRAP, + UNT_ELECTRICSHOCKER, + UNT_CLUSTERBOMB, + UNT_REVERBERATION, + UNT_SEVERE_RAINSTORM, + UNT_FIREWALK, + UNT_ELECTRICWALK, + UNT_NETHERWORLD, + UNT_PSYCHIC_WAVE, + UNT_CLOUD_KILL, + UNT_POISONSMOKE, + UNT_NEUTRALBARRIER, + UNT_STEALTHFIELD, + UNT_WARMER, + UNT_THORNS_TRAP, + UNT_WALLOFTHORN, + UNT_DEMONIC_FIRE, + UNT_FIRE_EXPANSION_SMOKE_POWDER, + UNT_FIRE_EXPANSION_TEAR_GAS, + UNT_HELLS_PLANT, + UNT_VACUUM_EXTREME, + UNT_BANDING, + UNT_FIRE_MANTLE, + UNT_WATER_BARRIER, + UNT_ZEPHYR, + UNT_POWER_OF_GAIA, + UNT_FIRE_INSIGNIA, + UNT_WATER_INSIGNIA, + UNT_WIND_INSIGNIA, + UNT_EARTH_INSIGNIA, + UNT_POISON_MIST, + UNT_LAVA_SLIDE, + UNT_VOLCANIC_ASH, + UNT_ZENKAI_WATER, + UNT_ZENKAI_LAND, + UNT_ZENKAI_FIRE, + UNT_ZENKAI_WIND, + UNT_MAKIBISHI, + UNT_VENOMFOG, + + /** + * Guild Auras + **/ + UNT_GD_LEADERSHIP = 0xc1, + UNT_GD_GLORYWOUNDS = 0xc2, + UNT_GD_SOULCOLD = 0xc3, + UNT_GD_HAWKEYES = 0xc4, + + UNT_MAX = 0x190 }; /** * Skill Unit Save **/ -void skill_usave_add(struct map_session_data *sd, int skill_num, int skill_lv); +void skill_usave_add(struct map_session_data * sd, int skill_num, int skill_lv); void skill_usave_trigger(struct map_session_data *sd); /** * Skill Cool Downs - load from pc.c when the character logs in **/ -void skill_cooldown_load(struct map_session_data *sd); +void skill_cooldown_load(struct map_session_data * sd); /** * Warlock **/ -#define MAX_SKILL_SPELLBOOK_DB 17 +#define MAX_SKILL_SPELLBOOK_DB 17 enum wl_spheres { - WLS_FIRE = 0x44, - WLS_WIND, - WLS_WATER, - WLS_STONE, + WLS_FIRE = 0x44, + WLS_WIND, + WLS_WATER, + WLS_STONE, }; -int skill_spellbook(struct map_session_data *sd, int nameid); +int skill_spellbook (struct map_session_data *sd, int nameid); int skill_block_check(struct block_list *bl, enum sc_type type, int skillid); /** * Guilottine Cross **/ #define MAX_SKILL_MAGICMUSHROOM_DB 23 struct s_skill_magicmushroom_db { - int skillid; + int skillid; }; extern struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB]; /** @@ -1834,16 +1838,16 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid); /** * Guiltoine Cross **/ -int skill_poisoningweapon(struct map_session_data *sd, int nameid); +int skill_poisoningweapon( struct map_session_data *sd, int nameid); enum gx_poison { - PO_PARALYSE = 12717, - PO_LEECHESEND, - PO_OBLIVIONCURSE, - PO_DEATHHURT, - PO_TOXIN, - PO_PYREXIA, - PO_MAGICMUSHROOM, - PO_VENOMBLEED + PO_PARALYSE = 12717, + PO_LEECHESEND, + PO_OBLIVIONCURSE, + PO_DEATHHURT, + PO_TOXIN, + PO_PYREXIA, + PO_MAGICMUSHROOM, + PO_VENOMBLEED }; /** * Auto Shadow Spell (Shadow Chaser) @@ -1851,7 +1855,7 @@ enum gx_poison { int skill_select_menu(struct map_session_data *sd,int skill_id); int skill_elementalanalysis(struct map_session_data *sd, int n, int type, unsigned short *item_list); // Sorcerer Four Elemental Analisys. -int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list); // Genetic Change Material. +int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list); // Genetic Change Material. int skill_get_elemental_type(int skill_id, int skill_lv); #endif /* _SKILL_H_ */ diff --git a/src/map/status.c b/src/map/status.c index c534233f8..a24011292 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -40,11 +40,12 @@ #include <math.h> //Regen related flags. -enum e_regen { - RGN_HP = 0x01, - RGN_SP = 0x02, - RGN_SHP = 0x04, - RGN_SSP = 0x08, +enum e_regen +{ + RGN_HP = 0x01, + RGN_SP = 0x02, + RGN_SHP = 0x04, + RGN_SSP = 0x08, }; static int max_weight_base[CLASS_COUNT]; @@ -55,17 +56,17 @@ static int sp_coefficient[CLASS_COUNT]; #ifdef RENEWAL_ASPD static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; #else -static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE]; //[blackhole89] +static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE]; //[blackhole89] #endif // bonus values and upgrade chances for refining equipment static struct { - int chance[MAX_REFINE]; // success chance - int bonus[MAX_REFINE]; // cumulative fixed bonus damage - int randombonus_max[MAX_REFINE]; // cumulative maximum random bonus damage + int chance[MAX_REFINE]; // success chance + int bonus[MAX_REFINE]; // cumulative fixed bonus damage + int randombonus_max[MAX_REFINE]; // cumulative maximum random bonus damage } refine_info[REFINE_TYPE_MAX]; -static int atkmods[3][MAX_WEAPON_TYPE]; //ATK weapon modification for size (size_fix.txt) +static int atkmods[3][MAX_WEAPON_TYPE]; //ATK weapon modification for size (size_fix.txt) static char job_bonus[CLASS_COUNT][MAX_LEVEL]; static struct eri *sc_data_ers; //For sc_data entries @@ -91,12 +92,12 @@ static unsigned int StatusChangeStateTable[SC_MAX]; // status -> flags **/ sc_type status_skill2sc(int skill) { - int sk = skill_get_index(skill); - if (sk == 0) { - ShowError("status_skill2sc: Unsupported skill id %d\n", skill); - return SC_NONE; - } - return SkillStatusChangeTable[sk]; + int sk = skill_get_index(skill); + if( sk == 0 ) { + ShowError("status_skill2sc: Unsupported skill id %d\n", skill); + return SC_NONE; + } + return SkillStatusChangeTable[sk]; } /** @@ -107,12 +108,12 @@ sc_type status_skill2sc(int skill) **/ int status_sc2skill(sc_type sc) { - if (sc < 0 || sc >= SC_MAX) { - ShowError("status_sc2skill: Unsupported status change id %d\n", sc); - return 0; - } + if( sc < 0 || sc >= SC_MAX ) { + ShowError("status_sc2skill: Unsupported status change id %d\n", sc); + return 0; + } - return StatusSkillChangeTable[sc]; + return StatusSkillChangeTable[sc]; } /** @@ -122,12 +123,12 @@ int status_sc2skill(sc_type sc) **/ unsigned int status_sc2scb_flag(sc_type sc) { - if (sc < 0 || sc >= SC_MAX) { - ShowError("status_sc2scb_flag: Unsupported status change id %d\n", sc); - return SCB_NONE; - } + if( sc < 0 || sc >= SC_MAX ) { + ShowError("status_sc2scb_flag: Unsupported status change id %d\n", sc); + return SCB_NONE; + } - return StatusChangeFlagTable[sc]; + return StatusChangeFlagTable[sc]; } /** @@ -137,12 +138,12 @@ unsigned int status_sc2scb_flag(sc_type sc) **/ int status_type2relevant_bl_types(int type) { - if (type < 0 || type >= SI_MAX) { - ShowError("status_type2relevant_bl_types: Unsupported type %d\n", type); - return SI_BLANK; - } + if( type < 0 || type >= SI_MAX ) { + ShowError("status_type2relevant_bl_types: Unsupported type %d\n", type); + return SI_BLANK; + } - return StatusRelevantBLTypes[type]; + return StatusRelevantBLTypes[type]; } #define add_sc(skill,sc) set_sc(skill,sc,SI_BLANK,SCB_NONE) @@ -151,933 +152,932 @@ int status_type2relevant_bl_types(int type) static void set_sc(int skill, sc_type sc, int icon, unsigned int flag) { - int sk = skill_get_index(skill); - if (sk == 0) { - ShowError("set_sc: Unsupported skill id %d\n", skill); - return; - } - if (sc < 0 || sc >= SC_MAX) { - ShowError("set_sc: Unsupported status change id %d\n", sc); - return; - } - - if (StatusSkillChangeTable[sc] == 0) - StatusSkillChangeTable[sc] = skill; - if (StatusIconChangeTable[sc] == SI_BLANK) - StatusIconChangeTable[sc] = icon; - StatusChangeFlagTable[sc] |= flag; - - if (SkillStatusChangeTable[sk] == SC_NONE) - SkillStatusChangeTable[sk] = sc; + int sk = skill_get_index(skill); + if( sk == 0 ) { + ShowError("set_sc: Unsupported skill id %d\n", skill); + return; + } + if( sc < 0 || sc >= SC_MAX ) { + ShowError("set_sc: Unsupported status change id %d\n", sc); + return; + } + + if( StatusSkillChangeTable[sc] == 0 ) + StatusSkillChangeTable[sc] = skill; + if( StatusIconChangeTable[sc] == SI_BLANK ) + StatusIconChangeTable[sc] = icon; + StatusChangeFlagTable[sc] |= flag; + + if( SkillStatusChangeTable[sk] == SC_NONE ) + SkillStatusChangeTable[sk] = sc; } -void initChangeTables(void) -{ - int i; - - for (i = 0; i < SC_MAX; i++) - StatusIconChangeTable[i] = SI_BLANK; - - for (i = 0; i < MAX_SKILL; i++) - SkillStatusChangeTable[i] = SC_NONE; - - for (i = 0; i < SI_MAX; i++) - StatusRelevantBLTypes[i] = BL_PC; - - memset(StatusSkillChangeTable, 0, sizeof(StatusSkillChangeTable)); - memset(StatusChangeFlagTable, 0, sizeof(StatusChangeFlagTable)); - memset(StatusChangeStateTable, 0, sizeof(StatusChangeStateTable)); - - - //First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex] - set_sc(NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF); - set_sc(NPC_WIDEFREEZE , SC_FREEZE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF); - set_sc(NPC_STUNATTACK , SC_STUN , SI_BLANK , SCB_NONE); - set_sc(NPC_SLEEPATTACK , SC_SLEEP , SI_BLANK , SCB_NONE); - set_sc(NPC_POISON , SC_POISON , SI_BLANK , SCB_DEF2|SCB_REGEN); - set_sc(NPC_CURSEATTACK , SC_CURSE , SI_BLANK , SCB_LUK|SCB_BATK|SCB_WATK|SCB_SPEED); - set_sc(NPC_SILENCEATTACK , SC_SILENCE , SI_BLANK , SCB_NONE); - set_sc(NPC_WIDECONFUSE , SC_CONFUSION , SI_BLANK , SCB_NONE); - set_sc(NPC_BLINDATTACK , SC_BLIND , SI_BLANK , SCB_HIT|SCB_FLEE); - set_sc(NPC_BLEEDING , SC_BLEEDING , SI_BLEEDING , SCB_REGEN); - set_sc(NPC_POISON , SC_DPOISON , SI_BLANK , SCB_DEF2|SCB_REGEN); - - //The main status definitions - add_sc(SM_BASH , SC_STUN); - set_sc(SM_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK); - add_sc(SM_MAGNUM , SC_WATK_ELEMENT); - set_sc(SM_ENDURE , SC_ENDURE , SI_ENDURE , SCB_MDEF|SCB_DSPD); - add_sc(MG_SIGHT , SC_SIGHT); - add_sc(MG_SAFETYWALL , SC_SAFETYWALL); - add_sc(MG_FROSTDIVER , SC_FREEZE); - add_sc(MG_STONECURSE , SC_STONE); - add_sc(AL_RUWACH , SC_RUWACH); - add_sc(AL_PNEUMA , SC_PNEUMA); - set_sc(AL_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED); - set_sc(AL_DECAGI , SC_DECREASEAGI , SI_DECREASEAGI , SCB_AGI|SCB_SPEED); - set_sc(AL_CRUCIS , SC_SIGNUMCRUCIS , SI_SIGNUMCRUCIS , SCB_DEF); - set_sc(AL_ANGELUS , SC_ANGELUS , SI_ANGELUS , SCB_DEF2); - set_sc(AL_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX); - set_sc(AC_CONCENTRATION , SC_CONCENTRATE , SI_CONCENTRATE , SCB_AGI|SCB_DEX); - set_sc(TF_HIDING , SC_HIDING , SI_HIDING , SCB_SPEED); - add_sc(TF_POISON , SC_POISON); - set_sc(KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD); - add_sc(KN_AUTOCOUNTER , SC_AUTOCOUNTER); - set_sc(PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO , SCB_WATK); - set_sc(PR_SUFFRAGIUM , SC_SUFFRAGIUM , SI_SUFFRAGIUM , SCB_NONE); - set_sc(PR_ASPERSIO , SC_ASPERSIO , SI_ASPERSIO , SCB_ATK_ELE); - set_sc(PR_BENEDICTIO , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE); - set_sc(PR_SLOWPOISON , SC_SLOWPOISON , SI_SLOWPOISON , SCB_REGEN); - set_sc(PR_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE); - set_sc(PR_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN); - set_sc(PR_GLORIA , SC_GLORIA , SI_GLORIA , SCB_LUK); - add_sc(PR_LEXDIVINA , SC_SILENCE); - set_sc(PR_LEXAETERNA , SC_AETERNA , SI_AETERNA , SCB_NONE); - add_sc(WZ_METEOR , SC_STUN); - add_sc(WZ_VERMILION , SC_BLIND); - add_sc(WZ_FROSTNOVA , SC_FREEZE); - add_sc(WZ_STORMGUST , SC_FREEZE); - set_sc(WZ_QUAGMIRE , SC_QUAGMIRE , SI_QUAGMIRE , SCB_AGI|SCB_DEX|SCB_ASPD|SCB_SPEED); - set_sc(BS_ADRENALINE , SC_ADRENALINE , SI_ADRENALINE , SCB_ASPD); - set_sc(BS_WEAPONPERFECT , SC_WEAPONPERFECTION, SI_WEAPONPERFECTION, SCB_NONE); - set_sc(BS_OVERTHRUST , SC_OVERTHRUST , SI_OVERTHRUST , SCB_NONE); - set_sc(BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZEPOWER , SCB_REGEN); - add_sc(HT_LANDMINE , SC_STUN); - add_sc(HT_ANKLESNARE , SC_ANKLE); - add_sc(HT_SANDMAN , SC_SLEEP); - add_sc(HT_FLASHER , SC_BLIND); - add_sc(HT_FREEZINGTRAP , SC_FREEZE); - set_sc(AS_CLOAKING , SC_CLOAKING , SI_CLOAKING , SCB_CRI|SCB_SPEED); - add_sc(AS_SONICBLOW , SC_STUN); - set_sc(AS_ENCHANTPOISON , SC_ENCPOISON , SI_ENCPOISON , SCB_ATK_ELE); - set_sc(AS_POISONREACT , SC_POISONREACT , SI_POISONREACT , SCB_NONE); - add_sc(AS_VENOMDUST , SC_POISON); - add_sc(AS_SPLASHER , SC_SPLASHER); - set_sc(NV_TRICKDEAD , SC_TRICKDEAD , SI_TRICKDEAD , SCB_REGEN); - set_sc(SM_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE); - add_sc(TF_SPRINKLESAND , SC_BLIND); - add_sc(TF_THROWSTONE , SC_STUN); - set_sc(MC_LOUD , SC_LOUD , SI_LOUD , SCB_STR); - set_sc(MG_ENERGYCOAT , SC_ENERGYCOAT , SI_ENERGYCOAT , SCB_NONE); - set_sc(NPC_EMOTION , SC_MODECHANGE , SI_BLANK , SCB_MODE); - add_sc(NPC_EMOTION_ON , SC_MODECHANGE); - set_sc(NPC_ATTRICHANGE , SC_ELEMENTALCHANGE , SI_ARMOR_PROPERTY , SCB_DEF_ELE); - add_sc(NPC_CHANGEWATER , SC_ELEMENTALCHANGE); - add_sc(NPC_CHANGEGROUND , SC_ELEMENTALCHANGE); - add_sc(NPC_CHANGEFIRE , SC_ELEMENTALCHANGE); - add_sc(NPC_CHANGEWIND , SC_ELEMENTALCHANGE); - add_sc(NPC_CHANGEPOISON , SC_ELEMENTALCHANGE); - add_sc(NPC_CHANGEHOLY , SC_ELEMENTALCHANGE); - add_sc(NPC_CHANGEDARKNESS , SC_ELEMENTALCHANGE); - add_sc(NPC_CHANGETELEKINESIS, SC_ELEMENTALCHANGE); - add_sc(NPC_POISON , SC_POISON); - add_sc(NPC_BLINDATTACK , SC_BLIND); - add_sc(NPC_SILENCEATTACK , SC_SILENCE); - add_sc(NPC_STUNATTACK , SC_STUN); - add_sc(NPC_PETRIFYATTACK , SC_STONE); - add_sc(NPC_CURSEATTACK , SC_CURSE); - add_sc(NPC_SLEEPATTACK , SC_SLEEP); - add_sc(NPC_MAGICALATTACK , SC_MAGICALATTACK); - set_sc(NPC_KEEPING , SC_KEEPING , SI_BLANK , SCB_DEF); - add_sc(NPC_DARKBLESSING , SC_COMA); - set_sc(NPC_BARRIER , SC_BARRIER , SI_BLANK , SCB_MDEF|SCB_DEF); - add_sc(NPC_DEFENDER , SC_ARMOR); - add_sc(NPC_LICK , SC_STUN); - set_sc(NPC_HALLUCINATION , SC_HALLUCINATION , SI_HALLUCINATION , SCB_NONE); - add_sc(NPC_REBIRTH , SC_REBIRTH); - add_sc(RG_RAID , SC_STUN); +void initChangeTables(void) { + int i; + + for (i = 0; i < SC_MAX; i++) + StatusIconChangeTable[i] = SI_BLANK; + + for (i = 0; i < MAX_SKILL; i++) + SkillStatusChangeTable[i] = SC_NONE; + + for (i = 0; i < SI_MAX; i++) + StatusRelevantBLTypes[i] = BL_PC; + + memset(StatusSkillChangeTable, 0, sizeof(StatusSkillChangeTable)); + memset(StatusChangeFlagTable, 0, sizeof(StatusChangeFlagTable)); + memset(StatusChangeStateTable, 0, sizeof(StatusChangeStateTable)); + + + //First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex] + set_sc( NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF ); + set_sc( NPC_WIDEFREEZE , SC_FREEZE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF ); + set_sc( NPC_STUNATTACK , SC_STUN , SI_BLANK , SCB_NONE ); + set_sc( NPC_SLEEPATTACK , SC_SLEEP , SI_BLANK , SCB_NONE ); + set_sc( NPC_POISON , SC_POISON , SI_BLANK , SCB_DEF2|SCB_REGEN ); + set_sc( NPC_CURSEATTACK , SC_CURSE , SI_BLANK , SCB_LUK|SCB_BATK|SCB_WATK|SCB_SPEED ); + set_sc( NPC_SILENCEATTACK , SC_SILENCE , SI_BLANK , SCB_NONE ); + set_sc( NPC_WIDECONFUSE , SC_CONFUSION , SI_BLANK , SCB_NONE ); + set_sc( NPC_BLINDATTACK , SC_BLIND , SI_BLANK , SCB_HIT|SCB_FLEE ); + set_sc( NPC_BLEEDING , SC_BLEEDING , SI_BLEEDING , SCB_REGEN ); + set_sc( NPC_POISON , SC_DPOISON , SI_BLANK , SCB_DEF2|SCB_REGEN ); + + //The main status definitions + add_sc( SM_BASH , SC_STUN ); + set_sc( SM_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); + add_sc( SM_MAGNUM , SC_WATK_ELEMENT ); + set_sc( SM_ENDURE , SC_ENDURE , SI_ENDURE , SCB_MDEF|SCB_DSPD ); + add_sc( MG_SIGHT , SC_SIGHT ); + add_sc( MG_SAFETYWALL , SC_SAFETYWALL ); + add_sc( MG_FROSTDIVER , SC_FREEZE ); + add_sc( MG_STONECURSE , SC_STONE ); + add_sc( AL_RUWACH , SC_RUWACH ); + add_sc( AL_PNEUMA , SC_PNEUMA ); + set_sc( AL_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED ); + set_sc( AL_DECAGI , SC_DECREASEAGI , SI_DECREASEAGI , SCB_AGI|SCB_SPEED ); + set_sc( AL_CRUCIS , SC_SIGNUMCRUCIS , SI_SIGNUMCRUCIS , SCB_DEF ); + set_sc( AL_ANGELUS , SC_ANGELUS , SI_ANGELUS , SCB_DEF2 ); + set_sc( AL_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); + set_sc( AC_CONCENTRATION , SC_CONCENTRATE , SI_CONCENTRATE , SCB_AGI|SCB_DEX ); + set_sc( TF_HIDING , SC_HIDING , SI_HIDING , SCB_SPEED ); + add_sc( TF_POISON , SC_POISON ); + set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD ); + add_sc( KN_AUTOCOUNTER , SC_AUTOCOUNTER ); + set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO , SCB_WATK ); + set_sc( PR_SUFFRAGIUM , SC_SUFFRAGIUM , SI_SUFFRAGIUM , SCB_NONE ); + set_sc( PR_ASPERSIO , SC_ASPERSIO , SI_ASPERSIO , SCB_ATK_ELE ); + set_sc( PR_BENEDICTIO , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE ); + set_sc( PR_SLOWPOISON , SC_SLOWPOISON , SI_SLOWPOISON , SCB_REGEN ); + set_sc( PR_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE ); + set_sc( PR_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN ); + set_sc( PR_GLORIA , SC_GLORIA , SI_GLORIA , SCB_LUK ); + add_sc( PR_LEXDIVINA , SC_SILENCE ); + set_sc( PR_LEXAETERNA , SC_AETERNA , SI_AETERNA , SCB_NONE ); + add_sc( WZ_METEOR , SC_STUN ); + add_sc( WZ_VERMILION , SC_BLIND ); + add_sc( WZ_FROSTNOVA , SC_FREEZE ); + add_sc( WZ_STORMGUST , SC_FREEZE ); + set_sc( WZ_QUAGMIRE , SC_QUAGMIRE , SI_QUAGMIRE , SCB_AGI|SCB_DEX|SCB_ASPD|SCB_SPEED ); + set_sc( BS_ADRENALINE , SC_ADRENALINE , SI_ADRENALINE , SCB_ASPD ); + set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECTION, SI_WEAPONPERFECTION, SCB_NONE ); + set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SI_OVERTHRUST , SCB_NONE ); + set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZEPOWER , SCB_REGEN ); + add_sc( HT_LANDMINE , SC_STUN ); + add_sc( HT_ANKLESNARE , SC_ANKLE ); + add_sc( HT_SANDMAN , SC_SLEEP ); + add_sc( HT_FLASHER , SC_BLIND ); + add_sc( HT_FREEZINGTRAP , SC_FREEZE ); + set_sc( AS_CLOAKING , SC_CLOAKING , SI_CLOAKING , SCB_CRI|SCB_SPEED ); + add_sc( AS_SONICBLOW , SC_STUN ); + set_sc( AS_ENCHANTPOISON , SC_ENCPOISON , SI_ENCPOISON , SCB_ATK_ELE ); + set_sc( AS_POISONREACT , SC_POISONREACT , SI_POISONREACT , SCB_NONE ); + add_sc( AS_VENOMDUST , SC_POISON ); + add_sc( AS_SPLASHER , SC_SPLASHER ); + set_sc( NV_TRICKDEAD , SC_TRICKDEAD , SI_TRICKDEAD , SCB_REGEN ); + set_sc( SM_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE ); + add_sc( TF_SPRINKLESAND , SC_BLIND ); + add_sc( TF_THROWSTONE , SC_STUN ); + set_sc( MC_LOUD , SC_LOUD , SI_LOUD , SCB_STR ); + set_sc( MG_ENERGYCOAT , SC_ENERGYCOAT , SI_ENERGYCOAT , SCB_NONE ); + set_sc( NPC_EMOTION , SC_MODECHANGE , SI_BLANK , SCB_MODE ); + add_sc( NPC_EMOTION_ON , SC_MODECHANGE ); + set_sc( NPC_ATTRICHANGE , SC_ELEMENTALCHANGE , SI_ARMOR_PROPERTY , SCB_DEF_ELE ); + add_sc( NPC_CHANGEWATER , SC_ELEMENTALCHANGE ); + add_sc( NPC_CHANGEGROUND , SC_ELEMENTALCHANGE ); + add_sc( NPC_CHANGEFIRE , SC_ELEMENTALCHANGE ); + add_sc( NPC_CHANGEWIND , SC_ELEMENTALCHANGE ); + add_sc( NPC_CHANGEPOISON , SC_ELEMENTALCHANGE ); + add_sc( NPC_CHANGEHOLY , SC_ELEMENTALCHANGE ); + add_sc( NPC_CHANGEDARKNESS , SC_ELEMENTALCHANGE ); + add_sc( NPC_CHANGETELEKINESIS, SC_ELEMENTALCHANGE ); + add_sc( NPC_POISON , SC_POISON ); + add_sc( NPC_BLINDATTACK , SC_BLIND ); + add_sc( NPC_SILENCEATTACK , SC_SILENCE ); + add_sc( NPC_STUNATTACK , SC_STUN ); + add_sc( NPC_PETRIFYATTACK , SC_STONE ); + add_sc( NPC_CURSEATTACK , SC_CURSE ); + add_sc( NPC_SLEEPATTACK , SC_SLEEP ); + add_sc( NPC_MAGICALATTACK , SC_MAGICALATTACK ); + set_sc( NPC_KEEPING , SC_KEEPING , SI_BLANK , SCB_DEF ); + add_sc( NPC_DARKBLESSING , SC_COMA ); + set_sc( NPC_BARRIER , SC_BARRIER , SI_BLANK , SCB_MDEF|SCB_DEF ); + add_sc( NPC_DEFENDER , SC_ARMOR ); + add_sc( NPC_LICK , SC_STUN ); + set_sc( NPC_HALLUCINATION , SC_HALLUCINATION , SI_HALLUCINATION , SCB_NONE ); + add_sc( NPC_REBIRTH , SC_REBIRTH ); + add_sc( RG_RAID , SC_STUN ); #ifdef RENEWAL - add_sc(RG_RAID , SC_RAID); - add_sc(RG_BACKSTAP , SC_STUN); + add_sc( RG_RAID , SC_RAID ); + add_sc( RG_BACKSTAP , SC_STUN ); #endif - set_sc(RG_STRIPWEAPON , SC_STRIPWEAPON , SI_STRIPWEAPON , SCB_WATK); - set_sc(RG_STRIPSHIELD , SC_STRIPSHIELD , SI_STRIPSHIELD , SCB_DEF); - set_sc(RG_STRIPARMOR , SC_STRIPARMOR , SI_STRIPARMOR , SCB_VIT); - set_sc(RG_STRIPHELM , SC_STRIPHELM , SI_STRIPHELM , SCB_INT); - add_sc(AM_ACIDTERROR , SC_BLEEDING); - set_sc(AM_CP_WEAPON , SC_CP_WEAPON , SI_CP_WEAPON , SCB_NONE); - set_sc(AM_CP_SHIELD , SC_CP_SHIELD , SI_CP_SHIELD , SCB_NONE); - set_sc(AM_CP_ARMOR , SC_CP_ARMOR , SI_CP_ARMOR , SCB_NONE); - set_sc(AM_CP_HELM , SC_CP_HELM , SI_CP_HELM , SCB_NONE); - set_sc(CR_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE); - add_sc(CR_SHIELDCHARGE , SC_STUN); - set_sc(CR_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE); - add_sc(CR_HOLYCROSS , SC_BLIND); - add_sc(CR_GRANDCROSS , SC_BLIND); - add_sc(CR_DEVOTION , SC_DEVOTION); - set_sc(CR_PROVIDENCE , SC_PROVIDENCE , SI_PROVIDENCE , SCB_ALL); - set_sc(CR_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD); - set_sc(CR_SPEARQUICKEN , SC_SPEARQUICKEN , SI_SPEARQUICKEN , SCB_ASPD|SCB_CRI|SCB_FLEE); - set_sc(MO_STEELBODY , SC_STEELBODY , SI_STEELBODY , SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED); - add_sc(MO_BLADESTOP , SC_BLADESTOP_WAIT); - add_sc(MO_BLADESTOP , SC_BLADESTOP); - set_sc(MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS, SI_EXPLOSIONSPIRITS, SCB_CRI|SCB_REGEN); - set_sc(MO_EXTREMITYFIST , SC_EXTREMITYFIST , SI_BLANK , SCB_REGEN); + set_sc( RG_STRIPWEAPON , SC_STRIPWEAPON , SI_STRIPWEAPON , SCB_WATK ); + set_sc( RG_STRIPSHIELD , SC_STRIPSHIELD , SI_STRIPSHIELD , SCB_DEF ); + set_sc( RG_STRIPARMOR , SC_STRIPARMOR , SI_STRIPARMOR , SCB_VIT ); + set_sc( RG_STRIPHELM , SC_STRIPHELM , SI_STRIPHELM , SCB_INT ); + add_sc( AM_ACIDTERROR , SC_BLEEDING ); + set_sc( AM_CP_WEAPON , SC_CP_WEAPON , SI_CP_WEAPON , SCB_NONE ); + set_sc( AM_CP_SHIELD , SC_CP_SHIELD , SI_CP_SHIELD , SCB_NONE ); + set_sc( AM_CP_ARMOR , SC_CP_ARMOR , SI_CP_ARMOR , SCB_NONE ); + set_sc( AM_CP_HELM , SC_CP_HELM , SI_CP_HELM , SCB_NONE ); + set_sc( CR_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE ); + add_sc( CR_SHIELDCHARGE , SC_STUN ); + set_sc( CR_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE ); + add_sc( CR_HOLYCROSS , SC_BLIND ); + add_sc( CR_GRANDCROSS , SC_BLIND ); + add_sc( CR_DEVOTION , SC_DEVOTION ); + set_sc( CR_PROVIDENCE , SC_PROVIDENCE , SI_PROVIDENCE , SCB_ALL ); + set_sc( CR_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD ); + set_sc( CR_SPEARQUICKEN , SC_SPEARQUICKEN , SI_SPEARQUICKEN , SCB_ASPD|SCB_CRI|SCB_FLEE ); + set_sc( MO_STEELBODY , SC_STEELBODY , SI_STEELBODY , SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED ); + add_sc( MO_BLADESTOP , SC_BLADESTOP_WAIT ); + add_sc( MO_BLADESTOP , SC_BLADESTOP ); + set_sc( MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS, SI_EXPLOSIONSPIRITS, SCB_CRI|SCB_REGEN ); + set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST , SI_BLANK , SCB_REGEN ); #ifdef RENEWAL - set_sc(MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SI_EXTREMITYFIST , SCB_NONE); + set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SI_EXTREMITYFIST , SCB_NONE ); #endif - add_sc(SA_MAGICROD , SC_MAGICROD); - set_sc(SA_AUTOSPELL , SC_AUTOSPELL , SI_AUTOSPELL , SCB_NONE); - set_sc(SA_FLAMELAUNCHER , SC_FIREWEAPON , SI_FIREWEAPON , SCB_ATK_ELE); - set_sc(SA_FROSTWEAPON , SC_WATERWEAPON , SI_WATERWEAPON , SCB_ATK_ELE); - set_sc(SA_LIGHTNINGLOADER , SC_WINDWEAPON , SI_WINDWEAPON , SCB_ATK_ELE); - set_sc(SA_SEISMICWEAPON , SC_EARTHWEAPON , SI_EARTHWEAPON , SCB_ATK_ELE); - set_sc(SA_VOLCANO , SC_VOLCANO , SI_LANDENDOW , SCB_WATK); - set_sc(SA_DELUGE , SC_DELUGE , SI_LANDENDOW , SCB_MAXHP); - set_sc(SA_VIOLENTGALE , SC_VIOLENTGALE , SI_LANDENDOW , SCB_FLEE); - add_sc(SA_REVERSEORCISH , SC_ORCISH); - add_sc(SA_COMA , SC_COMA); - set_sc(BD_ENCORE , SC_DANCING , SI_BLANK , SCB_SPEED|SCB_REGEN); - add_sc(BD_RICHMANKIM , SC_RICHMANKIM); - set_sc(BD_ETERNALCHAOS , SC_ETERNALCHAOS , SI_BLANK , SCB_DEF2); - set_sc(BD_DRUMBATTLEFIELD , SC_DRUMBATTLE , SI_BLANK , SCB_WATK|SCB_DEF); - set_sc(BD_RINGNIBELUNGEN , SC_NIBELUNGEN , SI_BLANK , SCB_WATK); - add_sc(BD_ROKISWEIL , SC_ROKISWEIL); - add_sc(BD_INTOABYSS , SC_INTOABYSS); - set_sc(BD_SIEGFRIED , SC_SIEGFRIED , SI_BLANK , SCB_ALL); - add_sc(BA_FROSTJOKER , SC_FREEZE); - set_sc(BA_WHISTLE , SC_WHISTLE , SI_BLANK , SCB_FLEE|SCB_FLEE2); - set_sc(BA_ASSASSINCROSS , SC_ASSNCROS , SI_BLANK , SCB_ASPD); - add_sc(BA_POEMBRAGI , SC_POEMBRAGI); - set_sc(BA_APPLEIDUN , SC_APPLEIDUN , SI_BLANK , SCB_MAXHP); - add_sc(DC_SCREAM , SC_STUN); - set_sc(DC_HUMMING , SC_HUMMING , SI_BLANK , SCB_HIT); - set_sc(DC_DONTFORGETME , SC_DONTFORGETME , SI_BLANK , SCB_SPEED|SCB_ASPD); - set_sc(DC_FORTUNEKISS , SC_FORTUNE , SI_BLANK , SCB_CRI); - set_sc(DC_SERVICEFORYOU , SC_SERVICE4U , SI_BLANK , SCB_ALL); - add_sc(NPC_DARKCROSS , SC_BLIND); - add_sc(NPC_GRANDDARKNESS , SC_BLIND); - set_sc(NPC_STOP , SC_STOP , SI_STOP , SCB_NONE); - set_sc(NPC_WEAPONBRAKER , SC_BROKENWEAPON , SI_BROKENWEAPON , SCB_NONE); - set_sc(NPC_ARMORBRAKE , SC_BROKENARMOR , SI_BROKENARMOR , SCB_NONE); - set_sc(NPC_CHANGEUNDEAD , SC_CHANGEUNDEAD , SI_UNDEAD , SCB_DEF_ELE); - set_sc(NPC_POWERUP , SC_INCHITRATE , SI_BLANK , SCB_HIT); - set_sc(NPC_AGIUP , SC_INCFLEERATE , SI_BLANK , SCB_FLEE); - add_sc(NPC_INVISIBLE , SC_CLOAKING); - set_sc(LK_AURABLADE , SC_AURABLADE , SI_AURABLADE , SCB_NONE); - set_sc(LK_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE); - set_sc(LK_CONCENTRATION , SC_CONCENTRATION , SI_CONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_DSPD); - set_sc(LK_TENSIONRELAX , SC_TENSIONRELAX , SI_TENSIONRELAX , SCB_REGEN); - set_sc(LK_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN); - set_sc(HP_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2); - add_sc(HP_BASILICA , SC_BASILICA); - set_sc(HW_MAGICPOWER , SC_MAGICPOWER , SI_MAGICPOWER , SCB_MATK); - add_sc(PA_SACRIFICE , SC_SACRIFICE); - set_sc(PA_GOSPEL , SC_GOSPEL , SI_BLANK , SCB_SPEED|SCB_ASPD); - add_sc(PA_GOSPEL , SC_SCRESIST); - add_sc(CH_TIGERFIST , SC_STOP); - set_sc(ASC_EDP , SC_EDP , SI_EDP , SCB_NONE); - set_sc(SN_SIGHT , SC_TRUESIGHT , SI_TRUESIGHT , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_CRI|SCB_HIT); - set_sc(SN_WINDWALK , SC_WINDWALK , SI_WINDWALK , SCB_FLEE|SCB_SPEED); - set_sc(WS_MELTDOWN , SC_MELTDOWN , SI_MELTDOWN , SCB_NONE); - set_sc(WS_CARTBOOST , SC_CARTBOOST , SI_CARTBOOST , SCB_SPEED); - set_sc(ST_CHASEWALK , SC_CHASEWALK , SI_BLANK , SCB_SPEED); - set_sc(ST_REJECTSWORD , SC_REJECTSWORD , SI_REJECTSWORD , SCB_NONE); - add_sc(ST_REJECTSWORD , SC_AUTOCOUNTER); - set_sc(CG_MARIONETTE , SC_MARIONETTE , SI_MARIONETTE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK); - set_sc(CG_MARIONETTE , SC_MARIONETTE2 , SI_MARIONETTE2 , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK); - add_sc(LK_SPIRALPIERCE , SC_STOP); - add_sc(LK_HEADCRUSH , SC_BLEEDING); - set_sc(LK_JOINTBEAT , SC_JOINTBEAT , SI_JOINTBEAT , SCB_BATK|SCB_DEF2|SCB_SPEED|SCB_ASPD); - add_sc(HW_NAPALMVULCAN , SC_CURSE); - set_sc(PF_MINDBREAKER , SC_MINDBREAKER , SI_BLANK , SCB_MATK|SCB_MDEF2); - add_sc(PF_MEMORIZE , SC_MEMORIZE); - add_sc(PF_FOGWALL , SC_FOGWALL); - set_sc(PF_SPIDERWEB , SC_SPIDERWEB , SI_BLANK , SCB_FLEE); - set_sc(WE_BABY , SC_BABY , SI_BABY , SCB_NONE); - set_sc(TK_RUN , SC_RUN , SI_RUN , SCB_SPEED|SCB_DSPD); - set_sc(TK_RUN , SC_SPURT , SI_SPURT , SCB_STR); - set_sc(TK_READYSTORM , SC_READYSTORM , SI_READYSTORM , SCB_NONE); - set_sc(TK_READYDOWN , SC_READYDOWN , SI_READYDOWN , SCB_NONE); - add_sc(TK_DOWNKICK , SC_STUN); - set_sc(TK_READYTURN , SC_READYTURN , SI_READYTURN , SCB_NONE); - set_sc(TK_READYCOUNTER , SC_READYCOUNTER , SI_READYCOUNTER , SCB_NONE); - set_sc(TK_DODGE , SC_DODGE , SI_DODGE , SCB_NONE); - set_sc(TK_SPTIME , SC_EARTHSCROLL , SI_EARTHSCROLL , SCB_NONE); - add_sc(TK_SEVENWIND , SC_SEVENWIND); - set_sc(TK_SEVENWIND , SC_GHOSTWEAPON , SI_GHOSTWEAPON , SCB_ATK_ELE); - set_sc(TK_SEVENWIND , SC_SHADOWWEAPON , SI_SHADOWWEAPON , SCB_ATK_ELE); - set_sc(SG_SUN_WARM , SC_WARM , SI_WARM , SCB_NONE); - add_sc(SG_MOON_WARM , SC_WARM); - add_sc(SG_STAR_WARM , SC_WARM); - set_sc(SG_SUN_COMFORT , SC_SUN_COMFORT , SI_SUN_COMFORT , SCB_DEF2); - set_sc(SG_MOON_COMFORT , SC_MOON_COMFORT , SI_MOON_COMFORT , SCB_FLEE); - set_sc(SG_STAR_COMFORT , SC_STAR_COMFORT , SI_STAR_COMFORT , SCB_ASPD); - add_sc(SG_FRIEND , SC_SKILLRATE_UP); - set_sc(SG_KNOWLEDGE , SC_KNOWLEDGE , SI_BLANK , SCB_ALL); - set_sc(SG_FUSION , SC_FUSION , SI_BLANK , SCB_SPEED); - set_sc(BS_ADRENALINE2 , SC_ADRENALINE2 , SI_ADRENALINE2 , SCB_ASPD); - set_sc(SL_KAIZEL , SC_KAIZEL , SI_KAIZEL , SCB_NONE); - set_sc(SL_KAAHI , SC_KAAHI , SI_KAAHI , SCB_NONE); - set_sc(SL_KAUPE , SC_KAUPE , SI_KAUPE , SCB_NONE); - set_sc(SL_KAITE , SC_KAITE , SI_KAITE , SCB_NONE); - add_sc(SL_STUN , SC_STUN); - set_sc(SL_SWOO , SC_SWOO , SI_BLANK , SCB_SPEED); - set_sc(SL_SKE , SC_SKE , SI_BLANK , SCB_BATK|SCB_WATK|SCB_DEF|SCB_DEF2); - set_sc(SL_SKA , SC_SKA , SI_BLANK , SCB_DEF|SCB_MDEF|SCB_ASPD); - set_sc(SL_SMA , SC_SMA , SI_SMA , SCB_NONE); - set_sc(SM_SELFPROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK); - set_sc(ST_PRESERVE , SC_PRESERVE , SI_PRESERVE , SCB_NONE); - set_sc(PF_DOUBLECASTING , SC_DOUBLECAST , SI_DOUBLECAST , SCB_NONE); - set_sc(HW_GRAVITATION , SC_GRAVITATION , SI_BLANK , SCB_ASPD); - add_sc(WS_CARTTERMINATION , SC_STUN); - set_sc(WS_OVERTHRUSTMAX , SC_MAXOVERTHRUST , SI_MAXOVERTHRUST , SCB_NONE); - set_sc(CG_LONGINGFREEDOM , SC_LONGING , SI_BLANK , SCB_SPEED|SCB_ASPD); - add_sc(CG_HERMODE , SC_HERMODE); - set_sc(ITEM_ENCHANTARMS , SC_ENCHANTARMS , SI_BLANK , SCB_ATK_ELE); - set_sc(SL_HIGH , SC_SPIRIT , SI_SPIRIT , SCB_ALL); - set_sc(KN_ONEHAND , SC_ONEHAND , SI_ONEHAND , SCB_ASPD); - set_sc(GS_FLING , SC_FLING , SI_BLANK , SCB_DEF|SCB_DEF2); - add_sc(GS_CRACKER , SC_STUN); - add_sc(GS_DISARM , SC_STRIPWEAPON); - add_sc(GS_PIERCINGSHOT , SC_BLEEDING); - set_sc(GS_MADNESSCANCEL , SC_MADNESSCANCEL , SI_MADNESSCANCEL , SCB_BATK|SCB_ASPD); - set_sc(GS_ADJUSTMENT , SC_ADJUSTMENT , SI_ADJUSTMENT , SCB_HIT|SCB_FLEE); - set_sc(GS_INCREASING , SC_INCREASING , SI_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT); - set_sc(GS_GATLINGFEVER , SC_GATLINGFEVER , SI_GATLINGFEVER , SCB_BATK|SCB_FLEE|SCB_SPEED|SCB_ASPD); - set_sc(NJ_TATAMIGAESHI , SC_TATAMIGAESHI , SI_BLANK , SCB_NONE); - set_sc(NJ_SUITON , SC_SUITON , SI_BLANK , SCB_AGI|SCB_SPEED); - add_sc(NJ_HYOUSYOURAKU , SC_FREEZE); - set_sc(NJ_NEN , SC_NEN , SI_NEN , SCB_STR|SCB_INT); - set_sc(NJ_UTSUSEMI , SC_UTSUSEMI , SI_UTSUSEMI , SCB_NONE); - set_sc(NJ_BUNSINJYUTSU , SC_BUNSINJYUTSU , SI_BUNSINJYUTSU , SCB_DYE); - - add_sc(NPC_ICEBREATH , SC_FREEZE); - add_sc(NPC_ACIDBREATH , SC_POISON); - add_sc(NPC_HELLJUDGEMENT , SC_CURSE); - add_sc(NPC_WIDESILENCE , SC_SILENCE); - add_sc(NPC_WIDEFREEZE , SC_FREEZE); - add_sc(NPC_WIDEBLEEDING , SC_BLEEDING); - add_sc(NPC_WIDESTONE , SC_STONE); - add_sc(NPC_WIDECONFUSE , SC_CONFUSION); - add_sc(NPC_WIDESLEEP , SC_SLEEP); - add_sc(NPC_WIDESIGHT , SC_SIGHT); - add_sc(NPC_EVILLAND , SC_BLIND); - add_sc(NPC_MAGICMIRROR , SC_MAGICMIRROR); - set_sc(NPC_SLOWCAST , SC_SLOWCAST , SI_SLOWCAST , SCB_NONE); - set_sc(NPC_CRITICALWOUND , SC_CRITICALWOUND , SI_CRITICALWOUND , SCB_NONE); - set_sc(NPC_STONESKIN , SC_ARMORCHANGE , SI_BLANK , SCB_DEF|SCB_MDEF); - add_sc(NPC_ANTIMAGIC , SC_ARMORCHANGE); - add_sc(NPC_WIDECURSE , SC_CURSE); - add_sc(NPC_WIDESTUN , SC_STUN); - - set_sc(NPC_HELLPOWER , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE); - set_sc(NPC_WIDEHELLDIGNITY , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE); - set_sc(NPC_INVINCIBLE , SC_INVINCIBLE , SI_INVINCIBLE , SCB_SPEED); - set_sc(NPC_INVINCIBLEOFF , SC_INVINCIBLEOFF , SI_BLANK , SCB_SPEED); - - set_sc(CASH_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX); - set_sc(CASH_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED); - set_sc(CASH_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2); - - set_sc(ALL_PARTYFLEE , SC_PARTYFLEE , SI_PARTYFLEE , SCB_NONE); - set_sc(ALL_ODINS_POWER , SC_ODINS_POWER , SI_ODINS_POWER , SCB_MATK|SCB_BATK|SCB_MDEF|SCB_DEF); - - set_sc(CR_SHRINK , SC_SHRINK , SI_SHRINK , SCB_NONE); - set_sc(RG_CLOSECONFINE , SC_CLOSECONFINE2 , SI_CLOSECONFINE2 , SCB_NONE); - set_sc(RG_CLOSECONFINE , SC_CLOSECONFINE , SI_CLOSECONFINE , SCB_FLEE); - set_sc(WZ_SIGHTBLASTER , SC_SIGHTBLASTER , SI_SIGHTBLASTER , SCB_NONE); - set_sc(DC_WINKCHARM , SC_WINKCHARM , SI_WINKCHARM , SCB_NONE); - add_sc(MO_BALKYOUNG , SC_STUN); - add_sc(SA_ELEMENTWATER , SC_ELEMENTALCHANGE); - add_sc(SA_ELEMENTFIRE , SC_ELEMENTALCHANGE); - add_sc(SA_ELEMENTGROUND , SC_ELEMENTALCHANGE); - add_sc(SA_ELEMENTWIND , SC_ELEMENTALCHANGE); - - set_sc(HLIF_AVOID , SC_AVOID , SI_BLANK , SCB_SPEED); - set_sc(HLIF_CHANGE , SC_CHANGE , SI_BLANK , SCB_VIT|SCB_INT); - set_sc(HFLI_FLEET , SC_FLEET , SI_BLANK , SCB_ASPD|SCB_BATK|SCB_WATK); - set_sc(HFLI_SPEED , SC_SPEED , SI_BLANK , SCB_FLEE); - set_sc(HAMI_DEFENCE , SC_DEFENCE , SI_BLANK , SCB_DEF); - set_sc(HAMI_BLOODLUST , SC_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK); - - // Homunculus S - add_sc(MH_STAHL_HORN, SC_STUN); - set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP); - set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP); - add_sc(MH_STEINWAND, SC_SAFETYWALL); - add_sc(MH_ERASER_CUTTER, SC_ERASER_CUTTER); - set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD); - add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE); - set_sc(MH_VOLCANIC_ASH, SC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE); - set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE); - set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE); - set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SI_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE); - add_sc(MH_LAVA_SLIDE, SC_BURNING); - set_sc(MH_NEEDLE_OF_PARALYZE, SC_PARALYSIS, SI_NEEDLE_OF_PARALYZE, SCB_DEF2); - add_sc(MH_POISON_MIST, SC_BLIND); - set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD); - - add_sc(MH_STYLE_CHANGE, SC_STYLE_CHANGE); - - - add_sc(MER_CRASH , SC_STUN); - set_sc(MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK); - add_sc(MS_MAGNUM , SC_WATK_ELEMENT); - add_sc(MER_SIGHT , SC_SIGHT); - set_sc(MER_DECAGI , SC_DECREASEAGI , SI_DECREASEAGI , SCB_AGI|SCB_SPEED); - set_sc(MER_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN); - add_sc(MER_LEXDIVINA , SC_SILENCE); - add_sc(MA_LANDMINE , SC_STUN); - add_sc(MA_SANDMAN , SC_SLEEP); - add_sc(MA_FREEZINGTRAP , SC_FREEZE); - set_sc(MER_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE); - set_sc(ML_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE); - set_sc(MS_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE); - set_sc(ML_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD); - set_sc(MS_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE); - set_sc(MS_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN); - add_sc(ML_SPIRALPIERCE , SC_STOP); - set_sc(MER_QUICKEN , SC_MERC_QUICKEN , SI_BLANK , SCB_ASPD); - add_sc(ML_DEVOTION , SC_DEVOTION); - set_sc(MER_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE); - set_sc(MER_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX); - set_sc(MER_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED); - - set_sc(GD_LEADERSHIP , SC_LEADERSHIP , SI_BLANK , SCB_STR); - set_sc(GD_GLORYWOUNDS , SC_GLORYWOUNDS , SI_BLANK , SCB_VIT); - set_sc(GD_SOULCOLD , SC_SOULCOLD , SI_BLANK , SCB_AGI); - set_sc(GD_HAWKEYES , SC_HAWKEYES , SI_BLANK , SCB_DEX); - - set_sc(GD_BATTLEORDER , SC_BATTLEORDERS , SI_BLANK , SCB_STR|SCB_INT|SCB_DEX); - set_sc(GD_REGENERATION , SC_REGENERATION , SI_BLANK , SCB_REGEN); - - /** - * Rune Knight - **/ - set_sc(RK_ENCHANTBLADE , SC_ENCHANTBLADE , SI_ENCHANTBLADE , SCB_NONE); - set_sc(RK_DRAGONHOWLING , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT); - set_sc(RK_DEATHBOUND , SC_DEATHBOUND , SI_DEATHBOUND , SCB_NONE); - set_sc(RK_WINDCUTTER , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT); - add_sc(RK_DRAGONBREATH , SC_BURNING); - set_sc(RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_REUSE_MILLENNIUMSHIELD , SCB_NONE); - set_sc(RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE); - set_sc(RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR); - set_sc(RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_NONE); - set_sc(RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SI_VITALITYACTIVATION, SCB_REGEN); - set_sc(RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD); - set_sc(RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE); - /** - * GC Guillotine Cross - **/ - set_sc_with_vfx(GC_VENOMIMPRESS , SC_VENOMIMPRESS , SI_VENOMIMPRESS , SCB_NONE); - set_sc(GC_POISONINGWEAPON , SC_POISONINGWEAPON , SI_POISONINGWEAPON , SCB_NONE); - set_sc(GC_WEAPONBLOCKING , SC_WEAPONBLOCKING , SI_WEAPONBLOCKING , SCB_NONE); - set_sc(GC_CLOAKINGEXCEED , SC_CLOAKINGEXCEED , SI_CLOAKINGEXCEED , SCB_SPEED); - set_sc(GC_HALLUCINATIONWALK , SC_HALLUCINATIONWALK, SI_HALLUCINATIONWALK, SCB_FLEE); - set_sc(GC_ROLLINGCUTTER , SC_ROLLINGCUTTER , SI_ROLLINGCUTTER , SCB_NONE); - /** - * Arch Bishop - **/ - set_sc(AB_ADORAMUS , SC_ADORAMUS , SI_ADORAMUS , SCB_AGI|SCB_SPEED); - add_sc(AB_CLEMENTIA , SC_BLESSING); - add_sc(AB_CANTO , SC_INCREASEAGI); - set_sc(AB_EPICLESIS , SC_EPICLESIS , SI_EPICLESIS , SCB_MAXHP); - add_sc(AB_PRAEFATIO , SC_KYRIE); - set_sc_with_vfx(AB_ORATIO , SC_ORATIO , SI_ORATIO , SCB_NONE); - set_sc(AB_LAUDAAGNUS , SC_LAUDAAGNUS , SI_LAUDAAGNUS , SCB_VIT); - set_sc(AB_LAUDARAMUS , SC_LAUDARAMUS , SI_LAUDARAMUS , SCB_LUK); - set_sc(AB_RENOVATIO , SC_RENOVATIO , SI_RENOVATIO , SCB_REGEN); - set_sc(AB_EXPIATIO , SC_EXPIATIO , SI_EXPIATIO , SCB_ATK_ELE); - set_sc(AB_DUPLELIGHT , SC_DUPLELIGHT , SI_DUPLELIGHT , SCB_NONE); - set_sc(AB_SECRAMENT , SC_SECRAMENT , SI_SECRAMENT , SCB_NONE); - /** - * Warlock - **/ - add_sc(WL_WHITEIMPRISON , SC_WHITEIMPRISON); - set_sc_with_vfx(WL_FROSTMISTY , SC_FREEZING , SI_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF|SCB_DEF2); - set_sc(WL_MARSHOFABYSS , SC_MARSHOFABYSS , SI_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_DEF|SCB_MDEF); - set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_MATK); - set_sc(WL_STASIS , SC_STASIS , SI_STASIS , SCB_NONE); - /** - * Ranger - **/ - set_sc(RA_FEARBREEZE , SC_FEARBREEZE , SI_FEARBREEZE , SCB_NONE); - set_sc(RA_ELECTRICSHOCKER , SC_ELECTRICSHOCKER , SI_ELECTRICSHOCKER , SCB_NONE); - set_sc(RA_WUGDASH , SC_WUGDASH , SI_WUGDASH , SCB_SPEED); - set_sc(RA_CAMOUFLAGE , SC_CAMOUFLAGE , SI_CAMOUFLAGE , SCB_SPEED); - add_sc(RA_MAGENTATRAP , SC_ELEMENTALCHANGE); - add_sc(RA_COBALTTRAP , SC_ELEMENTALCHANGE); - add_sc(RA_MAIZETRAP , SC_ELEMENTALCHANGE); - add_sc(RA_VERDURETRAP , SC_ELEMENTALCHANGE); - add_sc(RA_FIRINGTRAP , SC_BURNING); - set_sc_with_vfx(RA_ICEBOUNDTRAP , SC_FREEZING , SI_FROSTMISTY , SCB_NONE); - /** - * Mechanic - **/ - set_sc(NC_ACCELERATION , SC_ACCELERATION , SI_ACCELERATION , SCB_SPEED); - set_sc(NC_HOVERING , SC_HOVERING , SI_HOVERING , SCB_SPEED); - set_sc(NC_SHAPESHIFT , SC_SHAPESHIFT , SI_SHAPESHIFT , SCB_DEF_ELE); - set_sc(NC_INFRAREDSCAN , SC_INFRAREDSCAN , SI_INFRAREDSCAN , SCB_FLEE); - set_sc(NC_ANALYZE , SC_ANALYZE , SI_ANALYZE , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2); - set_sc(NC_MAGNETICFIELD , SC_MAGNETICFIELD , SI_MAGNETICFIELD , SCB_NONE); - set_sc(NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_NONE); - set_sc(NC_STEALTHFIELD , SC_STEALTHFIELD , SI_STEALTHFIELD , SCB_NONE); - /** - * Royal Guard - **/ - set_sc(LG_REFLECTDAMAGE , SC_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE); - set_sc(LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP|SCB_DEF); - set_sc(LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE); - set_sc(LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF); - set_sc(LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK); // Renewal: atk2 & def2 - set_sc(LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE); - set_sc(LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD); - set_sc(LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK); - set_sc(LG_SHIELDSPELL , SC_SHIELDSPELL_DEF , SI_SHIELDSPELL_DEF , SCB_WATK); - set_sc(LG_SHIELDSPELL , SC_SHIELDSPELL_REF , SI_SHIELDSPELL_REF , SCB_DEF); - /** - * Shadow Chaser - **/ - set_sc(SC_REPRODUCE , SC__REPRODUCE , SI_REPRODUCE , SCB_NONE); - set_sc(SC_AUTOSHADOWSPELL , SC__AUTOSHADOWSPELL, SI_AUTOSHADOWSPELL , SCB_NONE); - set_sc(SC_SHADOWFORM , SC__SHADOWFORM , SI_SHADOWFORM , SCB_NONE); - set_sc(SC_BODYPAINT , SC__BODYPAINT , SI_BODYPAINT , SCB_ASPD); - set_sc(SC_INVISIBILITY , SC__INVISIBILITY , SI_INVISIBILITY , SCB_ASPD|SCB_CRI|SCB_ATK_ELE); - set_sc(SC_DEADLYINFECT , SC__DEADLYINFECT , SI_DEADLYINFECT , SCB_NONE); - set_sc(SC_ENERVATION , SC__ENERVATION , SI_ENERVATION , SCB_BATK); - set_sc(SC_GROOMY , SC__GROOMY , SI_GROOMY , SCB_ASPD|SCB_HIT|SCB_SPEED); - set_sc(SC_IGNORANCE , SC__IGNORANCE , SI_IGNORANCE , SCB_NONE); - set_sc(SC_LAZINESS , SC__LAZINESS , SI_LAZINESS , SCB_FLEE); - set_sc(SC_UNLUCKY , SC__UNLUCKY , SI_UNLUCKY , SCB_CRI|SCB_FLEE2); - set_sc(SC_WEAKNESS , SC__WEAKNESS , SI_WEAKNESS , SCB_FLEE2|SCB_MAXHP); - set_sc(SC_STRIPACCESSARY , SC__STRIPACCESSORY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK); - set_sc_with_vfx(SC_MANHOLE , SC__MANHOLE , SI_MANHOLE , SCB_NONE); - add_sc(SC_CHAOSPANIC , SC_CONFUSION); - set_sc_with_vfx(SC_BLOODYLUST , SC__BLOODYLUST , SI_BLOODYLUST , SCB_DEF | SCB_DEF2 | SCB_MDEF | SCB_MDEF2 | SCB_FLEE | SCB_SPEED | SCB_ASPD | SCB_MAXHP | SCB_REGEN); - /** - * Sura - **/ - add_sc(SR_DRAGONCOMBO , SC_STUN); - add_sc(SR_EARTHSHAKER , SC_STUN); - set_sc(SR_CRESCENTELBOW , SC_CRESCENTELBOW , SI_CRESCENTELBOW , SCB_NONE); - set_sc_with_vfx(SR_CURSEDCIRCLE , SC_CURSEDCIRCLE_TARGET, SI_CURSEDCIRCLE_TARGET , SCB_NONE); - set_sc(SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SI_LIGHTNINGWALK , SCB_NONE); - set_sc(SR_RAISINGDRAGON , SC_RAISINGDRAGON , SI_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP); - set_sc(SR_GENTLETOUCH_ENERGYGAIN, SC_GT_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE); - set_sc(SR_GENTLETOUCH_CHANGE , SC_GT_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP); - set_sc(SR_GENTLETOUCH_REVITALIZE, SC_GT_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_REGEN); - /** - * Wanderer / Minstrel - **/ - set_sc(WA_SWING_DANCE , SC_SWINGDANCE , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD); - set_sc(WA_SYMPHONY_OF_LOVER , SC_SYMPHONYOFLOVER , SI_SYMPHONYOFLOVERS , SCB_MDEF); - set_sc(WA_MOONLIT_SERENADE , SC_MOONLITSERENADE , SI_MOONLITSERENADE , SCB_MATK); - set_sc(MI_RUSH_WINDMILL , SC_RUSHWINDMILL , SI_RUSHWINDMILL , SCB_BATK); - set_sc(MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2); - set_sc(MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK); - set_sc_with_vfx(WM_POEMOFNETHERWORLD , SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE); - set_sc_with_vfx(WM_VOICEOFSIREN , SC_VOICEOFSIREN , SI_VOICEOFSIREN , SCB_NONE); - set_sc_with_vfx(WM_LULLABY_DEEPSLEEP , SC_DEEPSLEEP , SI_DEEPSLEEP , SCB_NONE); - set_sc(WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE); - set_sc(WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_ASPD); - set_sc(WM_SONG_OF_MANA , SC_SONGOFMANA , SI_SONGOFMANA , SCB_NONE); - set_sc(WM_DANCE_WITH_WUG , SC_DANCEWITHWUG , SI_DANCEWITHWUG , SCB_ASPD); - set_sc(WM_SATURDAY_NIGHT_FEVER , SC_SATURDAYNIGHTFEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN); - set_sc(WM_LERADS_DEW , SC_LERADSDEW , SI_LERADSDEW , SCB_MAXHP); - set_sc(WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_BATK|SCB_MATK); - set_sc(WM_BEYOND_OF_WARCRY , SC_BEYONDOFWARCRY , SI_WARCRYOFBEYOND , SCB_BATK|SCB_MATK); - set_sc(WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITEDHUMMINGVOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE); - /** - * Sorcerer - **/ - set_sc(SO_FIREWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE); - set_sc(SO_ELECTRICWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE); - set_sc(SO_SPELLFIST , SC_SPELLFIST , SI_SPELLFIST , SCB_NONE); - set_sc_with_vfx(SO_DIAMONDDUST , SC_CRYSTALIZE , SI_COLD , SCB_NONE); // it does show the snow icon on mobs but doesn't affect it. - add_sc(SO_CLOUD_KILL , SC_POISON); - set_sc(SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI); - set_sc(SO_WARMER , SC_WARMER , SI_WARMER , SCB_NONE); - set_sc(SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE); - set_sc(SO_ARRULLO , SC_DEEPSLEEP , SI_DEEPSLEEP , SCB_NONE); - set_sc(SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SI_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN); - set_sc(SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SI_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN); - set_sc(SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SI_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN); - set_sc(SO_EARTH_INSIGNIA , SC_EARTH_INSIGNIA , SI_EARTH_INSIGNIA , SCB_MDEF|SCB_DEF|SCB_MAXHP|SCB_MAXSP|SCB_WATK | SCB_ATK_ELE | SCB_REGEN); - /** - * Genetic - **/ - set_sc(GN_CARTBOOST , SC_GN_CARTBOOST, SI_CARTSBOOST , SCB_SPEED); - set_sc(GN_THORNS_TRAP , SC_THORNSTRAP , SI_THORNTRAP , SCB_NONE); - set_sc_with_vfx(GN_BLOOD_SUCKER , SC_BLOODSUCKER , SI_BLOODSUCKER , SCB_NONE); - set_sc(GN_WALLOFTHORN , SC_STOP , SI_BLANK , SCB_NONE); - set_sc(GN_FIRE_EXPANSION_SMOKE_POWDER, SC_SMOKEPOWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_NONE); - set_sc(GN_FIRE_EXPANSION_TEAR_GAS , SC_TEARGAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE); - set_sc(GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT); - - // Elemental Spirit summoner's 'side' status changes. - set_sc(EL_CIRCLE_OF_FIRE , SC_CIRCLE_OF_FIRE_OPTION, SI_CIRCLE_OF_FIRE_OPTION, SCB_NONE); - set_sc(EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SI_FIRE_CLOAK_OPTION , SCB_ALL); - set_sc(EL_WATER_SCREEN , SC_WATER_SCREEN_OPTION , SI_WATER_SCREEN_OPTION , SCB_NONE); - set_sc(EL_WATER_DROP , SC_WATER_DROP_OPTION , SI_WATER_DROP_OPTION , SCB_ALL); - set_sc(EL_WATER_BARRIER , SC_WATER_BARRIER , SI_WATER_BARRIER , SCB_MDEF|SCB_WATK|SCB_MATK|SCB_FLEE); - set_sc(EL_WIND_STEP , SC_WIND_STEP_OPTION , SI_WIND_STEP_OPTION , SCB_SPEED|SCB_FLEE); - set_sc(EL_WIND_CURTAIN , SC_WIND_CURTAIN_OPTION , SI_WIND_CURTAIN_OPTION , SCB_ALL); - set_sc(EL_ZEPHYR , SC_ZEPHYR , SI_ZEPHYR , SCB_FLEE); - set_sc(EL_SOLID_SKIN , SC_SOLID_SKIN_OPTION , SI_SOLID_SKIN_OPTION , SCB_DEF|SCB_MAXHP); - set_sc(EL_STONE_SHIELD , SC_STONE_SHIELD_OPTION , SI_STONE_SHIELD_OPTION , SCB_ALL); - set_sc(EL_POWER_OF_GAIA , SC_POWER_OF_GAIA , SI_POWER_OF_GAIA , SCB_MAXHP|SCB_DEF|SCB_SPEED); - set_sc(EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SI_PYROTECHNIC_OPTION , SCB_WATK); - set_sc(EL_HEATER , SC_HEATER_OPTION , SI_HEATER_OPTION , SCB_WATK); - set_sc(EL_TROPIC , SC_TROPIC_OPTION , SI_TROPIC_OPTION , SCB_WATK); - set_sc(EL_AQUAPLAY , SC_AQUAPLAY_OPTION , SI_AQUAPLAY_OPTION , SCB_MATK); - set_sc(EL_COOLER , SC_COOLER_OPTION , SI_COOLER_OPTION , SCB_MATK); - set_sc(EL_CHILLY_AIR , SC_CHILLY_AIR_OPTION , SI_CHILLY_AIR_OPTION , SCB_MATK); - set_sc(EL_GUST , SC_GUST_OPTION , SI_GUST_OPTION , SCB_NONE); - set_sc(EL_BLAST , SC_BLAST_OPTION , SI_BLAST_OPTION , SCB_NONE); - set_sc(EL_WILD_STORM , SC_WILD_STORM_OPTION , SI_WILD_STORM_OPTION , SCB_NONE); - set_sc(EL_PETROLOGY , SC_PETROLOGY_OPTION , SI_PETROLOGY_OPTION , SCB_NONE); - set_sc(EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_NONE); - set_sc(EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_NONE); - set_sc(EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL); - set_sc(EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF); - set_sc(EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED); - - add_sc(KO_YAMIKUMO , SC_HIDING); - set_sc_with_vfx(KO_JYUMONJIKIRI , SC_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE); - add_sc(KO_MAKIBISHI , SC_STUN); - set_sc(KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE); - set_sc(KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK); - add_sc(KO_JYUSATSU , SC_CURSE); - set_sc(KO_ZENKAI , SC_ZENKAI , SI_ZENKAI , SCB_NONE); - set_sc(KO_IZAYOI , SC_IZAYOI , SI_IZAYOI , SCB_MATK); - set_sc(KG_KYOMU , SC_KYOMU , SI_KYOMU , SCB_NONE); - set_sc(KG_KAGEMUSYA , SC_KAGEMUSYA , SI_KAGEMUSYA , SCB_NONE); - set_sc(KG_KAGEHUMI , SC_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE); - set_sc(OB_ZANGETSU , SC_ZANGETSU , SI_ZANGETSU , SCB_MATK|SCB_BATK); - set_sc_with_vfx(OB_AKAITSUKI , SC_AKAITSUKI , SI_AKAITSUKI , SCB_NONE); - set_sc(OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE); - - // Storing the target job rather than simply SC_SPIRIT simplifies code later on. - SkillStatusChangeTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST, - SkillStatusChangeTable[SL_MONK] = (sc_type)MAPID_MONK, - SkillStatusChangeTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR, - SkillStatusChangeTable[SL_SAGE] = (sc_type)MAPID_SAGE, - SkillStatusChangeTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER, - SkillStatusChangeTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE, - SkillStatusChangeTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT, - SkillStatusChangeTable[SL_WIZARD] = (sc_type)MAPID_WIZARD, - SkillStatusChangeTable[SL_PRIEST] = (sc_type)MAPID_PRIEST, - SkillStatusChangeTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER, - SkillStatusChangeTable[SL_ROGUE] = (sc_type)MAPID_ROGUE, - SkillStatusChangeTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN, - SkillStatusChangeTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH, - SkillStatusChangeTable[SL_HUNTER] = (sc_type)MAPID_HUNTER, - SkillStatusChangeTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER, - - //Status that don't have a skill associated. - StatusIconChangeTable[SC_WEIGHT50] = SI_WEIGHT50; - StatusIconChangeTable[SC_WEIGHT90] = SI_WEIGHT90; - StatusIconChangeTable[SC_ASPDPOTION0] = SI_ASPDPOTION0; - StatusIconChangeTable[SC_ASPDPOTION1] = SI_ASPDPOTION1; - StatusIconChangeTable[SC_ASPDPOTION2] = SI_ASPDPOTION2; - StatusIconChangeTable[SC_ASPDPOTION3] = SI_ASPDPOTIONINFINITY; - StatusIconChangeTable[SC_SPEEDUP0] = SI_MOVHASTE_HORSE; - StatusIconChangeTable[SC_SPEEDUP1] = SI_SPEEDPOTION1; - StatusIconChangeTable[SC_INCSTR] = SI_INCSTR; - StatusIconChangeTable[SC_MIRACLE] = SI_SPIRIT; - StatusIconChangeTable[SC_INTRAVISION] = SI_INTRAVISION; - StatusIconChangeTable[SC_STRFOOD] = SI_FOODSTR; - StatusIconChangeTable[SC_AGIFOOD] = SI_FOODAGI; - StatusIconChangeTable[SC_VITFOOD] = SI_FOODVIT; - StatusIconChangeTable[SC_INTFOOD] = SI_FOODINT; - StatusIconChangeTable[SC_DEXFOOD] = SI_FOODDEX; - StatusIconChangeTable[SC_LUKFOOD] = SI_FOODLUK; - StatusIconChangeTable[SC_FLEEFOOD]= SI_FOODFLEE; - StatusIconChangeTable[SC_HITFOOD] = SI_FOODHIT; - StatusIconChangeTable[SC_MANU_ATK] = SI_MANU_ATK; - StatusIconChangeTable[SC_MANU_DEF] = SI_MANU_DEF; - StatusIconChangeTable[SC_SPL_ATK] = SI_SPL_ATK; - StatusIconChangeTable[SC_SPL_DEF] = SI_SPL_DEF; - StatusIconChangeTable[SC_MANU_MATK] = SI_MANU_MATK; - StatusIconChangeTable[SC_SPL_MATK] = SI_SPL_MATK; - //Cash Items - StatusIconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH; - StatusIconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH; - StatusIconChangeTable[SC_FOOD_VIT_CASH] = SI_FOOD_VIT_CASH; - StatusIconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH; - StatusIconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH; - StatusIconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH; - StatusIconChangeTable[SC_EXPBOOST] = SI_EXPBOOST; - StatusIconChangeTable[SC_ITEMBOOST] = SI_ITEMBOOST; - StatusIconChangeTable[SC_JEXPBOOST] = SI_CASH_PLUSONLYJOBEXP; - StatusIconChangeTable[SC_LIFEINSURANCE] = SI_LIFEINSURANCE; - StatusIconChangeTable[SC_BOSSMAPINFO] = SI_BOSSMAPINFO; - StatusIconChangeTable[SC_DEF_RATE] = SI_DEF_RATE; - StatusIconChangeTable[SC_MDEF_RATE] = SI_MDEF_RATE; - StatusIconChangeTable[SC_INCCRI] = SI_INCCRI; - StatusIconChangeTable[SC_INCFLEE2] = SI_PLUSAVOIDVALUE; - StatusIconChangeTable[SC_INCHEALRATE] = SI_INCHEALRATE; - StatusIconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION; - StatusIconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION; - StatusIconChangeTable[SC_SPCOST_RATE] = SI_ATKER_BLOOD; - StatusIconChangeTable[SC_COMMONSC_RESIST] = SI_TARGET_BLOOD; - // Mercenary Bonus Effects - StatusIconChangeTable[SC_MERC_FLEEUP] = SI_MERC_FLEEUP; - StatusIconChangeTable[SC_MERC_ATKUP] = SI_MERC_ATKUP; - StatusIconChangeTable[SC_MERC_HPUP] = SI_MERC_HPUP; - StatusIconChangeTable[SC_MERC_SPUP] = SI_MERC_SPUP; - StatusIconChangeTable[SC_MERC_HITUP] = SI_MERC_HITUP; - // Warlock Spheres - StatusIconChangeTable[SC_SPHERE_1] = SI_SPHERE_1; - StatusIconChangeTable[SC_SPHERE_2] = SI_SPHERE_2; - StatusIconChangeTable[SC_SPHERE_3] = SI_SPHERE_3; - StatusIconChangeTable[SC_SPHERE_4] = SI_SPHERE_4; - StatusIconChangeTable[SC_SPHERE_5] = SI_SPHERE_5; - // Warlock Preserved spells - StatusIconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1; - StatusIconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2; - StatusIconChangeTable[SC_SPELLBOOK3] = SI_SPELLBOOK3; - StatusIconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4; - StatusIconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5; - StatusIconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6; - StatusIconChangeTable[SC_MAXSPELLBOOK] = SI_SPELLBOOK7; - - StatusIconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER; - StatusIconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER; - StatusIconChangeTable[SC_OVERHEAT] = SI_OVERHEAT; - StatusIconChangeTable[SC_OVERHEAT_LIMITPOINT] = SI_OVERHEAT_LIMITPOINT; - - StatusIconChangeTable[SC_HALLUCINATIONWALK_POSTDELAY] = SI_HALLUCINATIONWALK_POSTDELAY; - StatusIconChangeTable[SC_TOXIN] = SI_TOXIN; - StatusIconChangeTable[SC_PARALYSE] = SI_PARALYSE; - StatusIconChangeTable[SC_VENOMBLEED] = SI_VENOMBLEED; - StatusIconChangeTable[SC_MAGICMUSHROOM] = SI_MAGICMUSHROOM; - StatusIconChangeTable[SC_DEATHHURT] = SI_DEATHHURT; - StatusIconChangeTable[SC_PYREXIA] = SI_PYREXIA; - StatusIconChangeTable[SC_OBLIVIONCURSE] = SI_OBLIVIONCURSE; - StatusIconChangeTable[SC_LEECHESEND] = SI_LEECHESEND; - - StatusIconChangeTable[SC_SHIELDSPELL_DEF] = SI_SHIELDSPELL_DEF; - StatusIconChangeTable[SC_SHIELDSPELL_MDEF] = SI_SHIELDSPELL_MDEF; - StatusIconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF; - StatusIconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE; - - StatusIconChangeTable[SC_GLOOMYDAY_SK] = SI_GLOOMYDAY; - - StatusIconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER; - - StatusIconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE; - StatusIconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER; - StatusIconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB; - StatusIconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB; - StatusIconChangeTable[SC_BANANA_BOMB_SITDOWN] = SI_BANANA_BOMB_SITDOWN_POSTDELAY; - - //Genetics New Food Items Status Icons - StatusIconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK; - StatusIconChangeTable[SC_COCKTAIL_WARG_BLOOD] = SI_COCKTAIL_WARG_BLOOD; - StatusIconChangeTable[SC_MINOR_BBQ] = SI_MINOR_BBQ; - StatusIconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA; - StatusIconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED; - StatusIconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES; - - StatusIconChangeTable[SC_BOOST500] |= SI_BOOST500; - StatusIconChangeTable[SC_FULL_SWING_K] |= SI_FULL_SWING_K; - StatusIconChangeTable[SC_MANA_PLUS] |= SI_MANA_PLUS; - StatusIconChangeTable[SC_MUSTLE_M] |= SI_MUSTLE_M; - StatusIconChangeTable[SC_LIFE_FORCE_F] |= SI_LIFE_FORCE_F; - StatusIconChangeTable[SC_EXTRACT_WHITE_POTION_Z] |= SI_EXTRACT_WHITE_POTION_Z; - StatusIconChangeTable[SC_VITATA_500] |= SI_VITATA_500; - StatusIconChangeTable[SC_EXTRACT_SALAMINE_JUICE] |= SI_EXTRACT_SALAMINE_JUICE; - - // Elemental Spirit's 'side' status change icons. - StatusIconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE; - StatusIconChangeTable[SC_FIRE_CLOAK] = SI_FIRE_CLOAK; - StatusIconChangeTable[SC_WATER_SCREEN] = SI_WATER_SCREEN; - StatusIconChangeTable[SC_WATER_DROP] = SI_WATER_DROP; - StatusIconChangeTable[SC_WIND_STEP] = SI_WIND_STEP; - StatusIconChangeTable[SC_WIND_CURTAIN] = SI_WIND_CURTAIN; - StatusIconChangeTable[SC_SOLID_SKIN] = SI_SOLID_SKIN; - StatusIconChangeTable[SC_STONE_SHIELD] = SI_STONE_SHIELD; - StatusIconChangeTable[SC_PYROTECHNIC] = SI_PYROTECHNIC; - StatusIconChangeTable[SC_HEATER] = SI_HEATER; - StatusIconChangeTable[SC_TROPIC] = SI_TROPIC; - StatusIconChangeTable[SC_AQUAPLAY] = SI_AQUAPLAY; - StatusIconChangeTable[SC_COOLER] = SI_COOLER; - StatusIconChangeTable[SC_CHILLY_AIR] = SI_CHILLY_AIR; - StatusIconChangeTable[SC_GUST] = SI_GUST; - StatusIconChangeTable[SC_BLAST] = SI_BLAST; - StatusIconChangeTable[SC_WILD_STORM] = SI_WILD_STORM; - StatusIconChangeTable[SC_PETROLOGY] = SI_PETROLOGY; - StatusIconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL; - StatusIconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL; - StatusIconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART; - - //Other SC which are not necessarily associated to skills. - StatusChangeFlagTable[SC_ASPDPOTION0] = SCB_ASPD; - StatusChangeFlagTable[SC_ASPDPOTION1] = SCB_ASPD; - StatusChangeFlagTable[SC_ASPDPOTION2] = SCB_ASPD; - StatusChangeFlagTable[SC_ASPDPOTION3] = SCB_ASPD; - StatusChangeFlagTable[SC_SPEEDUP0] = SCB_SPEED; - StatusChangeFlagTable[SC_SPEEDUP1] = SCB_SPEED; - StatusChangeFlagTable[SC_ATKPOTION] = SCB_BATK; - StatusChangeFlagTable[SC_MATKPOTION] = SCB_MATK; - StatusChangeFlagTable[SC_INCALLSTATUS] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK; - StatusChangeFlagTable[SC_INCSTR] |= SCB_STR; - StatusChangeFlagTable[SC_INCAGI] |= SCB_AGI; - StatusChangeFlagTable[SC_INCVIT] |= SCB_VIT; - StatusChangeFlagTable[SC_INCINT] |= SCB_INT; - StatusChangeFlagTable[SC_INCDEX] |= SCB_DEX; - StatusChangeFlagTable[SC_INCLUK] |= SCB_LUK; - StatusChangeFlagTable[SC_INCHIT] |= SCB_HIT; - StatusChangeFlagTable[SC_INCHITRATE] |= SCB_HIT; - StatusChangeFlagTable[SC_INCFLEE] |= SCB_FLEE; - StatusChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE; - StatusChangeFlagTable[SC_INCCRI] |= SCB_CRI; - StatusChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD; - StatusChangeFlagTable[SC_INCFLEE2] |= SCB_FLEE2; - StatusChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP; - StatusChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP; - StatusChangeFlagTable[SC_INCMHP] |= SCB_MAXHP; - StatusChangeFlagTable[SC_INCMSP] |= SCB_MAXSP; - StatusChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK; - StatusChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK; - StatusChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF; - StatusChangeFlagTable[SC_STRFOOD] |= SCB_STR; - StatusChangeFlagTable[SC_AGIFOOD] |= SCB_AGI; - StatusChangeFlagTable[SC_VITFOOD] |= SCB_VIT; - StatusChangeFlagTable[SC_INTFOOD] |= SCB_INT; - StatusChangeFlagTable[SC_DEXFOOD] |= SCB_DEX; - StatusChangeFlagTable[SC_LUKFOOD] |= SCB_LUK; - StatusChangeFlagTable[SC_HITFOOD] |= SCB_HIT; - StatusChangeFlagTable[SC_FLEEFOOD] |= SCB_FLEE; - StatusChangeFlagTable[SC_BATKFOOD] |= SCB_BATK; - StatusChangeFlagTable[SC_WATKFOOD] |= SCB_WATK; - StatusChangeFlagTable[SC_MATKFOOD] |= SCB_MATK; - StatusChangeFlagTable[SC_ARMOR_ELEMENT] |= SCB_ALL; - StatusChangeFlagTable[SC_ARMOR_RESIST] |= SCB_ALL; - StatusChangeFlagTable[SC_SPCOST_RATE] |= SCB_ALL; - StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; - StatusChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL; - // Cash Items - StatusChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR; - StatusChangeFlagTable[SC_FOOD_AGI_CASH] = SCB_AGI; - StatusChangeFlagTable[SC_FOOD_VIT_CASH] = SCB_VIT; - StatusChangeFlagTable[SC_FOOD_DEX_CASH] = SCB_DEX; - StatusChangeFlagTable[SC_FOOD_INT_CASH] = SCB_INT; - StatusChangeFlagTable[SC_FOOD_LUK_CASH] = SCB_LUK; - // Mercenary Bonus Effects - StatusChangeFlagTable[SC_MERC_FLEEUP] |= SCB_FLEE; - StatusChangeFlagTable[SC_MERC_ATKUP] |= SCB_WATK; - StatusChangeFlagTable[SC_MERC_HPUP] |= SCB_MAXHP; - StatusChangeFlagTable[SC_MERC_SPUP] |= SCB_MAXSP; - StatusChangeFlagTable[SC_MERC_HITUP] |= SCB_HIT; - // Guillotine Cross Poison Effects - StatusChangeFlagTable[SC_PARALYSE] |= SCB_ASPD|SCB_FLEE|SCB_SPEED; - StatusChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN; - StatusChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP; - StatusChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN; - - StatusChangeFlagTable[SC_SAVAGE_STEAK] |= SCB_STR; - StatusChangeFlagTable[SC_COCKTAIL_WARG_BLOOD] |= SCB_INT; - StatusChangeFlagTable[SC_MINOR_BBQ] |= SCB_VIT; - StatusChangeFlagTable[SC_SIROMA_ICE_TEA] |= SCB_DEX; - StatusChangeFlagTable[SC_DROCERA_HERB_STEAMED] |= SCB_AGI; - StatusChangeFlagTable[SC_PUTTI_TAILS_NOODLES] |= SCB_LUK; - StatusChangeFlagTable[SC_BOOST500] |= SCB_ASPD; - StatusChangeFlagTable[SC_FULL_SWING_K] |= SCB_BATK; - StatusChangeFlagTable[SC_MANA_PLUS] |= SCB_MATK; - StatusChangeFlagTable[SC_MUSTLE_M] |= SCB_MAXHP; - StatusChangeFlagTable[SC_LIFE_FORCE_F] |= SCB_MAXSP; - StatusChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN; - StatusChangeFlagTable[SC_VITATA_500] |= SCB_REGEN; - StatusChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD; + add_sc( SA_MAGICROD , SC_MAGICROD ); + set_sc( SA_AUTOSPELL , SC_AUTOSPELL , SI_AUTOSPELL , SCB_NONE ); + set_sc( SA_FLAMELAUNCHER , SC_FIREWEAPON , SI_FIREWEAPON , SCB_ATK_ELE ); + set_sc( SA_FROSTWEAPON , SC_WATERWEAPON , SI_WATERWEAPON , SCB_ATK_ELE ); + set_sc( SA_LIGHTNINGLOADER , SC_WINDWEAPON , SI_WINDWEAPON , SCB_ATK_ELE ); + set_sc( SA_SEISMICWEAPON , SC_EARTHWEAPON , SI_EARTHWEAPON , SCB_ATK_ELE ); + set_sc( SA_VOLCANO , SC_VOLCANO , SI_LANDENDOW , SCB_WATK ); + set_sc( SA_DELUGE , SC_DELUGE , SI_LANDENDOW , SCB_MAXHP ); + set_sc( SA_VIOLENTGALE , SC_VIOLENTGALE , SI_LANDENDOW , SCB_FLEE ); + add_sc( SA_REVERSEORCISH , SC_ORCISH ); + add_sc( SA_COMA , SC_COMA ); + set_sc( BD_ENCORE , SC_DANCING , SI_BLANK , SCB_SPEED|SCB_REGEN ); + add_sc( BD_RICHMANKIM , SC_RICHMANKIM ); + set_sc( BD_ETERNALCHAOS , SC_ETERNALCHAOS , SI_BLANK , SCB_DEF2 ); + set_sc( BD_DRUMBATTLEFIELD , SC_DRUMBATTLE , SI_BLANK , SCB_WATK|SCB_DEF ); + set_sc( BD_RINGNIBELUNGEN , SC_NIBELUNGEN , SI_BLANK , SCB_WATK ); + add_sc( BD_ROKISWEIL , SC_ROKISWEIL ); + add_sc( BD_INTOABYSS , SC_INTOABYSS ); + set_sc( BD_SIEGFRIED , SC_SIEGFRIED , SI_BLANK , SCB_ALL ); + add_sc( BA_FROSTJOKER , SC_FREEZE ); + set_sc( BA_WHISTLE , SC_WHISTLE , SI_BLANK , SCB_FLEE|SCB_FLEE2 ); + set_sc( BA_ASSASSINCROSS , SC_ASSNCROS , SI_BLANK , SCB_ASPD ); + add_sc( BA_POEMBRAGI , SC_POEMBRAGI ); + set_sc( BA_APPLEIDUN , SC_APPLEIDUN , SI_BLANK , SCB_MAXHP ); + add_sc( DC_SCREAM , SC_STUN ); + set_sc( DC_HUMMING , SC_HUMMING , SI_BLANK , SCB_HIT ); + set_sc( DC_DONTFORGETME , SC_DONTFORGETME , SI_BLANK , SCB_SPEED|SCB_ASPD ); + set_sc( DC_FORTUNEKISS , SC_FORTUNE , SI_BLANK , SCB_CRI ); + set_sc( DC_SERVICEFORYOU , SC_SERVICE4U , SI_BLANK , SCB_ALL ); + add_sc( NPC_DARKCROSS , SC_BLIND ); + add_sc( NPC_GRANDDARKNESS , SC_BLIND ); + set_sc( NPC_STOP , SC_STOP , SI_STOP , SCB_NONE ); + set_sc( NPC_WEAPONBRAKER , SC_BROKENWEAPON , SI_BROKENWEAPON , SCB_NONE ); + set_sc( NPC_ARMORBRAKE , SC_BROKENARMOR , SI_BROKENARMOR , SCB_NONE ); + set_sc( NPC_CHANGEUNDEAD , SC_CHANGEUNDEAD , SI_UNDEAD , SCB_DEF_ELE ); + set_sc( NPC_POWERUP , SC_INCHITRATE , SI_BLANK , SCB_HIT ); + set_sc( NPC_AGIUP , SC_INCFLEERATE , SI_BLANK , SCB_FLEE ); + add_sc( NPC_INVISIBLE , SC_CLOAKING ); + set_sc( LK_AURABLADE , SC_AURABLADE , SI_AURABLADE , SCB_NONE ); + set_sc( LK_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE ); + set_sc( LK_CONCENTRATION , SC_CONCENTRATION , SI_CONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_DSPD ); + set_sc( LK_TENSIONRELAX , SC_TENSIONRELAX , SI_TENSIONRELAX , SCB_REGEN ); + set_sc( LK_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN ); + set_sc( HP_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 ); + add_sc( HP_BASILICA , SC_BASILICA ); + set_sc( HW_MAGICPOWER , SC_MAGICPOWER , SI_MAGICPOWER , SCB_MATK ); + add_sc( PA_SACRIFICE , SC_SACRIFICE ); + set_sc( PA_GOSPEL , SC_GOSPEL , SI_BLANK , SCB_SPEED|SCB_ASPD ); + add_sc( PA_GOSPEL , SC_SCRESIST ); + add_sc( CH_TIGERFIST , SC_STOP ); + set_sc( ASC_EDP , SC_EDP , SI_EDP , SCB_NONE ); + set_sc( SN_SIGHT , SC_TRUESIGHT , SI_TRUESIGHT , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_CRI|SCB_HIT ); + set_sc( SN_WINDWALK , SC_WINDWALK , SI_WINDWALK , SCB_FLEE|SCB_SPEED ); + set_sc( WS_MELTDOWN , SC_MELTDOWN , SI_MELTDOWN , SCB_NONE ); + set_sc( WS_CARTBOOST , SC_CARTBOOST , SI_CARTBOOST , SCB_SPEED ); + set_sc( ST_CHASEWALK , SC_CHASEWALK , SI_BLANK , SCB_SPEED ); + set_sc( ST_REJECTSWORD , SC_REJECTSWORD , SI_REJECTSWORD , SCB_NONE ); + add_sc( ST_REJECTSWORD , SC_AUTOCOUNTER ); + set_sc( CG_MARIONETTE , SC_MARIONETTE , SI_MARIONETTE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + set_sc( CG_MARIONETTE , SC_MARIONETTE2 , SI_MARIONETTE2 , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + add_sc( LK_SPIRALPIERCE , SC_STOP ); + add_sc( LK_HEADCRUSH , SC_BLEEDING ); + set_sc( LK_JOINTBEAT , SC_JOINTBEAT , SI_JOINTBEAT , SCB_BATK|SCB_DEF2|SCB_SPEED|SCB_ASPD ); + add_sc( HW_NAPALMVULCAN , SC_CURSE ); + set_sc( PF_MINDBREAKER , SC_MINDBREAKER , SI_BLANK , SCB_MATK|SCB_MDEF2 ); + add_sc( PF_MEMORIZE , SC_MEMORIZE ); + add_sc( PF_FOGWALL , SC_FOGWALL ); + set_sc( PF_SPIDERWEB , SC_SPIDERWEB , SI_BLANK , SCB_FLEE ); + set_sc( WE_BABY , SC_BABY , SI_BABY , SCB_NONE ); + set_sc( TK_RUN , SC_RUN , SI_RUN , SCB_SPEED|SCB_DSPD ); + set_sc( TK_RUN , SC_SPURT , SI_SPURT , SCB_STR ); + set_sc( TK_READYSTORM , SC_READYSTORM , SI_READYSTORM , SCB_NONE ); + set_sc( TK_READYDOWN , SC_READYDOWN , SI_READYDOWN , SCB_NONE ); + add_sc( TK_DOWNKICK , SC_STUN ); + set_sc( TK_READYTURN , SC_READYTURN , SI_READYTURN , SCB_NONE ); + set_sc( TK_READYCOUNTER , SC_READYCOUNTER , SI_READYCOUNTER , SCB_NONE ); + set_sc( TK_DODGE , SC_DODGE , SI_DODGE , SCB_NONE ); + set_sc( TK_SPTIME , SC_EARTHSCROLL , SI_EARTHSCROLL , SCB_NONE ); + add_sc( TK_SEVENWIND , SC_SEVENWIND ); + set_sc( TK_SEVENWIND , SC_GHOSTWEAPON , SI_GHOSTWEAPON , SCB_ATK_ELE ); + set_sc( TK_SEVENWIND , SC_SHADOWWEAPON , SI_SHADOWWEAPON , SCB_ATK_ELE ); + set_sc( SG_SUN_WARM , SC_WARM , SI_WARM , SCB_NONE ); + add_sc( SG_MOON_WARM , SC_WARM ); + add_sc( SG_STAR_WARM , SC_WARM ); + set_sc( SG_SUN_COMFORT , SC_SUN_COMFORT , SI_SUN_COMFORT , SCB_DEF2 ); + set_sc( SG_MOON_COMFORT , SC_MOON_COMFORT , SI_MOON_COMFORT , SCB_FLEE ); + set_sc( SG_STAR_COMFORT , SC_STAR_COMFORT , SI_STAR_COMFORT , SCB_ASPD ); + add_sc( SG_FRIEND , SC_SKILLRATE_UP ); + set_sc( SG_KNOWLEDGE , SC_KNOWLEDGE , SI_BLANK , SCB_ALL ); + set_sc( SG_FUSION , SC_FUSION , SI_BLANK , SCB_SPEED ); + set_sc( BS_ADRENALINE2 , SC_ADRENALINE2 , SI_ADRENALINE2 , SCB_ASPD ); + set_sc( SL_KAIZEL , SC_KAIZEL , SI_KAIZEL , SCB_NONE ); + set_sc( SL_KAAHI , SC_KAAHI , SI_KAAHI , SCB_NONE ); + set_sc( SL_KAUPE , SC_KAUPE , SI_KAUPE , SCB_NONE ); + set_sc( SL_KAITE , SC_KAITE , SI_KAITE , SCB_NONE ); + add_sc( SL_STUN , SC_STUN ); + set_sc( SL_SWOO , SC_SWOO , SI_BLANK , SCB_SPEED ); + set_sc( SL_SKE , SC_SKE , SI_BLANK , SCB_BATK|SCB_WATK|SCB_DEF|SCB_DEF2 ); + set_sc( SL_SKA , SC_SKA , SI_BLANK , SCB_DEF|SCB_MDEF|SCB_ASPD ); + set_sc( SL_SMA , SC_SMA , SI_SMA , SCB_NONE ); + set_sc( SM_SELFPROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); + set_sc( ST_PRESERVE , SC_PRESERVE , SI_PRESERVE , SCB_NONE ); + set_sc( PF_DOUBLECASTING , SC_DOUBLECAST , SI_DOUBLECAST , SCB_NONE ); + set_sc( HW_GRAVITATION , SC_GRAVITATION , SI_BLANK , SCB_ASPD ); + add_sc( WS_CARTTERMINATION , SC_STUN ); + set_sc( WS_OVERTHRUSTMAX , SC_MAXOVERTHRUST , SI_MAXOVERTHRUST , SCB_NONE ); + set_sc( CG_LONGINGFREEDOM , SC_LONGING , SI_BLANK , SCB_SPEED|SCB_ASPD ); + add_sc( CG_HERMODE , SC_HERMODE ); + set_sc( ITEM_ENCHANTARMS , SC_ENCHANTARMS , SI_BLANK , SCB_ATK_ELE ); + set_sc( SL_HIGH , SC_SPIRIT , SI_SPIRIT , SCB_ALL ); + set_sc( KN_ONEHAND , SC_ONEHAND , SI_ONEHAND , SCB_ASPD ); + set_sc( GS_FLING , SC_FLING , SI_BLANK , SCB_DEF|SCB_DEF2 ); + add_sc( GS_CRACKER , SC_STUN ); + add_sc( GS_DISARM , SC_STRIPWEAPON ); + add_sc( GS_PIERCINGSHOT , SC_BLEEDING ); + set_sc( GS_MADNESSCANCEL , SC_MADNESSCANCEL , SI_MADNESSCANCEL , SCB_BATK|SCB_ASPD ); + set_sc( GS_ADJUSTMENT , SC_ADJUSTMENT , SI_ADJUSTMENT , SCB_HIT|SCB_FLEE ); + set_sc( GS_INCREASING , SC_INCREASING , SI_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT ); + set_sc( GS_GATLINGFEVER , SC_GATLINGFEVER , SI_GATLINGFEVER , SCB_BATK|SCB_FLEE|SCB_SPEED|SCB_ASPD ); + set_sc( NJ_TATAMIGAESHI , SC_TATAMIGAESHI , SI_BLANK , SCB_NONE ); + set_sc( NJ_SUITON , SC_SUITON , SI_BLANK , SCB_AGI|SCB_SPEED ); + add_sc( NJ_HYOUSYOURAKU , SC_FREEZE ); + set_sc( NJ_NEN , SC_NEN , SI_NEN , SCB_STR|SCB_INT ); + set_sc( NJ_UTSUSEMI , SC_UTSUSEMI , SI_UTSUSEMI , SCB_NONE ); + set_sc( NJ_BUNSINJYUTSU , SC_BUNSINJYUTSU , SI_BUNSINJYUTSU , SCB_DYE ); + + add_sc( NPC_ICEBREATH , SC_FREEZE ); + add_sc( NPC_ACIDBREATH , SC_POISON ); + add_sc( NPC_HELLJUDGEMENT , SC_CURSE ); + add_sc( NPC_WIDESILENCE , SC_SILENCE ); + add_sc( NPC_WIDEFREEZE , SC_FREEZE ); + add_sc( NPC_WIDEBLEEDING , SC_BLEEDING ); + add_sc( NPC_WIDESTONE , SC_STONE ); + add_sc( NPC_WIDECONFUSE , SC_CONFUSION ); + add_sc( NPC_WIDESLEEP , SC_SLEEP ); + add_sc( NPC_WIDESIGHT , SC_SIGHT ); + add_sc( NPC_EVILLAND , SC_BLIND ); + add_sc( NPC_MAGICMIRROR , SC_MAGICMIRROR ); + set_sc( NPC_SLOWCAST , SC_SLOWCAST , SI_SLOWCAST , SCB_NONE ); + set_sc( NPC_CRITICALWOUND , SC_CRITICALWOUND , SI_CRITICALWOUND , SCB_NONE ); + set_sc( NPC_STONESKIN , SC_ARMORCHANGE , SI_BLANK , SCB_DEF|SCB_MDEF ); + add_sc( NPC_ANTIMAGIC , SC_ARMORCHANGE ); + add_sc( NPC_WIDECURSE , SC_CURSE ); + add_sc( NPC_WIDESTUN , SC_STUN ); + + set_sc( NPC_HELLPOWER , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE ); + set_sc( NPC_WIDEHELLDIGNITY , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE ); + set_sc( NPC_INVINCIBLE , SC_INVINCIBLE , SI_INVINCIBLE , SCB_SPEED ); + set_sc( NPC_INVINCIBLEOFF , SC_INVINCIBLEOFF , SI_BLANK , SCB_SPEED ); + + set_sc( CASH_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); + set_sc( CASH_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED ); + set_sc( CASH_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 ); + + set_sc( ALL_PARTYFLEE , SC_PARTYFLEE , SI_PARTYFLEE , SCB_NONE ); + set_sc( ALL_ODINS_POWER , SC_ODINS_POWER , SI_ODINS_POWER , SCB_MATK|SCB_BATK|SCB_MDEF|SCB_DEF ); + + set_sc( CR_SHRINK , SC_SHRINK , SI_SHRINK , SCB_NONE ); + set_sc( RG_CLOSECONFINE , SC_CLOSECONFINE2 , SI_CLOSECONFINE2 , SCB_NONE ); + set_sc( RG_CLOSECONFINE , SC_CLOSECONFINE , SI_CLOSECONFINE , SCB_FLEE ); + set_sc( WZ_SIGHTBLASTER , SC_SIGHTBLASTER , SI_SIGHTBLASTER , SCB_NONE ); + set_sc( DC_WINKCHARM , SC_WINKCHARM , SI_WINKCHARM , SCB_NONE ); + add_sc( MO_BALKYOUNG , SC_STUN ); + add_sc( SA_ELEMENTWATER , SC_ELEMENTALCHANGE ); + add_sc( SA_ELEMENTFIRE , SC_ELEMENTALCHANGE ); + add_sc( SA_ELEMENTGROUND , SC_ELEMENTALCHANGE ); + add_sc( SA_ELEMENTWIND , SC_ELEMENTALCHANGE ); + + set_sc( HLIF_AVOID , SC_AVOID , SI_BLANK , SCB_SPEED ); + set_sc( HLIF_CHANGE , SC_CHANGE , SI_BLANK , SCB_VIT|SCB_INT ); + set_sc( HFLI_FLEET , SC_FLEET , SI_BLANK , SCB_ASPD|SCB_BATK|SCB_WATK ); + set_sc( HFLI_SPEED , SC_SPEED , SI_BLANK , SCB_FLEE ); + set_sc( HAMI_DEFENCE , SC_DEFENCE , SI_BLANK , SCB_DEF ); + set_sc( HAMI_BLOODLUST , SC_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK ); + + // Homunculus S + add_sc(MH_STAHL_HORN, SC_STUN); + set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP); + set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP); + add_sc( MH_STEINWAND, SC_SAFETYWALL ); + add_sc(MH_ERASER_CUTTER, SC_ERASER_CUTTER); + set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD); + add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE); + set_sc(MH_VOLCANIC_ASH, SC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE); + set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE); + set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE); + set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SI_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE); + add_sc(MH_LAVA_SLIDE, SC_BURNING); + set_sc(MH_NEEDLE_OF_PARALYZE, SC_PARALYSIS, SI_NEEDLE_OF_PARALYZE, SCB_DEF2); + add_sc(MH_POISON_MIST, SC_BLIND); + set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD); + + add_sc(MH_STYLE_CHANGE, SC_STYLE_CHANGE); + + + add_sc( MER_CRASH , SC_STUN ); + set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); + add_sc( MS_MAGNUM , SC_WATK_ELEMENT ); + add_sc( MER_SIGHT , SC_SIGHT ); + set_sc( MER_DECAGI , SC_DECREASEAGI , SI_DECREASEAGI , SCB_AGI|SCB_SPEED ); + set_sc( MER_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN ); + add_sc( MER_LEXDIVINA , SC_SILENCE ); + add_sc( MA_LANDMINE , SC_STUN ); + add_sc( MA_SANDMAN , SC_SLEEP ); + add_sc( MA_FREEZINGTRAP , SC_FREEZE ); + set_sc( MER_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE ); + set_sc( ML_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE ); + set_sc( MS_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE ); + set_sc( ML_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD ); + set_sc( MS_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE ); + set_sc( MS_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN ); + add_sc( ML_SPIRALPIERCE , SC_STOP ); + set_sc( MER_QUICKEN , SC_MERC_QUICKEN , SI_BLANK , SCB_ASPD ); + add_sc( ML_DEVOTION , SC_DEVOTION ); + set_sc( MER_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE ); + set_sc( MER_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); + set_sc( MER_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED ); + + set_sc( GD_LEADERSHIP , SC_LEADERSHIP , SI_BLANK , SCB_STR ); + set_sc( GD_GLORYWOUNDS , SC_GLORYWOUNDS , SI_BLANK , SCB_VIT ); + set_sc( GD_SOULCOLD , SC_SOULCOLD , SI_BLANK , SCB_AGI ); + set_sc( GD_HAWKEYES , SC_HAWKEYES , SI_BLANK , SCB_DEX ); + + set_sc( GD_BATTLEORDER , SC_BATTLEORDERS , SI_BLANK , SCB_STR|SCB_INT|SCB_DEX ); + set_sc( GD_REGENERATION , SC_REGENERATION , SI_BLANK , SCB_REGEN ); + + /** + * Rune Knight + **/ + set_sc( RK_ENCHANTBLADE , SC_ENCHANTBLADE , SI_ENCHANTBLADE , SCB_NONE ); + set_sc( RK_DRAGONHOWLING , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT ); + set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SI_DEATHBOUND , SCB_NONE ); + set_sc( RK_WINDCUTTER , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT ); + add_sc( RK_DRAGONBREATH , SC_BURNING ); + set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_REUSE_MILLENNIUMSHIELD , SCB_NONE ); + set_sc( RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE ); + set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR ); + set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_NONE ); + set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SI_VITALITYACTIVATION, SCB_REGEN ); + set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD ); + set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE ); + /** + * GC Guillotine Cross + **/ + set_sc_with_vfx( GC_VENOMIMPRESS , SC_VENOMIMPRESS , SI_VENOMIMPRESS , SCB_NONE ); + set_sc( GC_POISONINGWEAPON , SC_POISONINGWEAPON , SI_POISONINGWEAPON , SCB_NONE ); + set_sc( GC_WEAPONBLOCKING , SC_WEAPONBLOCKING , SI_WEAPONBLOCKING , SCB_NONE ); + set_sc( GC_CLOAKINGEXCEED , SC_CLOAKINGEXCEED , SI_CLOAKINGEXCEED , SCB_SPEED ); + set_sc( GC_HALLUCINATIONWALK , SC_HALLUCINATIONWALK, SI_HALLUCINATIONWALK, SCB_FLEE ); + set_sc( GC_ROLLINGCUTTER , SC_ROLLINGCUTTER , SI_ROLLINGCUTTER , SCB_NONE ); + /** + * Arch Bishop + **/ + set_sc( AB_ADORAMUS , SC_ADORAMUS , SI_ADORAMUS , SCB_AGI|SCB_SPEED ); + add_sc( AB_CLEMENTIA , SC_BLESSING ); + add_sc( AB_CANTO , SC_INCREASEAGI ); + set_sc( AB_EPICLESIS , SC_EPICLESIS , SI_EPICLESIS , SCB_MAXHP ); + add_sc( AB_PRAEFATIO , SC_KYRIE ); + set_sc_with_vfx( AB_ORATIO , SC_ORATIO , SI_ORATIO , SCB_NONE ); + set_sc( AB_LAUDAAGNUS , SC_LAUDAAGNUS , SI_LAUDAAGNUS , SCB_VIT ); + set_sc( AB_LAUDARAMUS , SC_LAUDARAMUS , SI_LAUDARAMUS , SCB_LUK ); + set_sc( AB_RENOVATIO , SC_RENOVATIO , SI_RENOVATIO , SCB_REGEN ); + set_sc( AB_EXPIATIO , SC_EXPIATIO , SI_EXPIATIO , SCB_ATK_ELE ); + set_sc( AB_DUPLELIGHT , SC_DUPLELIGHT , SI_DUPLELIGHT , SCB_NONE ); + set_sc( AB_SECRAMENT , SC_SECRAMENT , SI_SECRAMENT , SCB_NONE ); + /** + * Warlock + **/ + add_sc( WL_WHITEIMPRISON , SC_WHITEIMPRISON ); + set_sc_with_vfx( WL_FROSTMISTY , SC_FREEZING , SI_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF|SCB_DEF2 ); + set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SI_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_DEF|SCB_MDEF ); + set_sc( WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_NONE ); + set_sc( WL_STASIS , SC_STASIS , SI_STASIS , SCB_NONE ); + /** + * Ranger + **/ + set_sc( RA_FEARBREEZE , SC_FEARBREEZE , SI_FEARBREEZE , SCB_NONE ); + set_sc( RA_ELECTRICSHOCKER , SC_ELECTRICSHOCKER , SI_ELECTRICSHOCKER , SCB_NONE ); + set_sc( RA_WUGDASH , SC_WUGDASH , SI_WUGDASH , SCB_SPEED ); + set_sc( RA_CAMOUFLAGE , SC_CAMOUFLAGE , SI_CAMOUFLAGE , SCB_SPEED ); + add_sc( RA_MAGENTATRAP , SC_ELEMENTALCHANGE ); + add_sc( RA_COBALTTRAP , SC_ELEMENTALCHANGE ); + add_sc( RA_MAIZETRAP , SC_ELEMENTALCHANGE ); + add_sc( RA_VERDURETRAP , SC_ELEMENTALCHANGE ); + add_sc( RA_FIRINGTRAP , SC_BURNING ); + set_sc_with_vfx( RA_ICEBOUNDTRAP , SC_FREEZING , SI_FROSTMISTY , SCB_NONE ); + /** + * Mechanic + **/ + set_sc( NC_ACCELERATION , SC_ACCELERATION , SI_ACCELERATION , SCB_SPEED ); + set_sc( NC_HOVERING , SC_HOVERING , SI_HOVERING , SCB_SPEED ); + set_sc( NC_SHAPESHIFT , SC_SHAPESHIFT , SI_SHAPESHIFT , SCB_DEF_ELE ); + set_sc( NC_INFRAREDSCAN , SC_INFRAREDSCAN , SI_INFRAREDSCAN , SCB_FLEE ); + set_sc( NC_ANALYZE , SC_ANALYZE , SI_ANALYZE , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 ); + set_sc( NC_MAGNETICFIELD , SC_MAGNETICFIELD , SI_MAGNETICFIELD , SCB_NONE ); + set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_NONE ); + set_sc( NC_STEALTHFIELD , SC_STEALTHFIELD , SI_STEALTHFIELD , SCB_NONE ); + /** + * Royal Guard + **/ + set_sc( LG_REFLECTDAMAGE , SC_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE ); + set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP|SCB_DEF ); + set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE ); + set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF ); + set_sc( LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2 + set_sc( LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE ); + set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD ); + set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK); + set_sc( LG_SHIELDSPELL , SC_SHIELDSPELL_DEF , SI_SHIELDSPELL_DEF , SCB_WATK ); + set_sc( LG_SHIELDSPELL , SC_SHIELDSPELL_REF , SI_SHIELDSPELL_REF , SCB_DEF ); + /** + * Shadow Chaser + **/ + set_sc( SC_REPRODUCE , SC__REPRODUCE , SI_REPRODUCE , SCB_NONE ); + set_sc( SC_AUTOSHADOWSPELL , SC__AUTOSHADOWSPELL, SI_AUTOSHADOWSPELL , SCB_NONE ); + set_sc( SC_SHADOWFORM , SC__SHADOWFORM , SI_SHADOWFORM , SCB_NONE ); + set_sc( SC_BODYPAINT , SC__BODYPAINT , SI_BODYPAINT , SCB_ASPD ); + set_sc( SC_INVISIBILITY , SC__INVISIBILITY , SI_INVISIBILITY , SCB_ASPD|SCB_CRI|SCB_ATK_ELE ); + set_sc( SC_DEADLYINFECT , SC__DEADLYINFECT , SI_DEADLYINFECT , SCB_NONE ); + set_sc( SC_ENERVATION , SC__ENERVATION , SI_ENERVATION , SCB_BATK ); + set_sc( SC_GROOMY , SC__GROOMY , SI_GROOMY , SCB_ASPD|SCB_HIT|SCB_SPEED ); + set_sc( SC_IGNORANCE , SC__IGNORANCE , SI_IGNORANCE , SCB_NONE ); + set_sc( SC_LAZINESS , SC__LAZINESS , SI_LAZINESS , SCB_FLEE ); + set_sc( SC_UNLUCKY , SC__UNLUCKY , SI_UNLUCKY , SCB_CRI|SCB_FLEE2 ); + set_sc( SC_WEAKNESS , SC__WEAKNESS , SI_WEAKNESS , SCB_FLEE2|SCB_MAXHP ); + set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSORY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK ); + set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SI_MANHOLE , SCB_NONE ); + add_sc( SC_CHAOSPANIC , SC_CONFUSION ); + set_sc_with_vfx( SC_BLOODYLUST , SC__BLOODYLUST , SI_BLOODYLUST , SCB_DEF | SCB_DEF2 | SCB_MDEF | SCB_MDEF2 | SCB_FLEE | SCB_SPEED | SCB_ASPD | SCB_MAXHP | SCB_REGEN ); + /** + * Sura + **/ + add_sc( SR_DRAGONCOMBO , SC_STUN ); + add_sc( SR_EARTHSHAKER , SC_STUN ); + set_sc( SR_CRESCENTELBOW , SC_CRESCENTELBOW , SI_CRESCENTELBOW , SCB_NONE ); + set_sc_with_vfx( SR_CURSEDCIRCLE , SC_CURSEDCIRCLE_TARGET, SI_CURSEDCIRCLE_TARGET , SCB_NONE ); + set_sc( SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SI_LIGHTNINGWALK , SCB_NONE ); + set_sc( SR_RAISINGDRAGON , SC_RAISINGDRAGON , SI_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP ); + set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GT_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE ); + set_sc( SR_GENTLETOUCH_CHANGE , SC_GT_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP ); + set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GT_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_REGEN ); + /** + * Wanderer / Minstrel + **/ + set_sc( WA_SWING_DANCE , SC_SWINGDANCE , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD ); + set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONYOFLOVER , SI_SYMPHONYOFLOVERS , SCB_MDEF ); + set_sc( WA_MOONLIT_SERENADE , SC_MOONLITSERENADE , SI_MOONLITSERENADE , SCB_MATK ); + set_sc( MI_RUSH_WINDMILL , SC_RUSHWINDMILL , SI_RUSHWINDMILL , SCB_BATK ); + set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 ); + set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + set_sc_with_vfx( WM_POEMOFNETHERWORLD , SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE ); + set_sc_with_vfx( WM_VOICEOFSIREN , SC_VOICEOFSIREN , SI_VOICEOFSIREN , SCB_NONE ); + set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEPSLEEP , SI_DEEPSLEEP , SCB_NONE ); + set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE ); + set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_ASPD ); + set_sc( WM_SONG_OF_MANA , SC_SONGOFMANA , SI_SONGOFMANA , SCB_NONE ); + set_sc( WM_DANCE_WITH_WUG , SC_DANCEWITHWUG , SI_DANCEWITHWUG , SCB_ASPD ); + set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAYNIGHTFEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN ); + set_sc( WM_LERADS_DEW , SC_LERADSDEW , SI_LERADSDEW , SCB_MAXHP ); + set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_BATK|SCB_MATK ); + set_sc( WM_BEYOND_OF_WARCRY , SC_BEYONDOFWARCRY , SI_WARCRYOFBEYOND , SCB_BATK|SCB_MATK ); + set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITEDHUMMINGVOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE ); + /** + * Sorcerer + **/ + set_sc( SO_FIREWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE ); + set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE ); + set_sc( SO_SPELLFIST , SC_SPELLFIST , SI_SPELLFIST , SCB_NONE ); + set_sc_with_vfx( SO_DIAMONDDUST , SC_CRYSTALIZE , SI_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it. + add_sc( SO_CLOUD_KILL , SC_POISON ); + set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI ); + set_sc( SO_WARMER , SC_WARMER , SI_WARMER , SCB_NONE ); + set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE ); + set_sc( SO_ARRULLO , SC_DEEPSLEEP , SI_DEEPSLEEP , SCB_NONE ); + set_sc( SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SI_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); + set_sc( SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SI_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); + set_sc( SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SI_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); + set_sc( SO_EARTH_INSIGNIA , SC_EARTH_INSIGNIA , SI_EARTH_INSIGNIA , SCB_MDEF|SCB_DEF|SCB_MAXHP|SCB_MAXSP|SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); + /** + * Genetic + **/ + set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SI_CARTSBOOST , SCB_SPEED ); + set_sc( GN_THORNS_TRAP , SC_THORNSTRAP , SI_THORNTRAP , SCB_NONE ); + set_sc_with_vfx( GN_BLOOD_SUCKER , SC_BLOODSUCKER , SI_BLOODSUCKER , SCB_NONE ); + set_sc( GN_WALLOFTHORN , SC_STOP , SI_BLANK , SCB_NONE ); + set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_SMOKEPOWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_NONE ); + set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_TEARGAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE ); + set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT ); + + // Elemental Spirit summoner's 'side' status changes. + set_sc( EL_CIRCLE_OF_FIRE , SC_CIRCLE_OF_FIRE_OPTION, SI_CIRCLE_OF_FIRE_OPTION, SCB_NONE ); + set_sc( EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SI_FIRE_CLOAK_OPTION , SCB_ALL ); + set_sc( EL_WATER_SCREEN , SC_WATER_SCREEN_OPTION , SI_WATER_SCREEN_OPTION , SCB_NONE ); + set_sc( EL_WATER_DROP , SC_WATER_DROP_OPTION , SI_WATER_DROP_OPTION , SCB_ALL ); + set_sc( EL_WATER_BARRIER , SC_WATER_BARRIER , SI_WATER_BARRIER , SCB_MDEF|SCB_WATK|SCB_MATK|SCB_FLEE ); + set_sc( EL_WIND_STEP , SC_WIND_STEP_OPTION , SI_WIND_STEP_OPTION , SCB_SPEED|SCB_FLEE ); + set_sc( EL_WIND_CURTAIN , SC_WIND_CURTAIN_OPTION , SI_WIND_CURTAIN_OPTION , SCB_ALL ); + set_sc( EL_ZEPHYR , SC_ZEPHYR , SI_ZEPHYR , SCB_FLEE ); + set_sc( EL_SOLID_SKIN , SC_SOLID_SKIN_OPTION , SI_SOLID_SKIN_OPTION , SCB_DEF|SCB_MAXHP ); + set_sc( EL_STONE_SHIELD , SC_STONE_SHIELD_OPTION , SI_STONE_SHIELD_OPTION , SCB_ALL ); + set_sc( EL_POWER_OF_GAIA , SC_POWER_OF_GAIA , SI_POWER_OF_GAIA , SCB_MAXHP|SCB_DEF|SCB_SPEED ); + set_sc( EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SI_PYROTECHNIC_OPTION , SCB_WATK ); + set_sc( EL_HEATER , SC_HEATER_OPTION , SI_HEATER_OPTION , SCB_WATK ); + set_sc( EL_TROPIC , SC_TROPIC_OPTION , SI_TROPIC_OPTION , SCB_WATK ); + set_sc( EL_AQUAPLAY , SC_AQUAPLAY_OPTION , SI_AQUAPLAY_OPTION , SCB_MATK ); + set_sc( EL_COOLER , SC_COOLER_OPTION , SI_COOLER_OPTION , SCB_MATK ); + set_sc( EL_CHILLY_AIR , SC_CHILLY_AIR_OPTION , SI_CHILLY_AIR_OPTION , SCB_MATK ); + set_sc( EL_GUST , SC_GUST_OPTION , SI_GUST_OPTION , SCB_NONE ); + set_sc( EL_BLAST , SC_BLAST_OPTION , SI_BLAST_OPTION , SCB_NONE ); + set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SI_WILD_STORM_OPTION , SCB_NONE ); + set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SI_PETROLOGY_OPTION , SCB_NONE ); + set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_NONE ); + set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_NONE ); + set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL ); + set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF ); + set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED ); + + add_sc( KO_YAMIKUMO , SC_HIDING ); + set_sc_with_vfx( KO_JYUMONJIKIRI , SC_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE ); + add_sc( KO_MAKIBISHI , SC_STUN ); + set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE ); + set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + add_sc( KO_JYUSATSU , SC_CURSE ); + set_sc( KO_ZENKAI , SC_ZENKAI , SI_ZENKAI , SCB_NONE ); + set_sc( KO_IZAYOI , SC_IZAYOI , SI_IZAYOI , SCB_MATK ); + set_sc( KG_KYOMU , SC_KYOMU , SI_KYOMU , SCB_NONE ); + set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SI_KAGEMUSYA , SCB_NONE ); + set_sc( KG_KAGEHUMI , SC_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE ); + set_sc( OB_ZANGETSU , SC_ZANGETSU , SI_ZANGETSU , SCB_MATK|SCB_BATK ); + set_sc_with_vfx( OB_AKAITSUKI , SC_AKAITSUKI , SI_AKAITSUKI , SCB_NONE ); + set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE ); + + // Storing the target job rather than simply SC_SPIRIT simplifies code later on. + SkillStatusChangeTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST, + SkillStatusChangeTable[SL_MONK] = (sc_type)MAPID_MONK, + SkillStatusChangeTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR, + SkillStatusChangeTable[SL_SAGE] = (sc_type)MAPID_SAGE, + SkillStatusChangeTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER, + SkillStatusChangeTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE, + SkillStatusChangeTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT, + SkillStatusChangeTable[SL_WIZARD] = (sc_type)MAPID_WIZARD, + SkillStatusChangeTable[SL_PRIEST] = (sc_type)MAPID_PRIEST, + SkillStatusChangeTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER, + SkillStatusChangeTable[SL_ROGUE] = (sc_type)MAPID_ROGUE, + SkillStatusChangeTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN, + SkillStatusChangeTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH, + SkillStatusChangeTable[SL_HUNTER] = (sc_type)MAPID_HUNTER, + SkillStatusChangeTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER, + + //Status that don't have a skill associated. + StatusIconChangeTable[SC_WEIGHT50] = SI_WEIGHT50; + StatusIconChangeTable[SC_WEIGHT90] = SI_WEIGHT90; + StatusIconChangeTable[SC_ASPDPOTION0] = SI_ASPDPOTION0; + StatusIconChangeTable[SC_ASPDPOTION1] = SI_ASPDPOTION1; + StatusIconChangeTable[SC_ASPDPOTION2] = SI_ASPDPOTION2; + StatusIconChangeTable[SC_ASPDPOTION3] = SI_ASPDPOTIONINFINITY; + StatusIconChangeTable[SC_SPEEDUP0] = SI_MOVHASTE_HORSE; + StatusIconChangeTable[SC_SPEEDUP1] = SI_SPEEDPOTION1; + StatusIconChangeTable[SC_INCSTR] = SI_INCSTR; + StatusIconChangeTable[SC_MIRACLE] = SI_SPIRIT; + StatusIconChangeTable[SC_INTRAVISION] = SI_INTRAVISION; + StatusIconChangeTable[SC_STRFOOD] = SI_FOODSTR; + StatusIconChangeTable[SC_AGIFOOD] = SI_FOODAGI; + StatusIconChangeTable[SC_VITFOOD] = SI_FOODVIT; + StatusIconChangeTable[SC_INTFOOD] = SI_FOODINT; + StatusIconChangeTable[SC_DEXFOOD] = SI_FOODDEX; + StatusIconChangeTable[SC_LUKFOOD] = SI_FOODLUK; + StatusIconChangeTable[SC_FLEEFOOD]= SI_FOODFLEE; + StatusIconChangeTable[SC_HITFOOD] = SI_FOODHIT; + StatusIconChangeTable[SC_MANU_ATK] = SI_MANU_ATK; + StatusIconChangeTable[SC_MANU_DEF] = SI_MANU_DEF; + StatusIconChangeTable[SC_SPL_ATK] = SI_SPL_ATK; + StatusIconChangeTable[SC_SPL_DEF] = SI_SPL_DEF; + StatusIconChangeTable[SC_MANU_MATK] = SI_MANU_MATK; + StatusIconChangeTable[SC_SPL_MATK] = SI_SPL_MATK; + //Cash Items + StatusIconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH; + StatusIconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH; + StatusIconChangeTable[SC_FOOD_VIT_CASH] = SI_FOOD_VIT_CASH; + StatusIconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH; + StatusIconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH; + StatusIconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH; + StatusIconChangeTable[SC_EXPBOOST] = SI_EXPBOOST; + StatusIconChangeTable[SC_ITEMBOOST] = SI_ITEMBOOST; + StatusIconChangeTable[SC_JEXPBOOST] = SI_CASH_PLUSONLYJOBEXP; + StatusIconChangeTable[SC_LIFEINSURANCE] = SI_LIFEINSURANCE; + StatusIconChangeTable[SC_BOSSMAPINFO] = SI_BOSSMAPINFO; + StatusIconChangeTable[SC_DEF_RATE] = SI_DEF_RATE; + StatusIconChangeTable[SC_MDEF_RATE] = SI_MDEF_RATE; + StatusIconChangeTable[SC_INCCRI] = SI_INCCRI; + StatusIconChangeTable[SC_INCFLEE2] = SI_PLUSAVOIDVALUE; + StatusIconChangeTable[SC_INCHEALRATE] = SI_INCHEALRATE; + StatusIconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION; + StatusIconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION; + StatusIconChangeTable[SC_SPCOST_RATE] = SI_ATKER_BLOOD; + StatusIconChangeTable[SC_COMMONSC_RESIST] = SI_TARGET_BLOOD; + // Mercenary Bonus Effects + StatusIconChangeTable[SC_MERC_FLEEUP] = SI_MERC_FLEEUP; + StatusIconChangeTable[SC_MERC_ATKUP] = SI_MERC_ATKUP; + StatusIconChangeTable[SC_MERC_HPUP] = SI_MERC_HPUP; + StatusIconChangeTable[SC_MERC_SPUP] = SI_MERC_SPUP; + StatusIconChangeTable[SC_MERC_HITUP] = SI_MERC_HITUP; + // Warlock Spheres + StatusIconChangeTable[SC_SPHERE_1] = SI_SPHERE_1; + StatusIconChangeTable[SC_SPHERE_2] = SI_SPHERE_2; + StatusIconChangeTable[SC_SPHERE_3] = SI_SPHERE_3; + StatusIconChangeTable[SC_SPHERE_4] = SI_SPHERE_4; + StatusIconChangeTable[SC_SPHERE_5] = SI_SPHERE_5; + // Warlock Preserved spells + StatusIconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1; + StatusIconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2; + StatusIconChangeTable[SC_SPELLBOOK3] = SI_SPELLBOOK3; + StatusIconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4; + StatusIconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5; + StatusIconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6; + StatusIconChangeTable[SC_MAXSPELLBOOK] = SI_SPELLBOOK7; + + StatusIconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER; + StatusIconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER; + StatusIconChangeTable[SC_OVERHEAT] = SI_OVERHEAT; + StatusIconChangeTable[SC_OVERHEAT_LIMITPOINT] = SI_OVERHEAT_LIMITPOINT; + + StatusIconChangeTable[SC_HALLUCINATIONWALK_POSTDELAY] = SI_HALLUCINATIONWALK_POSTDELAY; + StatusIconChangeTable[SC_TOXIN] = SI_TOXIN; + StatusIconChangeTable[SC_PARALYSE] = SI_PARALYSE; + StatusIconChangeTable[SC_VENOMBLEED] = SI_VENOMBLEED; + StatusIconChangeTable[SC_MAGICMUSHROOM] = SI_MAGICMUSHROOM; + StatusIconChangeTable[SC_DEATHHURT] = SI_DEATHHURT; + StatusIconChangeTable[SC_PYREXIA] = SI_PYREXIA; + StatusIconChangeTable[SC_OBLIVIONCURSE] = SI_OBLIVIONCURSE; + StatusIconChangeTable[SC_LEECHESEND] = SI_LEECHESEND; + + StatusIconChangeTable[SC_SHIELDSPELL_DEF] = SI_SHIELDSPELL_DEF; + StatusIconChangeTable[SC_SHIELDSPELL_MDEF] = SI_SHIELDSPELL_MDEF; + StatusIconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF; + StatusIconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE; + + StatusIconChangeTable[SC_GLOOMYDAY_SK] = SI_GLOOMYDAY; + + StatusIconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER; + + StatusIconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE; + StatusIconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER; + StatusIconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB; + StatusIconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB; + StatusIconChangeTable[SC_BANANA_BOMB_SITDOWN] = SI_BANANA_BOMB_SITDOWN_POSTDELAY; + + //Genetics New Food Items Status Icons + StatusIconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK; + StatusIconChangeTable[SC_COCKTAIL_WARG_BLOOD] = SI_COCKTAIL_WARG_BLOOD; + StatusIconChangeTable[SC_MINOR_BBQ] = SI_MINOR_BBQ; + StatusIconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA; + StatusIconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED; + StatusIconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES; + + StatusIconChangeTable[SC_BOOST500] |= SI_BOOST500; + StatusIconChangeTable[SC_FULL_SWING_K] |= SI_FULL_SWING_K; + StatusIconChangeTable[SC_MANA_PLUS] |= SI_MANA_PLUS; + StatusIconChangeTable[SC_MUSTLE_M] |= SI_MUSTLE_M; + StatusIconChangeTable[SC_LIFE_FORCE_F] |= SI_LIFE_FORCE_F; + StatusIconChangeTable[SC_EXTRACT_WHITE_POTION_Z] |= SI_EXTRACT_WHITE_POTION_Z; + StatusIconChangeTable[SC_VITATA_500] |= SI_VITATA_500; + StatusIconChangeTable[SC_EXTRACT_SALAMINE_JUICE] |= SI_EXTRACT_SALAMINE_JUICE; + + // Elemental Spirit's 'side' status change icons. + StatusIconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE; + StatusIconChangeTable[SC_FIRE_CLOAK] = SI_FIRE_CLOAK; + StatusIconChangeTable[SC_WATER_SCREEN] = SI_WATER_SCREEN; + StatusIconChangeTable[SC_WATER_DROP] = SI_WATER_DROP; + StatusIconChangeTable[SC_WIND_STEP] = SI_WIND_STEP; + StatusIconChangeTable[SC_WIND_CURTAIN] = SI_WIND_CURTAIN; + StatusIconChangeTable[SC_SOLID_SKIN] = SI_SOLID_SKIN; + StatusIconChangeTable[SC_STONE_SHIELD] = SI_STONE_SHIELD; + StatusIconChangeTable[SC_PYROTECHNIC] = SI_PYROTECHNIC; + StatusIconChangeTable[SC_HEATER] = SI_HEATER; + StatusIconChangeTable[SC_TROPIC] = SI_TROPIC; + StatusIconChangeTable[SC_AQUAPLAY] = SI_AQUAPLAY; + StatusIconChangeTable[SC_COOLER] = SI_COOLER; + StatusIconChangeTable[SC_CHILLY_AIR] = SI_CHILLY_AIR; + StatusIconChangeTable[SC_GUST] = SI_GUST; + StatusIconChangeTable[SC_BLAST] = SI_BLAST; + StatusIconChangeTable[SC_WILD_STORM] = SI_WILD_STORM; + StatusIconChangeTable[SC_PETROLOGY] = SI_PETROLOGY; + StatusIconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL; + StatusIconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL; + StatusIconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART; + + //Other SC which are not necessarily associated to skills. + StatusChangeFlagTable[SC_ASPDPOTION0] = SCB_ASPD; + StatusChangeFlagTable[SC_ASPDPOTION1] = SCB_ASPD; + StatusChangeFlagTable[SC_ASPDPOTION2] = SCB_ASPD; + StatusChangeFlagTable[SC_ASPDPOTION3] = SCB_ASPD; + StatusChangeFlagTable[SC_SPEEDUP0] = SCB_SPEED; + StatusChangeFlagTable[SC_SPEEDUP1] = SCB_SPEED; + StatusChangeFlagTable[SC_ATKPOTION] = SCB_BATK; + StatusChangeFlagTable[SC_MATKPOTION] = SCB_MATK; + StatusChangeFlagTable[SC_INCALLSTATUS] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK; + StatusChangeFlagTable[SC_INCSTR] |= SCB_STR; + StatusChangeFlagTable[SC_INCAGI] |= SCB_AGI; + StatusChangeFlagTable[SC_INCVIT] |= SCB_VIT; + StatusChangeFlagTable[SC_INCINT] |= SCB_INT; + StatusChangeFlagTable[SC_INCDEX] |= SCB_DEX; + StatusChangeFlagTable[SC_INCLUK] |= SCB_LUK; + StatusChangeFlagTable[SC_INCHIT] |= SCB_HIT; + StatusChangeFlagTable[SC_INCHITRATE] |= SCB_HIT; + StatusChangeFlagTable[SC_INCFLEE] |= SCB_FLEE; + StatusChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE; + StatusChangeFlagTable[SC_INCCRI] |= SCB_CRI; + StatusChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD; + StatusChangeFlagTable[SC_INCFLEE2] |= SCB_FLEE2; + StatusChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP; + StatusChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP; + StatusChangeFlagTable[SC_INCMHP] |= SCB_MAXHP; + StatusChangeFlagTable[SC_INCMSP] |= SCB_MAXSP; + StatusChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK; + StatusChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK; + StatusChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF; + StatusChangeFlagTable[SC_STRFOOD] |= SCB_STR; + StatusChangeFlagTable[SC_AGIFOOD] |= SCB_AGI; + StatusChangeFlagTable[SC_VITFOOD] |= SCB_VIT; + StatusChangeFlagTable[SC_INTFOOD] |= SCB_INT; + StatusChangeFlagTable[SC_DEXFOOD] |= SCB_DEX; + StatusChangeFlagTable[SC_LUKFOOD] |= SCB_LUK; + StatusChangeFlagTable[SC_HITFOOD] |= SCB_HIT; + StatusChangeFlagTable[SC_FLEEFOOD] |= SCB_FLEE; + StatusChangeFlagTable[SC_BATKFOOD] |= SCB_BATK; + StatusChangeFlagTable[SC_WATKFOOD] |= SCB_WATK; + StatusChangeFlagTable[SC_MATKFOOD] |= SCB_MATK; + StatusChangeFlagTable[SC_ARMOR_ELEMENT] |= SCB_ALL; + StatusChangeFlagTable[SC_ARMOR_RESIST] |= SCB_ALL; + StatusChangeFlagTable[SC_SPCOST_RATE] |= SCB_ALL; + StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; + StatusChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL; + // Cash Items + StatusChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR; + StatusChangeFlagTable[SC_FOOD_AGI_CASH] = SCB_AGI; + StatusChangeFlagTable[SC_FOOD_VIT_CASH] = SCB_VIT; + StatusChangeFlagTable[SC_FOOD_DEX_CASH] = SCB_DEX; + StatusChangeFlagTable[SC_FOOD_INT_CASH] = SCB_INT; + StatusChangeFlagTable[SC_FOOD_LUK_CASH] = SCB_LUK; + // Mercenary Bonus Effects + StatusChangeFlagTable[SC_MERC_FLEEUP] |= SCB_FLEE; + StatusChangeFlagTable[SC_MERC_ATKUP] |= SCB_WATK; + StatusChangeFlagTable[SC_MERC_HPUP] |= SCB_MAXHP; + StatusChangeFlagTable[SC_MERC_SPUP] |= SCB_MAXSP; + StatusChangeFlagTable[SC_MERC_HITUP] |= SCB_HIT; + // Guillotine Cross Poison Effects + StatusChangeFlagTable[SC_PARALYSE] |= SCB_ASPD|SCB_FLEE|SCB_SPEED; + StatusChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN; + StatusChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP; + StatusChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN; + + StatusChangeFlagTable[SC_SAVAGE_STEAK] |= SCB_STR; + StatusChangeFlagTable[SC_COCKTAIL_WARG_BLOOD] |= SCB_INT; + StatusChangeFlagTable[SC_MINOR_BBQ] |= SCB_VIT; + StatusChangeFlagTable[SC_SIROMA_ICE_TEA] |= SCB_DEX; + StatusChangeFlagTable[SC_DROCERA_HERB_STEAMED] |= SCB_AGI; + StatusChangeFlagTable[SC_PUTTI_TAILS_NOODLES] |= SCB_LUK; + StatusChangeFlagTable[SC_BOOST500] |= SCB_ASPD; + StatusChangeFlagTable[SC_FULL_SWING_K] |= SCB_BATK; + StatusChangeFlagTable[SC_MANA_PLUS] |= SCB_MATK; + StatusChangeFlagTable[SC_MUSTLE_M] |= SCB_MAXHP; + StatusChangeFlagTable[SC_LIFE_FORCE_F] |= SCB_MAXSP; + StatusChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN; + StatusChangeFlagTable[SC_VITATA_500] |= SCB_REGEN; + StatusChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD; #ifdef RENEWAL_EDP - // renewal EDP increases your weapon atk - StatusChangeFlagTable[SC_EDP] |= SCB_WATK; + // renewal EDP increases your weapon atk + StatusChangeFlagTable[SC_EDP] |= SCB_WATK; #endif - if (!battle_config.display_hallucination) //Disable Hallucination. - StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK; - - /* StatusChangeState (SCS_) NOMOVE */ - StatusChangeStateTable[SC_ANKLE] |= SCS_NOMOVE; - StatusChangeStateTable[SC_AUTOCOUNTER] |= SCS_NOMOVE; - StatusChangeStateTable[SC_TRICKDEAD] |= SCS_NOMOVE; - StatusChangeStateTable[SC_BLADESTOP] |= SCS_NOMOVE; - StatusChangeStateTable[SC_BLADESTOP_WAIT] |= SCS_NOMOVE; - StatusChangeStateTable[SC_GOSPEL] |= SCS_NOMOVE|SCS_NOMOVECOND; - StatusChangeStateTable[SC_BASILICA] |= SCS_NOMOVE|SCS_NOMOVECOND; - StatusChangeStateTable[SC_STOP] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CLOSECONFINE] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CLOSECONFINE2] |= SCS_NOMOVE; - StatusChangeStateTable[SC_MADNESSCANCEL] |= SCS_NOMOVE; - StatusChangeStateTable[SC_GRAVITATION] |= SCS_NOMOVE|SCS_NOMOVECOND; - StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOMOVE; - StatusChangeStateTable[SC_ELECTRICSHOCKER] |= SCS_NOMOVE; - StatusChangeStateTable[SC_BITE] |= SCS_NOMOVE; - StatusChangeStateTable[SC_THORNSTRAP] |= SCS_NOMOVE; - StatusChangeStateTable[SC_MAGNETICFIELD] |= SCS_NOMOVE; - StatusChangeStateTable[SC__MANHOLE] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CURSEDCIRCLE_ATKER] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOMOVE|SCS_NOMOVECOND; - StatusChangeStateTable[SC_NETHERWORLD] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CAMOUFLAGE] |= SCS_NOMOVE|SCS_NOMOVECOND; - StatusChangeStateTable[SC_MEIKYOUSISUI] |= SCS_NOMOVE; - StatusChangeStateTable[SC_KAGEHUMI] |= SCS_NOMOVE; - StatusChangeStateTable[SC_KYOUGAKU] |= SCS_NOMOVE; - - /* StatusChangeState (SCS_) NOPICKUPITEMS */ - StatusChangeStateTable[SC_HIDING] |= SCS_NOPICKITEM; - StatusChangeStateTable[SC_CLOAKING] |= SCS_NOPICKITEM; - StatusChangeStateTable[SC_TRICKDEAD] |= SCS_NOPICKITEM; - StatusChangeStateTable[SC_BLADESTOP] |= SCS_NOPICKITEM; - StatusChangeStateTable[SC_CLOAKINGEXCEED] |= SCS_NOPICKITEM; - StatusChangeStateTable[SC_NOCHAT] |= SCS_NOPICKITEM|SCS_NOPICKITEMCOND; - - /* StatusChangeState (SCS_) NODROPITEMS */ - StatusChangeStateTable[SC_AUTOCOUNTER] |= SCS_NODROPITEM; - StatusChangeStateTable[SC_BLADESTOP] |= SCS_NODROPITEM; - StatusChangeStateTable[SC_NOCHAT] |= SCS_NODROPITEM|SCS_NODROPITEMCOND; - - /* StatusChangeState (SCS_) NOCAST (skills) */ - StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST; - StatusChangeStateTable[SC_STEELBODY] |= SCS_NOCAST; - StatusChangeStateTable[SC_BERSERK] |= SCS_NOCAST; - StatusChangeStateTable[SC__BLOODYLUST] |= SCS_NOCAST; - StatusChangeStateTable[SC_OBLIVIONCURSE] |= SCS_NOCAST; - StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOCAST; - StatusChangeStateTable[SC__INVISIBILITY] |= SCS_NOCAST; - StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOCAST|SCS_NOCASTCOND; - StatusChangeStateTable[SC__IGNORANCE] |= SCS_NOCAST; - StatusChangeStateTable[SC_DEEPSLEEP] |= SCS_NOCAST; - StatusChangeStateTable[SC_SATURDAYNIGHTFEVER] |= SCS_NOCAST; - StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOCAST; - StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST; - - //Homon S - StatusChangeStateTable[SC_PARALYSIS] |= SCS_NOMOVE; + if( !battle_config.display_hallucination ) //Disable Hallucination. + StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK; + + /* StatusChangeState (SCS_) NOMOVE */ + StatusChangeStateTable[SC_ANKLE] |= SCS_NOMOVE; + StatusChangeStateTable[SC_AUTOCOUNTER] |= SCS_NOMOVE; + StatusChangeStateTable[SC_TRICKDEAD] |= SCS_NOMOVE; + StatusChangeStateTable[SC_BLADESTOP] |= SCS_NOMOVE; + StatusChangeStateTable[SC_BLADESTOP_WAIT] |= SCS_NOMOVE; + StatusChangeStateTable[SC_GOSPEL] |= SCS_NOMOVE|SCS_NOMOVECOND; + StatusChangeStateTable[SC_BASILICA] |= SCS_NOMOVE|SCS_NOMOVECOND; + StatusChangeStateTable[SC_STOP] |= SCS_NOMOVE; + StatusChangeStateTable[SC_CLOSECONFINE] |= SCS_NOMOVE; + StatusChangeStateTable[SC_CLOSECONFINE2] |= SCS_NOMOVE; + StatusChangeStateTable[SC_MADNESSCANCEL] |= SCS_NOMOVE; + StatusChangeStateTable[SC_GRAVITATION] |= SCS_NOMOVE|SCS_NOMOVECOND; + StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOMOVE; + StatusChangeStateTable[SC_ELECTRICSHOCKER] |= SCS_NOMOVE; + StatusChangeStateTable[SC_BITE] |= SCS_NOMOVE; + StatusChangeStateTable[SC_THORNSTRAP] |= SCS_NOMOVE; + StatusChangeStateTable[SC_MAGNETICFIELD] |= SCS_NOMOVE; + StatusChangeStateTable[SC__MANHOLE] |= SCS_NOMOVE; + StatusChangeStateTable[SC_CURSEDCIRCLE_ATKER] |= SCS_NOMOVE; + StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOMOVE; + StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOMOVE|SCS_NOMOVECOND; + StatusChangeStateTable[SC_NETHERWORLD] |= SCS_NOMOVE; + StatusChangeStateTable[SC_CAMOUFLAGE] |= SCS_NOMOVE|SCS_NOMOVECOND; + StatusChangeStateTable[SC_MEIKYOUSISUI] |= SCS_NOMOVE; + StatusChangeStateTable[SC_KAGEHUMI] |= SCS_NOMOVE; + StatusChangeStateTable[SC_KYOUGAKU] |= SCS_NOMOVE; + + /* StatusChangeState (SCS_) NOPICKUPITEMS */ + StatusChangeStateTable[SC_HIDING] |= SCS_NOPICKITEM; + StatusChangeStateTable[SC_CLOAKING] |= SCS_NOPICKITEM; + StatusChangeStateTable[SC_TRICKDEAD] |= SCS_NOPICKITEM; + StatusChangeStateTable[SC_BLADESTOP] |= SCS_NOPICKITEM; + StatusChangeStateTable[SC_CLOAKINGEXCEED] |= SCS_NOPICKITEM; + StatusChangeStateTable[SC_NOCHAT] |= SCS_NOPICKITEM|SCS_NOPICKITEMCOND; + + /* StatusChangeState (SCS_) NODROPITEMS */ + StatusChangeStateTable[SC_AUTOCOUNTER] |= SCS_NODROPITEM; + StatusChangeStateTable[SC_BLADESTOP] |= SCS_NODROPITEM; + StatusChangeStateTable[SC_NOCHAT] |= SCS_NODROPITEM|SCS_NODROPITEMCOND; + + /* StatusChangeState (SCS_) NOCAST (skills) */ + StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST; + StatusChangeStateTable[SC_STEELBODY] |= SCS_NOCAST; + StatusChangeStateTable[SC_BERSERK] |= SCS_NOCAST; + StatusChangeStateTable[SC__BLOODYLUST] |= SCS_NOCAST; + StatusChangeStateTable[SC_OBLIVIONCURSE] |= SCS_NOCAST; + StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOCAST; + StatusChangeStateTable[SC__INVISIBILITY] |= SCS_NOCAST; + StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOCAST|SCS_NOCASTCOND; + StatusChangeStateTable[SC__IGNORANCE] |= SCS_NOCAST; + StatusChangeStateTable[SC_DEEPSLEEP] |= SCS_NOCAST; + StatusChangeStateTable[SC_SATURDAYNIGHTFEVER] |= SCS_NOCAST; + StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOCAST; + StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST; + + //Homon S + StatusChangeStateTable[SC_PARALYSIS] |= SCS_NOMOVE; } static void initDummyData(void) { - memset(&dummy_status, 0, sizeof(dummy_status)); - dummy_status.hp = - dummy_status.max_hp = - dummy_status.max_sp = - dummy_status.str = - dummy_status.agi = - dummy_status.vit = - dummy_status.int_ = - dummy_status.dex = - dummy_status.luk = - dummy_status.hit = 1; - dummy_status.speed = 2000; - dummy_status.adelay = 4000; - dummy_status.amotion = 2000; - dummy_status.dmotion = 2000; - dummy_status.ele_lv = 1; //Min elemental level. - dummy_status.mode = MD_CANMOVE; + memset(&dummy_status, 0, sizeof(dummy_status)); + dummy_status.hp = + dummy_status.max_hp = + dummy_status.max_sp = + dummy_status.str = + dummy_status.agi = + dummy_status.vit = + dummy_status.int_ = + dummy_status.dex = + dummy_status.luk = + dummy_status.hit = 1; + dummy_status.speed = 2000; + dummy_status.adelay = 4000; + dummy_status.amotion = 2000; + dummy_status.dmotion = 2000; + dummy_status.ele_lv = 1; //Min elemental level. + dummy_status.mode = MD_CANMOVE; } //For copying a status_data structure from b to a, without overwriting current Hp and Sp -static inline void status_cpy(struct status_data *a, const struct status_data *b) +static inline void status_cpy(struct status_data* a, const struct status_data* b) { - memcpy((void *)&a->max_hp, (const void *)&b->max_hp, sizeof(struct status_data)-(sizeof(a->hp)+sizeof(a->sp))); + memcpy((void*)&a->max_hp, (const void*)&b->max_hp, sizeof(struct status_data)-(sizeof(a->hp)+sizeof(a->sp))); } //Sets HP to given value. Flag is the flag passed to status_heal in case @@ -1085,17 +1085,17 @@ static inline void status_cpy(struct status_data *a, const struct status_data *b //on players) It will always succeed (overrides Berserk block), but it can't kill. int status_set_hp(struct block_list *bl, unsigned int hp, int flag) { - struct status_data *status; - if (hp < 1) return 0; - status = status_get_status_data(bl); - if (status == &dummy_status) - return 0; - - if (hp > status->max_hp) hp = status->max_hp; - if (hp == status->hp) return 0; - if (hp > status->hp) - return status_heal(bl, hp - status->hp, 0, 1|flag); - return status_zap(bl, status->hp - hp, 0); + struct status_data *status; + if (hp < 1) return 0; + status = status_get_status_data(bl); + if (status == &dummy_status) + return 0; + + if (hp > status->max_hp) hp = status->max_hp; + if (hp == status->hp) return 0; + if (hp > status->hp) + return status_heal(bl, hp - status->hp, 0, 1|flag); + return status_zap(bl, status->hp - hp, 0); } //Sets SP to given value. Flag is the flag passed to status_heal in case @@ -1103,24 +1103,24 @@ int status_set_hp(struct block_list *bl, unsigned int hp, int flag) //on players) int status_set_sp(struct block_list *bl, unsigned int sp, int flag) { - struct status_data *status; + struct status_data *status; - status = status_get_status_data(bl); - if (status == &dummy_status) - return 0; + status = status_get_status_data(bl); + if (status == &dummy_status) + return 0; - if (sp > status->max_sp) sp = status->max_sp; - if (sp == status->sp) return 0; - if (sp > status->sp) - return status_heal(bl, 0, sp - status->sp, 1|flag); - return status_zap(bl, 0, status->sp - sp); + if (sp > status->max_sp) sp = status->max_sp; + if (sp == status->sp) return 0; + if (sp > status->sp) + return status_heal(bl, 0, sp - status->sp, 1|flag); + return status_zap(bl, 0, status->sp - sp); } -int status_charge(struct block_list *bl, int hp, int sp) +int status_charge(struct block_list* bl, int hp, int sp) { - if (!(bl->type&BL_CONSUME)) - return hp+sp; //Assume all was charged so there are no 'not enough' fails. - return status_damage(NULL, bl, hp, sp, 0, 3); + if(!(bl->type&BL_CONSUME)) + return hp+sp; //Assume all was charged so there are no 'not enough' fails. + return status_damage(NULL, bl, hp, sp, 0, 3); } //Inflicts damage on the target with the according walkdelay. @@ -1130,321 +1130,292 @@ int status_charge(struct block_list *bl, int hp, int sp) //flag will be set to &8 when damaging sp of a dead character int status_damage(struct block_list *src,struct block_list *target,int hp, int sp, int walkdelay, int flag) { - struct status_data *status; - struct status_change *sc; - - if (sp && !(target->type&BL_CONSUME)) - sp = 0; //Not a valid SP target. - - if (hp < 0) { //Assume absorbed damage. - status_heal(target, -hp, 0, 1); - hp = 0; - } - - if (sp < 0) { - status_heal(target, 0, -sp, 1); - sp = 0; - } - - if (target->type == BL_SKILL) - return skill_unit_ondamaged((struct skill_unit *)target, src, hp, gettick()); - - status = status_get_status_data(target); - if (status == &dummy_status) - return 0; - - if ((unsigned int)hp >= status->hp) { - if (flag&2) return 0; - hp = status->hp; - } - - if ((unsigned int)sp > status->sp) { - if (flag&2) return 0; - sp = status->sp; - } - - if (!hp && !sp) - return 0; - - if (!status->hp) - flag |= 8; - - // Let through. battle.c/skill.c have the whole logic of when it's possible or - // not to hurt someone (and this check breaks pet catching) [Skotlex] - // if (!target->prev && !(flag&2)) - // return 0; //Cannot damage a bl not on a map, except when "charging" hp/sp - - sc = status_get_sc(target); - if (hp && battle_config.invincible_nodamage && src && sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF]) - hp = 1; - - if (hp && !(flag&1)) { - if (sc) { - struct status_change_entry *sce; - if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) - status_change_end(target, SC_STONE, INVALID_TIMER); - status_change_end(target, SC_FREEZE, INVALID_TIMER); - status_change_end(target, SC_SLEEP, INVALID_TIMER); - status_change_end(target, SC_WINKCHARM, INVALID_TIMER); - status_change_end(target, SC_CONFUSION, INVALID_TIMER); - status_change_end(target, SC_TRICKDEAD, INVALID_TIMER); - status_change_end(target, SC_HIDING, INVALID_TIMER); - status_change_end(target, SC_CLOAKING, INVALID_TIMER); - status_change_end(target, SC_CHASEWALK, INVALID_TIMER); - status_change_end(target, SC_CAMOUFLAGE, INVALID_TIMER); - status_change_end(target, SC__INVISIBILITY, INVALID_TIMER); - status_change_end(target, SC_DEEPSLEEP, INVALID_TIMER); - if ((sce=sc->data[SC_ENDURE]) && !sce->val4) { - //Endure count is only reduced by non-players on non-gvg maps. - //val4 signals infinite endure. [Skotlex] - if (src && src->type != BL_PC && !map_flag_gvg(target->m) && !map[target->m].flag.battleground && --(sce->val2) < 0) - status_change_end(target, SC_ENDURE, INVALID_TIMER); - } - if ((sce=sc->data[SC_GRAVITATION]) && sce->val3 == BCT_SELF) { - struct skill_unit_group *sg = skill_id2group(sce->val4); - if (sg) { - skill_delunitgroup(sg); - sce->val4 = 0; - status_change_end(target, SC_GRAVITATION, INVALID_TIMER); - } - } - if (sc->data[SC_DANCING] && (unsigned int)hp > status->max_hp>>2) - status_change_end(target, SC_DANCING, INVALID_TIMER); - if (sc->data[SC_CLOAKINGEXCEED] && --(sc->data[SC_CLOAKINGEXCEED]->val2) <= 0) - status_change_end(target, SC_CLOAKINGEXCEED, INVALID_TIMER); - if (sc->data[SC_KAGEMUSYA] && --(sc->data[SC_KAGEMUSYA]->val3) <= 0) - status_change_end(target, SC_KAGEMUSYA, INVALID_TIMER); - } - unit_skillcastcancel(target, 2); - } - - status->hp-= hp; - status->sp-= sp; - - if (sc && hp && status->hp) { - if (sc->data[SC_AUTOBERSERK] && - (!sc->data[SC_PROVOKE] || !sc->data[SC_PROVOKE]->val2) && - status->hp < status->max_hp>>2) - sc_start4(target,SC_PROVOKE,100,10,1,0,0,0); - if (sc->data[SC_BERSERK] && status->hp <= 100) - status_change_end(target, SC_BERSERK, INVALID_TIMER); - if (sc->data[SC_RAISINGDRAGON] && status->hp <= 1000) - status_change_end(target, SC_RAISINGDRAGON, INVALID_TIMER); - if (sc->data[SC_SATURDAYNIGHTFEVER] && status->hp <= 100) - status_change_end(target, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); - if (sc->data[SC__BLOODYLUST] && status->hp <= 100) - status_change_end(target, SC__BLOODYLUST, INVALID_TIMER); - } - - switch (target->type) { - case BL_PC: - pc_damage((TBL_PC *)target,src,hp,sp); - break; - case BL_MOB: - mob_damage((TBL_MOB *)target, src, hp); - break; - case BL_HOM: - merc_damage((TBL_HOM *)target); - break; - case BL_MER: - mercenary_heal((TBL_MER *)target,hp,sp); - break; - case BL_ELEM: - elemental_heal((TBL_ELEM *)target,hp,sp); - break; - } - - if (src && target->type == BL_PC && ((TBL_PC *)target)->disguise) {// stop walking when attacked in disguise to prevent walk-delay bug - unit_stop_walking(target, 1); - } - - if (status->hp || (flag&8)) { - //Still lives or has been dead before this damage. - if (walkdelay) - unit_set_walkdelay(target, gettick(), walkdelay, 0); - return hp+sp; - } - - status->hp = 1; //To let the dead function cast skills and all that. - //NOTE: These dead functions should return: [Skotlex] - //0: Death cancelled, auto-revived. - //Non-zero: Standard death. Clear status, cancel move/attack, etc - //&2: Also remove object from map. - //&4: Also delete object from memory. - switch (target->type) { - case BL_PC: - flag = pc_dead((TBL_PC *)target,src); - break; - case BL_MOB: - flag = mob_dead((TBL_MOB *)target, src, flag&4?3:0); - break; - case BL_HOM: - flag = merc_hom_dead((TBL_HOM *)target); - break; - case BL_MER: - flag = mercenary_dead((TBL_MER *)target); - break; - case BL_ELEM: - flag = elemental_dead((TBL_ELEM *)target); - break; - default: //Unhandled case, do nothing to object. - flag = 0; - break; - } - - if (!flag) //Death cancelled. - return hp+sp; - - //Normal death - status->hp = 0; - if (battle_config.clear_unit_ondeath && - battle_config.clear_unit_ondeath&target->type) - skill_clear_unitgroup(target); - - if (target->type&BL_REGEN) { - //Reset regen ticks. - struct regen_data *regen = status_get_regen_data(target); - if (regen) { - memset(®en->tick, 0, sizeof(regen->tick)); - if (regen->sregen) - memset(®en->sregen->tick, 0, sizeof(regen->sregen->tick)); - if (regen->ssregen) - memset(®en->ssregen->tick, 0, sizeof(regen->ssregen->tick)); - } - } - - if (sc && sc->data[SC_KAIZEL] && !map_flag_gvg(target->m)) { - //flag&8 = disable Kaizel - int time = skill_get_time2(SL_KAIZEL,sc->data[SC_KAIZEL]->val1); - //Look for Osiris Card's bonus effect on the character and revive 100% or revive normally - if (target->type == BL_PC && BL_CAST(BL_PC,target)->special_state.restart_full_recover) - status_revive(target, 100, 100); - else - status_revive(target, sc->data[SC_KAIZEL]->val2, 0); - status_change_clear(target,0); - clif_skill_nodamage(target,target,ALL_RESURRECTION,1,1); - sc_start(target,status_skill2sc(PR_KYRIE),100,10,time); - - if (target->type == BL_MOB) - ((TBL_MOB *)target)->state.rebirth = 1; - - return hp+sp; - } - if (target->type == BL_PC) { + struct status_data *status; + struct status_change *sc; + + if(sp && !(target->type&BL_CONSUME)) + sp = 0; //Not a valid SP target. + + if (hp < 0) { //Assume absorbed damage. + status_heal(target, -hp, 0, 1); + hp = 0; + } + + if (sp < 0) { + status_heal(target, 0, -sp, 1); + sp = 0; + } + + if (target->type == BL_SKILL) + return skill_unit_ondamaged((struct skill_unit *)target, src, hp, gettick()); + + status = status_get_status_data(target); + if( status == &dummy_status ) + return 0; + + if ((unsigned int)hp >= status->hp) { + if (flag&2) return 0; + hp = status->hp; + } + + if ((unsigned int)sp > status->sp) { + if (flag&2) return 0; + sp = status->sp; + } + + if (!hp && !sp) + return 0; + + if( !status->hp ) + flag |= 8; + +// Let through. battle.c/skill.c have the whole logic of when it's possible or +// not to hurt someone (and this check breaks pet catching) [Skotlex] +// if (!target->prev && !(flag&2)) +// return 0; //Cannot damage a bl not on a map, except when "charging" hp/sp + + sc = status_get_sc(target); + if( hp && battle_config.invincible_nodamage && src && sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) + hp = 1; + + if( hp && !(flag&1) ) { + if( sc ) { + struct status_change_entry *sce; + if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) + status_change_end(target, SC_STONE, INVALID_TIMER); + status_change_end(target, SC_FREEZE, INVALID_TIMER); + status_change_end(target, SC_SLEEP, INVALID_TIMER); + status_change_end(target, SC_WINKCHARM, INVALID_TIMER); + status_change_end(target, SC_CONFUSION, INVALID_TIMER); + status_change_end(target, SC_TRICKDEAD, INVALID_TIMER); + status_change_end(target, SC_HIDING, INVALID_TIMER); + status_change_end(target, SC_CLOAKING, INVALID_TIMER); + status_change_end(target, SC_CHASEWALK, INVALID_TIMER); + status_change_end(target, SC_CAMOUFLAGE, INVALID_TIMER); + status_change_end(target, SC__INVISIBILITY, INVALID_TIMER); + status_change_end(target, SC_DEEPSLEEP, INVALID_TIMER); + if ((sce=sc->data[SC_ENDURE]) && !sce->val4) { + //Endure count is only reduced by non-players on non-gvg maps. + //val4 signals infinite endure. [Skotlex] + if (src && src->type != BL_PC && !map_flag_gvg(target->m) && !map[target->m].flag.battleground && --(sce->val2) < 0) + status_change_end(target, SC_ENDURE, INVALID_TIMER); + } + if ((sce=sc->data[SC_GRAVITATION]) && sce->val3 == BCT_SELF) { + struct skill_unit_group* sg = skill_id2group(sce->val4); + if (sg) { + skill_delunitgroup(sg); + sce->val4 = 0; + status_change_end(target, SC_GRAVITATION, INVALID_TIMER); + } + } + if(sc->data[SC_DANCING] && (unsigned int)hp > status->max_hp>>2) + status_change_end(target, SC_DANCING, INVALID_TIMER); + if(sc->data[SC_CLOAKINGEXCEED] && --(sc->data[SC_CLOAKINGEXCEED]->val2) <= 0) + status_change_end(target, SC_CLOAKINGEXCEED, INVALID_TIMER); + if(sc->data[SC_KAGEMUSYA] && --(sc->data[SC_KAGEMUSYA]->val3) <= 0) + status_change_end(target, SC_KAGEMUSYA, INVALID_TIMER); + } + unit_skillcastcancel(target, 2); + } + + status->hp-= hp; + status->sp-= sp; + + if (sc && hp && status->hp) { + if (sc->data[SC_AUTOBERSERK] && + (!sc->data[SC_PROVOKE] || !sc->data[SC_PROVOKE]->val2) && + status->hp < status->max_hp>>2) + sc_start4(target,SC_PROVOKE,100,10,1,0,0,0); + if (sc->data[SC_BERSERK] && status->hp <= 100) + status_change_end(target, SC_BERSERK, INVALID_TIMER); + if( sc->data[SC_RAISINGDRAGON] && status->hp <= 1000 ) + status_change_end(target, SC_RAISINGDRAGON, INVALID_TIMER); + if (sc->data[SC_SATURDAYNIGHTFEVER] && status->hp <= 100) + status_change_end(target, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); + if (sc->data[SC__BLOODYLUST] && status->hp <= 100) + status_change_end(target, SC__BLOODYLUST, INVALID_TIMER); + } + + switch (target->type) { + case BL_PC: pc_damage((TBL_PC*)target,src,hp,sp); break; + case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); break; + case BL_HOM: merc_damage((TBL_HOM*)target); break; + case BL_MER: mercenary_heal((TBL_MER*)target,hp,sp); break; + case BL_ELEM: elemental_heal((TBL_ELEM*)target,hp,sp); break; + } + + if( src && target->type == BL_PC && ((TBL_PC*)target)->disguise ) {// stop walking when attacked in disguise to prevent walk-delay bug + unit_stop_walking( target, 1 ); + } + + if( status->hp || (flag&8) ) + { //Still lives or has been dead before this damage. + if (walkdelay) + unit_set_walkdelay(target, gettick(), walkdelay, 0); + return hp+sp; + } + + status->hp = 1; //To let the dead function cast skills and all that. + //NOTE: These dead functions should return: [Skotlex] + //0: Death cancelled, auto-revived. + //Non-zero: Standard death. Clear status, cancel move/attack, etc + //&2: Also remove object from map. + //&4: Also delete object from memory. + switch (target->type) { + case BL_PC: flag = pc_dead((TBL_PC*)target,src); break; + case BL_MOB: flag = mob_dead((TBL_MOB*)target, src, flag&4?3:0); break; + case BL_HOM: flag = merc_hom_dead((TBL_HOM*)target); break; + case BL_MER: flag = mercenary_dead((TBL_MER*)target); break; + case BL_ELEM: flag = elemental_dead((TBL_ELEM*)target); break; + default: //Unhandled case, do nothing to object. + flag = 0; + break; + } + + if(!flag) //Death cancelled. + return hp+sp; + + //Normal death + status->hp = 0; + if (battle_config.clear_unit_ondeath && + battle_config.clear_unit_ondeath&target->type) + skill_clear_unitgroup(target); + + if(target->type&BL_REGEN) + { //Reset regen ticks. + struct regen_data *regen = status_get_regen_data(target); + if (regen) { + memset(®en->tick, 0, sizeof(regen->tick)); + if (regen->sregen) + memset(®en->sregen->tick, 0, sizeof(regen->sregen->tick)); + if (regen->ssregen) + memset(®en->ssregen->tick, 0, sizeof(regen->ssregen->tick)); + } + } + + if( sc && sc->data[SC_KAIZEL] && !map_flag_gvg(target->m) ) + { //flag&8 = disable Kaizel + int time = skill_get_time2(SL_KAIZEL,sc->data[SC_KAIZEL]->val1); + //Look for Osiris Card's bonus effect on the character and revive 100% or revive normally + if ( target->type == BL_PC && BL_CAST(BL_PC,target)->special_state.restart_full_recover ) + status_revive(target, 100, 100); + else + status_revive(target, sc->data[SC_KAIZEL]->val2, 0); + status_change_clear(target,0); + clif_skill_nodamage(target,target,ALL_RESURRECTION,1,1); + sc_start(target,status_skill2sc(PR_KYRIE),100,10,time); + + if( target->type == BL_MOB ) + ((TBL_MOB*)target)->state.rebirth = 1; + + return hp+sp; + } + if(target->type == BL_PC){ TBL_PC *sd = BL_CAST(BL_PC,target); TBL_HOM *hd = sd->hd; - if (hd && hd->sc.data[SC_LIGHT_OF_REGENE]) { + if(hd && hd->sc.data[SC_LIGHT_OF_REGENE]){ clif_skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill_get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage clif_skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status_revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0)); status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER); return hp + sp; } } - if (target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB *) target)->state.rebirth) { // Ensure the monster has not already rebirthed before doing so. + if (target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*) target)->state.rebirth) {// Ensure the monster has not already rebirthed before doing so. status_revive(target, sc->data[SC_REBIRTH]->val2, 0); - status_change_clear(target,0); - ((TBL_MOB *)target)->state.rebirth = 1; - - return hp+sp; - } - - status_change_clear(target,0); - - if (flag&4) //Delete from memory. (also invokes map removal code) - unit_free(target,CLR_DEAD); - else if (flag&2) //remove from map - unit_remove_map(target,CLR_DEAD); - else { - //Some death states that would normally be handled by unit_remove_map - unit_stop_attack(target); - unit_stop_walking(target,1); - unit_skillcastcancel(target,0); - clif_clearunit_area(target,CLR_DEAD); - skill_unit_move(target,gettick(),4); - skill_cleartimerskill(target); - } - - return hp+sp; + status_change_clear(target,0); + ((TBL_MOB*)target)->state.rebirth = 1; + + return hp+sp; + } + + status_change_clear(target,0); + + if(flag&4) //Delete from memory. (also invokes map removal code) + unit_free(target,CLR_DEAD); + else + if(flag&2) //remove from map + unit_remove_map(target,CLR_DEAD); + else + { //Some death states that would normally be handled by unit_remove_map + unit_stop_attack(target); + unit_stop_walking(target,1); + unit_skillcastcancel(target,0); + clif_clearunit_area(target,CLR_DEAD); + skill_unit_move(target,gettick(),4); + skill_cleartimerskill(target); + } + + return hp+sp; } //Heals a character. If flag&1, this is forced healing (otherwise stuff like Berserk can block it) //If flag&2, when the player is healed, show the HP/SP heal effect. int status_heal(struct block_list *bl,int hp,int sp, int flag) { - struct status_data *status; - struct status_change *sc; - - status = status_get_status_data(bl); - - if (status == &dummy_status || !status->hp) - return 0; - - sc = status_get_sc(bl); - if (sc && !sc->count) - sc = NULL; - - if (hp < 0) { - if (hp == INT_MIN) hp++; //-INT_MIN == INT_MIN in some architectures! - status_damage(NULL, bl, -hp, 0, 0, 1); - hp = 0; - } - - if (hp) { - if (sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])) { - if (flag&1) - flag &= ~2; - else - hp = 0; - } - - if ((unsigned int)hp > status->max_hp - status->hp) - hp = status->max_hp - status->hp; - } - - if (sp < 0) { - if (sp==INT_MIN) sp++; - status_damage(NULL, bl, 0, -sp, 0, 1); - sp = 0; - } - - if (sp) { - if ((unsigned int)sp > status->max_sp - status->sp) - sp = status->max_sp - status->sp; - } - - if (!sp && !hp) return 0; - - status->hp+= hp; - status->sp+= sp; - - if (hp && sc && - sc->data[SC_AUTOBERSERK] && - sc->data[SC_PROVOKE] && - sc->data[SC_PROVOKE]->val2==1 && - status->hp>=status->max_hp>>2 - ) //End auto berserk. - status_change_end(bl, SC_PROVOKE, INVALID_TIMER); - - // send hp update to client - switch (bl->type) { - case BL_PC: - pc_heal((TBL_PC *)bl,hp,sp,flag&2?1:0); - break; - case BL_MOB: - mob_heal((TBL_MOB *)bl,hp); - break; - case BL_HOM: - merc_hom_heal((TBL_HOM *)bl); - break; - case BL_MER: - mercenary_heal((TBL_MER *)bl,hp,sp); - break; - case BL_ELEM: - elemental_heal((TBL_ELEM *)bl,hp,sp); - break; - } + struct status_data *status; + struct status_change *sc; + + status = status_get_status_data(bl); + + if (status == &dummy_status || !status->hp) + return 0; + + sc = status_get_sc(bl); + if (sc && !sc->count) + sc = NULL; + + if (hp < 0) { + if (hp == INT_MIN) hp++; //-INT_MIN == INT_MIN in some architectures! + status_damage(NULL, bl, -hp, 0, 0, 1); + hp = 0; + } + + if(hp) { + if( sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) ) { + if( flag&1 ) + flag &= ~2; + else + hp = 0; + } - return hp+sp; + if((unsigned int)hp > status->max_hp - status->hp) + hp = status->max_hp - status->hp; + } + + if(sp < 0) { + if (sp==INT_MIN) sp++; + status_damage(NULL, bl, 0, -sp, 0, 1); + sp = 0; + } + + if(sp) { + if((unsigned int)sp > status->max_sp - status->sp) + sp = status->max_sp - status->sp; + } + + if(!sp && !hp) return 0; + + status->hp+= hp; + status->sp+= sp; + + if(hp && sc && + sc->data[SC_AUTOBERSERK] && + sc->data[SC_PROVOKE] && + sc->data[SC_PROVOKE]->val2==1 && + status->hp>=status->max_hp>>2 + ) //End auto berserk. + status_change_end(bl, SC_PROVOKE, INVALID_TIMER); + + // send hp update to client + switch(bl->type) { + case BL_PC: pc_heal((TBL_PC*)bl,hp,sp,flag&2?1:0); break; + case BL_MOB: mob_heal((TBL_MOB*)bl,hp); break; + case BL_HOM: merc_hom_heal((TBL_HOM*)bl); break; + case BL_MER: mercenary_heal((TBL_MER*)bl,hp,sp); break; + case BL_ELEM: elemental_heal((TBL_ELEM*)bl,hp,sp); break; + } + + return hp+sp; } //Does percentual non-flinching damage/heal. If mob is killed this way, @@ -1455,812 +1426,825 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) //Furthermore, if flag==2, then the target must not die from the substraction. int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag) { - struct status_data *status; - unsigned int hp =0, sp = 0; - - status = status_get_status_data(target); - - //Change the equation when the values are high enough to discard the - //imprecision in exchange of overflow protection [Skotlex] - //Also add 100% checks since those are the most used cases where we don't - //want aproximation errors. - if (hp_rate > 99) - hp = status->hp; - else if (hp_rate > 0) - hp = status->hp>10000? - hp_rate*(status->hp/100): - (hp_rate*status->hp)/100; - else if (hp_rate < -99) - hp = status->max_hp; - else if (hp_rate < 0) - hp = status->max_hp>10000? - (-hp_rate)*(status->max_hp/100): - (-hp_rate*status->max_hp)/100; - if (hp_rate && !hp) - hp = 1; - - if (flag == 2 && hp >= status->hp) - hp = status->hp-1; //Must not kill target. - - //Should be safe to not do overflow protection here, noone should have - //millions upon millions of SP - if (sp_rate > 99) - sp = status->sp; - else if (sp_rate > 0) - sp = (sp_rate*status->sp)/100; - else if (sp_rate < -99) - sp = status->max_sp; - else if (sp_rate < 0) - sp = (-sp_rate)*status->max_sp/100; - if (sp_rate && !sp) - sp = 1; - - //Ugly check in case damage dealt is too much for the received args of - //status_heal / status_damage. [Skotlex] - if (hp > INT_MAX) { - hp -= INT_MAX; - if (flag) - status_damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1)); - else - status_heal(target, INT_MAX, 0, 0); - } - if (sp > INT_MAX) { - sp -= INT_MAX; - if (flag) - status_damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1)); - else - status_heal(target, 0, INT_MAX, 0); - } - if (flag) - return status_damage(src, target, hp, sp, 0, (!src||src==target?5:1)); - return status_heal(target, hp, sp, 0); + struct status_data *status; + unsigned int hp =0, sp = 0; + + status = status_get_status_data(target); + + //Change the equation when the values are high enough to discard the + //imprecision in exchange of overflow protection [Skotlex] + //Also add 100% checks since those are the most used cases where we don't + //want aproximation errors. + if (hp_rate > 99) + hp = status->hp; + else if (hp_rate > 0) + hp = status->hp>10000? + hp_rate*(status->hp/100): + (hp_rate*status->hp)/100; + else if (hp_rate < -99) + hp = status->max_hp; + else if (hp_rate < 0) + hp = status->max_hp>10000? + (-hp_rate)*(status->max_hp/100): + (-hp_rate*status->max_hp)/100; + if (hp_rate && !hp) + hp = 1; + + if (flag == 2 && hp >= status->hp) + hp = status->hp-1; //Must not kill target. + + //Should be safe to not do overflow protection here, noone should have + //millions upon millions of SP + if (sp_rate > 99) + sp = status->sp; + else if (sp_rate > 0) + sp = (sp_rate*status->sp)/100; + else if (sp_rate < -99) + sp = status->max_sp; + else if (sp_rate < 0) + sp = (-sp_rate)*status->max_sp/100; + if (sp_rate && !sp) + sp = 1; + + //Ugly check in case damage dealt is too much for the received args of + //status_heal / status_damage. [Skotlex] + if (hp > INT_MAX) { + hp -= INT_MAX; + if (flag) + status_damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1)); + else + status_heal(target, INT_MAX, 0, 0); + } + if (sp > INT_MAX) { + sp -= INT_MAX; + if (flag) + status_damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1)); + else + status_heal(target, 0, INT_MAX, 0); + } + if (flag) + return status_damage(src, target, hp, sp, 0, (!src||src==target?5:1)); + return status_heal(target, hp, sp, 0); } int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp) { - struct status_data *status; - unsigned int hp, sp; - if (!status_isdead(bl)) return 0; - - status = status_get_status_data(bl); - if (status == &dummy_status) - return 0; //Invalid target. - - hp = status->max_hp * per_hp/100; - sp = status->max_sp * per_sp/100; - - if (hp > status->max_hp - status->hp) - hp = status->max_hp - status->hp; - else if (per_hp && !hp) - hp = 1; - - if (sp > status->max_sp - status->sp) - sp = status->max_sp - status->sp; - else if (per_sp && !sp) - sp = 1; - - status->hp += hp; - status->sp += sp; - - if (bl->prev) //Animation only if character is already on a map. - clif_resurrection(bl, 1); - switch (bl->type) { - case BL_PC: - pc_revive((TBL_PC *)bl, hp, sp); - break; - case BL_MOB: - mob_revive((TBL_MOB *)bl, hp); - break; - case BL_HOM: - merc_hom_revive((TBL_HOM *)bl, hp, sp); - break; - } - return 1; + struct status_data *status; + unsigned int hp, sp; + if (!status_isdead(bl)) return 0; + + status = status_get_status_data(bl); + if (status == &dummy_status) + return 0; //Invalid target. + + hp = status->max_hp * per_hp/100; + sp = status->max_sp * per_sp/100; + + if(hp > status->max_hp - status->hp) + hp = status->max_hp - status->hp; + else if (per_hp && !hp) + hp = 1; + + if(sp > status->max_sp - status->sp) + sp = status->max_sp - status->sp; + else if (per_sp && !sp) + sp = 1; + + status->hp += hp; + status->sp += sp; + + if (bl->prev) //Animation only if character is already on a map. + clif_resurrection(bl, 1); + switch (bl->type) { + case BL_PC: pc_revive((TBL_PC*)bl, hp, sp); break; + case BL_MOB: mob_revive((TBL_MOB*)bl, hp); break; + case BL_HOM: merc_hom_revive((TBL_HOM*)bl, hp, sp); break; + } + return 1; } /*========================================== * Checks whether the src can use the skill on the target, * taking into account status/option of both source/target. [Skotlex] * flag: - * 0 - Trying to use skill on target. - * 1 - Cast bar is done. - * 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones. + * 0 - Trying to use skill on target. + * 1 - Cast bar is done. + * 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones. * src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack. * target MAY Be null, in which case the checks are only to see * whether the source can cast or not the skill on the ground. *------------------------------------------*/ int status_check_skilluse(struct block_list *src, struct block_list *target, int skill_num, int flag) { - struct status_data *status; - struct status_change *sc=NULL, *tsc; - int hide_flag; - - status = src?status_get_status_data(src):&dummy_status; - - if (src && src->type != BL_PC && status_isdead(src)) - return 0; - - if (!skill_num) { //Normal attack checks. - if (!(status->mode&MD_CANATTACK)) - return 0; //This mode is only needed for melee attacking. - //Dead state is not checked for skills as some skills can be used - //on dead characters, said checks are left to skill.c [Skotlex] - if (target && status_isdead(target)) - return 0; - if (src && (sc = status_get_sc(src)) && sc->data[SC_CRYSTALIZE] && src->type != BL_MOB) - return 0; - } - - switch (skill_num) { - case PA_PRESSURE: - if (flag && target) { - //Gloria Avoids pretty much everything.... - tsc = status_get_sc(target); - if (tsc && tsc->option&OPTION_HIDE) - return 0; - } - break; - case GN_WALLOFTHORN: - if (target && status_isdead(target)) - return 0; - break; - case AL_TELEPORT: - //Should fail when used on top of Land Protector [Skotlex] - if (src && map_getcell(src->m, src->x, src->y, CELL_CHKLANDPROTECTOR) - && !(status->mode&MD_BOSS) - && (src->type != BL_PC || ((TBL_PC *)src)->skillitem != skill_num)) - return 0; - break; - default: - break; - } - - if (src) sc = status_get_sc(src); - - if (sc && sc->count) { - - if (skill_num != RK_REFRESH && sc->opt1 >0 && (sc->opt1 != OPT1_CRYSTALIZE && src->type != BL_MOB) && sc->opt1 != OPT1_BURNING && skill_num != SR_GENTLETOUCH_CURE) { //Stuned/Frozen/etc - if (flag != 1) //Can't cast, casted stuff can't damage. - return 0; - if (!(skill_get_inf(skill_num)&INF_GROUND_SKILL)) - return 0; //Targetted spells can't come off. - } - - if ( - (sc->data[SC_TRICKDEAD] && skill_num != NV_TRICKDEAD) - || (sc->data[SC_AUTOCOUNTER] && !flag) - || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF && skill_num != PA_GOSPEL) - || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF && flag != 2) - ) - return 0; - - if (sc->data[SC_WINKCHARM] && target && !flag) { //Prevents skill usage - if (unit_bl2ud(src) && (unit_bl2ud(src))->walktimer == INVALID_TIMER) - unit_walktobl(src, map_id2bl(sc->data[SC_WINKCHARM]->val2), 3, 1); - clif_emotion(src, E_LV); - return 0; - } - - if (sc->data[SC_BLADESTOP]) { - switch (sc->data[SC_BLADESTOP]->val1) { - case 5: - if (skill_num == MO_EXTREMITYFIST) break; - case 4: - if (skill_num == MO_CHAINCOMBO) break; - case 3: - if (skill_num == MO_INVESTIGATE) break; - case 2: - if (skill_num == MO_FINGEROFFENSIVE) break; - default: - return 0; - } - } + struct status_data *status; + struct status_change *sc=NULL, *tsc; + int hide_flag; + + status = src?status_get_status_data(src):&dummy_status; + + if (src && src->type != BL_PC && status_isdead(src)) + return 0; + + if (!skill_num) { //Normal attack checks. + if (!(status->mode&MD_CANATTACK)) + return 0; //This mode is only needed for melee attacking. + //Dead state is not checked for skills as some skills can be used + //on dead characters, said checks are left to skill.c [Skotlex] + if (target && status_isdead(target)) + return 0; + if( src && (sc = status_get_sc(src)) && sc->data[SC_CRYSTALIZE] && src->type != BL_MOB) + return 0; + } + + switch( skill_num ) { + case PA_PRESSURE: + if( flag && target ) { + //Gloria Avoids pretty much everything.... + tsc = status_get_sc(target); + if(tsc && tsc->option&OPTION_HIDE) + return 0; + } + break; + case GN_WALLOFTHORN: + if( target && status_isdead(target) ) + return 0; + break; + case AL_TELEPORT: + //Should fail when used on top of Land Protector [Skotlex] + if (src && map_getcell(src->m, src->x, src->y, CELL_CHKLANDPROTECTOR) + && !(status->mode&MD_BOSS) + && (src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_num)) + return 0; + break; + default: + break; + } - if (sc->data[SC_DANCING] && flag!=2) { - if (src->type == BL_PC && skill_num >= WA_SWING_DANCE && skill_num <= WM_UNLIMITED_HUMMING_VOICE) { - // Lvl 5 Lesson or higher allow you use 3rd job skills while dancing.v - if (pc_checkskill((TBL_PC *)src,WM_LESSON) < 5) - return 0; - } else if (sc->data[SC_LONGING]) { //Allow everything except dancing/re-dancing. [Skotlex] - if (skill_num == BD_ENCORE || - skill_get_inf2(skill_num)&(INF2_SONG_DANCE|INF2_ENSEMBLE_SKILL) - ) - return 0; - } else { - switch (skill_num) { - case BD_ADAPTATION: - case CG_LONGINGFREEDOM: - case BA_MUSICALSTRIKE: - case DC_THROWARROW: - break; - default: - return 0; - } - } - if ((sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE && skill_num == BD_ADAPTATION) - return 0; //Can't amp out of Wand of Hermode :/ [Skotlex] - } + if ( src ) sc = status_get_sc(src); - if (skill_num && //Do not block item-casted skills. - (src->type != BL_PC || ((TBL_PC *)src)->skillitem != skill_num) - ) { //Skills blocked through status changes... - if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through - sc->cant.cast || - (sc->data[SC_MARIONETTE] && skill_num != CG_MARIONETTE) || //Only skill you can use is marionette again to cancel it - (sc->data[SC_MARIONETTE2] && skill_num == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another - (sc->data[SC_STASIS] && skill_block_check(src, SC_STASIS, skill_num)) || - (sc->data[SC_KAGEHUMI] && skill_block_check(src, SC_KAGEHUMI, skill_num)) - )) - return 0; + if( sc && sc->count ) { - //Skill blocking. - if ( - (sc->data[SC_VOLCANO] && skill_num == WZ_ICEWALL) || - (sc->data[SC_ROKISWEIL] && skill_num != BD_ADAPTATION) || - (sc->data[SC_HERMODE] && skill_get_inf(skill_num) & INF_SUPPORT_SKILL) || - (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOSKILL) - ) - return 0; + if( sc->opt1 >0 && (sc->opt1 != OPT1_CRYSTALIZE && src->type != BL_MOB) && sc->opt1 != OPT1_BURNING && skill_num != SR_GENTLETOUCH_CURE ) { //Stuned/Frozen/etc + if (flag != 1) //Can't cast, casted stuff can't damage. + return 0; + if (!(skill_get_inf(skill_num)&INF_GROUND_SKILL)) + return 0; //Targetted spells can't come off. + } - if (sc->data[SC__MANHOLE] || ((tsc = status_get_sc(target)) && tsc->data[SC__MANHOLE])) { - switch (skill_num) { //##TODO## make this a flag in skill_db? - // Skills that can be used even under Man Hole effects. - case SC_SHADOWFORM: - case SC_STRIPACCESSARY: - break; - default: - return 0; - } - } + if ( + (sc->data[SC_TRICKDEAD] && skill_num != NV_TRICKDEAD) + || (sc->data[SC_AUTOCOUNTER] && !flag) + || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF && skill_num != PA_GOSPEL) + || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF && flag != 2) + ) + return 0; + + if (sc->data[SC_WINKCHARM] && target && !flag) { //Prevents skill usage + if( unit_bl2ud(src) && (unit_bl2ud(src))->walktimer == INVALID_TIMER ) + unit_walktobl(src, map_id2bl(sc->data[SC_WINKCHARM]->val2), 3, 1); + clif_emotion(src, E_LV); + return 0; + } - } - } + if (sc->data[SC_BLADESTOP]) { + switch (sc->data[SC_BLADESTOP]->val1) + { + case 5: if (skill_num == MO_EXTREMITYFIST) break; + case 4: if (skill_num == MO_CHAINCOMBO) break; + case 3: if (skill_num == MO_INVESTIGATE) break; + case 2: if (skill_num == MO_FINGEROFFENSIVE) break; + default: return 0; + } + } - if (sc && sc->option) { - if (sc->option&OPTION_HIDE) - switch (skill_num) { //Usable skills while hiding. - case TF_HIDING: - case AS_GRIMTOOTH: - case RG_BACKSTAP: - case RG_RAID: - case NJ_SHADOWJUMP: - case NJ_KIRIKAGE: - case KO_YAMIKUMO: - break; - default: - //Non players can use all skills while hidden. - if (!skill_num || src->type == BL_PC) - return 0; - } - if (sc->option&OPTION_CHASEWALK && skill_num != ST_CHASEWALK) - return 0; - if (sc->option&OPTION_MOUNTING) - return 0;//New mounts can't attack nor use skills in the client; this check makes it cheat-safe [Ind] - } + if (sc->data[SC_DANCING] && flag!=2) { + if( src->type == BL_PC && skill_num >= WA_SWING_DANCE && skill_num <= WM_UNLIMITED_HUMMING_VOICE ) + { // Lvl 5 Lesson or higher allow you use 3rd job skills while dancing.v + if( pc_checkskill((TBL_PC*)src,WM_LESSON) < 5 ) + return 0; + } else if(sc->data[SC_LONGING]) { //Allow everything except dancing/re-dancing. [Skotlex] + if (skill_num == BD_ENCORE || + skill_get_inf2(skill_num)&(INF2_SONG_DANCE|INF2_ENSEMBLE_SKILL) + ) + return 0; + } else { + switch (skill_num) { + case BD_ADAPTATION: + case CG_LONGINGFREEDOM: + case BA_MUSICALSTRIKE: + case DC_THROWARROW: + break; + default: + return 0; + } + } + if ((sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE && skill_num == BD_ADAPTATION) + return 0; //Can't amp out of Wand of Hermode :/ [Skotlex] + } - if (target == NULL || target == src) //No further checking needed. - return 1; - - tsc = status_get_sc(target); - - if (tsc && tsc->count) { - /* attacks in invincible are capped to 1 damage and handled in batte.c; allow spell break and eske for sealed shrine GDB when in INVINCIBLE state. */ - if (tsc->data[SC_INVINCIBLE] && !tsc->data[SC_INVINCIBLEOFF] && skill_num && !(skill_num&(SA_SPELLBREAKER|SL_SKE))) - return 0; - if (!skill_num && tsc->data[SC_TRICKDEAD]) - return 0; - if ((skill_num == WZ_STORMGUST || skill_num == WZ_FROSTNOVA || skill_num == NJ_HYOUSYOURAKU) - && tsc->data[SC_FREEZE]) - return 0; - if (skill_num == PR_LEXAETERNA && (tsc->data[SC_FREEZE] || (tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE))) - return 0; - } + if (skill_num && //Do not block item-casted skills. + (src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_num) + ) { //Skills blocked through status changes... + if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through + sc->cant.cast || + (sc->data[SC_MARIONETTE] && skill_num != CG_MARIONETTE) || //Only skill you can use is marionette again to cancel it + (sc->data[SC_MARIONETTE2] && skill_num == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another + (sc->data[SC_STASIS] && skill_block_check(src, SC_STASIS, skill_num)) || + (sc->data[SC_KAGEHUMI] && skill_block_check(src, SC_KAGEHUMI, skill_num)) + )) + return 0; + + //Skill blocking. + if ( + (sc->data[SC_VOLCANO] && skill_num == WZ_ICEWALL) || + (sc->data[SC_ROKISWEIL] && skill_num != BD_ADAPTATION) || + (sc->data[SC_HERMODE] && skill_get_inf(skill_num) & INF_SUPPORT_SKILL) || + (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOSKILL) + ) + return 0; + + if( sc->data[SC__MANHOLE] || ((tsc = status_get_sc(target)) && tsc->data[SC__MANHOLE]) ) { + switch(skill_num) {//##TODO## make this a flag in skill_db? + // Skills that can be used even under Man Hole effects. + case SC_SHADOWFORM: + case SC_STRIPACCESSARY: + break; + default: + return 0; + } + } - //If targetting, cloak+hide protect you, otherwise only hiding does. - hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK); - - //You cannot hide from ground skills. - if (skill_get_ele(skill_num,1) == ELE_EARTH) //TODO: Need Skill Lv here :/ - hide_flag &= ~OPTION_HIDE; - - switch (target->type) { - case BL_PC: { - struct map_session_data *sd = (TBL_PC *) target; - bool is_boss = (status->mode&MD_BOSS); - bool is_detect = ((status->mode&MD_DETECTOR)?true:false);//god-knows-why gcc doesn't shut up until this happens - if (pc_isinvisible(sd)) - return 0; - if (tsc->option&hide_flag && !is_boss && - ((sd->special_state.perfect_hiding || !is_detect) || - (tsc->data[SC_CLOAKINGEXCEED] && is_detect))) - return 0; - if (tsc->data[SC_CAMOUFLAGE] && !(is_boss || is_detect) && !skill_num) - return 0; - if (tsc->data[SC_STEALTHFIELD] && !is_boss) - return 0; - } - break; - case BL_ITEM: //Allow targetting of items to pick'em up (or in the case of mobs, to loot them). - //TODO: Would be nice if this could be used to judge whether the player can or not pick up the item it targets. [Skotlex] - if (status->mode&MD_LOOTER) - return 1; - return 0; - case BL_HOM: - case BL_MER: - case BL_ELEM: - if (target->type == BL_HOM && skill_num && battle_config.hom_setting&0x1 && skill_get_inf(skill_num)&INF_SUPPORT_SKILL && battle_get_master(target) != src) - return 0; // Can't use support skills on Homunculus (only Master/Self) - if (target->type == BL_MER && (skill_num == PR_ASPERSIO || (skill_num >= SA_FLAMELAUNCHER && skill_num <= SA_SEISMICWEAPON)) && battle_get_master(target) != src) - return 0; // Can't use Weapon endow skills on Mercenary (only Master) - if (skill_num == AM_POTIONPITCHER && (target->type == BL_MER || target->type == BL_ELEM)) - return 0; // Can't use Potion Pitcher on Mercenaries - default: - //Check for chase-walk/hiding/cloaking opponents. - if (tsc) { - if (tsc->option&hide_flag && !(status->mode&(MD_BOSS|MD_DETECTOR))) - return 0; - if (tsc->data[SC_STEALTHFIELD] && !(status->mode&MD_BOSS)) - return 0; - } - } - return 1; + } + } + + if (sc && sc->option) + { + if (sc->option&OPTION_HIDE) + switch (skill_num) { //Usable skills while hiding. + case TF_HIDING: + case AS_GRIMTOOTH: + case RG_BACKSTAP: + case RG_RAID: + case NJ_SHADOWJUMP: + case NJ_KIRIKAGE: + case KO_YAMIKUMO: + break; + default: + //Non players can use all skills while hidden. + if (!skill_num || src->type == BL_PC) + return 0; + } + if (sc->option&OPTION_CHASEWALK && skill_num != ST_CHASEWALK) + return 0; + if(sc->option&OPTION_MOUNTING) + return 0;//New mounts can't attack nor use skills in the client; this check makes it cheat-safe [Ind] + } + + if (target == NULL || target == src) //No further checking needed. + return 1; + + tsc = status_get_sc(target); + + if(tsc && tsc->count) { + /* attacks in invincible are capped to 1 damage and handled in batte.c; allow spell break and eske for sealed shrine GDB when in INVINCIBLE state. */ + if( tsc->data[SC_INVINCIBLE] && !tsc->data[SC_INVINCIBLEOFF] && skill_num && !(skill_num&(SA_SPELLBREAKER|SL_SKE)) ) + return 0; + if(!skill_num && tsc->data[SC_TRICKDEAD]) + return 0; + if((skill_num == WZ_STORMGUST || skill_num == WZ_FROSTNOVA || skill_num == NJ_HYOUSYOURAKU) + && tsc->data[SC_FREEZE]) + return 0; + if(skill_num == PR_LEXAETERNA && (tsc->data[SC_FREEZE] || (tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE))) + return 0; + } + + //If targetting, cloak+hide protect you, otherwise only hiding does. + hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK); + + //You cannot hide from ground skills. + if( skill_get_ele(skill_num,1) == ELE_EARTH ) //TODO: Need Skill Lv here :/ + hide_flag &= ~OPTION_HIDE; + + switch( target->type ) { + case BL_PC: { + struct map_session_data *sd = (TBL_PC*) target; + bool is_boss = (status->mode&MD_BOSS); + bool is_detect = ((status->mode&MD_DETECTOR)?true:false);//god-knows-why gcc doesn't shut up until this happens + if (pc_isinvisible(sd)) + return 0; + if (tsc->option&hide_flag && !is_boss && + ((sd->special_state.perfect_hiding || !is_detect) || + (tsc->data[SC_CLOAKINGEXCEED] && is_detect))) + return 0; + if( tsc->data[SC_CAMOUFLAGE] && !(is_boss || is_detect) && !skill_num ) + return 0; + if( tsc->data[SC_STEALTHFIELD] && !is_boss ) + return 0; + } + break; + case BL_ITEM: //Allow targetting of items to pick'em up (or in the case of mobs, to loot them). + //TODO: Would be nice if this could be used to judge whether the player can or not pick up the item it targets. [Skotlex] + if (status->mode&MD_LOOTER) + return 1; + return 0; + case BL_HOM: + case BL_MER: + case BL_ELEM: + if( target->type == BL_HOM && skill_num && battle_config.hom_setting&0x1 && skill_get_inf(skill_num)&INF_SUPPORT_SKILL && battle_get_master(target) != src ) + return 0; // Can't use support skills on Homunculus (only Master/Self) + if( target->type == BL_MER && (skill_num == PR_ASPERSIO || (skill_num >= SA_FLAMELAUNCHER && skill_num <= SA_SEISMICWEAPON)) && battle_get_master(target) != src ) + return 0; // Can't use Weapon endow skills on Mercenary (only Master) + if( skill_num == AM_POTIONPITCHER && ( target->type == BL_MER || target->type == BL_ELEM) ) + return 0; // Can't use Potion Pitcher on Mercenaries + default: + //Check for chase-walk/hiding/cloaking opponents. + if( tsc ) { + if( tsc->option&hide_flag && !(status->mode&(MD_BOSS|MD_DETECTOR))) + return 0; + if( tsc->data[SC_STEALTHFIELD] && !(status->mode&MD_BOSS) ) + return 0; + } + } + return 1; } //Checks whether the source can see and chase target. int status_check_visibility(struct block_list *src, struct block_list *target) { - int view_range; - struct status_data *status = status_get_status_data(src); - struct status_change *tsc = status_get_sc(target); - switch (src->type) { - case BL_MOB: - view_range = ((TBL_MOB *)src)->min_chase; - break; - case BL_PET: - view_range = ((TBL_PET *)src)->db->range2; - break; - default: - view_range = AREA_SIZE; - } - - if (src->m != target->m || !check_distance_bl(src, target, view_range)) - return 0; - - if (tsc && tsc->data[SC_STEALTHFIELD]) - return 0; - - switch (target->type) { - //Check for chase-walk/hiding/cloaking opponents. - case BL_PC: - if (tsc->data[SC_CLOAKINGEXCEED] && !(status->mode&MD_BOSS)) - return 0; - if ((tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(status->mode&MD_BOSS) && - (((TBL_PC *)target)->special_state.perfect_hiding || !(status->mode&MD_DETECTOR))) - return 0; - break; - default: - if (tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(status->mode&(MD_BOSS|MD_DETECTOR))) - return 0; - - } - - return 1; + int view_range; + struct status_data* status = status_get_status_data(src); + struct status_change* tsc = status_get_sc(target); + switch (src->type) { + case BL_MOB: + view_range = ((TBL_MOB*)src)->min_chase; + break; + case BL_PET: + view_range = ((TBL_PET*)src)->db->range2; + break; + default: + view_range = AREA_SIZE; + } + + if (src->m != target->m || !check_distance_bl(src, target, view_range)) + return 0; + + if( tsc && tsc->data[SC_STEALTHFIELD] ) + return 0; + + switch (target->type) + { //Check for chase-walk/hiding/cloaking opponents. + case BL_PC: + if ( tsc->data[SC_CLOAKINGEXCEED] && !(status->mode&MD_BOSS) ) + return 0; + if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(status->mode&MD_BOSS) && + ( ((TBL_PC*)target)->special_state.perfect_hiding || !(status->mode&MD_DETECTOR) ) ) + return 0; + break; + default: + if( tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(status->mode&(MD_BOSS|MD_DETECTOR)) ) + return 0; + + } + + return 1; } // Basic ASPD value -int status_base_amotion_pc(struct map_session_data *sd, struct status_data *status) +int status_base_amotion_pc(struct map_session_data* sd, struct status_data* status) { - int amotion; + int amotion; #ifdef RENEWAL_ASPD - short mod = -1; - - switch (sd->weapontype2) { // adjustment for dual weilding - case W_DAGGER: - mod = 0; - break; // 0, 1, 1 - case W_1HSWORD: - case W_1HAXE: - mod = 1; - if ((sd->class_&MAPID_THIRDMASK) == MAPID_GUILLOTINE_CROSS) // 0, 2, 3 - mod = sd->weapontype2 / W_1HSWORD + W_1HSWORD / sd->weapontype2 ; - } - - amotion = (sd->status.weapon < MAX_WEAPON_TYPE && mod < 0) - ? (aspd_base[pc_class2idx(sd->status.class_)][sd->status.weapon]) // single weapon - : ((aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2] // dual-wield - + aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2]) * 6 / 10 + 10 * mod - - aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2] - + aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype1]); - - if (sd->status.shield) - amotion += (2000 - aspd_base[pc_class2idx(sd->status.class_)][W_FIST]) + - (aspd_base[pc_class2idx(sd->status.class_)][MAX_WEAPON_TYPE] - 2000); + short mod = -1; + + switch( sd->weapontype2 ){ // adjustment for dual weilding + case W_DAGGER: mod = 0; break; // 0, 1, 1 + case W_1HSWORD: + case W_1HAXE: mod = 1; + if( (sd->class_&MAPID_THIRDMASK) == MAPID_GUILLOTINE_CROSS ) // 0, 2, 3 + mod = sd->weapontype2 / W_1HSWORD + W_1HSWORD / sd->weapontype2 ; + } + + amotion = ( sd->status.weapon < MAX_WEAPON_TYPE && mod < 0 ) + ? (aspd_base[pc_class2idx(sd->status.class_)][sd->status.weapon]) // single weapon + : ((aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2] // dual-wield + + aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2]) * 6 / 10 + 10 * mod + - aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2] + + aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype1]); + + if ( sd->status.shield ) + amotion += ( 2000 - aspd_base[pc_class2idx(sd->status.class_)][W_FIST] ) + + ( aspd_base[pc_class2idx(sd->status.class_)][MAX_WEAPON_TYPE] - 2000 ); #else - // base weapon delay - amotion = (sd->status.weapon < MAX_WEAPON_TYPE) - ? (aspd_base[pc_class2idx(sd->status.class_)][sd->status.weapon]) // single weapon - : (aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype1] + aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2])*7/10; // dual-wield + // base weapon delay + amotion = (sd->status.weapon < MAX_WEAPON_TYPE) + ? (aspd_base[pc_class2idx(sd->status.class_)][sd->status.weapon]) // single weapon + : (aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype1] + aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2])*7/10; // dual-wield - // percentual delay reduction from stats - amotion -= amotion * (4*status->agi + status->dex)/1000; + // percentual delay reduction from stats + amotion -= amotion * (4*status->agi + status->dex)/1000; #endif - // raw delay adjustment from bAspd bonus - amotion += sd->bonus.aspd_add; + // raw delay adjustment from bAspd bonus + amotion += sd->bonus.aspd_add; - return amotion; + return amotion; } static unsigned short status_base_atk(const struct block_list *bl, const struct status_data *status) { - int flag = 0, str, dex, + int flag = 0, str, dex, #ifdef RENEWAL - rstr, + rstr, #endif - dstr; - - - if (!(bl->type&battle_config.enable_baseatk)) - return 0; - - if (bl->type == BL_PC) - switch (((TBL_PC *)bl)->status.weapon) { - case W_BOW: - case W_MUSICAL: - case W_WHIP: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - flag = 1; - } - if (flag) { + dstr; + + + if(!(bl->type&battle_config.enable_baseatk)) + return 0; + + if (bl->type == BL_PC) + switch(((TBL_PC*)bl)->status.weapon){ + case W_BOW: + case W_MUSICAL: + case W_WHIP: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + flag = 1; + } + if (flag) { #ifdef RENEWAL - rstr = + rstr = #endif - str = status->dex; - dex = status->str; - } else { + str = status->dex; + dex = status->str; + } else { #ifdef RENEWAL - rstr = + rstr = #endif - str = status->str; - dex = status->dex; - } - //Normally only players have base-atk, but homunc have a different batk - // equation, hinting that perhaps non-players should use this for batk. - // [Skotlex] - dstr = str/10; - str += dstr*dstr; - if (bl->type == BL_PC) + str = status->str; + dex = status->dex; + } + //Normally only players have base-atk, but homunc have a different batk + // equation, hinting that perhaps non-players should use this for batk. + // [Skotlex] + dstr = str/10; + str += dstr*dstr; + if (bl->type == BL_PC) #ifdef RENEWAL - str = (rstr*10 + dex*10/5 + status->luk*10/3 + ((TBL_PC *)bl)->status.base_level*10/4)/10; + str = (rstr*10 + dex*10/5 + status->luk*10/3 + ((TBL_PC*)bl)->status.base_level*10/4)/10; #else - str+= dex/5 + status->luk/5; + str+= dex/5 + status->luk/5; #endif - return cap_value(str, 0, USHRT_MAX); + return cap_value(str, 0, USHRT_MAX); } -#ifndef RENEWAL -static inline unsigned short status_base_matk_min(const struct status_data* status){ return status->int_+(status->int_/7)*(status->int_/7); } -static inline unsigned short status_base_matk_max(const struct status_data* status){ return status->int_+(status->int_/5)*(status->int_/5); } + +static inline unsigned short status_base_matk_max(const struct status_data* status) +{ +#ifdef RENEWAL + return status->matk_max; // in RE maximum MATK signs weapon matk, which we store in this var #else -unsigned short status_base_matk(const struct status_data* status, int level){ return status->int_+(status->int_/2)+(status->dex/5)+(status->luk/3)+(level/4); } + return status->int_+(status->int_/5)*(status->int_/5); #endif +} + +#ifdef RENEWAL +static inline unsigned short status_base_matk_min(const struct status_data* status, int lvl) +#else +static inline unsigned short status_base_matk_min(const struct status_data* status) +#endif +{ +#ifdef RENEWAL + return status->int_+(status->int_/2)+(status->dex/5)+(status->luk/3)+(lvl/4); +#else + return status->int_+(status->int_/7)*(status->int_/7); +#endif +} + //Fills in the misc data that can be calculated from the other status info (except for level) void status_calc_misc(struct block_list *bl, struct status_data *status, int level) { - //Non players get the value set, players need to stack with previous bonuses. - if (bl->type != BL_PC) - status->batk = - status->hit = status->flee = - status->def2 = status->mdef2 = - status->cri = status->flee2 = 0; + //Non players get the value set, players need to stack with previous bonuses. + if( bl->type != BL_PC ) + status->batk = + status->hit = status->flee = + status->def2 = status->mdef2 = + status->cri = status->flee2 = 0; +#ifdef RENEWAL + status->matk_min = status_base_matk_min(status, level); +#else + status->matk_min = status_base_matk_min(status); +#endif + status->matk_max = status_base_matk_max(status); #ifdef RENEWAL // renewal formulas - status->matk_min = status->matk_max = status_base_matk(status, level); - status->hit += level + status->dex + status->luk/3 + 175; //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175 - status->flee += level + status->agi + status->luk/5 + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 - status->def2 += (int)(((float)level + status->vit)/2 + ((float)status->agi/5)); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def) - status->mdef2 += (int)(status->int_ + ((float)level/4) + ((float)status->dex/5) + ((float)status->vit/5)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef) + status->hit += level + status->dex + status->luk/3 + 175; //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175 + status->flee += level + status->agi + status->luk/5 + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 + status->def2 += (int)(((float)level + status->vit)/2 + ((float)status->agi/5)); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def) + status->mdef2 += (int)(status->int_ + ((float)level/4) + ((float)status->dex/5) + ((float)status->vit/5)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef) #else - status->matk_min = status_base_matk_min(status); - status->matk_max = status_base_matk_max(status); - status->hit += level + status->dex; - status->flee += level + status->agi; - status->def2 += status->vit; - status->mdef2 += status->int_ + (status->vit>>1); + status->hit += level + status->dex; + status->flee += level + status->agi; + status->def2 += status->vit; + status->mdef2 += status->int_ + (status->vit>>1); #endif - if (bl->type&battle_config.enable_critical) - status->cri += 10 + (status->luk*10/3); //(every 1 luk = +0.3 critical) - else - status->cri = 0; - - if (bl->type&battle_config.enable_perfect_flee) - status->flee2 += status->luk + 10; //(every 10 luk = +1 perfect flee) - else - status->flee2 = 0; - - if (status->batk) { - int temp = status->batk + status_base_atk(bl, status); - status->batk = cap_value(temp, 0, USHRT_MAX); - } else - status->batk = status_base_atk(bl, status); - if (status->cri) - switch (bl->type) { - case BL_MOB: - if (battle_config.mob_critical_rate != 100) - status->cri = status->cri*battle_config.mob_critical_rate/100; - if (!status->cri && battle_config.mob_critical_rate) - status->cri = 10; - break; - case BL_PC: - //Players don't have a critical adjustment setting as of yet. - break; - default: - if (battle_config.critical_rate != 100) - status->cri = status->cri*battle_config.critical_rate/100; - if (!status->cri && battle_config.critical_rate) - status->cri = 10; - } - if (bl->type&BL_REGEN) - status_calc_regen(bl, status, status_get_regen_data(bl)); + if( bl->type&battle_config.enable_critical ) + status->cri += 10 + (status->luk*10/3); //(every 1 luk = +0.3 critical) + else + status->cri = 0; + + if (bl->type&battle_config.enable_perfect_flee) + status->flee2 += status->luk + 10; //(every 10 luk = +1 perfect flee) + else + status->flee2 = 0; + + if (status->batk) { + int temp = status->batk + status_base_atk(bl, status); + status->batk = cap_value(temp, 0, USHRT_MAX); + } else + status->batk = status_base_atk(bl, status); + if (status->cri) + switch (bl->type) { + case BL_MOB: + if(battle_config.mob_critical_rate != 100) + status->cri = status->cri*battle_config.mob_critical_rate/100; + if(!status->cri && battle_config.mob_critical_rate) + status->cri = 10; + break; + case BL_PC: + //Players don't have a critical adjustment setting as of yet. + break; + default: + if(battle_config.critical_rate != 100) + status->cri = status->cri*battle_config.critical_rate/100; + if (!status->cri && battle_config.critical_rate) + status->cri = 10; + } + if(bl->type&BL_REGEN) + status_calc_regen(bl, status, status_get_regen_data(bl)); } //Skotlex: Calculates the initial status for the given mob //first will only be false when the mob leveled up or got a GuardUp level. -int status_calc_mob_(struct mob_data *md, bool first) +int status_calc_mob_(struct mob_data* md, bool first) { - struct status_data *status; - struct block_list *mbl = NULL; - int flag=0; - - if (first) { - //Set basic level on respawn. - if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv) - ; - else - md->level = md->db->lv; - } - - //Check if we need custom base-status - if (battle_config.mobs_level_up && md->level > md->db->lv) - flag|=1; - - if (md->special_state.size) - flag|=2; - - if (md->guardian_data && md->guardian_data->guardup_lv) - flag|=4; - if (md->class_ == MOBID_EMPERIUM) - flag|=4; - - if (battle_config.slaves_inherit_speed && md->master_id) - flag|=8; - - if (md->master_id && md->special_state.ai>1) - flag|=16; - - if (!flag) { - //No special status required. - if (md->base_status) { - aFree(md->base_status); - md->base_status = NULL; - } - if (first) - memcpy(&md->status, &md->db->status, sizeof(struct status_data)); - return 0; - } - if (!md->base_status) - md->base_status = (struct status_data *)aCalloc(1, sizeof(struct status_data)); - - status = md->base_status; - memcpy(status, &md->db->status, sizeof(struct status_data)); - - if (flag&(8|16)) - mbl = map_id2bl(md->master_id); - - if (flag&8 && mbl) { - struct status_data *mstatus = status_get_base_status(mbl); - if (mstatus && - battle_config.slaves_inherit_speed&(mstatus->mode&MD_CANMOVE?1:2)) - status->speed = mstatus->speed; - if (status->speed < 2) /* minimum for the unit to function properly */ - status->speed = 2; - } - - if (flag&16 && mbl) { - //Max HP setting from Summon Flora/marine Sphere - struct unit_data *ud = unit_bl2ud(mbl); - //Remove special AI when this is used by regular mobs. - if (mbl->type == BL_MOB && !((TBL_MOB *)mbl)->special_state.ai) - md->special_state.ai = 0; - if (ud) { - // different levels of HP according to skill level - if (ud->skillid == AM_SPHEREMINE) { - status->max_hp = 2000 + 400*ud->skilllv; - } else if (ud->skillid == KO_ZANZOU) { - status->max_hp = 3000 + 3000 * ud->skilllv; - } else { //AM_CANNIBALIZE - status->max_hp = 1500 + 200*ud->skilllv + 10*status_get_lv(mbl); - status->mode|= MD_CANATTACK|MD_AGGRESSIVE; - } - status->hp = status->max_hp; - } - } - - if (flag&1) { - // increase from mobs leveling up [Valaris] - int diff = md->level - md->db->lv; - status->str+= diff; - status->agi+= diff; - status->vit+= diff; - status->int_+= diff; - status->dex+= diff; - status->luk+= diff; - status->max_hp += diff*status->vit; - status->max_sp += diff*status->int_; - status->hp = status->max_hp; - status->sp = status->max_sp; - status->speed -= cap_value(diff, 0, status->speed - 10); - } - - - if (flag&2 && battle_config.mob_size_influence) { - // change for sized monsters [Valaris] - if (md->special_state.size==SZ_MEDIUM) { - status->max_hp>>=1; - status->max_sp>>=1; - if (!status->max_hp) status->max_hp = 1; - if (!status->max_sp) status->max_sp = 1; - status->hp=status->max_hp; - status->sp=status->max_sp; - status->str>>=1; - status->agi>>=1; - status->vit>>=1; - status->int_>>=1; - status->dex>>=1; - status->luk>>=1; - if (!status->str) status->str = 1; - if (!status->agi) status->agi = 1; - if (!status->vit) status->vit = 1; - if (!status->int_) status->int_ = 1; - if (!status->dex) status->dex = 1; - if (!status->luk) status->luk = 1; - } else if (md->special_state.size==SZ_BIG) { - status->max_hp<<=1; - status->max_sp<<=1; - status->hp=status->max_hp; - status->sp=status->max_sp; - status->str<<=1; - status->agi<<=1; - status->vit<<=1; - status->int_<<=1; - status->dex<<=1; - status->luk<<=1; - } - } - - status_calc_misc(&md->bl, status, md->level); - - if (flag&4) { - // Strengthen Guardians - custom value +10% / lv - struct guild_castle *gc; - gc=guild_mapname2gc(map[md->bl.m].name); - if (!gc) - ShowError("status_calc_mob: No castle set at map %s\n", map[md->bl.m].name); - else if (gc->castle_id < 24 || md->class_ == MOBID_EMPERIUM) { + struct status_data *status; + struct block_list *mbl = NULL; + int flag=0; + + if(first) + { //Set basic level on respawn. + if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv) + ; + else + md->level = md->db->lv; + } + + //Check if we need custom base-status + if (battle_config.mobs_level_up && md->level > md->db->lv) + flag|=1; + + if (md->special_state.size) + flag|=2; + + if (md->guardian_data && md->guardian_data->guardup_lv) + flag|=4; + if (md->class_ == MOBID_EMPERIUM) + flag|=4; + + if (battle_config.slaves_inherit_speed && md->master_id) + flag|=8; + + if (md->master_id && md->special_state.ai>1) + flag|=16; + + if (!flag) + { //No special status required. + if (md->base_status) { + aFree(md->base_status); + md->base_status = NULL; + } + if(first) + memcpy(&md->status, &md->db->status, sizeof(struct status_data)); + return 0; + } + if (!md->base_status) + md->base_status = (struct status_data*)aCalloc(1, sizeof(struct status_data)); + + status = md->base_status; + memcpy(status, &md->db->status, sizeof(struct status_data)); + + if (flag&(8|16)) + mbl = map_id2bl(md->master_id); + + if (flag&8 && mbl) { + struct status_data *mstatus = status_get_base_status(mbl); + if (mstatus && + battle_config.slaves_inherit_speed&(mstatus->mode&MD_CANMOVE?1:2)) + status->speed = mstatus->speed; + if( status->speed < 2 ) /* minimum for the unit to function properly */ + status->speed = 2; + } + + if (flag&16 && mbl) + { //Max HP setting from Summon Flora/marine Sphere + struct unit_data *ud = unit_bl2ud(mbl); + //Remove special AI when this is used by regular mobs. + if (mbl->type == BL_MOB && !((TBL_MOB*)mbl)->special_state.ai) + md->special_state.ai = 0; + if (ud) + { // different levels of HP according to skill level + if (ud->skillid == AM_SPHEREMINE) { + status->max_hp = 2000 + 400*ud->skilllv; + } else if(ud->skillid == KO_ZANZOU){ + status->max_hp = 3000 + 3000 * ud->skilllv; + } else { //AM_CANNIBALIZE + status->max_hp = 1500 + 200*ud->skilllv + 10*status_get_lv(mbl); + status->mode|= MD_CANATTACK|MD_AGGRESSIVE; + } + status->hp = status->max_hp; + } + } + + if (flag&1) + { // increase from mobs leveling up [Valaris] + int diff = md->level - md->db->lv; + status->str+= diff; + status->agi+= diff; + status->vit+= diff; + status->int_+= diff; + status->dex+= diff; + status->luk+= diff; + status->max_hp += diff*status->vit; + status->max_sp += diff*status->int_; + status->hp = status->max_hp; + status->sp = status->max_sp; + status->speed -= cap_value(diff, 0, status->speed - 10); + } + + + if (flag&2 && battle_config.mob_size_influence) + { // change for sized monsters [Valaris] + if (md->special_state.size==SZ_MEDIUM) { + status->max_hp>>=1; + status->max_sp>>=1; + if (!status->max_hp) status->max_hp = 1; + if (!status->max_sp) status->max_sp = 1; + status->hp=status->max_hp; + status->sp=status->max_sp; + status->str>>=1; + status->agi>>=1; + status->vit>>=1; + status->int_>>=1; + status->dex>>=1; + status->luk>>=1; + if (!status->str) status->str = 1; + if (!status->agi) status->agi = 1; + if (!status->vit) status->vit = 1; + if (!status->int_) status->int_ = 1; + if (!status->dex) status->dex = 1; + if (!status->luk) status->luk = 1; + } else if (md->special_state.size==SZ_BIG) { + status->max_hp<<=1; + status->max_sp<<=1; + status->hp=status->max_hp; + status->sp=status->max_sp; + status->str<<=1; + status->agi<<=1; + status->vit<<=1; + status->int_<<=1; + status->dex<<=1; + status->luk<<=1; + } + } + + status_calc_misc(&md->bl, status, md->level); + + if(flag&4) + { // Strengthen Guardians - custom value +10% / lv + struct guild_castle *gc; + gc=guild_mapname2gc(map[md->bl.m].name); + if (!gc) + ShowError("status_calc_mob: No castle set at map %s\n", map[md->bl.m].name); + else + if(gc->castle_id < 24 || md->class_ == MOBID_EMPERIUM) { #ifdef RENEWAL - status->max_hp += 50 * gc->defense; - status->max_sp += 70 * gc->defense; + status->max_hp += 50 * gc->defense; + status->max_sp += 70 * gc->defense; #else - status->max_hp += 1000 * gc->defense; - status->max_sp += 200 * gc->defense; + status->max_hp += 1000 * gc->defense; + status->max_sp += 200 * gc->defense; #endif - status->hp = status->max_hp; - status->sp = status->max_sp; - status->def += (gc->defense+2)/3; - status->mdef += (gc->defense+2)/3; - } - if (md->class_ != MOBID_EMPERIUM) { - status->batk += status->batk * 10*md->guardian_data->guardup_lv/100; - status->rhw.atk += status->rhw.atk * 10*md->guardian_data->guardup_lv/100; - status->rhw.atk2 += status->rhw.atk2 * 10*md->guardian_data->guardup_lv/100; - status->aspd_rate -= 100*md->guardian_data->guardup_lv; - } - } + status->hp = status->max_hp; + status->sp = status->max_sp; + status->def += (gc->defense+2)/3; + status->mdef += (gc->defense+2)/3; + } + if(md->class_ != MOBID_EMPERIUM) { + status->batk += status->batk * 10*md->guardian_data->guardup_lv/100; + status->rhw.atk += status->rhw.atk * 10*md->guardian_data->guardup_lv/100; + status->rhw.atk2 += status->rhw.atk2 * 10*md->guardian_data->guardup_lv/100; + status->aspd_rate -= 100*md->guardian_data->guardup_lv; + } + } - if (first) //Initial battle status - memcpy(&md->status, status, sizeof(struct status_data)); + if( first ) //Initial battle status + memcpy(&md->status, status, sizeof(struct status_data)); - return 1; + return 1; } //Skotlex: Calculates the stats of the given pet. int status_calc_pet_(struct pet_data *pd, bool first) { - nullpo_ret(pd); - - if (first) { - memcpy(&pd->status, &pd->db->status, sizeof(struct status_data)); - pd->status.mode = MD_CANMOVE; // pets discard all modes, except walking - pd->status.speed = pd->petDB->speed; - - if (battle_config.pet_attack_support || battle_config.pet_damage_support) { - // attack support requires the pet to be able to attack - pd->status.mode|= MD_CANATTACK; - } - } - - if (battle_config.pet_lv_rate && pd->msd) { - struct map_session_data *sd = pd->msd; - int lv; - - lv =sd->status.base_level*battle_config.pet_lv_rate/100; - if (lv < 0) - lv = 1; - if (lv != pd->pet.level || first) { - struct status_data *bstat = &pd->db->status, *status = &pd->status; - pd->pet.level = lv; - if (!first) //Lv Up animation - clif_misceffect(&pd->bl, 0); - status->rhw.atk = (bstat->rhw.atk*lv)/pd->db->lv; - status->rhw.atk2 = (bstat->rhw.atk2*lv)/pd->db->lv; - status->str = (bstat->str*lv)/pd->db->lv; - status->agi = (bstat->agi*lv)/pd->db->lv; - status->vit = (bstat->vit*lv)/pd->db->lv; - status->int_ = (bstat->int_*lv)/pd->db->lv; - status->dex = (bstat->dex*lv)/pd->db->lv; - status->luk = (bstat->luk*lv)/pd->db->lv; - - status->rhw.atk = cap_value(status->rhw.atk, 1, battle_config.pet_max_atk1); - status->rhw.atk2 = cap_value(status->rhw.atk2, 2, battle_config.pet_max_atk2); - status->str = cap_value(status->str,1,battle_config.pet_max_stats); - status->agi = cap_value(status->agi,1,battle_config.pet_max_stats); - status->vit = cap_value(status->vit,1,battle_config.pet_max_stats); - status->int_= cap_value(status->int_,1,battle_config.pet_max_stats); - status->dex = cap_value(status->dex,1,battle_config.pet_max_stats); - status->luk = cap_value(status->luk,1,battle_config.pet_max_stats); - - status_calc_misc(&pd->bl, &pd->status, lv); - - if (!first) //Not done the first time because the pet is not visible yet - clif_send_petstatus(sd); - } - } else if (first) { - status_calc_misc(&pd->bl, &pd->status, pd->db->lv); - if (!battle_config.pet_lv_rate && pd->pet.level != pd->db->lv) - pd->pet.level = pd->db->lv; - } + nullpo_ret(pd); - //Support rate modifier (1000 = 100%) - pd->rate_fix = 1000*(pd->pet.intimate - battle_config.pet_support_min_friendly)/(1000- battle_config.pet_support_min_friendly) +500; - if (battle_config.pet_support_rate != 100) - pd->rate_fix = pd->rate_fix*battle_config.pet_support_rate/100; + if (first) { + memcpy(&pd->status, &pd->db->status, sizeof(struct status_data)); + pd->status.mode = MD_CANMOVE; // pets discard all modes, except walking + pd->status.speed = pd->petDB->speed; - return 1; + if(battle_config.pet_attack_support || battle_config.pet_damage_support) + {// attack support requires the pet to be able to attack + pd->status.mode|= MD_CANATTACK; + } + } + + if (battle_config.pet_lv_rate && pd->msd) + { + struct map_session_data *sd = pd->msd; + int lv; + + lv =sd->status.base_level*battle_config.pet_lv_rate/100; + if (lv < 0) + lv = 1; + if (lv != pd->pet.level || first) + { + struct status_data *bstat = &pd->db->status, *status = &pd->status; + pd->pet.level = lv; + if (!first) //Lv Up animation + clif_misceffect(&pd->bl, 0); + status->rhw.atk = (bstat->rhw.atk*lv)/pd->db->lv; + status->rhw.atk2 = (bstat->rhw.atk2*lv)/pd->db->lv; + status->str = (bstat->str*lv)/pd->db->lv; + status->agi = (bstat->agi*lv)/pd->db->lv; + status->vit = (bstat->vit*lv)/pd->db->lv; + status->int_ = (bstat->int_*lv)/pd->db->lv; + status->dex = (bstat->dex*lv)/pd->db->lv; + status->luk = (bstat->luk*lv)/pd->db->lv; + + status->rhw.atk = cap_value(status->rhw.atk, 1, battle_config.pet_max_atk1); + status->rhw.atk2 = cap_value(status->rhw.atk2, 2, battle_config.pet_max_atk2); + status->str = cap_value(status->str,1,battle_config.pet_max_stats); + status->agi = cap_value(status->agi,1,battle_config.pet_max_stats); + status->vit = cap_value(status->vit,1,battle_config.pet_max_stats); + status->int_= cap_value(status->int_,1,battle_config.pet_max_stats); + status->dex = cap_value(status->dex,1,battle_config.pet_max_stats); + status->luk = cap_value(status->luk,1,battle_config.pet_max_stats); + + status_calc_misc(&pd->bl, &pd->status, lv); + + if (!first) //Not done the first time because the pet is not visible yet + clif_send_petstatus(sd); + } + } else if (first) { + status_calc_misc(&pd->bl, &pd->status, pd->db->lv); + if (!battle_config.pet_lv_rate && pd->pet.level != pd->db->lv) + pd->pet.level = pd->db->lv; + } + + //Support rate modifier (1000 = 100%) + pd->rate_fix = 1000*(pd->pet.intimate - battle_config.pet_support_min_friendly)/(1000- battle_config.pet_support_min_friendly) +500; + if(battle_config.pet_support_rate != 100) + pd->rate_fix = pd->rate_fix*battle_config.pet_support_rate/100; + + return 1; } /// Helper function for status_base_pc_maxhp(), used to pre-calculate the hp_sigma_val[] array static void status_calc_sigma(void) { - int i,j; - - for (i = 0; i < CLASS_COUNT; i++) { - unsigned int k = 0; - hp_sigma_val[i][0] = hp_sigma_val[i][1] = 0; - for (j = 2; j <= MAX_LEVEL; j++) { - k += (hp_coefficient[i]*j + 50) / 100; - hp_sigma_val[i][j] = k; - if (k >= INT_MAX) - break; //Overflow protection. [Skotlex] - } - for (; j <= MAX_LEVEL; j++) - hp_sigma_val[i][j] = INT_MAX; - } + int i,j; + + for(i = 0; i < CLASS_COUNT; i++) + { + unsigned int k = 0; + hp_sigma_val[i][0] = hp_sigma_val[i][1] = 0; + for(j = 2; j <= MAX_LEVEL; j++) + { + k += (hp_coefficient[i]*j + 50) / 100; + hp_sigma_val[i][j] = k; + if (k >= INT_MAX) + break; //Overflow protection. [Skotlex] + } + for(; j <= MAX_LEVEL; j++) + hp_sigma_val[i][j] = INT_MAX; + } } /// Calculates base MaxHP value according to class and base level @@ -2268,1003 +2252,1010 @@ static void status_calc_sigma(void) /// f(0) = 35 | f(x+1) = f(x) + A + (x + B)*C/D /// which reduces to something close to /// f(x) = 35 + x*(A + B*C/D) + sum(i=2..x){ i*C/D } -static unsigned int status_base_pc_maxhp(struct map_session_data *sd, struct status_data *status) +static unsigned int status_base_pc_maxhp(struct map_session_data* sd, struct status_data* status) { - unsigned int val = pc_class2idx(sd->status.class_); - val = 35 + sd->status.base_level*hp_coefficient2[val]/100 + hp_sigma_val[val][sd->status.base_level]; - - if ((sd->class_&MAPID_UPPERMASK) == MAPID_NINJA || (sd->class_&MAPID_UPPERMASK) == MAPID_GUNSLINGER) - val += 100; //Since their HP can't be approximated well enough without this. - if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON)) - val *= 3; //Triple max HP for top ranking Taekwons over level 90. - if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99) - val += 2000; //Supernovice lvl99 hp bonus. - - val += val * status->vit/100; // +1% per each point of VIT - - if (sd->class_&JOBL_UPPER) - val += val * 25/100; //Trans classes get a 25% hp bonus - else if (sd->class_&JOBL_BABY) - val -= val * 30/100; //Baby classes get a 30% hp penalty - return val; + unsigned int val = pc_class2idx(sd->status.class_); + val = 35 + sd->status.base_level*hp_coefficient2[val]/100 + hp_sigma_val[val][sd->status.base_level]; + + if((sd->class_&MAPID_UPPERMASK) == MAPID_NINJA || (sd->class_&MAPID_UPPERMASK) == MAPID_GUNSLINGER) + val += 100; //Since their HP can't be approximated well enough without this. + if((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON)) + val *= 3; //Triple max HP for top ranking Taekwons over level 90. + if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99) + val += 2000; //Supernovice lvl99 hp bonus. + + val += val * status->vit/100; // +1% per each point of VIT + + if (sd->class_&JOBL_UPPER) + val += val * 25/100; //Trans classes get a 25% hp bonus + else if (sd->class_&JOBL_BABY) + val -= val * 30/100; //Baby classes get a 30% hp penalty + return val; } -static unsigned int status_base_pc_maxsp(struct map_session_data *sd, struct status_data *status) +static unsigned int status_base_pc_maxsp(struct map_session_data* sd, struct status_data *status) { - unsigned int val; + unsigned int val; - val = 10 + sd->status.base_level*sp_coefficient[pc_class2idx(sd->status.class_)]/100; - val += val * status->int_/100; + val = 10 + sd->status.base_level*sp_coefficient[pc_class2idx(sd->status.class_)]/100; + val += val * status->int_/100; - if (sd->class_&JOBL_UPPER) - val += val * 25/100; - else if (sd->class_&JOBL_BABY) - val -= val * 30/100; - if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON)) - val *= 3; //Triple max SP for top ranking Taekwons over level 90. + if (sd->class_&JOBL_UPPER) + val += val * 25/100; + else if (sd->class_&JOBL_BABY) + val -= val * 30/100; + if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON)) + val *= 3; //Triple max SP for top ranking Taekwons over level 90. - return val; + return val; } //Calculates player data from scratch without counting SC adjustments. //Should be invoked whenever players raise stats, learn passive skills or change equipment. -int status_calc_pc_(struct map_session_data *sd, bool first) +int status_calc_pc_(struct map_session_data* sd, bool first) { - static int calculating = 0; //Check for recursive call preemption. [Skotlex] - struct status_data *status; // pointer to the player's base status - const struct status_change *sc = &sd->sc; - struct s_skill b_skill[MAX_SKILL]; // previous skill tree - int b_weight, b_max_weight, b_cart_weight_max; // previous weight - int i,index; - int skill,refinedef=0; - - if (++calculating > 10) //Too many recursive calls! - return -1; - - // remember player-specific values that are currently being shown to the client (for refresh purposes) - memcpy(b_skill, &sd->status.skill, sizeof(b_skill)); - b_weight = sd->weight; - b_max_weight = sd->max_weight; - b_cart_weight_max = sd->cart_weight_max; - - pc_calc_skilltree(sd); // SkillTree calculation - - sd->max_weight = max_weight_base[pc_class2idx(sd->status.class_)]+sd->status.str*300; - - if (first) { - //Load Hp/SP from char-received data. - sd->battle_status.hp = sd->status.hp; - sd->battle_status.sp = sd->status.sp; - sd->regen.sregen = &sd->sregen; - sd->regen.ssregen = &sd->ssregen; - 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_weight=0; - 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++; - } - } - - status = &sd->base_status; - // these are not zeroed. [zzo] - sd->hprate=100; - sd->sprate=100; - sd->castrate=100; - sd->delayrate=100; - sd->dsprate=100; - sd->hprecov_rate = 100; - sd->sprecov_rate = 100; - sd->matk_rate = 100; - 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->regen.state.block = 0; - - // zeroed arrays, order follows the order in pc.h. - // add new arrays to the end of zeroed area in pc.h (see comments) and size here. [zzo] - memset(sd->param_bonus, 0, sizeof(sd->param_bonus) - + sizeof(sd->param_equip) - + sizeof(sd->subele) - + sizeof(sd->subrace) - + sizeof(sd->subrace2) - + sizeof(sd->subsize) - + sizeof(sd->reseff) - + sizeof(sd->weapon_coma_ele) - + sizeof(sd->weapon_coma_race) - + sizeof(sd->weapon_atk) - + sizeof(sd->weapon_atk_rate) - + sizeof(sd->arrow_addele) - + sizeof(sd->arrow_addrace) - + sizeof(sd->arrow_addsize) - + sizeof(sd->magic_addele) - + sizeof(sd->magic_addrace) - + sizeof(sd->magic_addsize) - + sizeof(sd->critaddrace) - + sizeof(sd->expaddrace) - + sizeof(sd->ignore_mdef) - + sizeof(sd->ignore_def) - + sizeof(sd->itemgrouphealrate) - + sizeof(sd->sp_gain_race) - + sizeof(sd->sp_gain_race_attack) - + sizeof(sd->hp_gain_race_attack) - ); - - memset(&sd->right_weapon.overrefine, 0, sizeof(sd->right_weapon) - sizeof(sd->right_weapon.atkmods)); - memset(&sd->left_weapon.overrefine, 0, sizeof(sd->left_weapon) - sizeof(sd->left_weapon.atkmods)); - - if (sd->special_state.intravision && !sd->sc.data[SC_INTRAVISION]) //Clear intravision as long as nothing else is using it - clif_status_load(&sd->bl, SI_INTRAVISION, 0); - - memset(&sd->special_state,0,sizeof(sd->special_state)); - memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp))); - - //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] - status->speed = DEFAULT_WALK_SPEED; - //Give them all modes except these (useful for clones) - status->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK); - - status->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM; - if (battle_config.character_size && pc_isriding(sd)) { //[Lupus] - if (sd->class_&JOBL_BABY) { - if (battle_config.character_size&SZ_BIG) - status->size++; - } else if (battle_config.character_size&SZ_MEDIUM) - status->size++; - } - status->aspd_rate = 1000; - status->ele_lv = 1; - status->race = RC_DEMIHUMAN; - - //zero up structures... - memset(&sd->autospell,0,sizeof(sd->autospell) - + sizeof(sd->autospell2) - + sizeof(sd->autospell3) - + sizeof(sd->addeff) - + sizeof(sd->addeff2) - + sizeof(sd->addeff3) - + sizeof(sd->skillatk) - + sizeof(sd->skillusesprate) - + sizeof(sd->skillusesp) - + sizeof(sd->skillheal) - + sizeof(sd->skillheal2) - + sizeof(sd->hp_loss) - + sizeof(sd->sp_loss) - + sizeof(sd->hp_regen) - + sizeof(sd->sp_regen) - + sizeof(sd->skillblown) - + sizeof(sd->skillcast) - + sizeof(sd->add_def) - + sizeof(sd->add_mdef) - + sizeof(sd->add_mdmg) - + sizeof(sd->add_drop) - + sizeof(sd->itemhealrate) - + sizeof(sd->subele2) - + sizeof(sd->skillcooldown) - + sizeof(sd->skillfixcast) - + sizeof(sd->skillvarcast) - ); - - memset(&sd->bonus, 0,sizeof(sd->bonus)); - - // Autobonus - pc_delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true); - pc_delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus2),true); - pc_delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),true); - - // Parse equipment. - for (i=0; i<EQI_MAX-1; 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 == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) - continue; - if (i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) - continue; - if (i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) - continue; - if (i == EQI_COSTUME_MID && sd->equip_index[EQI_COSTUME_LOW] == index) - continue; - if (i == EQI_COSTUME_TOP && (sd->equip_index[EQI_COSTUME_MID] == index || sd->equip_index[EQI_COSTUME_LOW] == index)) - continue; - if (!sd->inventory_data[index]) - continue; - - status->def += sd->inventory_data[index]->def; - - if (first && sd->inventory_data[index]->equip_script) { - //Execute equip-script on login - run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); - if (!calculating) - return 1; - } + static int calculating = 0; //Check for recursive call preemption. [Skotlex] + struct status_data *status; // pointer to the player's base status + const struct status_change *sc = &sd->sc; + struct s_skill b_skill[MAX_SKILL]; // previous skill tree + int b_weight, b_max_weight, b_cart_weight_max; // previous weight + int i,index; + int skill,refinedef=0; + + if (++calculating > 10) //Too many recursive calls! + return -1; + + // remember player-specific values that are currently being shown to the client (for refresh purposes) + memcpy(b_skill, &sd->status.skill, sizeof(b_skill)); + b_weight = sd->weight; + b_max_weight = sd->max_weight; + b_cart_weight_max = sd->cart_weight_max; + + pc_calc_skilltree(sd); // SkillTree calculation + + sd->max_weight = max_weight_base[pc_class2idx(sd->status.class_)]+sd->status.str*300; + + if(first) { + //Load Hp/SP from char-received data. + sd->battle_status.hp = sd->status.hp; + sd->battle_status.sp = sd->status.sp; + sd->regen.sregen = &sd->sregen; + sd->regen.ssregen = &sd->ssregen; + 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_weight=0; + 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++; + } + } + + status = &sd->base_status; + // these are not zeroed. [zzo] + sd->hprate=100; + sd->sprate=100; + sd->castrate=100; + sd->delayrate=100; + sd->dsprate=100; + sd->hprecov_rate = 100; + sd->sprecov_rate = 100; + sd->matk_rate = 100; + 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->regen.state.block = 0; + + // zeroed arrays, order follows the order in pc.h. + // add new arrays to the end of zeroed area in pc.h (see comments) and size here. [zzo] + memset (sd->param_bonus, 0, sizeof(sd->param_bonus) + + sizeof(sd->param_equip) + + sizeof(sd->subele) + + sizeof(sd->subrace) + + sizeof(sd->subrace2) + + sizeof(sd->subsize) + + sizeof(sd->reseff) + + sizeof(sd->weapon_coma_ele) + + sizeof(sd->weapon_coma_race) + + sizeof(sd->weapon_atk) + + sizeof(sd->weapon_atk_rate) + + sizeof(sd->arrow_addele) + + sizeof(sd->arrow_addrace) + + sizeof(sd->arrow_addsize) + + sizeof(sd->magic_addele) + + sizeof(sd->magic_addrace) + + sizeof(sd->magic_addsize) + + sizeof(sd->critaddrace) + + sizeof(sd->expaddrace) + + sizeof(sd->ignore_mdef) + + sizeof(sd->ignore_def) + + sizeof(sd->itemgrouphealrate) + + sizeof(sd->sp_gain_race) + + sizeof(sd->sp_gain_race_attack) + + sizeof(sd->hp_gain_race_attack) + ); + + memset (&sd->right_weapon.overrefine, 0, sizeof(sd->right_weapon) - sizeof(sd->right_weapon.atkmods)); + memset (&sd->left_weapon.overrefine, 0, sizeof(sd->left_weapon) - sizeof(sd->left_weapon.atkmods)); + + if (sd->special_state.intravision && !sd->sc.data[SC_INTRAVISION]) //Clear intravision as long as nothing else is using it + clif_status_load(&sd->bl, SI_INTRAVISION, 0); + + memset(&sd->special_state,0,sizeof(sd->special_state)); + memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp))); + + //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] + status->speed = DEFAULT_WALK_SPEED; + //Give them all modes except these (useful for clones) + status->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK); + + status->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM; + if (battle_config.character_size && pc_isriding(sd)) { //[Lupus] + if (sd->class_&JOBL_BABY) { + if (battle_config.character_size&SZ_BIG) + status->size++; + } else + if(battle_config.character_size&SZ_MEDIUM) + status->size++; + } + status->aspd_rate = 1000; + status->ele_lv = 1; + status->race = RC_DEMIHUMAN; + + //zero up structures... + memset(&sd->autospell,0,sizeof(sd->autospell) + + sizeof(sd->autospell2) + + sizeof(sd->autospell3) + + sizeof(sd->addeff) + + sizeof(sd->addeff2) + + sizeof(sd->addeff3) + + sizeof(sd->skillatk) + + sizeof(sd->skillusesprate) + + sizeof(sd->skillusesp) + + sizeof(sd->skillheal) + + sizeof(sd->skillheal2) + + sizeof(sd->hp_loss) + + sizeof(sd->sp_loss) + + sizeof(sd->hp_regen) + + sizeof(sd->sp_regen) + + sizeof(sd->skillblown) + + sizeof(sd->skillcast) + + sizeof(sd->add_def) + + sizeof(sd->add_mdef) + + sizeof(sd->add_mdmg) + + sizeof(sd->add_drop) + + sizeof(sd->itemhealrate) + + sizeof(sd->subele2) + + sizeof(sd->skillcooldown) + + sizeof(sd->skillfixcast) + + sizeof(sd->skillvarcast) + ); + + memset (&sd->bonus, 0,sizeof(sd->bonus)); + + // Autobonus + pc_delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true); + pc_delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus2),true); + pc_delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),true); + + // Parse equipment. + for(i=0;i<EQI_MAX-1;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 == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) + continue; + if(i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) + continue; + if(i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) + continue; + if(i == EQI_COSTUME_MID && sd->equip_index[EQI_COSTUME_LOW] == index) + continue; + if(i == EQI_COSTUME_TOP && (sd->equip_index[EQI_COSTUME_MID] == index || sd->equip_index[EQI_COSTUME_LOW] == index)) + continue; + if(!sd->inventory_data[index]) + continue; + + status->def += sd->inventory_data[index]->def; + + if(first && sd->inventory_data[index]->equip_script) + { //Execute equip-script on login + run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); + if (!calculating) + return 1; + } - // sanitize the refine level in case someone decreased the value inbetween - if (sd->status.inventory[index].refine > MAX_REFINE) - sd->status.inventory[index].refine = MAX_REFINE; - - if (sd->inventory_data[index]->type == IT_WEAPON) { - int r,wlv = sd->inventory_data[index]->wlv; - struct weapon_data *wd; - struct weapon_atk *wa; - if (wlv >= REFINE_TYPE_MAX) - wlv = REFINE_TYPE_MAX - 1; - if (i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) { - wd = &sd->left_weapon; // Left-hand weapon - wa = &status->lhw; - } else { - wd = &sd->right_weapon; - wa = &status->rhw; - } - wa->atk += sd->inventory_data[index]->atk; - if ((r = sd->status.inventory[index].refine)) - wa->atk2 = refine_info[wlv].bonus[r-1] / 100; + // sanitize the refine level in case someone decreased the value inbetween + if (sd->status.inventory[index].refine > MAX_REFINE) + sd->status.inventory[index].refine = MAX_REFINE; + + if(sd->inventory_data[index]->type == IT_WEAPON) { + int r,wlv = sd->inventory_data[index]->wlv; + struct weapon_data *wd; + struct weapon_atk *wa; + if (wlv >= REFINE_TYPE_MAX) + wlv = REFINE_TYPE_MAX - 1; + if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) { + wd = &sd->left_weapon; // Left-hand weapon + wa = &status->lhw; + } else { + wd = &sd->right_weapon; + wa = &status->rhw; + } + wa->atk += sd->inventory_data[index]->atk; + if ( (r = sd->status.inventory[index].refine) ) + wa->atk2 = refine_info[wlv].bonus[r-1] / 100; #ifdef RENEWAL - wa->matk += sd->inventory_data[index]->matk; - wa->wlv = wlv; - if( r ) // renewal magic attack refine bonus - wa->matk += refine_info[wlv].bonus[r-1] / 100; -#endif - - //Overrefine bonus. - if (r) - wd->overrefine = refine_info[wlv].randombonus_max[r-1] / 100; - - wa->range += sd->inventory_data[index]->range; - if (sd->inventory_data[index]->script) { - if (wd == &sd->left_weapon) { - sd->state.lr_flag = 1; - run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); - sd->state.lr_flag = 0; - } else - run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); - if (!calculating) //Abort, run_script retriggered this. [Skotlex] - return 1; - } - - if (sd->status.inventory[index].card[0]==CARD0_FORGE) { - // Forged weapon - wd->star += (sd->status.inventory[index].card[1]>>8); - if (wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg - if (pc_famerank(MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH)) - wd->star += 10; - - if (!wa->ele) //Do not overwrite element from previous bonuses. - wa->ele = (sd->status.inventory[index].card[1]&0x0f); - } - } else if (sd->inventory_data[index]->type == IT_ARMOR) { - int r; - if ((r = sd->status.inventory[index].refine)) - refinedef += refine_info[REFINE_TYPE_ARMOR].bonus[r-1]; - if (sd->inventory_data[index]->script) { - if (i == EQI_HAND_L) //Shield - sd->state.lr_flag = 3; - run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); - if (i == EQI_HAND_L) //Shield - sd->state.lr_flag = 0; - if (!calculating) //Abort, run_script retriggered this. [Skotlex] - return 1; - } - } - } - - if (sd->equip_index[EQI_AMMO] >= 0) { - index = sd->equip_index[EQI_AMMO]; - if (sd->inventory_data[index]) { // Arrows - sd->bonus.arrow_atk += sd->inventory_data[index]->atk; - sd->state.lr_flag = 2; - if (!itemdb_is_GNthrowable(sd->inventory_data[index]->nameid)) //don't run scripts on throwable items - run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); - sd->state.lr_flag = 0; - if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex] - return 1; - } - } - - /* we've got combos to process */ - if (sd->combos.count) { - for (i = 0; i < sd->combos.count; i++) { - run_script(sd->combos.bonus[i],0,sd->bl.id,0); - if (!calculating) //Abort, run_script retriggered this. - return 1; - } - } + // in renewal max MATK is the weapon MATK + status->matk_max += sd->inventory_data[index]->matk; - //Store equipment script bonuses - memcpy(sd->param_equip,sd->param_bonus,sizeof(sd->param_equip)); - memset(sd->param_bonus, 0, sizeof(sd->param_bonus)); - - status->def += (refinedef+50)/100; - - //Parse Cards - for (i=0; i<EQI_MAX-1; 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 == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) - continue; - if (i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) - continue; - if (i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) - continue; - - if (sd->inventory_data[index]) { - int j,c; - struct item_data *data; - - //Card script execution. - if (itemdb_isspecial(sd->status.inventory[index].card[0])) - continue; - for (j=0; j<MAX_SLOTS; j++) { // Uses MAX_SLOTS to support Soul Bound system [Inkfish] - current_equip_card_id= c= sd->status.inventory[index].card[j]; - if (!c) - continue; - data = itemdb_exists(c); - if (!data) - continue; - if (first && data->equip_script) { - //Execute equip-script on login - run_script(data->equip_script,0,sd->bl.id,0); - if (!calculating) - return 1; - } - if (!data->script) - continue; - if (data->flag.no_equip) { //Card restriction checks. - if (map[sd->bl.m].flag.restricted && data->flag.no_equip&(8*map[sd->bl.m].zone)) - continue; - if (!map_flag_vs(sd->bl.m) && data->flag.no_equip&1) - continue; - if (map[sd->bl.m].flag.pvp && data->flag.no_equip&2) - continue; - if (map_flag_gvg(sd->bl.m) && data->flag.no_equip&4) - continue; - if (map[sd->bl.m].flag.battleground && data->flag.no_equip&8) - continue; - } - if (i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) { - //Left hand status. - sd->state.lr_flag = 1; - run_script(data->script,0,sd->bl.id,0); - sd->state.lr_flag = 0; - } else - run_script(data->script,0,sd->bl.id,0); - if (!calculating) //Abort, run_script his function. [Skotlex] - return 1; - } - } - } - - if (sc->count && sc->data[SC_ITEMSCRIPT]) { - struct item_data *data = itemdb_exists(sc->data[SC_ITEMSCRIPT]->val1); - if (data && data->script) - run_script(data->script,0,sd->bl.id,0); - } - - if (sd->pd) { - // Pet Bonus - struct pet_data *pd = sd->pd; - if (pd && pd->petDB && pd->petDB->equip_script && pd->pet.intimate >= battle_config.pet_equip_min_friendly) - run_script(pd->petDB->equip_script,0,sd->bl.id,0); - if (pd && pd->pet.intimate > 0 && (!battle_config.pet_equip_required || pd->pet.equip > 0) && pd->state.skillbonus == 1 && pd->bonus) - pc_bonus(sd,pd->bonus->type, pd->bonus->val); - } + if( r ) + {// renewal magic attack refine bonus + status->matk_max += refine_info[wlv].bonus[r-1] / 100; + } - //param_bonus now holds card bonuses. - if (status->rhw.range < 1) status->rhw.range = 1; - if (status->lhw.range < 1) status->lhw.range = 1; - if (status->rhw.range < status->lhw.range) - status->rhw.range = status->lhw.range; - - sd->bonus.double_rate += sd->bonus.double_add_rate; - sd->bonus.perfect_hit += sd->bonus.perfect_hit_add; - sd->bonus.splash_range += sd->bonus.splash_add_range; - - // Damage modifiers from weapon type - sd->right_weapon.atkmods[0] = atkmods[0][sd->weapontype1]; - sd->right_weapon.atkmods[1] = atkmods[1][sd->weapontype1]; - sd->right_weapon.atkmods[2] = atkmods[2][sd->weapontype1]; - sd->left_weapon.atkmods[0] = atkmods[0][sd->weapontype2]; - sd->left_weapon.atkmods[1] = atkmods[1][sd->weapontype2]; - sd->left_weapon.atkmods[2] = atkmods[2][sd->weapontype2]; - - if (pc_isriding(sd) && - (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR)) { - //When Riding with spear, damage modifier to mid-class becomes - //same as versus large size. - sd->right_weapon.atkmods[1] = sd->right_weapon.atkmods[2]; - sd->left_weapon.atkmods[1] = sd->left_weapon.atkmods[2]; - } + // record the weapon level for future usage + status->wlv = wlv; +#endif - // ----- STATS CALCULATION ----- - - // Job bonuses - index = pc_class2idx(sd->status.class_); - for (i=0; i<(int)sd->status.job_level && i<MAX_LEVEL; i++) { - if (!job_bonus[index][i]) - continue; - switch (job_bonus[index][i]) { - case 1: - status->str++; - break; - case 2: - status->agi++; - break; - case 3: - status->vit++; - break; - case 4: - status->int_++; - break; - case 5: - status->dex++; - break; - case 6: - status->luk++; - break; - } - } + //Overrefine bonus. + if (r) + wd->overrefine = refine_info[wlv].randombonus_max[r-1] / 100; + + wa->range += sd->inventory_data[index]->range; + if(sd->inventory_data[index]->script) { + if (wd == &sd->left_weapon) { + sd->state.lr_flag = 1; + run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); + sd->state.lr_flag = 0; + } else + run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); + if (!calculating) //Abort, run_script retriggered this. [Skotlex] + return 1; + } - // If a Super Novice has never died and is at least joblv 70, he gets all stats +10 - if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->die_counter == 0 && sd->status.job_level >= 70) { - status->str += 10; - status->agi += 10; - status->vit += 10; - status->int_+= 10; - status->dex += 10; - status->luk += 10; - } + if(sd->status.inventory[index].card[0]==CARD0_FORGE) + { // Forged weapon + wd->star += (sd->status.inventory[index].card[1]>>8); + if(wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg + if(pc_famerank(MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH)) + wd->star += 10; - // Absolute modifiers from passive skills - if (pc_checkskill(sd,BS_HILTBINDING)>0) - status->str++; - if ((skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0) - status->int_ += (skill+1)/2; // +1 INT / 2 lv - if ((skill=pc_checkskill(sd,AC_OWL))>0) - status->dex += skill; - if ((skill = pc_checkskill(sd,RA_RESEARCHTRAP))>0) - status->int_ += skill; - - // Bonuses from cards and equipment as well as base stat, remember to avoid overflows. - i = status->str + sd->status.str + sd->param_bonus[0] + sd->param_equip[0]; - status->str = cap_value(i,0,USHRT_MAX); - i = status->agi + sd->status.agi + sd->param_bonus[1] + sd->param_equip[1]; - status->agi = cap_value(i,0,USHRT_MAX); - i = status->vit + sd->status.vit + sd->param_bonus[2] + sd->param_equip[2]; - status->vit = cap_value(i,0,USHRT_MAX); - i = status->int_+ sd->status.int_+ sd->param_bonus[3] + sd->param_equip[3]; - status->int_ = cap_value(i,0,USHRT_MAX); - i = status->dex + sd->status.dex + sd->param_bonus[4] + sd->param_equip[4]; - status->dex = cap_value(i,0,USHRT_MAX); - i = status->luk + sd->status.luk + sd->param_bonus[5] + sd->param_equip[5]; - status->luk = cap_value(i,0,USHRT_MAX); - - // ------ BASE ATTACK CALCULATION ------ - - // Base batk value is set on status_calc_misc - // weapon-type bonus (FIXME: Why is the weapon_atk bonus applied to base attack?) - if (sd->status.weapon < MAX_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon]) - status->batk += sd->weapon_atk[sd->status.weapon]; - // Absolute modifiers from passive skills - if ((skill=pc_checkskill(sd,BS_HILTBINDING))>0) - status->batk += 4; - - // ----- HP MAX CALCULATION ----- - - // Basic MaxHP value - //We hold the standard Max HP here to make it faster to recalculate on vit changes. - sd->status.max_hp = status_base_pc_maxhp(sd,status); - //This is done to handle underflows from negative Max HP bonuses - i = sd->status.max_hp + (int)status->max_hp; - status->max_hp = cap_value(i, 0, INT_MAX); - - // Absolute modifiers from passive skills - if ((skill=pc_checkskill(sd,CR_TRUST))>0) - status->max_hp += skill*200; - - // Apply relative modifiers from equipment - if (sd->hprate < 0) - sd->hprate = 0; - if (sd->hprate!=100) - status->max_hp = status->max_hp * sd->hprate/100; - if (battle_config.hp_rate != 100) - status->max_hp = status->max_hp * battle_config.hp_rate/100; - - if (status->max_hp > (unsigned int)battle_config.max_hp) - status->max_hp = battle_config.max_hp; - else if (!status->max_hp) - status->max_hp = 1; - - // ----- SP MAX CALCULATION ----- - - // Basic MaxSP value - sd->status.max_sp = status_base_pc_maxsp(sd,status); - //This is done to handle underflows from negative Max SP bonuses - i = sd->status.max_sp + (int)status->max_sp; - status->max_sp = cap_value(i, 0, INT_MAX); - - // Absolute modifiers from passive skills - if ((skill=pc_checkskill(sd,SL_KAINA))>0) - status->max_sp += 30*skill; - if ((skill=pc_checkskill(sd,HP_MEDITATIO))>0) - status->max_sp += status->max_sp * skill/100; - if ((skill=pc_checkskill(sd,HW_SOULDRAIN))>0) - status->max_sp += status->max_sp * 2*skill/100; - if ((skill = pc_checkskill(sd,RA_RESEARCHTRAP)) > 0) - status->max_sp += 200 + 20 * skill; - if ((skill = pc_checkskill(sd,WM_LESSON)) > 0) - status->max_sp += 30 * skill; - - - // Apply relative modifiers from equipment - if (sd->sprate < 0) - sd->sprate = 0; - if (sd->sprate!=100) - status->max_sp = status->max_sp * sd->sprate/100; - if (battle_config.sp_rate != 100) - status->max_sp = status->max_sp * battle_config.sp_rate/100; - - if (status->max_sp > (unsigned int)battle_config.max_sp) - status->max_sp = battle_config.max_sp; - else if (!status->max_sp) - status->max_sp = 1; - - // ----- RESPAWN HP/SP ----- - // - //Calc respawn hp and store it on base_status - if (sd->special_state.restart_full_recover) { - status->hp = status->max_hp; - status->sp = status->max_sp; - } else { - if ((sd->class_&MAPID_BASEMASK) == MAPID_NOVICE && !(sd->class_&JOBL_2) - && battle_config.restart_hp_rate < 50) - status->hp=status->max_hp>>1; - else - status->hp=status->max_hp * battle_config.restart_hp_rate/100; - if (!status->hp) - status->hp = 1; - - status->sp = status->max_sp * battle_config.restart_sp_rate /100; - - if (!status->sp) /* the minimum for the respawn setting is SP:1 */ - status->sp = 1; - } + if (!wa->ele) //Do not overwrite element from previous bonuses. + wa->ele = (sd->status.inventory[index].card[1]&0x0f); + } + } + else if(sd->inventory_data[index]->type == IT_ARMOR) { + int r; + if ( (r = sd->status.inventory[index].refine) ) + refinedef += refine_info[REFINE_TYPE_ARMOR].bonus[r-1]; + if(sd->inventory_data[index]->script) { + if( i == EQI_HAND_L ) //Shield + sd->state.lr_flag = 3; + run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); + if( i == EQI_HAND_L ) //Shield + sd->state.lr_flag = 0; + if (!calculating) //Abort, run_script retriggered this. [Skotlex] + return 1; + } + } + } + + if(sd->equip_index[EQI_AMMO] >= 0){ + index = sd->equip_index[EQI_AMMO]; + if(sd->inventory_data[index]){ // Arrows + sd->bonus.arrow_atk += sd->inventory_data[index]->atk; + sd->state.lr_flag = 2; + if( !itemdb_is_GNthrowable(sd->inventory_data[index]->nameid) ) //don't run scripts on throwable items + run_script(sd->inventory_data[index]->script,0,sd->bl.id,0); + sd->state.lr_flag = 0; + if (!calculating) //Abort, run_script retriggered status_calc_pc. [Skotlex] + return 1; + } + } + + /* we've got combos to process */ + if( sd->combos.count ) { + for( i = 0; i < sd->combos.count; i++ ) { + run_script(sd->combos.bonus[i],0,sd->bl.id,0); + if (!calculating) //Abort, run_script retriggered this. + return 1; + } + } - // ----- MISC CALCULATION ----- - status_calc_misc(&sd->bl, status, sd->status.base_level); + //Store equipment script bonuses + memcpy(sd->param_equip,sd->param_bonus,sizeof(sd->param_equip)); + memset(sd->param_bonus, 0, sizeof(sd->param_bonus)); - //Equipment modifiers for misc settings - if (sd->matk_rate < 0) - sd->matk_rate = 0; + status->def += (refinedef+50)/100; - if (sd->matk_rate != 100) { - status->matk_max = status->matk_max * sd->matk_rate/100; - status->matk_min = status->matk_min * sd->matk_rate/100; - } +#ifdef RENEWAL + // increment the weapon ATK using the MATK max value + status->matk_max += sd->bonus.sp_weapon_matk; +#endif - if (sd->hit_rate < 0) - sd->hit_rate = 0; - if (sd->hit_rate != 100) - status->hit = status->hit * sd->hit_rate/100; - - if (sd->flee_rate < 0) - sd->flee_rate = 0; - if (sd->flee_rate != 100) - status->flee = status->flee * sd->flee_rate/100; - - if (sd->def2_rate < 0) - sd->def2_rate = 0; - if (sd->def2_rate != 100) - status->def2 = status->def2 * sd->def2_rate/100; - - if (sd->mdef2_rate < 0) - sd->mdef2_rate = 0; - if (sd->mdef2_rate != 100) - status->mdef2 = status->mdef2 * sd->mdef2_rate/100; - - if (sd->critical_rate < 0) - sd->critical_rate = 0; - if (sd->critical_rate != 100) - status->cri = status->cri * sd->critical_rate/100; - - if (sd->flee2_rate < 0) - sd->flee2_rate = 0; - if (sd->flee2_rate != 100) - status->flee2 = status->flee2 * sd->flee2_rate/100; - - // ----- HIT CALCULATION ----- - - // Absolute modifiers from passive skills - if ((skill=pc_checkskill(sd,BS_WEAPONRESEARCH))>0) - status->hit += skill*2; - if ((skill=pc_checkskill(sd,AC_VULTURE))>0) { + //Parse Cards + for(i=0;i<EQI_MAX-1;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 == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) + continue; + if(i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) + continue; + if(i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) + continue; + + if(sd->inventory_data[index]) { + int j,c; + struct item_data *data; + + //Card script execution. + if(itemdb_isspecial(sd->status.inventory[index].card[0])) + continue; + for(j=0;j<MAX_SLOTS;j++){ // Uses MAX_SLOTS to support Soul Bound system [Inkfish] + current_equip_card_id= c= sd->status.inventory[index].card[j]; + if(!c) + continue; + data = itemdb_exists(c); + if(!data) + continue; + if(first && data->equip_script) + { //Execute equip-script on login + run_script(data->equip_script,0,sd->bl.id,0); + if (!calculating) + return 1; + } + if(!data->script) + continue; + if(data->flag.no_equip) { //Card restriction checks. + if(map[sd->bl.m].flag.restricted && data->flag.no_equip&(8*map[sd->bl.m].zone)) + continue; + if(!map_flag_vs(sd->bl.m) && data->flag.no_equip&1) + continue; + if(map[sd->bl.m].flag.pvp && data->flag.no_equip&2) + continue; + if(map_flag_gvg(sd->bl.m) && data->flag.no_equip&4) + continue; + if(map[sd->bl.m].flag.battleground && data->flag.no_equip&8) + continue; + } + if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) + { //Left hand status. + sd->state.lr_flag = 1; + run_script(data->script,0,sd->bl.id,0); + sd->state.lr_flag = 0; + } else + run_script(data->script,0,sd->bl.id,0); + if (!calculating) //Abort, run_script his function. [Skotlex] + return 1; + } + } + } + + if( sc->count && sc->data[SC_ITEMSCRIPT] ) + { + struct item_data *data = itemdb_exists(sc->data[SC_ITEMSCRIPT]->val1); + if( data && data->script ) + run_script(data->script,0,sd->bl.id,0); + } + + if( sd->pd ) + { // Pet Bonus + struct pet_data *pd = sd->pd; + if( pd && pd->petDB && pd->petDB->equip_script && pd->pet.intimate >= battle_config.pet_equip_min_friendly ) + run_script(pd->petDB->equip_script,0,sd->bl.id,0); + if( pd && pd->pet.intimate > 0 && (!battle_config.pet_equip_required || pd->pet.equip > 0) && pd->state.skillbonus == 1 && pd->bonus ) + pc_bonus(sd,pd->bonus->type, pd->bonus->val); + } + + //param_bonus now holds card bonuses. + if(status->rhw.range < 1) status->rhw.range = 1; + if(status->lhw.range < 1) status->lhw.range = 1; + if(status->rhw.range < status->lhw.range) + status->rhw.range = status->lhw.range; + + sd->bonus.double_rate += sd->bonus.double_add_rate; + sd->bonus.perfect_hit += sd->bonus.perfect_hit_add; + sd->bonus.splash_range += sd->bonus.splash_add_range; + + // Damage modifiers from weapon type + sd->right_weapon.atkmods[0] = atkmods[0][sd->weapontype1]; + sd->right_weapon.atkmods[1] = atkmods[1][sd->weapontype1]; + sd->right_weapon.atkmods[2] = atkmods[2][sd->weapontype1]; + sd->left_weapon.atkmods[0] = atkmods[0][sd->weapontype2]; + sd->left_weapon.atkmods[1] = atkmods[1][sd->weapontype2]; + sd->left_weapon.atkmods[2] = atkmods[2][sd->weapontype2]; + + if(pc_isriding(sd) && + (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR)) + { //When Riding with spear, damage modifier to mid-class becomes + //same as versus large size. + sd->right_weapon.atkmods[1] = sd->right_weapon.atkmods[2]; + sd->left_weapon.atkmods[1] = sd->left_weapon.atkmods[2]; + } + +// ----- STATS CALCULATION ----- + + // Job bonuses + index = pc_class2idx(sd->status.class_); + for(i=0;i<(int)sd->status.job_level && i<MAX_LEVEL;i++){ + if(!job_bonus[index][i]) + continue; + switch(job_bonus[index][i]) { + case 1: status->str++; break; + case 2: status->agi++; break; + case 3: status->vit++; break; + case 4: status->int_++; break; + case 5: status->dex++; break; + case 6: status->luk++; break; + } + } + + // If a Super Novice has never died and is at least joblv 70, he gets all stats +10 + if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->die_counter == 0 && sd->status.job_level >= 70){ + status->str += 10; + status->agi += 10; + status->vit += 10; + status->int_+= 10; + status->dex += 10; + status->luk += 10; + } + + // Absolute modifiers from passive skills + if(pc_checkskill(sd,BS_HILTBINDING)>0) + status->str++; + if((skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0) + status->int_ += (skill+1)/2; // +1 INT / 2 lv + if((skill=pc_checkskill(sd,AC_OWL))>0) + status->dex += skill; + if((skill = pc_checkskill(sd,RA_RESEARCHTRAP))>0) + status->int_ += skill; + + // Bonuses from cards and equipment as well as base stat, remember to avoid overflows. + i = status->str + sd->status.str + sd->param_bonus[0] + sd->param_equip[0]; + status->str = cap_value(i,0,USHRT_MAX); + i = status->agi + sd->status.agi + sd->param_bonus[1] + sd->param_equip[1]; + status->agi = cap_value(i,0,USHRT_MAX); + i = status->vit + sd->status.vit + sd->param_bonus[2] + sd->param_equip[2]; + status->vit = cap_value(i,0,USHRT_MAX); + i = status->int_+ sd->status.int_+ sd->param_bonus[3] + sd->param_equip[3]; + status->int_ = cap_value(i,0,USHRT_MAX); + i = status->dex + sd->status.dex + sd->param_bonus[4] + sd->param_equip[4]; + status->dex = cap_value(i,0,USHRT_MAX); + i = status->luk + sd->status.luk + sd->param_bonus[5] + sd->param_equip[5]; + status->luk = cap_value(i,0,USHRT_MAX); + +// ------ BASE ATTACK CALCULATION ------ + + // Base batk value is set on status_calc_misc + // weapon-type bonus (FIXME: Why is the weapon_atk bonus applied to base attack?) + if (sd->status.weapon < MAX_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon]) + status->batk += sd->weapon_atk[sd->status.weapon]; + // Absolute modifiers from passive skills + if((skill=pc_checkskill(sd,BS_HILTBINDING))>0) + status->batk += 4; + +// ----- HP MAX CALCULATION ----- + + // Basic MaxHP value + //We hold the standard Max HP here to make it faster to recalculate on vit changes. + sd->status.max_hp = status_base_pc_maxhp(sd,status); + //This is done to handle underflows from negative Max HP bonuses + i = sd->status.max_hp + (int)status->max_hp; + status->max_hp = cap_value(i, 0, INT_MAX); + + // Absolute modifiers from passive skills + if((skill=pc_checkskill(sd,CR_TRUST))>0) + status->max_hp += skill*200; + + // Apply relative modifiers from equipment + if(sd->hprate < 0) + sd->hprate = 0; + if(sd->hprate!=100) + status->max_hp = status->max_hp * sd->hprate/100; + if(battle_config.hp_rate != 100) + status->max_hp = status->max_hp * battle_config.hp_rate/100; + + if(status->max_hp > (unsigned int)battle_config.max_hp) + status->max_hp = battle_config.max_hp; + else if(!status->max_hp) + status->max_hp = 1; + +// ----- SP MAX CALCULATION ----- + + // Basic MaxSP value + sd->status.max_sp = status_base_pc_maxsp(sd,status); + //This is done to handle underflows from negative Max SP bonuses + i = sd->status.max_sp + (int)status->max_sp; + status->max_sp = cap_value(i, 0, INT_MAX); + + // Absolute modifiers from passive skills + if((skill=pc_checkskill(sd,SL_KAINA))>0) + status->max_sp += 30*skill; + if((skill=pc_checkskill(sd,HP_MEDITATIO))>0) + status->max_sp += status->max_sp * skill/100; + if((skill=pc_checkskill(sd,HW_SOULDRAIN))>0) + status->max_sp += status->max_sp * 2*skill/100; + if( (skill = pc_checkskill(sd,RA_RESEARCHTRAP)) > 0 ) + status->max_sp += 200 + 20 * skill; + if( (skill = pc_checkskill(sd,WM_LESSON)) > 0 ) + status->max_sp += 30 * skill; + + + // Apply relative modifiers from equipment + if(sd->sprate < 0) + sd->sprate = 0; + if(sd->sprate!=100) + status->max_sp = status->max_sp * sd->sprate/100; + if(battle_config.sp_rate != 100) + status->max_sp = status->max_sp * battle_config.sp_rate/100; + + if(status->max_sp > (unsigned int)battle_config.max_sp) + status->max_sp = battle_config.max_sp; + else if(!status->max_sp) + status->max_sp = 1; + +// ----- RESPAWN HP/SP ----- +// + //Calc respawn hp and store it on base_status + if (sd->special_state.restart_full_recover) + { + status->hp = status->max_hp; + status->sp = status->max_sp; + } else { + if((sd->class_&MAPID_BASEMASK) == MAPID_NOVICE && !(sd->class_&JOBL_2) + && battle_config.restart_hp_rate < 50) + status->hp=status->max_hp>>1; + else + status->hp=status->max_hp * battle_config.restart_hp_rate/100; + if(!status->hp) + status->hp = 1; + + status->sp = status->max_sp * battle_config.restart_sp_rate /100; + + if( !status->sp ) /* the minimum for the respawn setting is SP:1 */ + status->sp = 1; + } + +// ----- MISC CALCULATION ----- + status_calc_misc(&sd->bl, status, sd->status.base_level); + + //Equipment modifiers for misc settings + if(sd->matk_rate < 0) + sd->matk_rate = 0; + + if(sd->matk_rate != 100){ + status->matk_max = status->matk_max * sd->matk_rate/100; + status->matk_min = status->matk_min * sd->matk_rate/100; + } + + if(sd->hit_rate < 0) + sd->hit_rate = 0; + if(sd->hit_rate != 100) + status->hit = status->hit * sd->hit_rate/100; + + if(sd->flee_rate < 0) + sd->flee_rate = 0; + if(sd->flee_rate != 100) + status->flee = status->flee * sd->flee_rate/100; + + if(sd->def2_rate < 0) + sd->def2_rate = 0; + if(sd->def2_rate != 100) + status->def2 = status->def2 * sd->def2_rate/100; + + if(sd->mdef2_rate < 0) + sd->mdef2_rate = 0; + if(sd->mdef2_rate != 100) + status->mdef2 = status->mdef2 * sd->mdef2_rate/100; + + if(sd->critical_rate < 0) + sd->critical_rate = 0; + if(sd->critical_rate != 100) + status->cri = status->cri * sd->critical_rate/100; + + if(sd->flee2_rate < 0) + sd->flee2_rate = 0; + if(sd->flee2_rate != 100) + status->flee2 = status->flee2 * sd->flee2_rate/100; + +// ----- HIT CALCULATION ----- + + // Absolute modifiers from passive skills + if((skill=pc_checkskill(sd,BS_WEAPONRESEARCH))>0) + status->hit += skill*2; + if((skill=pc_checkskill(sd,AC_VULTURE))>0){ #ifndef RENEWAL - status->hit += skill; + status->hit += skill; #endif - if (sd->status.weapon == W_BOW) - status->rhw.range += skill; - } - if (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE) { - if ((skill=pc_checkskill(sd,GS_SINGLEACTION))>0) - status->hit += 2*skill; - if ((skill=pc_checkskill(sd,GS_SNAKEEYE))>0) { - status->hit += skill; - status->rhw.range += skill; - } - } + if(sd->status.weapon == W_BOW) + status->rhw.range += skill; + } + if(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE) + { + if((skill=pc_checkskill(sd,GS_SINGLEACTION))>0) + status->hit += 2*skill; + if((skill=pc_checkskill(sd,GS_SNAKEEYE))>0) { + status->hit += skill; + status->rhw.range += skill; + } + } - // ----- FLEE CALCULATION ----- - - // Absolute modifiers from passive skills - if ((skill=pc_checkskill(sd,TF_MISS))>0) - status->flee += skill*(sd->class_&JOBL_2 && (sd->class_&MAPID_BASEMASK) == MAPID_THIEF? 4 : 3); - if ((skill=pc_checkskill(sd,MO_DODGE))>0) - status->flee += (skill*3)>>1; - // ----- EQUIPMENT-DEF CALCULATION ----- - - // Apply relative modifiers from equipment - if (sd->def_rate < 0) - sd->def_rate = 0; - if (sd->def_rate != 100) { - i = status->def * sd->def_rate/100; - status->def = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX); - } +// ----- FLEE CALCULATION ----- + + // Absolute modifiers from passive skills + if((skill=pc_checkskill(sd,TF_MISS))>0) + status->flee += skill*(sd->class_&JOBL_2 && (sd->class_&MAPID_BASEMASK) == MAPID_THIEF? 4 : 3); + if((skill=pc_checkskill(sd,MO_DODGE))>0) + status->flee += (skill*3)>>1; +// ----- EQUIPMENT-DEF CALCULATION ----- + + // Apply relative modifiers from equipment + if(sd->def_rate < 0) + sd->def_rate = 0; + if(sd->def_rate != 100) { + i = status->def * sd->def_rate/100; + status->def = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX); + } #ifndef RENEWAL - if (!battle_config.weapon_defense_type && status->def > battle_config.max_def) { - status->def2 += battle_config.over_def_bonus*(status->def -battle_config.max_def); - status->def = (unsigned char)battle_config.max_def; - } + if (!battle_config.weapon_defense_type && status->def > battle_config.max_def) + { + status->def2 += battle_config.over_def_bonus*(status->def -battle_config.max_def); + status->def = (unsigned char)battle_config.max_def; + } #endif - // ----- EQUIPMENT-MDEF CALCULATION ----- +// ----- EQUIPMENT-MDEF CALCULATION ----- - // Apply relative modifiers from equipment - if (sd->mdef_rate < 0) - sd->mdef_rate = 0; - if (sd->mdef_rate != 100) { - i = status->mdef * sd->mdef_rate/100; - status->mdef = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX); - } + // Apply relative modifiers from equipment + if(sd->mdef_rate < 0) + sd->mdef_rate = 0; + if(sd->mdef_rate != 100) { + i = status->mdef * sd->mdef_rate/100; + status->mdef = cap_value(i, DEFTYPE_MIN, DEFTYPE_MAX); + } #ifndef RENEWAL - if (!battle_config.magic_defense_type && status->mdef > battle_config.max_def) { - status->mdef2 += battle_config.over_def_bonus*(status->mdef -battle_config.max_def); - status->mdef = (signed char)battle_config.max_def; - } + if (!battle_config.magic_defense_type && status->mdef > battle_config.max_def) + { + status->mdef2 += battle_config.over_def_bonus*(status->mdef -battle_config.max_def); + status->mdef = (signed char)battle_config.max_def; + } #endif - // ----- ASPD CALCULATION ----- - // Unlike other stats, ASPD rate modifiers from skills/SCs/items/etc are first all added together, then the final modifier is applied +// ----- ASPD CALCULATION ----- +// Unlike other stats, ASPD rate modifiers from skills/SCs/items/etc are first all added together, then the final modifier is applied - // Basic ASPD value - i = status_base_amotion_pc(sd,status); - status->amotion = cap_value(i,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000); + // Basic ASPD value + i = status_base_amotion_pc(sd,status); + status->amotion = cap_value(i,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000); - // Relative modifiers from passive skills + // Relative modifiers from passive skills #ifndef RENEWAL_ASPD - if ((skill=pc_checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK) - status->aspd_rate -= 5*skill; - if ((skill = pc_checkskill(sd,SG_DEVIL)) > 0 && !pc_nextjobexp(sd)) - status->aspd_rate -= 30*skill; - if ((skill=pc_checkskill(sd,GS_SINGLEACTION))>0 && - (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) - status->aspd_rate -= ((skill+1)/2) * 10; - if (pc_isriding(sd)) - status->aspd_rate += 500-100*pc_checkskill(sd,KN_CAVALIERMASTERY); - else if (pc_isridingdragon(sd)) - status->aspd_rate += 250-50*pc_checkskill(sd,RK_DRAGONTRAINING); + if((skill=pc_checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK) + status->aspd_rate -= 5*skill; + if((skill = pc_checkskill(sd,SG_DEVIL)) > 0 && !pc_nextjobexp(sd)) + status->aspd_rate -= 30*skill; + if((skill=pc_checkskill(sd,GS_SINGLEACTION))>0 && + (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) + status->aspd_rate -= ((skill+1)/2) * 10; + if(pc_isriding(sd)) + status->aspd_rate += 500-100*pc_checkskill(sd,KN_CAVALIERMASTERY); + else if(pc_isridingdragon(sd)) + status->aspd_rate += 250-50*pc_checkskill(sd,RK_DRAGONTRAINING); #else // needs more info - if ((skill=pc_checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK) - status->aspd_rate += 5*skill; - if ((skill = pc_checkskill(sd,SG_DEVIL)) > 0 && !pc_nextjobexp(sd)) - status->aspd_rate += 30*skill; - if ((skill=pc_checkskill(sd,GS_SINGLEACTION))>0 && - (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) - status->aspd_rate += ((skill+1)/2) * 10; - if (pc_isriding(sd)) - status->aspd_rate -= 500-100*pc_checkskill(sd,KN_CAVALIERMASTERY); - else if (pc_isridingdragon(sd)) - status->aspd_rate -= 250-50*pc_checkskill(sd,RK_DRAGONTRAINING); + if((skill=pc_checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK) + status->aspd_rate += 5*skill; + if((skill = pc_checkskill(sd,SG_DEVIL)) > 0 && !pc_nextjobexp(sd)) + status->aspd_rate += 30*skill; + if((skill=pc_checkskill(sd,GS_SINGLEACTION))>0 && + (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) + status->aspd_rate += ((skill+1)/2) * 10; + if(pc_isriding(sd)) + status->aspd_rate -= 500-100*pc_checkskill(sd,KN_CAVALIERMASTERY); + else if(pc_isridingdragon(sd)) + status->aspd_rate -= 250-50*pc_checkskill(sd,RK_DRAGONTRAINING); #endif - status->adelay = 2*status->amotion; - - - // ----- DMOTION ----- - // - i = 800-status->agi*4; - status->dmotion = cap_value(i, 400, 800); - if (battle_config.pc_damage_delay_rate != 100) - status->dmotion = status->dmotion*battle_config.pc_damage_delay_rate/100; - - // ----- MISC CALCULATIONS ----- - - // Weight - if ((skill=pc_checkskill(sd,MC_INCCARRY))>0) - sd->max_weight += 2000*skill; - if (pc_isriding(sd) && pc_checkskill(sd,KN_RIDING)>0) - sd->max_weight += 10000; - else if (pc_isridingdragon(sd)) - sd->max_weight += 5000+2000*pc_checkskill(sd,RK_DRAGONTRAINING); - if (sc->data[SC_KNOWLEDGE]) - sd->max_weight += sd->max_weight*sc->data[SC_KNOWLEDGE]->val1/10; - if ((skill=pc_checkskill(sd,ALL_INCCARRY))>0) - sd->max_weight += 2000*skill; - - sd->cart_weight_max = battle_config.max_cart_weight + (pc_checkskill(sd, GN_REMODELING_CART)*5000); - - if (pc_checkskill(sd,SM_MOVINGRECOVERY)>0) - sd->regen.state.walk = 1; - else - sd->regen.state.walk = 0; - - // Skill SP cost - if ((skill=pc_checkskill(sd,HP_MANARECHARGE))>0) - sd->dsprate -= 4*skill; - - if (sc->data[SC_SERVICE4U]) - sd->dsprate -= sc->data[SC_SERVICE4U]->val3; - - if (sc->data[SC_SPCOST_RATE]) - sd->dsprate -= sc->data[SC_SPCOST_RATE]->val1; - - //Underflow protections. - if (sd->dsprate < 0) - sd->dsprate = 0; - if (sd->castrate < 0) - sd->castrate = 0; - if (sd->delayrate < 0) - sd->delayrate = 0; - if (sd->hprecov_rate < 0) - sd->hprecov_rate = 0; - if (sd->sprecov_rate < 0) - sd->sprecov_rate = 0; - - // Anti-element and anti-race - if ((skill=pc_checkskill(sd,CR_TRUST))>0) - sd->subele[ELE_HOLY] += skill*5; - if ((skill=pc_checkskill(sd,BS_SKINTEMPER))>0) { - sd->subele[ELE_NEUTRAL] += skill; - sd->subele[ELE_FIRE] += skill*4; - } - if ((skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0) { - skill = skill*4; - sd->right_weapon.addrace[RC_DRAGON]+=skill; - sd->left_weapon.addrace[RC_DRAGON]+=skill; - sd->magic_addrace[RC_DRAGON]+=skill; - sd->subrace[RC_DRAGON]+=skill; - } - - if (sc->count) { - if (sc->data[SC_CONCENTRATE]) { //Update the card-bonus data - sc->data[SC_CONCENTRATE]->val3 = sd->param_bonus[1]; //Agi - sc->data[SC_CONCENTRATE]->val4 = sd->param_bonus[4]; //Dex - } - if (sc->data[SC_SIEGFRIED]) { - i = sc->data[SC_SIEGFRIED]->val2; - sd->subele[ELE_WATER] += i; - sd->subele[ELE_EARTH] += i; - sd->subele[ELE_FIRE] += i; - sd->subele[ELE_WIND] += i; - sd->subele[ELE_POISON] += i; - sd->subele[ELE_HOLY] += i; - sd->subele[ELE_DARK] += i; - sd->subele[ELE_GHOST] += i; - sd->subele[ELE_UNDEAD] += i; - } - if (sc->data[SC_PROVIDENCE]) { - sd->subele[ELE_HOLY] += sc->data[SC_PROVIDENCE]->val2; - sd->subrace[RC_DEMON] += sc->data[SC_PROVIDENCE]->val2; - } - if (sc->data[SC_ARMOR_ELEMENT]) { //This status change should grant card-type elemental resist. - sd->subele[ELE_WATER] += sc->data[SC_ARMOR_ELEMENT]->val1; - sd->subele[ELE_EARTH] += sc->data[SC_ARMOR_ELEMENT]->val2; - sd->subele[ELE_FIRE] += sc->data[SC_ARMOR_ELEMENT]->val3; - sd->subele[ELE_WIND] += sc->data[SC_ARMOR_ELEMENT]->val4; - } - if (sc->data[SC_ARMOR_RESIST]) { // Undead Scroll - sd->subele[ELE_WATER] += sc->data[SC_ARMOR_RESIST]->val1; - sd->subele[ELE_EARTH] += sc->data[SC_ARMOR_RESIST]->val2; - sd->subele[ELE_FIRE] += sc->data[SC_ARMOR_RESIST]->val3; - sd->subele[ELE_WIND] += sc->data[SC_ARMOR_RESIST]->val4; - } - if (sc->data[SC_FIRE_CLOAK_OPTION]) { - i = sc->data[SC_FIRE_CLOAK_OPTION]->val2; - sd->subele[ELE_FIRE] += i; - sd->subele[ELE_EARTH] -= i; - } - if (sc->data[SC_WATER_DROP_OPTION]) { - i = sc->data[SC_WATER_DROP_OPTION]->val2; - sd->subele[ELE_WATER] += i; - sd->subele[ELE_WIND] -= i; - } - if (sc->data[SC_WIND_CURTAIN_OPTION]) { - i = sc->data[SC_WIND_CURTAIN_OPTION]->val2; - sd->subele[ELE_WIND] += i; - sd->subele[ELE_WATER] -= i; - } - if (sc->data[SC_STONE_SHIELD_OPTION]) { - i = sc->data[SC_STONE_SHIELD_OPTION]->val2; - sd->subele[ELE_EARTH] += i; - sd->subele[ELE_FIRE] -= i; - } - if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3) - sd->magic_addele[ELE_FIRE] += 25; - if (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3) - sd->magic_addele[ELE_WATER] += 25; - if (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 3) - sd->magic_addele[ELE_WIND] += 25; - if (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3) - sd->magic_addele[ELE_EARTH] += 25; - } - status_cpy(&sd->battle_status, status); - - // ----- CLIENT-SIDE REFRESH ----- - if (!sd->bl.prev) { - //Will update on LoadEndAck - calculating = 0; - return 0; - } - if (memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill))) - clif_skillinfoblock(sd); - if (b_weight != sd->weight) - clif_updatestatus(sd,SP_WEIGHT); - if (b_max_weight != sd->max_weight) { - clif_updatestatus(sd,SP_MAXWEIGHT); - pc_updateweightstatus(sd); - } - if (b_cart_weight_max != sd->cart_weight_max) { - clif_updatestatus(sd,SP_CARTINFO); - } - - calculating = 0; - - return 0; + status->adelay = 2*status->amotion; + + +// ----- DMOTION ----- +// + i = 800-status->agi*4; + status->dmotion = cap_value(i, 400, 800); + if(battle_config.pc_damage_delay_rate != 100) + status->dmotion = status->dmotion*battle_config.pc_damage_delay_rate/100; + +// ----- MISC CALCULATIONS ----- + + // Weight + if((skill=pc_checkskill(sd,MC_INCCARRY))>0) + sd->max_weight += 2000*skill; + if(pc_isriding(sd) && pc_checkskill(sd,KN_RIDING)>0) + sd->max_weight += 10000; + else if(pc_isridingdragon(sd)) + sd->max_weight += 5000+2000*pc_checkskill(sd,RK_DRAGONTRAINING); + if(sc->data[SC_KNOWLEDGE]) + sd->max_weight += sd->max_weight*sc->data[SC_KNOWLEDGE]->val1/10; + if((skill=pc_checkskill(sd,ALL_INCCARRY))>0) + sd->max_weight += 2000*skill; + + sd->cart_weight_max = battle_config.max_cart_weight + (pc_checkskill(sd, GN_REMODELING_CART)*5000); + + if (pc_checkskill(sd,SM_MOVINGRECOVERY)>0) + sd->regen.state.walk = 1; + else + sd->regen.state.walk = 0; + + // Skill SP cost + if((skill=pc_checkskill(sd,HP_MANARECHARGE))>0 ) + sd->dsprate -= 4*skill; + + if(sc->data[SC_SERVICE4U]) + sd->dsprate -= sc->data[SC_SERVICE4U]->val3; + + if(sc->data[SC_SPCOST_RATE]) + sd->dsprate -= sc->data[SC_SPCOST_RATE]->val1; + + //Underflow protections. + if(sd->dsprate < 0) + sd->dsprate = 0; + if(sd->castrate < 0) + sd->castrate = 0; + if(sd->delayrate < 0) + sd->delayrate = 0; + if(sd->hprecov_rate < 0) + sd->hprecov_rate = 0; + if(sd->sprecov_rate < 0) + sd->sprecov_rate = 0; + + // Anti-element and anti-race + if((skill=pc_checkskill(sd,CR_TRUST))>0) + sd->subele[ELE_HOLY] += skill*5; + if((skill=pc_checkskill(sd,BS_SKINTEMPER))>0) { + sd->subele[ELE_NEUTRAL] += skill; + sd->subele[ELE_FIRE] += skill*4; + } + if((skill=pc_checkskill(sd,SA_DRAGONOLOGY))>0 ){ + skill = skill*4; + sd->right_weapon.addrace[RC_DRAGON]+=skill; + sd->left_weapon.addrace[RC_DRAGON]+=skill; + sd->magic_addrace[RC_DRAGON]+=skill; + sd->subrace[RC_DRAGON]+=skill; + } + + if(sc->count){ + if(sc->data[SC_CONCENTRATE]) { //Update the card-bonus data + sc->data[SC_CONCENTRATE]->val3 = sd->param_bonus[1]; //Agi + sc->data[SC_CONCENTRATE]->val4 = sd->param_bonus[4]; //Dex + } + if(sc->data[SC_SIEGFRIED]){ + i = sc->data[SC_SIEGFRIED]->val2; + sd->subele[ELE_WATER] += i; + sd->subele[ELE_EARTH] += i; + sd->subele[ELE_FIRE] += i; + sd->subele[ELE_WIND] += i; + sd->subele[ELE_POISON] += i; + sd->subele[ELE_HOLY] += i; + sd->subele[ELE_DARK] += i; + sd->subele[ELE_GHOST] += i; + sd->subele[ELE_UNDEAD] += i; + } + if(sc->data[SC_PROVIDENCE]){ + sd->subele[ELE_HOLY] += sc->data[SC_PROVIDENCE]->val2; + sd->subrace[RC_DEMON] += sc->data[SC_PROVIDENCE]->val2; + } + if(sc->data[SC_ARMOR_ELEMENT]) { //This status change should grant card-type elemental resist. + sd->subele[ELE_WATER] += sc->data[SC_ARMOR_ELEMENT]->val1; + sd->subele[ELE_EARTH] += sc->data[SC_ARMOR_ELEMENT]->val2; + sd->subele[ELE_FIRE] += sc->data[SC_ARMOR_ELEMENT]->val3; + sd->subele[ELE_WIND] += sc->data[SC_ARMOR_ELEMENT]->val4; + } + if(sc->data[SC_ARMOR_RESIST]) { // Undead Scroll + sd->subele[ELE_WATER] += sc->data[SC_ARMOR_RESIST]->val1; + sd->subele[ELE_EARTH] += sc->data[SC_ARMOR_RESIST]->val2; + sd->subele[ELE_FIRE] += sc->data[SC_ARMOR_RESIST]->val3; + sd->subele[ELE_WIND] += sc->data[SC_ARMOR_RESIST]->val4; + } + if( sc->data[SC_FIRE_CLOAK_OPTION] ) { + i = sc->data[SC_FIRE_CLOAK_OPTION]->val2; + sd->subele[ELE_FIRE] += i; + sd->subele[ELE_EARTH] -= i; + } + if( sc->data[SC_WATER_DROP_OPTION] ) { + i = sc->data[SC_WATER_DROP_OPTION]->val2; + sd->subele[ELE_WATER] += i; + sd->subele[ELE_WIND] -= i; + } + if( sc->data[SC_WIND_CURTAIN_OPTION] ) { + i = sc->data[SC_WIND_CURTAIN_OPTION]->val2; + sd->subele[ELE_WIND] += i; + sd->subele[ELE_WATER] -= i; + } + if( sc->data[SC_STONE_SHIELD_OPTION] ) { + i = sc->data[SC_STONE_SHIELD_OPTION]->val2; + sd->subele[ELE_EARTH] += i; + sd->subele[ELE_FIRE] -= i; + } + if( sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3 ) + sd->magic_addele[ELE_FIRE] += 25; + if( sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3 ) + sd->magic_addele[ELE_WATER] += 25; + if( sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 3 ) + sd->magic_addele[ELE_WIND] += 25; + if( sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3 ) + sd->magic_addele[ELE_EARTH] += 25; + } + status_cpy(&sd->battle_status, status); + +// ----- CLIENT-SIDE REFRESH ----- + if(!sd->bl.prev) { + //Will update on LoadEndAck + calculating = 0; + return 0; + } + if(memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill))) + clif_skillinfoblock(sd); + if(b_weight != sd->weight) + clif_updatestatus(sd,SP_WEIGHT); + if(b_max_weight != sd->max_weight) { + clif_updatestatus(sd,SP_MAXWEIGHT); + pc_updateweightstatus(sd); + } + if( b_cart_weight_max != sd->cart_weight_max ) { + clif_updatestatus(sd,SP_CARTINFO); + } + + calculating = 0; + + return 0; } int status_calc_mercenary_(struct mercenary_data *md, bool first) { - struct status_data *status = &md->base_status; - struct s_mercenary *merc = &md->mercenary; - - if (first) { - memcpy(status, &md->db->status, sizeof(struct status_data)); - status->mode = MD_CANMOVE|MD_CANATTACK; - status->hp = status->max_hp; - status->sp = status->max_sp; - md->battle_status.hp = merc->hp; - md->battle_status.sp = merc->sp; - } - - status_calc_misc(&md->bl, status, md->db->lv); - status_cpy(&md->battle_status, status); - - return 0; + struct status_data *status = &md->base_status; + struct s_mercenary *merc = &md->mercenary; + + if( first ) + { + memcpy(status, &md->db->status, sizeof(struct status_data)); + status->mode = MD_CANMOVE|MD_CANATTACK; + status->hp = status->max_hp; + status->sp = status->max_sp; + md->battle_status.hp = merc->hp; + md->battle_status.sp = merc->sp; + } + + status_calc_misc(&md->bl, status, md->db->lv); + status_cpy(&md->battle_status, status); + + return 0; } int status_calc_homunculus_(struct homun_data *hd, bool first) { - struct status_data *status = &hd->base_status; - struct s_homunculus *hom = &hd->homunculus; - int skill; - int amotion; - - status->str = hom->str / 10; - status->agi = hom->agi / 10; - status->vit = hom->vit / 10; - status->dex = hom->dex / 10; - status->int_ = hom->int_ / 10; - status->luk = hom->luk / 10; - - if (first) { //[orn] - const struct s_homunculus_db *db = hd->homunculusDB; - status->def_ele = db->element; - status->ele_lv = 1; - status->race = db->race; - status->size = (hom->class_ == db->evo_class)?db->evo_size:db->base_size; - status->rhw.range = 1 + status->size; - status->mode = MD_CANMOVE|MD_CANATTACK; - status->speed = DEFAULT_WALK_SPEED; - if (battle_config.hom_setting&0x8 && hd->master) - status->speed = status_get_speed(&hd->master->bl); - - status->hp = 1; - status->sp = 1; - } - skill = hom->level/10 + status->vit/5; - status->def = cap_value(skill, 0, 99); - - skill = hom->level/10 + status->int_/5; - status->mdef = cap_value(skill, 0, 99); - - status->max_hp = hom->max_hp ; - status->max_sp = hom->max_sp ; - - merc_hom_calc_skilltree(hd, 0); - - if ((skill=merc_hom_checkskill(hd,HAMI_SKIN)) > 0) - status->def += skill * 4; - - if ((skill = merc_hom_checkskill(hd,HVAN_INSTRUCT)) > 0) { - status->int_ += 1 +skill/2 +skill/4 +skill/5; - status->str += 1 +skill/3 +skill/3 +skill/4; - } - - if ((skill=merc_hom_checkskill(hd,HAMI_SKIN)) > 0) - status->max_hp += skill * 2 * status->max_hp / 100; - - if ((skill = merc_hom_checkskill(hd,HLIF_BRAIN)) > 0) - status->max_sp += (1 +skill/2 -skill/4 +skill/5) * status->max_sp / 100 ; - - if (first) { - hd->battle_status.hp = hom->hp ; - hd->battle_status.sp = hom->sp ; - } - - status->rhw.atk = status->dex; - status->rhw.atk2 = status->str + hom->level; - - status->aspd_rate = 1000; - - amotion = (1000 -4*status->agi -status->dex) * hd->homunculusDB->baseASPD/1000; - status->amotion = cap_value(amotion,battle_config.max_aspd,2000); - status->adelay = status->amotion; //It seems adelay = amotion for Homunculus. - - status_calc_misc(&hd->bl, status, hom->level); + struct status_data *status = &hd->base_status; + struct s_homunculus *hom = &hd->homunculus; + int skill; + int amotion; + + status->str = hom->str / 10; + status->agi = hom->agi / 10; + status->vit = hom->vit / 10; + status->dex = hom->dex / 10; + status->int_ = hom->int_ / 10; + status->luk = hom->luk / 10; + + if (first) { //[orn] + const struct s_homunculus_db *db = hd->homunculusDB; + status->def_ele = db->element; + status->ele_lv = 1; + status->race = db->race; + status->size = (hom->class_ == db->evo_class)?db->evo_size:db->base_size; + status->rhw.range = 1 + status->size; + status->mode = MD_CANMOVE|MD_CANATTACK; + status->speed = DEFAULT_WALK_SPEED; + if (battle_config.hom_setting&0x8 && hd->master) + status->speed = status_get_speed(&hd->master->bl); + + status->hp = 1; + status->sp = 1; + } + skill = hom->level/10 + status->vit/5; + status->def = cap_value(skill, 0, 99); + + skill = hom->level/10 + status->int_/5; + status->mdef = cap_value(skill, 0, 99); + + status->max_hp = hom->max_hp ; + status->max_sp = hom->max_sp ; + + merc_hom_calc_skilltree(hd, 0); + + if((skill=merc_hom_checkskill(hd,HAMI_SKIN)) > 0) + status->def += skill * 4; + + if((skill = merc_hom_checkskill(hd,HVAN_INSTRUCT)) > 0) + { + status->int_ += 1 +skill/2 +skill/4 +skill/5; + status->str += 1 +skill/3 +skill/3 +skill/4; + } + + if((skill=merc_hom_checkskill(hd,HAMI_SKIN)) > 0) + status->max_hp += skill * 2 * status->max_hp / 100; + + if((skill = merc_hom_checkskill(hd,HLIF_BRAIN)) > 0) + status->max_sp += (1 +skill/2 -skill/4 +skill/5) * status->max_sp / 100 ; + + if (first) { + hd->battle_status.hp = hom->hp ; + hd->battle_status.sp = hom->sp ; + } + + status->rhw.atk = status->dex; + status->rhw.atk2 = status->str + hom->level; + + status->aspd_rate = 1000; + + amotion = (1000 -4*status->agi -status->dex) * hd->homunculusDB->baseASPD/1000; + status->amotion = cap_value(amotion,battle_config.max_aspd,2000); + status->adelay = status->amotion; //It seems adelay = amotion for Homunculus. + + status_calc_misc(&hd->bl, status, hom->level); #ifdef RENEWAL - status->matk_max = status->matk_min; + status->matk_max = status->matk_min; #endif - status_cpy(&hd->battle_status, status); - return 1; + status_cpy(&hd->battle_status, status); + return 1; } -int status_calc_elemental_(struct elemental_data *ed, bool first) -{ - struct status_data *status = &ed->base_status; - struct s_elemental *ele = &ed->elemental; - struct map_session_data *sd = ed->master; - - if (!sd) - return 0; - - status->str = ele->str; - status->agi = ele->agi; - status->vit = ele->vit; - status->dex = ele->dex; - status->int_ = ele->int_; - status->luk = ele->luk; - - if (first) { - memcpy(status, &ed->db->status, sizeof(struct status_data)); - status->mode = MD_CANMOVE|MD_CANATTACK; - status->max_hp += 4000 + 500 * pc_checkskill(sd,SO_EL_SYMPATHY); - status->max_sp += 300 + 50 * pc_checkskill(sd,SO_EL_SYMPATHY); - status->hp = status->max_hp; - status->sp = status->max_sp; - status->str += sd->base_status.str * 25 / 100; - status->agi += sd->base_status.agi * 25 / 100; - status->vit += sd->base_status.vit * 25 / 100; - status->int_ += sd->base_status.int_ * 25 / 100; - status->def += sd->base_status.dex * 25 / 100; - status->luk += sd->base_status.luk * 25 / 100; - - status_calc_misc(&ed->bl, status, ed->db->lv); - memcpy(&ed->battle_status,status,sizeof(struct status_data)); - } else { - status_calc_misc(&ed->bl, status, ed->db->lv); - status_cpy(&ed->battle_status, status); - } - - return 0; +int status_calc_elemental_(struct elemental_data *ed, bool first) { + struct status_data *status = &ed->base_status; + struct s_elemental *ele = &ed->elemental; + struct map_session_data *sd = ed->master; + + if( !sd ) + return 0; + + status->str = ele->str; + status->agi = ele->agi; + status->vit = ele->vit; + status->dex = ele->dex; + status->int_ = ele->int_; + status->luk = ele->luk; + + if( first ) { + memcpy(status, &ed->db->status, sizeof(struct status_data)); + status->mode = MD_CANMOVE|MD_CANATTACK; + status->max_hp += 4000 + 500 * pc_checkskill(sd,SO_EL_SYMPATHY); + status->max_sp += 300 + 50 * pc_checkskill(sd,SO_EL_SYMPATHY); + status->hp = status->max_hp; + status->sp = status->max_sp; + status->str += sd->base_status.str * 25 / 100; + status->agi += sd->base_status.agi * 25 / 100; + status->vit += sd->base_status.vit * 25 / 100; + status->int_ += sd->base_status.int_ * 25 / 100; + status->def += sd->base_status.dex * 25 / 100; + status->luk += sd->base_status.luk * 25 / 100; + + status_calc_misc(&ed->bl, status, ed->db->lv); + memcpy(&ed->battle_status,status,sizeof(struct status_data)); + } else { + status_calc_misc(&ed->bl, status, ed->db->lv); + status_cpy(&ed->battle_status, status); + } + + return 0; } static unsigned short status_calc_str(struct block_list *,struct status_change *,int); @@ -3296,793 +3287,786 @@ static unsigned int status_calc_maxsp(struct block_list *,struct status_change * static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element); static unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv); static unsigned short status_calc_mode(struct block_list *bl, struct status_change *sc, int mode); -#ifdef RENEWAL -static unsigned short status_calc_ematk(struct block_list *,struct status_change *,int); -#endif //Calculates base regen values. void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen) { - struct map_session_data *sd; - int val, skill; + struct map_session_data *sd; + int val, skill; - if (!(bl->type&BL_REGEN) || !regen) - return; + if( !(bl->type&BL_REGEN) || !regen ) + return; - sd = BL_CAST(BL_PC,bl); - val = 1 + (status->vit/5) + (status->max_hp/200); + sd = BL_CAST(BL_PC,bl); + val = 1 + (status->vit/5) + (status->max_hp/200); - if (sd && sd->hprecov_rate != 100) - val = val*sd->hprecov_rate/100; + if( sd && sd->hprecov_rate != 100 ) + val = val*sd->hprecov_rate/100; - regen->hp = cap_value(val, 1, SHRT_MAX); + regen->hp = cap_value(val, 1, SHRT_MAX); - val = 1 + (status->int_/6) + (status->max_sp/100); - if (status->int_ >= 120) - val += ((status->int_-120)>>1) + 4; + val = 1 + (status->int_/6) + (status->max_sp/100); + if( status->int_ >= 120 ) + val += ((status->int_-120)>>1) + 4; - if (sd && sd->sprecov_rate != 100) - val = val*sd->sprecov_rate/100; + if( sd && sd->sprecov_rate != 100 ) + val = val*sd->sprecov_rate/100; - regen->sp = cap_value(val, 1, SHRT_MAX); + regen->sp = cap_value(val, 1, SHRT_MAX); - if (sd) { - struct regen_data_sub *sregen; - if ((skill=pc_checkskill(sd,HP_MEDITATIO)) > 0) { - val = regen->sp*(100+3*skill)/100; - regen->sp = cap_value(val, 1, SHRT_MAX); - } - //Only players have skill/sitting skill regen for now. - sregen = regen->sregen; - - val = 0; - if ((skill=pc_checkskill(sd,SM_RECOVERY)) > 0) - val += skill*5 + skill*status->max_hp/500; - sregen->hp = cap_value(val, 0, SHRT_MAX); - - val = 0; - if ((skill=pc_checkskill(sd,MG_SRECOVERY)) > 0) - val += skill*3 + skill*status->max_sp/500; - if ((skill=pc_checkskill(sd,NJ_NINPOU)) > 0) - val += skill*3 + skill*status->max_sp/500; - if ((skill=pc_checkskill(sd,WM_LESSON)) > 0) - val += 3 + 3 * skill; - - sregen->sp = cap_value(val, 0, SHRT_MAX); - - // Skill-related recovery (only when sit) - sregen = regen->ssregen; - - val = 0; - if ((skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0) - val += skill*4 + skill*status->max_hp/500; - - if ((skill=pc_checkskill(sd,TK_HPTIME)) > 0 && sd->state.rest) - val += skill*30 + skill*status->max_hp/500; - sregen->hp = cap_value(val, 0, SHRT_MAX); - - val = 0; - if ((skill=pc_checkskill(sd,TK_SPTIME)) > 0 && sd->state.rest) { - val += skill*3 + skill*status->max_sp/500; - if ((skill=pc_checkskill(sd,SL_KAINA)) > 0) //Power up Enjoyable Rest - val += (30+10*skill)*val/100; - } - if ((skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0) - val += skill*2 + skill*status->max_sp/500; - sregen->sp = cap_value(val, 0, SHRT_MAX); - } - - if (bl->type == BL_HOM) { - struct homun_data *hd = (TBL_HOM *)bl; - if ((skill = merc_hom_checkskill(hd,HAMI_SKIN)) > 0) { - val = regen->hp*(100+5*skill)/100; - regen->hp = cap_value(val, 1, SHRT_MAX); - } - if ((skill = merc_hom_checkskill(hd,HLIF_BRAIN)) > 0) { - val = regen->sp*(100+3*skill)/100; - regen->sp = cap_value(val, 1, SHRT_MAX); - } - } else if (bl->type == BL_MER) { - val = (status->max_hp * status->vit / 10000 + 1) * 6; - regen->hp = cap_value(val, 1, SHRT_MAX); - - val = (status->max_sp * (status->int_ + 10) / 750) + 1; - regen->sp = cap_value(val, 1, SHRT_MAX); - } else if (bl->type == BL_ELEM) { - val = (status->max_hp * status->vit / 10000 + 1) * 6; - regen->hp = cap_value(val, 1, SHRT_MAX); - - val = (status->max_sp * (status->int_ + 10) / 750) + 1; - regen->sp = cap_value(val, 1, SHRT_MAX); - } + if( sd ) + { + struct regen_data_sub *sregen; + if( (skill=pc_checkskill(sd,HP_MEDITATIO)) > 0 ) + { + val = regen->sp*(100+3*skill)/100; + regen->sp = cap_value(val, 1, SHRT_MAX); + } + //Only players have skill/sitting skill regen for now. + sregen = regen->sregen; + + val = 0; + if( (skill=pc_checkskill(sd,SM_RECOVERY)) > 0 ) + val += skill*5 + skill*status->max_hp/500; + sregen->hp = cap_value(val, 0, SHRT_MAX); + + val = 0; + if( (skill=pc_checkskill(sd,MG_SRECOVERY)) > 0 ) + val += skill*3 + skill*status->max_sp/500; + if( (skill=pc_checkskill(sd,NJ_NINPOU)) > 0 ) + val += skill*3 + skill*status->max_sp/500; + if( (skill=pc_checkskill(sd,WM_LESSON)) > 0 ) + val += 3 + 3 * skill; + + sregen->sp = cap_value(val, 0, SHRT_MAX); + + // Skill-related recovery (only when sit) + sregen = regen->ssregen; + + val = 0; + if( (skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0 ) + val += skill*4 + skill*status->max_hp/500; + + if( (skill=pc_checkskill(sd,TK_HPTIME)) > 0 && sd->state.rest ) + val += skill*30 + skill*status->max_hp/500; + sregen->hp = cap_value(val, 0, SHRT_MAX); + + val = 0; + if( (skill=pc_checkskill(sd,TK_SPTIME)) > 0 && sd->state.rest ) + { + val += skill*3 + skill*status->max_sp/500; + if ((skill=pc_checkskill(sd,SL_KAINA)) > 0) //Power up Enjoyable Rest + val += (30+10*skill)*val/100; + } + if( (skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0 ) + val += skill*2 + skill*status->max_sp/500; + sregen->sp = cap_value(val, 0, SHRT_MAX); + } + + if( bl->type == BL_HOM ) { + struct homun_data *hd = (TBL_HOM*)bl; + if( (skill = merc_hom_checkskill(hd,HAMI_SKIN)) > 0 ) { + val = regen->hp*(100+5*skill)/100; + regen->hp = cap_value(val, 1, SHRT_MAX); + } + if( (skill = merc_hom_checkskill(hd,HLIF_BRAIN)) > 0 ) { + val = regen->sp*(100+3*skill)/100; + regen->sp = cap_value(val, 1, SHRT_MAX); + } + } else if( bl->type == BL_MER ) { + val = (status->max_hp * status->vit / 10000 + 1) * 6; + regen->hp = cap_value(val, 1, SHRT_MAX); + + val = (status->max_sp * (status->int_ + 10) / 750) + 1; + regen->sp = cap_value(val, 1, SHRT_MAX); + } else if( bl->type == BL_ELEM ) { + val = (status->max_hp * status->vit / 10000 + 1) * 6; + regen->hp = cap_value(val, 1, SHRT_MAX); + + val = (status->max_sp * (status->int_ + 10) / 750) + 1; + regen->sp = cap_value(val, 1, SHRT_MAX); + } } //Calculates SC related regen rates. void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc) { - if (!(bl->type&BL_REGEN) || !regen) - return; - - regen->flag = RGN_HP|RGN_SP; - if (regen->sregen) { - if (regen->sregen->hp) - regen->flag|=RGN_SHP; - - if (regen->sregen->sp) - regen->flag|=RGN_SSP; - regen->sregen->rate.hp = regen->sregen->rate.sp = 1; - } - if (regen->ssregen) { - if (regen->ssregen->hp) - regen->flag|=RGN_SHP; - - if (regen->ssregen->sp) - regen->flag|=RGN_SSP; - regen->ssregen->rate.hp = regen->ssregen->rate.sp = 1; - } - regen->rate.hp = regen->rate.sp = 1; - - if (!sc || !sc->count) - return; - - if ( - (sc->data[SC_POISON] && !sc->data[SC_SLOWPOISON]) - || (sc->data[SC_DPOISON] && !sc->data[SC_SLOWPOISON]) - || sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST] - || sc->data[SC_TRICKDEAD] - || sc->data[SC_BLEEDING] - || sc->data[SC_MAGICMUSHROOM] - || sc->data[SC_RAISINGDRAGON] - || sc->data[SC_SATURDAYNIGHTFEVER] - ) //No regen - regen->flag = 0; - - if ( - sc->data[SC_DANCING] || sc->data[SC_OBLIVIONCURSE] || sc->data[SC_MAXIMIZEPOWER] - || ( - (bl->type == BL_PC && ((TBL_PC *)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK && - (sc->data[SC_EXTREMITYFIST] || (sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK))) - ) - ) //No natural SP regen - regen->flag &=~RGN_SP; - - if ( - sc->data[SC_TENSIONRELAX] - ) { - regen->rate.hp += 2; - if (regen->sregen) - regen->sregen->rate.hp += 3; - } - if (sc->data[SC_MAGNIFICAT]) { - regen->rate.hp += 1; - regen->rate.sp += 1; - } - if (sc->data[SC_REGENERATION]) { - const struct status_change_entry *sce = sc->data[SC_REGENERATION]; - if (!sce->val4) { - regen->rate.hp += sce->val2; - regen->rate.sp += sce->val3; - } else - regen->flag&=~sce->val4; //Remove regen as specified by val4 - } - if (sc->data[SC_GT_REVITALIZE]) { - regen->hp = cap_value(regen->hp*sc->data[SC_GT_REVITALIZE]->val3/100, 1, SHRT_MAX); - regen->state.walk= 1; - } - if ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) //if insignia lvl 1 - || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1) - || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1) - || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1)) - regen->rate.hp *= 2; + if (!(bl->type&BL_REGEN) || !regen) + return; + + regen->flag = RGN_HP|RGN_SP; + if(regen->sregen) + { + if (regen->sregen->hp) + regen->flag|=RGN_SHP; + + if (regen->sregen->sp) + regen->flag|=RGN_SSP; + regen->sregen->rate.hp = regen->sregen->rate.sp = 1; + } + if (regen->ssregen) + { + if (regen->ssregen->hp) + regen->flag|=RGN_SHP; + + if (regen->ssregen->sp) + regen->flag|=RGN_SSP; + regen->ssregen->rate.hp = regen->ssregen->rate.sp = 1; + } + regen->rate.hp = regen->rate.sp = 1; + + if (!sc || !sc->count) + return; + + if ( + (sc->data[SC_POISON] && !sc->data[SC_SLOWPOISON]) + || (sc->data[SC_DPOISON] && !sc->data[SC_SLOWPOISON]) + || sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST] + || sc->data[SC_TRICKDEAD] + || sc->data[SC_BLEEDING] + || sc->data[SC_MAGICMUSHROOM] + || sc->data[SC_RAISINGDRAGON] + || sc->data[SC_SATURDAYNIGHTFEVER] + ) //No regen + regen->flag = 0; + + if ( + sc->data[SC_DANCING] || sc->data[SC_OBLIVIONCURSE] || sc->data[SC_MAXIMIZEPOWER] + || ( + (bl->type == BL_PC && ((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK && + (sc->data[SC_EXTREMITYFIST] || (sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK))) + ) + ) //No natural SP regen + regen->flag &=~RGN_SP; + + if( + sc->data[SC_TENSIONRELAX] + ) { + regen->rate.hp += 2; + if (regen->sregen) + regen->sregen->rate.hp += 3; + } + if (sc->data[SC_MAGNIFICAT]) + { + regen->rate.hp += 1; + regen->rate.sp += 1; + } + if (sc->data[SC_REGENERATION]) + { + const struct status_change_entry *sce = sc->data[SC_REGENERATION]; + if (!sce->val4) + { + regen->rate.hp += sce->val2; + regen->rate.sp += sce->val3; + } else + regen->flag&=~sce->val4; //Remove regen as specified by val4 + } + if(sc->data[SC_GT_REVITALIZE]){ + regen->hp = cap_value(regen->hp*sc->data[SC_GT_REVITALIZE]->val3/100, 1, SHRT_MAX); + regen->state.walk= 1; + } + if ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) //if insignia lvl 1 + || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1) + || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1) + || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1)) + regen->rate.hp *= 2; } -void status_calc_state(struct block_list *bl, struct status_change *sc, enum scs_flag flag, bool start) -{ - - /* no sc at all, we can zero without any extra weight over our conciousness */ - if (!sc->count) { - memset(&sc->cant, 0, sizeof(sc->cant)); - return; - } - - /* can move? */ - if (flag&SCS_NOMOVE) { - if (!(flag&SCS_NOMOVECOND)) { - sc->cant.move += (start ? 1 : -1); - } else if ( - (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect - || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move - || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF) - || (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB) - || (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 - && !(sc->data[SC_CAMOUFLAGE]->val3&1)) - ) { - sc->cant.move += (start ? 1 : -1); - } - } - - /* can't use skills */ - if (flag&SCS_NOCAST) { - if (!(flag&SCS_NOCASTCOND)) { - sc->cant.cast += (start ? 1 : -1); - } else if ((sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB)) { - sc->cant.cast += (start ? 1 : -1); - } - } +void status_calc_state( struct block_list *bl, struct status_change *sc, enum scs_flag flag, bool start ) { + + /* no sc at all, we can zero without any extra weight over our conciousness */ + if( !sc->count ) { + memset(&sc->cant, 0, sizeof (sc->cant)); + return; + } + + /* can move? */ + if( flag&SCS_NOMOVE ) { + if( !(flag&SCS_NOMOVECOND) ) { + sc->cant.move += ( start ? 1 : -1 ); + } else if( + (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect + || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move + || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF) + || (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB) + || (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 + && !(sc->data[SC_CAMOUFLAGE]->val3&1)) + ) { + sc->cant.move += ( start ? 1 : -1 ); + } + } + + /* can't use skills */ + if( flag&SCS_NOCAST ) { + if( !(flag&SCS_NOCASTCOND) ) { + sc->cant.cast += ( start ? 1 : -1 ); + } else if( (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB) ){ + sc->cant.cast += ( start ? 1 : -1 ); + } + } - /* player-only states */ - if (bl->type == BL_PC) { + /* player-only states */ + if( bl->type == BL_PC ) { - /* can pick items? */ - if (flag&SCS_NOPICKITEM) { - if (!(flag&SCS_NOPICKITEMCOND)) { - sc->cant.pickup += (start ? 1 : -1); - } else if ((sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOITEM)) { - sc->cant.pickup += (start ? 1 : -1); - } - } + /* can pick items? */ + if( flag&SCS_NOPICKITEM ) { + if( !(flag&SCS_NOPICKITEMCOND) ) { + sc->cant.pickup += ( start ? 1 : -1 ); + } else if( (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOITEM) ) { + sc->cant.pickup += ( start ? 1 : -1 ); + } + } - /* can drop items? */ - if (flag&SCS_NODROPITEM) { - if (!(flag&SCS_NODROPITEMCOND)) { - sc->cant.drop += (start ? 1 : -1); - } else if ((sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOITEM)) { - sc->cant.drop += (start ? 1 : -1); - } - } - } + /* can drop items? */ + if( flag&SCS_NODROPITEM ) { + if( !(flag&SCS_NODROPITEMCOND) ) { + sc->cant.drop += ( start ? 1 : -1 ); + } else if( (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOITEM) ) { + sc->cant.drop += ( start ? 1 : -1 ); + } + } + } - return; + return; } /// Recalculates parts of an object's battle status according to the specified flags. /// @param flag bitfield of values from enum scb_flag void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { - const struct status_data *b_status = status_get_base_status(bl); - struct status_data *status = status_get_status_data(bl); - struct status_change *sc = status_get_sc(bl); - TBL_PC *sd = BL_CAST(BL_PC,bl); - int temp; - - if (!b_status || !status) - return; - - if ((!(bl->type&BL_REGEN)) && (!sc || !sc->count)) { //No difference. - status_cpy(status, b_status); - return; - } - - if (flag&SCB_STR) { - status->str = status_calc_str(bl, sc, b_status->str); - flag|=SCB_BATK; - if (bl->type&BL_HOM) - flag |= SCB_WATK; - } - - if (flag&SCB_AGI) { - status->agi = status_calc_agi(bl, sc, b_status->agi); - flag|=SCB_FLEE; - if (bl->type&(BL_PC|BL_HOM)) - flag |= SCB_ASPD|SCB_DSPD; - } - - if (flag&SCB_VIT) { - status->vit = status_calc_vit(bl, sc, b_status->vit); - flag|=SCB_DEF2|SCB_MDEF2; - if (bl->type&(BL_PC|BL_HOM|BL_MER|BL_ELEM)) - flag |= SCB_MAXHP; - if (bl->type&BL_HOM) - flag |= SCB_DEF; - } - - if (flag&SCB_INT) { - status->int_ = status_calc_int(bl, sc, b_status->int_); - flag|=SCB_MATK|SCB_MDEF2; - if (bl->type&(BL_PC|BL_HOM|BL_MER|BL_ELEM)) - flag |= SCB_MAXSP; - if (bl->type&BL_HOM) - flag |= SCB_MDEF; - } - - if (flag&SCB_DEX) { - status->dex = status_calc_dex(bl, sc, b_status->dex); - flag|=SCB_BATK|SCB_HIT; - if (bl->type&(BL_PC|BL_HOM)) - flag |= SCB_ASPD; - if (bl->type&BL_HOM) - flag |= SCB_WATK; - } - - if (flag&SCB_LUK) { - status->luk = status_calc_luk(bl, sc, b_status->luk); - flag|=SCB_BATK|SCB_CRI|SCB_FLEE2; - } - - if (flag&SCB_BATK && b_status->batk) { - status->batk = status_base_atk(bl,status); - temp = b_status->batk - status_base_atk(bl,b_status); - if (temp) { - temp += status->batk; - status->batk = cap_value(temp, 0, USHRT_MAX); - } - status->batk = status_calc_batk(bl, sc, status->batk); - } - - if (flag&SCB_WATK) { - - status->rhw.atk = status_calc_watk(bl, sc, b_status->rhw.atk); - if (!sd) //Should not affect weapon refine bonus - status->rhw.atk2 = status_calc_watk(bl, sc, b_status->rhw.atk2); - - if (b_status->lhw.atk) { - if (sd) { - sd->state.lr_flag = 1; - status->lhw.atk = status_calc_watk(bl, sc, b_status->lhw.atk); - sd->state.lr_flag = 0; - } else { - status->lhw.atk = status_calc_watk(bl, sc, b_status->lhw.atk); - status->lhw.atk2= status_calc_watk(bl, sc, b_status->lhw.atk2); - } - } - - if (bl->type&BL_HOM) { - status->rhw.atk += (status->dex - b_status->dex); - status->rhw.atk2 += (status->str - b_status->str); - if (status->rhw.atk2 < status->rhw.atk) - status->rhw.atk2 = status->rhw.atk; - } - } - - if (flag&SCB_HIT) { - if (status->dex == b_status->dex) - status->hit = status_calc_hit(bl, sc, b_status->hit); - else - status->hit = status_calc_hit(bl, sc, b_status->hit +(status->dex - b_status->dex)); - } - - if (flag&SCB_FLEE) { - if (status->agi == b_status->agi) - status->flee = status_calc_flee(bl, sc, b_status->flee); - else - status->flee = status_calc_flee(bl, sc, b_status->flee +(status->agi - b_status->agi)); - } - - if (flag&SCB_DEF) { - status->def = status_calc_def(bl, sc, b_status->def); - - if (bl->type&BL_HOM) - status->def += (status->vit/5 - b_status->vit/5); - } - - if (flag&SCB_DEF2) { - if (status->vit == b_status->vit) - status->def2 = status_calc_def2(bl, sc, b_status->def2); - else - status->def2 = status_calc_def2(bl, sc, b_status->def2 + (status->vit - b_status->vit)); - } - - if (flag&SCB_MDEF) { - status->mdef = status_calc_mdef(bl, sc, b_status->mdef); - - if (bl->type&BL_HOM) - status->mdef += (status->int_/5 - b_status->int_/5); - } - - if (flag&SCB_MDEF2) { - if (status->int_ == b_status->int_ && status->vit == b_status->vit) - status->mdef2 = status_calc_mdef2(bl, sc, b_status->mdef2); - else - status->mdef2 = status_calc_mdef2(bl, sc, b_status->mdef2 +(status->int_ - b_status->int_) +((status->vit - b_status->vit)>>1)); - } - - if (flag&SCB_SPEED) { - struct unit_data *ud = unit_bl2ud(bl); - status->speed = status_calc_speed(bl, sc, b_status->speed); - - //Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER - //because if you step on something while walking, the moment this - //piece of code triggers the walk-timer is set on INVALID_TIMER) [Skotlex] - if (ud) - ud->state.change_walk_target = ud->state.speed_changed = 1; - - if (bl->type&BL_PC && status->speed < battle_config.max_walk_speed) - status->speed = battle_config.max_walk_speed; - - if (bl->type&BL_HOM && battle_config.hom_setting&0x8 && ((TBL_HOM *)bl)->master) - status->speed = status_get_speed(&((TBL_HOM *)bl)->master->bl); - - - } - - if (flag&SCB_CRI && b_status->cri) { - if (status->luk == b_status->luk) - status->cri = status_calc_critical(bl, sc, b_status->cri); - else - status->cri = status_calc_critical(bl, sc, b_status->cri + 3*(status->luk - b_status->luk)); - /** - * after status_calc_critical so the bonus is applied despite if you have or not a sc bugreport:5240 - **/ - if (bl->type == BL_PC && ((TBL_PC *)bl)->status.weapon == W_KATAR) - status->cri <<= 1; - - } - - if (flag&SCB_FLEE2 && b_status->flee2) { - if (status->luk == b_status->luk) - status->flee2 = status_calc_flee2(bl, sc, b_status->flee2); - else - status->flee2 = status_calc_flee2(bl, sc, b_status->flee2 +(status->luk - b_status->luk)); - } - - if (flag&SCB_ATK_ELE) { - status->rhw.ele = status_calc_attack_element(bl, sc, b_status->rhw.ele); - if (sd) sd->state.lr_flag = 1; - status->lhw.ele = status_calc_attack_element(bl, sc, b_status->lhw.ele); - if (sd) sd->state.lr_flag = 0; - } - - if (flag&SCB_DEF_ELE) { - status->def_ele = status_calc_element(bl, sc, b_status->def_ele); - status->ele_lv = status_calc_element_lv(bl, sc, b_status->ele_lv); - } - - if (flag&SCB_MODE) { - status->mode = status_calc_mode(bl, sc, b_status->mode); - //Since mode changed, reset their state. - if (!(status->mode&MD_CANATTACK)) - unit_stop_attack(bl); - if (!(status->mode&MD_CANMOVE)) - unit_stop_walking(bl,1); - } - - // No status changes alter these yet. - // if(flag&SCB_SIZE) - // if(flag&SCB_RACE) - // if(flag&SCB_RANGE) - - if (flag&SCB_MAXHP) { - if (bl->type&BL_PC) { - status->max_hp = status_base_pc_maxhp(sd,status); - status->max_hp += b_status->max_hp - sd->status.max_hp; - - status->max_hp = status_calc_maxhp(bl, sc, status->max_hp); + const struct status_data *b_status = status_get_base_status(bl); + struct status_data *status = status_get_status_data(bl); + struct status_change *sc = status_get_sc(bl); + TBL_PC *sd = BL_CAST(BL_PC,bl); + int temp; + + if (!b_status || !status) + return; + + if((!(bl->type&BL_REGEN)) && (!sc || !sc->count)) { //No difference. + status_cpy(status, b_status); + return; + } + + if(flag&SCB_STR) { + status->str = status_calc_str(bl, sc, b_status->str); + flag|=SCB_BATK; + if( bl->type&BL_HOM ) + flag |= SCB_WATK; + } + + if(flag&SCB_AGI) { + status->agi = status_calc_agi(bl, sc, b_status->agi); + flag|=SCB_FLEE; + if( bl->type&(BL_PC|BL_HOM) ) + flag |= SCB_ASPD|SCB_DSPD; + } + + if(flag&SCB_VIT) { + status->vit = status_calc_vit(bl, sc, b_status->vit); + flag|=SCB_DEF2|SCB_MDEF2; + if( bl->type&(BL_PC|BL_HOM|BL_MER|BL_ELEM) ) + flag |= SCB_MAXHP; + if( bl->type&BL_HOM ) + flag |= SCB_DEF; + } + + if(flag&SCB_INT) { + status->int_ = status_calc_int(bl, sc, b_status->int_); + flag|=SCB_MATK|SCB_MDEF2; + if( bl->type&(BL_PC|BL_HOM|BL_MER|BL_ELEM) ) + flag |= SCB_MAXSP; + if( bl->type&BL_HOM ) + flag |= SCB_MDEF; + } + + if(flag&SCB_DEX) { + status->dex = status_calc_dex(bl, sc, b_status->dex); + flag|=SCB_BATK|SCB_HIT; + if( bl->type&(BL_PC|BL_HOM) ) + flag |= SCB_ASPD; + if( bl->type&BL_HOM ) + flag |= SCB_WATK; + } + + if(flag&SCB_LUK) { + status->luk = status_calc_luk(bl, sc, b_status->luk); + flag|=SCB_BATK|SCB_CRI|SCB_FLEE2; + } + + if(flag&SCB_BATK && b_status->batk) { + status->batk = status_base_atk(bl,status); + temp = b_status->batk - status_base_atk(bl,b_status); + if (temp) + { + temp += status->batk; + status->batk = cap_value(temp, 0, USHRT_MAX); + } + status->batk = status_calc_batk(bl, sc, status->batk); + } + + if(flag&SCB_WATK) { + + status->rhw.atk = status_calc_watk(bl, sc, b_status->rhw.atk); + if (!sd) //Should not affect weapon refine bonus + status->rhw.atk2 = status_calc_watk(bl, sc, b_status->rhw.atk2); + + if(b_status->lhw.atk) { + if (sd) { + sd->state.lr_flag = 1; + status->lhw.atk = status_calc_watk(bl, sc, b_status->lhw.atk); + sd->state.lr_flag = 0; + } else { + status->lhw.atk = status_calc_watk(bl, sc, b_status->lhw.atk); + status->lhw.atk2= status_calc_watk(bl, sc, b_status->lhw.atk2); + } + } - if (status->max_hp > (unsigned int)battle_config.max_hp) - status->max_hp = (unsigned int)battle_config.max_hp; - } else { - status->max_hp = status_calc_maxhp(bl, sc, b_status->max_hp); - } + if( bl->type&BL_HOM ) + { + status->rhw.atk += (status->dex - b_status->dex); + status->rhw.atk2 += (status->str - b_status->str); + if( status->rhw.atk2 < status->rhw.atk ) + status->rhw.atk2 = status->rhw.atk; + } + } + + if(flag&SCB_HIT) { + if (status->dex == b_status->dex) + status->hit = status_calc_hit(bl, sc, b_status->hit); + else + status->hit = status_calc_hit(bl, sc, b_status->hit +(status->dex - b_status->dex)); + } + + if(flag&SCB_FLEE) { + if (status->agi == b_status->agi) + status->flee = status_calc_flee(bl, sc, b_status->flee); + else + status->flee = status_calc_flee(bl, sc, b_status->flee +(status->agi - b_status->agi)); + } + + if(flag&SCB_DEF) + { + status->def = status_calc_def(bl, sc, b_status->def); + + if( bl->type&BL_HOM ) + status->def += (status->vit/5 - b_status->vit/5); + } + + if(flag&SCB_DEF2) { + if (status->vit == b_status->vit) + status->def2 = status_calc_def2(bl, sc, b_status->def2); + else + status->def2 = status_calc_def2(bl, sc, b_status->def2 + (status->vit - b_status->vit)); + } + + if(flag&SCB_MDEF) + { + status->mdef = status_calc_mdef(bl, sc, b_status->mdef); + + if( bl->type&BL_HOM ) + status->mdef += (status->int_/5 - b_status->int_/5); + } + + if(flag&SCB_MDEF2) { + if (status->int_ == b_status->int_ && status->vit == b_status->vit) + status->mdef2 = status_calc_mdef2(bl, sc, b_status->mdef2); + else + status->mdef2 = status_calc_mdef2(bl, sc, b_status->mdef2 +(status->int_ - b_status->int_) +((status->vit - b_status->vit)>>1)); + } + + if(flag&SCB_SPEED) { + struct unit_data *ud = unit_bl2ud(bl); + status->speed = status_calc_speed(bl, sc, b_status->speed); + + //Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER + //because if you step on something while walking, the moment this + //piece of code triggers the walk-timer is set on INVALID_TIMER) [Skotlex] + if (ud) + ud->state.change_walk_target = ud->state.speed_changed = 1; + + if( bl->type&BL_PC && status->speed < battle_config.max_walk_speed ) + status->speed = battle_config.max_walk_speed; + + if( bl->type&BL_HOM && battle_config.hom_setting&0x8 && ((TBL_HOM*)bl)->master) + status->speed = status_get_speed(&((TBL_HOM*)bl)->master->bl); + + + } + + if(flag&SCB_CRI && b_status->cri) { + if (status->luk == b_status->luk) + status->cri = status_calc_critical(bl, sc, b_status->cri); + else + status->cri = status_calc_critical(bl, sc, b_status->cri + 3*(status->luk - b_status->luk)); + /** + * after status_calc_critical so the bonus is applied despite if you have or not a sc bugreport:5240 + **/ + if( bl->type == BL_PC && ((TBL_PC*)bl)->status.weapon == W_KATAR ) + status->cri <<= 1; + + } + + if(flag&SCB_FLEE2 && b_status->flee2) { + if (status->luk == b_status->luk) + status->flee2 = status_calc_flee2(bl, sc, b_status->flee2); + else + status->flee2 = status_calc_flee2(bl, sc, b_status->flee2 +(status->luk - b_status->luk)); + } + + if(flag&SCB_ATK_ELE) { + status->rhw.ele = status_calc_attack_element(bl, sc, b_status->rhw.ele); + if (sd) sd->state.lr_flag = 1; + status->lhw.ele = status_calc_attack_element(bl, sc, b_status->lhw.ele); + if (sd) sd->state.lr_flag = 0; + } + + if(flag&SCB_DEF_ELE) { + status->def_ele = status_calc_element(bl, sc, b_status->def_ele); + status->ele_lv = status_calc_element_lv(bl, sc, b_status->ele_lv); + } + + if(flag&SCB_MODE) + { + status->mode = status_calc_mode(bl, sc, b_status->mode); + //Since mode changed, reset their state. + if (!(status->mode&MD_CANATTACK)) + unit_stop_attack(bl); + if (!(status->mode&MD_CANMOVE)) + unit_stop_walking(bl,1); + } + +// No status changes alter these yet. +// if(flag&SCB_SIZE) +// if(flag&SCB_RACE) +// if(flag&SCB_RANGE) + + if(flag&SCB_MAXHP) { + if( bl->type&BL_PC ) + { + status->max_hp = status_base_pc_maxhp(sd,status); + status->max_hp += b_status->max_hp - sd->status.max_hp; + + status->max_hp = status_calc_maxhp(bl, sc, status->max_hp); + + if( status->max_hp > (unsigned int)battle_config.max_hp ) + status->max_hp = (unsigned int)battle_config.max_hp; + } + else + { + status->max_hp = status_calc_maxhp(bl, sc, b_status->max_hp); + } - if (status->hp > status->max_hp) { //FIXME: Should perhaps a status_zap should be issued? - status->hp = status->max_hp; - if (sd) clif_updatestatus(sd,SP_HP); - } - } + if( status->hp > status->max_hp ) //FIXME: Should perhaps a status_zap should be issued? + { + status->hp = status->max_hp; + if( sd ) clif_updatestatus(sd,SP_HP); + } + } - if (flag&SCB_MAXSP) { - if (bl->type&BL_PC) { - status->max_sp = status_base_pc_maxsp(sd,status); - status->max_sp += b_status->max_sp - sd->status.max_sp; + if(flag&SCB_MAXSP) { + if( bl->type&BL_PC ) + { + status->max_sp = status_base_pc_maxsp(sd,status); + status->max_sp += b_status->max_sp - sd->status.max_sp; - status->max_sp = status_calc_maxsp(&sd->bl, &sd->sc, status->max_sp); + status->max_sp = status_calc_maxsp(&sd->bl, &sd->sc, status->max_sp); - if (status->max_sp > (unsigned int)battle_config.max_sp) - status->max_sp = (unsigned int)battle_config.max_sp; - } else { - status->max_sp = status_calc_maxsp(bl, sc, b_status->max_sp); - } + if( status->max_sp > (unsigned int)battle_config.max_sp ) + status->max_sp = (unsigned int)battle_config.max_sp; + } + else + { + status->max_sp = status_calc_maxsp(bl, sc, b_status->max_sp); + } - if (status->sp > status->max_sp) { - status->sp = status->max_sp; - if (sd) clif_updatestatus(sd,SP_SP); - } - } + if( status->sp > status->max_sp ) + { + status->sp = status->max_sp; + if( sd ) clif_updatestatus(sd,SP_SP); + } + } - if (flag&SCB_MATK) { -#ifndef RENEWAL - status->matk_min = status_base_matk_min(status) + (sd?sd->bonus.ematk:0); - status->matk_max = status_base_matk_max(status) + (sd?sd->bonus.ematk:0); + if(flag&SCB_MATK) { +#ifdef RENEWAL + status->matk_min = status_base_matk_min(status,status_get_lv(bl)); + if( sd ) + status->matk_min += sd->bonus.sp_base_matk; #else - /** - * RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK) - * MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers - **/ - status->matk_min = status->matk_max = status_base_matk(status, status_get_lv(bl)); - if( bl->type&BL_PC ){ - // Any +MATK you get from skills and cards, including cards in weapon, is added here. - if( sd->bonus.ematk > 0 ){ - status->matk_max += sd->bonus.ematk; - status->matk_min += sd->bonus.ematk; - } - status->matk_min = status_calc_ematk(bl, sc, status->matk_min); - status->matk_max = status_calc_ematk(bl, sc, status->matk_max); - //This is the only portion in MATK that varies depending on the weapon level and refinement rate. - if( status->rhw.matk > 0 ){ - int wMatk = status->rhw.matk; - int variance = wMatk * status->rhw.wlv / 10; - status->matk_min += wMatk - variance; - status->matk_max += wMatk + variance; - } - } + status->matk_min = status_base_matk_min(status); #endif - if (bl->type&BL_PC && sd->matk_rate != 100) { - status->matk_max = status->matk_max * sd->matk_rate/100; - status->matk_min = status->matk_min * sd->matk_rate/100; - } + status->matk_max = status_base_matk_max(status); - status->matk_min = status_calc_matk(bl, sc, status->matk_min); - status->matk_max = status_calc_matk(bl, sc, status->matk_max); + if( bl->type&BL_PC && sd->matk_rate != 100 ) + { + //Bonuses from previous matk +#ifndef RENEWAL // only changed in non-renewal [Ind] + status->matk_max = status->matk_max * sd->matk_rate/100; +#endif + status->matk_min = status->matk_min * sd->matk_rate/100; + } - if ((bl->type&BL_HOM && battle_config.hom_setting&0x20) //Hom Min Matk is always the same as Max Matk - || sc->data[SC_RECOGNIZEDSPELL]) - status->matk_min = status->matk_max; + status->matk_min = status_calc_matk(bl, sc, status->matk_min); -#ifdef RENEWAL - if( sd && sd->right_weapon.overrefine > 0){ - status->matk_min++; - status->matk_max += sd->right_weapon.overrefine - 1; - } +#ifndef RENEWAL // only changed in non-renewal [Ind] + status->matk_max = status_calc_matk(bl, sc, status->matk_max); #endif - } + if( bl->type&BL_HOM && battle_config.hom_setting&0x20 ) //Hom Min Matk is always the same as Max Matk + status->matk_min = status->matk_max; + + } - if (flag&SCB_ASPD) { - int amotion; - if (bl->type&BL_PC) { - amotion = status_base_amotion_pc(sd,status); + if(flag&SCB_ASPD) { + int amotion; + if( bl->type&BL_PC ) + { + amotion = status_base_amotion_pc(sd,status); #ifndef RENEWAL_ASPD - status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate); + status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate); - if (status->aspd_rate != 1000) - amotion = amotion*status->aspd_rate/1000; + if(status->aspd_rate != 1000) + amotion = amotion*status->aspd_rate/1000; #else - // aspd = baseaspd + floor(sqrt((agi^2/2) + (dex^2/5))/4 + (potskillbonus*agi/200)) - amotion -= (int)(sqrt((pow(status->agi, 2) / 2) + (pow(status->dex, 2) / 5)) / 4 + (status_calc_aspd(bl, sc, 1) * status->agi / 200)) * 10; + // aspd = baseaspd + floor(sqrt((agi^2/2) + (dex^2/5))/4 + (potskillbonus*agi/200)) + amotion -= (int)(sqrt( (pow(status->agi, 2) / 2) + (pow(status->dex, 2) / 5) ) / 4 + (status_calc_aspd(bl, sc, 1) * status->agi / 200)) * 10; - if ((status_calc_aspd(bl, sc, 2) + status->aspd_rate2) != 0) // RE ASPD percertage modifier - amotion -= (amotion - ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd)) - * (status_calc_aspd(bl, sc, 2) + status->aspd_rate2) / 100; + if( (status_calc_aspd(bl, sc, 2) + status->aspd_rate2) != 0 ) // RE ASPD percertage modifier + amotion -= ( amotion - ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd) ) + * (status_calc_aspd(bl, sc, 2) + status->aspd_rate2) / 100; - if (status->aspd_rate != 1000) // absolute percentage modifier - amotion = (200 - (200-amotion/10) * status->aspd_rate / 1000) * 10; + if(status->aspd_rate != 1000) // absolute percentage modifier + amotion = ( 200 - (200-amotion/10) * status->aspd_rate / 1000 ) * 10; #endif - //@TODO move FIGHTINGSPIRIT in fix_aspd - if (sc && sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2) - amotion -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) / 10 * 40; - amotion = status_calc_fix_aspd(bl, sc, amotion); - status->amotion = cap_value(amotion,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000); + //@TODO move FIGHTINGSPIRIT in fix_aspd + if( sc && sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 ) + amotion -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) / 10 * 40; + amotion = status_calc_fix_aspd(bl, sc, amotion); + status->amotion = cap_value(amotion,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000); - status->adelay = 2*status->amotion; - } else if (bl->type&BL_HOM) { - amotion = (1000 -4*status->agi -status->dex) * ((TBL_HOM *)bl)->homunculusDB->baseASPD/1000; - status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate); - - if (status->aspd_rate != 1000) - amotion = amotion*status->aspd_rate/1000; + status->adelay = 2*status->amotion; + } + else + if( bl->type&BL_HOM ) + { + amotion = (1000 -4*status->agi -status->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD/1000; + status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate); - amotion = status_calc_fix_aspd(bl, sc, amotion); - status->amotion = cap_value(amotion,battle_config.max_aspd,2000); + if(status->aspd_rate != 1000) + amotion = amotion*status->aspd_rate/1000; - status->adelay = status->amotion; - } else { // mercenary and mobs - amotion = b_status->amotion; - status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate); + amotion = status_calc_fix_aspd(bl, sc, amotion); + status->amotion = cap_value(amotion,battle_config.max_aspd,2000); - if (status->aspd_rate != 1000) - amotion = amotion*status->aspd_rate/1000; + status->adelay = status->amotion; + } + else // mercenary and mobs + { + amotion = b_status->amotion; + status->aspd_rate = status_calc_aspd_rate(bl, sc, b_status->aspd_rate); - amotion = status_calc_fix_aspd(bl, sc, amotion); - status->amotion = cap_value(amotion, battle_config.monster_max_aspd, 2000); + if(status->aspd_rate != 1000) + amotion = amotion*status->aspd_rate/1000; - temp = b_status->adelay*status->aspd_rate/1000; - status->adelay = cap_value(temp, battle_config.monster_max_aspd*2, 4000); - } - } + amotion = status_calc_fix_aspd(bl, sc, amotion); + status->amotion = cap_value(amotion, battle_config.monster_max_aspd, 2000); - if (flag&SCB_DSPD) { - int dmotion; - if (bl->type&BL_PC) { - if (b_status->agi == status->agi) - status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion); - else { - dmotion = 800-status->agi*4; - status->dmotion = cap_value(dmotion, 400, 800); - if (battle_config.pc_damage_delay_rate != 100) - status->dmotion = status->dmotion*battle_config.pc_damage_delay_rate/100; - //It's safe to ignore b_status->dmotion since no bonus affects it. - status->dmotion = status_calc_dmotion(bl, sc, status->dmotion); - } - } else if (bl->type&BL_HOM) { - dmotion = 800-status->agi*4; - status->dmotion = cap_value(dmotion, 400, 800); - status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion); - } else { // mercenary and mobs - status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion); - } - } + temp = b_status->adelay*status->aspd_rate/1000; + status->adelay = cap_value(temp, battle_config.monster_max_aspd*2, 4000); + } + } + + if(flag&SCB_DSPD) { + int dmotion; + if( bl->type&BL_PC ) + { + if (b_status->agi == status->agi) + status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion); + else { + dmotion = 800-status->agi*4; + status->dmotion = cap_value(dmotion, 400, 800); + if(battle_config.pc_damage_delay_rate != 100) + status->dmotion = status->dmotion*battle_config.pc_damage_delay_rate/100; + //It's safe to ignore b_status->dmotion since no bonus affects it. + status->dmotion = status_calc_dmotion(bl, sc, status->dmotion); + } + } + else + if( bl->type&BL_HOM ) + { + dmotion = 800-status->agi*4; + status->dmotion = cap_value(dmotion, 400, 800); + status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion); + } + else // mercenary and mobs + { + status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion); + } + } - if (flag&(SCB_VIT|SCB_MAXHP|SCB_INT|SCB_MAXSP) && bl->type&BL_REGEN) - status_calc_regen(bl, status, status_get_regen_data(bl)); + if(flag&(SCB_VIT|SCB_MAXHP|SCB_INT|SCB_MAXSP) && bl->type&BL_REGEN) + status_calc_regen(bl, status, status_get_regen_data(bl)); - if (flag&SCB_REGEN && bl->type&BL_REGEN) - status_calc_regen_rate(bl, status_get_regen_data(bl), sc); + if(flag&SCB_REGEN && bl->type&BL_REGEN) + status_calc_regen_rate(bl, status_get_regen_data(bl), sc); } /// Recalculates parts of an object's base status and battle status according to the specified flags. /// Also sends updates to the client wherever applicable. /// @param flag bitfield of values from enum scb_flag /// @param first if true, will cause status_calc_* functions to run their base status initialization code -void status_calc_bl_(struct block_list *bl, enum scb_flag flag, bool first) +void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first) { - struct status_data b_status; // previous battle status - struct status_data *status; // pointer to current battle status - - // remember previous values - status = status_get_status_data(bl); - memcpy(&b_status, status, sizeof(struct status_data)); - - if (flag&SCB_BASE) { // calculate the object's base status too - switch (bl->type) { - case BL_PC: - status_calc_pc_(BL_CAST(BL_PC,bl), first); - break; - case BL_MOB: - status_calc_mob_(BL_CAST(BL_MOB,bl), first); - break; - case BL_PET: - status_calc_pet_(BL_CAST(BL_PET,bl), first); - break; - case BL_HOM: - status_calc_homunculus_(BL_CAST(BL_HOM,bl), first); - break; - case BL_MER: - status_calc_mercenary_(BL_CAST(BL_MER,bl), first); - break; - case BL_ELEM: - status_calc_elemental_(BL_CAST(BL_ELEM,bl), first); - break; - } - } - - if (bl->type == BL_PET) - return; // pets are not affected by statuses - - if (first && bl->type == BL_MOB) - return; // assume there will be no statuses active - - status_calc_bl_main(bl, flag); - - if (first && bl->type == BL_HOM) - return; // client update handled by caller - - // compare against new values and send client updates - if (bl->type == BL_PC) { - TBL_PC *sd = BL_CAST(BL_PC, bl); - if (b_status.str != status->str) - clif_updatestatus(sd,SP_STR); - if (b_status.agi != status->agi) - clif_updatestatus(sd,SP_AGI); - if (b_status.vit != status->vit) - clif_updatestatus(sd,SP_VIT); - if (b_status.int_ != status->int_) - clif_updatestatus(sd,SP_INT); - if (b_status.dex != status->dex) - clif_updatestatus(sd,SP_DEX); - if (b_status.luk != status->luk) - clif_updatestatus(sd,SP_LUK); - if (b_status.hit != status->hit) - clif_updatestatus(sd,SP_HIT); - if (b_status.flee != status->flee) - clif_updatestatus(sd,SP_FLEE1); - if (b_status.amotion != status->amotion) - clif_updatestatus(sd,SP_ASPD); - if (b_status.speed != status->speed) - clif_updatestatus(sd,SP_SPEED); - - if (b_status.batk != status->batk + struct status_data b_status; // previous battle status + struct status_data* status; // pointer to current battle status + + // remember previous values + status = status_get_status_data(bl); + memcpy(&b_status, status, sizeof(struct status_data)); + + if( flag&SCB_BASE ) {// calculate the object's base status too + switch( bl->type ) { + case BL_PC: status_calc_pc_(BL_CAST(BL_PC,bl), first); break; + case BL_MOB: status_calc_mob_(BL_CAST(BL_MOB,bl), first); break; + case BL_PET: status_calc_pet_(BL_CAST(BL_PET,bl), first); break; + case BL_HOM: status_calc_homunculus_(BL_CAST(BL_HOM,bl), first); break; + case BL_MER: status_calc_mercenary_(BL_CAST(BL_MER,bl), first); break; + case BL_ELEM: status_calc_elemental_(BL_CAST(BL_ELEM,bl), first); break; + } + } + + if( bl->type == BL_PET ) + return; // pets are not affected by statuses + + if( first && bl->type == BL_MOB ) + return; // assume there will be no statuses active + + status_calc_bl_main(bl, flag); + + if( first && bl->type == BL_HOM ) + return; // client update handled by caller + + // compare against new values and send client updates + if( bl->type == BL_PC ) + { + TBL_PC* sd = BL_CAST(BL_PC, bl); + if(b_status.str != status->str) + clif_updatestatus(sd,SP_STR); + if(b_status.agi != status->agi) + clif_updatestatus(sd,SP_AGI); + if(b_status.vit != status->vit) + clif_updatestatus(sd,SP_VIT); + if(b_status.int_ != status->int_) + clif_updatestatus(sd,SP_INT); + if(b_status.dex != status->dex) + clif_updatestatus(sd,SP_DEX); + if(b_status.luk != status->luk) + clif_updatestatus(sd,SP_LUK); + if(b_status.hit != status->hit) + clif_updatestatus(sd,SP_HIT); + if(b_status.flee != status->flee) + clif_updatestatus(sd,SP_FLEE1); + if(b_status.amotion != status->amotion) + clif_updatestatus(sd,SP_ASPD); + if(b_status.speed != status->speed) + clif_updatestatus(sd,SP_SPEED); + + if(b_status.batk != status->batk #ifndef RENEWAL - || b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk + || b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk #endif - ) - clif_updatestatus(sd,SP_ATK1); + ) + clif_updatestatus(sd,SP_ATK1); - if (b_status.def != status->def) { - clif_updatestatus(sd,SP_DEF1); + if(b_status.def != status->def){ + clif_updatestatus(sd,SP_DEF1); #ifdef RENEWAL - clif_updatestatus(sd,SP_DEF2); + clif_updatestatus(sd,SP_DEF2); #endif - } + } - if (b_status.rhw.atk2 != status->rhw.atk2 || b_status.lhw.atk2 != status->lhw.atk2 + if(b_status.rhw.atk2 != status->rhw.atk2 || b_status.lhw.atk2 != status->lhw.atk2 #ifdef RENEWAL - || b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk + || b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk #endif - ) - clif_updatestatus(sd,SP_ATK2); + ) + clif_updatestatus(sd,SP_ATK2); - if (b_status.def2 != status->def2) { - clif_updatestatus(sd,SP_DEF2); + if(b_status.def2 != status->def2){ + clif_updatestatus(sd,SP_DEF2); #ifdef RENEWAL - clif_updatestatus(sd,SP_DEF1); + clif_updatestatus(sd,SP_DEF1); #endif - } - if (b_status.flee2 != status->flee2) - clif_updatestatus(sd,SP_FLEE2); - if (b_status.cri != status->cri) - clif_updatestatus(sd,SP_CRITICAL); -#ifndef RENEWAL - if (b_status.matk_max != status->matk_max) - clif_updatestatus(sd,SP_MATK1); - if (b_status.matk_min != status->matk_min) - clif_updatestatus(sd,SP_MATK2); -#else - if(b_status.matk_max != status->matk_max || b_status.matk_min != status->matk_min){ - clif_updatestatus(sd,SP_MATK2); - clif_updatestatus(sd,SP_MATK1); } -#endif - if (b_status.mdef != status->mdef) { - clif_updatestatus(sd,SP_MDEF1); + if(b_status.flee2 != status->flee2) + clif_updatestatus(sd,SP_FLEE2); + if(b_status.cri != status->cri) + clif_updatestatus(sd,SP_CRITICAL); + if(b_status.matk_max != status->matk_max) + clif_updatestatus(sd,SP_MATK1); + if(b_status.matk_min != status->matk_min) + clif_updatestatus(sd,SP_MATK2); + if(b_status.mdef != status->mdef){ + clif_updatestatus(sd,SP_MDEF1); #ifdef RENEWAL - clif_updatestatus(sd,SP_MDEF2); + clif_updatestatus(sd,SP_MDEF2); #endif - } - if (b_status.mdef2 != status->mdef2) { - clif_updatestatus(sd,SP_MDEF2); + } + if(b_status.mdef2 != status->mdef2){ + clif_updatestatus(sd,SP_MDEF2); #ifdef RENEWAL - clif_updatestatus(sd,SP_MDEF1); + clif_updatestatus(sd,SP_MDEF1); #endif - } - if (b_status.rhw.range != status->rhw.range) - clif_updatestatus(sd,SP_ATTACKRANGE); - if (b_status.max_hp != status->max_hp) - clif_updatestatus(sd,SP_MAXHP); - if (b_status.max_sp != status->max_sp) - clif_updatestatus(sd,SP_MAXSP); - if (b_status.hp != status->hp) - clif_updatestatus(sd,SP_HP); - if (b_status.sp != status->sp) - clif_updatestatus(sd,SP_SP); - } else if (bl->type == BL_HOM) { - TBL_HOM *hd = BL_CAST(BL_HOM, bl); - if (hd->master && memcmp(&b_status, status, sizeof(struct status_data)) != 0) - clif_hominfo(hd->master,hd,0); - } else if (bl->type == BL_MER) { - TBL_MER *md = BL_CAST(BL_MER, bl); - if (b_status.rhw.atk != status->rhw.atk || b_status.rhw.atk2 != status->rhw.atk2) - clif_mercenary_updatestatus(md->master, SP_ATK1); - if (b_status.matk_max != status->matk_max) - clif_mercenary_updatestatus(md->master, SP_MATK1); - if (b_status.hit != status->hit) - clif_mercenary_updatestatus(md->master, SP_HIT); - if (b_status.cri != status->cri) - clif_mercenary_updatestatus(md->master, SP_CRITICAL); - if (b_status.def != status->def) - clif_mercenary_updatestatus(md->master, SP_DEF1); - if (b_status.mdef != status->mdef) - clif_mercenary_updatestatus(md->master, SP_MDEF1); - if (b_status.flee != status->flee) - clif_mercenary_updatestatus(md->master, SP_MERCFLEE); - if (b_status.amotion != status->amotion) - clif_mercenary_updatestatus(md->master, SP_ASPD); - if (b_status.max_hp != status->max_hp) - clif_mercenary_updatestatus(md->master, SP_MAXHP); - if (b_status.max_sp != status->max_sp) - clif_mercenary_updatestatus(md->master, SP_MAXSP); - if (b_status.hp != status->hp) - clif_mercenary_updatestatus(md->master, SP_HP); - if (b_status.sp != status->sp) - clif_mercenary_updatestatus(md->master, SP_SP); - } else if (bl->type == BL_ELEM) { - TBL_ELEM *ed = BL_CAST(BL_ELEM, bl); - if (b_status.max_hp != status->max_hp) - clif_elemental_updatestatus(ed->master, SP_MAXHP); - if (b_status.max_sp != status->max_sp) - clif_elemental_updatestatus(ed->master, SP_MAXSP); - if (b_status.hp != status->hp) - clif_elemental_updatestatus(ed->master, SP_HP); - if (b_status.sp != status->sp) - clif_mercenary_updatestatus(ed->master, SP_SP); - } + } + if(b_status.rhw.range != status->rhw.range) + clif_updatestatus(sd,SP_ATTACKRANGE); + if(b_status.max_hp != status->max_hp) + clif_updatestatus(sd,SP_MAXHP); + if(b_status.max_sp != status->max_sp) + clif_updatestatus(sd,SP_MAXSP); + if(b_status.hp != status->hp) + clif_updatestatus(sd,SP_HP); + if(b_status.sp != status->sp) + clif_updatestatus(sd,SP_SP); + } else if( bl->type == BL_HOM ) { + TBL_HOM* hd = BL_CAST(BL_HOM, bl); + if( hd->master && memcmp(&b_status, status, sizeof(struct status_data)) != 0 ) + clif_hominfo(hd->master,hd,0); + } else if( bl->type == BL_MER ) { + TBL_MER* md = BL_CAST(BL_MER, bl); + if( b_status.rhw.atk != status->rhw.atk || b_status.rhw.atk2 != status->rhw.atk2 ) + clif_mercenary_updatestatus(md->master, SP_ATK1); + if( b_status.matk_max != status->matk_max ) + clif_mercenary_updatestatus(md->master, SP_MATK1); + if( b_status.hit != status->hit ) + clif_mercenary_updatestatus(md->master, SP_HIT); + if( b_status.cri != status->cri ) + clif_mercenary_updatestatus(md->master, SP_CRITICAL); + if( b_status.def != status->def ) + clif_mercenary_updatestatus(md->master, SP_DEF1); + if( b_status.mdef != status->mdef ) + clif_mercenary_updatestatus(md->master, SP_MDEF1); + if( b_status.flee != status->flee ) + clif_mercenary_updatestatus(md->master, SP_MERCFLEE); + if( b_status.amotion != status->amotion ) + clif_mercenary_updatestatus(md->master, SP_ASPD); + if( b_status.max_hp != status->max_hp ) + clif_mercenary_updatestatus(md->master, SP_MAXHP); + if( b_status.max_sp != status->max_sp ) + clif_mercenary_updatestatus(md->master, SP_MAXSP); + if( b_status.hp != status->hp ) + clif_mercenary_updatestatus(md->master, SP_HP); + if( b_status.sp != status->sp ) + clif_mercenary_updatestatus(md->master, SP_SP); + } else if( bl->type == BL_ELEM ) { + TBL_ELEM* ed = BL_CAST(BL_ELEM, bl); + if( b_status.max_hp != status->max_hp ) + clif_elemental_updatestatus(ed->master, SP_MAXHP); + if( b_status.max_sp != status->max_sp ) + clif_elemental_updatestatus(ed->master, SP_MAXSP); + if( b_status.hp != status->hp ) + clif_elemental_updatestatus(ed->master, SP_HP); + if( b_status.sp != status->sp ) + clif_mercenary_updatestatus(ed->master, SP_SP); + } } /*========================================== @@ -4090,1096 +4074,1071 @@ void status_calc_bl_(struct block_list *bl, enum scb_flag flag, bool first) *------------------------------------------*/ static unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, int str) { - if (!sc || !sc->count) - return cap_value(str,0,USHRT_MAX); - - if (sc->data[SC_HARMONIZE]) { - str -= sc->data[SC_HARMONIZE]->val2; - return (unsigned short)cap_value(str,0,USHRT_MAX); - } - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && str < 50) - return 50; - if (sc->data[SC_INCALLSTATUS]) - str += sc->data[SC_INCALLSTATUS]->val1; - if (sc->data[SC_INCSTR]) - str += sc->data[SC_INCSTR]->val1; - if (sc->data[SC_STRFOOD]) - str += sc->data[SC_STRFOOD]->val1; - if (sc->data[SC_FOOD_STR_CASH]) - str += sc->data[SC_FOOD_STR_CASH]->val1; - if (sc->data[SC_BATTLEORDERS]) - str += 5; - if (sc->data[SC_LEADERSHIP]) - str += sc->data[SC_LEADERSHIP]->val1; - if (sc->data[SC_LOUD]) - str += 4; - if (sc->data[SC_TRUESIGHT]) - str += 5; - if (sc->data[SC_SPURT]) - str += 10; - if (sc->data[SC_NEN]) - str += sc->data[SC_NEN]->val1; - if (sc->data[SC_BLESSING]) { - if (sc->data[SC_BLESSING]->val2) - str += sc->data[SC_BLESSING]->val2; - else - str >>= 1; - } - if (sc->data[SC_MARIONETTE]) - str -= ((sc->data[SC_MARIONETTE]->val3)>>16)&0xFF; - if (sc->data[SC_MARIONETTE2]) - str += ((sc->data[SC_MARIONETTE2]->val3)>>16)&0xFF; - if (sc->data[SC_GIANTGROWTH]) - str += 30; - if (sc->data[SC_SAVAGE_STEAK]) - str += sc->data[SC_SAVAGE_STEAK]->val1; - if (sc->data[SC_INSPIRATION]) - str += sc->data[SC_INSPIRATION]->val3; - if (sc->data[SC_STOMACHACHE]) - str -= sc->data[SC_STOMACHACHE]->val1; - if (sc->data[SC_KYOUGAKU]) - str -= sc->data[SC_KYOUGAKU]->val2; - - return (unsigned short)cap_value(str,0,USHRT_MAX); + if(!sc || !sc->count) + return cap_value(str,0,USHRT_MAX); + + if(sc->data[SC_HARMONIZE]) { + str -= sc->data[SC_HARMONIZE]->val2; + return (unsigned short)cap_value(str,0,USHRT_MAX); + } + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && str < 50) + return 50; + if(sc->data[SC_INCALLSTATUS]) + str += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCSTR]) + str += sc->data[SC_INCSTR]->val1; + if(sc->data[SC_STRFOOD]) + str += sc->data[SC_STRFOOD]->val1; + if(sc->data[SC_FOOD_STR_CASH]) + str += sc->data[SC_FOOD_STR_CASH]->val1; + if(sc->data[SC_BATTLEORDERS]) + str += 5; + if(sc->data[SC_LEADERSHIP]) + str += sc->data[SC_LEADERSHIP]->val1; + if(sc->data[SC_LOUD]) + str += 4; + if(sc->data[SC_TRUESIGHT]) + str += 5; + if(sc->data[SC_SPURT]) + str += 10; + if(sc->data[SC_NEN]) + str += sc->data[SC_NEN]->val1; + if(sc->data[SC_BLESSING]){ + if(sc->data[SC_BLESSING]->val2) + str += sc->data[SC_BLESSING]->val2; + else + str >>= 1; + } + if(sc->data[SC_MARIONETTE]) + str -= ((sc->data[SC_MARIONETTE]->val3)>>16)&0xFF; + if(sc->data[SC_MARIONETTE2]) + str += ((sc->data[SC_MARIONETTE2]->val3)>>16)&0xFF; + if(sc->data[SC_GIANTGROWTH]) + str += 30; + if(sc->data[SC_SAVAGE_STEAK]) + str += sc->data[SC_SAVAGE_STEAK]->val1; + if(sc->data[SC_INSPIRATION]) + str += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + str -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_KYOUGAKU]) + str -= sc->data[SC_KYOUGAKU]->val2; + + return (unsigned short)cap_value(str,0,USHRT_MAX); } static unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, int agi) { - if (!sc || !sc->count) - return cap_value(agi,0,USHRT_MAX); - - if (sc->data[SC_HARMONIZE]) { - agi -= sc->data[SC_HARMONIZE]->val2; - return (unsigned short)cap_value(agi,0,USHRT_MAX); - } - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && agi < 50) - return 50; - if (sc->data[SC_CONCENTRATE] && !sc->data[SC_QUAGMIRE]) - agi += (agi-sc->data[SC_CONCENTRATE]->val3)*sc->data[SC_CONCENTRATE]->val2/100; - if (sc->data[SC_INCALLSTATUS]) - agi += sc->data[SC_INCALLSTATUS]->val1; - if (sc->data[SC_INCAGI]) - agi += sc->data[SC_INCAGI]->val1; - if (sc->data[SC_AGIFOOD]) - agi += sc->data[SC_AGIFOOD]->val1; - if (sc->data[SC_FOOD_AGI_CASH]) - agi += sc->data[SC_FOOD_AGI_CASH]->val1; - if (sc->data[SC_SOULCOLD]) - agi += sc->data[SC_SOULCOLD]->val1; - if (sc->data[SC_TRUESIGHT]) - agi += 5; - if (sc->data[SC_INCREASEAGI]) - agi += sc->data[SC_INCREASEAGI]->val2; - if (sc->data[SC_INCREASING]) - agi += 4; // added based on skill updates [Reddozen] - if (sc->data[SC_DECREASEAGI]) - agi -= sc->data[SC_DECREASEAGI]->val2; - if (sc->data[SC_QUAGMIRE]) - agi -= sc->data[SC_QUAGMIRE]->val2; - if (sc->data[SC_SUITON] && sc->data[SC_SUITON]->val3) - agi -= sc->data[SC_SUITON]->val2; - if (sc->data[SC_MARIONETTE]) - agi -= ((sc->data[SC_MARIONETTE]->val3)>>8)&0xFF; - if (sc->data[SC_MARIONETTE2]) - agi += ((sc->data[SC_MARIONETTE2]->val3)>>8)&0xFF; - if (sc->data[SC_ADORAMUS]) - agi -= sc->data[SC_ADORAMUS]->val2; - if (sc->data[SC_DROCERA_HERB_STEAMED]) - agi += sc->data[SC_DROCERA_HERB_STEAMED]->val1; - if (sc->data[SC_INSPIRATION]) - agi += sc->data[SC_INSPIRATION]->val3; - if (sc->data[SC_STOMACHACHE]) - agi -= sc->data[SC_STOMACHACHE]->val1; - if (sc->data[SC_KYOUGAKU]) - agi -= sc->data[SC_KYOUGAKU]->val2; - - return (unsigned short)cap_value(agi,0,USHRT_MAX); + if(!sc || !sc->count) + return cap_value(agi,0,USHRT_MAX); + + if(sc->data[SC_HARMONIZE]) { + agi -= sc->data[SC_HARMONIZE]->val2; + return (unsigned short)cap_value(agi,0,USHRT_MAX); + } + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && agi < 50) + return 50; + if(sc->data[SC_CONCENTRATE] && !sc->data[SC_QUAGMIRE]) + agi += (agi-sc->data[SC_CONCENTRATE]->val3)*sc->data[SC_CONCENTRATE]->val2/100; + if(sc->data[SC_INCALLSTATUS]) + agi += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCAGI]) + agi += sc->data[SC_INCAGI]->val1; + if(sc->data[SC_AGIFOOD]) + agi += sc->data[SC_AGIFOOD]->val1; + if(sc->data[SC_FOOD_AGI_CASH]) + agi += sc->data[SC_FOOD_AGI_CASH]->val1; + if(sc->data[SC_SOULCOLD]) + agi += sc->data[SC_SOULCOLD]->val1; + if(sc->data[SC_TRUESIGHT]) + agi += 5; + if(sc->data[SC_INCREASEAGI]) + agi += sc->data[SC_INCREASEAGI]->val2; + if(sc->data[SC_INCREASING]) + agi += 4; // added based on skill updates [Reddozen] + if(sc->data[SC_DECREASEAGI]) + agi -= sc->data[SC_DECREASEAGI]->val2; + if(sc->data[SC_QUAGMIRE]) + agi -= sc->data[SC_QUAGMIRE]->val2; + if(sc->data[SC_SUITON] && sc->data[SC_SUITON]->val3) + agi -= sc->data[SC_SUITON]->val2; + if(sc->data[SC_MARIONETTE]) + agi -= ((sc->data[SC_MARIONETTE]->val3)>>8)&0xFF; + if(sc->data[SC_MARIONETTE2]) + agi += ((sc->data[SC_MARIONETTE2]->val3)>>8)&0xFF; + if(sc->data[SC_ADORAMUS]) + agi -= sc->data[SC_ADORAMUS]->val2; + if(sc->data[SC_DROCERA_HERB_STEAMED]) + agi += sc->data[SC_DROCERA_HERB_STEAMED]->val1; + if(sc->data[SC_INSPIRATION]) + agi += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + agi -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_KYOUGAKU]) + agi -= sc->data[SC_KYOUGAKU]->val2; + + return (unsigned short)cap_value(agi,0,USHRT_MAX); } static unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, int vit) { - if (!sc || !sc->count) - return cap_value(vit,0,USHRT_MAX); - - if (sc->data[SC_HARMONIZE]) { - vit -= sc->data[SC_HARMONIZE]->val2; - return (unsigned short)cap_value(vit,0,USHRT_MAX); - } - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && vit < 50) - return 50; - if (sc->data[SC_INCALLSTATUS]) - vit += sc->data[SC_INCALLSTATUS]->val1; - if (sc->data[SC_INCVIT]) - vit += sc->data[SC_INCVIT]->val1; - if (sc->data[SC_VITFOOD]) - vit += sc->data[SC_VITFOOD]->val1; - if (sc->data[SC_FOOD_VIT_CASH]) - vit += sc->data[SC_FOOD_VIT_CASH]->val1; - if (sc->data[SC_CHANGE]) - vit += sc->data[SC_CHANGE]->val2; - if (sc->data[SC_GLORYWOUNDS]) - vit += sc->data[SC_GLORYWOUNDS]->val1; - if (sc->data[SC_TRUESIGHT]) - vit += 5; - if (sc->data[SC_STRIPARMOR]) - vit -= vit * sc->data[SC_STRIPARMOR]->val2/100; - if (sc->data[SC_MARIONETTE]) - vit -= sc->data[SC_MARIONETTE]->val3&0xFF; - if (sc->data[SC_MARIONETTE2]) - vit += sc->data[SC_MARIONETTE2]->val3&0xFF; - if (sc->data[SC_LAUDAAGNUS]) - vit += 4 + sc->data[SC_LAUDAAGNUS]->val1; - if (sc->data[SC_MINOR_BBQ]) - vit += sc->data[SC_MINOR_BBQ]->val1; - if (sc->data[SC_INSPIRATION]) - vit += sc->data[SC_INSPIRATION]->val3; - if (sc->data[SC_STOMACHACHE]) - vit -= sc->data[SC_STOMACHACHE]->val1; - if (sc->data[SC_KYOUGAKU]) - vit -= sc->data[SC_KYOUGAKU]->val2; - - return (unsigned short)cap_value(vit,0,USHRT_MAX); + if(!sc || !sc->count) + return cap_value(vit,0,USHRT_MAX); + + if(sc->data[SC_HARMONIZE]) { + vit -= sc->data[SC_HARMONIZE]->val2; + return (unsigned short)cap_value(vit,0,USHRT_MAX); + } + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && vit < 50) + return 50; + if(sc->data[SC_INCALLSTATUS]) + vit += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCVIT]) + vit += sc->data[SC_INCVIT]->val1; + if(sc->data[SC_VITFOOD]) + vit += sc->data[SC_VITFOOD]->val1; + if(sc->data[SC_FOOD_VIT_CASH]) + vit += sc->data[SC_FOOD_VIT_CASH]->val1; + if(sc->data[SC_CHANGE]) + vit += sc->data[SC_CHANGE]->val2; + if(sc->data[SC_GLORYWOUNDS]) + vit += sc->data[SC_GLORYWOUNDS]->val1; + if(sc->data[SC_TRUESIGHT]) + vit += 5; + if(sc->data[SC_STRIPARMOR]) + vit -= vit * sc->data[SC_STRIPARMOR]->val2/100; + if(sc->data[SC_MARIONETTE]) + vit -= sc->data[SC_MARIONETTE]->val3&0xFF; + if(sc->data[SC_MARIONETTE2]) + vit += sc->data[SC_MARIONETTE2]->val3&0xFF; + if(sc->data[SC_LAUDAAGNUS]) + vit += 4 + sc->data[SC_LAUDAAGNUS]->val1; + if(sc->data[SC_MINOR_BBQ]) + vit += sc->data[SC_MINOR_BBQ]->val1; + if(sc->data[SC_INSPIRATION]) + vit += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + vit -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_KYOUGAKU]) + vit -= sc->data[SC_KYOUGAKU]->val2; + + return (unsigned short)cap_value(vit,0,USHRT_MAX); } static unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, int int_) { - if (!sc || !sc->count) - return cap_value(int_,0,USHRT_MAX); - - if (sc->data[SC_HARMONIZE]) { - int_ -= sc->data[SC_HARMONIZE]->val2; - return (unsigned short)cap_value(int_,0,USHRT_MAX); - } - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && int_ < 50) - return 50; - if (sc->data[SC_INCALLSTATUS]) - int_ += sc->data[SC_INCALLSTATUS]->val1; - if (sc->data[SC_INCINT]) - int_ += sc->data[SC_INCINT]->val1; - if (sc->data[SC_INTFOOD]) - int_ += sc->data[SC_INTFOOD]->val1; - if (sc->data[SC_FOOD_INT_CASH]) - int_ += sc->data[SC_FOOD_INT_CASH]->val1; - if (sc->data[SC_CHANGE]) - int_ += sc->data[SC_CHANGE]->val3; - if (sc->data[SC_BATTLEORDERS]) - int_ += 5; - if (sc->data[SC_TRUESIGHT]) - int_ += 5; - if (sc->data[SC_BLESSING]) { - if (sc->data[SC_BLESSING]->val2) - int_ += sc->data[SC_BLESSING]->val2; - else - int_ >>= 1; - } - if (sc->data[SC_STRIPHELM]) - int_ -= int_ * sc->data[SC_STRIPHELM]->val2/100; - if (sc->data[SC_NEN]) - int_ += sc->data[SC_NEN]->val1; - if (sc->data[SC_MARIONETTE]) - int_ -= ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF; - if (sc->data[SC_MARIONETTE2]) - int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF; - if (sc->data[SC_MANDRAGORA]) - int_ -= 5 + 5 * sc->data[SC_MANDRAGORA]->val1; - if (sc->data[SC__STRIPACCESSORY]) - int_ -= int_ * sc->data[SC__STRIPACCESSORY]->val2 / 100; - if (sc->data[SC_COCKTAIL_WARG_BLOOD]) - int_ += sc->data[SC_COCKTAIL_WARG_BLOOD]->val1; - if (sc->data[SC_INSPIRATION]) - int_ += sc->data[SC_INSPIRATION]->val3; - if (sc->data[SC_STOMACHACHE]) - int_ -= sc->data[SC_STOMACHACHE]->val1; - if (sc->data[SC_KYOUGAKU]) - int_ -= sc->data[SC_KYOUGAKU]->val2; - - return (unsigned short)cap_value(int_,0,USHRT_MAX); + if(!sc || !sc->count) + return cap_value(int_,0,USHRT_MAX); + + if(sc->data[SC_HARMONIZE]) { + int_ -= sc->data[SC_HARMONIZE]->val2; + return (unsigned short)cap_value(int_,0,USHRT_MAX); + } + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && int_ < 50) + return 50; + if(sc->data[SC_INCALLSTATUS]) + int_ += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCINT]) + int_ += sc->data[SC_INCINT]->val1; + if(sc->data[SC_INTFOOD]) + int_ += sc->data[SC_INTFOOD]->val1; + if(sc->data[SC_FOOD_INT_CASH]) + int_ += sc->data[SC_FOOD_INT_CASH]->val1; + if(sc->data[SC_CHANGE]) + int_ += sc->data[SC_CHANGE]->val3; + if(sc->data[SC_BATTLEORDERS]) + int_ += 5; + if(sc->data[SC_TRUESIGHT]) + int_ += 5; + if(sc->data[SC_BLESSING]){ + if (sc->data[SC_BLESSING]->val2) + int_ += sc->data[SC_BLESSING]->val2; + else + int_ >>= 1; + } + if(sc->data[SC_STRIPHELM]) + int_ -= int_ * sc->data[SC_STRIPHELM]->val2/100; + if(sc->data[SC_NEN]) + int_ += sc->data[SC_NEN]->val1; + if(sc->data[SC_MARIONETTE]) + int_ -= ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF; + if(sc->data[SC_MARIONETTE2]) + int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF; + if(sc->data[SC_MANDRAGORA]) + int_ -= 5 + 5 * sc->data[SC_MANDRAGORA]->val1; + if(sc->data[SC__STRIPACCESSORY]) + int_ -= int_ * sc->data[SC__STRIPACCESSORY]->val2 / 100; + if(sc->data[SC_COCKTAIL_WARG_BLOOD]) + int_ += sc->data[SC_COCKTAIL_WARG_BLOOD]->val1; + if(sc->data[SC_INSPIRATION]) + int_ += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + int_ -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_KYOUGAKU]) + int_ -= sc->data[SC_KYOUGAKU]->val2; + + return (unsigned short)cap_value(int_,0,USHRT_MAX); } static unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, int dex) { - if (!sc || !sc->count) - return cap_value(dex,0,USHRT_MAX); - - if (sc->data[SC_HARMONIZE]) { - dex -= sc->data[SC_HARMONIZE]->val2; - return (unsigned short)cap_value(dex,0,USHRT_MAX); - } - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && dex < 50) - return 50; - if (sc->data[SC_CONCENTRATE] && !sc->data[SC_QUAGMIRE]) - dex += (dex-sc->data[SC_CONCENTRATE]->val4)*sc->data[SC_CONCENTRATE]->val2/100; - if (sc->data[SC_INCALLSTATUS]) - dex += sc->data[SC_INCALLSTATUS]->val1; - if (sc->data[SC_INCDEX]) - dex += sc->data[SC_INCDEX]->val1; - if (sc->data[SC_DEXFOOD]) - dex += sc->data[SC_DEXFOOD]->val1; - if (sc->data[SC_FOOD_DEX_CASH]) - dex += sc->data[SC_FOOD_DEX_CASH]->val1; - if (sc->data[SC_BATTLEORDERS]) - dex += 5; - if (sc->data[SC_HAWKEYES]) - dex += sc->data[SC_HAWKEYES]->val1; - if (sc->data[SC_TRUESIGHT]) - dex += 5; - if (sc->data[SC_QUAGMIRE]) - dex -= sc->data[SC_QUAGMIRE]->val2; - if (sc->data[SC_BLESSING]) { - if (sc->data[SC_BLESSING]->val2) - dex += sc->data[SC_BLESSING]->val2; - else - dex >>= 1; - } - if (sc->data[SC_INCREASING]) - dex += 4; // added based on skill updates [Reddozen] - if (sc->data[SC_MARIONETTE]) - dex -= ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF; - if (sc->data[SC_MARIONETTE2]) - dex += ((sc->data[SC_MARIONETTE2]->val4)>>8)&0xFF; - if (sc->data[SC__STRIPACCESSORY]) - dex -= dex * sc->data[SC__STRIPACCESSORY]->val2 / 100; - if (sc->data[SC_SIROMA_ICE_TEA]) - dex += sc->data[SC_SIROMA_ICE_TEA]->val1; - if (sc->data[SC_INSPIRATION]) - dex += sc->data[SC_INSPIRATION]->val3; - if (sc->data[SC_STOMACHACHE]) - dex -= sc->data[SC_STOMACHACHE]->val1; - if (sc->data[SC_KYOUGAKU]) - dex -= sc->data[SC_KYOUGAKU]->val2; - - return (unsigned short)cap_value(dex,0,USHRT_MAX); + if(!sc || !sc->count) + return cap_value(dex,0,USHRT_MAX); + + if(sc->data[SC_HARMONIZE]) { + dex -= sc->data[SC_HARMONIZE]->val2; + return (unsigned short)cap_value(dex,0,USHRT_MAX); + } + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && dex < 50) + return 50; + if(sc->data[SC_CONCENTRATE] && !sc->data[SC_QUAGMIRE]) + dex += (dex-sc->data[SC_CONCENTRATE]->val4)*sc->data[SC_CONCENTRATE]->val2/100; + if(sc->data[SC_INCALLSTATUS]) + dex += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCDEX]) + dex += sc->data[SC_INCDEX]->val1; + if(sc->data[SC_DEXFOOD]) + dex += sc->data[SC_DEXFOOD]->val1; + if(sc->data[SC_FOOD_DEX_CASH]) + dex += sc->data[SC_FOOD_DEX_CASH]->val1; + if(sc->data[SC_BATTLEORDERS]) + dex += 5; + if(sc->data[SC_HAWKEYES]) + dex += sc->data[SC_HAWKEYES]->val1; + if(sc->data[SC_TRUESIGHT]) + dex += 5; + if(sc->data[SC_QUAGMIRE]) + dex -= sc->data[SC_QUAGMIRE]->val2; + if(sc->data[SC_BLESSING]){ + if (sc->data[SC_BLESSING]->val2) + dex += sc->data[SC_BLESSING]->val2; + else + dex >>= 1; + } + if(sc->data[SC_INCREASING]) + dex += 4; // added based on skill updates [Reddozen] + if(sc->data[SC_MARIONETTE]) + dex -= ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF; + if(sc->data[SC_MARIONETTE2]) + dex += ((sc->data[SC_MARIONETTE2]->val4)>>8)&0xFF; + if(sc->data[SC__STRIPACCESSORY]) + dex -= dex * sc->data[SC__STRIPACCESSORY]->val2 / 100; + if(sc->data[SC_SIROMA_ICE_TEA]) + dex += sc->data[SC_SIROMA_ICE_TEA]->val1; + if(sc->data[SC_INSPIRATION]) + dex += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + dex -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_KYOUGAKU]) + dex -= sc->data[SC_KYOUGAKU]->val2; + + return (unsigned short)cap_value(dex,0,USHRT_MAX); } static unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, int luk) { - if (!sc || !sc->count) - return cap_value(luk,0,USHRT_MAX); - - if (sc->data[SC_HARMONIZE]) { - luk -= sc->data[SC_HARMONIZE]->val2; - return (unsigned short)cap_value(luk,0,USHRT_MAX); - } - if (sc->data[SC_CURSE]) - return 0; - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && luk < 50) - return 50; - if (sc->data[SC_INCALLSTATUS]) - luk += sc->data[SC_INCALLSTATUS]->val1; - if (sc->data[SC_INCLUK]) - luk += sc->data[SC_INCLUK]->val1; - if (sc->data[SC_LUKFOOD]) - luk += sc->data[SC_LUKFOOD]->val1; - if (sc->data[SC_FOOD_LUK_CASH]) - luk += sc->data[SC_FOOD_LUK_CASH]->val1; - if (sc->data[SC_TRUESIGHT]) - luk += 5; - if (sc->data[SC_GLORIA]) - luk += 30; - if (sc->data[SC_MARIONETTE]) - luk -= sc->data[SC_MARIONETTE]->val4&0xFF; - if (sc->data[SC_MARIONETTE2]) - luk += sc->data[SC_MARIONETTE2]->val4&0xFF; - if (sc->data[SC_LAUDARAMUS]) - luk += 4 + sc->data[SC_LAUDARAMUS]->val1; - if (sc->data[SC__STRIPACCESSORY]) - luk -= luk * sc->data[SC__STRIPACCESSORY]->val2 / 100; - if (sc->data[SC_PUTTI_TAILS_NOODLES]) - luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1; - if (sc->data[SC_INSPIRATION]) - luk += sc->data[SC_INSPIRATION]->val3; - if (sc->data[SC_STOMACHACHE]) - luk -= sc->data[SC_STOMACHACHE]->val1; - if (sc->data[SC_BANANA_BOMB]) - luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100; - if (sc->data[SC_KYOUGAKU]) - luk -= sc->data[SC_KYOUGAKU]->val2; - - return (unsigned short)cap_value(luk,0,USHRT_MAX); + if(!sc || !sc->count) + return cap_value(luk,0,USHRT_MAX); + + if(sc->data[SC_HARMONIZE]) { + luk -= sc->data[SC_HARMONIZE]->val2; + return (unsigned short)cap_value(luk,0,USHRT_MAX); + } + if(sc->data[SC_CURSE]) + return 0; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && luk < 50) + return 50; + if(sc->data[SC_INCALLSTATUS]) + luk += sc->data[SC_INCALLSTATUS]->val1; + if(sc->data[SC_INCLUK]) + luk += sc->data[SC_INCLUK]->val1; + if(sc->data[SC_LUKFOOD]) + luk += sc->data[SC_LUKFOOD]->val1; + if(sc->data[SC_FOOD_LUK_CASH]) + luk += sc->data[SC_FOOD_LUK_CASH]->val1; + if(sc->data[SC_TRUESIGHT]) + luk += 5; + if(sc->data[SC_GLORIA]) + luk += 30; + if(sc->data[SC_MARIONETTE]) + luk -= sc->data[SC_MARIONETTE]->val4&0xFF; + if(sc->data[SC_MARIONETTE2]) + luk += sc->data[SC_MARIONETTE2]->val4&0xFF; + if(sc->data[SC_LAUDARAMUS]) + luk += 4 + sc->data[SC_LAUDARAMUS]->val1; + if(sc->data[SC__STRIPACCESSORY]) + luk -= luk * sc->data[SC__STRIPACCESSORY]->val2 / 100; + if(sc->data[SC_PUTTI_TAILS_NOODLES]) + luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1; + if(sc->data[SC_INSPIRATION]) + luk += sc->data[SC_INSPIRATION]->val3; + if(sc->data[SC_STOMACHACHE]) + luk -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_BANANA_BOMB]) + luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100; + if(sc->data[SC_KYOUGAKU]) + luk -= sc->data[SC_KYOUGAKU]->val2; + + return (unsigned short)cap_value(luk,0,USHRT_MAX); } static unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, int batk) { - if (!sc || !sc->count) - return cap_value(batk,0,USHRT_MAX); - - if (sc->data[SC_ATKPOTION]) - batk += sc->data[SC_ATKPOTION]->val1; - if (sc->data[SC_BATKFOOD]) - batk += sc->data[SC_BATKFOOD]->val1; - if (sc->data[SC_INCATKRATE]) - batk += batk * sc->data[SC_INCATKRATE]->val1/100; - if (sc->data[SC_PROVOKE]) - batk += batk * sc->data[SC_PROVOKE]->val3/100; - if (sc->data[SC_CONCENTRATION]) - batk += batk * sc->data[SC_CONCENTRATION]->val2/100; - if (sc->data[SC_SKE]) - batk += batk * 3; - if (sc->data[SC_BLOODLUST]) - batk += batk * sc->data[SC_BLOODLUST]->val2/100; - if (sc->data[SC_JOINTBEAT] && sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST) - batk -= batk * 25/100; - if (sc->data[SC_CURSE]) - batk -= batk * 25/100; - //Curse shouldn't effect on this? <- Curse OR Bleeding?? - // if(sc->data[SC_BLEEDING]) - // batk -= batk * 25/100; - if (sc->data[SC_FLEET]) - batk += batk * sc->data[SC_FLEET]->val3/100; - if (sc->data[SC_GATLINGFEVER]) - batk += sc->data[SC_GATLINGFEVER]->val3; - if (sc->data[SC_MADNESSCANCEL]) - batk += 100; - if (sc->data[SC__ENERVATION]) - batk -= batk * sc->data[SC__ENERVATION]->val2 / 100; - if (sc->data[SC_RUSHWINDMILL]) - batk += batk * sc->data[SC_RUSHWINDMILL]->val2/100; - if (sc->data[SC_SATURDAYNIGHTFEVER]) - batk += 100 * sc->data[SC_SATURDAYNIGHTFEVER]->val1; - if (sc->data[SC_MELODYOFSINK]) - batk -= batk * sc->data[SC_MELODYOFSINK]->val3/100; - if (sc->data[SC_BEYONDOFWARCRY]) - batk += batk * sc->data[SC_BEYONDOFWARCRY]->val3/100; - if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) - batk += 50; - if (bl->type == BL_ELEM - && ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) - || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1) - || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1) - || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1)) - ) - batk += batk / 5; - if (sc->data[SC_FULL_SWING_K]) - batk += sc->data[SC_FULL_SWING_K]->val1; - if (sc->data[SC_ODINS_POWER]) - batk += 70; - if (sc->data[SC_ZANGETSU]) - batk += batk * sc->data[SC_ZANGETSU]->val2 / 100; - if (sc->data[SC_ASH] && (bl->type==BL_MOB)) { - if (status_get_element(bl) == ELE_WATER) //water type - batk /= 2; - } - if (sc->data[SC_PYROCLASTIC]) - batk += sc->data[SC_PYROCLASTIC]->val2; - if (sc->data[SC_ANGRIFFS_MODUS]) - batk += sc->data[SC_ANGRIFFS_MODUS]->val2; - - return (unsigned short)cap_value(batk,0,USHRT_MAX); + if(!sc || !sc->count) + return cap_value(batk,0,USHRT_MAX); + + if(sc->data[SC_ATKPOTION]) + batk += sc->data[SC_ATKPOTION]->val1; + if(sc->data[SC_BATKFOOD]) + batk += sc->data[SC_BATKFOOD]->val1; + if(sc->data[SC_INCATKRATE]) + batk += batk * sc->data[SC_INCATKRATE]->val1/100; + if(sc->data[SC_PROVOKE]) + batk += batk * sc->data[SC_PROVOKE]->val3/100; + if(sc->data[SC_CONCENTRATION]) + batk += batk * sc->data[SC_CONCENTRATION]->val2/100; + if(sc->data[SC_SKE]) + batk += batk * 3; + if(sc->data[SC_BLOODLUST]) + batk += batk * sc->data[SC_BLOODLUST]->val2/100; + if(sc->data[SC_JOINTBEAT] && sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST) + batk -= batk * 25/100; + if(sc->data[SC_CURSE]) + batk -= batk * 25/100; +//Curse shouldn't effect on this? <- Curse OR Bleeding?? +// if(sc->data[SC_BLEEDING]) +// batk -= batk * 25/100; + if(sc->data[SC_FLEET]) + batk += batk * sc->data[SC_FLEET]->val3/100; + if(sc->data[SC_GATLINGFEVER]) + batk += sc->data[SC_GATLINGFEVER]->val3; + if(sc->data[SC_MADNESSCANCEL]) + batk += 100; + if(sc->data[SC__ENERVATION]) + batk -= batk * sc->data[SC__ENERVATION]->val2 / 100; + if(sc->data[SC_RUSHWINDMILL]) + batk += batk * sc->data[SC_RUSHWINDMILL]->val2/100; + if(sc->data[SC_SATURDAYNIGHTFEVER]) + batk += 100 * sc->data[SC_SATURDAYNIGHTFEVER]->val1; + if(sc->data[SC_MELODYOFSINK]) + batk -= batk * sc->data[SC_MELODYOFSINK]->val3/100; + if(sc->data[SC_BEYONDOFWARCRY]) + batk += batk * sc->data[SC_BEYONDOFWARCRY]->val3/100; + if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) + batk += 50; + if(bl->type == BL_ELEM + && ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) + || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1) + || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1) + || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1)) + ) + batk += batk / 5; + if(sc->data[SC_FULL_SWING_K]) + batk += sc->data[SC_FULL_SWING_K]->val1; + if(sc->data[SC_ODINS_POWER]) + batk += 70; + if( sc->data[SC_ZANGETSU] ) + batk += batk * sc->data[SC_ZANGETSU]->val2 / 100; + if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ + if(status_get_element(bl) == ELE_WATER) //water type + batk /= 2; + } + if(sc->data[SC_PYROCLASTIC]) + batk += sc->data[SC_PYROCLASTIC]->val2; + if (sc->data[SC_ANGRIFFS_MODUS]) + batk += sc->data[SC_ANGRIFFS_MODUS]->val2; + + return (unsigned short)cap_value(batk,0,USHRT_MAX); } static unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, int watk) { - if (!sc || !sc->count) - return cap_value(watk,0,USHRT_MAX); - - if (sc->data[SC_IMPOSITIO]) - watk += sc->data[SC_IMPOSITIO]->val2; - if (sc->data[SC_WATKFOOD]) - watk += sc->data[SC_WATKFOOD]->val1; - if (sc->data[SC_DRUMBATTLE]) - watk += sc->data[SC_DRUMBATTLE]->val2; - if (sc->data[SC_VOLCANO]) - watk += sc->data[SC_VOLCANO]->val2; - if (sc->data[SC_INCATKRATE]) - watk += watk * sc->data[SC_INCATKRATE]->val1/100; - if (sc->data[SC_PROVOKE]) - watk += watk * sc->data[SC_PROVOKE]->val3/100; - if (sc->data[SC_CONCENTRATION]) - watk += watk * sc->data[SC_CONCENTRATION]->val2/100; - if (sc->data[SC_SKE]) - watk += watk * 3; - if (sc->data[SC_NIBELUNGEN]) { - if (bl->type != BL_PC) - watk += sc->data[SC_NIBELUNGEN]->val2; - else { -#ifndef RENEWAL - TBL_PC *sd = (TBL_PC *)bl; - int index = sd->equip_index[sd->state.lr_flag?EQI_HAND_L:EQI_HAND_R]; - if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4) -#endif - watk += sc->data[SC_NIBELUNGEN]->val2; - } - } - if (sc->data[SC__ENERVATION]) - watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; - if (sc->data[SC_FLEET]) - watk += watk * sc->data[SC_FLEET]->val3/100; - if (sc->data[SC_CURSE]) - watk -= watk * 25/100; - if (sc->data[SC_STRIPWEAPON]) - watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100; - if (sc->data[SC_MERC_ATKUP]) - watk += sc->data[SC_MERC_ATKUP]->val2; - if (sc->data[SC_FIGHTINGSPIRIT]) - watk += sc->data[SC_FIGHTINGSPIRIT]->val1; - if (sc->data[SC__ENERVATION]) - watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; - if (sc->data[SC_STRIKING]) - watk += sc->data[SC_STRIKING]->val2; - if (sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3) - watk += sc->data[SC_SHIELDSPELL_DEF]->val2; - if (sc->data[SC_INSPIRATION]) - watk += sc->data[SC_INSPIRATION]->val2; - if (sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0) - watk += (10 + 10 * sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); - if (sc->data[SC_TROPIC_OPTION]) - watk += sc->data[SC_TROPIC_OPTION]->val2; - if (sc->data[SC_HEATER_OPTION]) - watk += sc->data[SC_HEATER_OPTION]->val2; - if (sc->data[SC_WATER_BARRIER]) - watk -= sc->data[SC_WATER_BARRIER]->val3; - if (sc->data[SC_PYROTECHNIC_OPTION]) - watk += sc->data[SC_PYROTECHNIC_OPTION]->val2; - if ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) - || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) - || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2) - || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) - ) - watk += watk / 10; - if (sc && sc->data[SC_TIDAL_WEAPON]) - watk += watk * sc->data[SC_TIDAL_WEAPON]->val2 / 100; - if (sc->data[SC_ANGRIFFS_MODUS]) - watk += watk * sc->data[SC_ANGRIFFS_MODUS]->val2/100; + if(!sc || !sc->count) + return cap_value(watk,0,USHRT_MAX); + + if(sc->data[SC_IMPOSITIO]) + watk += sc->data[SC_IMPOSITIO]->val2; + if(sc->data[SC_WATKFOOD]) + watk += sc->data[SC_WATKFOOD]->val1; + if(sc->data[SC_DRUMBATTLE]) + watk += sc->data[SC_DRUMBATTLE]->val2; + if(sc->data[SC_VOLCANO]) + watk += sc->data[SC_VOLCANO]->val2; + if(sc->data[SC_INCATKRATE]) + watk += watk * sc->data[SC_INCATKRATE]->val1/100; + if(sc->data[SC_PROVOKE]) + watk += watk * sc->data[SC_PROVOKE]->val3/100; + if(sc->data[SC_CONCENTRATION]) + watk += watk * sc->data[SC_CONCENTRATION]->val2/100; + if(sc->data[SC_SKE]) + watk += watk * 3; + if(sc->data[SC_NIBELUNGEN]) { + if (bl->type != BL_PC) + watk += sc->data[SC_NIBELUNGEN]->val2; + else { + #ifndef RENEWAL + TBL_PC *sd = (TBL_PC*)bl; + int index = sd->equip_index[sd->state.lr_flag?EQI_HAND_L:EQI_HAND_R]; + if(index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->wlv == 4) + #endif + watk += sc->data[SC_NIBELUNGEN]->val2; + } + } + if(sc->data[SC__ENERVATION]) + watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; + if(sc->data[SC_FLEET]) + watk += watk * sc->data[SC_FLEET]->val3/100; + if(sc->data[SC_CURSE]) + watk -= watk * 25/100; + if(sc->data[SC_STRIPWEAPON]) + watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100; + if(sc->data[SC_MERC_ATKUP]) + watk += sc->data[SC_MERC_ATKUP]->val2; + if(sc->data[SC_FIGHTINGSPIRIT]) + watk += sc->data[SC_FIGHTINGSPIRIT]->val1; + if(sc->data[SC__ENERVATION]) + watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; + if(sc->data[SC_STRIKING]) + watk += sc->data[SC_STRIKING]->val2; + if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3) + watk += sc->data[SC_SHIELDSPELL_DEF]->val2; + if(sc->data[SC_INSPIRATION]) + watk += sc->data[SC_INSPIRATION]->val2; + if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 ) + watk += (10 + 10 * sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); + if( sc->data[SC_TROPIC_OPTION] ) + watk += sc->data[SC_TROPIC_OPTION]->val2; + if( sc->data[SC_HEATER_OPTION] ) + watk += sc->data[SC_HEATER_OPTION]->val2; + if( sc->data[SC_WATER_BARRIER] ) + watk -= sc->data[SC_WATER_BARRIER]->val3; + if( sc->data[SC_PYROTECHNIC_OPTION] ) + watk += sc->data[SC_PYROTECHNIC_OPTION]->val2; + if((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) + || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) + || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2) + || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) + ) + watk += watk / 10; + if( sc && sc->data[SC_TIDAL_WEAPON] ) + watk += watk * sc->data[SC_TIDAL_WEAPON]->val2 / 100; + if(sc->data[SC_ANGRIFFS_MODUS]) + watk += watk * sc->data[SC_ANGRIFFS_MODUS]->val2/100; #ifdef RENEWAL_EDP - if (sc->data[SC_EDP]) - watk = watk * (100 + sc->data[SC_EDP]->val1 * 80) / 100; + if( sc->data[SC_EDP] ) + watk = watk * (100 + sc->data[SC_EDP]->val1 * 80) / 100; #endif - return (unsigned short)cap_value(watk,0,USHRT_MAX); -} -#ifdef RENEWAL -static unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc, int matk) -{ - - if (!sc || !sc->count) - return cap_value(matk,0,USHRT_MAX); - if (sc->data[SC_MATKPOTION]) - matk += sc->data[SC_MATKPOTION]->val1; - if (sc->data[SC_MATKFOOD]) - matk += sc->data[SC_MATKFOOD]->val1; - if (sc->data[SC_MANA_PLUS]) - matk += sc->data[SC_MANA_PLUS]->val1; - if (sc->data[SC_AQUAPLAY_OPTION]) - matk += sc->data[SC_AQUAPLAY_OPTION]->val2; - if (sc->data[SC_CHILLY_AIR_OPTION]) - matk += sc->data[SC_CHILLY_AIR_OPTION]->val2; - if (sc->data[SC_WATER_BARRIER]) - matk -= sc->data[SC_WATER_BARRIER]->val3; - if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3) - matk += 50; - if (sc->data[SC_ODINS_POWER]) - matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2 - if (sc->data[SC_IZAYOI]) - matk += 50 * sc->data[SC_IZAYOI]->val1; - - return (unsigned short)cap_value(matk,0,USHRT_MAX); + return (unsigned short)cap_value(watk,0,USHRT_MAX); } -#endif + static unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk) { - if (!sc || !sc->count) - return cap_value(matk,0,USHRT_MAX); -#ifndef RENEWAL - // take note fixed value first before % modifiers - if (sc->data[SC_MATKPOTION]) - matk += sc->data[SC_MATKPOTION]->val1; - if (sc->data[SC_MATKFOOD]) - matk += sc->data[SC_MATKFOOD]->val1; - if (sc->data[SC_MANA_PLUS]) - matk += sc->data[SC_MANA_PLUS]->val1; - if (sc->data[SC_AQUAPLAY_OPTION]) - matk += sc->data[SC_AQUAPLAY_OPTION]->val2; - if (sc->data[SC_CHILLY_AIR_OPTION]) - matk += sc->data[SC_CHILLY_AIR_OPTION]->val2; - if (sc->data[SC_WATER_BARRIER]) - matk -= sc->data[SC_WATER_BARRIER]->val3; - if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3) - matk += 50; - if (sc->data[SC_ODINS_POWER]) - matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2 - if (sc->data[SC_IZAYOI]) - matk += 50 * sc->data[SC_IZAYOI]->val1; -#endif - if (sc->data[SC_MAGICPOWER]) - matk += matk * sc->data[SC_MAGICPOWER]->val3/100; - if (sc->data[SC_MINDBREAKER]) - matk += matk * sc->data[SC_MINDBREAKER]->val2/100; - if (sc->data[SC_INCMATKRATE]) - matk += matk * sc->data[SC_INCMATKRATE]->val1/100; - if (sc->data[SC_MOONLITSERENADE]) - matk += matk * sc->data[SC_MOONLITSERENADE]->val2/100; - if (sc->data[SC_MELODYOFSINK]) - matk += matk * sc->data[SC_MELODYOFSINK]->val3/100; - if (sc->data[SC_BEYONDOFWARCRY]) - matk -= matk * sc->data[SC_BEYONDOFWARCRY]->val3/100; - if (sc->data[SC_ZANGETSU]) - matk += matk * sc->data[SC_ZANGETSU]->val2 / 100; - - return (unsigned short)cap_value(matk,0,USHRT_MAX); + if(!sc || !sc->count) + return cap_value(matk,0,USHRT_MAX); + + if(sc->data[SC_MATKPOTION]) + matk += sc->data[SC_MATKPOTION]->val1; + if(sc->data[SC_MATKFOOD]) + matk += sc->data[SC_MATKFOOD]->val1; + if(sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4) + matk += matk * sc->data[SC_MAGICPOWER]->val3/100; + if(sc->data[SC_MINDBREAKER]) + matk += matk * sc->data[SC_MINDBREAKER]->val2/100; + if(sc->data[SC_INCMATKRATE]) + matk += matk * sc->data[SC_INCMATKRATE]->val1/100; + if(sc->data[SC_MOONLITSERENADE]) + matk += matk * sc->data[SC_MOONLITSERENADE]->val2/100; + if(sc->data[SC_MELODYOFSINK]) + matk += matk * sc->data[SC_MELODYOFSINK]->val3/100; + if(sc->data[SC_BEYONDOFWARCRY]) + matk -= matk * sc->data[SC_BEYONDOFWARCRY]->val3/100; + if(sc->data[SC_MANA_PLUS]) + matk += sc->data[SC_MANA_PLUS]->val1; + if(sc->data[SC_AQUAPLAY_OPTION]) + matk += sc->data[SC_AQUAPLAY_OPTION]->val2; + if(sc->data[SC_CHILLY_AIR_OPTION]) + matk += sc->data[SC_CHILLY_AIR_OPTION]->val2; + if(sc->data[SC_WATER_BARRIER]) + matk -= sc->data[SC_WATER_BARRIER]->val3; + if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3) + matk += 50; + if(sc->data[SC_ODINS_POWER]) + matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2 + if(sc->data[SC_IZAYOI]) + matk += 50 * sc->data[SC_IZAYOI]->val1; + if( sc->data[SC_ZANGETSU] ) + matk += matk * sc->data[SC_ZANGETSU]->val2 / 100; + + return (unsigned short)cap_value(matk,0,USHRT_MAX); } -static signed short status_calc_critical(struct block_list *bl, struct status_change *sc, int critical) -{ - - if (!sc || !sc->count) - return cap_value(critical,10,SHRT_MAX); - - if (sc->data[SC_INCCRI]) - critical += sc->data[SC_INCCRI]->val2; - if (sc->data[SC_EXPLOSIONSPIRITS]) - critical += sc->data[SC_EXPLOSIONSPIRITS]->val2; - if (sc->data[SC_FORTUNE]) - critical += sc->data[SC_FORTUNE]->val2; - if (sc->data[SC_TRUESIGHT]) - critical += sc->data[SC_TRUESIGHT]->val2; - if (sc->data[SC_CLOAKING]) - critical += critical; - if (sc->data[SC_STRIKING]) - critical += sc->data[SC_STRIKING]->val1; - if (sc->data[SC__INVISIBILITY]) - critical += critical * sc->data[SC__INVISIBILITY]->val3 / 100; - if (sc->data[SC__UNLUCKY]) - critical -= critical * sc->data[SC__UNLUCKY]->val2 / 100; +static signed short status_calc_critical(struct block_list *bl, struct status_change *sc, int critical) { + + if(!sc || !sc->count) + return cap_value(critical,10,SHRT_MAX); + + if (sc->data[SC_INCCRI]) + critical += sc->data[SC_INCCRI]->val2; + if (sc->data[SC_EXPLOSIONSPIRITS]) + critical += sc->data[SC_EXPLOSIONSPIRITS]->val2; + if (sc->data[SC_FORTUNE]) + critical += sc->data[SC_FORTUNE]->val2; + if (sc->data[SC_TRUESIGHT]) + critical += sc->data[SC_TRUESIGHT]->val2; + if(sc->data[SC_CLOAKING]) + critical += critical; + if(sc->data[SC_STRIKING]) + critical += sc->data[SC_STRIKING]->val1; + if(sc->data[SC__INVISIBILITY]) + critical += critical * sc->data[SC__INVISIBILITY]->val3 / 100; + if(sc->data[SC__UNLUCKY]) + critical -= critical * sc->data[SC__UNLUCKY]->val2 / 100; #ifdef RENEWAL - if (sc->data[SC_SPEARQUICKEN]) - critical += 3*sc->data[SC_SPEARQUICKEN]->val1*10; + if (sc->data[SC_SPEARQUICKEN]) + critical += 3*sc->data[SC_SPEARQUICKEN]->val1*10; #endif - return (short)cap_value(critical,10,SHRT_MAX); + return (short)cap_value(critical,10,SHRT_MAX); } static signed short status_calc_hit(struct block_list *bl, struct status_change *sc, int hit) { - if (!sc || !sc->count) - return cap_value(hit,1,SHRT_MAX); - - if (sc->data[SC_INCHIT]) - hit += sc->data[SC_INCHIT]->val1; - if (sc->data[SC_HITFOOD]) - hit += sc->data[SC_HITFOOD]->val1; - if (sc->data[SC_TRUESIGHT]) - hit += sc->data[SC_TRUESIGHT]->val3; - if (sc->data[SC_HUMMING]) - hit += sc->data[SC_HUMMING]->val2; - if (sc->data[SC_CONCENTRATION]) - hit += sc->data[SC_CONCENTRATION]->val3; - if (sc->data[SC_INCHITRATE]) - hit += hit * sc->data[SC_INCHITRATE]->val1/100; - if (sc->data[SC_BLIND]) - hit -= hit * 25/100; - if (sc->data[SC_ADJUSTMENT]) - hit -= 30; - if (sc->data[SC_INCREASING]) - hit += 20; // RockmanEXE; changed based on updated [Reddozen] - if (sc->data[SC_MERC_HITUP]) - hit += sc->data[SC_MERC_HITUP]->val2; - if (sc->data[SC__GROOMY]) - hit -= hit * sc->data[SC__GROOMY]->val3 / 100; - if (sc->data[SC_FEAR]) - hit -= hit * 20 / 100; - if (sc->data[SC_INSPIRATION]) - hit += 5 * sc->data[SC_INSPIRATION]->val1; - if (sc->data[SC_ASH]) - hit /= 2; - - return (short)cap_value(hit,1,SHRT_MAX); + if(!sc || !sc->count) + return cap_value(hit,1,SHRT_MAX); + + if(sc->data[SC_INCHIT]) + hit += sc->data[SC_INCHIT]->val1; + if(sc->data[SC_HITFOOD]) + hit += sc->data[SC_HITFOOD]->val1; + if(sc->data[SC_TRUESIGHT]) + hit += sc->data[SC_TRUESIGHT]->val3; + if(sc->data[SC_HUMMING]) + hit += sc->data[SC_HUMMING]->val2; + if(sc->data[SC_CONCENTRATION]) + hit += sc->data[SC_CONCENTRATION]->val3; + if(sc->data[SC_INCHITRATE]) + hit += hit * sc->data[SC_INCHITRATE]->val1/100; + if(sc->data[SC_BLIND]) + hit -= hit * 25/100; + if(sc->data[SC_ADJUSTMENT]) + hit -= 30; + if(sc->data[SC_INCREASING]) + hit += 20; // RockmanEXE; changed based on updated [Reddozen] + if(sc->data[SC_MERC_HITUP]) + hit += sc->data[SC_MERC_HITUP]->val2; + if(sc->data[SC__GROOMY]) + hit -= hit * sc->data[SC__GROOMY]->val3 / 100; + if(sc->data[SC_FEAR]) + hit -= hit * 20 / 100; + if(sc->data[SC_INSPIRATION]) + hit += 5 * sc->data[SC_INSPIRATION]->val1; + if (sc->data[SC_ASH]) + hit /= 2; + + return (short)cap_value(hit,1,SHRT_MAX); } static signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee) { - if (bl->type == BL_PC) { - if (map_flag_gvg(bl->m)) - flee -= flee * battle_config.gvg_flee_penalty/100; - else if (map[bl->m].flag.battleground) - flee -= flee * battle_config.bg_flee_penalty/100; - } - - if (!sc || !sc->count) - return cap_value(flee,1,SHRT_MAX); - - if (sc->data[SC_INCFLEE]) - flee += sc->data[SC_INCFLEE]->val1; - if (sc->data[SC_FLEEFOOD]) - flee += sc->data[SC_FLEEFOOD]->val1; - if (sc->data[SC_WHISTLE]) - flee += sc->data[SC_WHISTLE]->val2; - if (sc->data[SC_WINDWALK]) - flee += sc->data[SC_WINDWALK]->val2; - if (sc->data[SC_INCFLEERATE]) - flee += flee * sc->data[SC_INCFLEERATE]->val1/100; - if (sc->data[SC_VIOLENTGALE]) - flee += sc->data[SC_VIOLENTGALE]->val2; - if (sc->data[SC_MOON_COMFORT]) //SG skill [Komurka] - flee += sc->data[SC_MOON_COMFORT]->val2; - if (sc->data[SC_CLOSECONFINE]) - flee += 10; - if (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) - flee -= flee * 50/100; - if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) - flee -= flee * 50/100; - if (sc->data[SC_BLIND]) - flee -= flee * 25/100; - if (sc->data[SC_ADJUSTMENT]) - flee += 30; - if (sc->data[SC_GATLINGFEVER]) - flee -= sc->data[SC_GATLINGFEVER]->val4; - if (sc->data[SC_SPEED]) - flee += 10 + sc->data[SC_SPEED]->val1 * 10; - if (sc->data[SC_PARTYFLEE]) - flee += sc->data[SC_PARTYFLEE]->val1 * 10; - if (sc->data[SC_MERC_FLEEUP]) - flee += sc->data[SC_MERC_FLEEUP]->val2; - if (sc->data[SC_FEAR]) - flee -= flee * 20 / 100; - if (sc->data[SC_PARALYSE]) - flee -= flee * 10 / 100; // 10% Flee reduction - if (sc->data[SC_INFRAREDSCAN]) - flee -= flee * 30 / 100; - if (sc->data[SC__LAZINESS]) - flee -= flee * sc->data[SC__LAZINESS]->val3 / 100; - if (sc->data[SC_GLOOMYDAY]) - flee -= flee * sc->data[SC_GLOOMYDAY]->val2 / 100; - if (sc->data[SC_HALLUCINATIONWALK]) - flee += sc->data[SC_HALLUCINATIONWALK]->val2; - if (sc->data[SC_SATURDAYNIGHTFEVER]) - flee -= flee * (40 + 10 * sc->data[SC_SATURDAYNIGHTFEVER]->val1) / 100; - if (sc->data[SC_WATER_BARRIER]) - flee -= sc->data[SC_WATER_BARRIER]->val3; - if (sc->data[SC_WIND_STEP_OPTION]) - flee += flee * sc->data[SC_WIND_STEP_OPTION]->val2 / 100; - if (sc->data[SC_ZEPHYR]) - flee += flee * sc->data[SC_ZEPHYR]->val2 / 100; - if (sc->data[SC_MARSHOFABYSS]) - flee -= (9 * sc->data[SC_MARSHOFABYSS]->val3 / 10 + sc->data[SC_MARSHOFABYSS]->val2 / 10) * (bl->type == BL_MOB ? 2 : 1); + if( bl->type == BL_PC ) + { + if( map_flag_gvg(bl->m) ) + flee -= flee * battle_config.gvg_flee_penalty/100; + else if( map[bl->m].flag.battleground ) + flee -= flee * battle_config.bg_flee_penalty/100; + } + + if(!sc || !sc->count) + return cap_value(flee,1,SHRT_MAX); + + if(sc->data[SC_INCFLEE]) + flee += sc->data[SC_INCFLEE]->val1; + if(sc->data[SC_FLEEFOOD]) + flee += sc->data[SC_FLEEFOOD]->val1; + if(sc->data[SC_WHISTLE]) + flee += sc->data[SC_WHISTLE]->val2; + if(sc->data[SC_WINDWALK]) + flee += sc->data[SC_WINDWALK]->val2; + if(sc->data[SC_INCFLEERATE]) + flee += flee * sc->data[SC_INCFLEERATE]->val1/100; + if(sc->data[SC_VIOLENTGALE]) + flee += sc->data[SC_VIOLENTGALE]->val2; + if(sc->data[SC_MOON_COMFORT]) //SG skill [Komurka] + flee += sc->data[SC_MOON_COMFORT]->val2; + if(sc->data[SC_CLOSECONFINE]) + flee += 10; + if(sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) + flee -= flee * 50/100; + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) + flee -= flee * 50/100; + if(sc->data[SC_BLIND]) + flee -= flee * 25/100; + if(sc->data[SC_ADJUSTMENT]) + flee += 30; + if(sc->data[SC_GATLINGFEVER]) + flee -= sc->data[SC_GATLINGFEVER]->val4; + if(sc->data[SC_SPEED]) + flee += 10 + sc->data[SC_SPEED]->val1 * 10; + if(sc->data[SC_PARTYFLEE]) + flee += sc->data[SC_PARTYFLEE]->val1 * 10; + if(sc->data[SC_MERC_FLEEUP]) + flee += sc->data[SC_MERC_FLEEUP]->val2; + if(sc->data[SC_FEAR]) + flee -= flee * 20 / 100; + if(sc->data[SC_PARALYSE]) + flee -= flee * 10 / 100; // 10% Flee reduction + if(sc->data[SC_INFRAREDSCAN]) + flee -= flee * 30 / 100; + if( sc->data[SC__LAZINESS] ) + flee -= flee * sc->data[SC__LAZINESS]->val3 / 100; + if( sc->data[SC_GLOOMYDAY] ) + flee -= flee * sc->data[SC_GLOOMYDAY]->val2 / 100; + if( sc->data[SC_HALLUCINATIONWALK] ) + flee += sc->data[SC_HALLUCINATIONWALK]->val2; + if( sc->data[SC_SATURDAYNIGHTFEVER] ) + flee -= flee * (40 + 10 * sc->data[SC_SATURDAYNIGHTFEVER]->val1) / 100; + if( sc->data[SC_WATER_BARRIER] ) + flee -= sc->data[SC_WATER_BARRIER]->val3; + if( sc->data[SC_WIND_STEP_OPTION] ) + flee += flee * sc->data[SC_WIND_STEP_OPTION]->val2 / 100; + if( sc->data[SC_ZEPHYR] ) + flee += flee * sc->data[SC_ZEPHYR]->val2 / 100; + if( sc->data[SC_MARSHOFABYSS] ) + flee -= (9 * sc->data[SC_MARSHOFABYSS]->val3 / 10 + sc->data[SC_MARSHOFABYSS]->val2 / 10) * (bl->type == BL_MOB ? 2 : 1); #ifdef RENEWAL - if (sc->data[SC_SPEARQUICKEN]) - flee += 2 * sc->data[SC_SPEARQUICKEN]->val1; + if( sc->data[SC_SPEARQUICKEN] ) + flee += 2 * sc->data[SC_SPEARQUICKEN]->val1; #endif - if (sc->data[SC_ANGRIFFS_MODUS]) - flee -= sc->data[SC_ANGRIFFS_MODUS]->val3; - if (sc->data[SC_OVERED_BOOST]) - flee = max(flee,sc->data[SC_OVERED_BOOST]->val2); - if (sc->data[SC_ASH] && (bl->type==BL_MOB)) { //mob - if (status_get_element(bl) == ELE_WATER) //water type - flee /= 2; - } - - return (short)cap_value(flee,1,SHRT_MAX); + if (sc->data[SC_ANGRIFFS_MODUS]) + flee -= sc->data[SC_ANGRIFFS_MODUS]->val3; + if (sc->data[SC_OVERED_BOOST]) + flee = max(flee,sc->data[SC_OVERED_BOOST]->val2); + if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ //mob + if(status_get_element(bl) == ELE_WATER) //water type + flee /= 2; + } + + return (short)cap_value(flee,1,SHRT_MAX); } static signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2) { - if (!sc || !sc->count) - return cap_value(flee2,10,SHRT_MAX); + if(!sc || !sc->count) + return cap_value(flee2,10,SHRT_MAX); - if (sc->data[SC_INCFLEE2]) - flee2 += sc->data[SC_INCFLEE2]->val2; - if (sc->data[SC_WHISTLE]) - flee2 += sc->data[SC_WHISTLE]->val3*10; - if (sc->data[SC__UNLUCKY]) - flee2 -= flee2 * sc->data[SC__UNLUCKY]->val2 / 100; + if(sc->data[SC_INCFLEE2]) + flee2 += sc->data[SC_INCFLEE2]->val2; + if(sc->data[SC_WHISTLE]) + flee2 += sc->data[SC_WHISTLE]->val3*10; + if(sc->data[SC__UNLUCKY]) + flee2 -= flee2 * sc->data[SC__UNLUCKY]->val2 / 100; - return (short)cap_value(flee2,10,SHRT_MAX); + return (short)cap_value(flee2,10,SHRT_MAX); } -static defType status_calc_def(struct block_list *bl, struct status_change *sc, int def) -{ - - if (!sc || !sc->count) - return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); - - if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) - return 0; - if (sc->data[SC_SKA]) - return sc->data[SC_SKA]->val3; - if (sc->data[SC_BARRIER]) - return 100; - if (sc->data[SC_KEEPING]) - return 90; +static defType status_calc_def(struct block_list *bl, struct status_change *sc, int def) { + + if(!sc || !sc->count) + return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); + + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) + return 0; + if(sc->data[SC_SKA]) + return sc->data[SC_SKA]->val3; + if(sc->data[SC_BARRIER]) + return 100; + if(sc->data[SC_KEEPING]) + return 90; #ifndef RENEWAL // does not provide 90 DEF in renewal mode - if (sc->data[SC_STEELBODY]) - return 90; + if(sc->data[SC_STEELBODY]) + return 90; #endif - if (sc->data[SC_ARMORCHANGE]) - def += sc->data[SC_ARMORCHANGE]->val2; - if (sc->data[SC_DRUMBATTLE]) - def += sc->data[SC_DRUMBATTLE]->val3; - if (sc->data[SC_DEFENCE]) //[orn] - def += sc->data[SC_DEFENCE]->val2 ; - if (sc->data[SC_INCDEFRATE]) - def += def * sc->data[SC_INCDEFRATE]->val1/100; - if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) - def >>=1; - if (sc->data[SC_FREEZE]) - def >>=1; + if(sc->data[SC_ARMORCHANGE]) + def += sc->data[SC_ARMORCHANGE]->val2; + if(sc->data[SC_DRUMBATTLE]) + def += sc->data[SC_DRUMBATTLE]->val3; + if(sc->data[SC_DEFENCE]) //[orn] + def += sc->data[SC_DEFENCE]->val2 ; + if(sc->data[SC_INCDEFRATE]) + def += def * sc->data[SC_INCDEFRATE]->val1/100; + if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) + def >>=1; + if(sc->data[SC_FREEZE]) + def >>=1; #ifdef RENEWAL - if (sc->data[SC_ASSUMPTIO]) - def *= 2; + if(sc->data[SC_ASSUMPTIO]) + def *= 2; #endif - if (sc->data[SC_SIGNUMCRUCIS]) - def -= def * sc->data[SC_SIGNUMCRUCIS]->val2/100; - if (sc->data[SC_CONCENTRATION]) - def -= def * sc->data[SC_CONCENTRATION]->val4/100; - if (sc->data[SC_SKE]) - def >>=1; - if (sc->data[SC_PROVOKE] && bl->type != BL_PC) // Provoke doesn't alter player defense-> - def -= def * sc->data[SC_PROVOKE]->val4/100; - if (sc->data[SC_STRIPSHIELD]) - def -= def * sc->data[SC_STRIPSHIELD]->val2/100; - if (sc->data[SC_FLING]) - def -= def * (sc->data[SC_FLING]->val2)/100; - if (sc->data[SC_STONEHARDSKIN]) // Final DEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] - def += sc->data[SC_STONEHARDSKIN]->val1; - if (sc->data[SC_FREEZING]) - def -= def * 10 / 100; - if (sc->data[SC_MARSHOFABYSS]) - def -= def * (6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36) / 100; - if (sc->data[SC_ANALYZE]) - def -= def * (14 * sc->data[SC_ANALYZE]->val1) / 100; - if (sc->data[SC_FORCEOFVANGUARD]) - def += def * 2 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100; - if (sc->data[SC_SATURDAYNIGHTFEVER]) - def -= def * (10 + 10 * sc->data[SC_SATURDAYNIGHTFEVER]->val1) / 100; - if (sc->data[SC_EARTHDRIVE]) - def -= def * 25 / 100; - if (sc->data[SC_ROCK_CRUSHER]) - def -= def * sc->data[SC_ROCK_CRUSHER]->val2 / 100; - if (sc->data[SC_POWER_OF_GAIA]) - def += def * sc->data[SC_POWER_OF_GAIA]->val2 / 100; - if (sc->data[SC_PRESTIGE]) - def += def * sc->data[SC_PRESTIGE]->val1 / 100; - if (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) - def += 50; - if (sc->data[SC_ODINS_POWER]) - def -= 20; - if (sc->data[SC_ANGRIFFS_MODUS]) - def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1; - if (sc->data[SC_ASH] && (bl->type==BL_MOB)) { - if (status_get_race(bl)==RC_PLANT) - def /= 2; - } - - return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);; + if(sc->data[SC_SIGNUMCRUCIS]) + def -= def * sc->data[SC_SIGNUMCRUCIS]->val2/100; + if(sc->data[SC_CONCENTRATION]) + def -= def * sc->data[SC_CONCENTRATION]->val4/100; + if(sc->data[SC_SKE]) + def >>=1; + if(sc->data[SC_PROVOKE] && bl->type != BL_PC) // Provoke doesn't alter player defense-> + def -= def * sc->data[SC_PROVOKE]->val4/100; + if(sc->data[SC_STRIPSHIELD]) + def -= def * sc->data[SC_STRIPSHIELD]->val2/100; + if (sc->data[SC_FLING]) + def -= def * (sc->data[SC_FLING]->val2)/100; + if(sc->data[SC_STONEHARDSKIN])// Final DEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] + def += sc->data[SC_STONEHARDSKIN]->val1; + if( sc->data[SC_FREEZING] ) + def -= def * 10 / 100; + if( sc->data[SC_MARSHOFABYSS] ) + def -= def * ( 6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36 ) / 100; + if( sc->data[SC_ANALYZE] ) + def -= def * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; + if( sc->data[SC_FORCEOFVANGUARD] ) + def += def * 2 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100; + if(sc->data[SC_SATURDAYNIGHTFEVER]) + def -= def * (10 + 10 * sc->data[SC_SATURDAYNIGHTFEVER]->val1) / 100; + if(sc->data[SC_EARTHDRIVE]) + def -= def * 25 / 100; + if( sc->data[SC_ROCK_CRUSHER] ) + def -= def * sc->data[SC_ROCK_CRUSHER]->val2 / 100; + if( sc->data[SC_POWER_OF_GAIA] ) + def += def * sc->data[SC_POWER_OF_GAIA]->val2 / 100; + if( sc->data[SC_PRESTIGE] ) + def += def * sc->data[SC_PRESTIGE]->val1 / 100; + if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) + def += 50; + if(sc->data[SC_ODINS_POWER]) + def -= 20; + if( sc->data[SC_ANGRIFFS_MODUS] ) + def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1; + if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ + if(status_get_race(bl)==RC_PLANT) + def /= 2; + } + + return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);; } static signed short status_calc_def2(struct block_list *bl, struct status_change *sc, int def2) { - if (!sc || !sc->count) + if(!sc || !sc->count) #ifdef RENEWAL - return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); + return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); #else - return (short)cap_value(def2,1,SHRT_MAX); + return (short)cap_value(def2,1,SHRT_MAX); #endif - if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) - return 0; - if (sc->data[SC_ETERNALCHAOS]) - return 0; - if (sc->data[SC_SUN_COMFORT]) - def2 += sc->data[SC_SUN_COMFORT]->val2; + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) + return 0; + if(sc->data[SC_ETERNALCHAOS]) + return 0; + if(sc->data[SC_SUN_COMFORT]) + def2 += sc->data[SC_SUN_COMFORT]->val2; - if (sc->data[SC_ANGELUS]) + if(sc->data[SC_ANGELUS]) #ifdef RENEWAL //in renewal only the VIT stat bonus is boosted by angelus - def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100; + def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100; #else - def2 += def2 * sc->data[SC_ANGELUS]->val2/100; + def2 += def2 * sc->data[SC_ANGELUS]->val2/100; #endif - if (sc->data[SC_CONCENTRATION]) - def2 -= def2 * sc->data[SC_CONCENTRATION]->val4/100; - if (sc->data[SC_POISON]) - def2 -= def2 * 25/100; - if (sc->data[SC_DPOISON]) - def2 -= def2 * 25/100; - if (sc->data[SC_SKE]) - def2 -= def2 * 50/100; - if (sc->data[SC_PROVOKE]) - def2 -= def2 * sc->data[SC_PROVOKE]->val4/100; + if(sc->data[SC_CONCENTRATION]) + def2 -= def2 * sc->data[SC_CONCENTRATION]->val4/100; + if(sc->data[SC_POISON]) + def2 -= def2 * 25/100; + if(sc->data[SC_DPOISON]) + def2 -= def2 * 25/100; + if(sc->data[SC_SKE]) + def2 -= def2 * 50/100; + if(sc->data[SC_PROVOKE]) + def2 -= def2 * sc->data[SC_PROVOKE]->val4/100; #ifdef RENEWAL - if (sc->data[SC_ASSUMPTIO]) - def2 *= 2; + if(sc->data[SC_ASSUMPTIO]) + def2 *= 2; #endif - if (sc->data[SC_JOINTBEAT]) - def2 -= def2 * (sc->data[SC_JOINTBEAT]->val2&BREAK_SHOULDER ? 50 : 0) / 100 - + def2 * (sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST ? 25 : 0) / 100; - if (sc->data[SC_FLING]) - def2 -= def2 * (sc->data[SC_FLING]->val3)/100; - if (sc->data[SC_FREEZING]) - def2 -= def2 * 3 / 10; - if (sc->data[SC_ANALYZE]) - def2 -= def2 * (14 * sc->data[SC_ANALYZE]->val1) / 100; - if (sc->data[SC_ECHOSONG]) - def2 += def2 * sc->data[SC_ECHOSONG]->val2/100; - if (sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1) - def2 += sc->data[SC_SHIELDSPELL_REF]->val2; - if (sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0) - def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); - if (sc->data[SC_GT_REVITALIZE] && sc->data[SC_GT_REVITALIZE]->val4) - def2 += def2 * sc->data[SC_GT_REVITALIZE]->val4 / 100; - if (sc->data[SC_ASH] && (bl->type==BL_MOB)) { - if (status_get_race(bl)==RC_PLANT) - def2 /= 2; - } - if (sc->data[SC_PARALYSIS]) - def2 -= def2 * sc->data[SC_PARALYSIS]->val2 / 100; + if(sc->data[SC_JOINTBEAT]) + def2 -= def2 * ( sc->data[SC_JOINTBEAT]->val2&BREAK_SHOULDER ? 50 : 0 ) / 100 + + def2 * ( sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST ? 25 : 0 ) / 100; + if(sc->data[SC_FLING]) + def2 -= def2 * (sc->data[SC_FLING]->val3)/100; + if( sc->data[SC_FREEZING] ) + def2 -= def2 * 3 / 10; + if(sc->data[SC_ANALYZE]) + def2 -= def2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; + if( sc->data[SC_ECHOSONG] ) + def2 += def2 * sc->data[SC_ECHOSONG]->val2/100; + if( sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 ) + def2 += sc->data[SC_SHIELDSPELL_REF]->val2; + if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 ) + def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); + if( sc->data[SC_GT_REVITALIZE] && sc->data[SC_GT_REVITALIZE]->val4) + def2 += def2 * sc->data[SC_GT_REVITALIZE]->val4 / 100; + if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ + if(status_get_race(bl)==RC_PLANT) + def2 /= 2; + } + if (sc->data[SC_PARALYSIS]) + def2 -= def2 * sc->data[SC_PARALYSIS]->val2 / 100; #ifdef RENEWAL - return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); + return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); #else - return (short)cap_value(def2,1,SHRT_MAX); + return (short)cap_value(def2,1,SHRT_MAX); #endif } -static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef) -{ +static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef) { - if (!sc || !sc->count) - return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); + if(!sc || !sc->count) + return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); - if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) - return 0; - if (sc->data[SC_BARRIER]) - return 100; + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) + return 0; + if(sc->data[SC_BARRIER]) + return 100; #ifndef RENEWAL // no longer provides 90 MDEF in renewal mode - if (sc->data[SC_STEELBODY]) - return 90; + if(sc->data[SC_STEELBODY]) + return 90; #endif - if (sc->data[SC_ARMORCHANGE]) - mdef += sc->data[SC_ARMORCHANGE]->val3; - if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) - mdef += 25*mdef/100; - if (sc->data[SC_FREEZE]) - mdef += 25*mdef/100; - if (sc->data[SC_ENDURE]) // It has been confirmed that eddga card grants 1 MDEF, not 0, not 10, but 1. - mdef += (sc->data[SC_ENDURE]->val4 == 0) ? sc->data[SC_ENDURE]->val1 : 1; - if (sc->data[SC_CONCENTRATION]) - mdef += 1; //Skill info says it adds a fixed 1 Mdef point. + if(sc->data[SC_ARMORCHANGE]) + mdef += sc->data[SC_ARMORCHANGE]->val3; + if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) + mdef += 25*mdef/100; + if(sc->data[SC_FREEZE]) + mdef += 25*mdef/100; + if(sc->data[SC_ENDURE])// It has been confirmed that eddga card grants 1 MDEF, not 0, not 10, but 1. + mdef += (sc->data[SC_ENDURE]->val4 == 0) ? sc->data[SC_ENDURE]->val1 : 1; + if(sc->data[SC_CONCENTRATION]) + mdef += 1; //Skill info says it adds a fixed 1 Mdef point. #ifdef RENEWAL - if (sc->data[SC_ASSUMPTIO]) - mdef *= 2; + if(sc->data[SC_ASSUMPTIO]) + mdef *= 2; #endif - if (sc->data[SC_STONEHARDSKIN]) // Final MDEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] - mdef += sc->data[SC_STONEHARDSKIN]->val1; - if (sc->data[SC_MARSHOFABYSS]) - mdef -= mdef * (6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36) / 100; - if (sc->data[SC_ANALYZE]) - mdef -= mdef * (14 * sc->data[SC_ANALYZE]->val1) / 100; - if (sc->data[SC_SYMPHONYOFLOVER]) - mdef += mdef * sc->data[SC_SYMPHONYOFLOVER]->val2 / 100; - if (sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val4) - mdef -= mdef * sc->data[SC_GT_CHANGE]->val4 / 100; - if (sc->data[SC_WATER_BARRIER]) - mdef += sc->data[SC_WATER_BARRIER]->val2; - if (sc->data[SC_ODINS_POWER]) - mdef -= 20 * sc->data[SC_ODINS_POWER]->val1; - if (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3) - mdef += 50; - - return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); + if(sc->data[SC_STONEHARDSKIN])// Final MDEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] + mdef += sc->data[SC_STONEHARDSKIN]->val1; + if( sc->data[SC_MARSHOFABYSS] ) + mdef -= mdef * ( 6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36 ) / 100; + if(sc->data[SC_ANALYZE]) + mdef -= mdef * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; + if(sc->data[SC_SYMPHONYOFLOVER]) + mdef += mdef * sc->data[SC_SYMPHONYOFLOVER]->val2 / 100; + if(sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val4) + mdef -= mdef * sc->data[SC_GT_CHANGE]->val4 / 100; + if(sc->data[SC_WATER_BARRIER]) + mdef += sc->data[SC_WATER_BARRIER]->val2; + if (sc->data[SC_ODINS_POWER]) + mdef -= 20 * sc->data[SC_ODINS_POWER]->val1; + if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3) + mdef += 50; + + return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); } static signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, int mdef2) { - if (!sc || !sc->count) + if(!sc || !sc->count) #ifdef RENEWAL - return (short)cap_value(mdef2,SHRT_MIN,SHRT_MAX); + return (short)cap_value(mdef2,SHRT_MIN,SHRT_MAX); #else - return (short)cap_value(mdef2,1,SHRT_MAX); + return (short)cap_value(mdef2,1,SHRT_MAX); #endif - if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) - return 0; - if (sc->data[SC_SKA]) - return 90; + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) + return 0; + if(sc->data[SC_SKA]) + return 90; #ifdef RENEWAL - if (sc->data[SC_ASSUMPTIO]) - mdef2 *= 2; + if(sc->data[SC_ASSUMPTIO]) + mdef2 *= 2; #endif - if (sc->data[SC_MINDBREAKER]) - mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100; - if (sc->data[SC_ANALYZE]) - mdef2 -= mdef2 * (14 * sc->data[SC_ANALYZE]->val1) / 100; + if(sc->data[SC_MINDBREAKER]) + mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100; + if(sc->data[SC_ANALYZE]) + mdef2 -= mdef2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; #ifdef RENEWAL - return (short)cap_value(mdef2,SHRT_MIN,SHRT_MAX); + return (short)cap_value(mdef2,SHRT_MIN,SHRT_MAX); #else - return (short)cap_value(mdef2,1,SHRT_MAX); + return (short)cap_value(mdef2,1,SHRT_MAX); #endif } static unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed) { - TBL_PC *sd = BL_CAST(BL_PC, bl); - int speed_rate; - - if (sc == NULL) - return cap_value(speed,10,USHRT_MAX); - - if (sd && sd->ud.skilltimer != INVALID_TIMER && (pc_checkskill(sd,SA_FREECAST) > 0 || sd->ud.skillid == LG_EXEEDBREAK)) { - if (sd->ud.skillid == LG_EXEEDBREAK) - speed_rate = 100 + 60 - (sd->ud.skilllv * 10); - else - speed_rate = 175 - 5 * pc_checkskill(sd,SA_FREECAST); - } else { - speed_rate = 100; - - //GetMoveHasteValue2() - { - int val = 0; - - if (sc->data[SC_FUSION]) - val = 25; - else if (sd) { - if (pc_isriding(sd) || sd->sc.option&(OPTION_DRAGON|OPTION_MOUNTING)) - val = 25;//Same bonus - else if (pc_isridingwug(sd)) - val = 15 + 5 * pc_checkskill(sd, RA_WUGRIDER); - else if (pc_ismadogear(sd)) { - val = (- 10 * (5 - pc_checkskill(sd,NC_MADOLICENCE))); - if (sc->data[SC_ACCELERATION]) - val += 25; - } - } - - speed_rate -= val; - } - - //GetMoveSlowValue() - { - int val = 0; - - if (sd && sc->data[SC_HIDING] && pc_checkskill(sd,RG_TUNNELDRIVE) > 0) - val = 120 - 6 * pc_checkskill(sd,RG_TUNNELDRIVE); - else if (sd && sc->data[SC_CHASEWALK] && sc->data[SC_CHASEWALK]->val3 < 0) - val = sc->data[SC_CHASEWALK]->val3; - else { - // Longing for Freedom cancels song/dance penalty - if (sc->data[SC_LONGING]) - val = max(val, 50 - 10 * sc->data[SC_LONGING]->val1); - else if (sd && sc->data[SC_DANCING]) - val = max(val, 500 - (40 + 10 * (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) * pc_checkskill(sd,(sd->status.sex?BA_MUSICALLESSON:DC_DANCINGLESSON))); - - if (sc->data[SC_DECREASEAGI]) - val = max(val, 25); - if (sc->data[SC_QUAGMIRE] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY] || (sc->data[SC_GLOOMYDAY] && sc->data[SC_GLOOMYDAY]->val4)) - val = max(val, 50); - if (sc->data[SC_DONTFORGETME]) - val = max(val, sc->data[SC_DONTFORGETME]->val3); - if (sc->data[SC_CURSE]) - val = max(val, 300); - if (sc->data[SC_CHASEWALK]) - val = max(val, sc->data[SC_CHASEWALK]->val3); - if (sc->data[SC_WEDDING]) - val = max(val, 100); - if (sc->data[SC_JOINTBEAT] && sc->data[SC_JOINTBEAT]->val2&(BREAK_ANKLE|BREAK_KNEE)) - val = max(val, (sc->data[SC_JOINTBEAT]->val2&BREAK_ANKLE ? 50 : 0) + (sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE ? 30 : 0)); - if (sc->data[SC_CLOAKING] && (sc->data[SC_CLOAKING]->val4&1) == 0) - val = max(val, sc->data[SC_CLOAKING]->val1 < 3 ? 300 : 30 - 3 * sc->data[SC_CLOAKING]->val1); - if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) - val = max(val, 75); - if (sc->data[SC_SLOWDOWN]) // Slow Potion - val = max(val, 100); - if (sc->data[SC_GATLINGFEVER]) - val = max(val, 100); - if (sc->data[SC_SUITON]) - val = max(val, sc->data[SC_SUITON]->val3); - if (sc->data[SC_SWOO]) - val = max(val, 300); - if (sc->data[SC_FREEZING]) - val = max(val, 70); - if (sc->data[SC_MARSHOFABYSS]) - val = max(val, 40 + 10 * sc->data[SC_MARSHOFABYSS]->val1); - if (sc->data[SC_CAMOUFLAGE] && (sc->data[SC_CAMOUFLAGE]->val3&1) == 0) - val = max(val, sc->data[SC_CAMOUFLAGE]->val1 < 3 ? 0 : 25 * (5 - sc->data[SC_CAMOUFLAGE]->val1)); - if (sc->data[SC__GROOMY]) - val = max(val, sc->data[SC__GROOMY]->val2); - if (sc->data[SC_STEALTHFIELD_MASTER]) - val = max(val, 30); - if (sc->data[SC_BANDING_DEFENCE]) - val = max(val, sc->data[SC_BANDING_DEFENCE]->val1); //+90% walking speed. - if (sc->data[SC_ROCK_CRUSHER_ATK]) - val = max(val, sc->data[SC_ROCK_CRUSHER_ATK]->val2); - if (sc->data[SC_POWER_OF_GAIA]) - val = max(val, sc->data[SC_POWER_OF_GAIA]->val2); - if (sc->data[SC_MELON_BOMB]) - val = max(val, sc->data[SC_MELON_BOMB]->val1); - - if (sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0) // permanent item-based speedup - val = max(val, sd->bonus.speed_rate + sd->bonus.speed_add_rate); - } + TBL_PC* sd = BL_CAST(BL_PC, bl); + int speed_rate; + + if( sc == NULL ) + return cap_value(speed,10,USHRT_MAX); + + if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc_checkskill(sd,SA_FREECAST) > 0 || sd->ud.skillid == LG_EXEEDBREAK) ) + { + if( sd->ud.skillid == LG_EXEEDBREAK ) + speed_rate = 100 + 60 - (sd->ud.skilllv * 10); + else + speed_rate = 175 - 5 * pc_checkskill(sd,SA_FREECAST); + } + else + { + speed_rate = 100; + + //GetMoveHasteValue2() + { + int val = 0; + + if( sc->data[SC_FUSION] ) + val = 25; + else if( sd ) { + if( pc_isriding(sd) || sd->sc.option&(OPTION_DRAGON|OPTION_MOUNTING) ) + val = 25;//Same bonus + else if( pc_isridingwug(sd) ) + val = 15 + 5 * pc_checkskill(sd, RA_WUGRIDER); + else if( pc_ismadogear(sd) ) { + val = (- 10 * (5 - pc_checkskill(sd,NC_MADOLICENCE))); + if( sc->data[SC_ACCELERATION] ) + val += 25; + } + } - speed_rate += val; - } + speed_rate -= val; + } - //GetMoveHasteValue1() - { - int val = 0; - - if (sc->data[SC_SPEEDUP1]) //FIXME: used both by NPC_AGIUP and Speed Potion script - val = max(val, 50); - if (sc->data[SC_INCREASEAGI]) - val = max(val, 25); - if (sc->data[SC_WINDWALK]) - val = max(val, 2 * sc->data[SC_WINDWALK]->val1); - if (sc->data[SC_CARTBOOST]) - val = max(val, 20); - if (sd && (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN && pc_checkskill(sd,TF_MISS) > 0) - val = max(val, 1 * pc_checkskill(sd,TF_MISS)); - if (sc->data[SC_CLOAKING] && (sc->data[SC_CLOAKING]->val4&1) == 1) - val = max(val, sc->data[SC_CLOAKING]->val1 >= 10 ? 25 : 3 * sc->data[SC_CLOAKING]->val1 - 3); - if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) - val = max(val, 25); - if (sc->data[SC_RUN]) - val = max(val, 55); - if (sc->data[SC_AVOID]) - val = max(val, 10 * sc->data[SC_AVOID]->val1); - if (sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF]) - val = max(val, 75); - if (sc->data[SC_CLOAKINGEXCEED]) - val = max(val, sc->data[SC_CLOAKINGEXCEED]->val3); - if (sc->data[SC_HOVERING]) - val = max(val, 10); - if (sc->data[SC_GN_CARTBOOST]) - val = max(val, sc->data[SC_GN_CARTBOOST]->val2); - if (sc->data[SC_SWINGDANCE]) - val = max(val, sc->data[SC_SWINGDANCE]->val2); - if (sc->data[SC_WIND_STEP_OPTION]) - val = max(val, sc->data[SC_WIND_STEP_OPTION]->val2); - - //FIXME: official items use a single bonus for this [ultramage] - if (sc->data[SC_SPEEDUP0]) // temporary item-based speedup - val = max(val, 25); - if (sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate < 0) // permanent item-based speedup - val = max(val, -(sd->bonus.speed_rate + sd->bonus.speed_add_rate)); - - speed_rate -= val; - } + //GetMoveSlowValue() + { + int val = 0; + + if( sd && sc->data[SC_HIDING] && pc_checkskill(sd,RG_TUNNELDRIVE) > 0 ) + val = 120 - 6 * pc_checkskill(sd,RG_TUNNELDRIVE); + else + if( sd && sc->data[SC_CHASEWALK] && sc->data[SC_CHASEWALK]->val3 < 0 ) + val = sc->data[SC_CHASEWALK]->val3; + else + { + // Longing for Freedom cancels song/dance penalty + if( sc->data[SC_LONGING] ) + val = max( val, 50 - 10 * sc->data[SC_LONGING]->val1 ); + else + if( sd && sc->data[SC_DANCING] ) + val = max( val, 500 - (40 + 10 * (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) * pc_checkskill(sd,(sd->status.sex?BA_MUSICALLESSON:DC_DANCINGLESSON)) ); + + if( sc->data[SC_DECREASEAGI] ) + val = max( val, 25 ); + if( sc->data[SC_QUAGMIRE] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY] || (sc->data[SC_GLOOMYDAY] && sc->data[SC_GLOOMYDAY]->val4) ) + val = max( val, 50 ); + if( sc->data[SC_DONTFORGETME] ) + val = max( val, sc->data[SC_DONTFORGETME]->val3 ); + if( sc->data[SC_CURSE] ) + val = max( val, 300 ); + if( sc->data[SC_CHASEWALK] ) + val = max( val, sc->data[SC_CHASEWALK]->val3 ); + if( sc->data[SC_WEDDING] ) + val = max( val, 100 ); + if( sc->data[SC_JOINTBEAT] && sc->data[SC_JOINTBEAT]->val2&(BREAK_ANKLE|BREAK_KNEE) ) + val = max( val, (sc->data[SC_JOINTBEAT]->val2&BREAK_ANKLE ? 50 : 0) + (sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE ? 30 : 0) ); + if( sc->data[SC_CLOAKING] && (sc->data[SC_CLOAKING]->val4&1) == 0 ) + val = max( val, sc->data[SC_CLOAKING]->val1 < 3 ? 300 : 30 - 3 * sc->data[SC_CLOAKING]->val1 ); + if( sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY ) + val = max( val, 75 ); + if( sc->data[SC_SLOWDOWN] ) // Slow Potion + val = max( val, 100 ); + if( sc->data[SC_GATLINGFEVER] ) + val = max( val, 100 ); + if( sc->data[SC_SUITON] ) + val = max( val, sc->data[SC_SUITON]->val3 ); + if( sc->data[SC_SWOO] ) + val = max( val, 300 ); + if( sc->data[SC_FREEZING] ) + val = max( val, 70 ); + if( sc->data[SC_MARSHOFABYSS] ) + val = max( val, 40 + 10 * sc->data[SC_MARSHOFABYSS]->val1 ); + if( sc->data[SC_CAMOUFLAGE] && (sc->data[SC_CAMOUFLAGE]->val3&1) == 0 ) + val = max( val, sc->data[SC_CAMOUFLAGE]->val1 < 3 ? 0 : 25 * (5 - sc->data[SC_CAMOUFLAGE]->val1) ); + if( sc->data[SC__GROOMY] ) + val = max( val, sc->data[SC__GROOMY]->val2); + if( sc->data[SC_STEALTHFIELD_MASTER] ) + val = max( val, 30 ); + if( sc->data[SC_BANDING_DEFENCE] ) + val = max( val, sc->data[SC_BANDING_DEFENCE]->val1 );//+90% walking speed. + if( sc->data[SC_ROCK_CRUSHER_ATK] ) + val = max( val, sc->data[SC_ROCK_CRUSHER_ATK]->val2 ); + if( sc->data[SC_POWER_OF_GAIA] ) + val = max( val, sc->data[SC_POWER_OF_GAIA]->val2 ); + if( sc->data[SC_MELON_BOMB] ) + val = max( val, sc->data[SC_MELON_BOMB]->val1 ); + + if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0 ) // permanent item-based speedup + val = max( val, sd->bonus.speed_rate + sd->bonus.speed_add_rate ); + } - if (speed_rate < 40) - speed_rate = 40; - } + speed_rate += val; + } - //GetSpeed() - { - if (sd && pc_iscarton(sd)) - speed += speed * (50 - 5 * pc_checkskill(sd,MC_PUSHCART)) / 100; - if (sc->data[SC_PARALYSE]) - speed += speed * 50 / 100; - if (speed_rate != 100) - speed = speed * speed_rate / 100; - if (sc->data[SC_STEELBODY]) - speed = 200; - if (sc->data[SC_DEFENDER]) - speed = max(speed, 200); - if (sc->data[SC_WALKSPEED] && sc->data[SC_WALKSPEED]->val1 > 0) // ChangeSpeed - speed = speed * 100 / sc->data[SC_WALKSPEED]->val1; - } + //GetMoveHasteValue1() + { + int val = 0; + + if( sc->data[SC_SPEEDUP1] ) //FIXME: used both by NPC_AGIUP and Speed Potion script + val = max( val, 50 ); + if( sc->data[SC_INCREASEAGI] ) + val = max( val, 25 ); + if( sc->data[SC_WINDWALK] ) + val = max( val, 2 * sc->data[SC_WINDWALK]->val1 ); + if( sc->data[SC_CARTBOOST] ) + val = max( val, 20 ); + if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN && pc_checkskill(sd,TF_MISS) > 0 ) + val = max( val, 1 * pc_checkskill(sd,TF_MISS) ); + if( sc->data[SC_CLOAKING] && (sc->data[SC_CLOAKING]->val4&1) == 1 ) + val = max( val, sc->data[SC_CLOAKING]->val1 >= 10 ? 25 : 3 * sc->data[SC_CLOAKING]->val1 - 3 ); + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) + val = max( val, 25 ); + if( sc->data[SC_RUN] ) + val = max( val, 55 ); + if( sc->data[SC_AVOID] ) + val = max( val, 10 * sc->data[SC_AVOID]->val1 ); + if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) + val = max( val, 75 ); + if( sc->data[SC_CLOAKINGEXCEED] ) + val = max( val, sc->data[SC_CLOAKINGEXCEED]->val3); + if( sc->data[SC_HOVERING] ) + val = max( val, 10 ); + if( sc->data[SC_GN_CARTBOOST] ) + val = max( val, sc->data[SC_GN_CARTBOOST]->val2 ); + if( sc->data[SC_SWINGDANCE] ) + val = max( val, sc->data[SC_SWINGDANCE]->val2 ); + if( sc->data[SC_WIND_STEP_OPTION] ) + val = max( val, sc->data[SC_WIND_STEP_OPTION]->val2 ); + + //FIXME: official items use a single bonus for this [ultramage] + if( sc->data[SC_SPEEDUP0] ) // temporary item-based speedup + val = max( val, 25 ); + if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate < 0 ) // permanent item-based speedup + val = max( val, -(sd->bonus.speed_rate + sd->bonus.speed_add_rate) ); + + speed_rate -= val; + } - return (short)cap_value(speed,10,USHRT_MAX); + if( speed_rate < 40 ) + speed_rate = 40; + } + + //GetSpeed() + { + if( sd && pc_iscarton(sd) ) + speed += speed * (50 - 5 * pc_checkskill(sd,MC_PUSHCART)) / 100; + if( sc->data[SC_PARALYSE] ) + speed += speed * 50 / 100; + if( speed_rate != 100 ) + speed = speed * speed_rate / 100; + if( sc->data[SC_STEELBODY] ) + speed = 200; + if( sc->data[SC_DEFENDER] ) + speed = max(speed, 200); + if( sc->data[SC_WALKSPEED] && sc->data[SC_WALKSPEED]->val1 > 0 ) // ChangeSpeed + speed = speed * 100 / sc->data[SC_WALKSPEED]->val1; + } + + return (short)cap_value(speed,10,USHRT_MAX); } #ifdef RENEWAL_ASPD @@ -5187,125 +5146,126 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha // flag&2 - percentage value static short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag) { - int i, pots = 0, skills1 = 0, skills2 = 0; - - if (!sc || !sc->count) - return 0; - - if (sc->data[i=SC_ASPDPOTION3] || - sc->data[i=SC_ASPDPOTION2] || - sc->data[i=SC_ASPDPOTION1] || - sc->data[i=SC_ASPDPOTION0]) - pots += sc->data[i]->val1; - - if (!sc->data[SC_QUAGMIRE]) { - if (sc->data[SC_STAR_COMFORT]) - skills1 = 5; // needs more info - - if (sc->data[SC_TWOHANDQUICKEN] && skills1 < 7) - skills1 = 7; - - if (sc->data[SC_ONEHAND] && skills1 < 7) skills1 = 7; - - if (sc->data[SC_MERC_QUICKEN] && skills1 < 7) // needs more info - skills1 = 7; - - if (sc->data[SC_ADRENALINE2] && skills1 < 6) - skills1 = 6; - - if (sc->data[SC_ADRENALINE] && skills1 < 7) - skills1 = 7; - - if (sc->data[SC_SPEARQUICKEN] && skills1 < 7) - skills1 = 7; - - if (sc->data[SC_GATLINGFEVER] && skills1 < 9) // needs more info - skills1 = 9; - - if (sc->data[SC_FLEET] && skills1 < 5) - skills1 = 5; - - if (sc->data[SC_ASSNCROS] && - skills1 < 5+1*sc->data[SC_ASSNCROS]->val1) { // needs more info - if (bl->type!=BL_PC) - skills1 = 4+1*sc->data[SC_ASSNCROS]->val1; - else - switch (((TBL_PC *)bl)->status.weapon) { - case W_BOW: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - break; - default: - skills1 = 5+1*sc->data[SC_ASSNCROS]->val1; - } - } - } - - if ((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) && skills1 < 15) - skills1 = 15; - else if (sc->data[SC_MADNESSCANCEL] && skills1 < 15) // needs more info - skills1 = 15; - - if (sc->data[SC_DONTFORGETME]) - skills2 -= sc->data[SC_DONTFORGETME]->val2; // needs more info - if (sc->data[SC_LONGING]) - skills2 -= sc->data[SC_LONGING]->val2; // needs more info - if (sc->data[SC_STEELBODY]) - skills2 -= 25; - if (sc->data[SC_SKA]) - skills2 -= 25; - if (sc->data[SC_DEFENDER]) - skills2 -= sc->data[SC_DEFENDER]->val4; // needs more info - if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) // needs more info - skills2 -= 25; - if (sc->data[SC_GRAVITATION]) - skills2 -= sc->data[SC_GRAVITATION]->val2; // needs more info - if (sc->data[SC_JOINTBEAT]) { // needs more info - if (sc->data[SC_JOINTBEAT]->val2&BREAK_WRIST) - skills2 -= 25; - if (sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE) - skills2 -= 10; - } - if (sc->data[SC_FREEZING]) - skills2 -= 30; - if (sc->data[SC_HALLUCINATIONWALK_POSTDELAY]) - skills2 -= 50; - if (sc->data[SC_PARALYSE]) - skills2 -= 10; - if (sc->data[SC__BODYPAINT]) - skills2 -= 2 + 5 * sc->data[SC__BODYPAINT]->val1; - if (sc->data[SC__INVISIBILITY]) - skills2 -= sc->data[SC__INVISIBILITY]->val2 ; - if (sc->data[SC__GROOMY]) - skills2 -= sc->data[SC__GROOMY]->val2; - if (sc->data[SC_SWINGDANCE]) - skills2 += sc->data[SC_SWINGDANCE]->val2; - if (sc->data[SC_DANCEWITHWUG]) - skills2 += sc->data[SC_DANCEWITHWUG]->val3; - if (sc->data[SC_GLOOMYDAY]) - skills2 -= sc->data[SC_GLOOMYDAY]->val3; - if (sc->data[SC_EARTHDRIVE]) - skills2 -= 25; - if (sc->data[SC_GT_CHANGE]) - skills2 += sc->data[SC_GT_CHANGE]->val3; - if (sc->data[SC_MELON_BOMB]) - skills2 -= sc->data[SC_MELON_BOMB]->val1; - if (sc->data[SC_BOOST500]) - skills2 += sc->data[SC_BOOST500]->val1; - if (sc->data[SC_EXTRACT_SALAMINE_JUICE]) - skills2 += sc->data[SC_EXTRACT_SALAMINE_JUICE]->val1; - if (sc->data[SC_INCASPDRATE]) - skills2 += sc->data[SC_INCASPDRATE]->val1; - - return (flag&1? (skills1 + pots) : skills2); + int i, pots = 0, skills1 = 0, skills2 = 0; + + if(!sc || !sc->count) + return 0; + + if(sc->data[i=SC_ASPDPOTION3] || + sc->data[i=SC_ASPDPOTION2] || + sc->data[i=SC_ASPDPOTION1] || + sc->data[i=SC_ASPDPOTION0]) + pots += sc->data[i]->val1; + + if( !sc->data[SC_QUAGMIRE] ){ + if(sc->data[SC_STAR_COMFORT]) + skills1 = 5; // needs more info + + if(sc->data[SC_TWOHANDQUICKEN] && skills1 < 7) + skills1 = 7; + + if(sc->data[SC_ONEHAND] && skills1 < 7) skills1 = 7; + + if(sc->data[SC_MERC_QUICKEN] && skills1 < 7) // needs more info + skills1 = 7; + + if(sc->data[SC_ADRENALINE2] && skills1 < 6) + skills1 = 6; + + if(sc->data[SC_ADRENALINE] && skills1 < 7) + skills1 = 7; + + if(sc->data[SC_SPEARQUICKEN] && skills1 < 7) + skills1 = 7; + + if(sc->data[SC_GATLINGFEVER] && skills1 < 9) // needs more info + skills1 = 9; + + if(sc->data[SC_FLEET] && skills1 < 5) + skills1 = 5; + + if(sc->data[SC_ASSNCROS] && + skills1 < 5+1*sc->data[SC_ASSNCROS]->val1) // needs more info + { + if (bl->type!=BL_PC) + skills1 = 4+1*sc->data[SC_ASSNCROS]->val1; + else + switch(((TBL_PC*)bl)->status.weapon) + { + case W_BOW: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + break; + default: + skills1 = 5+1*sc->data[SC_ASSNCROS]->val1; + } + } + } + + if((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) && skills1 < 15) + skills1 = 15; + else if(sc->data[SC_MADNESSCANCEL] && skills1 < 15) // needs more info + skills1 = 15; + + if(sc->data[SC_DONTFORGETME]) + skills2 -= sc->data[SC_DONTFORGETME]->val2; // needs more info + if(sc->data[SC_LONGING]) + skills2 -= sc->data[SC_LONGING]->val2; // needs more info + if(sc->data[SC_STEELBODY]) + skills2 -= 25; + if(sc->data[SC_SKA]) + skills2 -= 25; + if(sc->data[SC_DEFENDER]) + skills2 -= sc->data[SC_DEFENDER]->val4; // needs more info + if(sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) // needs more info + skills2 -= 25; + if(sc->data[SC_GRAVITATION]) + skills2 -= sc->data[SC_GRAVITATION]->val2; // needs more info + if(sc->data[SC_JOINTBEAT]) { // needs more info + if( sc->data[SC_JOINTBEAT]->val2&BREAK_WRIST ) + skills2 -= 25; + if( sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE ) + skills2 -= 10; + } + if( sc->data[SC_FREEZING] ) + skills2 -= 30; + if( sc->data[SC_HALLUCINATIONWALK_POSTDELAY] ) + skills2 -= 50; + if( sc->data[SC_PARALYSE] ) + skills2 -= 10; + if( sc->data[SC__BODYPAINT] ) + skills2 -= 2 + 5 * sc->data[SC__BODYPAINT]->val1; + if( sc->data[SC__INVISIBILITY] ) + skills2 -= sc->data[SC__INVISIBILITY]->val2 ; + if( sc->data[SC__GROOMY] ) + skills2 -= sc->data[SC__GROOMY]->val2; + if( sc->data[SC_SWINGDANCE] ) + skills2 += sc->data[SC_SWINGDANCE]->val2; + if( sc->data[SC_DANCEWITHWUG] ) + skills2 += sc->data[SC_DANCEWITHWUG]->val3; + if( sc->data[SC_GLOOMYDAY] ) + skills2 -= sc->data[SC_GLOOMYDAY]->val3; + if( sc->data[SC_EARTHDRIVE] ) + skills2 -= 25; + if( sc->data[SC_GT_CHANGE] ) + skills2 += sc->data[SC_GT_CHANGE]->val3; + if( sc->data[SC_MELON_BOMB] ) + skills2 -= sc->data[SC_MELON_BOMB]->val1; + if( sc->data[SC_BOOST500] ) + skills2 += sc->data[SC_BOOST500]->val1; + if( sc->data[SC_EXTRACT_SALAMINE_JUICE] ) + skills2 += sc->data[SC_EXTRACT_SALAMINE_JUICE]->val1; + if( sc->data[SC_INCASPDRATE] ) + skills2 += sc->data[SC_INCASPDRATE]->val1; + + return ( flag&1? (skills1 + pots) : skills2 ); } #endif -static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) -{ +static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) { if (!sc || !sc->count) return cap_value(aspd, 0, 2000); @@ -5313,15 +5273,15 @@ static short status_calc_fix_aspd(struct block_list *bl, struct status_change *s if (sc->data[SC_FIGHTINGSPIRIT]) aspd += sc->data[SC_FIGHTINGSPIRIT]->val3; if ((sc->data[SC_GUST_OPTION] - || sc->data[SC_BLAST_OPTION] - || sc->data[SC_WILD_STORM_OPTION]) - ) + || sc->data[SC_BLAST_OPTION] + || sc->data[SC_WILD_STORM_OPTION]) + ) aspd -= 50; // ventus passive = +5 ASPD - if (sc->data[SC_OVERED_BOOST]) { - aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3*10; + if (sc->data[SC_OVERED_BOOST]){ + aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3*10; } - // if(sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 ) - // aspd -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) * 4; +// if(sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 ) +// aspd -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) * 4; } return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway @@ -5331,809 +5291,768 @@ static short status_calc_fix_aspd(struct block_list *bl, struct status_change *s /// Note that the scale of aspd_rate is 1000 = 100%. static short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate) { - int i; - - if (!sc || !sc->count) - return cap_value(aspd_rate,0,SHRT_MAX); - - if (!sc->data[SC_QUAGMIRE]) { - int max = 0; - if (sc->data[SC_STAR_COMFORT]) - max = sc->data[SC_STAR_COMFORT]->val2; - - if (sc->data[SC_TWOHANDQUICKEN] && - max < sc->data[SC_TWOHANDQUICKEN]->val2) - max = sc->data[SC_TWOHANDQUICKEN]->val2; - - if (sc->data[SC_ONEHAND] && - max < sc->data[SC_ONEHAND]->val2) - max = sc->data[SC_ONEHAND]->val2; - - if (sc->data[SC_MERC_QUICKEN] && - max < sc->data[SC_MERC_QUICKEN]->val2) - max = sc->data[SC_MERC_QUICKEN]->val2; - - if (sc->data[SC_ADRENALINE2] && - max < sc->data[SC_ADRENALINE2]->val3) - max = sc->data[SC_ADRENALINE2]->val3; - - if (sc->data[SC_ADRENALINE] && - max < sc->data[SC_ADRENALINE]->val3) - max = sc->data[SC_ADRENALINE]->val3; - - if (sc->data[SC_SPEARQUICKEN] && - max < sc->data[SC_SPEARQUICKEN]->val2) - max = sc->data[SC_SPEARQUICKEN]->val2; - - if (sc->data[SC_GATLINGFEVER] && - max < sc->data[SC_GATLINGFEVER]->val2) - max = sc->data[SC_GATLINGFEVER]->val2; - - if (sc->data[SC_FLEET] && - max < sc->data[SC_FLEET]->val2) - max = sc->data[SC_FLEET]->val2; - - if (sc->data[SC_ASSNCROS] && - max < sc->data[SC_ASSNCROS]->val2) { - if (bl->type!=BL_PC) - max = sc->data[SC_ASSNCROS]->val2; - else - switch (((TBL_PC *)bl)->status.weapon) { - case W_BOW: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - break; - default: - max = sc->data[SC_ASSNCROS]->val2; - } - } - aspd_rate -= max; - - if ((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])) - aspd_rate -= 300; - else if (sc->data[SC_MADNESSCANCEL]) - aspd_rate -= 200; - } - - if (sc->data[i=SC_ASPDPOTION3] || - sc->data[i=SC_ASPDPOTION2] || - sc->data[i=SC_ASPDPOTION1] || - sc->data[i=SC_ASPDPOTION0]) - aspd_rate -= sc->data[i]->val2; - - if (sc->data[SC_DONTFORGETME]) - aspd_rate += 10 * sc->data[SC_DONTFORGETME]->val2; - if (sc->data[SC_LONGING]) - aspd_rate += sc->data[SC_LONGING]->val2; - if (sc->data[SC_STEELBODY]) - aspd_rate += 250; - if (sc->data[SC_SKA]) - aspd_rate += 250; - if (sc->data[SC_DEFENDER]) - aspd_rate += sc->data[SC_DEFENDER]->val4; - if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) - aspd_rate += 250; - if (sc->data[SC_GRAVITATION]) - aspd_rate += sc->data[SC_GRAVITATION]->val2; - if (sc->data[SC_JOINTBEAT]) { - if (sc->data[SC_JOINTBEAT]->val2&BREAK_WRIST) - aspd_rate += 250; - if (sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE) - aspd_rate += 100; - } - if (sc->data[SC_FREEZING]) - aspd_rate += 300; - if (sc->data[SC_HALLUCINATIONWALK_POSTDELAY]) - aspd_rate += 500; - if (sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2) - aspd_rate -= sc->data[SC_FIGHTINGSPIRIT]->val2; - if (sc->data[SC_PARALYSE]) - aspd_rate += 100; - if (sc->data[SC__BODYPAINT]) - aspd_rate += 200 + 50 * sc->data[SC__BODYPAINT]->val1; - if (sc->data[SC__INVISIBILITY]) - aspd_rate += sc->data[SC__INVISIBILITY]->val2 * 10 ; - if (sc->data[SC__GROOMY]) - aspd_rate += sc->data[SC__GROOMY]->val2 * 10; - if (sc->data[SC_SWINGDANCE]) - aspd_rate -= sc->data[SC_SWINGDANCE]->val2 * 10; - if (sc->data[SC_DANCEWITHWUG]) - aspd_rate -= sc->data[SC_DANCEWITHWUG]->val3 * 10; - if (sc->data[SC_GLOOMYDAY]) - aspd_rate += sc->data[SC_GLOOMYDAY]->val3 * 10; - if (sc->data[SC_EARTHDRIVE]) - aspd_rate += 250; - if (sc->data[SC_GT_CHANGE]) - aspd_rate -= sc->data[SC_GT_CHANGE]->val3 * 10; - if (sc->data[SC_MELON_BOMB]) - aspd_rate += sc->data[SC_MELON_BOMB]->val1 * 10; - if (sc->data[SC_BOOST500]) - aspd_rate -= sc->data[SC_BOOST500]->val1 *10; - if (sc->data[SC_EXTRACT_SALAMINE_JUICE]) - aspd_rate -= sc->data[SC_EXTRACT_SALAMINE_JUICE]->val1 * 10; - if (sc->data[SC_INCASPDRATE]) - aspd_rate -= sc->data[SC_INCASPDRATE]->val1 * 10; - if (sc->data[SC_PAIN_KILLER]) - aspd_rate += sc->data[SC_PAIN_KILLER]->val2 * 10; - if (sc->data[SC_GOLDENE_FERSE]) - aspd_rate -= sc->data[SC_GOLDENE_FERSE]->val3 * 10; - - return (short)cap_value(aspd_rate,0,SHRT_MAX); + int i; + + if(!sc || !sc->count) + return cap_value(aspd_rate,0,SHRT_MAX); + + if( !sc->data[SC_QUAGMIRE] ){ + int max = 0; + if(sc->data[SC_STAR_COMFORT]) + max = sc->data[SC_STAR_COMFORT]->val2; + + if(sc->data[SC_TWOHANDQUICKEN] && + max < sc->data[SC_TWOHANDQUICKEN]->val2) + max = sc->data[SC_TWOHANDQUICKEN]->val2; + + if(sc->data[SC_ONEHAND] && + max < sc->data[SC_ONEHAND]->val2) + max = sc->data[SC_ONEHAND]->val2; + + if(sc->data[SC_MERC_QUICKEN] && + max < sc->data[SC_MERC_QUICKEN]->val2) + max = sc->data[SC_MERC_QUICKEN]->val2; + + if(sc->data[SC_ADRENALINE2] && + max < sc->data[SC_ADRENALINE2]->val3) + max = sc->data[SC_ADRENALINE2]->val3; + + if(sc->data[SC_ADRENALINE] && + max < sc->data[SC_ADRENALINE]->val3) + max = sc->data[SC_ADRENALINE]->val3; + + if(sc->data[SC_SPEARQUICKEN] && + max < sc->data[SC_SPEARQUICKEN]->val2) + max = sc->data[SC_SPEARQUICKEN]->val2; + + if(sc->data[SC_GATLINGFEVER] && + max < sc->data[SC_GATLINGFEVER]->val2) + max = sc->data[SC_GATLINGFEVER]->val2; + + if(sc->data[SC_FLEET] && + max < sc->data[SC_FLEET]->val2) + max = sc->data[SC_FLEET]->val2; + + if(sc->data[SC_ASSNCROS] && + max < sc->data[SC_ASSNCROS]->val2) + { + if (bl->type!=BL_PC) + max = sc->data[SC_ASSNCROS]->val2; + else + switch(((TBL_PC*)bl)->status.weapon) + { + case W_BOW: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + break; + default: + max = sc->data[SC_ASSNCROS]->val2; + } + } + aspd_rate -= max; + + if((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])) + aspd_rate -= 300; + else if(sc->data[SC_MADNESSCANCEL]) + aspd_rate -= 200; + } + + if( sc->data[i=SC_ASPDPOTION3] || + sc->data[i=SC_ASPDPOTION2] || + sc->data[i=SC_ASPDPOTION1] || + sc->data[i=SC_ASPDPOTION0] ) + aspd_rate -= sc->data[i]->val2; + + if(sc->data[SC_DONTFORGETME]) + aspd_rate += 10 * sc->data[SC_DONTFORGETME]->val2; + if(sc->data[SC_LONGING]) + aspd_rate += sc->data[SC_LONGING]->val2; + if(sc->data[SC_STEELBODY]) + aspd_rate += 250; + if(sc->data[SC_SKA]) + aspd_rate += 250; + if(sc->data[SC_DEFENDER]) + aspd_rate += sc->data[SC_DEFENDER]->val4; + if(sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) + aspd_rate += 250; + if(sc->data[SC_GRAVITATION]) + aspd_rate += sc->data[SC_GRAVITATION]->val2; + if(sc->data[SC_JOINTBEAT]) { + if( sc->data[SC_JOINTBEAT]->val2&BREAK_WRIST ) + aspd_rate += 250; + if( sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE ) + aspd_rate += 100; + } + if( sc->data[SC_FREEZING] ) + aspd_rate += 300; + if( sc->data[SC_HALLUCINATIONWALK_POSTDELAY] ) + aspd_rate += 500; + if( sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 ) + aspd_rate -= sc->data[SC_FIGHTINGSPIRIT]->val2; + if( sc->data[SC_PARALYSE] ) + aspd_rate += 100; + if( sc->data[SC__BODYPAINT] ) + aspd_rate += 200 + 50 * sc->data[SC__BODYPAINT]->val1; + if( sc->data[SC__INVISIBILITY] ) + aspd_rate += sc->data[SC__INVISIBILITY]->val2 * 10 ; + if( sc->data[SC__GROOMY] ) + aspd_rate += sc->data[SC__GROOMY]->val2 * 10; + if( sc->data[SC_SWINGDANCE] ) + aspd_rate -= sc->data[SC_SWINGDANCE]->val2 * 10; + if( sc->data[SC_DANCEWITHWUG] ) + aspd_rate -= sc->data[SC_DANCEWITHWUG]->val3 * 10; + if( sc->data[SC_GLOOMYDAY] ) + aspd_rate += sc->data[SC_GLOOMYDAY]->val3 * 10; + if( sc->data[SC_EARTHDRIVE] ) + aspd_rate += 250; + if( sc->data[SC_GT_CHANGE] ) + aspd_rate -= sc->data[SC_GT_CHANGE]->val3 * 10; + if( sc->data[SC_MELON_BOMB] ) + aspd_rate += sc->data[SC_MELON_BOMB]->val1 * 10; + if( sc->data[SC_BOOST500] ) + aspd_rate -= sc->data[SC_BOOST500]->val1 *10; + if( sc->data[SC_EXTRACT_SALAMINE_JUICE] ) + aspd_rate -= sc->data[SC_EXTRACT_SALAMINE_JUICE]->val1 * 10; + if( sc->data[SC_INCASPDRATE] ) + aspd_rate -= sc->data[SC_INCASPDRATE]->val1 * 10; + if( sc->data[SC_PAIN_KILLER]) + aspd_rate += sc->data[SC_PAIN_KILLER]->val2 * 10; + if( sc->data[SC_GOLDENE_FERSE]) + aspd_rate -= sc->data[SC_GOLDENE_FERSE]->val3 * 10; + + return (short)cap_value(aspd_rate,0,SHRT_MAX); } static unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion) { - if (!sc || !sc->count || map_flag_gvg(bl->m) || map[bl->m].flag.battleground) - return cap_value(dmotion,0,USHRT_MAX); - /** - * It has been confirmed on official servers that MvP mobs have no dmotion even without endure - **/ - if (sc->data[SC_ENDURE] || (bl->type == BL_MOB && (((TBL_MOB *)bl)->status.mode&MD_BOSS))) - return 0; - if (sc->data[SC_CONCENTRATION]) - return 0; - if (sc->data[SC_RUN] || sc->data[SC_WUGDASH]) - return 0; - - return (unsigned short)cap_value(dmotion,0,USHRT_MAX); + if( !sc || !sc->count || map_flag_gvg(bl->m) || map[bl->m].flag.battleground ) + return cap_value(dmotion,0,USHRT_MAX); + /** + * It has been confirmed on official servers that MvP mobs have no dmotion even without endure + **/ + if( sc->data[SC_ENDURE] || ( bl->type == BL_MOB && (((TBL_MOB*)bl)->status.mode&MD_BOSS) ) ) + return 0; + if( sc->data[SC_CONCENTRATION] ) + return 0; + if( sc->data[SC_RUN] || sc->data[SC_WUGDASH] ) + return 0; + + return (unsigned short)cap_value(dmotion,0,USHRT_MAX); } static unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, unsigned int maxhp) { - if (!sc || !sc->count) - return cap_value(maxhp,1,UINT_MAX); - - if (sc->data[SC_INCMHPRATE]) - maxhp += maxhp * sc->data[SC_INCMHPRATE]->val1/100; - if (sc->data[SC_INCMHP]) - maxhp += (sc->data[SC_INCMHP]->val1); - if (sc->data[SC_APPLEIDUN]) - maxhp += maxhp * sc->data[SC_APPLEIDUN]->val2/100; - if (sc->data[SC_DELUGE]) - maxhp += maxhp * sc->data[SC_DELUGE]->val2/100; - if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) - maxhp += maxhp * 2; - if (sc->data[SC_MARIONETTE]) - maxhp -= 1000; - - if (sc->data[SC_MERC_HPUP]) - maxhp += maxhp * sc->data[SC_MERC_HPUP]->val2/100; - - if (sc->data[SC_EPICLESIS]) - maxhp += maxhp * 5 * sc->data[SC_EPICLESIS]->val1 / 100; - if (sc->data[SC_VENOMBLEED]) - maxhp -= maxhp * 15 / 100; - if (sc->data[SC__WEAKNESS]) - maxhp -= maxhp * sc->data[SC__WEAKNESS]->val2 / 100; - if (sc->data[SC_LERADSDEW]) - maxhp += maxhp * sc->data[SC_LERADSDEW]->val3 / 100; - if (sc->data[SC_FORCEOFVANGUARD]) - maxhp += maxhp * 3 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100; - if (sc->data[SC_INSPIRATION]) //Custom value. - maxhp += maxhp * 3 * sc->data[SC_INSPIRATION]->val1 / 100; - if (sc->data[SC_RAISINGDRAGON]) - maxhp += maxhp * (2 + sc->data[SC_RAISINGDRAGON]->val1) / 100; - if (sc->data[SC_GT_CHANGE]) // Max HP decrease: [Skill Level x 4] % - maxhp -= maxhp * (4 * sc->data[SC_GT_CHANGE]->val1) / 100; - if (sc->data[SC_GT_REVITALIZE]) // Max HP increase: [Skill Level x 2] % - maxhp += maxhp * (2 * sc->data[SC_GT_REVITALIZE]->val1) / 100; - if (sc->data[SC_MUSTLE_M]) - maxhp += maxhp * sc->data[SC_MUSTLE_M]->val1/100; - if (sc->data[SC_SOLID_SKIN_OPTION]) - maxhp += 2000;// Fix amount. - if (sc->data[SC_POWER_OF_GAIA]) - maxhp += 3000; - if (sc->data[SC_MYSTERIOUS_POWDER]) - maxhp -= sc->data[SC_MYSTERIOUS_POWDER]->val1 / 100; - if (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) - maxhp += 500; - if (sc->data[SC_ANGRIFFS_MODUS]) - maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100; - if (sc->data[SC_GOLDENE_FERSE]) - maxhp += (maxhp * sc->data[SC_GOLDENE_FERSE]->val2) / 100; - - return cap_value(maxhp,1,UINT_MAX); + if(!sc || !sc->count) + return cap_value(maxhp,1,UINT_MAX); + + if(sc->data[SC_INCMHPRATE]) + maxhp += maxhp * sc->data[SC_INCMHPRATE]->val1/100; + if(sc->data[SC_INCMHP]) + maxhp += (sc->data[SC_INCMHP]->val1); + if(sc->data[SC_APPLEIDUN]) + maxhp += maxhp * sc->data[SC_APPLEIDUN]->val2/100; + if(sc->data[SC_DELUGE]) + maxhp += maxhp * sc->data[SC_DELUGE]->val2/100; + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) + maxhp += maxhp * 2; + if(sc->data[SC_MARIONETTE]) + maxhp -= 1000; + + if(sc->data[SC_MERC_HPUP]) + maxhp += maxhp * sc->data[SC_MERC_HPUP]->val2/100; + + if(sc->data[SC_EPICLESIS]) + maxhp += maxhp * 5 * sc->data[SC_EPICLESIS]->val1 / 100; + if(sc->data[SC_VENOMBLEED]) + maxhp -= maxhp * 15 / 100; + if(sc->data[SC__WEAKNESS]) + maxhp -= maxhp * sc->data[SC__WEAKNESS]->val2 / 100; + if(sc->data[SC_LERADSDEW]) + maxhp += maxhp * sc->data[SC_LERADSDEW]->val3 / 100; + if(sc->data[SC_FORCEOFVANGUARD]) + maxhp += maxhp * 3 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100; + if(sc->data[SC_INSPIRATION]) //Custom value. + maxhp += maxhp * 3 * sc->data[SC_INSPIRATION]->val1 / 100; + if(sc->data[SC_RAISINGDRAGON]) + maxhp += maxhp * (2 + sc->data[SC_RAISINGDRAGON]->val1) / 100; + if(sc->data[SC_GT_CHANGE]) // Max HP decrease: [Skill Level x 4] % + maxhp -= maxhp * (4 * sc->data[SC_GT_CHANGE]->val1) / 100; + if(sc->data[SC_GT_REVITALIZE])// Max HP increase: [Skill Level x 2] % + maxhp += maxhp * (2 * sc->data[SC_GT_REVITALIZE]->val1) / 100; + if(sc->data[SC_MUSTLE_M]) + maxhp += maxhp * sc->data[SC_MUSTLE_M]->val1/100; + if(sc->data[SC_SOLID_SKIN_OPTION]) + maxhp += 2000;// Fix amount. + if(sc->data[SC_POWER_OF_GAIA]) + maxhp += 3000; + if(sc->data[SC_MYSTERIOUS_POWDER]) + maxhp -= sc->data[SC_MYSTERIOUS_POWDER]->val1 / 100; + if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) + maxhp += 500; + if (sc->data[SC_ANGRIFFS_MODUS]) + maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100; + if (sc->data[SC_GOLDENE_FERSE]) + maxhp += (maxhp * sc->data[SC_GOLDENE_FERSE]->val2) / 100; + + return cap_value(maxhp,1,UINT_MAX); } static unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, unsigned int maxsp) { - if (!sc || !sc->count) - return cap_value(maxsp,1,UINT_MAX); - - if (sc->data[SC_INCMSPRATE]) - maxsp += maxsp * sc->data[SC_INCMSPRATE]->val1/100; - if (sc->data[SC_INCMSP]) - maxsp += (sc->data[SC_INCMSP]->val1); - if (sc->data[SC_SERVICE4U]) - maxsp += maxsp * sc->data[SC_SERVICE4U]->val2/100; - if (sc->data[SC_MERC_SPUP]) - maxsp += maxsp * sc->data[SC_MERC_SPUP]->val2/100; - if (sc->data[SC_RAISINGDRAGON]) - maxsp += maxsp * (2 + sc->data[SC_RAISINGDRAGON]->val1) / 100; - if (sc->data[SC_LIFE_FORCE_F]) - maxsp += maxsp * sc->data[SC_LIFE_FORCE_F]->val1/100; - if (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3) - maxsp += 50; - - return cap_value(maxsp,1,UINT_MAX); + if(!sc || !sc->count) + return cap_value(maxsp,1,UINT_MAX); + + if(sc->data[SC_INCMSPRATE]) + maxsp += maxsp * sc->data[SC_INCMSPRATE]->val1/100; + if(sc->data[SC_INCMSP]) + maxsp += (sc->data[SC_INCMSP]->val1); + if(sc->data[SC_SERVICE4U]) + maxsp += maxsp * sc->data[SC_SERVICE4U]->val2/100; + if(sc->data[SC_MERC_SPUP]) + maxsp += maxsp * sc->data[SC_MERC_SPUP]->val2/100; + if(sc->data[SC_RAISINGDRAGON]) + maxsp += maxsp * (2 + sc->data[SC_RAISINGDRAGON]->val1) / 100; + if(sc->data[SC_LIFE_FORCE_F]) + maxsp += maxsp * sc->data[SC_LIFE_FORCE_F]->val1/100; + if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3) + maxsp += 50; + + return cap_value(maxsp,1,UINT_MAX); } static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element) { - if (!sc || !sc->count) - return element; - - if (sc->data[SC_FREEZE]) - return ELE_WATER; - if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) - return ELE_EARTH; - if (sc->data[SC_BENEDICTIO]) - return ELE_HOLY; - if (sc->data[SC_CHANGEUNDEAD]) - return ELE_UNDEAD; - if (sc->data[SC_ELEMENTALCHANGE]) - return sc->data[SC_ELEMENTALCHANGE]->val2; - if (sc->data[SC_SHAPESHIFT]) - return sc->data[SC_SHAPESHIFT]->val2; - - return (unsigned char)cap_value(element,0,UCHAR_MAX); + if(!sc || !sc->count) + return element; + + if(sc->data[SC_FREEZE]) + return ELE_WATER; + if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) + return ELE_EARTH; + if(sc->data[SC_BENEDICTIO]) + return ELE_HOLY; + if(sc->data[SC_CHANGEUNDEAD]) + return ELE_UNDEAD; + if(sc->data[SC_ELEMENTALCHANGE]) + return sc->data[SC_ELEMENTALCHANGE]->val2; + if(sc->data[SC_SHAPESHIFT]) + return sc->data[SC_SHAPESHIFT]->val2; + + return (unsigned char)cap_value(element,0,UCHAR_MAX); } static unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv) { - if (!sc || !sc->count) - return lv; - - if (sc->data[SC_FREEZE]) - return 1; - if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) - return 1; - if (sc->data[SC_BENEDICTIO]) - return 1; - if (sc->data[SC_CHANGEUNDEAD]) - return 1; - if (sc->data[SC_ELEMENTALCHANGE]) - return sc->data[SC_ELEMENTALCHANGE]->val1; - if (sc->data[SC_SHAPESHIFT]) - return 1; - if (sc->data[SC__INVISIBILITY]) - return 1; - - return (unsigned char)cap_value(lv,1,4); + if(!sc || !sc->count) + return lv; + + if(sc->data[SC_FREEZE]) + return 1; + if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) + return 1; + if(sc->data[SC_BENEDICTIO]) + return 1; + if(sc->data[SC_CHANGEUNDEAD]) + return 1; + if(sc->data[SC_ELEMENTALCHANGE]) + return sc->data[SC_ELEMENTALCHANGE]->val1; + if(sc->data[SC_SHAPESHIFT]) + return 1; + if(sc->data[SC__INVISIBILITY]) + return 1; + + return (unsigned char)cap_value(lv,1,4); } unsigned char status_calc_attack_element(struct block_list *bl, struct status_change *sc, int element) { - if (!sc || !sc->count) - return element; - if (sc->data[SC_ENCHANTARMS]) - return sc->data[SC_ENCHANTARMS]->val2; - if (sc->data[SC_WATERWEAPON] - || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2)) - return ELE_WATER; - if (sc->data[SC_EARTHWEAPON] - || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2)) - return ELE_EARTH; - if (sc->data[SC_FIREWEAPON] - || (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2)) - return ELE_FIRE; - if (sc->data[SC_WINDWEAPON] - || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2)) - return ELE_WIND; - if (sc->data[SC_ENCPOISON]) - return ELE_POISON; - if (sc->data[SC_ASPERSIO]) - return ELE_HOLY; - if (sc->data[SC_SHADOWWEAPON]) - return ELE_DARK; - if (sc->data[SC_GHOSTWEAPON] || sc->data[SC__INVISIBILITY]) - return ELE_GHOST; - if (sc->data[SC_TIDAL_WEAPON_OPTION] || sc->data[SC_TIDAL_WEAPON]) - return ELE_WATER; - if (sc->data[SC_PYROCLASTIC]) + if(!sc || !sc->count) + return element; + if(sc->data[SC_ENCHANTARMS]) + return sc->data[SC_ENCHANTARMS]->val2; + if(sc->data[SC_WATERWEAPON] + || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) ) + return ELE_WATER; + if(sc->data[SC_EARTHWEAPON] + || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) ) + return ELE_EARTH; + if(sc->data[SC_FIREWEAPON] + || (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) ) + return ELE_FIRE; + if(sc->data[SC_WINDWEAPON] + || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2) ) + return ELE_WIND; + if(sc->data[SC_ENCPOISON]) + return ELE_POISON; + if(sc->data[SC_ASPERSIO]) + return ELE_HOLY; + if(sc->data[SC_SHADOWWEAPON]) + return ELE_DARK; + if(sc->data[SC_GHOSTWEAPON] || sc->data[SC__INVISIBILITY]) + return ELE_GHOST; + if(sc->data[SC_TIDAL_WEAPON_OPTION] || sc->data[SC_TIDAL_WEAPON] ) + return ELE_WATER; + if(sc->data[SC_PYROCLASTIC]) return ELE_FIRE; - return (unsigned char)cap_value(element,0,UCHAR_MAX); + return (unsigned char)cap_value(element,0,UCHAR_MAX); } static unsigned short status_calc_mode(struct block_list *bl, struct status_change *sc, int mode) { - if (!sc || !sc->count) - return mode; - if (sc->data[SC_MODECHANGE]) { - if (sc->data[SC_MODECHANGE]->val2) - mode = sc->data[SC_MODECHANGE]->val2; //Set mode - if (sc->data[SC_MODECHANGE]->val3) - mode|= sc->data[SC_MODECHANGE]->val3; //Add mode - if (sc->data[SC_MODECHANGE]->val4) - mode&=~sc->data[SC_MODECHANGE]->val4; //Del mode - } - return cap_value(mode,0,USHRT_MAX); + if(!sc || !sc->count) + return mode; + if(sc->data[SC_MODECHANGE]) { + if (sc->data[SC_MODECHANGE]->val2) + mode = sc->data[SC_MODECHANGE]->val2; //Set mode + if (sc->data[SC_MODECHANGE]->val3) + mode|= sc->data[SC_MODECHANGE]->val3; //Add mode + if (sc->data[SC_MODECHANGE]->val4) + mode&=~sc->data[SC_MODECHANGE]->val4; //Del mode + } + return cap_value(mode,0,USHRT_MAX); } -const char *status_get_name(struct block_list *bl) -{ - nullpo_ret(bl); - switch (bl->type) { - case BL_PC: - return ((TBL_PC *)bl)->fakename[0] != '\0' ? ((TBL_PC *)bl)->fakename : ((TBL_PC *)bl)->status.name; - case BL_MOB: - return ((TBL_MOB *)bl)->name; - case BL_PET: - return ((TBL_PET *)bl)->pet.name; - case BL_HOM: - return ((TBL_HOM *)bl)->homunculus.name; - case BL_NPC: - return ((TBL_NPC *)bl)->name; - } - return "Unknown"; +const char* status_get_name(struct block_list *bl) { + nullpo_ret(bl); + switch (bl->type) { + case BL_PC: return ((TBL_PC *)bl)->fakename[0] != '\0' ? ((TBL_PC*)bl)->fakename : ((TBL_PC*)bl)->status.name; + case BL_MOB: return ((TBL_MOB*)bl)->name; + case BL_PET: return ((TBL_PET*)bl)->pet.name; + case BL_HOM: return ((TBL_HOM*)bl)->homunculus.name; + case BL_NPC: return ((TBL_NPC*)bl)->name; + } + return "Unknown"; } /*========================================== * Get the class of the current bl * return - * 0 = fail - * class_id = success + * 0 = fail + * class_id = success *------------------------------------------*/ -int status_get_class(struct block_list *bl) -{ - nullpo_ret(bl); - switch (bl->type) { - case BL_PC: - return ((TBL_PC *)bl)->status.class_; - case BL_MOB: - return ((TBL_MOB *)bl)->vd->class_; //Class used on all code should be the view class of the mob. - case BL_PET: - return ((TBL_PET *)bl)->pet.class_; - case BL_HOM: - return ((TBL_HOM *)bl)->homunculus.class_; - case BL_MER: - return ((TBL_MER *)bl)->mercenary.class_; - case BL_NPC: - return ((TBL_NPC *)bl)->class_; - case BL_ELEM: - return ((TBL_ELEM *)bl)->elemental.class_; - } - return 0; +int status_get_class(struct block_list *bl) { + nullpo_ret(bl); + switch( bl->type ) { + case BL_PC: return ((TBL_PC*)bl)->status.class_; + case BL_MOB: return ((TBL_MOB*)bl)->vd->class_; //Class used on all code should be the view class of the mob. + case BL_PET: return ((TBL_PET*)bl)->pet.class_; + case BL_HOM: return ((TBL_HOM*)bl)->homunculus.class_; + case BL_MER: return ((TBL_MER*)bl)->mercenary.class_; + case BL_NPC: return ((TBL_NPC*)bl)->class_; + case BL_ELEM: return ((TBL_ELEM*)bl)->elemental.class_; + } + return 0; } /*========================================== * Get the base level of the current bl * return - * 1 = fail - * level = success + * 1 = fail + * level = success *------------------------------------------*/ -int status_get_lv(struct block_list *bl) -{ - nullpo_ret(bl); - switch (bl->type) { - case BL_PC: - return ((TBL_PC *)bl)->status.base_level; - case BL_MOB: - return ((TBL_MOB *)bl)->level; - case BL_PET: - return ((TBL_PET *)bl)->pet.level; - case BL_HOM: - return ((TBL_HOM *)bl)->homunculus.level; - case BL_MER: - return ((TBL_MER *)bl)->db->lv; - case BL_ELEM: - return ((TBL_ELEM *)bl)->db->lv; - } - return 1; +int status_get_lv(struct block_list *bl) { + nullpo_ret(bl); + switch (bl->type) { + case BL_PC: return ((TBL_PC*)bl)->status.base_level; + case BL_MOB: return ((TBL_MOB*)bl)->level; + case BL_PET: return ((TBL_PET*)bl)->pet.level; + case BL_HOM: return ((TBL_HOM*)bl)->homunculus.level; + case BL_MER: return ((TBL_MER*)bl)->db->lv; + case BL_ELEM: return ((TBL_ELEM*)bl)->db->lv; + } + return 1; } -struct regen_data *status_get_regen_data(struct block_list *bl) { - nullpo_retr(NULL, bl); - switch (bl->type) { - case BL_PC: - return &((TBL_PC *)bl)->regen; - case BL_HOM: - return &((TBL_HOM *)bl)->regen; - case BL_MER: - return &((TBL_MER *)bl)->regen; - case BL_ELEM: - return &((TBL_ELEM *)bl)->regen; - default: - return NULL; - } +struct regen_data *status_get_regen_data(struct block_list *bl) +{ + nullpo_retr(NULL, bl); + switch (bl->type) { + case BL_PC: return &((TBL_PC*)bl)->regen; + case BL_HOM: return &((TBL_HOM*)bl)->regen; + case BL_MER: return &((TBL_MER*)bl)->regen; + case BL_ELEM: return &((TBL_ELEM*)bl)->regen; + default: + return NULL; + } } -struct status_data *status_get_status_data(struct block_list *bl) { - nullpo_retr(&dummy_status, bl); - - switch (bl->type) { - case BL_PC: - return &((TBL_PC *)bl)->battle_status; - case BL_MOB: - return &((TBL_MOB *)bl)->status; - case BL_PET: - return &((TBL_PET *)bl)->status; - case BL_HOM: - return &((TBL_HOM *)bl)->battle_status; - case BL_MER: - return &((TBL_MER *)bl)->battle_status; - case BL_ELEM: - return &((TBL_ELEM *)bl)->battle_status; - default: - return &dummy_status; - } +struct status_data *status_get_status_data(struct block_list *bl) +{ + nullpo_retr(&dummy_status, bl); + + switch (bl->type) { + case BL_PC: return &((TBL_PC*)bl)->battle_status; + case BL_MOB: return &((TBL_MOB*)bl)->status; + case BL_PET: return &((TBL_PET*)bl)->status; + case BL_HOM: return &((TBL_HOM*)bl)->battle_status; + case BL_MER: return &((TBL_MER*)bl)->battle_status; + case BL_ELEM: return &((TBL_ELEM*)bl)->battle_status; + default: + return &dummy_status; + } } -struct status_data *status_get_base_status(struct block_list *bl) { - nullpo_retr(NULL, bl); - switch (bl->type) { - case BL_PC: - return &((TBL_PC *)bl)->base_status; - case BL_MOB: - return ((TBL_MOB *)bl)->base_status ? ((TBL_MOB *)bl)->base_status : &((TBL_MOB *)bl)->db->status; - case BL_PET: - return &((TBL_PET *)bl)->db->status; - case BL_HOM: - return &((TBL_HOM *)bl)->base_status; - case BL_MER: - return &((TBL_MER *)bl)->base_status; - case BL_ELEM: - return &((TBL_ELEM *)bl)->base_status; - default: - return NULL; - } -} -defType status_get_def(struct block_list *bl) +struct status_data *status_get_base_status(struct block_list *bl) { - struct unit_data *ud; - struct status_data *status = status_get_status_data(bl); - int def = status?status->def:0; - ud = unit_bl2ud(bl); - if (ud && ud->skilltimer != INVALID_TIMER) - def -= def * skill_get_castdef(ud->skillid)/100; - - return cap_value(def, DEFTYPE_MIN, DEFTYPE_MAX); + nullpo_retr(NULL, bl); + switch (bl->type) { + case BL_PC: return &((TBL_PC*)bl)->base_status; + case BL_MOB: return ((TBL_MOB*)bl)->base_status ? ((TBL_MOB*)bl)->base_status : &((TBL_MOB*)bl)->db->status; + case BL_PET: return &((TBL_PET*)bl)->db->status; + case BL_HOM: return &((TBL_HOM*)bl)->base_status; + case BL_MER: return &((TBL_MER*)bl)->base_status; + case BL_ELEM: return &((TBL_ELEM*)bl)->base_status; + default: + return NULL; + } +} +defType status_get_def(struct block_list *bl) { + struct unit_data *ud; + struct status_data *status = status_get_status_data(bl); + int def = status?status->def:0; + ud = unit_bl2ud(bl); + if (ud && ud->skilltimer != INVALID_TIMER) + def -= def * skill_get_castdef(ud->skillid)/100; + + return cap_value(def, DEFTYPE_MIN, DEFTYPE_MAX); } unsigned short status_get_speed(struct block_list *bl) { - if (bl->type==BL_NPC) //Only BL with speed data but no status_data [Skotlex] - return ((struct npc_data *)bl)->speed; - return status_get_status_data(bl)->speed; + if(bl->type==BL_NPC)//Only BL with speed data but no status_data [Skotlex] + return ((struct npc_data *)bl)->speed; + return status_get_status_data(bl)->speed; } -int status_get_party_id(struct block_list *bl) -{ - nullpo_ret(bl); - switch (bl->type) { - case BL_PC: - return ((TBL_PC *)bl)->status.party_id; - case BL_PET: - if (((TBL_PET *)bl)->msd) - return ((TBL_PET *)bl)->msd->status.party_id; - break; - case BL_MOB: { - struct mob_data *md=(TBL_MOB *)bl; - if (md->master_id > 0) { - struct map_session_data *msd; - if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL) - return msd->status.party_id; - return -md->master_id; - } - } - break; - case BL_HOM: - if (((TBL_HOM *)bl)->master) - return ((TBL_HOM *)bl)->master->status.party_id; - break; - case BL_MER: - if (((TBL_MER *)bl)->master) - return ((TBL_MER *)bl)->master->status.party_id; - break; - case BL_SKILL: - return ((TBL_SKILL *)bl)->group->party_id; - case BL_ELEM: - if (((TBL_ELEM *)bl)->master) - return ((TBL_ELEM *)bl)->master->status.party_id; - break; - } - return 0; +int status_get_party_id(struct block_list *bl) { + nullpo_ret(bl); + switch (bl->type) { + case BL_PC: + return ((TBL_PC*)bl)->status.party_id; + case BL_PET: + if (((TBL_PET*)bl)->msd) + return ((TBL_PET*)bl)->msd->status.party_id; + break; + case BL_MOB: { + struct mob_data *md=(TBL_MOB*)bl; + if( md->master_id > 0 ) { + struct map_session_data *msd; + if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL) + return msd->status.party_id; + return -md->master_id; + } + } + break; + case BL_HOM: + if (((TBL_HOM*)bl)->master) + return ((TBL_HOM*)bl)->master->status.party_id; + break; + case BL_MER: + if (((TBL_MER*)bl)->master) + return ((TBL_MER*)bl)->master->status.party_id; + break; + case BL_SKILL: + return ((TBL_SKILL*)bl)->group->party_id; + case BL_ELEM: + if (((TBL_ELEM*)bl)->master) + return ((TBL_ELEM*)bl)->master->status.party_id; + break; + } + return 0; } -int status_get_guild_id(struct block_list *bl) -{ - nullpo_ret(bl); - switch (bl->type) { - case BL_PC: - return ((TBL_PC *)bl)->status.guild_id; - case BL_PET: - if (((TBL_PET *)bl)->msd) - return ((TBL_PET *)bl)->msd->status.guild_id; - break; - case BL_MOB: { - struct map_session_data *msd; - struct mob_data *md = (struct mob_data *)bl; - if (md->guardian_data) //Guardian's guild [Skotlex] - return md->guardian_data->guild_id; - if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL) - return msd->status.guild_id; //Alchemist's mobs [Skotlex] - } - break; - case BL_HOM: - if (((TBL_HOM *)bl)->master) - return ((TBL_HOM *)bl)->master->status.guild_id; - break; - case BL_MER: - if (((TBL_MER *)bl)->master) - return ((TBL_MER *)bl)->master->status.guild_id; - break; - case BL_NPC: - if (((TBL_NPC *)bl)->subtype == SCRIPT) - return ((TBL_NPC *)bl)->u.scr.guild_id; - break; - case BL_SKILL: - return ((TBL_SKILL *)bl)->group->guild_id; - case BL_ELEM: - if (((TBL_ELEM *)bl)->master) - return ((TBL_ELEM *)bl)->master->status.guild_id; - break; - } - return 0; +int status_get_guild_id(struct block_list *bl) { + nullpo_ret(bl); + switch (bl->type) { + case BL_PC: + return ((TBL_PC*)bl)->status.guild_id; + case BL_PET: + if (((TBL_PET*)bl)->msd) + return ((TBL_PET*)bl)->msd->status.guild_id; + break; + case BL_MOB: { + struct map_session_data *msd; + struct mob_data *md = (struct mob_data *)bl; + if (md->guardian_data) //Guardian's guild [Skotlex] + return md->guardian_data->guild_id; + if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL) + return msd->status.guild_id; //Alchemist's mobs [Skotlex] + } + break; + case BL_HOM: + if (((TBL_HOM*)bl)->master) + return ((TBL_HOM*)bl)->master->status.guild_id; + break; + case BL_MER: + if (((TBL_MER*)bl)->master) + return ((TBL_MER*)bl)->master->status.guild_id; + break; + case BL_NPC: + if (((TBL_NPC*)bl)->subtype == SCRIPT) + return ((TBL_NPC*)bl)->u.scr.guild_id; + break; + case BL_SKILL: + return ((TBL_SKILL*)bl)->group->guild_id; + case BL_ELEM: + if (((TBL_ELEM*)bl)->master) + return ((TBL_ELEM*)bl)->master->status.guild_id; + break; + } + return 0; } -int status_get_emblem_id(struct block_list *bl) -{ - nullpo_ret(bl); - switch (bl->type) { - case BL_PC: - return ((TBL_PC *)bl)->guild_emblem_id; - case BL_PET: - if (((TBL_PET *)bl)->msd) - return ((TBL_PET *)bl)->msd->guild_emblem_id; - break; - case BL_MOB: { - struct map_session_data *msd; - struct mob_data *md = (struct mob_data *)bl; - if (md->guardian_data) //Guardian's guild [Skotlex] - return md->guardian_data->emblem_id; - if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL) - return msd->guild_emblem_id; //Alchemist's mobs [Skotlex] - } - break; - case BL_HOM: - if (((TBL_HOM *)bl)->master) - return ((TBL_HOM *)bl)->master->guild_emblem_id; - break; - case BL_MER: - if (((TBL_MER *)bl)->master) - return ((TBL_MER *)bl)->master->guild_emblem_id; - break; - case BL_NPC: - if (((TBL_NPC *)bl)->subtype == SCRIPT && ((TBL_NPC *)bl)->u.scr.guild_id > 0) { - struct guild *g = guild_search(((TBL_NPC *)bl)->u.scr.guild_id); - if (g) - return g->emblem_id; - } - break; - case BL_ELEM: - if (((TBL_ELEM *)bl)->master) - return ((TBL_ELEM *)bl)->master->guild_emblem_id; - break; - } - return 0; +int status_get_emblem_id(struct block_list *bl) { + nullpo_ret(bl); + switch (bl->type) { + case BL_PC: + return ((TBL_PC*)bl)->guild_emblem_id; + case BL_PET: + if (((TBL_PET*)bl)->msd) + return ((TBL_PET*)bl)->msd->guild_emblem_id; + break; + case BL_MOB: { + struct map_session_data *msd; + struct mob_data *md = (struct mob_data *)bl; + if (md->guardian_data) //Guardian's guild [Skotlex] + return md->guardian_data->emblem_id; + if (md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL) + return msd->guild_emblem_id; //Alchemist's mobs [Skotlex] + } + break; + case BL_HOM: + if (((TBL_HOM*)bl)->master) + return ((TBL_HOM*)bl)->master->guild_emblem_id; + break; + case BL_MER: + if (((TBL_MER*)bl)->master) + return ((TBL_MER*)bl)->master->guild_emblem_id; + break; + case BL_NPC: + if (((TBL_NPC*)bl)->subtype == SCRIPT && ((TBL_NPC*)bl)->u.scr.guild_id > 0) { + struct guild *g = guild_search(((TBL_NPC*)bl)->u.scr.guild_id); + if (g) + return g->emblem_id; + } + break; + case BL_ELEM: + if (((TBL_ELEM*)bl)->master) + return ((TBL_ELEM*)bl)->master->guild_emblem_id; + break; + } + return 0; } int status_get_mexp(struct block_list *bl) { - nullpo_ret(bl); - if (bl->type==BL_MOB) - return ((struct mob_data *)bl)->db->mexp; - if (bl->type==BL_PET) - return ((struct pet_data *)bl)->db->mexp; - return 0; + nullpo_ret(bl); + if(bl->type==BL_MOB) + return ((struct mob_data *)bl)->db->mexp; + if(bl->type==BL_PET) + return ((struct pet_data *)bl)->db->mexp; + return 0; } int status_get_race2(struct block_list *bl) { - nullpo_ret(bl); - if (bl->type == BL_MOB) - return ((struct mob_data *)bl)->db->race2; - if (bl->type==BL_PET) - return ((struct pet_data *)bl)->db->race2; - return 0; + nullpo_ret(bl); + if(bl->type == BL_MOB) + return ((struct mob_data *)bl)->db->race2; + if(bl->type==BL_PET) + return ((struct pet_data *)bl)->db->race2; + return 0; } int status_isdead(struct block_list *bl) { - nullpo_ret(bl); - return status_get_status_data(bl)->hp == 0; + nullpo_ret(bl); + return status_get_status_data(bl)->hp == 0; } int status_isimmune(struct block_list *bl) { - struct status_change *sc =status_get_sc(bl); - if (sc && sc->data[SC_HERMODE]) - return 100; - - if (bl->type == BL_PC && - ((TBL_PC *)bl)->special_state.no_magic_damage >= battle_config.gtb_sc_immunity) - return ((TBL_PC *)bl)->special_state.no_magic_damage; - return 0; + struct status_change *sc =status_get_sc(bl); + if (sc && sc->data[SC_HERMODE]) + return 100; + + if (bl->type == BL_PC && + ((TBL_PC*)bl)->special_state.no_magic_damage >= battle_config.gtb_sc_immunity) + return ((TBL_PC*)bl)->special_state.no_magic_damage; + return 0; } -struct view_data *status_get_viewdata(struct block_list *bl) { - nullpo_retr(NULL, bl); - switch (bl->type) { - case BL_PC: - return &((TBL_PC *)bl)->vd; - case BL_MOB: - return ((TBL_MOB *)bl)->vd; - case BL_PET: - return &((TBL_PET *)bl)->vd; - case BL_NPC: - return ((TBL_NPC *)bl)->vd; - case BL_HOM: - return ((TBL_HOM *)bl)->vd; - case BL_MER: - return ((TBL_MER *)bl)->vd; - case BL_ELEM: - return ((TBL_ELEM *)bl)->vd; - } - return NULL; +struct view_data* status_get_viewdata(struct block_list *bl) +{ + nullpo_retr(NULL, bl); + switch (bl->type) { + case BL_PC: return &((TBL_PC*)bl)->vd; + case BL_MOB: return ((TBL_MOB*)bl)->vd; + case BL_PET: return &((TBL_PET*)bl)->vd; + case BL_NPC: return ((TBL_NPC*)bl)->vd; + case BL_HOM: return ((TBL_HOM*)bl)->vd; + case BL_MER: return ((TBL_MER*)bl)->vd; + case BL_ELEM: return ((TBL_ELEM*)bl)->vd; + } + return NULL; } void status_set_viewdata(struct block_list *bl, int class_) { - struct view_data *vd; - nullpo_retv(bl); - if (mobdb_checkid(class_) || mob_is_clone(class_)) - vd = mob_get_viewdata(class_); - else if (npcdb_checkid(class_) || (bl->type == BL_NPC && class_ == WARP_CLASS)) - vd = npc_get_viewdata(class_); - else if (homdb_checkid(class_)) - vd = merc_get_hom_viewdata(class_); - else if (merc_class(class_)) - vd = merc_get_viewdata(class_); - else if (elemental_class(class_)) - vd = elemental_get_viewdata(class_); - else - vd = NULL; - - switch (bl->type) { - case BL_PC: { - TBL_PC *sd = (TBL_PC *)bl; - if (pcdb_checkid(class_)) { - if (sd->sc.option&OPTION_WEDDING) - class_ = JOB_WEDDING; - else if (sd->sc.option&OPTION_SUMMER) - class_ = JOB_SUMMER; - else if (sd->sc.option&OPTION_XMAS) - class_ = JOB_XMAS; - else if (sd->sc.option&OPTION_RIDING) { - switch (class_) { //Adapt class to a Mounted one. - case JOB_KNIGHT: - class_ = JOB_KNIGHT2; - break; - case JOB_CRUSADER: - class_ = JOB_CRUSADER2; - break; - case JOB_LORD_KNIGHT: - class_ = JOB_LORD_KNIGHT2; - break; - case JOB_PALADIN: - class_ = JOB_PALADIN2; - break; - case JOB_BABY_KNIGHT: - class_ = JOB_BABY_KNIGHT2; - break; - case JOB_BABY_CRUSADER: - class_ = JOB_BABY_CRUSADER2; - break; - } - } - sd->vd.class_ = class_; - clif_get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield); - sd->vd.head_top = sd->status.head_top; - sd->vd.head_mid = sd->status.head_mid; - sd->vd.head_bottom = sd->status.head_bottom; - sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style); - sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color); - sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color); - sd->vd.sex = sd->status.sex; - } else if (vd) - memcpy(&sd->vd, vd, sizeof(struct view_data)); - else - ShowError("status_set_viewdata (PC): No view data for class %d\n", class_); - } - break; - case BL_MOB: { - TBL_MOB *md = (TBL_MOB *)bl; - if (vd) - md->vd = vd; - else - ShowError("status_set_viewdata (MOB): No view data for class %d\n", class_); - } - break; - case BL_PET: { - TBL_PET *pd = (TBL_PET *)bl; - if (vd) { - memcpy(&pd->vd, vd, sizeof(struct view_data)); - if (!pcdb_checkid(vd->class_)) { - pd->vd.hair_style = battle_config.pet_hair_style; - if (pd->pet.equip) { - pd->vd.head_bottom = itemdb_viewid(pd->pet.equip); - if (!pd->vd.head_bottom) - pd->vd.head_bottom = pd->pet.equip; - } - } - } else - ShowError("status_set_viewdata (PET): No view data for class %d\n", class_); - } - break; - case BL_NPC: { - TBL_NPC *nd = (TBL_NPC *)bl; - if (vd) - nd->vd = vd; - else - ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_); - } - break; - case BL_HOM: { //[blackhole89] - struct homun_data *hd = (struct homun_data *)bl; - if (vd) - hd->vd = vd; - else - ShowError("status_set_viewdata (HOMUNCULUS): No view data for class %d\n", class_); - } - break; - case BL_MER: { - struct mercenary_data *md = (struct mercenary_data *)bl; - if (vd) - md->vd = vd; - else - ShowError("status_set_viewdata (MERCENARY): No view data for class %d\n", class_); - } - break; - case BL_ELEM: { - struct elemental_data *ed = (struct elemental_data *)bl; - if (vd) - ed->vd = vd; - else - ShowError("status_set_viewdata (ELEMENTAL): No view data for class %d\n", class_); - } - break; - } - vd = status_get_viewdata(bl); - if (vd && vd->cloth_color && ( - (vd->class_==JOB_WEDDING && battle_config.wedding_ignorepalette) - || (vd->class_==JOB_XMAS && battle_config.xmas_ignorepalette) - || (vd->class_==JOB_SUMMER && battle_config.summer_ignorepalette) - )) - vd->cloth_color = 0; + struct view_data* vd; + nullpo_retv(bl); + if (mobdb_checkid(class_) || mob_is_clone(class_)) + vd = mob_get_viewdata(class_); + else if (npcdb_checkid(class_) || (bl->type == BL_NPC && class_ == WARP_CLASS)) + vd = npc_get_viewdata(class_); + else if (homdb_checkid(class_)) + vd = merc_get_hom_viewdata(class_); + else if (merc_class(class_)) + vd = merc_get_viewdata(class_); + else if (elemental_class(class_)) + vd = elemental_get_viewdata(class_); + else + vd = NULL; + + switch (bl->type) { + case BL_PC: + { + TBL_PC* sd = (TBL_PC*)bl; + if (pcdb_checkid(class_)) { + if (sd->sc.option&OPTION_WEDDING) + class_ = JOB_WEDDING; + else if (sd->sc.option&OPTION_SUMMER) + class_ = JOB_SUMMER; + else if (sd->sc.option&OPTION_XMAS) + class_ = JOB_XMAS; + else if (sd->sc.option&OPTION_RIDING) { + switch (class_) { //Adapt class to a Mounted one. + case JOB_KNIGHT: + class_ = JOB_KNIGHT2; + break; + case JOB_CRUSADER: + class_ = JOB_CRUSADER2; + break; + case JOB_LORD_KNIGHT: + class_ = JOB_LORD_KNIGHT2; + break; + case JOB_PALADIN: + class_ = JOB_PALADIN2; + break; + case JOB_BABY_KNIGHT: + class_ = JOB_BABY_KNIGHT2; + break; + case JOB_BABY_CRUSADER: + class_ = JOB_BABY_CRUSADER2; + break; + } + } + sd->vd.class_ = class_; + clif_get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield); + sd->vd.head_top = sd->status.head_top; + sd->vd.head_mid = sd->status.head_mid; + sd->vd.head_bottom = sd->status.head_bottom; + sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style); + sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color); + sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color); + sd->vd.sex = sd->status.sex; + } else if (vd) + memcpy(&sd->vd, vd, sizeof(struct view_data)); + else + ShowError("status_set_viewdata (PC): No view data for class %d\n", class_); + } + break; + case BL_MOB: + { + TBL_MOB* md = (TBL_MOB*)bl; + if (vd) + md->vd = vd; + else + ShowError("status_set_viewdata (MOB): No view data for class %d\n", class_); + } + break; + case BL_PET: + { + TBL_PET* pd = (TBL_PET*)bl; + if (vd) { + memcpy(&pd->vd, vd, sizeof(struct view_data)); + if (!pcdb_checkid(vd->class_)) { + pd->vd.hair_style = battle_config.pet_hair_style; + if(pd->pet.equip) { + pd->vd.head_bottom = itemdb_viewid(pd->pet.equip); + if (!pd->vd.head_bottom) + pd->vd.head_bottom = pd->pet.equip; + } + } + } else + ShowError("status_set_viewdata (PET): No view data for class %d\n", class_); + } + break; + case BL_NPC: + { + TBL_NPC* nd = (TBL_NPC*)bl; + if (vd) + nd->vd = vd; + else + ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_); + } + break; + case BL_HOM: //[blackhole89] + { + struct homun_data *hd = (struct homun_data*)bl; + if (vd) + hd->vd = vd; + else + ShowError("status_set_viewdata (HOMUNCULUS): No view data for class %d\n", class_); + } + break; + case BL_MER: + { + struct mercenary_data *md = (struct mercenary_data*)bl; + if (vd) + md->vd = vd; + else + ShowError("status_set_viewdata (MERCENARY): No view data for class %d\n", class_); + } + break; + case BL_ELEM: + { + struct elemental_data *ed = (struct elemental_data*)bl; + if (vd) + ed->vd = vd; + else + ShowError("status_set_viewdata (ELEMENTAL): No view data for class %d\n", class_); + } + break; + } + vd = status_get_viewdata(bl); + if (vd && vd->cloth_color && ( + (vd->class_==JOB_WEDDING && battle_config.wedding_ignorepalette) + || (vd->class_==JOB_XMAS && battle_config.xmas_ignorepalette) + || (vd->class_==JOB_SUMMER && battle_config.summer_ignorepalette) + )) + vd->cloth_color = 0; } /// Returns the status_change data of bl or NULL if it doesn't exist. struct status_change *status_get_sc(struct block_list *bl) { - if (bl) - switch (bl->type) { - case BL_PC: - return &((TBL_PC *)bl)->sc; - case BL_MOB: - return &((TBL_MOB *)bl)->sc; - case BL_NPC: - return &((TBL_NPC *)bl)->sc; - case BL_HOM: - return &((TBL_HOM *)bl)->sc; - case BL_MER: - return &((TBL_MER *)bl)->sc; - case BL_ELEM: - return &((TBL_ELEM *)bl)->sc; - } - return NULL; + if( bl ) + switch (bl->type) { + case BL_PC: return &((TBL_PC*)bl)->sc; + case BL_MOB: return &((TBL_MOB*)bl)->sc; + case BL_NPC: return &((TBL_NPC*)bl)->sc; + case BL_HOM: return &((TBL_HOM*)bl)->sc; + case BL_MER: return &((TBL_MER*)bl)->sc; + case BL_ELEM: return &((TBL_ELEM*)bl)->sc; + } + return NULL; } void status_change_init(struct block_list *bl) { - struct status_change *sc = status_get_sc(bl); - nullpo_retv(sc); - memset(sc, 0, sizeof(struct status_change)); + struct status_change *sc = status_get_sc(bl); + nullpo_retv(sc); + memset(sc, 0, sizeof (struct status_change)); } //Applies SC defense to a given status change. @@ -6141,234 +6060,227 @@ void status_change_init(struct block_list *bl) //the flag values are the same as in status_change_start. int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int tick, int flag) { - int sc_def = 0, tick_def = 0; - struct status_data *status; - struct status_change *sc; - struct map_session_data *sd; - - nullpo_ret(bl); - - //Status that are blocked by Golden Thief Bug card or Wand of Hermod - if (status_isimmune(bl)) - switch (type) { - case SC_DECREASEAGI: - case SC_SILENCE: - case SC_COMA: - case SC_INCREASEAGI: - case SC_BLESSING: - case SC_SLOWPOISON: - case SC_IMPOSITIO: - case SC_AETERNA: - case SC_SUFFRAGIUM: - case SC_BENEDICTIO: - case SC_PROVIDENCE: - case SC_KYRIE: - case SC_ASSUMPTIO: - case SC_ANGELUS: - case SC_MAGNIFICAT: - case SC_GLORIA: - case SC_WINDWALK: - case SC_MAGICROD: - case SC_HALLUCINATION: - case SC_STONE: - case SC_QUAGMIRE: - case SC_SUITON: - case SC_SWINGDANCE: - case SC__ENERVATION: - case SC__GROOMY: - case SC__IGNORANCE: - case SC__LAZINESS: - case SC__UNLUCKY: - case SC__WEAKNESS: - case SC__BLOODYLUST: - return 0; - } + int sc_def = 0, tick_def = 0; + struct status_data* status; + struct status_change* sc; + struct map_session_data *sd; + + nullpo_ret(bl); + + //Status that are blocked by Golden Thief Bug card or Wand of Hermod + if (status_isimmune(bl)) + switch (type) { + case SC_DECREASEAGI: + case SC_SILENCE: + case SC_COMA: + case SC_INCREASEAGI: + case SC_BLESSING: + case SC_SLOWPOISON: + case SC_IMPOSITIO: + case SC_AETERNA: + case SC_SUFFRAGIUM: + case SC_BENEDICTIO: + case SC_PROVIDENCE: + case SC_KYRIE: + case SC_ASSUMPTIO: + case SC_ANGELUS: + case SC_MAGNIFICAT: + case SC_GLORIA: + case SC_WINDWALK: + case SC_MAGICROD: + case SC_HALLUCINATION: + case SC_STONE: + case SC_QUAGMIRE: + case SC_SUITON: + case SC_SWINGDANCE: + case SC__ENERVATION: + case SC__GROOMY: + case SC__IGNORANCE: + case SC__LAZINESS: + case SC__UNLUCKY: + case SC__WEAKNESS: + case SC__BLOODYLUST: + return 0; + } - sd = BL_CAST(BL_PC,bl); - status = status_get_status_data(bl); - sc = status_get_sc(bl); - if (sc && !sc->count) - sc = NULL; - switch (type) { - case SC_STUN: - case SC_POISON: - if (sc && sc->data[SC__UNLUCKY]) - return tick; - case SC_DPOISON: - case SC_SILENCE: - case SC_BLEEDING: - sc_def = 3 +status->vit; - break; - case SC_SLEEP: - sc_def = 3 +status->int_; - break; - case SC_DEEPSLEEP: - tick_def = status->int_ / 10 + status_get_lv(bl) * 65 / 1000; // Seems to be -1 sec every 10 int and -5% chance every 10 int. - sc_def = 5 * status->int_ /10; - break; - case SC_DECREASEAGI: - case SC_ADORAMUS://Arch Bishop - if (sd) tick>>=1; //Half duration for players. - case SC_STONE: - case SC_FREEZE: - sc_def = 3 +status->mdef; - break; - case SC_CURSE: - //Special property: inmunity when luk is greater than level or zero - if (status->luk > status_get_lv(bl) || status->luk == 0) - return 0; - else - sc_def = 3 +status->luk; - tick_def = status->vit; - break; - case SC_BLIND: - if (sc && sc->data[SC__UNLUCKY]) - return tick; - sc_def = 3 +(status->vit + status->int_)/2; - break; - case SC_CONFUSION: - sc_def = 3 +(status->str + status->int_)/2; - break; - case SC_ANKLE: - if (status->mode&MD_BOSS) // Lasts 5 times less on bosses - tick /= 5; - sc_def = status->agi / 2; - break; - case SC_MAGICMIRROR: - case SC_ARMORCHANGE: - if (sd) //Duration greatly reduced for players. - tick /= 15; - //No defense against it (buff). - rate -= (status_get_lv(bl) / 5 + status->vit / 4 + status->agi / 10)*100; // Lineal Reduction of Rate - break; - case SC_MARSHOFABYSS: - //5 second (Fixed) + 25 second - {( INT + LUK ) / 20 second } - tick -= (status->int_ + status->luk) / 20 * 1000; - break; - case SC_STASIS: - //5 second (fixed) + { Stasis Skill level * 5 - (Targetソスs VIT + DEX) / 20 } - tick -= (status->vit + status->dex) / 20 * 1000; - break; - case SC_WHITEIMPRISON: - if (tick == 5000) // 100% on caster - break; - if (bl->type == BL_PC) - tick -= (status_get_lv(bl) / 5 + status->vit / 4 + status->agi / 10)*100; - else - tick -= (status->vit + status->luk) / 20 * 1000; - break; - case SC_BURNING: - // From iROwiki : http://forums.irowiki.org/showpost.php?p=577240&postcount=583 - tick -= 50*status->luk + 60*status->int_ + 170*status->vit; - tick = max(tick,10000); // Minimum Duration 10s. - break; - case SC_FREEZING: - tick -= 1000 * ((status->vit + status->dex) / 20); - tick = max(tick,10000); // Minimum Duration 10s. - break; - case SC_OBLIVIONCURSE: // 100% - (100 - 0.8 x INT) - sc_def = 100 - (100 - status->int_* 8 / 10); - sc_def = max(sc_def, 5); // minimum of 5% - break; - case SC_BITE: // {(Base Success chance) - (Target's AGI / 4)} - rate -= status->agi*1000/4; - rate = max(rate,50000); // minimum of 50% - break; - case SC_ELECTRICSHOCKER: - if (bl->type == BL_MOB) - tick -= 1000 * (status->agi/10); - break; - case SC_CRYSTALIZE: - tick -= (1000*(status->vit/10))+(status_get_lv(bl)/50); - break; - case SC_MANDRAGORA: - sc_def = (status->vit+status->luk)/5; - break; - case SC_KYOUGAKU: - tick -= 30*status->int_; - break; + sd = BL_CAST(BL_PC,bl); + status = status_get_status_data(bl); + sc = status_get_sc(bl); + if( sc && !sc->count ) + sc = NULL; + switch (type) { + case SC_STUN: + case SC_POISON: + if( sc && sc->data[SC__UNLUCKY] ) + return tick; + case SC_DPOISON: + case SC_SILENCE: + case SC_BLEEDING: + sc_def = 3 +status->vit; + break; + case SC_SLEEP: + sc_def = 3 +status->int_; + break; + case SC_DEEPSLEEP: + tick_def = status->int_ / 10 + status_get_lv(bl) * 65 / 1000; // Seems to be -1 sec every 10 int and -5% chance every 10 int. + sc_def = 5 * status->int_ /10; + break; + case SC_DECREASEAGI: + case SC_ADORAMUS://Arch Bishop + if (sd) tick>>=1; //Half duration for players. + case SC_STONE: + case SC_FREEZE: + sc_def = 3 +status->mdef; + break; + case SC_CURSE: + //Special property: inmunity when luk is greater than level or zero + if (status->luk > status_get_lv(bl) || status->luk == 0) + return 0; + else + sc_def = 3 +status->luk; + tick_def = status->vit; + break; + case SC_BLIND: + if( sc && sc->data[SC__UNLUCKY] ) + return tick; + sc_def = 3 +(status->vit + status->int_)/2; + break; + case SC_CONFUSION: + sc_def = 3 +(status->str + status->int_)/2; + break; + case SC_ANKLE: + if(status->mode&MD_BOSS) // Lasts 5 times less on bosses + tick /= 5; + sc_def = status->agi / 2; + break; + case SC_MAGICMIRROR: + case SC_ARMORCHANGE: + if (sd) //Duration greatly reduced for players. + tick /= 15; + //No defense against it (buff). + rate -= (status_get_lv(bl) / 5 + status->vit / 4 + status->agi / 10)*100; // Lineal Reduction of Rate + break; + case SC_WHITEIMPRISON: + if( tick == 5000 ) // 100% on caster + break; + if( bl->type == BL_PC ) + tick -= (status_get_lv(bl) / 5 + status->vit / 4 + status->agi / 10)*100; + else + tick -= (status->vit + status->luk) / 20 * 1000; + break; + case SC_BURNING: + // From iROwiki : http://forums.irowiki.org/showpost.php?p=577240&postcount=583 + tick -= 50*status->luk + 60*status->int_ + 170*status->vit; + tick = max(tick,10000); // Minimum Duration 10s. + break; + case SC_FREEZING: + tick -= 1000 * ((status->vit + status->dex) / 20); + tick = max(tick,10000); // Minimum Duration 10s. + break; + case SC_OBLIVIONCURSE: // 100% - (100 - 0.8 x INT) + sc_def = 100 - ( 100 - status->int_* 8 / 10 ); + sc_def = max(sc_def, 5); // minimum of 5% + break; + case SC_BITE: // {(Base Success chance) - (Target's AGI / 4)} + rate -= status->agi*1000/4; + rate = max(rate,50000); // minimum of 50% + break; + case SC_ELECTRICSHOCKER: + if( bl->type == BL_MOB ) + tick -= 1000 * (status->agi/10); + break; + case SC_CRYSTALIZE: + tick -= (1000*(status->vit/10))+(status_get_lv(bl)/50); + break; + case SC_MANDRAGORA: + sc_def = (status->vit+status->luk)/5; + break; + case SC_KYOUGAKU: + tick -= 30*status->int_; + break; case SC_PARALYSIS: tick -= 50 * (status->vit + status->luk); //(1000/20); break; - default: - //Effect that cannot be reduced? Likely a buff. - if (!(rnd()%10000 < rate)) - return 0; - return tick?tick:1; - } - - if (sd) { - - if (battle_config.pc_sc_def_rate != 100) - sc_def = sc_def*battle_config.pc_sc_def_rate/100; + default: + //Effect that cannot be reduced? Likely a buff. + if (!(rnd()%10000 < rate)) + return 0; + return tick?tick:1; + } - if (sc_def < battle_config.pc_max_sc_def) - sc_def += (battle_config.pc_max_sc_def - sc_def)* - status->luk/battle_config.pc_luk_sc_def; - else - sc_def = battle_config.pc_max_sc_def; + if (sd) { - if (tick_def) { - if (battle_config.pc_sc_def_rate != 100) - tick_def = tick_def*battle_config.pc_sc_def_rate/100; - } - - } else { + if (battle_config.pc_sc_def_rate != 100) + sc_def = sc_def*battle_config.pc_sc_def_rate/100; - if (battle_config.mob_sc_def_rate != 100) - sc_def = sc_def*battle_config.mob_sc_def_rate/100; + if (sc_def < battle_config.pc_max_sc_def) + sc_def += (battle_config.pc_max_sc_def - sc_def)* + status->luk/battle_config.pc_luk_sc_def; + else + sc_def = battle_config.pc_max_sc_def; - if (sc_def < battle_config.mob_max_sc_def) - sc_def += (battle_config.mob_max_sc_def - sc_def)* - status->luk/battle_config.mob_luk_sc_def; - else - sc_def = battle_config.mob_max_sc_def; - - if (tick_def) { - if (battle_config.mob_sc_def_rate != 100) - tick_def = tick_def*battle_config.mob_sc_def_rate/100; - } - } + if (tick_def) { + if (battle_config.pc_sc_def_rate != 100) + tick_def = tick_def*battle_config.pc_sc_def_rate/100; + } - if (sc) { - if (sc->data[SC_SCRESIST]) - sc_def += sc->data[SC_SCRESIST]->val1; //Status resist - else if (sc->data[SC_SIEGFRIED]) - sc_def += sc->data[SC_SIEGFRIED]->val3; //Status resistance. - } + } else { - //When no tick def, reduction is the same for both. - if (!tick_def && type != SC_STONE) //Recent tests show duration of petrify isn't reduced by MDEF. [Inkfish] - tick_def = sc_def; + if (battle_config.mob_sc_def_rate != 100) + sc_def = sc_def*battle_config.mob_sc_def_rate/100; - //Natural resistance - if (!(flag&8)) { - rate -= rate*sc_def/100; + if (sc_def < battle_config.mob_max_sc_def) + sc_def += (battle_config.mob_max_sc_def - sc_def)* + status->luk/battle_config.mob_luk_sc_def; + else + sc_def = battle_config.mob_max_sc_def; - //Item resistance (only applies to rate%) - if (sd && SC_COMMON_MIN <= type && type <= SC_COMMON_MAX) { - if (sd->reseff[type-SC_COMMON_MIN] > 0) - rate -= rate*sd->reseff[type-SC_COMMON_MIN]/10000; - if (sd->sc.data[SC_COMMONSC_RESIST]) - rate -= rate*sd->sc.data[SC_COMMONSC_RESIST]->val1/100; - } - } - if (!(rnd()%10000 < rate)) - return 0; - - //Why would a status start with no duration? Presume it has - //duration defined elsewhere. - if (!tick) return 1; - - //Rate reduction - if (flag&2) - return tick; - - tick -= tick*tick_def/100; - // Changed to 5 seconds according to recent tests [Playtester] - if (type == SC_ANKLE && tick < 5000) - tick = 5000; - return tick<=0?0:tick; + if (tick_def) { + if (battle_config.mob_sc_def_rate != 100) + tick_def = tick_def*battle_config.mob_sc_def_rate/100; + } + } + + if (sc) { + if (sc->data[SC_SCRESIST]) + sc_def += sc->data[SC_SCRESIST]->val1; //Status resist + else if (sc->data[SC_SIEGFRIED]) + sc_def += sc->data[SC_SIEGFRIED]->val3; //Status resistance. + } + + //When no tick def, reduction is the same for both. + if( !tick_def && type != SC_STONE ) //Recent tests show duration of petrify isn't reduced by MDEF. [Inkfish] + tick_def = sc_def; + + //Natural resistance + if (!(flag&8)) { + rate -= rate*sc_def/100; + + //Item resistance (only applies to rate%) + if(sd && SC_COMMON_MIN <= type && type <= SC_COMMON_MAX) + { + if( sd->reseff[type-SC_COMMON_MIN] > 0 ) + rate -= rate*sd->reseff[type-SC_COMMON_MIN]/10000; + if( sd->sc.data[SC_COMMONSC_RESIST] ) + rate -= rate*sd->sc.data[SC_COMMONSC_RESIST]->val1/100; + } + } + if (!(rnd()%10000 < rate)) + return 0; + + //Why would a status start with no duration? Presume it has + //duration defined elsewhere. + if (!tick) return 1; + + //Rate reduction + if (flag&2) + return tick; + + tick -= tick*tick_def/100; + // Changed to 5 seconds according to recent tests [Playtester] + if (type == SC_ANKLE && tick < 5000) + tick = 5000; + return tick<=0?0:tick; } /*========================================== @@ -6382,578 +6294,583 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti * &4: sc_data loaded, no value has to be altered. * &8: rate should not be reduced *------------------------------------------*/ -int status_change_start(struct block_list *bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag) +int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag) { - struct map_session_data *sd = NULL; - struct status_change *sc; - struct status_change_entry *sce; - struct status_data *status; - struct view_data *vd; - int opt_flag, calc_flag, undead_flag, val_flag = 0, tick_time = 0; - bool sc_isnew = true; - - nullpo_ret(bl); - sc = status_get_sc(bl); - status = status_get_status_data(bl); - - if (type <= SC_NONE || type >= SC_MAX) { - ShowError("status_change_start: invalid status change (%d)!\n", type); - return 0; - } - - if (!sc) - return 0; //Unable to receive status changes - - if (status_isdead(bl) && type != SC_NOCHAT) // SC_NOCHAT should work even on dead characters - return 0; - - if (bl->type == BL_MOB) { - struct mob_data *md = BL_CAST(BL_MOB,bl); - if (md && (md->class_ == MOBID_EMPERIUM || mob_is_battleground(md)) && type != SC_SAFETYWALL && type != SC_PNEUMA) - return 0; //Emperium/BG Monsters can't be afflicted by status changes - // if(md && mob_is_gvg(md) && status_sc2scb_flag(type)&SCB_MAXHP) - // return 0; //prevent status addinh hp to gvg mob (like bloodylust=hp*3 etc... - } - - if (sc->data[SC_REFRESH]) { - if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed. - return 0; // Immune to status ailements - switch (type) { - case SC_QUAGMIRE://Tester said it protects against this and decrease agi. - case SC_DECREASEAGI: - case SC_BURNING: - case SC_FREEZING: - //case SC_WHITEIMPRISON://Need confirm. Protected against this in the past. [Rytech] - case SC_MARSHOFABYSS: - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_DEATHHURT: - case SC_PYREXIA: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: //08/31/2011 - Class Balance Changes - case SC_CRYSTALIZE: - case SC_DEEPSLEEP: - case SC_MANDRAGORA: - return 0; - } - } else if (sc->data[SC_INSPIRATION]) { - if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) - return 0; // Immune to status ailements - switch (type) { - case SC_DEEPSLEEP: - case SC_SATURDAYNIGHTFEVER: - case SC_PYREXIA: - case SC_DEATHHURT: - case SC_MAGICMUSHROOM: - case SC_VENOMBLEED: - case SC_TOXIN: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - case SC__ENERVATION: - case SC__GROOMY: - case SC__LAZINESS: - case SC__UNLUCKY: - case SC__WEAKNESS: - case SC__BODYPAINT: - case SC__IGNORANCE: - return 0; - } - } + struct map_session_data *sd = NULL; + struct status_change* sc; + struct status_change_entry* sce; + struct status_data *status; + struct view_data *vd; + int opt_flag, calc_flag, undead_flag, val_flag = 0, tick_time = 0; + bool sc_isnew = true; + + nullpo_ret(bl); + sc = status_get_sc(bl); + status = status_get_status_data(bl); + + if( type <= SC_NONE || type >= SC_MAX ) + { + ShowError("status_change_start: invalid status change (%d)!\n", type); + return 0; + } + + if( !sc ) + return 0; //Unable to receive status changes + + if( status_isdead(bl) && type != SC_NOCHAT ) // SC_NOCHAT should work even on dead characters + return 0; + + if( bl->type == BL_MOB) + { + struct mob_data *md = BL_CAST(BL_MOB,bl); + if(md && (md->class_ == MOBID_EMPERIUM || mob_is_battleground(md)) && type != SC_SAFETYWALL && type != SC_PNEUMA) + return 0; //Emperium/BG Monsters can't be afflicted by status changes + // if(md && mob_is_gvg(md) && status_sc2scb_flag(type)&SCB_MAXHP) + // return 0; //prevent status addinh hp to gvg mob (like bloodylust=hp*3 etc... + } + + if( sc->data[SC_REFRESH] ) { + if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed. + return 0; // Immune to status ailements + switch( type ) { + case SC_QUAGMIRE://Tester said it protects against this and decrease agi. + case SC_DECREASEAGI: + case SC_BURNING: + case SC_FREEZING: + //case SC_WHITEIMPRISON://Need confirm. Protected against this in the past. [Rytech] + case SC_MARSHOFABYSS: + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_DEATHHURT: + case SC_PYREXIA: + case SC_OBLIVIONCURSE: + //case SC_LEECHESEND://Need confirm. If it protects against nearly every Guillotine poison, it should work on this too right? [Rytech] + case SC_CRYSTALIZE: + case SC_DEEPSLEEP: + case SC_MANDRAGORA: + return 0; + } + } + else if( sc->data[SC_INSPIRATION] ) { + if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX ) + return 0; // Immune to status ailements + switch( type ) { + case SC_DEEPSLEEP: + case SC_SATURDAYNIGHTFEVER: + case SC_PYREXIA: + case SC_DEATHHURT: + case SC_MAGICMUSHROOM: + case SC_VENOMBLEED: + case SC_TOXIN: + case SC_OBLIVIONCURSE: + case SC_LEECHESEND: + case SC__ENERVATION: + case SC__GROOMY: + case SC__LAZINESS: + case SC__UNLUCKY: + case SC__WEAKNESS: + case SC__BODYPAINT: + case SC__IGNORANCE: + return 0; + } + } - sd = BL_CAST(BL_PC, bl); + sd = BL_CAST(BL_PC, bl); - //Adjust tick according to status resistances - if (!(flag&(1|4))) { - tick = status_get_sc_def(bl, type, rate, tick, flag); - if (!tick) return 0; - } + //Adjust tick according to status resistances + if( !(flag&(1|4)) ) + { + tick = status_get_sc_def(bl, type, rate, tick, flag); + if( !tick ) return 0; + } - undead_flag = battle_check_undead(status->race,status->def_ele); - //Check for inmunities / sc fails - switch (type) { + undead_flag = battle_check_undead(status->race,status->def_ele); + //Check for inmunities / sc fails + switch (type) { case SC_ANGRIFFS_MODUS: case SC_GOLDENE_FERSE: - if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS]) - || (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE]) - ) + if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS]) + || (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE]) + ) return 0; - case SC_STONE: - if (sc->data[SC_POWER_OF_GAIA]) - return 0; - case SC_FREEZE: - //Undead are immune to Freeze/Stone - if (undead_flag && !(flag&1)) - return 0; - case SC_DEEPSLEEP: - case SC_SLEEP: - case SC_STUN: - case SC_FREEZING: - case SC_CRYSTALIZE: - if (sc->opt1) - return 0; //Cannot override other opt1 status changes. [Skotlex] - if ((type == SC_FREEZE || type == SC_FREEZING || type == SC_CRYSTALIZE) && sc->data[SC_WARMER]) - return 0; //Immune to Frozen and Freezing status if under Warmer status. [Jobbie] - break; + case SC_STONE: + if(sc->data[SC_POWER_OF_GAIA]) + return 0; + case SC_FREEZE: + //Undead are immune to Freeze/Stone + if (undead_flag && !(flag&1)) + return 0; + case SC_DEEPSLEEP: + case SC_SLEEP: + case SC_STUN: + case SC_FREEZING: + case SC_CRYSTALIZE: + if (sc->opt1) + return 0; //Cannot override other opt1 status changes. [Skotlex] + if((type == SC_FREEZE || type == SC_FREEZING || type == SC_CRYSTALIZE) && sc->data[SC_WARMER]) + return 0; //Immune to Frozen and Freezing status if under Warmer status. [Jobbie] + break; //There all like berserk, do not everlap each other - case SC__BLOODYLUST: - if (!sd) return 0; //should only affect player - case SC_BERSERK: - if (((type == SC_BERSERK) && (sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST])) - || ((type == SC__BLOODYLUST) && (sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC_BERSERK])) - ) - return 0; - break; - - case SC_BURNING: - if (sc->opt1 || sc->data[SC_FREEZING]) - return 0; - break; - - case SC_SIGNUMCRUCIS: - //Only affects demons and undead element (but not players) - if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) - return 0; - break; - case SC_AETERNA: - if ((sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) || sc->data[SC_FREEZE]) - return 0; - break; - case SC_KYRIE: - if (bl->type == BL_MOB) - return 0; - break; - case SC_OVERTHRUST: - if (sc->data[SC_MAXOVERTHRUST]) - return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex] - case SC_MAXOVERTHRUST: - if (sc->option&OPTION_MADOGEAR) - return 0;//Overthrust and Overthrust Max cannot be used on Mado Gear [Ind] - break; - case SC_ADRENALINE: - if (sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE))) - return 0; - if (sc->data[SC_QUAGMIRE] || - sc->data[SC_DECREASEAGI] || - sc->option&OPTION_MADOGEAR //Adrenaline doesn't affect Mado Gear [Ind] - ) - return 0; - break; - case SC_ADRENALINE2: - if (sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE2))) - return 0; - if (sc->data[SC_QUAGMIRE] || - sc->data[SC_DECREASEAGI] - ) - return 0; - break; - case SC_MAGNIFICAT: - if (sc->option&OPTION_MADOGEAR) //Mado is immune to magnificat - return 0; - break; - case SC_ONEHAND: - case SC_MERC_QUICKEN: - case SC_TWOHANDQUICKEN: - if (sc->data[SC_DECREASEAGI]) - return 0; - - case SC_INCREASEAGI: - if (sd && pc_issit(sd)) { - pc_setstand(sd); - } - - case SC_CONCENTRATE: - case SC_SPEARQUICKEN: - case SC_TRUESIGHT: - case SC_WINDWALK: - case SC_CARTBOOST: - case SC_ASSNCROS: - if (sc->data[SC_QUAGMIRE]) - return 0; - if (sc->option&OPTION_MADOGEAR) - return 0;//Mado is immune to increase agi, wind walk, cart boost, etc (others above) [Ind] - break; - case SC_CLOAKING: - //Avoid cloaking with no wall and low skill level. [Skotlex] - //Due to the cloaking card, we have to check the wall versus to known - //skill level rather than the used one. [Skotlex] - //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL)) - if (sd && pc_checkskill(sd, AS_CLOAKING) < 3 && !skill_check_cloaking(bl,NULL)) - return 0; - break; - case SC_MODECHANGE: { - int mode; - struct status_data *bstatus = status_get_base_status(bl); - if (!bstatus) return 0; - if (sc->data[type]) { - //Pile up with previous values. - if (!val2) val2 = sc->data[type]->val2; - val3 |= sc->data[type]->val3; - val4 |= sc->data[type]->val4; - } - mode = val2?val2:bstatus->mode; //Base mode - if (val4) mode&=~val4; //Del mode - if (val3) mode|= val3; //Add mode - if (mode == bstatus->mode) { //No change. - if (sc->data[type]) //Abort previous status - return status_change_end(bl, type, INVALID_TIMER); - return 0; - } - } - break; - //Strip skills, need to divest something or it fails. - case SC_STRIPWEAPON: - if (sd && !(flag&4)) { //apply sc anyway if loading saved sc_data - int i; - opt_flag = 0; //Reuse to check success condition. - if (sd->bonus.unstripable_equip&EQP_WEAPON) - return 0; - i = sd->equip_index[EQI_HAND_L]; - if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) { - opt_flag|=1; - pc_unequipitem(sd,i,3); //L-hand weapon - } + case SC__BLOODYLUST: + if(!sd) return 0; //should only affect player + case SC_BERSERK: + if (((type == SC_BERSERK) && (sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST])) + || ((type == SC__BLOODYLUST) && (sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC_BERSERK])) + ) + return 0; + break; + + case SC_BURNING: + if(sc->opt1 || sc->data[SC_FREEZING]) + return 0; + break; + + case SC_SIGNUMCRUCIS: + //Only affects demons and undead element (but not players) + if((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) + return 0; + break; + case SC_AETERNA: + if( (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) || sc->data[SC_FREEZE] ) + return 0; + break; + case SC_KYRIE: + if (bl->type == BL_MOB) + return 0; + break; + case SC_OVERTHRUST: + if (sc->data[SC_MAXOVERTHRUST]) + return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex] + case SC_MAXOVERTHRUST: + if( sc->option&OPTION_MADOGEAR ) + return 0;//Overthrust and Overthrust Max cannot be used on Mado Gear [Ind] + break; + case SC_ADRENALINE: + if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE))) + return 0; + if (sc->data[SC_QUAGMIRE] || + sc->data[SC_DECREASEAGI] || + sc->option&OPTION_MADOGEAR //Adrenaline doesn't affect Mado Gear [Ind] + ) + return 0; + break; + case SC_ADRENALINE2: + if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE2))) + return 0; + if (sc->data[SC_QUAGMIRE] || + sc->data[SC_DECREASEAGI] + ) + return 0; + break; + case SC_MAGNIFICAT: + if( sc->option&OPTION_MADOGEAR ) //Mado is immune to magnificat + return 0; + break; + case SC_ONEHAND: + case SC_MERC_QUICKEN: + case SC_TWOHANDQUICKEN: + if(sc->data[SC_DECREASEAGI]) + return 0; + + case SC_INCREASEAGI: + if(sd && pc_issit(sd)){ + pc_setstand(sd); + } + + case SC_CONCENTRATE: + case SC_SPEARQUICKEN: + case SC_TRUESIGHT: + case SC_WINDWALK: + case SC_CARTBOOST: + case SC_ASSNCROS: + if (sc->data[SC_QUAGMIRE]) + return 0; + if(sc->option&OPTION_MADOGEAR) + return 0;//Mado is immune to increase agi, wind walk, cart boost, etc (others above) [Ind] + break; + case SC_CLOAKING: + //Avoid cloaking with no wall and low skill level. [Skotlex] + //Due to the cloaking card, we have to check the wall versus to known + //skill level rather than the used one. [Skotlex] + //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL)) + if( sd && pc_checkskill(sd, AS_CLOAKING) < 3 && !skill_check_cloaking(bl,NULL) ) + return 0; + break; + case SC_MODECHANGE: + { + int mode; + struct status_data *bstatus = status_get_base_status(bl); + if (!bstatus) return 0; + if (sc->data[type]) + { //Pile up with previous values. + if(!val2) val2 = sc->data[type]->val2; + val3 |= sc->data[type]->val3; + val4 |= sc->data[type]->val4; + } + mode = val2?val2:bstatus->mode; //Base mode + if (val4) mode&=~val4; //Del mode + if (val3) mode|= val3; //Add mode + if (mode == bstatus->mode) { //No change. + if (sc->data[type]) //Abort previous status + return status_change_end(bl, type, INVALID_TIMER); + return 0; + } + } + break; + //Strip skills, need to divest something or it fails. + case SC_STRIPWEAPON: + if (sd && !(flag&4)) { //apply sc anyway if loading saved sc_data + int i; + opt_flag = 0; //Reuse to check success condition. + if(sd->bonus.unstripable_equip&EQP_WEAPON) + return 0; + i = sd->equip_index[EQI_HAND_L]; + if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) { + opt_flag|=1; + pc_unequipitem(sd,i,3); //L-hand weapon + } - i = sd->equip_index[EQI_HAND_R]; - if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) { - opt_flag|=2; - pc_unequipitem(sd,i,3); - } - if (!opt_flag) return 0; - } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC - break; - case SC_STRIPSHIELD: - if (val2 == 1) val2 = 0; //GX effect. Do not take shield off.. - else if (sd && !(flag&4)) { - int i; - if (sd->bonus.unstripable_equip&EQP_SHIELD) - return 0; - i = sd->equip_index[EQI_HAND_L]; - if (i < 0 || !sd->inventory_data[i] || sd->inventory_data[i]->type != IT_ARMOR) - return 0; - pc_unequipitem(sd,i,3); - } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC - break; - case SC_STRIPARMOR: - if (sd && !(flag&4)) { - int i; - if (sd->bonus.unstripable_equip&EQP_ARMOR) - return 0; - i = sd->equip_index[EQI_ARMOR]; - if (i < 0 || !sd->inventory_data[i]) - return 0; - pc_unequipitem(sd,i,3); - } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC - break; - case SC_STRIPHELM: - if (sd && !(flag&4)) { - int i; - if (sd->bonus.unstripable_equip&EQP_HELM) - return 0; - i = sd->equip_index[EQI_HEAD_TOP]; - if (i < 0 || !sd->inventory_data[i]) - return 0; - pc_unequipitem(sd,i,3); - } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC - break; - case SC_MERC_FLEEUP: - case SC_MERC_ATKUP: - case SC_MERC_HPUP: - case SC_MERC_SPUP: - case SC_MERC_HITUP: - if (bl->type != BL_MER) - return 0; // Stats only for Mercenaries - break; - case SC_STRFOOD: - if (sc->data[SC_FOOD_STR_CASH] && sc->data[SC_FOOD_STR_CASH]->val1 > val1) - return 0; - break; - case SC_AGIFOOD: - if (sc->data[SC_FOOD_AGI_CASH] && sc->data[SC_FOOD_AGI_CASH]->val1 > val1) - return 0; - break; - case SC_VITFOOD: - if (sc->data[SC_FOOD_VIT_CASH] && sc->data[SC_FOOD_VIT_CASH]->val1 > val1) - return 0; - break; - case SC_INTFOOD: - if (sc->data[SC_FOOD_INT_CASH] && sc->data[SC_FOOD_INT_CASH]->val1 > val1) - return 0; - break; - case SC_DEXFOOD: - if (sc->data[SC_FOOD_DEX_CASH] && sc->data[SC_FOOD_DEX_CASH]->val1 > val1) - return 0; - break; - case SC_LUKFOOD: - if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1) - return 0; - break; - case SC_FOOD_STR_CASH: - if (sc->data[SC_STRFOOD] && sc->data[SC_STRFOOD]->val1 > val1) - return 0; - break; - case SC_FOOD_AGI_CASH: - if (sc->data[SC_AGIFOOD] && sc->data[SC_AGIFOOD]->val1 > val1) - return 0; - break; - case SC_FOOD_VIT_CASH: - if (sc->data[SC_VITFOOD] && sc->data[SC_VITFOOD]->val1 > val1) - return 0; - break; - case SC_FOOD_INT_CASH: - if (sc->data[SC_INTFOOD] && sc->data[SC_INTFOOD]->val1 > val1) - return 0; - break; - case SC_FOOD_DEX_CASH: - if (sc->data[SC_DEXFOOD] && sc->data[SC_DEXFOOD]->val1 > val1) - return 0; - break; - case SC_FOOD_LUK_CASH: - if (sc->data[SC_LUKFOOD] && sc->data[SC_LUKFOOD]->val1 > val1) - return 0; - break; - case SC_CAMOUFLAGE: - if (sd && pc_checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill_check_camouflage(bl,NULL)) - return 0; - break; - case SC__STRIPACCESSORY: - if (sd) { - int i = -1; - if (!(sd->bonus.unstripable_equip&EQI_ACC_L)) { - i = sd->equip_index[EQI_ACC_L]; - if (i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR) - pc_unequipitem(sd,i,3); //L-Accessory - } - if (!(sd->bonus.unstripable_equip&EQI_ACC_R)) { - i = sd->equip_index[EQI_ACC_R]; - if (i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR) - pc_unequipitem(sd,i,3); //R-Accessory - } - if (i < 0) - return 0; - } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC - break; - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_DEATHHURT: - case SC_PYREXIA: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: { - // it doesn't stack or even renewed - int i = SC_TOXIN; - for (; i<= SC_LEECHESEND; i++) - if (sc->data[i]) return 0; - } - break; - case SC_SATURDAYNIGHTFEVER: - if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION] || sc->data[SC__BLOODYLUST]) - return 0; - break; - } + i = sd->equip_index[EQI_HAND_R]; + if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) { + opt_flag|=2; + pc_unequipitem(sd,i,3); + } + if (!opt_flag) return 0; + } + if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + break; + case SC_STRIPSHIELD: + if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off.. + else + if (sd && !(flag&4)) { + int i; + if(sd->bonus.unstripable_equip&EQP_SHIELD) + return 0; + i = sd->equip_index[EQI_HAND_L]; + if ( i < 0 || !sd->inventory_data[i] || sd->inventory_data[i]->type != IT_ARMOR ) + return 0; + pc_unequipitem(sd,i,3); + } + if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + break; + case SC_STRIPARMOR: + if (sd && !(flag&4)) { + int i; + if(sd->bonus.unstripable_equip&EQP_ARMOR) + return 0; + i = sd->equip_index[EQI_ARMOR]; + if ( i < 0 || !sd->inventory_data[i] ) + return 0; + pc_unequipitem(sd,i,3); + } + if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + break; + case SC_STRIPHELM: + if (sd && !(flag&4)) { + int i; + if(sd->bonus.unstripable_equip&EQP_HELM) + return 0; + i = sd->equip_index[EQI_HEAD_TOP]; + if ( i < 0 || !sd->inventory_data[i] ) + return 0; + pc_unequipitem(sd,i,3); + } + if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + break; + case SC_MERC_FLEEUP: + case SC_MERC_ATKUP: + case SC_MERC_HPUP: + case SC_MERC_SPUP: + case SC_MERC_HITUP: + if( bl->type != BL_MER ) + return 0; // Stats only for Mercenaries + break; + case SC_STRFOOD: + if (sc->data[SC_FOOD_STR_CASH] && sc->data[SC_FOOD_STR_CASH]->val1 > val1) + return 0; + break; + case SC_AGIFOOD: + if (sc->data[SC_FOOD_AGI_CASH] && sc->data[SC_FOOD_AGI_CASH]->val1 > val1) + return 0; + break; + case SC_VITFOOD: + if (sc->data[SC_FOOD_VIT_CASH] && sc->data[SC_FOOD_VIT_CASH]->val1 > val1) + return 0; + break; + case SC_INTFOOD: + if (sc->data[SC_FOOD_INT_CASH] && sc->data[SC_FOOD_INT_CASH]->val1 > val1) + return 0; + break; + case SC_DEXFOOD: + if (sc->data[SC_FOOD_DEX_CASH] && sc->data[SC_FOOD_DEX_CASH]->val1 > val1) + return 0; + break; + case SC_LUKFOOD: + if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1) + return 0; + break; + case SC_FOOD_STR_CASH: + if (sc->data[SC_STRFOOD] && sc->data[SC_STRFOOD]->val1 > val1) + return 0; + break; + case SC_FOOD_AGI_CASH: + if (sc->data[SC_AGIFOOD] && sc->data[SC_AGIFOOD]->val1 > val1) + return 0; + break; + case SC_FOOD_VIT_CASH: + if (sc->data[SC_VITFOOD] && sc->data[SC_VITFOOD]->val1 > val1) + return 0; + break; + case SC_FOOD_INT_CASH: + if (sc->data[SC_INTFOOD] && sc->data[SC_INTFOOD]->val1 > val1) + return 0; + break; + case SC_FOOD_DEX_CASH: + if (sc->data[SC_DEXFOOD] && sc->data[SC_DEXFOOD]->val1 > val1) + return 0; + break; + case SC_FOOD_LUK_CASH: + if (sc->data[SC_LUKFOOD] && sc->data[SC_LUKFOOD]->val1 > val1) + return 0; + break; + case SC_CAMOUFLAGE: + if( sd && pc_checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill_check_camouflage(bl,NULL) ) + return 0; + break; + case SC__STRIPACCESSORY: + if( sd ) { + int i = -1; + if( !(sd->bonus.unstripable_equip&EQI_ACC_L) ) { + i = sd->equip_index[EQI_ACC_L]; + if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR ) + pc_unequipitem(sd,i,3); //L-Accessory + } if( !(sd->bonus.unstripable_equip&EQI_ACC_R) ) { + i = sd->equip_index[EQI_ACC_R]; + if( i >= 0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_ARMOR ) + pc_unequipitem(sd,i,3); //R-Accessory + } + if( i < 0 ) + return 0; + } + if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + break; + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_DEATHHURT: + case SC_PYREXIA: + case SC_OBLIVIONCURSE: + case SC_LEECHESEND: + { // it doesn't stack or even renewed + int i = SC_TOXIN; + for(; i<= SC_LEECHESEND; i++) + if(sc->data[i]) return 0; + } + break; + case SC_SATURDAYNIGHTFEVER: + if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION] || sc->data[SC__BLOODYLUST]) + return 0; + break; + } + + //Check for BOSS resistances + if(status->mode&MD_BOSS && !(flag&1)) { + if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX) + return 0; + switch (type) { + case SC_BLESSING: + case SC_DECREASEAGI: + case SC_PROVOKE: + case SC_COMA: + case SC_GRAVITATION: + case SC_SUITON: + case SC_RICHMANKIM: + case SC_ROKISWEIL: + case SC_FOGWALL: + case SC_FREEZING: + case SC_BURNING: // Place here until we have info about its behavior on Boss-monsters. [pakpil] + case SC_MARSHOFABYSS: + case SC_ADORAMUS: + case SC_PARALYSIS: - //Check for BOSS resistances - if (status->mode&MD_BOSS && !(flag&1)) { - if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX) - return 0; - switch (type) { - case SC_BLESSING: - case SC_DECREASEAGI: - case SC_PROVOKE: - case SC_COMA: - case SC_GRAVITATION: - case SC_SUITON: - case SC_RICHMANKIM: - case SC_ROKISWEIL: - case SC_FOGWALL: - case SC_FREEZING: - case SC_BURNING: // Place here until we have info about its behavior on Boss-monsters. [pakpil] - case SC_MARSHOFABYSS: - case SC_ADORAMUS: - case SC_PARALYSIS: - - // Exploit prevention - kRO Fix - case SC_PYREXIA: - case SC_DEATHHURT: - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - - // Ranger Effects - case SC_BITE: - case SC_ELECTRICSHOCKER: - case SC_MAGNETICFIELD: + // Exploit prevention - kRO Fix + case SC_PYREXIA: + case SC_DEATHHURT: + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_OBLIVIONCURSE: + case SC_LEECHESEND: - return 0; - } - } + // Ranger Effects + case SC_BITE: + case SC_ELECTRICSHOCKER: + case SC_MAGNETICFIELD: - //Before overlapping fail, one must check for status cured. - switch (type) { - case SC_BLESSING: - //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM - //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm] - if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) { - status_change_end(bl, SC_CURSE, INVALID_TIMER); - if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) - status_change_end(bl, SC_STONE, INVALID_TIMER); - } - break; - case SC_INCREASEAGI: - status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER); - break; - case SC_QUAGMIRE: - status_change_end(bl, SC_CONCENTRATE, INVALID_TIMER); - status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER); - status_change_end(bl, SC_WINDWALK, INVALID_TIMER); - //Also blocks the ones below... - case SC_DECREASEAGI: - status_change_end(bl, SC_CARTBOOST, INVALID_TIMER); - //Also blocks the ones below... - case SC_DONTFORGETME: - status_change_end(bl, SC_INCREASEAGI, INVALID_TIMER); - status_change_end(bl, SC_ADRENALINE, INVALID_TIMER); - status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); - status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_ONEHAND, INVALID_TIMER); - status_change_end(bl, SC_MERC_QUICKEN, INVALID_TIMER); - status_change_end(bl, SC_ACCELERATION, INVALID_TIMER); - break; - case SC_ONEHAND: - //Removes the Aspd potion effect, as reported by Vicious. [Skotlex] - status_change_end(bl, SC_ASPDPOTION0, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION1, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION3, INVALID_TIMER); - break; - case SC_MAXOVERTHRUST: - //Cancels Normal Overthrust. [Skotlex] - status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER); - break; - case SC_KYRIE: - //Cancels Assumptio - status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); - break; - case SC_DELUGE: - if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND]) - status_change_end(bl, SC_BLIND, INVALID_TIMER); - break; - case SC_SILENCE: - if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) - status_change_end(bl, SC_GOSPEL, INVALID_TIMER); - break; - case SC_HIDING: - status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); - status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); - break; - case SC__BLOODYLUST: - case SC_BERSERK: - if (battle_config.berserk_cancels_buffs) { - status_change_end(bl, SC_ONEHAND, INVALID_TIMER); - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); - status_change_end(bl, SC_PARRYING, INVALID_TIMER); - status_change_end(bl, SC_AURABLADE, INVALID_TIMER); - status_change_end(bl, SC_MERC_QUICKEN, INVALID_TIMER); - } + return 0; + } + } + + //Before overlapping fail, one must check for status cured. + switch (type) { + case SC_BLESSING: + //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM + //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm] + if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) { + status_change_end(bl, SC_CURSE, INVALID_TIMER); + if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) + status_change_end(bl, SC_STONE, INVALID_TIMER); + } + break; + case SC_INCREASEAGI: + status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER); + break; + case SC_QUAGMIRE: + status_change_end(bl, SC_CONCENTRATE, INVALID_TIMER); + status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER); + status_change_end(bl, SC_WINDWALK, INVALID_TIMER); + //Also blocks the ones below... + case SC_DECREASEAGI: + status_change_end(bl, SC_CARTBOOST, INVALID_TIMER); + //Also blocks the ones below... + case SC_DONTFORGETME: + status_change_end(bl, SC_INCREASEAGI, INVALID_TIMER); + status_change_end(bl, SC_ADRENALINE, INVALID_TIMER); + status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); + status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_ONEHAND, INVALID_TIMER); + status_change_end(bl, SC_MERC_QUICKEN, INVALID_TIMER); + status_change_end(bl, SC_ACCELERATION, INVALID_TIMER); + break; + case SC_ONEHAND: + //Removes the Aspd potion effect, as reported by Vicious. [Skotlex] + status_change_end(bl, SC_ASPDPOTION0, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION1, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION3, INVALID_TIMER); + break; + case SC_MAXOVERTHRUST: + //Cancels Normal Overthrust. [Skotlex] + status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER); + break; + case SC_KYRIE: + //Cancels Assumptio + status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); + break; + case SC_DELUGE: + if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND]) + status_change_end(bl, SC_BLIND, INVALID_TIMER); + break; + case SC_SILENCE: + if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) + status_change_end(bl, SC_GOSPEL, INVALID_TIMER); + break; + case SC_HIDING: + status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); + status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); + break; + case SC__BLOODYLUST: + case SC_BERSERK: + if(battle_config.berserk_cancels_buffs) { + status_change_end(bl, SC_ONEHAND, INVALID_TIMER); + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); + status_change_end(bl, SC_PARRYING, INVALID_TIMER); + status_change_end(bl, SC_AURABLADE, INVALID_TIMER); + status_change_end(bl, SC_MERC_QUICKEN, INVALID_TIMER); + } #ifdef RENEWAL - else { - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - } + else { + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + } #endif - break; - case SC_ASSUMPTIO: - status_change_end(bl, SC_KYRIE, INVALID_TIMER); - status_change_end(bl, SC_KAITE, INVALID_TIMER); - break; - case SC_KAITE: - status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); - break; - case SC_CARTBOOST: - if (sc->data[SC_DECREASEAGI]) { - //Cancel Decrease Agi, but take no further effect [Skotlex] - status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER); - return 0; - } - break; - case SC_FUSION: - status_change_end(bl, SC_SPIRIT, INVALID_TIMER); - break; - case SC_ADJUSTMENT: - status_change_end(bl, SC_MADNESSCANCEL, INVALID_TIMER); - break; - case SC_MADNESSCANCEL: - status_change_end(bl, SC_ADJUSTMENT, INVALID_TIMER); - break; - //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up - case SC_CHANGEUNDEAD: - status_change_end(bl, SC_BLESSING, INVALID_TIMER); - status_change_end(bl, SC_INCREASEAGI, INVALID_TIMER); - break; - case SC_STRFOOD: - status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER); - break; - case SC_AGIFOOD: - status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER); - break; - case SC_VITFOOD: - status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER); - break; - case SC_INTFOOD: - status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER); - break; - case SC_DEXFOOD: - status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER); - break; - case SC_LUKFOOD: - status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER); - break; - case SC_FOOD_STR_CASH: - status_change_end(bl, SC_STRFOOD, INVALID_TIMER); - break; - case SC_FOOD_AGI_CASH: - status_change_end(bl, SC_AGIFOOD, INVALID_TIMER); - break; - case SC_FOOD_VIT_CASH: - status_change_end(bl, SC_VITFOOD, INVALID_TIMER); - break; - case SC_FOOD_INT_CASH: - status_change_end(bl, SC_INTFOOD, INVALID_TIMER); - break; - case SC_FOOD_DEX_CASH: - status_change_end(bl, SC_DEXFOOD, INVALID_TIMER); - break; - case SC_FOOD_LUK_CASH: - status_change_end(bl, SC_LUKFOOD, INVALID_TIMER); - break; - case SC_FIGHTINGSPIRIT: - status_change_end(bl, type, INVALID_TIMER); // Remove previous one. - break; - case SC_MARSHOFABYSS: - status_change_end(bl, SC_INCAGI, INVALID_TIMER); - status_change_end(bl, SC_WINDWALK, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION0, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION1, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION3, INVALID_TIMER); - break; - case SC_SWINGDANCE: - case SC_SYMPHONYOFLOVER: - case SC_MOONLITSERENADE: - case SC_RUSHWINDMILL: - case SC_ECHOSONG: + break; + case SC_ASSUMPTIO: + status_change_end(bl, SC_KYRIE, INVALID_TIMER); + status_change_end(bl, SC_KAITE, INVALID_TIMER); + break; + case SC_KAITE: + status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); + break; + case SC_CARTBOOST: + if(sc->data[SC_DECREASEAGI]) + { //Cancel Decrease Agi, but take no further effect [Skotlex] + status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER); + return 0; + } + break; + case SC_FUSION: + status_change_end(bl, SC_SPIRIT, INVALID_TIMER); + break; + case SC_ADJUSTMENT: + status_change_end(bl, SC_MADNESSCANCEL, INVALID_TIMER); + break; + case SC_MADNESSCANCEL: + status_change_end(bl, SC_ADJUSTMENT, INVALID_TIMER); + break; + //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up + case SC_CHANGEUNDEAD: + status_change_end(bl, SC_BLESSING, INVALID_TIMER); + status_change_end(bl, SC_INCREASEAGI, INVALID_TIMER); + break; + case SC_STRFOOD: + status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER); + break; + case SC_AGIFOOD: + status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER); + break; + case SC_VITFOOD: + status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER); + break; + case SC_INTFOOD: + status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER); + break; + case SC_DEXFOOD: + status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER); + break; + case SC_LUKFOOD: + status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER); + break; + case SC_FOOD_STR_CASH: + status_change_end(bl, SC_STRFOOD, INVALID_TIMER); + break; + case SC_FOOD_AGI_CASH: + status_change_end(bl, SC_AGIFOOD, INVALID_TIMER); + break; + case SC_FOOD_VIT_CASH: + status_change_end(bl, SC_VITFOOD, INVALID_TIMER); + break; + case SC_FOOD_INT_CASH: + status_change_end(bl, SC_INTFOOD, INVALID_TIMER); + break; + case SC_FOOD_DEX_CASH: + status_change_end(bl, SC_DEXFOOD, INVALID_TIMER); + break; + case SC_FOOD_LUK_CASH: + status_change_end(bl, SC_LUKFOOD, INVALID_TIMER); + break; + case SC_FIGHTINGSPIRIT: + status_change_end(bl, type, INVALID_TIMER); // Remove previous one. + break; + case SC_MARSHOFABYSS: + status_change_end(bl, SC_INCAGI, INVALID_TIMER); + status_change_end(bl, SC_WINDWALK, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION0, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION1, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION3, INVALID_TIMER); + break; + case SC_SWINGDANCE: + case SC_SYMPHONYOFLOVER: + case SC_MOONLITSERENADE: + case SC_RUSHWINDMILL: + case SC_ECHOSONG: case SC_HARMONIZE: //group A doesn't overlap if (type != SC_SWINGDANCE) status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); if (type != SC_SYMPHONYOFLOVER) status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); @@ -6991,1952 +6908,1930 @@ int status_change_start(struct block_list *bl,enum sc_type type,int rate,int val } } break; - case SC_REFLECTSHIELD: - status_change_end(bl, SC_REFLECTDAMAGE, INVALID_TIMER); - break; - case SC_REFLECTDAMAGE: - status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); - break; - case SC_SHIELDSPELL_DEF: - case SC_SHIELDSPELL_MDEF: - case SC_SHIELDSPELL_REF: - status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); - if (type != SC_SHIELDSPELL_DEF) - status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER); - if (type != SC_SHIELDSPELL_MDEF) - status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER); - if (type != SC_SHIELDSPELL_REF) - status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER); - break; - case SC_GT_ENERGYGAIN: - case SC_GT_CHANGE: - case SC_GT_REVITALIZE: - if (type != SC_GT_REVITALIZE) - status_change_end(bl, SC_GT_REVITALIZE, INVALID_TIMER); - if (type != SC_GT_ENERGYGAIN) - status_change_end(bl, SC_GT_ENERGYGAIN, INVALID_TIMER); - if (type != SC_GT_CHANGE) - status_change_end(bl, SC_GT_CHANGE, INVALID_TIMER); - break; - case SC_INVINCIBLE: - status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER); - break; - case SC_INVINCIBLEOFF: - status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER); - break; - case SC_MAGICPOWER: - status_change_end(bl, type, INVALID_TIMER); - break; - } - - //Check for overlapping fails - if ((sce = sc->data[type])) { - switch (type) { - case SC_MERC_FLEEUP: - case SC_MERC_ATKUP: - case SC_MERC_HPUP: - case SC_MERC_SPUP: - case SC_MERC_HITUP: - if (sce->val1 > val1) - val1 = sce->val1; - break; - case SC_ADRENALINE: - case SC_ADRENALINE2: - case SC_WEAPONPERFECTION: - case SC_OVERTHRUST: - if (sce->val2 > val2) - return 0; - break; - case SC_S_LIFEPOTION: - case SC_L_LIFEPOTION: - case SC_BOSSMAPINFO: - case SC_STUN: - case SC_SLEEP: - case SC_POISON: - case SC_CURSE: - case SC_SILENCE: - case SC_CONFUSION: - case SC_BLIND: - case SC_BLEEDING: - case SC_DPOISON: - case SC_CLOSECONFINE2: //Can't be re-closed in. - case SC_MARIONETTE: - case SC_MARIONETTE2: - case SC_NOCHAT: - case SC_CHANGE: //Otherwise your Hp/Sp would get refilled while still within effect of the last invocation. - case SC__INVISIBILITY: - case SC__ENERVATION: - case SC__GROOMY: - case SC__IGNORANCE: - case SC__LAZINESS: - case SC__WEAKNESS: - case SC__UNLUCKY: - return 0; - case SC_COMBO: - case SC_DANCING: - case SC_DEVOTION: - case SC_ASPDPOTION0: - case SC_ASPDPOTION1: - case SC_ASPDPOTION2: - case SC_ASPDPOTION3: - case SC_ATKPOTION: - case SC_MATKPOTION: - case SC_ENCHANTARMS: - case SC_ARMOR_ELEMENT: - case SC_ARMOR_RESIST: - break; - case SC_GOSPEL: - //Must not override a casting gospel char. - if (sce->val4 == BCT_SELF) - return 0; - if (sce->val1 > val1) - return 1; - break; - case SC_ENDURE: - if (sce->val4 && !val4) - return 1; //Don't let you override infinite endure. - if (sce->val1 > val1) - return 1; - break; - case SC_KAAHI: - //Kaahi overwrites previous level regardless of existing level. - //Delete timer if it exists. - if (sce->val4 != INVALID_TIMER) { - delete_timer(sce->val4,kaahi_heal_timer); - sce->val4 = INVALID_TIMER; - } - break; - case SC_JAILED: - //When a player is already jailed, do not edit the jail data. - val2 = sce->val2; - val3 = sce->val3; - val4 = sce->val4; - break; - case SC_LERADSDEW: - if (sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])) - return 0; - case SC_SHAPESHIFT: - case SC_PROPERTYWALK: - break; - case SC_LEADERSHIP: - case SC_GLORYWOUNDS: - case SC_SOULCOLD: - case SC_HAWKEYES: - if (sce->val4 && !val4) //you cannot override master guild aura - return 0; - break; - case SC_JOINTBEAT: - val2 |= sce->val2; // stackable ailments - default: - if (sce->val1 > val1) - return 1; //Return true to not mess up skill animations. [Skotlex] - } - } - - vd = status_get_viewdata(bl); - calc_flag = StatusChangeFlagTable[type]; - if (!(flag&4)) //&4 - Do not parse val settings when loading SCs - switch (type) { - case SC_DECREASEAGI: - case SC_INCREASEAGI: - val2 = 2 + val1; //Agi change - break; - case SC_ENDURE: - val2 = 7; // Hit-count [Celest] - if (!(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && !val4) { - struct map_session_data *tsd; - if (sd) { - int i; - for (i = 0; i < 5; i++) { - if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i]))) - status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); - } - } else if (bl->type == BL_MER && ((TBL_MER *)bl)->devotion_flag && (tsd = ((TBL_MER *)bl)->master)) - status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); - } - //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) - if (val4) - tick = -1; - break; - case SC_AUTOBERSERK: - if (status->hp < status->max_hp>>2 && - (!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0)) - sc_start4(bl,SC_PROVOKE,100,10,1,0,0,60000); - tick = -1; - break; - case SC_SIGNUMCRUCIS: - val2 = 10 + 4*val1; //Def reduction - tick = -1; - clif_emotion(bl,E_SWT); - break; - case SC_MAXIMIZEPOWER: - tick_time = val2 = tick>0?tick:60000; - tick = -1; // duration sent to the client should be infinite - break; - case SC_EDP: // [Celest] - val2 = val1 + 2; //Chance to Poison enemies. + case SC_REFLECTSHIELD: + status_change_end(bl, SC_REFLECTDAMAGE, INVALID_TIMER); + break; + case SC_REFLECTDAMAGE: + status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); + break; + case SC_SHIELDSPELL_DEF: + case SC_SHIELDSPELL_MDEF: + case SC_SHIELDSPELL_REF: + status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); + if( type != SC_SHIELDSPELL_DEF ) + status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER); + if( type != SC_SHIELDSPELL_MDEF ) + status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER); + if( type != SC_SHIELDSPELL_REF ) + status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER); + break; + case SC_GT_ENERGYGAIN: + case SC_GT_CHANGE: + case SC_GT_REVITALIZE: + if( type != SC_GT_REVITALIZE ) + status_change_end(bl, SC_GT_REVITALIZE, INVALID_TIMER); + if( type != SC_GT_ENERGYGAIN ) + status_change_end(bl, SC_GT_ENERGYGAIN, INVALID_TIMER); + if( type != SC_GT_CHANGE ) + status_change_end(bl, SC_GT_CHANGE, INVALID_TIMER); + break; + case SC_INVINCIBLE: + status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER); + break; + case SC_INVINCIBLEOFF: + status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER); + break; + } + + //Check for overlapping fails + if( (sce = sc->data[type]) ) { + switch( type ) { + case SC_MERC_FLEEUP: + case SC_MERC_ATKUP: + case SC_MERC_HPUP: + case SC_MERC_SPUP: + case SC_MERC_HITUP: + if( sce->val1 > val1 ) + val1 = sce->val1; + break; + case SC_ADRENALINE: + case SC_ADRENALINE2: + case SC_WEAPONPERFECTION: + case SC_OVERTHRUST: + if (sce->val2 > val2) + return 0; + break; + case SC_S_LIFEPOTION: + case SC_L_LIFEPOTION: + case SC_BOSSMAPINFO: + case SC_STUN: + case SC_SLEEP: + case SC_POISON: + case SC_CURSE: + case SC_SILENCE: + case SC_CONFUSION: + case SC_BLIND: + case SC_BLEEDING: + case SC_DPOISON: + case SC_CLOSECONFINE2: //Can't be re-closed in. + case SC_MARIONETTE: + case SC_MARIONETTE2: + case SC_NOCHAT: + case SC_CHANGE: //Otherwise your Hp/Sp would get refilled while still within effect of the last invocation. + case SC__INVISIBILITY: + case SC__ENERVATION: + case SC__GROOMY: + case SC__IGNORANCE: + case SC__LAZINESS: + case SC__WEAKNESS: + case SC__UNLUCKY: + return 0; + case SC_COMBO: + case SC_DANCING: + case SC_DEVOTION: + case SC_ASPDPOTION0: + case SC_ASPDPOTION1: + case SC_ASPDPOTION2: + case SC_ASPDPOTION3: + case SC_ATKPOTION: + case SC_MATKPOTION: + case SC_ENCHANTARMS: + case SC_ARMOR_ELEMENT: + case SC_ARMOR_RESIST: + break; + case SC_GOSPEL: + //Must not override a casting gospel char. + if(sce->val4 == BCT_SELF) + return 0; + if(sce->val1 > val1) + return 1; + break; + case SC_ENDURE: + if(sce->val4 && !val4) + return 1; //Don't let you override infinite endure. + if(sce->val1 > val1) + return 1; + break; + case SC_KAAHI: + //Kaahi overwrites previous level regardless of existing level. + //Delete timer if it exists. + if (sce->val4 != INVALID_TIMER) { + delete_timer(sce->val4,kaahi_heal_timer); + sce->val4 = INVALID_TIMER; + } + break; + case SC_JAILED: + //When a player is already jailed, do not edit the jail data. + val2 = sce->val2; + val3 = sce->val3; + val4 = sce->val4; + break; + case SC_LERADSDEW: + if (sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])) + return 0; + case SC_SHAPESHIFT: + case SC_PROPERTYWALK: + break; + case SC_LEADERSHIP: + case SC_GLORYWOUNDS: + case SC_SOULCOLD: + case SC_HAWKEYES: + if( sce->val4 && !val4 )//you cannot override master guild aura + return 0; + break; + case SC_JOINTBEAT: + val2 |= sce->val2; // stackable ailments + default: + if(sce->val1 > val1) + return 1; //Return true to not mess up skill animations. [Skotlex] + } + } + + vd = status_get_viewdata(bl); + calc_flag = StatusChangeFlagTable[type]; + if(!(flag&4)) //&4 - Do not parse val settings when loading SCs + switch(type) + { + case SC_DECREASEAGI: + case SC_INCREASEAGI: + val2 = 2 + val1; //Agi change + break; + case SC_ENDURE: + val2 = 7; // Hit-count [Celest] + if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && !val4 ) + { + struct map_session_data *tsd; + if( sd ) + { + int i; + for( i = 0; i < 5; i++ ) + { + if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); + } + } + else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); + } + //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) + if( val4 ) + tick = -1; + break; + case SC_AUTOBERSERK: + if (status->hp < status->max_hp>>2 && + (!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0)) + sc_start4(bl,SC_PROVOKE,100,10,1,0,0,60000); + tick = -1; + break; + case SC_SIGNUMCRUCIS: + val2 = 10 + 4*val1; //Def reduction + tick = -1; + clif_emotion(bl,E_SWT); + break; + case SC_MAXIMIZEPOWER: + tick_time = val2 = tick>0?tick:60000; + tick = -1; // duration sent to the client should be infinite + break; + case SC_EDP: // [Celest] + val2 = val1 + 2; //Chance to Poison enemies. #ifndef RENEWAL_EDP - val3 = 50*(val1+1); //Damage increase (+50 +50*lv%) -#endif - if (sd) //[Ind] - iROwiki says each level increases its duration by 3 seconds - tick += pc_checkskill(sd,GC_RESEARCHNEWPOISON)*3000; - break; - case SC_POISONREACT: - val2=(val1+1)/2 + val1/10; // Number of counters [Skotlex] - val3=50; // + 5*val1; //Chance to counter. [Skotlex] - break; - case SC_MAGICROD: - val2 = val1*20; //SP gained - break; - case SC_KYRIE: - val2 = status->max_hp * (val1 * 2 + 10) / 100; //%Max HP to absorb - val3 = (val1 / 2 + 5); //Hits - break; - case SC_MAGICPOWER: - //val1: Skill lv - val2 = 1; //Lasts 1 invocation - val3 = 5*val1; //Matk% increase - val4 = 0; // 0 = ready to be used, 1 = activated and running - break; - case SC_SACRIFICE: - val2 = 5; //Lasts 5 hits - tick = -1; - break; - case SC_ENCPOISON: - val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate - case SC_ASPERSIO: - case SC_FIREWEAPON: - case SC_WATERWEAPON: - case SC_WINDWEAPON: - case SC_EARTHWEAPON: - case SC_SHADOWWEAPON: - case SC_GHOSTWEAPON: - skill_enchant_elemental_end(bl,type); - break; - case SC_ELEMENTALCHANGE: - // val1 : Element Lvl (if called by skill lvl 1, takes random value between 1 and 4) - // val2 : Element (When no element, random one is picked) - // val3 : 0 = called by skill 1 = called by script (fixed level) - if (!val2) val2 = rnd()%ELE_MAX; - - if (val1 == 1 && val3 == 0) - val1 = 1 + rnd()%4; - else if (val1 > 4) - val1 = 4; // Max Level - val3 = 0; // Not need to keep this info. - break; - case SC_PROVIDENCE: - val2=val1*5; //Race/Ele resist - break; - case SC_REFLECTSHIELD: - val2=10+val1*3; // %Dmg reflected - if (!(flag&1) && (bl->type&(BL_PC|BL_MER))) { - struct map_session_data *tsd; - if (sd) { - int i; - for (i = 0; i < 5; i++) { - if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i]))) - status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); - } - } else if (bl->type == BL_MER && ((TBL_MER *)bl)->devotion_flag && (tsd = ((TBL_MER *)bl)->master)) - status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); - } - break; - case SC_STRIPWEAPON: - if (!sd) //Watk reduction - val2 = 25; - break; - case SC_STRIPSHIELD: - if (!sd) //Def reduction - val2 = 15; - break; - case SC_STRIPARMOR: - if (!sd) //Vit reduction - val2 = 40; - break; - case SC_STRIPHELM: - if (!sd) //Int reduction - val2 = 40; - break; - case SC_AUTOSPELL: - //Val1 Skill LV of Autospell - //Val2 Skill ID to cast - //Val3 Max Lv to cast - val4 = 5 + val1*2; //Chance of casting - break; - case SC_VOLCANO: - val2 = val1*10; //Watk increase -#ifndef RENEWAL - if (status->def_ele != ELE_FIRE) - val2 = 0; + val3 = 50*(val1+1); //Damage increase (+50 +50*lv%) #endif - break; - case SC_VIOLENTGALE: - val2 = val1*3; //Flee increase + if( sd )//[Ind] - iROwiki says each level increases its duration by 3 seconds + tick += pc_checkskill(sd,GC_RESEARCHNEWPOISON)*3000; + break; + case SC_POISONREACT: + val2=(val1+1)/2 + val1/10; // Number of counters [Skotlex] + val3=50; // + 5*val1; //Chance to counter. [Skotlex] + break; + case SC_MAGICROD: + val2 = val1*20; //SP gained + break; + case SC_KYRIE: + val2 = status->max_hp * (val1 * 2 + 10) / 100; //%Max HP to absorb + val3 = (val1 / 2 + 5); //Hits + break; + case SC_MAGICPOWER: + //val1: Skill lv + val2 = 1; //Lasts 1 invocation + val3 = 5*val1; //Matk% increase + val4 = 0; // 0 = ready to be used, 1 = activated and running + break; + case SC_SACRIFICE: + val2 = 5; //Lasts 5 hits + tick = -1; + break; + case SC_ENCPOISON: + val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate + case SC_ASPERSIO: + case SC_FIREWEAPON: + case SC_WATERWEAPON: + case SC_WINDWEAPON: + case SC_EARTHWEAPON: + case SC_SHADOWWEAPON: + case SC_GHOSTWEAPON: + skill_enchant_elemental_end(bl,type); + break; + case SC_ELEMENTALCHANGE: + // val1 : Element Lvl (if called by skill lvl 1, takes random value between 1 and 4) + // val2 : Element (When no element, random one is picked) + // val3 : 0 = called by skill 1 = called by script (fixed level) + if( !val2 ) val2 = rnd()%ELE_MAX; + + if( val1 == 1 && val3 == 0 ) + val1 = 1 + rnd()%4; + else if( val1 > 4 ) + val1 = 4; // Max Level + val3 = 0; // Not need to keep this info. + break; + case SC_PROVIDENCE: + val2=val1*5; //Race/Ele resist + break; + case SC_REFLECTSHIELD: + val2=10+val1*3; // %Dmg reflected + if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) ) + { + struct map_session_data *tsd; + if( sd ) + { + int i; + for( i = 0; i < 5; i++ ) + { + if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + } + } + else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + } + break; + case SC_STRIPWEAPON: + if (!sd) //Watk reduction + val2 = 25; + break; + case SC_STRIPSHIELD: + if (!sd) //Def reduction + val2 = 15; + break; + case SC_STRIPARMOR: + if (!sd) //Vit reduction + val2 = 40; + break; + case SC_STRIPHELM: + if (!sd) //Int reduction + val2 = 40; + break; + case SC_AUTOSPELL: + //Val1 Skill LV of Autospell + //Val2 Skill ID to cast + //Val3 Max Lv to cast + val4 = 5 + val1*2; //Chance of casting + break; + case SC_VOLCANO: + val2 = val1*10; //Watk increase #ifndef RENEWAL - if (status->def_ele != ELE_WIND) - val2 = 0; + if (status->def_ele != ELE_FIRE) + val2 = 0; #endif - break; - case SC_DELUGE: - val2 = deluge_eff[val1-1]; //HP increase + break; + case SC_VIOLENTGALE: + val2 = val1*3; //Flee increase + #ifndef RENEWAL + if (status->def_ele != ELE_WIND) + val2 = 0; + #endif + break; + case SC_DELUGE: + val2 = deluge_eff[val1-1]; //HP increase #ifndef RENEWAL - if (status->def_ele != ELE_WATER) - val2 = 0; + if(status->def_ele != ELE_WATER) + val2 = 0; #endif - break; - case SC_SUITON: - if (!val2 || (sd && (sd->class_&MAPID_UPPERMASK) == MAPID_NINJA)) { - //No penalties. - val2 = 0; //Agi penalty - val3 = 0; //Walk speed penalty - break; - } - val3 = 50; - val2 = 3*((val1+1)/3); - if (val1 > 4) val2--; - break; - case SC_ONEHAND: - case SC_TWOHANDQUICKEN: - val2 = 300; - if (val1 > 10) //For boss casted skills [Skotlex] - val2 += 20*(val1-10); - break; - case SC_MERC_QUICKEN: - val2 = 300; - break; + break; + case SC_SUITON: + if (!val2 || (sd && (sd->class_&MAPID_UPPERMASK) == MAPID_NINJA)) { + //No penalties. + val2 = 0; //Agi penalty + val3 = 0; //Walk speed penalty + break; + } + val3 = 50; + val2 = 3*((val1+1)/3); + if (val1 > 4) val2--; + break; + case SC_ONEHAND: + case SC_TWOHANDQUICKEN: + val2 = 300; + if (val1 > 10) //For boss casted skills [Skotlex] + val2 += 20*(val1-10); + break; + case SC_MERC_QUICKEN: + val2 = 300; + break; #ifndef RENEWAL - case SC_SPEARQUICKEN: - val2 = 200+10*val1; - break; + case SC_SPEARQUICKEN: + val2 = 200+10*val1; + break; #endif - case SC_DANCING: - //val1 : Skill ID + LV - //val2 : Skill Group of the Dance. - //val3 : Brings the skilllv (merged into val1 here) - //val4 : Partner - if (val1 == CG_MOONLIT) - clif_status_change(bl,SI_MOONLIT,1,tick,0, 0, 0); - val1|= (val3<<16); - val3 = tick/1000; //Tick duration - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_LONGING: - val2 = 500-100*val1; //Aspd penalty. - break; - case SC_EXPLOSIONSPIRITS: - val2 = 75 + 25*val1; //Cri bonus - break; - - case SC_ASPDPOTION0: - case SC_ASPDPOTION1: - case SC_ASPDPOTION2: - case SC_ASPDPOTION3: - val2 = 50*(2+type-SC_ASPDPOTION0); - break; - - case SC_WEDDING: - case SC_XMAS: - case SC_SUMMER: - if (!vd) return 0; - //Store previous values as they could be removed. - val1 = vd->class_; - val2 = vd->weapon; - val3 = vd->shield; - val4 = vd->cloth_color; - unit_stop_attack(bl); - clif_changelook(bl,LOOK_WEAPON,0); - clif_changelook(bl,LOOK_SHIELD,0); - clif_changelook(bl,LOOK_BASE,type==SC_WEDDING?JOB_WEDDING:type==SC_XMAS?JOB_XMAS:JOB_SUMMER); - clif_changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); - break; - case SC_NOCHAT: - // [GodLesZ] FIXME: is this correct? a hardcoded interval of 60sec? what about configuration ?_? - tick = 60000; - val1 = battle_config.manner_system; //Mute filters. - if (sd) { - clif_changestatus(sd,SP_MANNER,sd->status.manner); - clif_updatestatus(sd,SP_MANNER); - } - break; - - case SC_STONE: - val3 = tick/1000; //Petrified HP-damage iterations. - if (val3 < 1) val3 = 1; - tick = val4; //Petrifying time. - tick = max(tick, 1000); //Min time - calc_flag = 0; //Actual status changes take effect on petrified state. - break; - - case SC_DPOISON: - //Lose 10/15% of your life as long as it doesn't brings life below 25% - if (status->hp > status->max_hp>>2) { - int diff = status->max_hp*(bl->type==BL_PC?10:15)/100; - if (status->hp - diff < status->max_hp>>2) - diff = status->hp - (status->max_hp>>2); - if (val2 && bl->type == BL_MOB) { - struct block_list *src = map_id2bl(val2); - if (src) - mob_log_damage((TBL_MOB *)bl,src,diff); - } - status_zap(bl, diff, 0); - } - // fall through - case SC_POISON: - val3 = tick/1000; //Damage iterations - if (val3 < 1) val3 = 1; - tick_time = 1000; // [GodLesZ] tick time - //val4: HP damage - if (bl->type == BL_PC) - val4 = (type == SC_DPOISON) ? 3 + status->max_hp/50 : 3 + status->max_hp*3/200; - else - val4 = (type == SC_DPOISON) ? 3 + status->max_hp/100 : 3 + status->max_hp/200; - - break; - case SC_CONFUSION: - clif_emotion(bl,E_WHAT); - break; - case SC_BLEEDING: - val4 = tick/10000; - if (!val4) val4 = 1; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_S_LIFEPOTION: - case SC_L_LIFEPOTION: - if (val1 == 0) return 0; - // val1 = heal percent/amout - // val2 = seconds between heals - // val4 = total of heals - if (val2 < 1) val2 = 1; - if ((val4 = tick/(val2 * 1000)) < 1) - val4 = 1; - tick_time = val2 * 1000; // [GodLesZ] tick time - break; - case SC_BOSSMAPINFO: - if (sd != NULL) { - struct mob_data *boss_md = map_getmob_boss(bl->m); // Search for Boss on this Map - if (boss_md == NULL || boss_md->bl.prev == NULL) { - // No MVP on this map - MVP is dead - clif_bossmapinfo(sd->fd, boss_md, 1); - return 0; // No need to start SC - } - val1 = boss_md->bl.id; - if ((val4 = tick/1000) < 1) - val4 = 1; - tick_time = 1000; // [GodLesZ] tick time - } - break; - case SC_HIDING: - val2 = tick/1000; - tick_time = 1000; // [GodLesZ] tick time - val3 = 0; // unused, previously speed adjustment - val4 = val1+3; //Seconds before SP substraction happen. - break; - case SC_CHASEWALK: - val2 = tick>0?tick:10000; //Interval at which SP is drained. - val3 = 35 - 5 * val1; //Speed adjustment. - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE) - val3 -= 40; - val4 = 10+val1*2; //SP cost. - if (map_flag_gvg(bl->m) || map[bl->m].flag.battleground) val4 *= 5; - break; - case SC_CLOAKING: - if (!sd) //Monsters should be able to walk with no penalties. [Skotlex] - val1 = 10; - tick_time = val2 = tick>0?tick:60000; //SP consumption rate. - tick = -1; // duration sent to the client should be infinite - val3 = 0; // unused, previously walk speed adjustment - //val4&1 signals the presence of a wall. - //val4&2 makes cloak not end on normal attacks [Skotlex] - //val4&4 makes cloak not end on using skills - if (bl->type == BL_PC || (bl->type == BL_MOB && ((TBL_MOB *)bl)->special_state.clone)) //Standard cloaking. - val4 |= battle_config.pc_cloak_check_type&7; - else - val4 |= battle_config.monster_cloak_check_type&7; - break; - case SC_SIGHT: /* splash status */ - case SC_RUWACH: - case SC_SIGHTBLASTER: - val3 = skill_get_splash(val2, val1); //Val2 should bring the skill-id. - val2 = tick/250; - tick_time = 10; // [GodLesZ] tick time - break; - - //Permanent effects. - case SC_AETERNA: - case SC_MODECHANGE: - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_BROKENWEAPON: - case SC_BROKENARMOR: - case SC_READYSTORM: - case SC_READYDOWN: - case SC_READYCOUNTER: - case SC_READYTURN: - case SC_DODGE: - case SC_PUSH_CART: - tick = -1; - break; - - case SC_AUTOGUARD: - if (!(flag&1)) { - struct map_session_data *tsd; - int i,t; - for (i = val2 = 0; i < val1; i++) { - t = 5-(i>>1); - val2 += (t < 0)? 1:t; - } - - if (bl->type&(BL_PC|BL_MER)) { - if (sd) { - for (i = 0; i < 5; i++) { - if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i]))) - status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); - } - } else if (bl->type == BL_MER && ((TBL_MER *)bl)->devotion_flag && (tsd = ((TBL_MER *)bl)->master)) - status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); - } - } - break; - - case SC_DEFENDER: - if (!(flag&1)) { - val2 = 5 + 15*val1; //Damage reduction - val3 = 0; // unused, previously speed adjustment - val4 = 250 - 50*val1; //Aspd adjustment - - if (sd) { - struct map_session_data *tsd; - int i; - for (i = 0; i < 5; i++) { - //See if there are devoted characters, and pass the status to them. [Skotlex] - if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i]))) - status_change_start(&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1); - } - } - } - break; + case SC_DANCING: + //val1 : Skill ID + LV + //val2 : Skill Group of the Dance. + //val3 : Brings the skilllv (merged into val1 here) + //val4 : Partner + if (val1 == CG_MOONLIT) + clif_status_change(bl,SI_MOONLIT,1,tick,0, 0, 0); + val1|= (val3<<16); + val3 = tick/1000; //Tick duration + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_LONGING: + val2 = 500-100*val1; //Aspd penalty. + break; + case SC_EXPLOSIONSPIRITS: + val2 = 75 + 25*val1; //Cri bonus + break; - case SC_TENSIONRELAX: - if (sd) { - pc_setsit(sd); - clif_sitting(&sd->bl); - } - val2 = 12; //SP cost - val4 = 10000; //Decrease at 10secs intervals. - val3 = tick/val4; - tick = -1; // duration sent to the client should be infinite - tick_time = val4; // [GodLesZ] tick time - break; - case SC_PARRYING: - val2 = 20 + val1*3; //Block Chance - break; - - case SC_WINDWALK: - val2 = (val1+1)/2; // Flee bonus is 1/1/2/2/3/3/4/4/5/5 - break; - - case SC_JOINTBEAT: - if (val2&BREAK_NECK) - sc_start(bl,SC_BLEEDING,100,val1,skill_get_time2(status_sc2skill(type),val1)); - break; - - case SC_BERSERK: - if (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) - sc_start4(bl, SC_ENDURE, 100,10,0,0,2, tick); - case SC__BLOODYLUST: - //HP healing is performing after the calc_status call. - //Val2 holds HP penalty - if (!val4) val4 = skill_get_time2(status_sc2skill(type),val1); - if (!val4) val4 = 10000; //Val4 holds damage interval - val3 = tick/val4; //val3 holds skill duration - tick_time = val4; // [GodLesZ] tick time - break; - - case SC_GOSPEL: - if (val4 == BCT_SELF) { // self effect - val2 = tick/10000; - tick_time = 10000; // [GodLesZ] tick time - status_change_clear_buffs(bl,3); //Remove buffs/debuffs - } - break; - - case SC_MARIONETTE: { - int stat; - - val3 = 0; - val4 = 0; - stat = (sd ? sd->status.str : status_get_base_status(bl)->str) / 2; - val3 |= cap_value(stat,0,0xFF)<<16; - stat = (sd ? sd->status.agi : status_get_base_status(bl)->agi) / 2; - val3 |= cap_value(stat,0,0xFF)<<8; - stat = (sd ? sd->status.vit : status_get_base_status(bl)->vit) / 2; - val3 |= cap_value(stat,0,0xFF); - stat = (sd ? sd->status.int_: status_get_base_status(bl)->int_) / 2; - val4 |= cap_value(stat,0,0xFF)<<16; - stat = (sd ? sd->status.dex : status_get_base_status(bl)->dex) / 2; - val4 |= cap_value(stat,0,0xFF)<<8; - stat = (sd ? sd->status.luk : status_get_base_status(bl)->luk) / 2; - val4 |= cap_value(stat,0,0xFF); - break; - } - case SC_MARIONETTE2: { - int stat,max_stat; - // fetch caster information - struct block_list *pbl = map_id2bl(val1); - struct status_change *psc = pbl?status_get_sc(pbl):NULL; - struct status_change_entry *psce = psc?psc->data[SC_MARIONETTE]:NULL; - // fetch target's stats - struct status_data *status = status_get_status_data(bl); // battle status - - if (!psce) - return 0; - - val3 = 0; - val4 = 0; - max_stat = battle_config.max_parameter; //Cap to 99 (default) - stat = (psce->val3 >>16)&0xFF; - stat = min(stat, max_stat - status->str); - val3 |= cap_value(stat,0,0xFF)<<16; - stat = (psce->val3 >> 8)&0xFF; - stat = min(stat, max_stat - status->agi); - val3 |= cap_value(stat,0,0xFF)<<8; - stat = (psce->val3 >> 0)&0xFF; - stat = min(stat, max_stat - status->vit); - val3 |= cap_value(stat,0,0xFF); - stat = (psce->val4 >>16)&0xFF; - stat = min(stat, max_stat - status->int_); - val4 |= cap_value(stat,0,0xFF)<<16; - stat = (psce->val4 >> 8)&0xFF; - stat = min(stat, max_stat - status->dex); - val4 |= cap_value(stat,0,0xFF)<<8; - stat = (psce->val4 >> 0)&0xFF; - stat = min(stat, max_stat - status->luk); - val4 |= cap_value(stat,0,0xFF); - break; - } - case SC_REJECTSWORD: - val2 = 15*val1; //Reflect chance - val3 = 3; //Reflections - tick = -1; - break; - - case SC_MEMORIZE: - val2 = 5; //Memorized casts. - tick = -1; - break; - - case SC_GRAVITATION: - val2 = 50*val1; //aspd reduction - break; - - case SC_REGENERATION: - if (val1 == 1) - val2 = 2; - else - val2 = val1; //HP Regerenation rate: 200% 200% 300% - val3 = val1; //SP Regeneration Rate: 100% 200% 300% - //if val4 comes set, this blocks regen rather than increase it. - break; - - case SC_DEVOTION: { - struct block_list *d_bl; - struct status_change *d_sc; - - if ((d_bl = map_id2bl(val1)) && (d_sc = status_get_sc(d_bl)) && d_sc->count) { - // Inherits Status From Source - const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE }; - enum sc_type type2; - int i = (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)?2:3; - while (i >= 0) { - type2 = types[i]; - if (d_sc->data[type2]) - sc_start(bl, type2, 100, d_sc->data[type2]->val1, skill_get_time(status_sc2skill(type2),d_sc->data[type2]->val1)); - i--; - } - } - break; - } + case SC_ASPDPOTION0: + case SC_ASPDPOTION1: + case SC_ASPDPOTION2: + case SC_ASPDPOTION3: + val2 = 50*(2+type-SC_ASPDPOTION0); + break; - case SC_COMA: //Coma. Sends a char to 1HP. If val2, do not zap sp - if (val3 && bl->type == BL_MOB) { - struct block_list *src = map_id2bl(val3); - if (src) - mob_log_damage((TBL_MOB *)bl,src,status->hp - 1); - } - status_zap(bl, status->hp-1, val2?0:status->sp); - return 1; - break; - case SC_CLOSECONFINE2: { - struct block_list *src = val2?map_id2bl(val2):NULL; - struct status_change *sc2 = src?status_get_sc(src):NULL; - struct status_change_entry *sce2 = sc2?sc2->data[SC_CLOSECONFINE]:NULL; - if (src && sc2) { - if (!sce2) //Start lock on caster. - sc_start4(src,SC_CLOSECONFINE,100,val1,1,0,0,tick+1000); - else { //Increase count of locked enemies and refresh time. - (sce2->val2)++; - delete_timer(sce2->timer, status_change_timer); - sce2->timer = add_timer(gettick()+tick+1000, status_change_timer, src->id, SC_CLOSECONFINE); - } - } else //Status failed. - return 0; - } - break; - case SC_KAITE: - val2 = 1+val1/5; //Number of bounces: 1 + skilllv/5 - break; - case SC_KAUPE: - switch (val1) { - case 3: //33*3 + 1 -> 100% - val2++; - case 1: - case 2: //33, 66% - val2 += 33*val1; - val3 = 1; //Dodge 1 attack total. - break; - default: //Custom. For high level mob usage, higher level means more blocks. [Skotlex] - val2 = 100; - val3 = val1-2; - break; - } - break; - - case SC_COMBO: { - //val1: Skill ID - //val2: When given, target (for autotargetting skills) - //val3: When set, this combo time should NOT delay attack/movement - //val3: TK: Last used kick - //val4: TK: Combo time - struct unit_data *ud = unit_bl2ud(bl); - if (ud && !val3) { - tick += 300 * battle_config.combo_delay_rate/100; - ud->attackabletime = gettick()+tick; - unit_set_walkdelay(bl, gettick(), tick, 1); - } - val3 = 0; - val4 = tick; - } - break; - case SC_EARTHSCROLL: - val2 = 11-val1; //Chance to consume: 11-skilllv% - break; - case SC_RUN: - val4 = gettick(); //Store time at which you started running. - tick = -1; - break; - case SC_KAAHI: - val2 = 200*val1; //HP heal - val3 = 5*val1; //SP cost - val4 = INVALID_TIMER; //Kaahi Timer. - break; - case SC_BLESSING: - if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) - val2 = val1; - else - val2 = 0; //0 -> Half stat. - break; - case SC_TRICKDEAD: - if (vd) vd->dead_sit = 1; - tick = -1; - break; - case SC_CONCENTRATE: - val2 = 2 + val1; - if (sd) { //Store the card-bonus data that should not count in the % - val3 = sd->param_bonus[1]; //Agi - val4 = sd->param_bonus[4]; //Dex - } else { - val3 = val4 = 0; - } - break; - case SC_MAXOVERTHRUST: - val2 = 20*val1; //Power increase - break; - case SC_OVERTHRUST: - //val2 holds if it was casted on self, or is bonus received from others - val3 = 5*val1; //Power increase - if (sd && pc_checkskill(sd,BS_HILTBINDING)>0) - tick += tick / 10; - break; - case SC_ADRENALINE2: - case SC_ADRENALINE: - val3 = (val2) ? 300 : 200; // aspd increase - case SC_WEAPONPERFECTION: - if (sd && pc_checkskill(sd,BS_HILTBINDING)>0) - tick += tick / 10; - break; - case SC_CONCENTRATION: - val2 = 5*val1; //Batk/Watk Increase - val3 = 10*val1; //Hit Increase - val4 = 5*val1; //Def reduction - break; - case SC_ANGELUS: - val2 = 5*val1; //def increase - break; - case SC_IMPOSITIO: - val2 = 5*val1; //watk increase - break; - case SC_MELTDOWN: - val2 = 100*val1; //Chance to break weapon - val3 = 70*val1; //Change to break armor - break; - case SC_TRUESIGHT: - val2 = 10*val1; //Critical increase - val3 = 3*val1; //Hit increase - break; - case SC_SUN_COMFORT: - val2 = (status_get_lv(bl) + status->dex + status->luk)/2; //def increase - break; - case SC_MOON_COMFORT: - val2 = (status_get_lv(bl) + status->dex + status->luk)/10; //flee increase - break; - case SC_STAR_COMFORT: - val2 = (status_get_lv(bl) + status->dex + status->luk); //Aspd increase - break; - case SC_QUAGMIRE: - val2 = (sd?5:10)*val1; //Agi/Dex decrease. - break; - - // gs_something1 [Vicious] - case SC_GATLINGFEVER: - val2 = 20*val1; //Aspd increase - val3 = 20+10*val1; //Batk increase - val4 = 5*val1; //Flee decrease - break; - - case SC_FLING: - if (bl->type == BL_PC) - val2 = 0; //No armor reduction to players. - else - val2 = 5*val1; //Def reduction - val3 = 5*val1; //Def2 reduction - break; - case SC_PROVOKE: - //val2 signals autoprovoke. - val3 = 2+3*val1; //Atk increase - val4 = 5+5*val1; //Def reduction. - break; - case SC_AVOID: - //val2 = 10*val1; //Speed change rate. - break; - case SC_DEFENCE: - val2 = 2*val1; //Def bonus - break; - case SC_BLOODLUST: - val2 = 20+10*val1; //Atk rate change. - val3 = 3*val1; //Leech chance - val4 = 20; //Leech percent - break; - case SC_FLEET: - val2 = 30*val1; //Aspd change - val3 = 5+5*val1; //bAtk/wAtk rate change - break; - case SC_MINDBREAKER: - val2 = 20*val1; //matk increase. - val3 = 12*val1; //mdef2 reduction. - break; - case SC_SKA: - val2 = tick/1000; - val3 = rnd()%100; //Def changes randomly every second... - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_JAILED: - //Val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time. - tick = val1>0?1000:250; - if (sd) { - if (sd->mapindex != val2) { - int pos = (bl->x&0xFFFF)|(bl->y<<16), //Current Coordinates - map = sd->mapindex; //Current Map - //1. Place in Jail (val2 -> Jail Map, val3 -> x, val4 -> y - pc_setpos(sd,(unsigned short)val2,val3,val4, CLR_TELEPORT); - //2. Set restore point (val3 -> return map, val4 return coords - val3 = map; - val4 = pos; - } else if (!val3 || val3 == sd->mapindex) { //Use save point. - val3 = sd->status.save_point.map; - val4 = (sd->status.save_point.x&0xFFFF) - |(sd->status.save_point.y<<16); - } - } - break; - case SC_UTSUSEMI: - val2=(val1+1)/2; // number of hits blocked - val3=skill_get_blewcount(NJ_UTSUSEMI, val1); //knockback value. - break; - case SC_BUNSINJYUTSU: - val2=(val1+1)/2; // number of hits blocked - break; - case SC_CHANGE: - val2= 30*val1; //Vit increase - val3= 20*val1; //Int increase - break; - case SC_SWOO: - if (status->mode&MD_BOSS) - tick /= 5; //TODO: Reduce skill's duration. But for how long? - break; - case SC_SPIDERWEB: - if (bl->type == BL_PC) - tick /= 2; - break; - case SC_ARMOR: - //NPC_DEFENDER: - val2 = 80; //Damage reduction - //Attack requirements to be blocked: - val3 = BF_LONG; //Range - val4 = BF_WEAPON|BF_MISC; //Type - break; - case SC_ENCHANTARMS: - //end previous enchants - skill_enchant_elemental_end(bl,type); - //Make sure the received element is valid. - if (val2 >= ELE_MAX) - val2 = val2%ELE_MAX; - else if (val2 < 0) - val2 = rnd()%ELE_MAX; - break; - case SC_CRITICALWOUND: - val2 = 20*val1; //Heal effectiveness decrease - break; - case SC_MAGICMIRROR: - case SC_SLOWCAST: - val2 = 20*val1; //Magic reflection/cast rate - break; - - case SC_ARMORCHANGE: - if (val2 == NPC_ANTIMAGIC) { - //Boost mdef - val2 =-20; - val3 = 20; - } else { //Boost def - val2 = 20; - val3 =-20; - } - val2*=val1; //20% per level - val3*=val1; - break; - case SC_EXPBOOST: - case SC_JEXPBOOST: - if (val1 < 0) - val1 = 0; - break; - case SC_INCFLEE2: - case SC_INCCRI: - val2 = val1*10; //Actual boost (since 100% = 1000) - break; - case SC_SUFFRAGIUM: - val2 = 15 * val1; //Speed cast decrease - break; - case SC_INCHEALRATE: - if (val1 < 1) - val1 = 1; - break; - case SC_HALLUCINATION: - val2 = 5+val1; //Factor by which displayed damage is increased by - break; - case SC_DOUBLECAST: - val2 = 30+10*val1; //Trigger rate - break; - case SC_KAIZEL: - val2 = 10*val1; //% of life to be revived with - break; - // case SC_ARMOR_ELEMENT: - // case SC_ARMOR_RESIST: - // Mod your resistance against elements: - // val1 = water | val2 = earth | val3 = fire | val4 = wind - // break; - //case ????: - //Place here SCs that have no SCB_* data, no skill associated, no ICON - //associated, and yet are not wrong/unknown. [Skotlex] - //break; - - case SC_MERC_FLEEUP: - case SC_MERC_ATKUP: - case SC_MERC_HITUP: - val2 = 15 * val1; - break; - case SC_MERC_HPUP: - case SC_MERC_SPUP: - val2 = 5 * val1; - break; - case SC_REBIRTH: - val2 = 20*val1; //% of life to be revived with - break; - - case SC_MANU_DEF: - case SC_MANU_ATK: - case SC_MANU_MATK: - val2 = 1; // Manuk group - break; - case SC_SPL_DEF: - case SC_SPL_ATK: - case SC_SPL_MATK: - val2 = 2; // Splendide group - break; - /** - * General - **/ - case SC_FEAR: - val2 = 2; - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_BURNING: - val4 = tick / 2000; // Total Ticks to Burn!! - tick_time = 2000; // [GodLesZ] tick time - break; - /** - * Rune Knight - **/ - case SC_DEATHBOUND: - val2 = 500 + 100 * val1; - break; - case SC_FIGHTINGSPIRIT: - val_flag |= 1|2; - break; - case SC_ABUNDANCE: - val4 = tick / 10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_GIANTGROWTH: - val2 = 10; // Triple damage success rate. - break; - /** - * Arch Bishop - **/ - case SC_RENOVATIO: - val4 = tick / 5000; - tick_time = 5000; - break; - case SC_SECRAMENT: - val2 = 10 * val1; - break; - case SC_VENOMIMPRESS: - val2 = 10 * val1; - val_flag |= 1|2; - break; - case SC_POISONINGWEAPON: - val_flag |= 1|2|4; - break; - case SC_WEAPONBLOCKING: - val2 = 10 + 2 * val1; // Chance - val4 = tick / 3000; - tick_time = 3000; // [GodLesZ] tick time - val_flag |= 1|2; - break; - case SC_TOXIN: - val4 = tick / 10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_MAGICMUSHROOM: - val4 = tick / 4000; - tick_time = 4000; // [GodLesZ] tick time - break; - case SC_PYREXIA: - status_change_start(bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds - val4 = tick / 3000; - tick_time = 3000; // [GodLesZ] tick time - break; - case SC_LEECHESEND: - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_OBLIVIONCURSE: - val4 = tick / 3000; - tick_time = 3000; // [GodLesZ] tick time - break; - case SC_ROLLINGCUTTER: - val_flag |= 1; - break; - case SC_CLOAKINGEXCEED: - val2 = (val1 + 1) / 2; // Hits - val3 = 90 + val1 * 10; // Walk speed - val_flag |= 1|2|4; - if (bl->type == BL_PC) - val4 |= battle_config.pc_cloak_check_type&7; - else - val4 |= battle_config.monster_cloak_check_type&7; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_HALLUCINATIONWALK: - val2 = 50 * val1; // Evasion rate of physical attacks. Flee - val3 = 10 * val1; // Evasion rate of magical attacks. - val_flag |= 1|2|4; - break; - case SC_WHITEIMPRISON: - status_change_end(bl, SC_BURNING, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); - break; - case SC_FREEZING: - status_change_end(bl, SC_BURNING, INVALID_TIMER); - break; - case SC_READING_SB: - // val2 = sp reduction per second - tick_time = 5000; // [GodLesZ] tick time - break; - case SC_SPHERE_1: - case SC_SPHERE_2: - case SC_SPHERE_3: - case SC_SPHERE_4: - case SC_SPHERE_5: - if (!sd) - return 0; // Should only work on players. - val4 = tick / 1000; - if (val4 < 1) - val4 = 1; - tick_time = 1000; // [GodLesZ] tick time - val_flag |= 1; - break; - case SC_SHAPESHIFT: - switch (val1) { - case 1: - val2 = ELE_FIRE; - break; - case 2: - val2 = ELE_EARTH; - break; - case 3: - val2 = ELE_WIND; - break; - case 4: - val2 = ELE_WATER; - break; - } - break; - case SC_ELECTRICSHOCKER: - case SC_CRYSTALIZE: - case SC_MEIKYOUSISUI: - val4 = tick / 1000; - if (val4 < 1) - val4 = 1; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_CAMOUFLAGE: - val4 = tick/1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_WUGDASH: - val4 = gettick(); //Store time at which you started running. - tick = -1; - break; - case SC__SHADOWFORM: { - struct map_session_data *s_sd = map_id2sd(val2); - if (s_sd) - s_sd->shadowform_id = bl->id; - val4 = tick / 1000; - val_flag |= 1|2|4; - tick_time = 1000; // [GodLesZ] tick time - } - break; - case SC__STRIPACCESSORY: - if (!sd) - val2 = 20; - break; - case SC__INVISIBILITY: - val2 = 50 - 10 * val1; // ASPD - val3 = 20 * val1; // CRITICAL - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - val_flag |= 1|2; - break; - case SC__ENERVATION: - val2 = 20 + 10 * val1; // ATK Reduction - val_flag |= 1|2; - if (sd) pc_delspiritball(sd,sd->spiritball,0); - break; - case SC__GROOMY: - val2 = 20 + 10 * val1; //ASPD. Need to confirm if Movement Speed reduction is the same. [Jobbie] - val3 = 20 * val1; //HIT - val_flag |= 1|2|4; - if (sd) { - // Removes Animals - if (pc_isriding(sd)) pc_setriding(sd, 0); - if (pc_isridingdragon(sd)) pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); - if (pc_iswug(sd)) pc_setoption(sd, sd->sc.option&~OPTION_WUG); - if (pc_isridingwug(sd)) pc_setoption(sd, sd->sc.option&~OPTION_WUGRIDER); - if (pc_isfalcon(sd)) pc_setoption(sd, sd->sc.option&~OPTION_FALCON); - if (sd->status.pet_id > 0) pet_menu(sd, 3); - if (merc_is_hom_active(sd->hd)) merc_hom_vaporize(sd,1); - if (sd->md) merc_delete(sd->md,3); - } - break; - case SC__LAZINESS: - val2 = 10 + 10 * val1; // Cast reduction - val3 = 10 * val1; // Flee Reduction - val_flag |= 1|2|4; - break; - case SC__UNLUCKY: - val2 = 10 * val1; // Crit and Flee2 Reduction - val_flag |= 1|2|4; - break; - case SC__WEAKNESS: - val2 = 10 * val1; - val_flag |= 1|2; - // bypasses coating protection and MADO - sc_start(bl,SC_STRIPWEAPON,100,val1,tick); - sc_start(bl,SC_STRIPSHIELD,100,val1,tick); - break; - break; - case SC_GN_CARTBOOST: - if (val1 < 3) - val2 = 50; - else if (val1 < 5) - val2 = 75; - else - val2 = 100; - break; - case SC_PROPERTYWALK: - val_flag |= 1|2; - val3 = 0; - break; - case SC_WARMER: - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); - status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); - break; - case SC_STRIKING: - val1 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1) - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_BLOODSUCKER: - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_VACUUM_EXTREME: - tick -= (status->str / 20) * 1000; - val4 = val3 = tick / 100; - tick_time = 100; // [GodLesZ] tick time - break; - case SC_SWINGDANCE: - val2 = 4 * val1; // Walk speed and aspd reduction. - break; - case SC_SYMPHONYOFLOVER: - case SC_RUSHWINDMILL: - case SC_ECHOSONG: - val2 = 6 * val1; - val2 += val3; //Adding 1% * Lesson Bonus - val2 += (int)(val4*2/10); //Adding 0.2% per JobLevel - break; - case SC_MOONLITSERENADE: - val2 = 10 * val1; - break; - case SC_HARMONIZE: - val2 = 5 + 5 * val1; - break; - case SC_VOICEOFSIREN: - val4 = tick / 2000; - tick_time = 2000; // [GodLesZ] tick time - break; - case SC_DEEPSLEEP: - val4 = tick / 2000; - tick_time = 2000; // [GodLesZ] tick time - break; - case SC_SIRCLEOFNATURE: - val2 = 1 + val1; //SP consume - val3 = 40 * val1; //HP recovery - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_SONGOFMANA: - val3 = 10 + (2 * val2); - val4 = tick/3000; - tick_time = 3000; // [GodLesZ] tick time - break; - case SC_SATURDAYNIGHTFEVER: - if (!val4) val4 = skill_get_time2(status_sc2skill(type),val1); - if (!val4) val4 = 3000; - val3 = tick/val4; - tick_time = val4; // [GodLesZ] tick time - break; - case SC_GLOOMYDAY: - val2 = 20 + 5 * val1; // Flee reduction. - val3 = 15 + 5 * val1; // ASPD reduction. - if (sd && rand()%100 < val1) { // (Skill Lv) % - val4 = 1; // reduce walk speed by half. - if (pc_isriding(sd)) pc_setriding(sd, 0); - if (pc_isridingdragon(sd)) pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); - } - break; - case SC_GLOOMYDAY_SK: - // Random number between [15 ~ (Voice Lesson Skill Level x 5) + (Skill Level x 10)] %. - val2 = 15 + rand()%((sd?pc_checkskill(sd, WM_LESSON)*5:0) + val1*10); - break; - case SC_SITDOWN_FORCE: - case SC_BANANA_BOMB_SITDOWN: - if (sd && !pc_issit(sd)) { - pc_setsit(sd); - skill_sit(sd,1); - clif_sitting(bl); - } - break; - case SC_DANCEWITHWUG: - val3 = (5 * val1) + (1 * val2); //Still need official value. - break; - case SC_LERADSDEW: - val3 = (5 * val1) + (1 * val2); - break; - case SC_MELODYOFSINK: - val3 = (5 * val1) + (1 * val2); - break; - case SC_BEYONDOFWARCRY: - val3 = (5 * val1) + (1 * val2); - break; - case SC_UNLIMITEDHUMMINGVOICE: { - struct unit_data *ud = unit_bl2ud(bl); - if (ud == NULL) return 0; - ud->state.skillcastcancel = 0; - val3 = 15 - (2 * val2); - } - break; - case SC_REFLECTDAMAGE: - val2 = 15 + 5 * val1; - val3 = (val1==5)?20:(val1+4)*2; // SP consumption - val4 = tick/10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_FORCEOFVANGUARD: // This is not the official way to handle it but I think we should use it. [pakpil] - val2 = 20 + 12 * (val1 - 1); // Chance - val3 = 5 + (2 * val1); // Max rage counters - tick = -1; //endless duration in the client - tick_time = 6000; // [GodLesZ] tick time - val_flag |= 1|2|4; - break; - case SC_EXEEDBREAK: - val1 *= 150; // 150 * skill_lv - if (sd && sd->inventory_data[sd->equip_index[EQI_HAND_R]]) { // Chars. - val1 += (sd->inventory_data[sd->equip_index[EQI_HAND_R]]->weight/10 * sd->inventory_data[sd->equip_index[EQI_HAND_R]]->wlv * status_get_lv(bl) / 100); - val1 += 15 * (sd ? sd->status.job_level:50) + 100; - } else // Mobs - val1 += (400 * status_get_lv(bl) / 100) + (15 * (status_get_lv(bl) / 2)); // About 1138% at mob_lvl 99. Is an aproximation to a standard weapon. [pakpil] - break; - case SC_PRESTIGE: // Bassed on suggested formula in iRO Wiki and some test, still need more test. [pakpil] - val2 = ((status->int_ + status->luk) / 6) + 5; // Chance to evade magic damage. - val1 *= 15; // Defence added - if (sd) - val1 += 10 * pc_checkskill(sd,CR_DEFENDER); - val_flag |= 1|2; - break; - case SC_BANDING: - tick_time = 5000; // [GodLesZ] tick time - val_flag |= 1; - break; - case SC_SHIELDSPELL_DEF: - case SC_SHIELDSPELL_MDEF: - case SC_SHIELDSPELL_REF: - val_flag |= 1|2; - break; - case SC_MAGNETICFIELD: - val3 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_INSPIRATION: - if (sd) { - val2 = (40 * val1) + (3 * sd->status.job_level); // ATK bonus - val3 = (sd->status.job_level / 10) * 2 + 12; // All stat bonus - } - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - status_change_clear_buffs(bl,3); //Remove buffs/debuffs - break; - case SC_SPELLFIST: - case SC_CURSEDCIRCLE_ATKER: - val_flag |= 1|2|4; - break; - case SC_CRESCENTELBOW: - val2 = 94 + val1; - val_flag |= 1|2; - break; - case SC_LIGHTNINGWALK: // [(Job Level / 2) + (40 + 5 * Skill Level)] % - val1 = (sd?sd->status.job_level:2)/2 + 40 + 5 * val1; - val_flag |= 1; - break; - case SC_RAISINGDRAGON: - val3 = tick / 5000; - tick_time = 5000; // [GodLesZ] tick time - break; - case SC_GT_CHANGE: { - // take note there is no def increase as skill desc says. [malufett] - struct block_list *src; - val3 = status->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] % - if ((src = map_id2bl(val2))) - val4 = (200/status_get_int(src)) * val1; // MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] - } - break; - case SC_GT_REVITALIZE: { - // take note there is no vit,aspd,speed increase as skill desc says. [malufett] - struct block_list *src; - val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] % - if ((src = map_id2bl(val2))) // the stat def is not shown in the status window and it is process differently - val4 = (status_get_vit(src)/4) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level] - } - break; - case SC_PYROTECHNIC_OPTION: - val2 = 60; // Watk TODO: Renewal (Atk2) - val3 = 11; // % Increase damage. - val_flag |= 1|2|4; - break; - case SC_HEATER_OPTION: - val2 = 120; // Watk. TODO: Renewal (Atk2) - val3 = 33; // % Increase effects. - val4 = 3; // Change into fire element. - val_flag |= 1|2|4; - break; - case SC_TROPIC_OPTION: - val2 = 180; // Watk. TODO: Renewal (Atk2) - val3 = MG_FIREBOLT; - break; - case SC_AQUAPLAY_OPTION: - val2 = 40; // Matk. TODO: Renewal (Matk1) - val3 = 33; // % Increase effects. - val_flag |= 1|2|4; - break; - case SC_COOLER_OPTION: - val2 = 80; // % Freezing chance - val3 = 33; // % increased damage - val4 = 1; // Change into water elemet - val_flag |= 1|2|4; - break; - case SC_CHILLY_AIR_OPTION: - val2 = 120; // Matk. TODO: Renewal (Matk1) - val3 = MG_COLDBOLT; - val_flag |= 1|2; - break; - case SC_GUST_OPTION: - val2 = 33; - val_flag |= 1|2; - break; - case SC_WIND_STEP_OPTION: - val2 = 50; // % Increase speed and flee. - break; - case SC_BLAST_OPTION: - val2 = 33; - val3 = 4; - val_flag |= 1|2|4; - break; - case SC_WILD_STORM_OPTION: - val2 = MG_LIGHTNINGBOLT; - val_flag |= 1|2; - break; - case SC_PETROLOGY_OPTION: - val2 = 5; - val3 = 33; - val_flag |= 1|2|4; - break; - case SC_CURSED_SOIL_OPTION: - val2 = 10; - val3 = 33; - val4 = 2; - val_flag |= 1|2|4; - break; - case SC_UPHEAVAL_OPTION: - val2 = WZ_EARTHSPIKE; - val_flag |= 1|2; - break; - case SC_CIRCLE_OF_FIRE_OPTION: - val2 = 300; - val_flag |= 1|2; - break; - case SC_FIRE_CLOAK_OPTION: - case SC_WATER_DROP_OPTION: - case SC_WIND_CURTAIN_OPTION: - case SC_STONE_SHIELD_OPTION: - val2 = 20; // Elemental modifier. Not confirmed. - break; - case SC_CIRCLE_OF_FIRE: - case SC_FIRE_CLOAK: - case SC_WATER_DROP: - case SC_WATER_SCREEN: - case SC_WIND_CURTAIN: - case SC_WIND_STEP: - case SC_STONE_SHIELD: - case SC_SOLID_SKIN: - val2 = 10; - tick_time = 2000; // [GodLesZ] tick time - break; - case SC_WATER_BARRIER: - val2 = 40; // Increasement. Mdef1 ??? - val3 = 20; // Reductions. Atk2, Flee1, Matk1 ???? - val_flag |= 1|2|4; - break; - case SC_ZEPHYR: - val2 = 22; // Flee. - break; - case SC_TIDAL_WEAPON: - val2 = 20; // Increase Elemental's attack. - break; - case SC_ROCK_CRUSHER: - case SC_ROCK_CRUSHER_ATK: - case SC_POWER_OF_GAIA: - val2 = 33; - break; - case SC_MELON_BOMB: - case SC_BANANA_BOMB: - val1 = 15; - break; - case SC_STOMACHACHE: - val2 = 8; // SP consume. - val4 = tick / 10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_KYOUGAKU: - val2 = 2*val1 + rand()%val1; - clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); - break; - case SC_KAGEMUSYA: - val3 = val1 * 2; - case SC_IZAYOI: - val2 = tick/1000; - tick_time = 1000; - break; - case SC_ZANGETSU: - if ((status_get_hp(bl)+status_get_sp(bl)) % 2 == 0) - val2 = status_get_lv(bl) / 2 + 50; - else - val2 -= 50; - break; - case SC_GENSOU: { - int hp = status_get_hp(bl), lv = 5; - short per = 100 / (status_get_max_hp(bl) / hp); - - if (per <= 15) - lv = 1; - else if (per <= 30) - lv = 2; - else if (per <= 50) - lv = 3; - else if (per <= 75) - lv = 4; - if (hp % 2 == 0) - status_heal(bl, hp * (6-lv) * 4 / 100, status_get_sp(bl) * (6-lv) * 3 / 100, 1); - else - status_zap(bl, hp * (lv*4) / 100, status_get_sp(bl) * (lv*3) / 100); - } - break; - case SC_ANGRIFFS_MODUS: - val2 = 50 + 20 * val1; //atk bonus - val3 = 40 + 20 * val1; // Flee reduction. - val4 = tick/1000; // hp/sp reduction timer - tick_time = 1000; - break; - case SC_GOLDENE_FERSE: - val2 = 10 + 10*val1; //max hp bonus - val3 = 6 + 4 * val1; // Aspd Bonus - val4 = 2 + 2 * val1; // Chance of holy attack - break; - case SC_OVERED_BOOST: - val2 = 300 + 40*val1; //flee bonus - val3 = 179 + 2*val1; //aspd bonus - break; - case SC_GRANITIC_ARMOR: - val2 = 2*val1; //dmg reduction - val3 = 6*val1; //dmg on status end - break; - case SC_MAGMA_FLOW: - val2 = 3*val1; //activation chance - break; - case SC_PYROCLASTIC: - val2 += 10*val1; //atk bonus - break; - case SC_PARALYSIS: //[Lighta] need real info - val2 = 2*val1; //def reduction - val3 = 500*val1; //varcast augmentation - break; - case SC_PAIN_KILLER: //[Lighta] need real info - val2 = 2*val1; //aspd reduction % - val3 = 2*val1; //dmg reduction % - if (sc->data[SC_PARALYSIS]) - sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration - break; - default: - if (calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0) { - //Status change with no calc, no icon, and no skill associated...? - ShowError("UnknownStatusChange [%d]\n", type); - return 0; - } - } - else //Special considerations when loading SC data. - switch (type) { - case SC_WEDDING: - case SC_XMAS: - case SC_SUMMER: - clif_changelook(bl,LOOK_WEAPON,0); - clif_changelook(bl,LOOK_SHIELD,0); - clif_changelook(bl,LOOK_BASE,type==SC_WEDDING?JOB_WEDDING:type==SC_XMAS?JOB_XMAS:JOB_SUMMER); - clif_changelook(bl,LOOK_CLOTHES_COLOR,val4); - break; - case SC_KAAHI: - val4 = INVALID_TIMER; - break; - } + case SC_WEDDING: + case SC_XMAS: + case SC_SUMMER: + if (!vd) return 0; + //Store previous values as they could be removed. + val1 = vd->class_; + val2 = vd->weapon; + val3 = vd->shield; + val4 = vd->cloth_color; + unit_stop_attack(bl); + clif_changelook(bl,LOOK_WEAPON,0); + clif_changelook(bl,LOOK_SHIELD,0); + clif_changelook(bl,LOOK_BASE,type==SC_WEDDING?JOB_WEDDING:type==SC_XMAS?JOB_XMAS:JOB_SUMMER); + clif_changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); + break; + case SC_NOCHAT: + // [GodLesZ] FIXME: is this correct? a hardcoded interval of 60sec? what about configuration ?_? + tick = 60000; + val1 = battle_config.manner_system; //Mute filters. + if (sd) + { + clif_changestatus(sd,SP_MANNER,sd->status.manner); + clif_updatestatus(sd,SP_MANNER); + } + break; - //Those that make you stop attacking/walking.... - switch (type) { - case SC_FREEZE: - case SC_STUN: - case SC_SLEEP: - case SC_STONE: - case SC_DEEPSLEEP: - if (sd && pc_issit(sd)) //Avoid sprite sync problems. - pc_setstand(sd); - case SC_TRICKDEAD: - unit_stop_attack(bl); - status_change_end(bl, SC_DANCING, INVALID_TIMER); - // Cancel cast when get status [LuzZza] - if (battle_config.sc_castcancel&bl->type) - unit_skillcastcancel(bl, 0); - case SC_STOP: - case SC_CONFUSION: - case SC_CLOSECONFINE: - case SC_CLOSECONFINE2: - case SC_ANKLE: - case SC_SPIDERWEB: - case SC_ELECTRICSHOCKER: - case SC_BITE: - case SC_THORNSTRAP: - case SC__MANHOLE: - case SC_CRYSTALIZE: - case SC_WHITEIMPRISON: - case SC_CURSEDCIRCLE_ATKER: - case SC_CURSEDCIRCLE_TARGET: - case SC_FEAR: - case SC_NETHERWORLD: - case SC_MEIKYOUSISUI: - case SC_KYOUGAKU: - case SC_PARALYSIS: - unit_stop_walking(bl,1); - break; - case SC_HIDING: - case SC_CLOAKING: - case SC_CLOAKINGEXCEED: - case SC_CHASEWALK: - case SC_WEIGHT90: - case SC_CAMOUFLAGE: - case SC_VOICEOFSIREN: - unit_stop_attack(bl); - break; - case SC_SILENCE: - if (battle_config.sc_castcancel&bl->type) - unit_skillcastcancel(bl, 0); - break; - } + case SC_STONE: + val3 = tick/1000; //Petrified HP-damage iterations. + if(val3 < 1) val3 = 1; + tick = val4; //Petrifying time. + tick = max(tick, 1000); //Min time + calc_flag = 0; //Actual status changes take effect on petrified state. + break; - // Set option as needed. - opt_flag = 1; - switch (type) { - //OPT1 - case SC_STONE: - sc->opt1 = OPT1_STONEWAIT; - break; - case SC_FREEZE: - sc->opt1 = OPT1_FREEZE; - break; - case SC_STUN: - sc->opt1 = OPT1_STUN; - break; - case SC_SLEEP: - case SC_DEEPSLEEP: - if(type == SC_DEEPSLEEP) - opt_flag = 0; - sc->opt1 = OPT1_SLEEP; - break; - case SC_BURNING: - sc->opt1 = OPT1_BURNING; - break; // Burning need this to be showed correctly. [pakpil] - case SC_WHITEIMPRISON: - sc->opt1 = OPT1_IMPRISON; - break; - case SC_CRYSTALIZE: - sc->opt1 = OPT1_CRYSTALIZE; - break; - //OPT2 - case SC_POISON: - sc->opt2 |= OPT2_POISON; - break; - case SC_CURSE: - sc->opt2 |= OPT2_CURSE; - break; - case SC_SILENCE: - sc->opt2 |= OPT2_SILENCE; - break; + case SC_DPOISON: + //Lose 10/15% of your life as long as it doesn't brings life below 25% + if (status->hp > status->max_hp>>2) { + int diff = status->max_hp*(bl->type==BL_PC?10:15)/100; + if (status->hp - diff < status->max_hp>>2) + diff = status->hp - (status->max_hp>>2); + if( val2 && bl->type == BL_MOB ) { + struct block_list* src = map_id2bl(val2); + if( src ) + mob_log_damage((TBL_MOB*)bl,src,diff); + } + status_zap(bl, diff, 0); + } + // fall through + case SC_POISON: + val3 = tick/1000; //Damage iterations + if(val3 < 1) val3 = 1; + tick_time = 1000; // [GodLesZ] tick time + //val4: HP damage + if (bl->type == BL_PC) + val4 = (type == SC_DPOISON) ? 3 + status->max_hp/50 : 3 + status->max_hp*3/200; + else + val4 = (type == SC_DPOISON) ? 3 + status->max_hp/100 : 3 + status->max_hp/200; + + break; + case SC_CONFUSION: + clif_emotion(bl,E_WHAT); + break; + case SC_BLEEDING: + val4 = tick/10000; + if (!val4) val4 = 1; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_S_LIFEPOTION: + case SC_L_LIFEPOTION: + if( val1 == 0 ) return 0; + // val1 = heal percent/amout + // val2 = seconds between heals + // val4 = total of heals + if( val2 < 1 ) val2 = 1; + if( (val4 = tick/(val2 * 1000)) < 1 ) + val4 = 1; + tick_time = val2 * 1000; // [GodLesZ] tick time + break; + case SC_BOSSMAPINFO: + if( sd != NULL ) + { + struct mob_data *boss_md = map_getmob_boss(bl->m); // Search for Boss on this Map + if( boss_md == NULL || boss_md->bl.prev == NULL ) + { // No MVP on this map - MVP is dead + clif_bossmapinfo(sd->fd, boss_md, 1); + return 0; // No need to start SC + } + val1 = boss_md->bl.id; + if( (val4 = tick/1000) < 1 ) + val4 = 1; + tick_time = 1000; // [GodLesZ] tick time + } + break; + case SC_HIDING: + val2 = tick/1000; + tick_time = 1000; // [GodLesZ] tick time + val3 = 0; // unused, previously speed adjustment + val4 = val1+3; //Seconds before SP substraction happen. + break; + case SC_CHASEWALK: + val2 = tick>0?tick:10000; //Interval at which SP is drained. + val3 = 35 - 5 * val1; //Speed adjustment. + if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE) + val3 -= 40; + val4 = 10+val1*2; //SP cost. + if (map_flag_gvg(bl->m) || map[bl->m].flag.battleground) val4 *= 5; + break; + case SC_CLOAKING: + if (!sd) //Monsters should be able to walk with no penalties. [Skotlex] + val1 = 10; + tick_time = val2 = tick>0?tick:60000; //SP consumption rate. + tick = -1; // duration sent to the client should be infinite + val3 = 0; // unused, previously walk speed adjustment + //val4&1 signals the presence of a wall. + //val4&2 makes cloak not end on normal attacks [Skotlex] + //val4&4 makes cloak not end on using skills + if (bl->type == BL_PC || (bl->type == BL_MOB && ((TBL_MOB*)bl)->special_state.clone) ) //Standard cloaking. + val4 |= battle_config.pc_cloak_check_type&7; + else + val4 |= battle_config.monster_cloak_check_type&7; + break; + case SC_SIGHT: /* splash status */ + case SC_RUWACH: + case SC_SIGHTBLASTER: + val3 = skill_get_splash(val2, val1); //Val2 should bring the skill-id. + val2 = tick/250; + tick_time = 10; // [GodLesZ] tick time + break; - case SC_SIGNUMCRUCIS: - sc->opt2 |= OPT2_SIGNUMCRUCIS; - break; + //Permanent effects. + case SC_AETERNA: + case SC_MODECHANGE: + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_BROKENWEAPON: + case SC_BROKENARMOR: + case SC_READYSTORM: + case SC_READYDOWN: + case SC_READYCOUNTER: + case SC_READYTURN: + case SC_DODGE: + case SC_PUSH_CART: + tick = -1; + break; - case SC_BLIND: - sc->opt2 |= OPT2_BLIND; - break; - case SC_ANGELUS: - sc->opt2 |= OPT2_ANGELUS; - break; - case SC_BLEEDING: - sc->opt2 |= OPT2_BLEEDING; - break; - case SC_DPOISON: - sc->opt2 |= OPT2_DPOISON; - break; - //OPT3 - case SC_TWOHANDQUICKEN: - case SC_ONEHAND: - case SC_SPEARQUICKEN: - case SC_CONCENTRATION: - case SC_MERC_QUICKEN: - sc->opt3 |= OPT3_QUICKEN; - opt_flag = 0; - break; - case SC_MAXOVERTHRUST: - case SC_OVERTHRUST: - case SC_SWOO: //Why does it shares the same opt as Overthrust? Perhaps we'll never know... - sc->opt3 |= OPT3_OVERTHRUST; - opt_flag = 0; - break; - case SC_ENERGYCOAT: - case SC_SKE: - sc->opt3 |= OPT3_ENERGYCOAT; - opt_flag = 0; - break; - case SC_INCATKRATE: - //Simulate Explosion Spirits effect for NPC_POWERUP [Skotlex] - if (bl->type != BL_MOB) { - opt_flag = 0; - break; - } - case SC_EXPLOSIONSPIRITS: - sc->opt3 |= OPT3_EXPLOSIONSPIRITS; - opt_flag = 0; - break; - case SC_STEELBODY: - case SC_SKA: - sc->opt3 |= OPT3_STEELBODY; - opt_flag = 0; - break; - case SC_BLADESTOP: - sc->opt3 |= OPT3_BLADESTOP; - opt_flag = 0; - break; - case SC_AURABLADE: - sc->opt3 |= OPT3_AURABLADE; - opt_flag = 0; - break; - case SC_BERSERK: - opt_flag = 0; - // case SC__BLOODYLUST: - sc->opt3 |= OPT3_BERSERK; - break; - // case ???: // doesn't seem to do anything - // sc->opt3 |= OPT3_LIGHTBLADE; - // opt_flag = 0; - // break; - case SC_DANCING: - if ((val1&0xFFFF) == CG_MOONLIT) - sc->opt3 |= OPT3_MOONLIT; - opt_flag = 0; - break; - case SC_MARIONETTE: - case SC_MARIONETTE2: - sc->opt3 |= OPT3_MARIONETTE; - opt_flag = 0; - break; - case SC_ASSUMPTIO: - sc->opt3 |= OPT3_ASSUMPTIO; - opt_flag = 0; - break; - case SC_WARM: //SG skills [Komurka] - sc->opt3 |= OPT3_WARM; - opt_flag = 0; - break; - case SC_KAITE: - sc->opt3 |= OPT3_KAITE; - opt_flag = 0; - break; - case SC_BUNSINJYUTSU: - sc->opt3 |= OPT3_BUNSIN; - opt_flag = 0; - break; - case SC_SPIRIT: - sc->opt3 |= OPT3_SOULLINK; - opt_flag = 0; - break; - case SC_CHANGEUNDEAD: - sc->opt3 |= OPT3_UNDEAD; - opt_flag = 0; - break; - // case ???: // from DA_CONTRACT (looks like biolab mobs aura) - // sc->opt3 |= OPT3_CONTRACT; - // opt_flag = 0; - // break; - //OPTION - case SC_HIDING: - sc->option |= OPTION_HIDE; - opt_flag = 2; - break; - case SC_CLOAKING: - case SC_CLOAKINGEXCEED: - case SC__INVISIBILITY: - sc->option |= OPTION_CLOAK; - opt_flag = 2; - break; - case SC_CHASEWALK: - sc->option |= OPTION_CHASEWALK|OPTION_CLOAK; - opt_flag = 2; - break; - case SC_SIGHT: - sc->option |= OPTION_SIGHT; - break; - case SC_RUWACH: - sc->option |= OPTION_RUWACH; - break; - case SC_WEDDING: - sc->option |= OPTION_WEDDING; - break; - case SC_XMAS: - sc->option |= OPTION_XMAS; - break; - case SC_SUMMER: - sc->option |= OPTION_SUMMER; - break; - case SC_ORCISH: - sc->option |= OPTION_ORCISH; - break; - case SC_FUSION: - sc->option |= OPTION_FLYING; - break; - default: - opt_flag = 0; - } + case SC_AUTOGUARD: + if( !(flag&1) ) + { + struct map_session_data *tsd; + int i,t; + for( i = val2 = 0; i < val1; i++) + { + t = 5-(i>>1); + val2 += (t < 0)? 1:t; + } + + if( bl->type&(BL_PC|BL_MER) ) + { + if( sd ) + { + for( i = 0; i < 5; i++ ) + { + if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + } + } + else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + } + } + break; - //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. - if (opt_flag) - clif_changeoption(bl); + case SC_DEFENDER: + if (!(flag&1)) + { + val2 = 5 + 15*val1; //Damage reduction + val3 = 0; // unused, previously speed adjustment + val4 = 250 - 50*val1; //Aspd adjustment + + if (sd) + { + struct map_session_data *tsd; + int i; + for (i = 0; i < 5; i++) + { //See if there are devoted characters, and pass the status to them. [Skotlex] + if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i]))) + status_change_start(&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1); + } + } + } + break; - if (calc_flag&SCB_DYE) { - //Reset DYE color - if (vd && vd->cloth_color) { - val4 = vd->cloth_color; - clif_changelook(bl,LOOK_CLOTHES_COLOR,0); - } - calc_flag&=~SCB_DYE; - } + case SC_TENSIONRELAX: + if (sd) { + pc_setsit(sd); + clif_sitting(&sd->bl); + } + val2 = 12; //SP cost + val4 = 10000; //Decrease at 10secs intervals. + val3 = tick/val4; + tick = -1; // duration sent to the client should be infinite + tick_time = val4; // [GodLesZ] tick time + break; + case SC_PARRYING: + val2 = 20 + val1*3; //Block Chance + break; - clif_status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); - - /** - * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. - **/ - if (tick_time) - tick = tick_time; - - //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here. - if ((sce=sc->data[type])) { // reuse old sc - if (sce->timer != INVALID_TIMER) - delete_timer(sce->timer, status_change_timer); - sc_isnew = false; - } else {// new sc - ++(sc->count); - sce = sc->data[type] = ers_alloc(sc_data_ers, struct status_change_entry); - } - sce->val1 = val1; - sce->val2 = val2; - sce->val3 = val3; - sce->val4 = val4; - if (tick >= 0) - sce->timer = add_timer(gettick() + tick, status_change_timer, bl->id, type); - else - sce->timer = INVALID_TIMER; //Infinite duration + case SC_WINDWALK: + val2 = (val1+1)/2; // Flee bonus is 1/1/2/2/3/3/4/4/5/5 + break; + + case SC_JOINTBEAT: + if( val2&BREAK_NECK ) + sc_start(bl,SC_BLEEDING,100,val1,skill_get_time2(status_sc2skill(type),val1)); + break; - if (calc_flag) - status_calc_bl(bl,calc_flag); + case SC_BERSERK: + if (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) + sc_start4(bl, SC_ENDURE, 100,10,0,0,2, tick); + case SC__BLOODYLUST: + //HP healing is performing after the calc_status call. + //Val2 holds HP penalty + if (!val4) val4 = skill_get_time2(status_sc2skill(type),val1); + if (!val4) val4 = 10000; //Val4 holds damage interval + val3 = tick/val4; //val3 holds skill duration + tick_time = val4; // [GodLesZ] tick time + break; - if (sc_isnew && StatusChangeStateTable[type]) /* non-zero */ - status_calc_state(bl,sc,(enum scs_flag) StatusChangeStateTable[type],true); + case SC_GOSPEL: + if(val4 == BCT_SELF) { // self effect + val2 = tick/10000; + tick_time = 10000; // [GodLesZ] tick time + status_change_clear_buffs(bl,3); //Remove buffs/debuffs + } + break; + case SC_MARIONETTE: + { + int stat; + + val3 = 0; + val4 = 0; + stat = ( sd ? sd->status.str : status_get_base_status(bl)->str ) / 2; val3 |= cap_value(stat,0,0xFF)<<16; + stat = ( sd ? sd->status.agi : status_get_base_status(bl)->agi ) / 2; val3 |= cap_value(stat,0,0xFF)<<8; + stat = ( sd ? sd->status.vit : status_get_base_status(bl)->vit ) / 2; val3 |= cap_value(stat,0,0xFF); + stat = ( sd ? sd->status.int_: status_get_base_status(bl)->int_) / 2; val4 |= cap_value(stat,0,0xFF)<<16; + stat = ( sd ? sd->status.dex : status_get_base_status(bl)->dex ) / 2; val4 |= cap_value(stat,0,0xFF)<<8; + stat = ( sd ? sd->status.luk : status_get_base_status(bl)->luk ) / 2; val4 |= cap_value(stat,0,0xFF); + break; + } + case SC_MARIONETTE2: + { + int stat,max_stat; + // fetch caster information + struct block_list *pbl = map_id2bl(val1); + struct status_change *psc = pbl?status_get_sc(pbl):NULL; + struct status_change_entry *psce = psc?psc->data[SC_MARIONETTE]:NULL; + // fetch target's stats + struct status_data* status = status_get_status_data(bl); // battle status + + if (!psce) + return 0; + + val3 = 0; + val4 = 0; + max_stat = battle_config.max_parameter; //Cap to 99 (default) + stat = (psce->val3 >>16)&0xFF; stat = min(stat, max_stat - status->str ); val3 |= cap_value(stat,0,0xFF)<<16; + stat = (psce->val3 >> 8)&0xFF; stat = min(stat, max_stat - status->agi ); val3 |= cap_value(stat,0,0xFF)<<8; + stat = (psce->val3 >> 0)&0xFF; stat = min(stat, max_stat - status->vit ); val3 |= cap_value(stat,0,0xFF); + stat = (psce->val4 >>16)&0xFF; stat = min(stat, max_stat - status->int_); val4 |= cap_value(stat,0,0xFF)<<16; + stat = (psce->val4 >> 8)&0xFF; stat = min(stat, max_stat - status->dex ); val4 |= cap_value(stat,0,0xFF)<<8; + stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - status->luk ); val4 |= cap_value(stat,0,0xFF); + break; + } + case SC_REJECTSWORD: + val2 = 15*val1; //Reflect chance + val3 = 3; //Reflections + tick = -1; + break; - if (sd && sd->pd) - pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing + case SC_MEMORIZE: + val2 = 5; //Memorized casts. + tick = -1; + break; + + case SC_GRAVITATION: + val2 = 50*val1; //aspd reduction + break; + + case SC_REGENERATION: + if (val1 == 1) + val2 = 2; + else + val2 = val1; //HP Regerenation rate: 200% 200% 300% + val3 = val1; //SP Regeneration Rate: 100% 200% 300% + //if val4 comes set, this blocks regen rather than increase it. + break; + + case SC_DEVOTION: + { + struct block_list *d_bl; + struct status_change *d_sc; + + if( (d_bl = map_id2bl(val1)) && (d_sc = status_get_sc(d_bl)) && d_sc->count ) + { // Inherits Status From Source + const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE }; + enum sc_type type2; + int i = (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)?2:3; + while( i >= 0 ) + { + type2 = types[i]; + if( d_sc->data[type2] ) + sc_start(bl, type2, 100, d_sc->data[type2]->val1, skill_get_time(status_sc2skill(type2),d_sc->data[type2]->val1)); + i--; + } + } + break; + } + + case SC_COMA: //Coma. Sends a char to 1HP. If val2, do not zap sp + if( val3 && bl->type == BL_MOB ) { + struct block_list* src = map_id2bl(val3); + if( src ) + mob_log_damage((TBL_MOB*)bl,src,status->hp - 1); + } + status_zap(bl, status->hp-1, val2?0:status->sp); + return 1; + break; + case SC_CLOSECONFINE2: + { + struct block_list *src = val2?map_id2bl(val2):NULL; + struct status_change *sc2 = src?status_get_sc(src):NULL; + struct status_change_entry *sce2 = sc2?sc2->data[SC_CLOSECONFINE]:NULL; + if (src && sc2) { + if (!sce2) //Start lock on caster. + sc_start4(src,SC_CLOSECONFINE,100,val1,1,0,0,tick+1000); + else { //Increase count of locked enemies and refresh time. + (sce2->val2)++; + delete_timer(sce2->timer, status_change_timer); + sce2->timer = add_timer(gettick()+tick+1000, status_change_timer, src->id, SC_CLOSECONFINE); + } + } else //Status failed. + return 0; + } + break; + case SC_KAITE: + val2 = 1+val1/5; //Number of bounces: 1 + skilllv/5 + break; + case SC_KAUPE: + switch (val1) { + case 3: //33*3 + 1 -> 100% + val2++; + case 1: + case 2: //33, 66% + val2 += 33*val1; + val3 = 1; //Dodge 1 attack total. + break; + default: //Custom. For high level mob usage, higher level means more blocks. [Skotlex] + val2 = 100; + val3 = val1-2; + break; + } + break; + + case SC_COMBO: { + //val1: Skill ID + //val2: When given, target (for autotargetting skills) + //val3: When set, this combo time should NOT delay attack/movement + //val3: TK: Last used kick + //val4: TK: Combo time + struct unit_data *ud = unit_bl2ud(bl); + if (ud && !val3) { + tick += 300 * battle_config.combo_delay_rate/100; + ud->attackabletime = gettick()+tick; + unit_set_walkdelay(bl, gettick(), tick, 1); + } + val3 = 0; + val4 = tick; + } + break; + case SC_EARTHSCROLL: + val2 = 11-val1; //Chance to consume: 11-skilllv% + break; + case SC_RUN: + val4 = gettick(); //Store time at which you started running. + tick = -1; + break; + case SC_KAAHI: + val2 = 200*val1; //HP heal + val3 = 5*val1; //SP cost + val4 = INVALID_TIMER; //Kaahi Timer. + break; + case SC_BLESSING: + if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) + val2 = val1; + else + val2 = 0; //0 -> Half stat. + break; + case SC_TRICKDEAD: + if (vd) vd->dead_sit = 1; + tick = -1; + break; + case SC_CONCENTRATE: + val2 = 2 + val1; + if (sd) { //Store the card-bonus data that should not count in the % + val3 = sd->param_bonus[1]; //Agi + val4 = sd->param_bonus[4]; //Dex + } else { + val3 = val4 = 0; + } + break; + case SC_MAXOVERTHRUST: + val2 = 20*val1; //Power increase + break; + case SC_OVERTHRUST: + //val2 holds if it was casted on self, or is bonus received from others + val3 = 5*val1; //Power increase + if(sd && pc_checkskill(sd,BS_HILTBINDING)>0) + tick += tick / 10; + break; + case SC_ADRENALINE2: + case SC_ADRENALINE: + val3 = (val2) ? 300 : 200; // aspd increase + case SC_WEAPONPERFECTION: + if(sd && pc_checkskill(sd,BS_HILTBINDING)>0) + tick += tick / 10; + break; + case SC_CONCENTRATION: + val2 = 5*val1; //Batk/Watk Increase + val3 = 10*val1; //Hit Increase + val4 = 5*val1; //Def reduction + break; + case SC_ANGELUS: + val2 = 5*val1; //def increase + break; + case SC_IMPOSITIO: + val2 = 5*val1; //watk increase + break; + case SC_MELTDOWN: + val2 = 100*val1; //Chance to break weapon + val3 = 70*val1; //Change to break armor + break; + case SC_TRUESIGHT: + val2 = 10*val1; //Critical increase + val3 = 3*val1; //Hit increase + break; + case SC_SUN_COMFORT: + val2 = (status_get_lv(bl) + status->dex + status->luk)/2; //def increase + break; + case SC_MOON_COMFORT: + val2 = (status_get_lv(bl) + status->dex + status->luk)/10; //flee increase + break; + case SC_STAR_COMFORT: + val2 = (status_get_lv(bl) + status->dex + status->luk); //Aspd increase + break; + case SC_QUAGMIRE: + val2 = (sd?5:10)*val1; //Agi/Dex decrease. + break; + + // gs_something1 [Vicious] + case SC_GATLINGFEVER: + val2 = 20*val1; //Aspd increase + val3 = 20+10*val1; //Batk increase + val4 = 5*val1; //Flee decrease + break; + + case SC_FLING: + if (bl->type == BL_PC) + val2 = 0; //No armor reduction to players. + else + val2 = 5*val1; //Def reduction + val3 = 5*val1; //Def2 reduction + break; + case SC_PROVOKE: + //val2 signals autoprovoke. + val3 = 2+3*val1; //Atk increase + val4 = 5+5*val1; //Def reduction. + break; + case SC_AVOID: + //val2 = 10*val1; //Speed change rate. + break; + case SC_DEFENCE: + val2 = 2*val1; //Def bonus + break; + case SC_BLOODLUST: + val2 = 20+10*val1; //Atk rate change. + val3 = 3*val1; //Leech chance + val4 = 20; //Leech percent + break; + case SC_FLEET: + val2 = 30*val1; //Aspd change + val3 = 5+5*val1; //bAtk/wAtk rate change + break; + case SC_MINDBREAKER: + val2 = 20*val1; //matk increase. + val3 = 12*val1; //mdef2 reduction. + break; + case SC_SKA: + val2 = tick/1000; + val3 = rnd()%100; //Def changes randomly every second... + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_JAILED: + //Val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time. + tick = val1>0?1000:250; + if (sd) + { + if (sd->mapindex != val2) + { + int pos = (bl->x&0xFFFF)|(bl->y<<16), //Current Coordinates + map = sd->mapindex; //Current Map + //1. Place in Jail (val2 -> Jail Map, val3 -> x, val4 -> y + pc_setpos(sd,(unsigned short)val2,val3,val4, CLR_TELEPORT); + //2. Set restore point (val3 -> return map, val4 return coords + val3 = map; + val4 = pos; + } else if (!val3 || val3 == sd->mapindex) { //Use save point. + val3 = sd->status.save_point.map; + val4 = (sd->status.save_point.x&0xFFFF) + |(sd->status.save_point.y<<16); + } + } + break; + case SC_UTSUSEMI: + val2=(val1+1)/2; // number of hits blocked + val3=skill_get_blewcount(NJ_UTSUSEMI, val1); //knockback value. + break; + case SC_BUNSINJYUTSU: + val2=(val1+1)/2; // number of hits blocked + break; + case SC_CHANGE: + val2= 30*val1; //Vit increase + val3= 20*val1; //Int increase + break; + case SC_SWOO: + if(status->mode&MD_BOSS) + tick /= 5; //TODO: Reduce skill's duration. But for how long? + break; + case SC_SPIDERWEB: + if( bl->type == BL_PC ) + tick /= 2; + break; + case SC_ARMOR: + //NPC_DEFENDER: + val2 = 80; //Damage reduction + //Attack requirements to be blocked: + val3 = BF_LONG; //Range + val4 = BF_WEAPON|BF_MISC; //Type + break; + case SC_ENCHANTARMS: + //end previous enchants + skill_enchant_elemental_end(bl,type); + //Make sure the received element is valid. + if (val2 >= ELE_MAX) + val2 = val2%ELE_MAX; + else if (val2 < 0) + val2 = rnd()%ELE_MAX; + break; + case SC_CRITICALWOUND: + val2 = 20*val1; //Heal effectiveness decrease + break; + case SC_MAGICMIRROR: + case SC_SLOWCAST: + val2 = 20*val1; //Magic reflection/cast rate + break; + + case SC_ARMORCHANGE: + if (val2 == NPC_ANTIMAGIC) + { //Boost mdef + val2 =-20; + val3 = 20; + } else { //Boost def + val2 = 20; + val3 =-20; + } + val2*=val1; //20% per level + val3*=val1; + break; + case SC_EXPBOOST: + case SC_JEXPBOOST: + if (val1 < 0) + val1 = 0; + break; + case SC_INCFLEE2: + case SC_INCCRI: + val2 = val1*10; //Actual boost (since 100% = 1000) + break; + case SC_SUFFRAGIUM: + val2 = 15 * val1; //Speed cast decrease + break; + case SC_INCHEALRATE: + if (val1 < 1) + val1 = 1; + break; + case SC_HALLUCINATION: + val2 = 5+val1; //Factor by which displayed damage is increased by + break; + case SC_DOUBLECAST: + val2 = 30+10*val1; //Trigger rate + break; + case SC_KAIZEL: + val2 = 10*val1; //% of life to be revived with + break; + // case SC_ARMOR_ELEMENT: + // case SC_ARMOR_RESIST: + // Mod your resistance against elements: + // val1 = water | val2 = earth | val3 = fire | val4 = wind + // break; + //case ????: + //Place here SCs that have no SCB_* data, no skill associated, no ICON + //associated, and yet are not wrong/unknown. [Skotlex] + //break; + + case SC_MERC_FLEEUP: + case SC_MERC_ATKUP: + case SC_MERC_HITUP: + val2 = 15 * val1; + break; + case SC_MERC_HPUP: + case SC_MERC_SPUP: + val2 = 5 * val1; + break; + case SC_REBIRTH: + val2 = 20*val1; //% of life to be revived with + break; + + case SC_MANU_DEF: + case SC_MANU_ATK: + case SC_MANU_MATK: + val2 = 1; // Manuk group + break; + case SC_SPL_DEF: + case SC_SPL_ATK: + case SC_SPL_MATK: + val2 = 2; // Splendide group + break; + /** + * General + **/ + case SC_FEAR: + val2 = 2; + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_BURNING: + val4 = tick / 2000; // Total Ticks to Burn!! + tick_time = 2000; // [GodLesZ] tick time + break; + /** + * Rune Knight + **/ + case SC_DEATHBOUND: + val2 = 500 + 100 * val1; + break; + case SC_FIGHTINGSPIRIT: + val_flag |= 1|2; + break; + case SC_ABUNDANCE: + val4 = tick / 10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_GIANTGROWTH: + val2 = 10; // Triple damage success rate. + break; + /** + * Arch Bishop + **/ + case SC_RENOVATIO: + val4 = tick / 5000; + tick_time = 5000; + break; + case SC_SECRAMENT: + val2 = 10 * val1; + break; + case SC_VENOMIMPRESS: + val2 = 10 * val1; + val_flag |= 1|2; + break; + case SC_POISONINGWEAPON: + val_flag |= 1|2|4; + break; + case SC_WEAPONBLOCKING: + val2 = 10 + 2 * val1; // Chance + val4 = tick / 3000; + tick_time = 3000; // [GodLesZ] tick time + val_flag |= 1|2; + break; + case SC_TOXIN: + val4 = tick / 10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_MAGICMUSHROOM: + val4 = tick / 4000; + tick_time = 4000; // [GodLesZ] tick time + break; + case SC_PYREXIA: + status_change_start(bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds + val4 = tick / 3000; + tick_time = 3000; // [GodLesZ] tick time + break; + case SC_LEECHESEND: + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_OBLIVIONCURSE: + val4 = tick / 3000; + tick_time = 3000; // [GodLesZ] tick time + break; + case SC_ROLLINGCUTTER: + val_flag |= 1; + break; + case SC_CLOAKINGEXCEED: + val2 = ( val1 + 1 ) / 2; // Hits + val3 = 90 + val1 * 10; // Walk speed + val_flag |= 1|2|4; + if (bl->type == BL_PC) + val4 |= battle_config.pc_cloak_check_type&7; + else + val4 |= battle_config.monster_cloak_check_type&7; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_HALLUCINATIONWALK: + val2 = 50 * val1; // Evasion rate of physical attacks. Flee + val3 = 10 * val1; // Evasion rate of magical attacks. + val_flag |= 1|2|4; + break; + case SC_WHITEIMPRISON: + status_change_end(bl, SC_BURNING, INVALID_TIMER); + status_change_end(bl, SC_FREEZING, INVALID_TIMER); + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + break; + case SC_FREEZING: + status_change_end(bl, SC_BURNING, INVALID_TIMER); + break; + case SC_READING_SB: + // val2 = sp reduction per second + tick_time = 5000; // [GodLesZ] tick time + break; + case SC_SPHERE_1: + case SC_SPHERE_2: + case SC_SPHERE_3: + case SC_SPHERE_4: + case SC_SPHERE_5: + if( !sd ) + return 0; // Should only work on players. + val4 = tick / 1000; + if( val4 < 1 ) + val4 = 1; + tick_time = 1000; // [GodLesZ] tick time + val_flag |= 1; + break; + case SC_SHAPESHIFT: + switch( val1 ) + { + case 1: val2 = ELE_FIRE; break; + case 2: val2 = ELE_EARTH; break; + case 3: val2 = ELE_WIND; break; + case 4: val2 = ELE_WATER; break; + } + break; + case SC_ELECTRICSHOCKER: + case SC_CRYSTALIZE: + case SC_MEIKYOUSISUI: + val4 = tick / 1000; + if( val4 < 1 ) + val4 = 1; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_CAMOUFLAGE: + val4 = tick/1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_WUGDASH: + val4 = gettick(); //Store time at which you started running. + tick = -1; + break; + case SC__SHADOWFORM: { + struct map_session_data * s_sd = map_id2sd(val2); + if( s_sd ) + s_sd->shadowform_id = bl->id; + val4 = tick / 1000; + val_flag |= 1|2|4; + tick_time = 1000; // [GodLesZ] tick time + } + break; + case SC__STRIPACCESSORY: + if (!sd) + val2 = 20; + break; + case SC__INVISIBILITY: + val2 = 50 - 10 * val1; // ASPD + val3 = 20 * val1; // CRITICAL + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + val_flag |= 1|2; + break; + case SC__ENERVATION: + val2 = 20 + 10 * val1; // ATK Reduction + val_flag |= 1|2; + if( sd ) pc_delspiritball(sd,sd->spiritball,0); + break; + case SC__GROOMY: + val2 = 20 + 10 * val1; //ASPD. Need to confirm if Movement Speed reduction is the same. [Jobbie] + val3 = 20 * val1; //HIT + val_flag |= 1|2|4; + if( sd ) + { // Removes Animals + if( pc_isriding(sd) ) pc_setriding(sd, 0); + if( pc_isridingdragon(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); + if( pc_iswug(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_WUG); + if( pc_isridingwug(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_WUGRIDER); + if( pc_isfalcon(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_FALCON); + if( sd->status.pet_id > 0 ) pet_menu(sd, 3); + if( merc_is_hom_active(sd->hd) ) merc_hom_vaporize(sd,1); + if( sd->md ) merc_delete(sd->md,3); + } + break; + case SC__LAZINESS: + val2 = 10 + 10 * val1; // Cast reduction + val3 = 10 * val1; // Flee Reduction + val_flag |= 1|2|4; + break; + case SC__UNLUCKY: + val2 = 10 * val1; // Crit and Flee2 Reduction + val_flag |= 1|2|4; + break; + case SC__WEAKNESS: + val2 = 10 * val1; + val_flag |= 1|2; + // bypasses coating protection and MADO + sc_start(bl,SC_STRIPWEAPON,100,val1,tick); + sc_start(bl,SC_STRIPSHIELD,100,val1,tick); + break; + break; + case SC_GN_CARTBOOST: + if( val1 < 3 ) + val2 = 50; + else if( val1 < 5 ) + val2 = 75; + else + val2 = 100; + break; + case SC_PROPERTYWALK: + val_flag |= 1|2; + val3 = 0; + break; + case SC_WARMER: + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_FREEZING, INVALID_TIMER); + status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); + break; + case SC_STRIKING: + val1 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1) + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_BLOODSUCKER: + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_VACUUM_EXTREME: + tick -= (status->str / 20) * 1000; + val4 = val3 = tick / 100; + tick_time = 100; // [GodLesZ] tick time + break; + case SC_SWINGDANCE: + val2 = 4 * val1; // Walk speed and aspd reduction. + break; + case SC_SYMPHONYOFLOVER: + case SC_RUSHWINDMILL: + case SC_ECHOSONG: + val2 = 6 * val1; + val2 += val3; //Adding 1% * Lesson Bonus + val2 += (int)(val4*2/10); //Adding 0.2% per JobLevel + break; + case SC_MOONLITSERENADE: + val2 = 10 * val1; + break; + case SC_HARMONIZE: + val2 = 5 + 5 * val1; + break; + case SC_VOICEOFSIREN: + val4 = tick / 2000; + tick_time = 2000; // [GodLesZ] tick time + break; + case SC_DEEPSLEEP: + val4 = tick / 2000; + tick_time = 2000; // [GodLesZ] tick time + break; + case SC_SIRCLEOFNATURE: + val2 = 1 + val1; //SP consume + val3 = 40 * val1; //HP recovery + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_SONGOFMANA: + val3 = 10 + (2 * val2); + val4 = tick/3000; + tick_time = 3000; // [GodLesZ] tick time + break; + case SC_SATURDAYNIGHTFEVER: + if (!val4) val4 = skill_get_time2(status_sc2skill(type),val1); + if (!val4) val4 = 3000; + val3 = tick/val4; + tick_time = val4; // [GodLesZ] tick time + break; + case SC_GLOOMYDAY: + val2 = 20 + 5 * val1; // Flee reduction. + val3 = 15 + 5 * val1; // ASPD reduction. + if( sd && rand()%100 < val1 ){ // (Skill Lv) % + val4 = 1; // reduce walk speed by half. + if( pc_isriding(sd) ) pc_setriding(sd, 0); + if( pc_isridingdragon(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); + } + break; + case SC_GLOOMYDAY_SK: + // Random number between [15 ~ (Voice Lesson Skill Level x 5) + (Skill Level x 10)] %. + val2 = 15 + rand()%( (sd?pc_checkskill(sd, WM_LESSON)*5:0) + val1*10 ); + break; + case SC_SITDOWN_FORCE: + case SC_BANANA_BOMB_SITDOWN: + if( sd && !pc_issit(sd) ) + { + pc_setsit(sd); + skill_sit(sd,1); + clif_sitting(bl); + } + break; + case SC_DANCEWITHWUG: + val3 = (5 * val1) + (1 * val2); //Still need official value. + break; + case SC_LERADSDEW: + val3 = (5 * val1) + (1 * val2); + break; + case SC_MELODYOFSINK: + val3 = (5 * val1) + (1 * val2); + break; + case SC_BEYONDOFWARCRY: + val3 = (5 * val1) + (1 * val2); + break; + case SC_UNLIMITEDHUMMINGVOICE: + { + struct unit_data *ud = unit_bl2ud(bl); + if( ud == NULL ) return 0; + ud->state.skillcastcancel = 0; + val3 = 15 - (2 * val2); + } + break; + case SC_REFLECTDAMAGE: + val2 = 15 + 5 * val1; + val3 = (val1==5)?20:(val1+4)*2; // SP consumption + val4 = tick/10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_FORCEOFVANGUARD: // This is not the official way to handle it but I think we should use it. [pakpil] + val2 = 20 + 12 * (val1 - 1); // Chance + val3 = 5 + (2 * val1); // Max rage counters + tick = -1; //endless duration in the client + tick_time = 6000; // [GodLesZ] tick time + val_flag |= 1|2|4; + break; + case SC_EXEEDBREAK: + val1 *= 150; // 150 * skill_lv + if( sd && sd->inventory_data[sd->equip_index[EQI_HAND_R]] ) { // Chars. + val1 += (sd->inventory_data[sd->equip_index[EQI_HAND_R]]->weight/10 * sd->inventory_data[sd->equip_index[EQI_HAND_R]]->wlv * status_get_lv(bl) / 100); + val1 += 15 * (sd ? sd->status.job_level:50) + 100; + } + else // Mobs + val1 += (400 * status_get_lv(bl) / 100) + (15 * (status_get_lv(bl) / 2)); // About 1138% at mob_lvl 99. Is an aproximation to a standard weapon. [pakpil] + break; + case SC_PRESTIGE: // Bassed on suggested formula in iRO Wiki and some test, still need more test. [pakpil] + val2 = ((status->int_ + status->luk) / 6) + 5; // Chance to evade magic damage. + val1 *= 15; // Defence added + if( sd ) + val1 += 10 * pc_checkskill(sd,CR_DEFENDER); + val_flag |= 1|2; + break; + case SC_BANDING: + tick_time = 5000; // [GodLesZ] tick time + val_flag |= 1; + break; + case SC_SHIELDSPELL_DEF: + case SC_SHIELDSPELL_MDEF: + case SC_SHIELDSPELL_REF: + val_flag |= 1|2; + break; + case SC_MAGNETICFIELD: + val3 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_INSPIRATION: + if( sd ) + { + val2 = (40 * val1) + (3 * sd->status.job_level); // ATK bonus + val3 = (sd->status.job_level / 10) * 2 + 12; // All stat bonus + } + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + status_change_clear_buffs(bl,3); //Remove buffs/debuffs + break; + case SC_SPELLFIST: + case SC_CURSEDCIRCLE_ATKER: + val_flag |= 1|2|4; + break; + case SC_CRESCENTELBOW: + val2 = 94 + val1; + val_flag |= 1|2; + break; + case SC_LIGHTNINGWALK: // [(Job Level / 2) + (40 + 5 * Skill Level)] % + val1 = (sd?sd->status.job_level:2)/2 + 40 + 5 * val1; + val_flag |= 1; + break; + case SC_RAISINGDRAGON: + val3 = tick / 5000; + tick_time = 5000; // [GodLesZ] tick time + break; + case SC_GT_CHANGE: + {// take note there is no def increase as skill desc says. [malufett] + struct block_list * src; + val3 = status->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] % + if( (src = map_id2bl(val2)) ) + val4 = ( 200/status_get_int(src) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] + } + break; + case SC_GT_REVITALIZE: + {// take note there is no vit,aspd,speed increase as skill desc says. [malufett] + struct block_list * src; + val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] % + if( (src = map_id2bl(val2)) ) // the stat def is not shown in the status window and it is process differently + val4 = ( status_get_vit(src)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level] + } + break; + case SC_PYROTECHNIC_OPTION: + val2 = 60; // Watk TODO: Renewal (Atk2) + val3 = 11; // % Increase damage. + val_flag |= 1|2|4; + break; + case SC_HEATER_OPTION: + val2 = 120; // Watk. TODO: Renewal (Atk2) + val3 = 33; // % Increase effects. + val4 = 3; // Change into fire element. + val_flag |= 1|2|4; + break; + case SC_TROPIC_OPTION: + val2 = 180; // Watk. TODO: Renewal (Atk2) + val3 = MG_FIREBOLT; + break; + case SC_AQUAPLAY_OPTION: + val2 = 40; // Matk. TODO: Renewal (Matk1) + val3 = 33; // % Increase effects. + val_flag |= 1|2|4; + break; + case SC_COOLER_OPTION: + val2 = 80; // % Freezing chance + val3 = 33; // % increased damage + val4 = 1; // Change into water elemet + val_flag |= 1|2|4; + break; + case SC_CHILLY_AIR_OPTION: + val2 = 120; // Matk. TODO: Renewal (Matk1) + val3 = MG_COLDBOLT; + val_flag |= 1|2; + break; + case SC_GUST_OPTION: + val2 = 33; + val_flag |= 1|2; + break; + case SC_WIND_STEP_OPTION: + val2 = 50; // % Increase speed and flee. + break; + case SC_BLAST_OPTION: + val2 = 33; + val3 = 4; + val_flag |= 1|2|4; + break; + case SC_WILD_STORM_OPTION: + val2 = MG_LIGHTNINGBOLT; + val_flag |= 1|2; + break; + case SC_PETROLOGY_OPTION: + val2 = 5; + val3 = 33; + val_flag |= 1|2|4; + break; + case SC_CURSED_SOIL_OPTION: + val2 = 10; + val3 = 33; + val4 = 2; + val_flag |= 1|2|4; + break; + case SC_UPHEAVAL_OPTION: + val2 = WZ_EARTHSPIKE; + val_flag |= 1|2; + break; + case SC_CIRCLE_OF_FIRE_OPTION: + val2 = 300; + val_flag |= 1|2; + break; + case SC_FIRE_CLOAK_OPTION: + case SC_WATER_DROP_OPTION: + case SC_WIND_CURTAIN_OPTION: + case SC_STONE_SHIELD_OPTION: + val2 = 20; // Elemental modifier. Not confirmed. + break; + case SC_CIRCLE_OF_FIRE: + case SC_FIRE_CLOAK: + case SC_WATER_DROP: + case SC_WATER_SCREEN: + case SC_WIND_CURTAIN: + case SC_WIND_STEP: + case SC_STONE_SHIELD: + case SC_SOLID_SKIN: + val2 = 10; + tick_time = 2000; // [GodLesZ] tick time + break; + case SC_WATER_BARRIER: + val2 = 40; // Increasement. Mdef1 ??? + val3 = 20; // Reductions. Atk2, Flee1, Matk1 ???? + val_flag |= 1|2|4; + break; + case SC_ZEPHYR: + val2 = 22; // Flee. + break; + case SC_TIDAL_WEAPON: + val2 = 20; // Increase Elemental's attack. + break; + case SC_ROCK_CRUSHER: + case SC_ROCK_CRUSHER_ATK: + case SC_POWER_OF_GAIA: + val2 = 33; + break; + case SC_MELON_BOMB: + case SC_BANANA_BOMB: + val1 = 15; + break; + case SC_STOMACHACHE: + val2 = 8; // SP consume. + val4 = tick / 10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_KYOUGAKU: + val2 = 2*val1 + rand()%val1; + clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); + break; + case SC_KAGEMUSYA: + val3 = val1 * 2; + case SC_IZAYOI: + val2 = tick/1000; + tick_time = 1000; + break; + case SC_ZANGETSU: + if( (status_get_hp(bl)+status_get_sp(bl)) % 2 == 0) + val2 = status_get_lv(bl) / 2 + 50; + else + val2 -= 50; + break; + case SC_GENSOU: + { + int hp = status_get_hp(bl), lv = 5; + short per = 100 / (status_get_max_hp(bl) / hp); + + if( per <= 15 ) + lv = 1; + else if( per <= 30 ) + lv = 2; + else if( per <= 50 ) + lv = 3; + else if( per <= 75 ) + lv = 4; + if( hp % 2 == 0) + status_heal(bl, hp * (6-lv) * 4 / 100, status_get_sp(bl) * (6-lv) * 3 / 100, 1); + else + status_zap(bl, hp * (lv*4) / 100, status_get_sp(bl) * (lv*3) / 100); + } + break; + case SC_ANGRIFFS_MODUS: + val2 = 50 + 20 * val1; //atk bonus + val3 = 40 + 20 * val1; // Flee reduction. + val4 = tick/1000; // hp/sp reduction timer + tick_time = 1000; + break; + case SC_GOLDENE_FERSE: + val2 = 10 + 10*val1; //max hp bonus + val3 = 6 + 4 * val1; // Aspd Bonus + val4 = 2 + 2 * val1; // Chance of holy attack + break; + case SC_OVERED_BOOST: + val2 = 300 + 40*val1; //flee bonus + val3 = 179 + 2*val1; //aspd bonus + break; + case SC_GRANITIC_ARMOR: + val2 = 2*val1; //dmg reduction + val3 = 6*val1; //dmg on status end + break; + case SC_MAGMA_FLOW: + val2 = 3*val1; //activation chance + break; + case SC_PYROCLASTIC: + val2 += 10*val1; //atk bonus + break; + case SC_PARALYSIS: //[Lighta] need real info + val2 = 2*val1; //def reduction + val3 = 500*val1; //varcast augmentation + break; + case SC_PAIN_KILLER: //[Lighta] need real info + val2 = 2*val1; //aspd reduction % + val3 = 2*val1; //dmg reduction % + if(sc->data[SC_PARALYSIS]) + sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration + break; + default: + if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 ) + { //Status change with no calc, no icon, and no skill associated...? + ShowError("UnknownStatusChange [%d]\n", type); + return 0; + } + } + else //Special considerations when loading SC data. + switch( type ) + { + case SC_WEDDING: + case SC_XMAS: + case SC_SUMMER: + clif_changelook(bl,LOOK_WEAPON,0); + clif_changelook(bl,LOOK_SHIELD,0); + clif_changelook(bl,LOOK_BASE,type==SC_WEDDING?JOB_WEDDING:type==SC_XMAS?JOB_XMAS:JOB_SUMMER); + clif_changelook(bl,LOOK_CLOTHES_COLOR,val4); + break; + case SC_KAAHI: + val4 = INVALID_TIMER; + break; + } + + //Those that make you stop attacking/walking.... + switch (type) { + case SC_FREEZE: + case SC_STUN: + case SC_SLEEP: + case SC_STONE: + case SC_DEEPSLEEP: + if (sd && pc_issit(sd)) //Avoid sprite sync problems. + pc_setstand(sd); + case SC_TRICKDEAD: + unit_stop_attack(bl); + status_change_end(bl, SC_DANCING, INVALID_TIMER); + // Cancel cast when get status [LuzZza] + if (battle_config.sc_castcancel&bl->type) + unit_skillcastcancel(bl, 0); + case SC_STOP: + case SC_CONFUSION: + case SC_CLOSECONFINE: + case SC_CLOSECONFINE2: + case SC_ANKLE: + case SC_SPIDERWEB: + case SC_ELECTRICSHOCKER: + case SC_BITE: + case SC_THORNSTRAP: + case SC__MANHOLE: + case SC_CRYSTALIZE: + case SC_WHITEIMPRISON: + case SC_CURSEDCIRCLE_ATKER: + case SC_CURSEDCIRCLE_TARGET: + case SC_FEAR: + case SC_NETHERWORLD: + case SC_MEIKYOUSISUI: + case SC_KYOUGAKU: + case SC_PARALYSIS: + unit_stop_walking(bl,1); + break; + case SC_HIDING: + case SC_CLOAKING: + case SC_CLOAKINGEXCEED: + case SC_CHASEWALK: + case SC_WEIGHT90: + case SC_CAMOUFLAGE: + case SC_VOICEOFSIREN: + unit_stop_attack(bl); + break; + case SC_SILENCE: + if (battle_config.sc_castcancel&bl->type) + unit_skillcastcancel(bl, 0); + break; + } + + // Set option as needed. + opt_flag = 1; + switch(type) + { + //OPT1 + case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break; + case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break; + case SC_STUN: sc->opt1 = OPT1_STUN; break; + case SC_SLEEP: + case SC_DEEPSLEEP: sc->opt1 = OPT1_SLEEP; break; + case SC_BURNING: sc->opt1 = OPT1_BURNING; break; // Burning need this to be showed correctly. [pakpil] + case SC_WHITEIMPRISON: sc->opt1 = OPT1_IMPRISON; break; + case SC_CRYSTALIZE: sc->opt1 = OPT1_CRYSTALIZE; break; + //OPT2 + case SC_POISON: sc->opt2 |= OPT2_POISON; break; + case SC_CURSE: sc->opt2 |= OPT2_CURSE; break; + case SC_SILENCE: sc->opt2 |= OPT2_SILENCE; break; + + case SC_SIGNUMCRUCIS: + sc->opt2 |= OPT2_SIGNUMCRUCIS; + break; + + case SC_BLIND: sc->opt2 |= OPT2_BLIND; break; + case SC_ANGELUS: sc->opt2 |= OPT2_ANGELUS; break; + case SC_BLEEDING: sc->opt2 |= OPT2_BLEEDING; break; + case SC_DPOISON: sc->opt2 |= OPT2_DPOISON; break; + //OPT3 + case SC_TWOHANDQUICKEN: + case SC_ONEHAND: + case SC_SPEARQUICKEN: + case SC_CONCENTRATION: + case SC_MERC_QUICKEN: + sc->opt3 |= OPT3_QUICKEN; + opt_flag = 0; + break; + case SC_MAXOVERTHRUST: + case SC_OVERTHRUST: + case SC_SWOO: //Why does it shares the same opt as Overthrust? Perhaps we'll never know... + sc->opt3 |= OPT3_OVERTHRUST; + opt_flag = 0; + break; + case SC_ENERGYCOAT: + case SC_SKE: + sc->opt3 |= OPT3_ENERGYCOAT; + opt_flag = 0; + break; + case SC_INCATKRATE: + //Simulate Explosion Spirits effect for NPC_POWERUP [Skotlex] + if (bl->type != BL_MOB) { + opt_flag = 0; + break; + } + case SC_EXPLOSIONSPIRITS: + sc->opt3 |= OPT3_EXPLOSIONSPIRITS; + opt_flag = 0; + break; + case SC_STEELBODY: + case SC_SKA: + sc->opt3 |= OPT3_STEELBODY; + opt_flag = 0; + break; + case SC_BLADESTOP: + sc->opt3 |= OPT3_BLADESTOP; + opt_flag = 0; + break; + case SC_AURABLADE: + sc->opt3 |= OPT3_AURABLADE; + opt_flag = 0; + break; + case SC_BERSERK: + opt_flag = 0; +// case SC__BLOODYLUST: + sc->opt3 |= OPT3_BERSERK; + break; +// case ???: // doesn't seem to do anything +// sc->opt3 |= OPT3_LIGHTBLADE; +// opt_flag = 0; +// break; + case SC_DANCING: + if ((val1&0xFFFF) == CG_MOONLIT) + sc->opt3 |= OPT3_MOONLIT; + opt_flag = 0; + break; + case SC_MARIONETTE: + case SC_MARIONETTE2: + sc->opt3 |= OPT3_MARIONETTE; + opt_flag = 0; + break; + case SC_ASSUMPTIO: + sc->opt3 |= OPT3_ASSUMPTIO; + opt_flag = 0; + break; + case SC_WARM: //SG skills [Komurka] + sc->opt3 |= OPT3_WARM; + opt_flag = 0; + break; + case SC_KAITE: + sc->opt3 |= OPT3_KAITE; + opt_flag = 0; + break; + case SC_BUNSINJYUTSU: + sc->opt3 |= OPT3_BUNSIN; + opt_flag = 0; + break; + case SC_SPIRIT: + sc->opt3 |= OPT3_SOULLINK; + opt_flag = 0; + break; + case SC_CHANGEUNDEAD: + sc->opt3 |= OPT3_UNDEAD; + opt_flag = 0; + break; +// case ???: // from DA_CONTRACT (looks like biolab mobs aura) +// sc->opt3 |= OPT3_CONTRACT; +// opt_flag = 0; +// break; + //OPTION + case SC_HIDING: + sc->option |= OPTION_HIDE; + opt_flag = 2; + break; + case SC_CLOAKING: + case SC_CLOAKINGEXCEED: + case SC__INVISIBILITY: + sc->option |= OPTION_CLOAK; + opt_flag = 2; + break; + case SC_CHASEWALK: + sc->option |= OPTION_CHASEWALK|OPTION_CLOAK; + opt_flag = 2; + break; + case SC_SIGHT: + sc->option |= OPTION_SIGHT; + break; + case SC_RUWACH: + sc->option |= OPTION_RUWACH; + break; + case SC_WEDDING: + sc->option |= OPTION_WEDDING; + break; + case SC_XMAS: + sc->option |= OPTION_XMAS; + break; + case SC_SUMMER: + sc->option |= OPTION_SUMMER; + break; + case SC_ORCISH: + sc->option |= OPTION_ORCISH; + break; + case SC_FUSION: + sc->option |= OPTION_FLYING; + break; + default: + opt_flag = 0; + } + + //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. + if(opt_flag) + clif_changeoption(bl); + + if (calc_flag&SCB_DYE) + { //Reset DYE color + if (vd && vd->cloth_color) + { + val4 = vd->cloth_color; + clif_changelook(bl,LOOK_CLOTHES_COLOR,0); + } + calc_flag&=~SCB_DYE; + } + + clif_status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); + + /** + * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. + **/ + if( tick_time ) + tick = tick_time; + + //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here. + if((sce=sc->data[type])) {// reuse old sc + if( sce->timer != INVALID_TIMER ) + delete_timer(sce->timer, status_change_timer); + sc_isnew = false; + } else {// new sc + ++(sc->count); + sce = sc->data[type] = ers_alloc(sc_data_ers, struct status_change_entry); + } + sce->val1 = val1; + sce->val2 = val2; + sce->val3 = val3; + sce->val4 = val4; + if (tick >= 0) + sce->timer = add_timer(gettick() + tick, status_change_timer, bl->id, type); + else + sce->timer = INVALID_TIMER; //Infinite duration + + if (calc_flag) + status_calc_bl(bl,calc_flag); + + if ( sc_isnew && StatusChangeStateTable[type] ) /* non-zero */ + status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],true); + + + if(sd && sd->pd) + pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing switch (type) { - case SC__BLOODYLUST: - case SC_BERSERK: - if (!(sce->val2)) { //don't heal if already set - status_heal(bl, status->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block. - status_set_sp(bl, 0, 0); //Damage all SP - } - sce->val2 = 5 * status->max_hp / 100; - break; - case SC_CHANGE: - status_percent_heal(bl, 100, 100); - break; - case SC_RUN: { - struct unit_data *ud = unit_bl2ud(bl); - if (ud) - ud->state.running = unit_run(bl); - } - break; - case SC_BOSSMAPINFO: - clif_bossmapinfo(sd->fd, map_id2boss(sce->val1), 0); // First Message - break; - case SC_MERC_HPUP: - status_percent_heal(bl, 100, 0); // Recover Full HP - break; - case SC_MERC_SPUP: - status_percent_heal(bl, 0, 100); // Recover Full SP - break; - /** - * Ranger - **/ - case SC_WUGDASH: { - struct unit_data *ud = unit_bl2ud(bl); - if (ud) - ud->state.running = unit_wugdash(bl, sd); - } - break; - case SC_COMBO: - switch (sce->val1) { - case TK_STORMKICK: - clif_skill_nodamage(bl,bl,TK_READYSTORM,1,1); - break; - case TK_DOWNKICK: - clif_skill_nodamage(bl,bl,TK_READYDOWN,1,1); - break; - case TK_TURNKICK: - clif_skill_nodamage(bl,bl,TK_READYTURN,1,1); - break; - case TK_COUNTER: - clif_skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); - break; - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - if (sd) - clif_skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); - break; - case TK_JUMPKICK: - if (sd) - clif_skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); - break; - case MO_TRIPLEATTACK: - if (sd && pc_checkskill(sd, SR_DRAGONCOMBO) > 0) - clif_skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); - break; - case SR_FALLENEMPIRE: - if (sd) { - clif_skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); - clif_skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); - } - break; - } - break; - case SC_RAISINGDRAGON: - sce->val2 = status->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie] - break; - } + case SC__BLOODYLUST: + case SC_BERSERK: + if (!(sce->val2)) { //don't heal if already set + status_heal(bl, status->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block. + status_set_sp(bl, 0, 0); //Damage all SP + } + sce->val2 = 5 * status->max_hp / 100; + break; + case SC_CHANGE: + status_percent_heal(bl, 100, 100); + break; + case SC_RUN: + { + struct unit_data *ud = unit_bl2ud(bl); + if( ud ) + ud->state.running = unit_run(bl); + } + break; + case SC_BOSSMAPINFO: + clif_bossmapinfo(sd->fd, map_id2boss(sce->val1), 0); // First Message + break; + case SC_MERC_HPUP: + status_percent_heal(bl, 100, 0); // Recover Full HP + break; + case SC_MERC_SPUP: + status_percent_heal(bl, 0, 100); // Recover Full SP + break; + /** + * Ranger + **/ + case SC_WUGDASH: + { + struct unit_data *ud = unit_bl2ud(bl); + if( ud ) + ud->state.running = unit_wugdash(bl, sd); + } + break; + case SC_COMBO: + switch (sce->val1) { + case TK_STORMKICK: + clif_skill_nodamage(bl,bl,TK_READYSTORM,1,1); + break; + case TK_DOWNKICK: + clif_skill_nodamage(bl,bl,TK_READYDOWN,1,1); + break; + case TK_TURNKICK: + clif_skill_nodamage(bl,bl,TK_READYTURN,1,1); + break; + case TK_COUNTER: + clif_skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); + break; + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + if (sd) + clif_skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); + break; + case TK_JUMPKICK: + if (sd) + clif_skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); + break; + case MO_TRIPLEATTACK: + if (sd && pc_checkskill(sd, SR_DRAGONCOMBO) > 0) + clif_skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); + break; + case SR_FALLENEMPIRE: + if (sd){ + clif_skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); + clif_skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); + } + break; + } + break; + case SC_RAISINGDRAGON: + sce->val2 = status->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie] + break; + } - if (opt_flag&2 && sd && sd->touching_id) - npc_touchnext_areanpc(sd,false); // run OnTouch_ on next char in range + if( opt_flag&2 && sd && sd->touching_id ) + npc_touchnext_areanpc(sd,false); // run OnTouch_ on next char in range - return 1; + return 1; } /*========================================== @@ -8948,797 +8843,821 @@ int status_change_start(struct block_list *bl,enum sc_type type,int rate,int val * 2 - Do clif * 3 - Do not remove some permanent/time-independent effects *------------------------------------------*/ -int status_change_clear(struct block_list *bl, int type) +int status_change_clear(struct block_list* bl, int type) { - struct status_change *sc; - int i; + struct status_change* sc; + int i; - sc = status_get_sc(bl); + sc = status_get_sc(bl); - if (!sc || !sc->count) - return 0; - - for (i = 0; i < SC_MAX; i++) { - if (!sc->data[i]) - continue; - - if (type == 0) - switch (i) { - //Type 0: PC killed -> Place here statuses that do not dispel on death. - case SC_ELEMENTALCHANGE://Only when its Holy or Dark that it doesn't dispell on death - if (sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK) - break; - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_EDP: - case SC_MELTDOWN: - case SC_XMAS: - case SC_SUMMER: - case SC_NOCHAT: - case SC_FUSION: - case SC_EARTHSCROLL: - case SC_READYSTORM: - case SC_READYDOWN: - case SC_READYCOUNTER: - case SC_READYTURN: - case SC_DODGE: - case SC_JAILED: - case SC_EXPBOOST: - case SC_ITEMBOOST: - case SC_HELLPOWER: - case SC_JEXPBOOST: - case SC_AUTOTRADE: - case SC_WHISTLE: - case SC_ASSNCROS: - case SC_POEMBRAGI: - case SC_APPLEIDUN: - case SC_HUMMING: - case SC_DONTFORGETME: - case SC_FORTUNE: - case SC_SERVICE4U: - case SC_FOOD_STR_CASH: - case SC_FOOD_AGI_CASH: - case SC_FOOD_VIT_CASH: - case SC_FOOD_DEX_CASH: - case SC_FOOD_INT_CASH: - case SC_FOOD_LUK_CASH: - case SC_DEF_RATE: - case SC_MDEF_RATE: - case SC_INCHEALRATE: - case SC_INCFLEE2: - case SC_INCHIT: - case SC_ATKPOTION: - case SC_MATKPOTION: - case SC_S_LIFEPOTION: - case SC_L_LIFEPOTION: - case SC_PUSH_CART: - continue; + if (!sc || !sc->count) + return 0; - } + for(i = 0; i < SC_MAX; i++) + { + if(!sc->data[i]) + continue; - if (type == 3) { - switch (i) { - // TODO: This list may be incomplete - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_NOCHAT: - case SC_PUSH_CART: - continue; - } - } + if(type == 0) + switch (i) + { //Type 0: PC killed -> Place here statuses that do not dispel on death. + case SC_ELEMENTALCHANGE://Only when its Holy or Dark that it doesn't dispell on death + if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK ) + break; + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_EDP: + case SC_MELTDOWN: + case SC_XMAS: + case SC_SUMMER: + case SC_NOCHAT: + case SC_FUSION: + case SC_EARTHSCROLL: + case SC_READYSTORM: + case SC_READYDOWN: + case SC_READYCOUNTER: + case SC_READYTURN: + case SC_DODGE: + case SC_JAILED: + case SC_EXPBOOST: + case SC_ITEMBOOST: + case SC_HELLPOWER: + case SC_JEXPBOOST: + case SC_AUTOTRADE: + case SC_WHISTLE: + case SC_ASSNCROS: + case SC_POEMBRAGI: + case SC_APPLEIDUN: + case SC_HUMMING: + case SC_DONTFORGETME: + case SC_FORTUNE: + case SC_SERVICE4U: + case SC_FOOD_STR_CASH: + case SC_FOOD_AGI_CASH: + case SC_FOOD_VIT_CASH: + case SC_FOOD_DEX_CASH: + case SC_FOOD_INT_CASH: + case SC_FOOD_LUK_CASH: + case SC_DEF_RATE: + case SC_MDEF_RATE: + case SC_INCHEALRATE: + case SC_INCFLEE2: + case SC_INCHIT: + case SC_ATKPOTION: + case SC_MATKPOTION: + case SC_S_LIFEPOTION: + case SC_L_LIFEPOTION: + case SC_PUSH_CART: + continue; - status_change_end(bl, (sc_type)i, INVALID_TIMER); + } + + if( type == 3 ) + { + switch (i) + {// TODO: This list may be incomplete + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_NOCHAT: + case SC_PUSH_CART: + continue; + } + } - if (type == 1 && sc->data[i]) { - //If for some reason status_change_end decides to still keep the status when quitting. [Skotlex] - (sc->count)--; - if (sc->data[i]->timer != INVALID_TIMER) - delete_timer(sc->data[i]->timer, status_change_timer); - ers_free(sc_data_ers, sc->data[i]); - sc->data[i] = NULL; - } - } + status_change_end(bl, (sc_type)i, INVALID_TIMER); - sc->opt1 = 0; - sc->opt2 = 0; - sc->opt3 = 0; - sc->option &= OPTION_MASK; + if( type == 1 && sc->data[i] ) + { //If for some reason status_change_end decides to still keep the status when quitting. [Skotlex] + (sc->count)--; + if (sc->data[i]->timer != INVALID_TIMER) + delete_timer(sc->data[i]->timer, status_change_timer); + ers_free(sc_data_ers, sc->data[i]); + sc->data[i] = NULL; + } + } - if (type == 0 || type == 2) - clif_changeoption(bl); + sc->opt1 = 0; + sc->opt2 = 0; + sc->opt3 = 0; + sc->option &= OPTION_MASK; - return 1; + if( type == 0 || type == 2 ) + clif_changeoption(bl); + + return 1; } /*========================================== * Special condition we want to effectuate, check before ending a status. *------------------------------------------*/ -int status_change_end_(struct block_list *bl, enum sc_type type, int tid, const char *file, int line) +int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) { - struct map_session_data *sd; - struct status_change *sc; - struct status_change_entry *sce; - struct status_data *status; - struct view_data *vd; - int opt_flag=0, calc_flag; - - nullpo_ret(bl); - - sc = status_get_sc(bl); - status = status_get_status_data(bl); - - if (type < 0 || type >= SC_MAX || !sc || !(sce = sc->data[type])) - return 0; - - sd = BL_CAST(BL_PC,bl); - - if (sce->timer != tid && tid != INVALID_TIMER) - return 0; - - if (tid == INVALID_TIMER) { - if (type == SC_ENDURE && sce->val4) - //Do not end infinite endure. - return 0; - if (sce->timer != INVALID_TIMER) //Could be a SC with infinite duration - delete_timer(sce->timer,status_change_timer); - if (sc->opt1) - switch (type) { - //"Ugly workaround" [Skotlex] - //delays status change ending so that a skill that sets opt1 fails to - //trigger when it also removed one - case SC_STONE: - sce->val3 = 0; //Petrify time counter. - case SC_FREEZE: - case SC_STUN: - case SC_SLEEP: - if (sce->val1) { - //Removing the 'level' shouldn't affect anything in the code - //since these SC are not affected by it, and it lets us know - //if we have already delayed this attack or not. - sce->val1 = 0; - sce->timer = add_timer(gettick()+10, status_change_timer, bl->id, type); - return 1; - } - } - } + struct map_session_data *sd; + struct status_change *sc; + struct status_change_entry *sce; + struct status_data *status; + struct view_data *vd; + int opt_flag=0, calc_flag; + + nullpo_ret(bl); + + sc = status_get_sc(bl); + status = status_get_status_data(bl); + + if(type < 0 || type >= SC_MAX || !sc || !(sce = sc->data[type])) + return 0; + + sd = BL_CAST(BL_PC,bl); + + if (sce->timer != tid && tid != INVALID_TIMER) + return 0; + + if (tid == INVALID_TIMER) { + if (type == SC_ENDURE && sce->val4) + //Do not end infinite endure. + return 0; + if (sce->timer != INVALID_TIMER) //Could be a SC with infinite duration + delete_timer(sce->timer,status_change_timer); + if (sc->opt1) + switch (type) { + //"Ugly workaround" [Skotlex] + //delays status change ending so that a skill that sets opt1 fails to + //trigger when it also removed one + case SC_STONE: + sce->val3 = 0; //Petrify time counter. + case SC_FREEZE: + case SC_STUN: + case SC_SLEEP: + if (sce->val1) { + //Removing the 'level' shouldn't affect anything in the code + //since these SC are not affected by it, and it lets us know + //if we have already delayed this attack or not. + sce->val1 = 0; + sce->timer = add_timer(gettick()+10, status_change_timer, bl->id, type); + return 1; + } + } + } - (sc->count)--; + (sc->count)--; - if (StatusChangeStateTable[type]) - status_calc_state(bl,sc,(enum scs_flag) StatusChangeStateTable[type],false); + if ( StatusChangeStateTable[type] ) + status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],false); - sc->data[type] = NULL; + sc->data[type] = NULL; - vd = status_get_viewdata(bl); - calc_flag = StatusChangeFlagTable[type]; - switch (type) { - case SC_GRANITIC_ARMOR: { - int dammage = status->max_hp*sce->val3/100; - if (status->hp < dammage) //to not kill him - dammage = status->hp-1; - status_damage(NULL, bl, dammage,0,0,1); - break; - } + vd = status_get_viewdata(bl); + calc_flag = StatusChangeFlagTable[type]; + switch(type){ + case SC_GRANITIC_ARMOR:{ + int dammage = status->max_hp*sce->val3/100; + if(status->hp < dammage) //to not kill him + dammage = status->hp-1; + status_damage(NULL, bl, dammage,0,0,1); + break; + } case SC_PYROCLASTIC: - if (bl->type == BL_PC) + if(bl->type == BL_PC) skill_break_equip(bl,EQP_WEAPON,10000,BCT_SELF); break; - case SC_WEDDING: - case SC_XMAS: - case SC_SUMMER: - if (!vd) break; - if (sd) { - //Load data from sd->status.* as the stored values could have changed. - //Must remove OPTION to prevent class being rechanged. - sc->option &= type==SC_WEDDING?~OPTION_WEDDING:type==SC_XMAS?~OPTION_XMAS:~OPTION_SUMMER; - clif_changeoption(&sd->bl); - status_set_viewdata(bl, sd->status.class_); - } else { - vd->class_ = sce->val1; - vd->weapon = sce->val2; - vd->shield = sce->val3; - vd->cloth_color = sce->val4; - } - clif_changelook(bl,LOOK_BASE,vd->class_); - clif_changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); - clif_changelook(bl,LOOK_WEAPON,vd->weapon); - clif_changelook(bl,LOOK_SHIELD,vd->shield); - if (sd) clif_skillinfoblock(sd); - break; - case SC_RUN: { - struct unit_data *ud = unit_bl2ud(bl); - bool begin_spurt = true; - if (ud) { - if (!ud->state.running) - begin_spurt = false; - ud->state.running = 0; - if (ud->walktimer != INVALID_TIMER) - unit_stop_walking(bl,1); - } - if (begin_spurt && sce->val1 >= 7 && - DIFF_TICK(gettick(), sce->val4) <= 1000 && - (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0)) - ) - sc_start(bl,SC_SPURT,100,sce->val1,skill_get_time2(status_sc2skill(type), sce->val1)); - } - break; - case SC_AUTOBERSERK: - if (sc->data[SC_PROVOKE] && sc->data[SC_PROVOKE]->val2 == 1) - status_change_end(bl, SC_PROVOKE, INVALID_TIMER); - break; - - case SC_ENDURE: - case SC_DEFENDER: - case SC_REFLECTSHIELD: - case SC_AUTOGUARD: { - struct map_session_data *tsd; - if (bl->type == BL_PC) { - // Clear Status from others - int i; - for (i = 0; i < 5; i++) { - if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) && tsd->sc.data[type]) - status_change_end(&tsd->bl, type, INVALID_TIMER); - } - } else if (bl->type == BL_MER && ((TBL_MER *)bl)->devotion_flag) { - // Clear Status from Master - tsd = ((TBL_MER *)bl)->master; - if (tsd && tsd->sc.data[type]) - status_change_end(&tsd->bl, type, INVALID_TIMER); - } - } - break; - case SC_DEVOTION: { - struct block_list *d_bl = map_id2bl(sce->val1); - if (d_bl) { - if (d_bl->type == BL_PC) - ((TBL_PC *)d_bl)->devotion[sce->val2] = 0; - else if (d_bl->type == BL_MER) - ((TBL_MER *)d_bl)->devotion_flag = 0; - clif_devotion(d_bl, NULL); - } - - status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER); - status_change_end(bl, SC_DEFENDER, INVALID_TIMER); - status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); - status_change_end(bl, SC_ENDURE, INVALID_TIMER); - } - break; - - case SC_BLADESTOP: - if (sce->val4) { - int tid = sce->val4; - struct block_list *tbl = map_id2bl(tid); - struct status_change *tsc = status_get_sc(tbl); - sce->val4 = 0; - if (tbl && tsc && tsc->data[SC_BLADESTOP]) { - tsc->data[SC_BLADESTOP]->val4 = 0; - status_change_end(tbl, SC_BLADESTOP, INVALID_TIMER); - } - clif_bladestop(bl, tid, 0); - } - break; - case SC_DANCING: { - const char *prevfile = "<unknown>"; - int prevline = 0; - struct map_session_data *dsd; - struct status_change_entry *dsc; - struct skill_unit_group *group; - - if (sd) { - if (sd->delunit_prevfile) { - // initially this is NULL, when a character logs in - prevfile = sd->delunit_prevfile; - prevline = sd->delunit_prevline; - } else { - prevfile = "<none>"; - } - sd->delunit_prevfile = file; - sd->delunit_prevline = line; - } - - if (sce->val4 && sce->val4 != BCT_SELF && (dsd=map_id2sd(sce->val4))) { - // end status on partner as well - dsc = dsd->sc.data[SC_DANCING]; - if (dsc) { - - //This will prevent recursive loops. - dsc->val2 = dsc->val4 = 0; - - status_change_end(&dsd->bl, SC_DANCING, INVALID_TIMER); - } - } - - if (sce->val2) { - // erase associated land skill - group = skill_id2group(sce->val2); - - if (group == NULL) { - ShowDebug("status_change_end: SC_DANCING is missing skill unit group (val1=%d, val2=%d, val3=%d, val4=%d, timer=%d, tid=%d, char_id=%d, map=%s, x=%d, y=%d, prev=%s:%d, from=%s:%d). Please report this! (#3504)\n", - sce->val1, sce->val2, sce->val3, sce->val4, sce->timer, tid, - sd ? sd->status.char_id : 0, - mapindex_id2name(map_id2index(bl->m)), bl->x, bl->y, - prevfile, prevline, - file, line); - } - - sce->val2 = 0; - skill_delunitgroup(group); - } - - if ((sce->val1&0xFFFF) == CG_MOONLIT) - clif_status_change(bl,SI_MOONLIT,0,0,0,0,0); - - status_change_end(bl, SC_LONGING, INVALID_TIMER); - } - break; - case SC_NOCHAT: - if (sd && sd->status.manner < 0 && tid != INVALID_TIMER) - sd->status.manner = 0; - if (sd && tid == INVALID_TIMER) { - clif_changestatus(sd,SP_MANNER,sd->status.manner); - clif_updatestatus(sd,SP_MANNER); - } - break; - case SC_SPLASHER: { - struct block_list *src=map_id2bl(sce->val3); - if (src && tid != INVALID_TIMER) - skill_castend_damage_id(src, bl, sce->val2, sce->val1, gettick(), SD_LEVEL); - } - break; - case SC_CLOSECONFINE2: { - struct block_list *src = sce->val2?map_id2bl(sce->val2):NULL; - struct status_change *sc2 = src?status_get_sc(src):NULL; - if (src && sc2 && sc2->data[SC_CLOSECONFINE]) { - //If status was already ended, do nothing. - //Decrease count - if (--(sc2->data[SC_CLOSECONFINE]->val1) <= 0) //No more holds, free him up. - status_change_end(src, SC_CLOSECONFINE, INVALID_TIMER); - } - } - case SC_CLOSECONFINE: - if (sce->val2 > 0) { - //Caster has been unlocked... nearby chars need to be unlocked. - int range = 1 - +skill_get_range2(bl, status_sc2skill(type), sce->val1) - +skill_get_range2(bl, TF_BACKSLIDING, 1); //Since most people use this to escape the hold.... - map_foreachinarea(status_change_timer_sub, - bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sce,type,gettick()); - } - break; - case SC_COMBO: - if (sd) - switch (sce->val1) { - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - clif_skillinfo(sd, MO_EXTREMITYFIST, 0); - break; - case TK_JUMPKICK: - clif_skillinfo(sd, TK_JUMPKICK, 0); - break; - case MO_TRIPLEATTACK: - if (pc_checkskill(sd, SR_DRAGONCOMBO) > 0) - clif_skillinfo(sd, SR_DRAGONCOMBO, 0); - break; - case SR_FALLENEMPIRE: - clif_skillinfo(sd, SR_GATEOFHELL, 0); - clif_skillinfo(sd, SR_TIGERCANNON, 0); - break; - } - break; - - case SC_MARIONETTE: - case SC_MARIONETTE2: /// Marionette target - if (sce->val1) { - // check for partner and end their marionette status as well - enum sc_type type2 = (type == SC_MARIONETTE) ? SC_MARIONETTE2 : SC_MARIONETTE; - struct block_list *pbl = map_id2bl(sce->val1); - struct status_change *sc2 = pbl?status_get_sc(pbl):NULL; - - if (sc2 && sc2->data[type2]) { - sc2->data[type2]->val1 = 0; - status_change_end(pbl, type2, INVALID_TIMER); - } - } - break; - - case SC_BERSERK: - case SC_SATURDAYNIGHTFEVER: - //If val2 is removed, no HP penalty (dispelled?) [Skotlex] - if (status->hp > 100 && sce->val2) - status_set_hp(bl, 100, 0); - if (sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) { - sc->data[SC_ENDURE]->val4 = 0; - status_change_end(bl, SC_ENDURE, INVALID_TIMER); - } - case SC__BLOODYLUST: - sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill_get_time(LK_BERSERK, sce->val1)); - if (type == SC_SATURDAYNIGHTFEVER) //Sit down force of Saturday Night Fever has the duration of only 3 seconds. - sc_start(bl,SC_SITDOWN_FORCE,100,sce->val1,skill_get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1)); - break; - case SC_GOSPEL: - if (sce->val3) { //Clear the group. - struct skill_unit_group *group = skill_id2group(sce->val3); - sce->val3 = 0; - skill_delunitgroup(group); - } - break; - case SC_HERMODE: - if (sce->val3 == BCT_SELF) - skill_clear_unitgroup(bl); - break; - case SC_BASILICA: //Clear the skill area. [Skotlex] - skill_clear_unitgroup(bl); - break; - case SC_TRICKDEAD: - if (vd) vd->dead_sit = 0; - break; - case SC_WARM: - case SC__MANHOLE: - if (sce->val4) { //Clear the group. - struct skill_unit_group *group = skill_id2group(sce->val4); - sce->val4 = 0; - if (group) /* might have been cleared before status ended, e.g. land protector */ - skill_delunitgroup(group); - } - break; - case SC_KAAHI: - //Delete timer if it exists. - if (sce->val4 != INVALID_TIMER) - delete_timer(sce->val4,kaahi_heal_timer); - break; - case SC_JAILED: - if (tid == INVALID_TIMER) - break; - //natural expiration. - if (sd && sd->mapindex == sce->val2) - pc_setpos(sd,(unsigned short)sce->val3,sce->val4&0xFFFF, sce->val4>>16, CLR_TELEPORT); - break; //guess hes not in jail :P - case SC_CHANGE: - if (tid == INVALID_TIMER) - break; - // "lose almost all their HP and SP" on natural expiration. - status_set_hp(bl, 10, 0); - status_set_sp(bl, 10, 0); - break; - case SC_AUTOTRADE: - if (tid == INVALID_TIMER) - break; - // Note: vending/buying is closed by unit_remove_map, no - // need to do it here. - map_quit(sd); - // Because map_quit calls status_change_end with tid -1 - // from here it's not neccesary to continue - return 1; - break; - case SC_STOP: - if (sce->val2) { - struct block_list *tbl = map_id2bl(sce->val2); - sce->val2 = 0; - if (tbl && (sc = status_get_sc(tbl)) && sc->data[SC_STOP] && sc->data[SC_STOP]->val2 == bl->id) - status_change_end(tbl, SC_STOP, INVALID_TIMER); - } - break; - /** - * 3rd Stuff - **/ - case SC_MILLENNIUMSHIELD: - clif_millenniumshield(sd,0); - break; - case SC_HALLUCINATIONWALK: - sc_start(bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill_get_time2(GC_HALLUCINATIONWALK,sce->val1)); - break; - case SC_WHITEIMPRISON: - if (tid == -1) - break; // Terminated by Damage - status_fix_damage(bl,bl,400*sce->val1,clif_damage(bl,bl,gettick(),0,0,400*sce->val1,0,0,0)); - break; - case SC_WUGDASH: { - struct unit_data *ud = unit_bl2ud(bl); - if (ud) { - ud->state.running = 0; - if (ud->walktimer != -1) - unit_stop_walking(bl,1); - } - } - break; - case SC_ADORAMUS: - status_change_end(bl, SC_BLIND, INVALID_TIMER); - break; - case SC__SHADOWFORM: { - struct map_session_data *s_sd = map_id2sd(sce->val2); - if (!s_sd) - break; - s_sd->shadowform_id = 0; - } - break; - case SC_SITDOWN_FORCE: - if (sd && pc_issit(sd)) { - pc_setstand(sd); - clif_standing(bl); - } - break; - case SC_NEUTRALBARRIER_MASTER: - case SC_STEALTHFIELD_MASTER: - if (sce->val2) { - struct skill_unit_group *group = skill_id2group(sce->val2); - sce->val2 = 0; - if (group) /* might have been cleared before status ended, e.g. land protector */ - skill_delunitgroup(group); - } - break; - case SC_BANDING: - if (sce->val4) { - struct skill_unit_group *group = skill_id2group(sce->val4); - sce->val4 = 0; - if (group) /* might have been cleared before status ended, e.g. land protector */ - skill_delunitgroup(group); - } - break; - case SC_CURSEDCIRCLE_ATKER: - if (sce->val2) // used the default area size cause there is a chance the caster could knock back and can't clear the target. - map_foreachinrange(status_change_timer_sub, bl, battle_config.area_size,BL_CHAR, bl, sce, SC_CURSEDCIRCLE_TARGET, gettick()); - break; - case SC_RAISINGDRAGON: - if (sd && sce->val2 && !pc_isdead(sd)) { - int i; - i = min(sd->spiritball,5); - pc_delspiritball(sd, sd->spiritball, 0); - status_change_end(bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER); - while (i > 0) { - pc_addspiritball(sd, skill_get_time(MO_CALLSPIRITS, pc_checkskill(sd,MO_CALLSPIRITS)), 5); - --i; - } - } - break; - case SC_CURSEDCIRCLE_TARGET: { - struct block_list *src = map_id2bl(sce->val2); - struct status_change *sc = status_get_sc(src); - if (sc && sc->data[SC_CURSEDCIRCLE_ATKER] && --(sc->data[SC_CURSEDCIRCLE_ATKER]->val2) == 0) { - status_change_end(src, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER); - clif_bladestop(bl, sce->val2, 0); - } - } - break; - case SC_BLOODSUCKER: - if (sce->val2) { - struct block_list *src = map_id2bl(sce->val2); - if (src) { - struct status_change *sc = status_get_sc(src); - sc->bs_counter--; - } - } - break; - case SC_VACUUM_EXTREME: - if (sc && sc->cant.move > 0) sc->cant.move--; - break; - case SC_KYOUGAKU: - clif_status_load(bl, SI_KYOUGAKU, 0); // Avoid client crash - clif_status_load(bl, SI_ACTIVE_MONSTER_TRANSFORM, 0); - break; - case SC_INTRAVISION: - calc_flag = SCB_ALL;/* required for overlapping */ - break; - } - - opt_flag = 1; - switch (type) { - case SC_STONE: - case SC_FREEZE: - case SC_STUN: - case SC_SLEEP: - case SC_DEEPSLEEP: - case SC_BURNING: - case SC_WHITEIMPRISON: - case SC_CRYSTALIZE: - sc->opt1 = 0; - break; - - case SC_POISON: - case SC_CURSE: - case SC_SILENCE: - case SC_BLIND: - sc->opt2 &= ~(1<<(type-SC_POISON)); - break; - case SC_DPOISON: - sc->opt2 &= ~OPT2_DPOISON; - break; - case SC_SIGNUMCRUCIS: - sc->opt2 &= ~OPT2_SIGNUMCRUCIS; - break; - - case SC_HIDING: - sc->option &= ~OPTION_HIDE; - opt_flag|= 2|4; //Check for warp trigger + AoE trigger - break; - case SC_CLOAKING: - case SC_CLOAKINGEXCEED: - case SC__INVISIBILITY: - sc->option &= ~OPTION_CLOAK; - case SC_CAMOUFLAGE: - opt_flag|= 2; - break; - case SC_CHASEWALK: - sc->option &= ~(OPTION_CHASEWALK|OPTION_CLOAK); - opt_flag|= 2; - break; - case SC_SIGHT: - sc->option &= ~OPTION_SIGHT; - break; - case SC_WEDDING: - sc->option &= ~OPTION_WEDDING; - break; - case SC_XMAS: - sc->option &= ~OPTION_XMAS; - break; - case SC_SUMMER: - sc->option &= ~OPTION_SUMMER; - break; - case SC_ORCISH: - sc->option &= ~OPTION_ORCISH; - break; - case SC_RUWACH: - sc->option &= ~OPTION_RUWACH; - break; - case SC_FUSION: - sc->option &= ~OPTION_FLYING; - break; - //opt3 - case SC_TWOHANDQUICKEN: - case SC_ONEHAND: - case SC_SPEARQUICKEN: - case SC_CONCENTRATION: - case SC_MERC_QUICKEN: - sc->opt3 &= ~OPT3_QUICKEN; - opt_flag = 0; - break; - case SC_OVERTHRUST: - case SC_MAXOVERTHRUST: - case SC_SWOO: - sc->opt3 &= ~OPT3_OVERTHRUST; - if (type == SC_SWOO) - opt_flag = 8; - else - opt_flag = 0; - break; - case SC_ENERGYCOAT: - case SC_SKE: - sc->opt3 &= ~OPT3_ENERGYCOAT; - opt_flag = 0; - break; - case SC_INCATKRATE: //Simulated Explosion spirits effect. - if (bl->type != BL_MOB) { - opt_flag = 0; - break; - } - case SC_EXPLOSIONSPIRITS: - sc->opt3 &= ~OPT3_EXPLOSIONSPIRITS; - opt_flag = 0; - break; - case SC_STEELBODY: - case SC_SKA: - sc->opt3 &= ~OPT3_STEELBODY; - opt_flag = 0; - break; - case SC_BLADESTOP: - sc->opt3 &= ~OPT3_BLADESTOP; - opt_flag = 0; - break; - case SC_AURABLADE: - sc->opt3 &= ~OPT3_AURABLADE; - opt_flag = 0; - break; - case SC_BERSERK: - opt_flag = 0; - // case SC__BLOODYLUST: - sc->opt3 &= ~OPT3_BERSERK; - break; - // case ???: // doesn't seem to do anything - // sc->opt3 &= ~OPT3_LIGHTBLADE; - // opt_flag = 0; - // break; - case SC_DANCING: - if ((sce->val1&0xFFFF) == CG_MOONLIT) - sc->opt3 &= ~OPT3_MOONLIT; - opt_flag = 0; - break; - case SC_MARIONETTE: - case SC_MARIONETTE2: - sc->opt3 &= ~OPT3_MARIONETTE; - opt_flag = 0; - break; - case SC_ASSUMPTIO: - sc->opt3 &= ~OPT3_ASSUMPTIO; - opt_flag = 0; - break; - case SC_WARM: //SG skills [Komurka] - sc->opt3 &= ~OPT3_WARM; - opt_flag = 0; - break; - case SC_KAITE: - sc->opt3 &= ~OPT3_KAITE; - opt_flag = 0; - break; - case SC_BUNSINJYUTSU: - sc->opt3 &= ~OPT3_BUNSIN; - opt_flag = 0; - break; - case SC_SPIRIT: - sc->opt3 &= ~OPT3_SOULLINK; - opt_flag = 0; - break; - case SC_CHANGEUNDEAD: - sc->opt3 &= ~OPT3_UNDEAD; - opt_flag = 0; - break; - // case ???: // from DA_CONTRACT (looks like biolab mobs aura) - // sc->opt3 &= ~OPT3_CONTRACT; - // opt_flag = 0; - // break; - default: - opt_flag = 0; - } - - if (calc_flag&SCB_DYE) { - //Restore DYE color - if (vd && !vd->cloth_color && sce->val4) - clif_changelook(bl,LOOK_CLOTHES_COLOR,sce->val4); - calc_flag&=~SCB_DYE; - } - - //On Aegis, when turning off a status change, first goes the sc packet, then the option packet. - clif_status_change(bl,StatusIconChangeTable[type],0,0,0,0,0); + case SC_WEDDING: + case SC_XMAS: + case SC_SUMMER: + if (!vd) break; + if (sd) + { //Load data from sd->status.* as the stored values could have changed. + //Must remove OPTION to prevent class being rechanged. + sc->option &= type==SC_WEDDING?~OPTION_WEDDING:type==SC_XMAS?~OPTION_XMAS:~OPTION_SUMMER; + clif_changeoption(&sd->bl); + status_set_viewdata(bl, sd->status.class_); + } else { + vd->class_ = sce->val1; + vd->weapon = sce->val2; + vd->shield = sce->val3; + vd->cloth_color = sce->val4; + } + clif_changelook(bl,LOOK_BASE,vd->class_); + clif_changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); + clif_changelook(bl,LOOK_WEAPON,vd->weapon); + clif_changelook(bl,LOOK_SHIELD,vd->shield); + if(sd) clif_skillinfoblock(sd); + break; + case SC_RUN: + { + struct unit_data *ud = unit_bl2ud(bl); + bool begin_spurt = true; + if (ud) { + if(!ud->state.running) + begin_spurt = false; + ud->state.running = 0; + if (ud->walktimer != INVALID_TIMER) + unit_stop_walking(bl,1); + } + if (begin_spurt && sce->val1 >= 7 && + DIFF_TICK(gettick(), sce->val4) <= 1000 && + (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0)) + ) + sc_start(bl,SC_SPURT,100,sce->val1,skill_get_time2(status_sc2skill(type), sce->val1)); + } + break; + case SC_AUTOBERSERK: + if (sc->data[SC_PROVOKE] && sc->data[SC_PROVOKE]->val2 == 1) + status_change_end(bl, SC_PROVOKE, INVALID_TIMER); + break; - if (opt_flag&8) //bugreport:681 - clif_changeoption2(bl); - else if (opt_flag) - clif_changeoption(bl); + case SC_ENDURE: + case SC_DEFENDER: + case SC_REFLECTSHIELD: + case SC_AUTOGUARD: + { + struct map_session_data *tsd; + if( bl->type == BL_PC ) + { // Clear Status from others + int i; + for( i = 0; i < 5; i++ ) + { + if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) && tsd->sc.data[type] ) + status_change_end(&tsd->bl, type, INVALID_TIMER); + } + } + else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag ) + { // Clear Status from Master + tsd = ((TBL_MER*)bl)->master; + if( tsd && tsd->sc.data[type] ) + status_change_end(&tsd->bl, type, INVALID_TIMER); + } + } + break; + case SC_DEVOTION: + { + struct block_list *d_bl = map_id2bl(sce->val1); + if( d_bl ) + { + if( d_bl->type == BL_PC ) + ((TBL_PC*)d_bl)->devotion[sce->val2] = 0; + else if( d_bl->type == BL_MER ) + ((TBL_MER*)d_bl)->devotion_flag = 0; + clif_devotion(d_bl, NULL); + } + + status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER); + status_change_end(bl, SC_DEFENDER, INVALID_TIMER); + status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); + status_change_end(bl, SC_ENDURE, INVALID_TIMER); + } + break; - if (calc_flag) - status_calc_bl(bl,calc_flag); + case SC_BLADESTOP: + if(sce->val4) + { + int tid = sce->val4; + struct block_list *tbl = map_id2bl(tid); + struct status_change *tsc = status_get_sc(tbl); + sce->val4 = 0; + if(tbl && tsc && tsc->data[SC_BLADESTOP]) + { + tsc->data[SC_BLADESTOP]->val4 = 0; + status_change_end(tbl, SC_BLADESTOP, INVALID_TIMER); + } + clif_bladestop(bl, tid, 0); + } + break; + case SC_DANCING: + { + const char* prevfile = "<unknown>"; + int prevline = 0; + struct map_session_data *dsd; + struct status_change_entry *dsc; + struct skill_unit_group *group; + + if( sd ) + { + if( sd->delunit_prevfile ) + {// initially this is NULL, when a character logs in + prevfile = sd->delunit_prevfile; + prevline = sd->delunit_prevline; + } + else + { + prevfile = "<none>"; + } + sd->delunit_prevfile = file; + sd->delunit_prevline = line; + } + + if(sce->val4 && sce->val4 != BCT_SELF && (dsd=map_id2sd(sce->val4))) + {// end status on partner as well + dsc = dsd->sc.data[SC_DANCING]; + if(dsc) { + + //This will prevent recursive loops. + dsc->val2 = dsc->val4 = 0; + + status_change_end(&dsd->bl, SC_DANCING, INVALID_TIMER); + } + } + + if(sce->val2) + {// erase associated land skill + group = skill_id2group(sce->val2); + + if( group == NULL ) + { + ShowDebug("status_change_end: SC_DANCING is missing skill unit group (val1=%d, val2=%d, val3=%d, val4=%d, timer=%d, tid=%d, char_id=%d, map=%s, x=%d, y=%d, prev=%s:%d, from=%s:%d). Please report this! (#3504)\n", + sce->val1, sce->val2, sce->val3, sce->val4, sce->timer, tid, + sd ? sd->status.char_id : 0, + mapindex_id2name(map_id2index(bl->m)), bl->x, bl->y, + prevfile, prevline, + file, line); + } + + sce->val2 = 0; + skill_delunitgroup(group); + } + + if((sce->val1&0xFFFF) == CG_MOONLIT) + clif_status_change(bl,SI_MOONLIT,0,0,0,0,0); + + status_change_end(bl, SC_LONGING, INVALID_TIMER); + } + break; + case SC_NOCHAT: + if (sd && sd->status.manner < 0 && tid != INVALID_TIMER) + sd->status.manner = 0; + if (sd && tid == INVALID_TIMER) + { + clif_changestatus(sd,SP_MANNER,sd->status.manner); + clif_updatestatus(sd,SP_MANNER); + } + break; + case SC_SPLASHER: + { + struct block_list *src=map_id2bl(sce->val3); + if(src && tid != INVALID_TIMER) + skill_castend_damage_id(src, bl, sce->val2, sce->val1, gettick(), SD_LEVEL ); + } + break; + case SC_CLOSECONFINE2: + { + struct block_list *src = sce->val2?map_id2bl(sce->val2):NULL; + struct status_change *sc2 = src?status_get_sc(src):NULL; + if (src && sc2 && sc2->data[SC_CLOSECONFINE]) { + //If status was already ended, do nothing. + //Decrease count + if (--(sc2->data[SC_CLOSECONFINE]->val1) <= 0) //No more holds, free him up. + status_change_end(src, SC_CLOSECONFINE, INVALID_TIMER); + } + } + case SC_CLOSECONFINE: + if (sce->val2 > 0) { + //Caster has been unlocked... nearby chars need to be unlocked. + int range = 1 + +skill_get_range2(bl, status_sc2skill(type), sce->val1) + +skill_get_range2(bl, TF_BACKSLIDING, 1); //Since most people use this to escape the hold.... + map_foreachinarea(status_change_timer_sub, + bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sce,type,gettick()); + } + break; + case SC_COMBO: + if( sd ) + switch (sce->val1) { + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + clif_skillinfo(sd, MO_EXTREMITYFIST, 0); + break; + case TK_JUMPKICK: + clif_skillinfo(sd, TK_JUMPKICK, 0); + break; + case MO_TRIPLEATTACK: + if (pc_checkskill(sd, SR_DRAGONCOMBO) > 0) + clif_skillinfo(sd, SR_DRAGONCOMBO, 0); + break; + case SR_FALLENEMPIRE: + clif_skillinfo(sd, SR_GATEOFHELL, 0); + clif_skillinfo(sd, SR_TIGERCANNON, 0); + break; + } + break; - if (opt_flag&4) //Out of hiding, invoke on place. - skill_unit_move(bl,gettick(),1); + case SC_MARIONETTE: + case SC_MARIONETTE2: /// Marionette target + if (sce->val1) + { // check for partner and end their marionette status as well + enum sc_type type2 = (type == SC_MARIONETTE) ? SC_MARIONETTE2 : SC_MARIONETTE; + struct block_list *pbl = map_id2bl(sce->val1); + struct status_change* sc2 = pbl?status_get_sc(pbl):NULL; + + if (sc2 && sc2->data[type2]) + { + sc2->data[type2]->val1 = 0; + status_change_end(pbl, type2, INVALID_TIMER); + } + } + break; - if (opt_flag&2 && sd && map_getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) - npc_touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event. + case SC_BERSERK: + case SC_SATURDAYNIGHTFEVER: + //If val2 is removed, no HP penalty (dispelled?) [Skotlex] + if (status->hp > 100 && sce->val2) + status_set_hp(bl, 100, 0); + if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) + { + sc->data[SC_ENDURE]->val4 = 0; + status_change_end(bl, SC_ENDURE, INVALID_TIMER); + } + case SC__BLOODYLUST: + sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill_get_time(LK_BERSERK, sce->val1)); + if( type == SC_SATURDAYNIGHTFEVER ) //Sit down force of Saturday Night Fever has the duration of only 3 seconds. + sc_start(bl,SC_SITDOWN_FORCE,100,sce->val1,skill_get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1)); + break; + case SC_GOSPEL: + if (sce->val3) { //Clear the group. + struct skill_unit_group* group = skill_id2group(sce->val3); + sce->val3 = 0; + skill_delunitgroup(group); + } + break; + case SC_HERMODE: + if(sce->val3 == BCT_SELF) + skill_clear_unitgroup(bl); + break; + case SC_BASILICA: //Clear the skill area. [Skotlex] + skill_clear_unitgroup(bl); + break; + case SC_TRICKDEAD: + if (vd) vd->dead_sit = 0; + break; + case SC_WARM: + case SC__MANHOLE: + if (sce->val4) { //Clear the group. + struct skill_unit_group* group = skill_id2group(sce->val4); + sce->val4 = 0; + if( group ) /* might have been cleared before status ended, e.g. land protector */ + skill_delunitgroup(group); + } + break; + case SC_KAAHI: + //Delete timer if it exists. + if (sce->val4 != INVALID_TIMER) + delete_timer(sce->val4,kaahi_heal_timer); + break; + case SC_JAILED: + if(tid == INVALID_TIMER) + break; + //natural expiration. + if(sd && sd->mapindex == sce->val2) + pc_setpos(sd,(unsigned short)sce->val3,sce->val4&0xFFFF, sce->val4>>16, CLR_TELEPORT); + break; //guess hes not in jail :P + case SC_CHANGE: + if (tid == INVALID_TIMER) + break; + // "lose almost all their HP and SP" on natural expiration. + status_set_hp(bl, 10, 0); + status_set_sp(bl, 10, 0); + break; + case SC_AUTOTRADE: + if (tid == INVALID_TIMER) + break; + // Note: vending/buying is closed by unit_remove_map, no + // need to do it here. + map_quit(sd); + // Because map_quit calls status_change_end with tid -1 + // from here it's not neccesary to continue + return 1; + break; + case SC_STOP: + if( sce->val2 ) + { + struct block_list* tbl = map_id2bl(sce->val2); + sce->val2 = 0; + if( tbl && (sc = status_get_sc(tbl)) && sc->data[SC_STOP] && sc->data[SC_STOP]->val2 == bl->id ) + status_change_end(tbl, SC_STOP, INVALID_TIMER); + } + break; + /** + * 3rd Stuff + **/ + case SC_MILLENNIUMSHIELD: + clif_millenniumshield(sd,0); + break; + case SC_HALLUCINATIONWALK: + sc_start(bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill_get_time2(GC_HALLUCINATIONWALK,sce->val1)); + break; + case SC_WHITEIMPRISON: + if( tid == -1 ) + break; // Terminated by Damage + status_fix_damage(bl,bl,400*sce->val1,clif_damage(bl,bl,gettick(),0,0,400*sce->val1,0,0,0)); + break; + case SC_WUGDASH: + { + struct unit_data *ud = unit_bl2ud(bl); + if (ud) { + ud->state.running = 0; + if (ud->walktimer != -1) + unit_stop_walking(bl,1); + } + } + break; + case SC_ADORAMUS: + status_change_end(bl, SC_BLIND, INVALID_TIMER); + break; + case SC__SHADOWFORM: { + struct map_session_data *s_sd = map_id2sd(sce->val2); + if( !s_sd ) + break; + s_sd->shadowform_id = 0; + } + break; + case SC_SITDOWN_FORCE: + if( sd && pc_issit(sd) ) { + pc_setstand(sd); + clif_standing(bl); + } + break; + case SC_NEUTRALBARRIER_MASTER: + case SC_STEALTHFIELD_MASTER: + if( sce->val2 ) { + struct skill_unit_group* group = skill_id2group(sce->val2); + sce->val2 = 0; + if( group ) /* might have been cleared before status ended, e.g. land protector */ + skill_delunitgroup(group); + } + break; + case SC_BANDING: + if(sce->val4) { + struct skill_unit_group *group = skill_id2group(sce->val4); + sce->val4 = 0; + if( group ) /* might have been cleared before status ended, e.g. land protector */ + skill_delunitgroup(group); + } + break; + case SC_CURSEDCIRCLE_ATKER: + if( sce->val2 ) // used the default area size cause there is a chance the caster could knock back and can't clear the target. + map_foreachinrange(status_change_timer_sub, bl, battle_config.area_size,BL_CHAR, bl, sce, SC_CURSEDCIRCLE_TARGET, gettick()); + break; + case SC_RAISINGDRAGON: + if( sd && sce->val2 && !pc_isdead(sd) ) { + int i; + i = min(sd->spiritball,5); + pc_delspiritball(sd, sd->spiritball, 0); + status_change_end(bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER); + while( i > 0 ) { + pc_addspiritball(sd, skill_get_time(MO_CALLSPIRITS, pc_checkskill(sd,MO_CALLSPIRITS)), 5); + --i; + } + } + break; + case SC_CURSEDCIRCLE_TARGET: + { + struct block_list *src = map_id2bl(sce->val2); + struct status_change *sc = status_get_sc(src); + if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] && --(sc->data[SC_CURSEDCIRCLE_ATKER]->val2) == 0 ){ + status_change_end(src, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER); + clif_bladestop(bl, sce->val2, 0); + } + } + break; + case SC_BLOODSUCKER: + if( sce->val2 ){ + struct block_list *src = map_id2bl(sce->val2); + if(src){ + struct status_change *sc = status_get_sc(src); + sc->bs_counter--; + } + } + break; + case SC_VACUUM_EXTREME: + if(sc && sc->cant.move > 0) sc->cant.move--; + break; + case SC_KYOUGAKU: + clif_status_load(bl, SI_KYOUGAKU, 0); // Avoid client crash + clif_status_load(bl, SI_ACTIVE_MONSTER_TRANSFORM, 0); + break; + case SC_INTRAVISION: + calc_flag = SCB_ALL;/* required for overlapping */ + break; + } - ers_free(sc_data_ers, sce); - return 1; + opt_flag = 1; + switch(type){ + case SC_STONE: + case SC_FREEZE: + case SC_STUN: + case SC_SLEEP: + case SC_DEEPSLEEP: + case SC_BURNING: + case SC_WHITEIMPRISON: + case SC_CRYSTALIZE: + sc->opt1 = 0; + break; + + case SC_POISON: + case SC_CURSE: + case SC_SILENCE: + case SC_BLIND: + sc->opt2 &= ~(1<<(type-SC_POISON)); + break; + case SC_DPOISON: + sc->opt2 &= ~OPT2_DPOISON; + break; + case SC_SIGNUMCRUCIS: + sc->opt2 &= ~OPT2_SIGNUMCRUCIS; + break; + + case SC_HIDING: + sc->option &= ~OPTION_HIDE; + opt_flag|= 2|4; //Check for warp trigger + AoE trigger + break; + case SC_CLOAKING: + case SC_CLOAKINGEXCEED: + case SC__INVISIBILITY: + sc->option &= ~OPTION_CLOAK; + case SC_CAMOUFLAGE: + opt_flag|= 2; + break; + case SC_CHASEWALK: + sc->option &= ~(OPTION_CHASEWALK|OPTION_CLOAK); + opt_flag|= 2; + break; + case SC_SIGHT: + sc->option &= ~OPTION_SIGHT; + break; + case SC_WEDDING: + sc->option &= ~OPTION_WEDDING; + break; + case SC_XMAS: + sc->option &= ~OPTION_XMAS; + break; + case SC_SUMMER: + sc->option &= ~OPTION_SUMMER; + break; + case SC_ORCISH: + sc->option &= ~OPTION_ORCISH; + break; + case SC_RUWACH: + sc->option &= ~OPTION_RUWACH; + break; + case SC_FUSION: + sc->option &= ~OPTION_FLYING; + break; + //opt3 + case SC_TWOHANDQUICKEN: + case SC_ONEHAND: + case SC_SPEARQUICKEN: + case SC_CONCENTRATION: + case SC_MERC_QUICKEN: + sc->opt3 &= ~OPT3_QUICKEN; + opt_flag = 0; + break; + case SC_OVERTHRUST: + case SC_MAXOVERTHRUST: + case SC_SWOO: + sc->opt3 &= ~OPT3_OVERTHRUST; + if( type == SC_SWOO ) + opt_flag = 8; + else + opt_flag = 0; + break; + case SC_ENERGYCOAT: + case SC_SKE: + sc->opt3 &= ~OPT3_ENERGYCOAT; + opt_flag = 0; + break; + case SC_INCATKRATE: //Simulated Explosion spirits effect. + if (bl->type != BL_MOB) + { + opt_flag = 0; + break; + } + case SC_EXPLOSIONSPIRITS: + sc->opt3 &= ~OPT3_EXPLOSIONSPIRITS; + opt_flag = 0; + break; + case SC_STEELBODY: + case SC_SKA: + sc->opt3 &= ~OPT3_STEELBODY; + opt_flag = 0; + break; + case SC_BLADESTOP: + sc->opt3 &= ~OPT3_BLADESTOP; + opt_flag = 0; + break; + case SC_AURABLADE: + sc->opt3 &= ~OPT3_AURABLADE; + opt_flag = 0; + break; + case SC_BERSERK: + opt_flag = 0; +// case SC__BLOODYLUST: + sc->opt3 &= ~OPT3_BERSERK; + break; +// case ???: // doesn't seem to do anything +// sc->opt3 &= ~OPT3_LIGHTBLADE; +// opt_flag = 0; +// break; + case SC_DANCING: + if ((sce->val1&0xFFFF) == CG_MOONLIT) + sc->opt3 &= ~OPT3_MOONLIT; + opt_flag = 0; + break; + case SC_MARIONETTE: + case SC_MARIONETTE2: + sc->opt3 &= ~OPT3_MARIONETTE; + opt_flag = 0; + break; + case SC_ASSUMPTIO: + sc->opt3 &= ~OPT3_ASSUMPTIO; + opt_flag = 0; + break; + case SC_WARM: //SG skills [Komurka] + sc->opt3 &= ~OPT3_WARM; + opt_flag = 0; + break; + case SC_KAITE: + sc->opt3 &= ~OPT3_KAITE; + opt_flag = 0; + break; + case SC_BUNSINJYUTSU: + sc->opt3 &= ~OPT3_BUNSIN; + opt_flag = 0; + break; + case SC_SPIRIT: + sc->opt3 &= ~OPT3_SOULLINK; + opt_flag = 0; + break; + case SC_CHANGEUNDEAD: + sc->opt3 &= ~OPT3_UNDEAD; + opt_flag = 0; + break; +// case ???: // from DA_CONTRACT (looks like biolab mobs aura) +// sc->opt3 &= ~OPT3_CONTRACT; +// opt_flag = 0; +// break; + default: + opt_flag = 0; + } + + if (calc_flag&SCB_DYE) + { //Restore DYE color + if (vd && !vd->cloth_color && sce->val4) + clif_changelook(bl,LOOK_CLOTHES_COLOR,sce->val4); + calc_flag&=~SCB_DYE; + } + + //On Aegis, when turning off a status change, first goes the sc packet, then the option packet. + clif_status_change(bl,StatusIconChangeTable[type],0,0,0,0,0); + + if( opt_flag&8 ) //bugreport:681 + clif_changeoption2(bl); + else if(opt_flag) + clif_changeoption(bl); + + if (calc_flag) + status_calc_bl(bl,calc_flag); + + if(opt_flag&4) //Out of hiding, invoke on place. + skill_unit_move(bl,gettick(),1); + + if(opt_flag&2 && sd && map_getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) + npc_touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event. + + ers_free(sc_data_ers, sce); + return 1; } int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *bl; - struct status_change *sc; - struct status_change_entry *sce; - struct status_data *status; - int hp; - - if (!((bl=map_id2bl(id))&& - (sc=status_get_sc(bl)) && - (sce = sc->data[SC_KAAHI]))) - return 0; - - if (sce->val4 != tid) { - ShowError("kaahi_heal_timer: Timer mismatch: %d != %d\n", tid, sce->val4); - sce->val4 = INVALID_TIMER; - return 0; - } - - status=status_get_status_data(bl); - if (!status_charge(bl, 0, sce->val3)) { - sce->val4 = INVALID_TIMER; - return 0; - } - - hp = status->max_hp - status->hp; - if (hp > sce->val2) - hp = sce->val2; - if (hp) - status_heal(bl, hp, 0, 2); - sce->val4 = INVALID_TIMER; - return 1; + struct block_list *bl; + struct status_change *sc; + struct status_change_entry *sce; + struct status_data *status; + int hp; + + if(!((bl=map_id2bl(id))&& + (sc=status_get_sc(bl)) && + (sce = sc->data[SC_KAAHI]))) + return 0; + + if(sce->val4 != tid) { + ShowError("kaahi_heal_timer: Timer mismatch: %d != %d\n", tid, sce->val4); + sce->val4 = INVALID_TIMER; + return 0; + } + + status=status_get_status_data(bl); + if(!status_charge(bl, 0, sce->val3)) { + sce->val4 = INVALID_TIMER; + return 0; + } + + hp = status->max_hp - status->hp; + if (hp > sce->val2) + hp = sce->val2; + if (hp) + status_heal(bl, hp, 0, 2); + sce->val4 = INVALID_TIMER; + return 1; } /*========================================== @@ -9747,1265 +9666,1299 @@ int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) { - enum sc_type type = (sc_type)data; - struct block_list *bl; - struct map_session_data *sd; - struct status_data *status; - struct status_change *sc; - struct status_change_entry *sce; - - bl = map_id2bl(id); - if (!bl) { - ShowDebug("status_change_timer: Null pointer id: %d data: %d\n", id, data); - return 0; - } - sc = status_get_sc(bl); - status = status_get_status_data(bl); - - if (!(sc && (sce = sc->data[type]))) { - ShowDebug("status_change_timer: Null pointer id: %d data: %d bl-type: %d\n", id, data, bl->type); - return 0; - } - - if (sce->timer != tid) { - ShowError("status_change_timer: Mismatch for type %d: %d != %d (bl id %d)\n",type,tid,sce->timer, bl->id); - return 0; - } - - sd = BL_CAST(BL_PC, bl); - - // set the next timer of the sce (don't assume the status still exists) + enum sc_type type = (sc_type)data; + struct block_list *bl; + struct map_session_data *sd; + struct status_data *status; + struct status_change *sc; + struct status_change_entry *sce; + + bl = map_id2bl(id); + if(!bl) + { + ShowDebug("status_change_timer: Null pointer id: %d data: %d\n", id, data); + return 0; + } + sc = status_get_sc(bl); + status = status_get_status_data(bl); + + if(!(sc && (sce = sc->data[type]))) + { + ShowDebug("status_change_timer: Null pointer id: %d data: %d bl-type: %d\n", id, data, bl->type); + return 0; + } + + if( sce->timer != tid ) + { + ShowError("status_change_timer: Mismatch for type %d: %d != %d (bl id %d)\n",type,tid,sce->timer, bl->id); + return 0; + } + + sd = BL_CAST(BL_PC, bl); + +// set the next timer of the sce (don't assume the status still exists) #define sc_timer_next(t,f,i,d) \ - if( (sce=sc->data[type]) ) \ - sce->timer = add_timer(t,f,i,d); \ - else \ - ShowError("status_change_timer: Unexpected NULL status change id: %d data: %d\n", id, data) - - switch (type) { - case SC_MAXIMIZEPOWER: - case SC_CLOAKING: - if (!status_charge(bl, 0, 1)) - break; //Not enough SP to continue. - sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data); - return 0; - - case SC_CHASEWALK: - if (!status_charge(bl, 0, sce->val4)) - break; //Not enough SP to continue. - - if (!sc->data[SC_INCSTR]) { - sc_start(bl, SC_INCSTR,100,1<<(sce->val1-1), - (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration - *skill_get_time2(status_sc2skill(type),sce->val1)); - } - sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data); - return 0; - break; - - case SC_SKA: - if (--(sce->val2)>0) { - sce->val3 = rnd()%100; //Random defense. - sc_timer_next(1000+tick, status_change_timer,bl->id, data); - return 0; - } - break; - - case SC_HIDING: - if (--(sce->val2)>0) { - - if (sce->val2 % sce->val4 == 0 && !status_charge(bl, 0, 1)) - break; //Fail if it's time to substract SP and there isn't. - - sc_timer_next(1000+tick, status_change_timer,bl->id, data); - return 0; - } - break; - - case SC_SIGHT: - case SC_RUWACH: - case SC_SIGHTBLASTER: - map_foreachinrange(status_change_timer_sub, bl, sce->val3, BL_CHAR, bl, sce, type, tick); - - if (--(sce->val2)>0) { - sce->val4 += 250; // use for Shadow Form 2 seconds checking. - sc_timer_next(250+tick, status_change_timer, bl->id, data); - return 0; - } - break; - - case SC_PROVOKE: - if (sce->val2) { //Auto-provoke (it is ended in status_heal) - sc_timer_next(1000*60+tick,status_change_timer, bl->id, data); - return 0; - } - break; - - case SC_STONE: - if (sc->opt1 == OPT1_STONEWAIT && sce->val3) { - sce->val4 = 0; - unit_stop_walking(bl,1); - unit_stop_attack(bl); - sc->opt1 = OPT1_STONE; - clif_changeoption(bl); - sc_timer_next(1000+tick,status_change_timer, bl->id, data); - status_calc_bl(bl, StatusChangeFlagTable[type]); - return 0; - } - if (--(sce->val3) > 0) { - if (++(sce->val4)%5 == 0 && status->hp > status->max_hp/4) - status_percent_damage(NULL, bl, 1, 0, false); - sc_timer_next(1000+tick,status_change_timer, bl->id, data); - return 0; - } - break; - - case SC_POISON: - if (status->hp <= max(status->max_hp>>2, sce->val4)) //Stop damaging after 25% HP left. - break; - case SC_DPOISON: - if (--(sce->val3) > 0) { - if (!sc->data[SC_SLOWPOISON]) { - if (sce->val2 && bl->type == BL_MOB) { - struct block_list *src = map_id2bl(sce->val2); - if (src) - mob_log_damage((TBL_MOB *)bl,src,sce->val4); - } - map_freeblock_lock(); - status_zap(bl, sce->val4, 0); - if (sc->data[type]) { // Check if the status still last ( can be dead since then ). - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - } - map_freeblock_unlock(); - } - return 0; - } - break; - - case SC_TENSIONRELAX: - if (status->max_hp > status->hp && --(sce->val3) > 0) { - sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data); - return 0; - } - break; - - case SC_KNOWLEDGE: - if (!sd) break; - if (bl->m == sd->feel_map[0].m || - bl->m == sd->feel_map[1].m || - bl->m == sd->feel_map[2].m) { - //Timeout will be handled by pc_setpos - sce->timer = INVALID_TIMER; - return 0; - } - break; - - case SC_BLEEDING: - if (--(sce->val4) >= 0) { - int hp = rnd()%600 + 200; - map_freeblock_lock(); - status_fix_damage(NULL, bl, sd||hp<status->hp?hp:status->hp-1, 1); - if (sc->data[type]) { - if (status->hp == 1) { - map_freeblock_unlock(); - break; - } - sc_timer_next(10000 + tick, status_change_timer, bl->id, data); - } - map_freeblock_unlock(); - return 0; - } - break; - - case SC_S_LIFEPOTION: - case SC_L_LIFEPOTION: - if (sd && --(sce->val4) >= 0) { - // val1 < 0 = per max% | val1 > 0 = exact amount - int hp = 0; - if (status->hp < status->max_hp) - hp = (sce->val1 < 0) ? (int)(sd->status.max_hp * -1 * sce->val1 / 100.) : sce->val1 ; - status_heal(bl, hp, 0, 2); - sc_timer_next((sce->val2 * 1000) + tick, status_change_timer, bl->id, data); - return 0; - } - break; - - case SC_BOSSMAPINFO: - if (sd && --(sce->val4) >= 0) { - struct mob_data *boss_md = map_id2boss(sce->val1); - if (boss_md && sd->bl.m == boss_md->bl.m) { - clif_bossmapinfo(sd->fd, boss_md, 1); // Update X - Y on minimap - if (boss_md->bl.prev != NULL) { - sc_timer_next(5000 + tick, status_change_timer, bl->id, data); - return 0; - } - } - } - break; - - case SC_DANCING: { //SP consumption by time of dancing skills - int s = 0; - int sp = 1; - if (--sce->val3 <= 0) - break; - switch (sce->val1&0xFFFF) { - case BD_RICHMANKIM: - case BD_DRUMBATTLEFIELD: - case BD_RINGNIBELUNGEN: - case BD_SIEGFRIED: - case BA_DISSONANCE: - case BA_ASSASSINCROSS: - case DC_UGLYDANCE: - s=3; - break; - case BD_LULLABY: - case BD_ETERNALCHAOS: - case BD_ROKISWEIL: - case DC_FORTUNEKISS: - s=4; - break; - case CG_HERMODE: - case BD_INTOABYSS: - case BA_WHISTLE: - case DC_HUMMING: - case BA_POEMBRAGI: - case DC_SERVICEFORYOU: - s=5; - break; - case BA_APPLEIDUN: -#ifdef RENEWAL - s=5; -#else - s=6; -#endif - break; - case CG_MOONLIT: - //Moonlit's cost is 4sp*skill_lv [Skotlex] - sp= 4*(sce->val1>>16); - //Upkeep is also every 10 secs. - case DC_DONTFORGETME: - s=10; - break; - } - if (s != 0 && sce->val3 % s == 0) { - if (sc->data[SC_LONGING]) - sp*= 3; - if (!status_charge(bl, 0, sp)) - break; - } - sc_timer_next(1000+tick, status_change_timer, bl->id, data); - return 0; - } - break; - case SC__BLOODYLUST: - case SC_BERSERK: - // 5% every 10 seconds [DracoRPG] - if (--(sce->val3) > 0 && status_charge(bl, sce->val2, 0) && status->hp > 100) { - sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data); - return 0; - } - break; - - case SC_NOCHAT: - if (sd) { - sd->status.manner++; - clif_changestatus(sd,SP_MANNER,sd->status.manner); - clif_updatestatus(sd,SP_MANNER); - if (sd->status.manner < 0) { - //Every 60 seconds your manner goes up by 1 until it gets back to 0. - sc_timer_next(60000+tick, status_change_timer, bl->id, data); - return 0; - } - } - break; - - case SC_SPLASHER: - // custom Venom Splasher countdown timer - //if (sce->val4 % 1000 == 0) { - // char timer[10]; - // snprintf (timer, 10, "%d", sce->val4/1000); - // clif_message(bl, timer); - //} - if ((sce->val4 -= 500) > 0) { - sc_timer_next(500 + tick, status_change_timer, bl->id, data); - return 0; - } - break; - - case SC_MARIONETTE: - case SC_MARIONETTE2: { - struct block_list *pbl = map_id2bl(sce->val1); - if (pbl && check_distance_bl(bl, pbl, 7)) { - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - } - break; - - case SC_GOSPEL: - if (sce->val4 == BCT_SELF && --(sce->val2) > 0) { - int hp, sp; - hp = (sce->val1 > 5) ? 45 : 30; - sp = (sce->val1 > 5) ? 35 : 20; - if (!status_charge(bl, hp, sp)) - break; - sc_timer_next(10000+tick, status_change_timer, bl->id, data); - return 0; - } - break; - - case SC_JAILED: - if (sce->val1 == INT_MAX || --(sce->val1) > 0) { - sc_timer_next(60000+tick, status_change_timer, bl->id,data); - return 0; - } - break; - - case SC_BLIND: - if (sc->data[SC_FOGWALL]) { - //Blind lasts forever while you are standing on the fog. - sc_timer_next(5000+tick, status_change_timer, bl->id, data); - return 0; - } - break; - case SC_ABUNDANCE: - if (--(sce->val4) > 0) { - status_heal(bl,0,60,0); - sc_timer_next(10000+tick, status_change_timer, bl->id, data); - } - break; - - case SC_PYREXIA: - if (--(sce->val4) >= 0) { - map_freeblock_lock(); - clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,0,0); - status_fix_damage(NULL,bl,100,0); - if (sc->data[type]) { - sc_timer_next(3000+tick,status_change_timer,bl->id,data); - } - map_freeblock_unlock(); - return 0; - } - break; - - case SC_LEECHESEND: - if (--(sce->val4) >= 0) { - int damage = status->max_hp/100; // {Target VIT x (New Poison Research Skill Level - 3)} + (Target HP/100) - damage += status->vit * (sce->val1 - 3); - unit_skillcastcancel(bl,2); - map_freeblock_lock(); - status_damage(bl, bl, damage, 0, clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,0,0), 1); - if (sc->data[type]) { - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - } - map_freeblock_unlock(); - return 0; - } - break; - - case SC_MAGICMUSHROOM: - if (--(sce->val4) >= 0) { - bool flag = 0; - int damage = status->max_hp * 3 / 100; - if (status->hp <= damage) - damage = status->hp - 1; // Cannot Kill - - if (damage > 0) { // 3% Damage each 4 seconds - map_freeblock_lock(); - status_zap(bl,damage,0); - flag = !sc->data[type]; // Killed? Should not - map_freeblock_unlock(); - } - - if (!flag) { // Random Skill Cast - if (sd && !pc_issit(sd)) { //can't cast if sit - int mushroom_skillid = 0, i; - unit_stop_attack(bl); - unit_skillcastcancel(bl,1); - do { - i = rnd() % MAX_SKILL_MAGICMUSHROOM_DB; - mushroom_skillid = skill_magicmushroom_db[i].skillid; - } while (mushroom_skillid == 0); - - switch (skill_get_casttype(mushroom_skillid)) { // Magic Mushroom skills are buffs or area damage - case CAST_GROUND: - skill_castend_pos2(bl,bl->x,bl->y,mushroom_skillid,1,tick,0); - break; - case CAST_NODAMAGE: - skill_castend_nodamage_id(bl,bl,mushroom_skillid,1,tick,0); - break; - case CAST_DAMAGE: - skill_castend_damage_id(bl,bl,mushroom_skillid,1,tick,0); - break; - } - } - - clif_emotion(bl,E_HEH); - sc_timer_next(4000+tick,status_change_timer,bl->id,data); - } - return 0; - } - break; - - case SC_TOXIN: - if (--(sce->val4) >= 0) { - //Damage is every 10 seconds including 3%sp drain. - map_freeblock_lock(); - clif_damage(bl,bl,tick,status_get_amotion(bl),1,1,0,0,0); - status_damage(NULL, bl, 1, status->max_sp * 3 / 100, 0, 0); //cancel dmg only if cancelable - if (sc->data[type]) { - sc_timer_next(10000 + tick, status_change_timer, bl->id, data); - } - map_freeblock_unlock(); - return 0; - } - break; + if( (sce=sc->data[type]) ) \ + sce->timer = add_timer(t,f,i,d); \ + else \ + ShowError("status_change_timer: Unexpected NULL status change id: %d data: %d\n", id, data) + + switch(type) + { + case SC_MAXIMIZEPOWER: + case SC_CLOAKING: + if(!status_charge(bl, 0, 1)) + break; //Not enough SP to continue. + sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data); + return 0; + + case SC_CHASEWALK: + if(!status_charge(bl, 0, sce->val4)) + break; //Not enough SP to continue. + + if (!sc->data[SC_INCSTR]) { + sc_start(bl, SC_INCSTR,100,1<<(sce->val1-1), + (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration + *skill_get_time2(status_sc2skill(type),sce->val1)); + } + sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data); + return 0; + break; + + case SC_SKA: + if(--(sce->val2)>0){ + sce->val3 = rnd()%100; //Random defense. + sc_timer_next(1000+tick, status_change_timer,bl->id, data); + return 0; + } + break; - case SC_OBLIVIONCURSE: - if (--(sce->val4) >= 0) { - clif_emotion(bl,E_WHAT); - sc_timer_next(3000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC_HIDING: + if(--(sce->val2)>0){ - case SC_WEAPONBLOCKING: - if (--(sce->val4) >= 0) { - if (!status_charge(bl,0,3)) - break; - sc_timer_next(3000+tick,status_change_timer,bl->id,data); - return 0; - } - break; + if(sce->val2 % sce->val4 == 0 && !status_charge(bl, 0, 1)) + break; //Fail if it's time to substract SP and there isn't. - case SC_CLOAKINGEXCEED: - if (!status_charge(bl,0,10-sce->val1)) - break; - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - - case SC_RENOVATIO: - if (--(sce->val4) >= 0) { - int heal = status->max_hp * 3 / 100; - if (sc && sc->data[SC_AKAITSUKI] && heal) - heal = ~heal + 1; - status_heal(bl, heal, 0, 2); - sc_timer_next(5000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + sc_timer_next(1000+tick, status_change_timer,bl->id, data); + return 0; + } + break; - case SC_BURNING: - if (--(sce->val4) >= 0) { - struct block_list *src = map_id2bl(sce->val3); - int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP) + case SC_SIGHT: + case SC_RUWACH: + case SC_SIGHTBLASTER: + map_foreachinrange( status_change_timer_sub, bl, sce->val3, BL_CHAR, bl, sce, type, tick); - map_freeblock_lock(); - clif_damage(bl,bl,tick,0,0,damage,1,9,0); //damage is like endure effect with no walk delay - status_damage(src, bl, damage, 0, 0, 1); + if( --(sce->val2)>0 ){ + sce->val4 += 250; // use for Shadow Form 2 seconds checking. + sc_timer_next(250+tick, status_change_timer, bl->id, data); + return 0; + } + break; - if (sc->data[type]) { // Target still lives. [LimitLine] - sc_timer_next(2000 + tick, status_change_timer, bl->id, data); - } - map_freeblock_unlock(); - return 0; - } - break; + case SC_PROVOKE: + if(sce->val2) { //Auto-provoke (it is ended in status_heal) + sc_timer_next(1000*60+tick,status_change_timer, bl->id, data ); + return 0; + } + break; + + case SC_STONE: + if(sc->opt1 == OPT1_STONEWAIT && sce->val3) { + sce->val4 = 0; + unit_stop_walking(bl,1); + unit_stop_attack(bl); + sc->opt1 = OPT1_STONE; + clif_changeoption(bl); + sc_timer_next(1000+tick,status_change_timer, bl->id, data ); + status_calc_bl(bl, StatusChangeFlagTable[type]); + return 0; + } + if(--(sce->val3) > 0) { + if(++(sce->val4)%5 == 0 && status->hp > status->max_hp/4) + status_percent_damage(NULL, bl, 1, 0, false); + sc_timer_next(1000+tick,status_change_timer, bl->id, data ); + return 0; + } + break; - case SC_FEAR: - if (--(sce->val4) >= 0) { - if (sce->val2 > 0) - sce->val2--; - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC_POISON: + if(status->hp <= max(status->max_hp>>2, sce->val4)) //Stop damaging after 25% HP left. + break; + case SC_DPOISON: + if (--(sce->val3) > 0) { + if (!sc->data[SC_SLOWPOISON]) { + if( sce->val2 && bl->type == BL_MOB ) { + struct block_list* src = map_id2bl(sce->val2); + if( src ) + mob_log_damage((TBL_MOB*)bl,src,sce->val4); + } + map_freeblock_lock(); + status_zap(bl, sce->val4, 0); + if (sc->data[type]) { // Check if the status still last ( can be dead since then ). + sc_timer_next(1000 + tick, status_change_timer, bl->id, data ); + } + map_freeblock_unlock(); + } + return 0; + } + break; - case SC_SPHERE_1: - case SC_SPHERE_2: - case SC_SPHERE_3: - case SC_SPHERE_4: - case SC_SPHERE_5: - if (--(sce->val4) >= 0) { - if (!status_charge(bl, 0, 1)) - break; - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC_TENSIONRELAX: + if(status->max_hp > status->hp && --(sce->val3) > 0){ + sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data); + return 0; + } + break; + + case SC_KNOWLEDGE: + if (!sd) break; + if(bl->m == sd->feel_map[0].m || + bl->m == sd->feel_map[1].m || + bl->m == sd->feel_map[2].m) + { //Timeout will be handled by pc_setpos + sce->timer = INVALID_TIMER; + return 0; + } + break; + + case SC_BLEEDING: + if (--(sce->val4) >= 0) { + int hp = rnd()%600 + 200; + map_freeblock_lock(); + status_fix_damage(NULL, bl, sd||hp<status->hp?hp:status->hp-1, 1); + if( sc->data[type] ) { + if( status->hp == 1 ) { + map_freeblock_unlock(); + break; + } + sc_timer_next(10000 + tick, status_change_timer, bl->id, data); + } + map_freeblock_unlock(); + return 0; + } + break; + + case SC_S_LIFEPOTION: + case SC_L_LIFEPOTION: + if( sd && --(sce->val4) >= 0 ) + { + // val1 < 0 = per max% | val1 > 0 = exact amount + int hp = 0; + if( status->hp < status->max_hp ) + hp = (sce->val1 < 0) ? (int)(sd->status.max_hp * -1 * sce->val1 / 100.) : sce->val1 ; + status_heal(bl, hp, 0, 2); + sc_timer_next((sce->val2 * 1000) + tick, status_change_timer, bl->id, data); + return 0; + } + break; + + case SC_BOSSMAPINFO: + if( sd && --(sce->val4) >= 0 ) + { + struct mob_data *boss_md = map_id2boss(sce->val1); + if( boss_md && sd->bl.m == boss_md->bl.m ) + { + clif_bossmapinfo(sd->fd, boss_md, 1); // Update X - Y on minimap + if (boss_md->bl.prev != NULL) { + sc_timer_next(5000 + tick, status_change_timer, bl->id, data); + return 0; + } + } + } + break; - case SC_READING_SB: - if (!status_charge(bl, 0, sce->val2)) { - int i; - for (i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) // Also remove stored spell as well. - status_change_end(bl, (sc_type)i, INVALID_TIMER); - break; - } - sc_timer_next(5000 + tick, status_change_timer, bl->id, data); - return 0; + case SC_DANCING: //SP consumption by time of dancing skills + { + int s = 0; + int sp = 1; + if (--sce->val3 <= 0) + break; + switch(sce->val1&0xFFFF){ + case BD_RICHMANKIM: + case BD_DRUMBATTLEFIELD: + case BD_RINGNIBELUNGEN: + case BD_SIEGFRIED: + case BA_DISSONANCE: + case BA_ASSASSINCROSS: + case DC_UGLYDANCE: + s=3; + break; + case BD_LULLABY: + case BD_ETERNALCHAOS: + case BD_ROKISWEIL: + case DC_FORTUNEKISS: + s=4; + break; + case CG_HERMODE: + case BD_INTOABYSS: + case BA_WHISTLE: + case DC_HUMMING: + case BA_POEMBRAGI: + case DC_SERVICEFORYOU: + s=5; + break; + case BA_APPLEIDUN: + #ifdef RENEWAL + s=5; + #else + s=6; + #endif + break; + case CG_MOONLIT: + //Moonlit's cost is 4sp*skill_lv [Skotlex] + sp= 4*(sce->val1>>16); + //Upkeep is also every 10 secs. + case DC_DONTFORGETME: + s=10; + break; + } + if( s != 0 && sce->val3 % s == 0 ) + { + if (sc->data[SC_LONGING]) + sp*= 3; + if (!status_charge(bl, 0, sp)) + break; + } + sc_timer_next(1000+tick, status_change_timer, bl->id, data); + return 0; + } + break; + case SC__BLOODYLUST: + case SC_BERSERK: + // 5% every 10 seconds [DracoRPG] + if( --( sce->val3 ) > 0 && status_charge(bl, sce->val2, 0) && status->hp > 100 ) + { + sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data); + return 0; + } + break; + + case SC_NOCHAT: + if(sd){ + sd->status.manner++; + clif_changestatus(sd,SP_MANNER,sd->status.manner); + clif_updatestatus(sd,SP_MANNER); + if (sd->status.manner < 0) + { //Every 60 seconds your manner goes up by 1 until it gets back to 0. + sc_timer_next(60000+tick, status_change_timer, bl->id, data); + return 0; + } + } + break; + + case SC_SPLASHER: + // custom Venom Splasher countdown timer + //if (sce->val4 % 1000 == 0) { + // char timer[10]; + // snprintf (timer, 10, "%d", sce->val4/1000); + // clif_message(bl, timer); + //} + if((sce->val4 -= 500) > 0) { + sc_timer_next(500 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + + case SC_MARIONETTE: + case SC_MARIONETTE2: + { + struct block_list *pbl = map_id2bl(sce->val1); + if( pbl && check_distance_bl(bl, pbl, 7) ) + { + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + } + break; + + case SC_GOSPEL: + if(sce->val4 == BCT_SELF && --(sce->val2) > 0) + { + int hp, sp; + hp = (sce->val1 > 5) ? 45 : 30; + sp = (sce->val1 > 5) ? 35 : 20; + if(!status_charge(bl, hp, sp)) + break; + sc_timer_next(10000+tick, status_change_timer, bl->id, data); + return 0; + } + break; - case SC_ELECTRICSHOCKER: - if (--(sce->val4) >= 0) { - status_charge(bl, 0, status->max_sp / 100 * sce->val1); - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC_JAILED: + if(sce->val1 == INT_MAX || --(sce->val1) > 0) + { + sc_timer_next(60000+tick, status_change_timer, bl->id,data); + return 0; + } + break; - case SC_CAMOUFLAGE: - if (--(sce->val4) > 0) { - status_charge(bl,0,7 - sce->val1); - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC_BLIND: + if(sc->data[SC_FOGWALL]) + { //Blind lasts forever while you are standing on the fog. + sc_timer_next(5000+tick, status_change_timer, bl->id, data); + return 0; + } + break; + case SC_ABUNDANCE: + if(--(sce->val4) > 0) { + status_heal(bl,0,60,0); + sc_timer_next(10000+tick, status_change_timer, bl->id, data); + } + break; + + case SC_PYREXIA: + if( --(sce->val4) >= 0 ) { + map_freeblock_lock(); + clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,0,0); + status_fix_damage(NULL,bl,100,0); + if( sc->data[type] ) { + sc_timer_next(3000+tick,status_change_timer,bl->id,data); + } + map_freeblock_unlock(); + return 0; + } + break; + + case SC_LEECHESEND: + if( --(sce->val4) >= 0 ) { + int damage = status->max_hp/100; // {Target VIT x (New Poison Research Skill Level - 3)} + (Target HP/100) + damage += status->vit * (sce->val1 - 3); + unit_skillcastcancel(bl,2); + map_freeblock_lock(); + status_damage(bl, bl, damage, 0, clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,0,0), 1); + if( sc->data[type] ) { + sc_timer_next(1000 + tick, status_change_timer, bl->id, data ); + } + map_freeblock_unlock(); + return 0; + } + break; + + case SC_MAGICMUSHROOM: + if( --(sce->val4) >= 0 ) { + bool flag = 0; + int damage = status->max_hp * 3 / 100; + if( status->hp <= damage ) + damage = status->hp - 1; // Cannot Kill + + if( damage > 0 ) { // 3% Damage each 4 seconds + map_freeblock_lock(); + status_zap(bl,damage,0); + flag = !sc->data[type]; // Killed? Should not + map_freeblock_unlock(); + } - case SC__REPRODUCE: - if (!status_charge(bl, 0, 1)) - break; - sc_timer_next(1000+tick, status_change_timer, bl->id, data); - return 0; - - case SC__SHADOWFORM: - if (--(sce->val4) >= 0) { - if (!status_charge(bl, 0, sce->val1 - (sce->val1 - 1))) - break; - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + if( !flag ) { // Random Skill Cast + if (sd && !pc_issit(sd)) { //can't cast if sit + int mushroom_skillid = 0, i; + unit_stop_attack(bl); + unit_skillcastcancel(bl,1); + do { + i = rnd() % MAX_SKILL_MAGICMUSHROOM_DB; + mushroom_skillid = skill_magicmushroom_db[i].skillid; + } + while( mushroom_skillid == 0 ); + + switch( skill_get_casttype(mushroom_skillid) ) { // Magic Mushroom skills are buffs or area damage + case CAST_GROUND: + skill_castend_pos2(bl,bl->x,bl->y,mushroom_skillid,1,tick,0); + break; + case CAST_NODAMAGE: + skill_castend_nodamage_id(bl,bl,mushroom_skillid,1,tick,0); + break; + case CAST_DAMAGE: + skill_castend_damage_id(bl,bl,mushroom_skillid,1,tick,0); + break; + } + } + + clif_emotion(bl,E_HEH); + sc_timer_next(4000+tick,status_change_timer,bl->id,data); + } + return 0; + } + break; + + case SC_TOXIN: + if( --(sce->val4) >= 0 ) + { //Damage is every 10 seconds including 3%sp drain. + map_freeblock_lock(); + clif_damage(bl,bl,tick,status_get_amotion(bl),1,1,0,0,0); + status_damage(NULL, bl, 1, status->max_sp * 3 / 100, 0, 0); //cancel dmg only if cancelable + if( sc->data[type] ) { + sc_timer_next(10000 + tick, status_change_timer, bl->id, data ); + } + map_freeblock_unlock(); + return 0; + } + break; + + case SC_OBLIVIONCURSE: + if( --(sce->val4) >= 0 ) + { + clif_emotion(bl,E_WHAT); + sc_timer_next(3000 + tick, status_change_timer, bl->id, data ); + return 0; + } + break; - case SC__INVISIBILITY: - if (--(sce->val4) >= 0) { - if (!status_charge(bl, 0, (status->sp * 6 - sce->val1) / 100)) // 6% - skilllv. - break; - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC_WEAPONBLOCKING: + if( --(sce->val4) >= 0 ) + { + if( !status_charge(bl,0,3) ) + break; + sc_timer_next(3000+tick,status_change_timer,bl->id,data); + return 0; + } + break; - case SC_STRIKING: - if (--(sce->val4) >= 0) { - if (!status_charge(bl,0, sce->val1)) - break; - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; - case SC_VACUUM_EXTREME: - if (--(sce->val4) >= 0) { - if (!unit_is_walking(bl) && !sce->val2) { - sc->cant.move++; - sce->val2 = 1; - } - sc_timer_next(100 + tick, status_change_timer, bl->id, data); - return 0; - } - break; - case SC_BLOODSUCKER: - if (--(sce->val4) >= 0) { - struct block_list *src = map_id2bl(sce->val2); - int damage; - if (!src || (src && (status_isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12))) - break; - map_freeblock_lock(); - damage = 200 + 100 * sce->val1 + status_get_int(src); - status_damage(src, bl, damage, 0, clif_damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,0,0), 1); - unit_skillcastcancel(bl,1); - if (sc->data[type]) { - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - } - map_freeblock_unlock(); - status_heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level - return 0; - } - break; + case SC_CLOAKINGEXCEED: + if(!status_charge(bl,0,10-sce->val1)) + break; + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + + case SC_RENOVATIO: + if( --(sce->val4) >= 0 ) + { + int heal = status->max_hp * 3 / 100; + if( sc && sc->data[SC_AKAITSUKI] && heal ) + heal = ~heal + 1; + status_heal(bl, heal, 0, 2); + sc_timer_next(5000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; - case SC_VOICEOFSIREN: - if (--(sce->val4) >= 0) { - clif_emotion(bl,E_LV); - sc_timer_next(2000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC_BURNING: + if( --(sce->val4) >= 0 ) + { + struct block_list *src = map_id2bl(sce->val3); + int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP) - case SC_DEEPSLEEP: - if (--(sce->val4) >= 0) { - // Recovers 1% HP/SP every 2 seconds. - status_heal(bl, status->max_hp / 100, status->max_sp / 100, 2); - sc_timer_next(2000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + map_freeblock_lock(); + clif_damage(bl,bl,tick,0,0,damage,1,9,0); //damage is like endure effect with no walk delay + status_damage(src, bl, damage, 0, 0, 1); - case SC_SIRCLEOFNATURE: - if (--(sce->val4) >= 0) { - if (!status_charge(bl,0,sce->val2)) - break; - status_heal(bl, sce->val3, 0, 1); - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + if( sc->data[type]){ // Target still lives. [LimitLine] + sc_timer_next(2000 + tick, status_change_timer, bl->id, data); + } + map_freeblock_unlock(); + return 0; + } + break; + + case SC_FEAR: + if( --(sce->val4) >= 0 ) + { + if( sce->val2 > 0 ) + sce->val2--; + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + + case SC_SPHERE_1: + case SC_SPHERE_2: + case SC_SPHERE_3: + case SC_SPHERE_4: + case SC_SPHERE_5: + if( --(sce->val4) >= 0 ) + { + if( !status_charge(bl, 0, 1) ) + break; + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; - case SC_SONGOFMANA: - if (--(sce->val4) >= 0) { - status_heal(bl,0,sce->val3,3); - sc_timer_next(3000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC_READING_SB: + if( !status_charge(bl, 0, sce->val2) ){ + int i; + for(i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) // Also remove stored spell as well. + status_change_end(bl, (sc_type)i, INVALID_TIMER); + break; + } + sc_timer_next(5000 + tick, status_change_timer, bl->id, data); + return 0; + + case SC_ELECTRICSHOCKER: + if( --(sce->val4) >= 0 ) + { + status_charge(bl, 0, status->max_sp / 100 * sce->val1 ); + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + case SC_CAMOUFLAGE: + if(--(sce->val4) > 0){ + status_charge(bl,0,7 - sce->val1); + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; - case SC_SATURDAYNIGHTFEVER: - // 1% HP/SP drain every val4 seconds [Jobbie] - if (--(sce->val3) >= 0) { - int hp = status->hp / 100; - int sp = status->sp / 100; - if (!status_charge(bl, hp, sp)) - break; - sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC__REPRODUCE: + if(!status_charge(bl, 0, 1)) + break; + sc_timer_next(1000+tick, status_change_timer, bl->id, data); + return 0; - case SC_CRYSTALIZE: - if (--(sce->val4) >= 0) { - // Drains 2% of HP and 1% of SP every seconds. - if (bl->type != BL_MOB) // doesn't work on mobs - status_charge(bl, status->max_hp * 2 / 100, status->max_sp / 100); - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC__SHADOWFORM: + if( --(sce->val4) >= 0 ) + { + if( !status_charge(bl, 0, sce->val1 - (sce->val1 - 1)) ) + break; + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; - case SC_FORCEOFVANGUARD: - if (!status_charge(bl,0,20)) - break; - sc_timer_next(6000 + tick, status_change_timer, bl->id, data); - return 0; + case SC__INVISIBILITY: + if( --(sce->val4) >= 0 ) + { + if( !status_charge(bl, 0, (status->sp * 6 - sce->val1) / 100) )// 6% - skilllv. + break; + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; - case SC_BANDING: - if (status_charge(bl, 0, 7 - sce->val1)) { - if (sd) pc_banding(sd, sce->val1); - sc_timer_next(5000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC_STRIKING: + if( --(sce->val4) >= 0 ) + { + if( !status_charge(bl,0, sce->val1 ) ) + break; + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + case SC_VACUUM_EXTREME: + if( --(sce->val4) >= 0 ){ + if( !unit_is_walking(bl) && !sce->val2 ){ + sc->cant.move++; + sce->val2 = 1; + } + sc_timer_next(100 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + case SC_BLOODSUCKER: + if( --(sce->val4) >= 0 ) { + struct block_list *src = map_id2bl(sce->val2); + int damage; + if( !src || (src && (status_isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12)) ) + break; + map_freeblock_lock(); + damage = 200 + 100 * sce->val1 + status_get_int(src); + status_damage(src, bl, damage, 0, clif_damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,0,0), 1); + unit_skillcastcancel(bl,1); + if ( sc->data[type] ) { + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + } + map_freeblock_unlock(); + status_heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level + return 0; + } + break; + + case SC_VOICEOFSIREN: + if( --(sce->val4) >= 0 ) + { + clif_emotion(bl,E_LV); + sc_timer_next(2000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + + case SC_DEEPSLEEP: + if( --(sce->val4) >= 0 ) + { // Recovers 1% HP/SP every 2 seconds. + status_heal(bl, status->max_hp / 100, status->max_sp / 100, 2); + sc_timer_next(2000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; - case SC_REFLECTDAMAGE: - if (--(sce->val4) >= 0) { - if (!status_charge(bl,0,sce->val3)) - break; - sc_timer_next(10000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + case SC_SIRCLEOFNATURE: + if( --(sce->val4) >= 0 ) + { + if( !status_charge(bl,0,sce->val2) ) + break; + status_heal(bl, sce->val3, 0, 1); + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + + case SC_SONGOFMANA: + if( --(sce->val4) >= 0 ) + { + status_heal(bl,0,sce->val3,3); + sc_timer_next(3000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; - case SC_OVERHEAT_LIMITPOINT: - if (--(sce->val1) > 0) { // Cooling - sc_timer_next(30000 + tick, status_change_timer, bl->id, data); - } - break; - case SC_OVERHEAT: { - int damage = status->max_hp / 100; // Suggestion 1% each second - if (damage >= status->hp) damage = status->hp - 1; // Do not kill, just keep you with 1 hp minimum - map_freeblock_lock(); - status_fix_damage(NULL,bl,damage,clif_damage(bl,bl,tick,0,0,damage,0,0,0)); - if (sc->data[type]) { - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - } - map_freeblock_unlock(); - } - break; + case SC_SATURDAYNIGHTFEVER: + // 1% HP/SP drain every val4 seconds [Jobbie] + if( --(sce->val3) >= 0 ) + { + int hp = status->hp / 100; + int sp = status->sp / 100; + if( !status_charge(bl, hp, sp) ) + break; + sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data); + return 0; + } + break; + + case SC_CRYSTALIZE: + if( --(sce->val4) >= 0 ) + { // Drains 2% of HP and 1% of SP every seconds. + if( bl->type != BL_MOB) // doesn't work on mobs + status_charge(bl, status->max_hp * 2 / 100, status->max_sp / 100); + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; - case SC_MAGNETICFIELD: { - if (--(sce->val3) <= 0) - break; // Time out - if (sce->val2 == bl->id) { - if (!status_charge(bl,0,14 + (3 * sce->val1))) - break; // No more SP status should end, and in the next second will end for the other affected players - } else { - struct block_list *src = map_id2bl(sce->val2); - struct status_change *ssc; - if (!src || (ssc = status_get_sc(src)) == NULL || !ssc->data[SC_MAGNETICFIELD]) - break; // Source no more under Magnetic Field - } - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - } - break; + case SC_FORCEOFVANGUARD: + if( !status_charge(bl,0,20) ) + break; + sc_timer_next(6000 + tick, status_change_timer, bl->id, data); + return 0; + + case SC_BANDING: + if( status_charge(bl, 0, 7 - sce->val1) ) + { + if( sd ) pc_banding(sd, sce->val1); + sc_timer_next(5000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; - case SC_INSPIRATION: - if (--(sce->val4) >= 0) { - int hp = status->max_hp * (7-sce->val1) / 100; - int sp = status->max_sp * (9-sce->val1) / 100; + case SC_REFLECTDAMAGE: + if( --(sce->val4) >= 0 ) { + if( !status_charge(bl,0,sce->val3) ) + break; + sc_timer_next(10000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; - if (!status_charge(bl,hp,sp)) break; + case SC_OVERHEAT_LIMITPOINT: + if( --(sce->val1) > 0 ) { // Cooling + sc_timer_next(30000 + tick, status_change_timer, bl->id, data); + } + break; + + case SC_OVERHEAT: + { + int damage = status->max_hp / 100; // Suggestion 1% each second + if( damage >= status->hp ) damage = status->hp - 1; // Do not kill, just keep you with 1 hp minimum + map_freeblock_lock(); + status_fix_damage(NULL,bl,damage,clif_damage(bl,bl,tick,0,0,damage,0,0,0)); + if( sc->data[type] ) { + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + } + map_freeblock_unlock(); + } + break; + + case SC_MAGNETICFIELD: + { + if( --(sce->val3) <= 0 ) + break; // Time out + if( sce->val2 == bl->id ) + { + if( !status_charge(bl,0,14 + (3 * sce->val1)) ) + break; // No more SP status should end, and in the next second will end for the other affected players + } + else + { + struct block_list *src = map_id2bl(sce->val2); + struct status_change *ssc; + if( !src || (ssc = status_get_sc(src)) == NULL || !ssc->data[SC_MAGNETICFIELD] ) + break; // Source no more under Magnetic Field + } + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + } + break; - sc_timer_next(1000+tick,status_change_timer,bl->id, data); - return 0; - } - break; + case SC_INSPIRATION: + if(--(sce->val4) >= 0) + { + int hp = status->max_hp * (7-sce->val1) / 100; + int sp = status->max_sp * (9-sce->val1) / 100; - case SC_RAISINGDRAGON: - // 1% every 5 seconds [Jobbie] - if (--(sce->val3)>0 && status_charge(bl, sce->val2, 0)) { - if (!sc->data[type]) return 0; - sc_timer_next(5000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; + if( !status_charge(bl,hp,sp) ) break; - case SC_CIRCLE_OF_FIRE: - case SC_FIRE_CLOAK: - case SC_WATER_DROP: - case SC_WATER_SCREEN: - case SC_WIND_CURTAIN: - case SC_WIND_STEP: - case SC_STONE_SHIELD: - case SC_SOLID_SKIN: - if (!status_charge(bl,0,sce->val2)) { - struct block_list *s_bl = battle_get_master(bl); - if (s_bl) - status_change_end(s_bl,type+1,INVALID_TIMER); - status_change_end(bl,type,INVALID_TIMER); - break; - } - sc_timer_next(2000 + tick, status_change_timer, bl->id, data); - return 0; - - case SC_STOMACHACHE: - if (--(sce->val4) > 0) { - status_charge(bl,0,sce->val2); // Reduce 8 every 10 seconds. - if (sd && !pc_issit(sd)) { // Force to sit every 10 seconds. - pc_stop_walking(sd,1|4); - pc_stop_attack(sd); - pc_setsit(sd); - clif_sitting(bl); - } - sc_timer_next(10000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; - case SC_LEADERSHIP: - case SC_GLORYWOUNDS: - case SC_SOULCOLD: - case SC_HAWKEYES: - /* they only end by status_change_end */ - sc_timer_next(600000 + tick, status_change_timer, bl->id, data); - return 0; - case SC_MEIKYOUSISUI: - if (--(sce->val4) > 0) { - status_heal(bl, status->max_hp * (sce->val1+1) / 100, status->max_sp * sce->val1 / 100, 0); - sc_timer_next(1000 + tick, status_change_timer, bl->id, data); - return 0; - } - break; - case SC_IZAYOI: - case SC_KAGEMUSYA: - if (--(sce->val2) > 0) { - if (!status_charge(bl, 0, 1)) break; - sc_timer_next(1000+tick, status_change_timer, bl->id, data); - return 0; - } - break; - case SC_ANGRIFFS_MODUS: - if (--(sce->val4) >= 0) { //drain hp/sp - if (!status_charge(bl,100,20)) break; - sc_timer_next(1000+tick,status_change_timer,bl->id, data); - return 0; - } - break; - } + sc_timer_next(1000+tick,status_change_timer,bl->id, data); + return 0; + } + break; + + case SC_RAISINGDRAGON: + // 1% every 5 seconds [Jobbie] + if( --(sce->val3)>0 && status_charge(bl, sce->val2, 0) ) + { + if( !sc->data[type] ) return 0; + sc_timer_next(5000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + + case SC_CIRCLE_OF_FIRE: + case SC_FIRE_CLOAK: + case SC_WATER_DROP: + case SC_WATER_SCREEN: + case SC_WIND_CURTAIN: + case SC_WIND_STEP: + case SC_STONE_SHIELD: + case SC_SOLID_SKIN: + if( !status_charge(bl,0,sce->val2) ){ + struct block_list *s_bl = battle_get_master(bl); + if( s_bl ) + status_change_end(s_bl,type+1,INVALID_TIMER); + status_change_end(bl,type,INVALID_TIMER); + break; + } + sc_timer_next(2000 + tick, status_change_timer, bl->id, data); + return 0; + + case SC_STOMACHACHE: + if( --(sce->val4) > 0 ){ + status_charge(bl,0,sce->val2); // Reduce 8 every 10 seconds. + if( sd && !pc_issit(sd) ) // Force to sit every 10 seconds. + { + pc_stop_walking(sd,1|4); + pc_stop_attack(sd); + pc_setsit(sd); + clif_sitting(bl); + } + sc_timer_next(10000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + case SC_LEADERSHIP: + case SC_GLORYWOUNDS: + case SC_SOULCOLD: + case SC_HAWKEYES: + /* they only end by status_change_end */ + sc_timer_next(600000 + tick, status_change_timer, bl->id, data); + return 0; + case SC_MEIKYOUSISUI: + if( --(sce->val4) > 0 ){ + status_heal(bl, status->max_hp * (sce->val1+1) / 100, status->max_sp * sce->val1 / 100, 0); + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + case SC_IZAYOI: + case SC_KAGEMUSYA: + if( --(sce->val2) > 0 ){ + if(!status_charge(bl, 0, 1)) break; + sc_timer_next(1000+tick, status_change_timer, bl->id, data); + return 0; + } + break; + case SC_ANGRIFFS_MODUS: + if(--(sce->val4) >= 0) { //drain hp/sp + if( !status_charge(bl,100,20) ) break; + sc_timer_next(1000+tick,status_change_timer,bl->id, data); + return 0; + } + break; + } - // default for all non-handled control paths is to end the status - return status_change_end(bl,type,tid); + // default for all non-handled control paths is to end the status + return status_change_end( bl,type,tid ); #undef sc_timer_next } /*========================================== * Foreach iteration of repetitive status *------------------------------------------*/ -int status_change_timer_sub(struct block_list *bl, va_list ap) +int status_change_timer_sub(struct block_list* bl, va_list ap) { - struct status_change *tsc; - - struct block_list *src = va_arg(ap,struct block_list *); - struct status_change_entry *sce = va_arg(ap,struct status_change_entry *); - enum sc_type type = (sc_type)va_arg(ap,int); //gcc: enum args get promoted to int - unsigned int tick = va_arg(ap,unsigned int); - - if (status_isdead(bl)) - return 0; - - tsc = status_get_sc(bl); - - switch (type) { - case SC_SIGHT: /* Reveal hidden ennemy on 3*3 range */ - if (tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking - rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10) // [100 - (Skill Level x 10)] % - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - case SC_CONCENTRATE: - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); - status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); - break; - case SC_RUWACH: /* Reveal hidden target and deal little dammages if ennemy */ - if (tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || - tsc->data[SC_CAMOUFLAGE] || tsc->data[SC_CLOAKINGEXCEED] || - tsc->data[SC__INVISIBILITY])) { - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); - if (battle_check_target(src, bl, BCT_ENEMY) > 0) - skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,1,tick,0); - } - if (tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking - rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10) // [100 - (Skill Level x 10)] % - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - break; - case SC_SIGHTBLASTER: - if (battle_check_target(src, bl, BCT_ENEMY) > 0 && - status_check_skilluse(src, bl, WZ_SIGHTBLASTER, 2)) { - skill_attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,1,tick,0); - if (sce) sce->val2 = 0; //This signals it to end. - } - break; - case SC_CLOSECONFINE: - //Lock char has released the hold on everyone... - if (tsc && tsc->data[SC_CLOSECONFINE2] && tsc->data[SC_CLOSECONFINE2]->val2 == src->id) { - tsc->data[SC_CLOSECONFINE2]->val2 = 0; - status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); - } - break; - case SC_CURSEDCIRCLE_TARGET: - if (tsc && tsc->data[SC_CURSEDCIRCLE_TARGET] && tsc->data[SC_CURSEDCIRCLE_TARGET]->val2 == src->id) { - clif_bladestop(bl, tsc->data[SC_CURSEDCIRCLE_TARGET]->val2, 0); - status_change_end(bl, type, INVALID_TIMER); - } - break; - } - return 0; + struct status_change* tsc; + + struct block_list* src = va_arg(ap,struct block_list*); + struct status_change_entry* sce = va_arg(ap,struct status_change_entry*); + enum sc_type type = (sc_type)va_arg(ap,int); //gcc: enum args get promoted to int + unsigned int tick = va_arg(ap,unsigned int); + + if (status_isdead(bl)) + return 0; + + tsc = status_get_sc(bl); + + switch( type ) { + case SC_SIGHT: /* Reveal hidden ennemy on 3*3 range */ + if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking + rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] % + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + case SC_CONCENTRATE: + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); + status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); + break; + case SC_RUWACH: /* Reveal hidden target and deal little dammages if ennemy */ + if (tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || + tsc->data[SC_CAMOUFLAGE] || tsc->data[SC_CLOAKINGEXCEED] || + tsc->data[SC__INVISIBILITY])) { + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); + if(battle_check_target( src, bl, BCT_ENEMY ) > 0) + skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,1,tick,0); + } + if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking + rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] % + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + break; + case SC_SIGHTBLASTER: + if (battle_check_target( src, bl, BCT_ENEMY ) > 0 && + status_check_skilluse(src, bl, WZ_SIGHTBLASTER, 2)) + { + skill_attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,1,tick,0); + if (sce) sce->val2 = 0; //This signals it to end. + } + break; + case SC_CLOSECONFINE: + //Lock char has released the hold on everyone... + if (tsc && tsc->data[SC_CLOSECONFINE2] && tsc->data[SC_CLOSECONFINE2]->val2 == src->id) { + tsc->data[SC_CLOSECONFINE2]->val2 = 0; + status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); + } + break; + case SC_CURSEDCIRCLE_TARGET: + if( tsc && tsc->data[SC_CURSEDCIRCLE_TARGET] && tsc->data[SC_CURSEDCIRCLE_TARGET]->val2 == src->id ) { + clif_bladestop(bl, tsc->data[SC_CURSEDCIRCLE_TARGET]->val2, 0); + status_change_end(bl, type, INVALID_TIMER); + } + break; + } + return 0; } /*========================================== * Clears buffs/debuffs of a character. * type&1 -> buffs, type&2 -> debuffs - * type&4 -> especific debuffs(implemented with refresh) *------------------------------------------*/ -int status_change_clear_buffs(struct block_list *bl, int type) +int status_change_clear_buffs (struct block_list* bl, int type) { - int i; - struct status_change *sc= status_get_sc(bl); - - if (!sc || !sc->count) - return 0; - - if (type&6) //Debuffs - for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) - status_change_end(bl, (sc_type)i, INVALID_TIMER); - - for (i = SC_COMMON_MAX+1; i < SC_MAX; i++) { - if (!sc->data[i]) - continue; - - switch (i) { - //Stuff that cannot be removed - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_COMBO: - case SC_SMA: - case SC_DANCING: - case SC_LEADERSHIP: - case SC_GLORYWOUNDS: - case SC_SOULCOLD: - case SC_HAWKEYES: - case SC_GUILDAURA: - case SC_SAFETYWALL: - case SC_PNEUMA: - case SC_NOCHAT: - case SC_JAILED: - case SC_ANKLE: - case SC_BLADESTOP: - case SC_CP_WEAPON: - case SC_CP_SHIELD: - case SC_CP_ARMOR: - case SC_CP_HELM: - case SC_STRFOOD: - case SC_AGIFOOD: - case SC_VITFOOD: - case SC_INTFOOD: - case SC_DEXFOOD: - case SC_LUKFOOD: - case SC_HITFOOD: - case SC_FLEEFOOD: - case SC_BATKFOOD: - case SC_WATKFOOD: - case SC_MATKFOOD: - case SC_FOOD_STR_CASH: - case SC_FOOD_AGI_CASH: - case SC_FOOD_VIT_CASH: - case SC_FOOD_DEX_CASH: - case SC_FOOD_INT_CASH: - case SC_FOOD_LUK_CASH: - case SC_EXPBOOST: - case SC_JEXPBOOST: - case SC_ITEMBOOST: - case SC_ELECTRICSHOCKER: - case SC__MANHOLE: - case SC_GIANTGROWTH: - case SC_MILLENNIUMSHIELD: - case SC_REFRESH: - case SC_STONEHARDSKIN: - case SC_VITALITYACTIVATION: - case SC_FIGHTINGSPIRIT: - case SC_ABUNDANCE: - case SC_CURSEDCIRCLE_ATKER: - case SC_CURSEDCIRCLE_TARGET: - continue; - - //Debuffs that can be removed. - case SC_DEEPSLEEP: + int i; + struct status_change *sc= status_get_sc(bl); + + if (!sc || !sc->count) + return 0; + + if (type&2) //Debuffs + for( i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++ ) + { + status_change_end(bl, (sc_type)i, INVALID_TIMER); + } + + for( i = SC_COMMON_MAX+1; i < SC_MAX; i++ ) + { + if(!sc->data[i]) + continue; + + switch (i) { + //Stuff that cannot be removed + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_COMBO: + case SC_SMA: + case SC_DANCING: + case SC_LEADERSHIP: + case SC_GLORYWOUNDS: + case SC_SOULCOLD: + case SC_HAWKEYES: + case SC_GUILDAURA: + case SC_SAFETYWALL: + case SC_PNEUMA: + case SC_NOCHAT: + case SC_JAILED: + case SC_ANKLE: + case SC_BLADESTOP: + case SC_CP_WEAPON: + case SC_CP_SHIELD: + case SC_CP_ARMOR: + case SC_CP_HELM: + case SC_STRFOOD: + case SC_AGIFOOD: + case SC_VITFOOD: + case SC_INTFOOD: + case SC_DEXFOOD: + case SC_LUKFOOD: + case SC_HITFOOD: + case SC_FLEEFOOD: + case SC_BATKFOOD: + case SC_WATKFOOD: + case SC_MATKFOOD: + case SC_FOOD_STR_CASH: + case SC_FOOD_AGI_CASH: + case SC_FOOD_VIT_CASH: + case SC_FOOD_DEX_CASH: + case SC_FOOD_INT_CASH: + case SC_FOOD_LUK_CASH: + case SC_EXPBOOST: + case SC_JEXPBOOST: + case SC_ITEMBOOST: + case SC_ELECTRICSHOCKER: + case SC__MANHOLE: + case SC_GIANTGROWTH: + case SC_MILLENNIUMSHIELD: + case SC_REFRESH: + case SC_STONEHARDSKIN: + case SC_VITALITYACTIVATION: + case SC_FIGHTINGSPIRIT: + case SC_ABUNDANCE: + case SC_CURSEDCIRCLE_ATKER: + case SC_CURSEDCIRCLE_TARGET: + continue; + + //Debuffs that can be removed. + case SC_HALLUCINATION: + case SC_QUAGMIRE: + case SC_SIGNUMCRUCIS: + case SC_DECREASEAGI: + case SC_SLOWDOWN: + case SC_MINDBREAKER: + case SC_WINKCHARM: + case SC_STOP: + case SC_ORCISH: + case SC_STRIPWEAPON: + case SC_STRIPSHIELD: + case SC_STRIPARMOR: + case SC_STRIPHELM: + case SC_BITE: + case SC_ADORAMUS: + case SC_VACUUM_EXTREME: case SC_BURNING: + case SC_FEAR: + case SC_MAGNETICFIELD: + case SC_NETHERWORLD: + if (!(type&2)) + continue; + break; + //The rest are buffs that can be removed. + case SC__BLOODYLUST: + case SC_BERSERK: + case SC_SATURDAYNIGHTFEVER: + if (!(type&1)) + continue; + sc->data[i]->val2 = 0; + break; + default: + if (!(type&1)) + continue; + break; + } + status_change_end(bl, (sc_type)i, INVALID_TIMER); + } + return 0; +} + +int status_change_spread( struct block_list *src, struct block_list *bl ) { + int i, flag = 0; + struct status_change *sc = status_get_sc(src); + const struct TimerData *timer; + unsigned int tick; + struct status_change_data data; + + if( !sc || !sc->count ) + return 0; + + tick = gettick(); + + for( i = SC_COMMON_MIN; i < SC_MAX; i++ ) { + if( !sc->data[i] || i == SC_COMMON_MAX ) + continue; + + switch( i ) { + //Debuffs that can be spreaded. + // NOTE: We'll add/delte SCs when we are able to confirm it. + case SC_CURSE: + case SC_SILENCE: + case SC_CONFUSION: + case SC_BLIND: + case SC_NOCHAT: + case SC_HALLUCINATION: + case SC_SIGNUMCRUCIS: + case SC_DECREASEAGI: + case SC_SLOWDOWN: + case SC_MINDBREAKER: + case SC_WINKCHARM: + case SC_STOP: + case SC_ORCISH: + //case SC_STRIPWEAPON://Omg I got infected and had the urge to strip myself physically. + //case SC_STRIPSHIELD://No this is stupid and shouldnt be spreadable at all. + //case SC_STRIPARMOR:// Disabled until I can confirm if it does or not. [Rytech] + //case SC_STRIPHELM: + //case SC__STRIPACCESSORY: + case SC_BITE: case SC_FREEZING: - case SC_CRYSTALIZE: - case SC_TOXIN: - case SC_PARALYSE: case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: case SC_DEATHHURT: + case SC_PARALYSE: + if( sc->data[i]->timer != INVALID_TIMER ) { + timer = get_timer(sc->data[i]->timer); + if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0) + continue; + data.tick = DIFF_TICK(timer->tick,tick); + } else + data.tick = INVALID_TIMER; + break; + // Special cases + case SC_POISON: + case SC_DPOISON: + data.tick = sc->data[i]->val3 * 1000; + break; + case SC_FEAR: + case SC_LEECHESEND: + data.tick = sc->data[i]->val4 * 1000; + break; + case SC_BURNING: + data.tick = sc->data[i]->val4 * 2000; + break; case SC_PYREXIA: case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - case SC_MARSHOFABYSS: - case SC_MANDRAGORA: - if(!(type&4)) + data.tick = sc->data[i]->val4 * 3000; + break; + case SC_MAGICMUSHROOM: + data.tick = sc->data[i]->val4 * 4000; + break; + case SC_TOXIN: + case SC_BLEEDING: + data.tick = sc->data[i]->val4 * 10000; + break; + default: continue; break; - case SC_HALLUCINATION: - case SC_QUAGMIRE: - case SC_SIGNUMCRUCIS: - case SC_DECREASEAGI: - case SC_SLOWDOWN: - case SC_MINDBREAKER: - case SC_WINKCHARM: - case SC_STOP: - case SC_ORCISH: - case SC_STRIPWEAPON: - case SC_STRIPSHIELD: - case SC_STRIPARMOR: - case SC_STRIPHELM: - case SC_BITE: - case SC_ADORAMUS: - case SC_VACUUM_EXTREME: - case SC_FEAR: - case SC_MAGNETICFIELD: - case SC_NETHERWORLD: - if (!(type&2)) - continue; - break; - //The rest are buffs that can be removed. - case SC__BLOODYLUST: - case SC_BERSERK: - case SC_SATURDAYNIGHTFEVER: - if (!(type&1)) - continue; - sc->data[i]->val2 = 0; - break; - default: - if (!(type&1)) - continue; - break; - } - status_change_end(bl, (sc_type)i, INVALID_TIMER); - } - return 0; -} - -int status_change_spread(struct block_list *src, struct block_list *bl) -{ - int i, flag = 0; - struct status_change *sc = status_get_sc(src); - const struct TimerData *timer; - unsigned int tick; - struct status_change_data data; - - if (!sc || !sc->count) - return 0; - - tick = gettick(); - - for (i = SC_COMMON_MIN; i < SC_MAX; i++) { - if (!sc->data[i] || i == SC_COMMON_MAX) - continue; - - switch (i) { - //Debuffs that can be spreaded. - // NOTE: We'll add/delte SCs when we are able to confirm it. - case SC_CURSE: - case SC_SILENCE: - case SC_CONFUSION: - case SC_BLIND: - case SC_NOCHAT: - case SC_HALLUCINATION: - case SC_SIGNUMCRUCIS: - case SC_DECREASEAGI: - case SC_SLOWDOWN: - case SC_MINDBREAKER: - case SC_WINKCHARM: - case SC_STOP: - case SC_ORCISH: - //case SC_STRIPWEAPON://Omg I got infected and had the urge to strip myself physically. - //case SC_STRIPSHIELD://No this is stupid and shouldnt be spreadable at all. - //case SC_STRIPARMOR:// Disabled until I can confirm if it does or not. [Rytech] - //case SC_STRIPHELM: - //case SC__STRIPACCESSORY: - case SC_BITE: - case SC_FREEZING: - case SC_VENOMBLEED: - case SC_DEATHHURT: - case SC_PARALYSE: - if (sc->data[i]->timer != INVALID_TIMER) { - timer = get_timer(sc->data[i]->timer); - if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0) - continue; - data.tick = DIFF_TICK(timer->tick,tick); - } else - data.tick = INVALID_TIMER; - break; - // Special cases - case SC_POISON: - case SC_DPOISON: - data.tick = sc->data[i]->val3 * 1000; - break; - case SC_FEAR: - case SC_LEECHESEND: - data.tick = sc->data[i]->val4 * 1000; - break; - case SC_BURNING: - data.tick = sc->data[i]->val4 * 2000; - break; - case SC_PYREXIA: - case SC_OBLIVIONCURSE: - data.tick = sc->data[i]->val4 * 3000; - break; - case SC_MAGICMUSHROOM: - data.tick = sc->data[i]->val4 * 4000; - break; - case SC_TOXIN: - case SC_BLEEDING: - data.tick = sc->data[i]->val4 * 10000; - break; - default: - continue; - break; - } - if (i) { - data.val1 = sc->data[i]->val1; - data.val2 = sc->data[i]->val2; - data.val3 = sc->data[i]->val3; - data.val4 = sc->data[i]->val4; - status_change_start(bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,1|2|8); - flag = 1; - } - } + } + if( i ){ + data.val1 = sc->data[i]->val1; + data.val2 = sc->data[i]->val2; + data.val3 = sc->data[i]->val3; + data.val4 = sc->data[i]->val4; + status_change_start(bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,1|2|8); + flag = 1; + } + } - return flag; + return flag; } //Natural regen related stuff. static unsigned int natural_heal_prev_tick,natural_heal_diff_tick; -static int status_natural_heal(struct block_list *bl, va_list args) +static int status_natural_heal(struct block_list* bl, va_list args) { - struct regen_data *regen; - struct status_data *status; - struct status_change *sc; - struct unit_data *ud; - struct view_data *vd = NULL; - struct regen_data_sub *sregen; - struct map_session_data *sd; - int val,rate,bonus = 0,flag; - - regen = status_get_regen_data(bl); - if (!regen) return 0; - status = status_get_status_data(bl); - sc = status_get_sc(bl); - if (sc && !sc->count) - sc = NULL; - sd = BL_CAST(BL_PC,bl); - - flag = regen->flag; - if (flag&RGN_HP && (status->hp >= status->max_hp || regen->state.block&1)) - flag&=~(RGN_HP|RGN_SHP); - if (flag&RGN_SP && (status->sp >= status->max_sp || regen->state.block&2)) - flag&=~(RGN_SP|RGN_SSP); - - if (flag && ( - status_isdead(bl) || - (sc && (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || sc->data[SC__INVISIBILITY])) - )) - flag=0; - - if (sd) { - if (sd->hp_loss.value || sd->sp_loss.value) - pc_bleeding(sd, natural_heal_diff_tick); - if (sd->hp_regen.value || sd->sp_regen.value) - pc_regen(sd, natural_heal_diff_tick); - } - - if (flag&(RGN_SHP|RGN_SSP) && regen->ssregen && - (vd = status_get_viewdata(bl)) && vd->dead_sit == 2) { - //Apply sitting regen bonus. - sregen = regen->ssregen; - if (flag&(RGN_SHP)) { - //Sitting HP regen - val = natural_heal_diff_tick * sregen->rate.hp; - if (regen->state.overweight) - val>>=1; //Half as fast when overweight. - sregen->tick.hp += val; - while (sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) { - sregen->tick.hp -= battle_config.natural_heal_skill_interval; - if (status_heal(bl, sregen->hp, 0, 3) < sregen->hp) { - //Full - flag&=~(RGN_HP|RGN_SHP); - break; - } - } - } - if (flag&(RGN_SSP)) { - //Sitting SP regen - val = natural_heal_diff_tick * sregen->rate.sp; - if (regen->state.overweight) - val>>=1; //Half as fast when overweight. - sregen->tick.sp += val; - while (sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) { - sregen->tick.sp -= battle_config.natural_heal_skill_interval; - if (status_heal(bl, 0, sregen->sp, 3) < sregen->sp) { - //Full - flag&=~(RGN_SP|RGN_SSP); - break; - } - } - } - } - - if (flag && regen->state.overweight) - flag=0; - - ud = unit_bl2ud(bl); - - if (flag&(RGN_HP|RGN_SHP|RGN_SSP) && ud && ud->walktimer != INVALID_TIMER) { - flag&=~(RGN_SHP|RGN_SSP); - if (!regen->state.walk) - flag&=~RGN_HP; - } - - if (!flag) - return 0; - - if (flag&(RGN_HP|RGN_SP)) { - if (!vd) vd = status_get_viewdata(bl); - if (vd && vd->dead_sit == 2) - bonus++; - if (regen->state.gc) - bonus++; - } - - //Natural Hp regen - if (flag&RGN_HP) { - rate = natural_heal_diff_tick*(regen->rate.hp+bonus); - if (ud && ud->walktimer != INVALID_TIMER) - rate/=2; - // Homun HP regen fix (they should regen as if they were sitting (twice as fast) - if (bl->type==BL_HOM) rate *=2; - - regen->tick.hp += rate; - - if (regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval) { - val = 0; - do { - val += regen->hp; - regen->tick.hp -= battle_config.natural_healhp_interval; - } while (regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval); - if (status_heal(bl, val, 0, 1) < val) - flag&=~RGN_SHP; //full. - } - } - - //Natural SP regen - if (flag&RGN_SP) { - rate = natural_heal_diff_tick*(regen->rate.sp+bonus); - // Homun SP regen fix (they should regen as if they were sitting (twice as fast) - if (bl->type==BL_HOM) rate *=2; - - regen->tick.sp += rate; - - if (regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval) { - val = 0; - do { - val += regen->sp; - regen->tick.sp -= battle_config.natural_healsp_interval; - } while (regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval); - if (status_heal(bl, 0, val, 1) < val) - flag&=~RGN_SSP; //full. - } - } + struct regen_data *regen; + struct status_data *status; + struct status_change *sc; + struct unit_data *ud; + struct view_data *vd = NULL; + struct regen_data_sub *sregen; + struct map_session_data *sd; + int val,rate,bonus = 0,flag; + + regen = status_get_regen_data(bl); + if (!regen) return 0; + status = status_get_status_data(bl); + sc = status_get_sc(bl); + if (sc && !sc->count) + sc = NULL; + sd = BL_CAST(BL_PC,bl); + + flag = regen->flag; + if (flag&RGN_HP && (status->hp >= status->max_hp || regen->state.block&1)) + flag&=~(RGN_HP|RGN_SHP); + if (flag&RGN_SP && (status->sp >= status->max_sp || regen->state.block&2)) + flag&=~(RGN_SP|RGN_SSP); + + if (flag && ( + status_isdead(bl) || + (sc && (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || sc->data[SC__INVISIBILITY])) + )) + flag=0; + + if (sd) { + if (sd->hp_loss.value || sd->sp_loss.value) + pc_bleeding(sd, natural_heal_diff_tick); + if (sd->hp_regen.value || sd->sp_regen.value) + pc_regen(sd, natural_heal_diff_tick); + } + + if(flag&(RGN_SHP|RGN_SSP) && regen->ssregen && + (vd = status_get_viewdata(bl)) && vd->dead_sit == 2) + { //Apply sitting regen bonus. + sregen = regen->ssregen; + if(flag&(RGN_SHP)) + { //Sitting HP regen + val = natural_heal_diff_tick * sregen->rate.hp; + if (regen->state.overweight) + val>>=1; //Half as fast when overweight. + sregen->tick.hp += val; + while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) + { + sregen->tick.hp -= battle_config.natural_heal_skill_interval; + if(status_heal(bl, sregen->hp, 0, 3) < sregen->hp) + { //Full + flag&=~(RGN_HP|RGN_SHP); + break; + } + } + } + if(flag&(RGN_SSP)) + { //Sitting SP regen + val = natural_heal_diff_tick * sregen->rate.sp; + if (regen->state.overweight) + val>>=1; //Half as fast when overweight. + sregen->tick.sp += val; + while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) + { + sregen->tick.sp -= battle_config.natural_heal_skill_interval; + if(status_heal(bl, 0, sregen->sp, 3) < sregen->sp) + { //Full + flag&=~(RGN_SP|RGN_SSP); + break; + } + } + } + } + + if (flag && regen->state.overweight) + flag=0; + + ud = unit_bl2ud(bl); + + if (flag&(RGN_HP|RGN_SHP|RGN_SSP) && ud && ud->walktimer != INVALID_TIMER) + { + flag&=~(RGN_SHP|RGN_SSP); + if(!regen->state.walk) + flag&=~RGN_HP; + } + + if (!flag) + return 0; + + if (flag&(RGN_HP|RGN_SP)) + { + if(!vd) vd = status_get_viewdata(bl); + if(vd && vd->dead_sit == 2) + bonus++; + if(regen->state.gc) + bonus++; + } + + //Natural Hp regen + if (flag&RGN_HP) + { + rate = natural_heal_diff_tick*(regen->rate.hp+bonus); + if (ud && ud->walktimer != INVALID_TIMER) + rate/=2; + // Homun HP regen fix (they should regen as if they were sitting (twice as fast) + if(bl->type==BL_HOM) rate *=2; + + regen->tick.hp += rate; + + if(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval) + { + val = 0; + do { + val += regen->hp; + regen->tick.hp -= battle_config.natural_healhp_interval; + } while(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval); + if (status_heal(bl, val, 0, 1) < val) + flag&=~RGN_SHP; //full. + } + } + + //Natural SP regen + if(flag&RGN_SP) + { + rate = natural_heal_diff_tick*(regen->rate.sp+bonus); + // Homun SP regen fix (they should regen as if they were sitting (twice as fast) + if(bl->type==BL_HOM) rate *=2; + + regen->tick.sp += rate; + + if(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval) + { + val = 0; + do { + val += regen->sp; + regen->tick.sp -= battle_config.natural_healsp_interval; + } while(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval); + if (status_heal(bl, 0, val, 1) < val) + flag&=~RGN_SSP; //full. + } + } - if (!regen->sregen) - return flag; + if (!regen->sregen) + return flag; - //Skill regen - sregen = regen->sregen; + //Skill regen + sregen = regen->sregen; - if (flag&RGN_SHP) { - //Skill HP regen - sregen->tick.hp += natural_heal_diff_tick * sregen->rate.hp; + if(flag&RGN_SHP) + { //Skill HP regen + sregen->tick.hp += natural_heal_diff_tick * sregen->rate.hp; - while (sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) { - sregen->tick.hp -= battle_config.natural_heal_skill_interval; - if (status_heal(bl, sregen->hp, 0, 3) < sregen->hp) - break; //Full - } - } - if (flag&RGN_SSP) { - //Skill SP regen - sregen->tick.sp += natural_heal_diff_tick * sregen->rate.sp; - while (sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) { - val = sregen->sp; - if (sd && sd->state.doridori) { - val*=2; - sd->state.doridori = 0; - if ((rate = pc_checkskill(sd,TK_SPTIME))) - sc_start(bl,status_skill2sc(TK_SPTIME), - 100,rate,skill_get_time(TK_SPTIME, rate)); - if ( - (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && - rnd()%10000 < battle_config.sg_angel_skill_ratio - ) { //Angel of the Sun/Moon/Star - clif_feel_hate_reset(sd); - pc_resethate(sd); - pc_resetfeel(sd); - } - } - sregen->tick.sp -= battle_config.natural_heal_skill_interval; - if (status_heal(bl, 0, val, 3) < val) - break; //Full - } - } - return flag; + while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) + { + sregen->tick.hp -= battle_config.natural_heal_skill_interval; + if(status_heal(bl, sregen->hp, 0, 3) < sregen->hp) + break; //Full + } + } + if(flag&RGN_SSP) + { //Skill SP regen + sregen->tick.sp += natural_heal_diff_tick * sregen->rate.sp; + while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) + { + val = sregen->sp; + if (sd && sd->state.doridori) { + val*=2; + sd->state.doridori = 0; + if ((rate = pc_checkskill(sd,TK_SPTIME))) + sc_start(bl,status_skill2sc(TK_SPTIME), + 100,rate,skill_get_time(TK_SPTIME, rate)); + if ( + (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && + rnd()%10000 < battle_config.sg_angel_skill_ratio + ) { //Angel of the Sun/Moon/Star + clif_feel_hate_reset(sd); + pc_resethate(sd); + pc_resetfeel(sd); + } + } + sregen->tick.sp -= battle_config.natural_heal_skill_interval; + if(status_heal(bl, 0, val, 3) < val) + break; //Full + } + } + return flag; } //Natural heal main timer. static int status_natural_heal_timer(int tid, unsigned int tick, int id, intptr_t data) { - natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick); - map_foreachregen(status_natural_heal); - natural_heal_prev_tick = tick; - return 0; + natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick); + map_foreachregen(status_natural_heal); + natural_heal_prev_tick = tick; + return 0; } /** @@ -11014,13 +10967,12 @@ static int status_natural_heal_timer(int tid, unsigned int tick, int id, intptr_ * @param refine The target refine level * @return The chance to refine the item, in percent (0~100) **/ -int status_get_refine_chance(enum refine_type wlv, int refine) -{ +int status_get_refine_chance(enum refine_type wlv, int refine) { - if (refine < 0 || refine >= MAX_REFINE) - return 0; + if ( refine < 0 || refine >= MAX_REFINE) + return 0; - return refine_info[wlv].chance[refine]; + return refine_info[wlv].chance[refine]; } @@ -11031,94 +10983,98 @@ int status_get_refine_chance(enum refine_type wlv, int refine) * size_fix.txt - size adjustment table for weapons * refine_db.txt - refining data table *------------------------------------------*/ -static bool status_readdb_job1(char *fields[], int columns, int current) -{ - // Job-specific values (weight, HP, SP, ASPD) - int idx, class_; - unsigned int i; - - class_ = atoi(fields[0]); - - if (!pcdb_checkid(class_)) { - ShowWarning("status_readdb_job1: Invalid job class %d specified.\n", class_); - return false; - } - idx = pc_class2idx(class_); - - max_weight_base[idx] = atoi(fields[1]); - hp_coefficient[idx] = atoi(fields[2]); - hp_coefficient2[idx] = atoi(fields[3]); - sp_coefficient[idx] = atoi(fields[4]); +static bool status_readdb_job1(char* fields[], int columns, int current) +{// Job-specific values (weight, HP, SP, ASPD) + int idx, class_; + unsigned int i; + + class_ = atoi(fields[0]); + + if(!pcdb_checkid(class_)) + { + ShowWarning("status_readdb_job1: Invalid job class %d specified.\n", class_); + return false; + } + idx = pc_class2idx(class_); + + max_weight_base[idx] = atoi(fields[1]); + hp_coefficient[idx] = atoi(fields[2]); + hp_coefficient2[idx] = atoi(fields[3]); + sp_coefficient[idx] = atoi(fields[4]); #ifdef RENEWAL_ASPD - for (i = 0; i <= MAX_WEAPON_TYPE; i++) + for(i = 0; i <= MAX_WEAPON_TYPE; i++) #else - for (i = 0; i < MAX_WEAPON_TYPE; i++) + for(i = 0; i < MAX_WEAPON_TYPE; i++) #endif - { - aspd_base[idx][i] = atoi(fields[i+5]); - } - return true; + { + aspd_base[idx][i] = atoi(fields[i+5]); + } + return true; } -static bool status_readdb_job2(char *fields[], int columns, int current) +static bool status_readdb_job2(char* fields[], int columns, int current) { - int idx, class_, i; - - class_ = atoi(fields[0]); - - if (!pcdb_checkid(class_)) { - ShowWarning("status_readdb_job2: Invalid job class %d specified.\n", class_); - return false; - } - idx = pc_class2idx(class_); - - for (i = 1; i < columns; i++) { - job_bonus[idx][i-1] = atoi(fields[i]); - } - return true; + int idx, class_, i; + + class_ = atoi(fields[0]); + + if(!pcdb_checkid(class_)) + { + ShowWarning("status_readdb_job2: Invalid job class %d specified.\n", class_); + return false; + } + idx = pc_class2idx(class_); + + for(i = 1; i < columns; i++) + { + job_bonus[idx][i-1] = atoi(fields[i]); + } + return true; } -static bool status_readdb_sizefix(char *fields[], int columns, int current) +static bool status_readdb_sizefix(char* fields[], int columns, int current) { - unsigned int i; + unsigned int i; - for (i = 0; i < MAX_WEAPON_TYPE; i++) { - atkmods[current][i] = atoi(fields[i]); - } - return true; + for(i = 0; i < MAX_WEAPON_TYPE; i++) + { + atkmods[current][i] = atoi(fields[i]); + } + return true; } -static bool status_readdb_refine(char *fields[], int columns, int current) +static bool status_readdb_refine(char* fields[], int columns, int current) { - int i, bonus_per_level, random_bonus, random_bonus_start_level; + int i, bonus_per_level, random_bonus, random_bonus_start_level; - current = atoi(fields[0]); + current = atoi(fields[0]); - if (current < 0 || current >= REFINE_TYPE_MAX) - return false; + if (current < 0 || current >= REFINE_TYPE_MAX) + return false; - bonus_per_level = atoi(fields[1]); - random_bonus_start_level = atoi(fields[2]); - random_bonus = atoi(fields[3]); + bonus_per_level = atoi(fields[1]); + random_bonus_start_level = atoi(fields[2]); + random_bonus = atoi(fields[3]); - for (i = 0; i < MAX_REFINE; i++) { - char *delim; + for(i = 0; i < MAX_REFINE; i++) + { + char* delim; - if (!(delim = strchr(fields[4+i], ':'))) - return false; + if (!(delim = strchr(fields[4+i], ':'))) + return false; - *delim = '\0'; + *delim = '\0'; - refine_info[current].chance[i] = atoi(fields[4+i]); + refine_info[current].chance[i] = atoi(fields[4+i]); - if (i >= random_bonus_start_level - 1) - refine_info[current].randombonus_max[i] = random_bonus * (i - random_bonus_start_level + 2); + if (i >= random_bonus_start_level - 1) + refine_info[current].randombonus_max[i] = random_bonus * (i - random_bonus_start_level + 2); - refine_info[current].bonus[i] = bonus_per_level + atoi(delim+1); - if (i > 0) - refine_info[current].bonus[i] += refine_info[current].bonus[i-1]; - } - return true; + refine_info[current].bonus[i] = bonus_per_level + atoi(delim+1); + if (i > 0) + refine_info[current].bonus[i] += refine_info[current].bonus[i-1]; + } + return true; } /* @@ -11130,48 +11086,50 @@ static bool status_readdb_refine(char *fields[], int columns, int current) */ int status_readdb(void) { - int i, j; - - // initialize databases to default - // - - // reset job_db1.txt data - memset(max_weight_base, 0, sizeof(max_weight_base)); - memset(hp_coefficient, 0, sizeof(hp_coefficient)); - memset(hp_coefficient2, 0, sizeof(hp_coefficient2)); - memset(sp_coefficient, 0, sizeof(sp_coefficient)); - memset(aspd_base, 0, sizeof(aspd_base)); - // reset job_db2.txt data - memset(job_bonus,0,sizeof(job_bonus)); // Job-specific stats bonus - - // size_fix.txt - for (i=0; i<ARRAYLENGTH(atkmods); i++) - for (j=0; j<MAX_WEAPON_TYPE; j++) - atkmods[i][j]=100; - - // refine_db.txt - for (i=0; i<ARRAYLENGTH(refine_info); i++) { - for (j=0; j<MAX_REFINE; j++) { - refine_info[i].chance[j] = 100; - refine_info[i].bonus[j] = 0; - refine_info[i].randombonus_max[j] = 0; - } - } + int i, j; + + // initialize databases to default + // + + // reset job_db1.txt data + memset(max_weight_base, 0, sizeof(max_weight_base)); + memset(hp_coefficient, 0, sizeof(hp_coefficient)); + memset(hp_coefficient2, 0, sizeof(hp_coefficient2)); + memset(sp_coefficient, 0, sizeof(sp_coefficient)); + memset(aspd_base, 0, sizeof(aspd_base)); + // reset job_db2.txt data + memset(job_bonus,0,sizeof(job_bonus)); // Job-specific stats bonus + + // size_fix.txt + for(i=0;i<ARRAYLENGTH(atkmods);i++) + for(j=0;j<MAX_WEAPON_TYPE;j++) + atkmods[i][j]=100; + + // refine_db.txt + for(i=0;i<ARRAYLENGTH(refine_info);i++) + { + for(j=0;j<MAX_REFINE; j++) + { + refine_info[i].chance[j] = 100; + refine_info[i].bonus[j] = 0; + refine_info[i].randombonus_max[j] = 0; + } + } - // read databases - // + // read databases + // #ifdef RENEWAL_ASPD - sv_readdb(db_path, "re/job_db1.txt", ',', 6+MAX_WEAPON_TYPE, 6+MAX_WEAPON_TYPE, -1, &status_readdb_job1); + sv_readdb(db_path, "re/job_db1.txt", ',', 6+MAX_WEAPON_TYPE, 6+MAX_WEAPON_TYPE, -1, &status_readdb_job1); #else - sv_readdb(db_path, "pre-re/job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, &status_readdb_job1); + sv_readdb(db_path, "pre-re/job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, &status_readdb_job1); #endif - sv_readdb(db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, &status_readdb_job2); - sv_readdb(db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(atkmods), &status_readdb_sizefix); - sv_readdb(db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine); + sv_readdb(db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, &status_readdb_job2); + sv_readdb(db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(atkmods), &status_readdb_sizefix); + sv_readdb(db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine); - return 0; + return 0; } /*========================================== @@ -11179,19 +11137,19 @@ int status_readdb(void) *------------------------------------------*/ int do_init_status(void) { - add_timer_func_list(status_change_timer,"status_change_timer"); - add_timer_func_list(kaahi_heal_timer,"kaahi_heal_timer"); - add_timer_func_list(status_natural_heal_timer,"status_natural_heal_timer"); - initChangeTables(); - initDummyData(); - status_readdb(); - status_calc_sigma(); - natural_heal_prev_tick = gettick(); - sc_data_ers = ers_new(sizeof(struct status_change_entry),"status.c::sc_data_ers",ERS_OPT_NONE); - add_timer_interval(natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status_natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL); - return 0; + add_timer_func_list(status_change_timer,"status_change_timer"); + add_timer_func_list(kaahi_heal_timer,"kaahi_heal_timer"); + add_timer_func_list(status_natural_heal_timer,"status_natural_heal_timer"); + initChangeTables(); + initDummyData(); + status_readdb(); + status_calc_sigma(); + natural_heal_prev_tick = gettick(); + sc_data_ers = ers_new(sizeof(struct status_change_entry),"status.c::sc_data_ers",ERS_OPT_NONE); + add_timer_interval(natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status_natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL); + return 0; } void do_final_status(void) { - ers_destroy(sc_data_ers); + ers_destroy(sc_data_ers); } diff --git a/src/map/status.h b/src/map/status.h index 130b858e0..402dfc690 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -16,628 +16,628 @@ struct status_change; * Changing this limit requires edits to refine_db.txt **/ #ifdef RENEWAL -# define MAX_REFINE 20 +# define MAX_REFINE 20 #else -# define MAX_REFINE 10 +# define MAX_REFINE 10 #endif enum refine_type { - REFINE_TYPE_ARMOR = 0, - REFINE_TYPE_WEAPON1 = 1, - REFINE_TYPE_WEAPON2 = 2, - REFINE_TYPE_WEAPON3 = 3, - REFINE_TYPE_WEAPON4 = 4, + REFINE_TYPE_ARMOR = 0, + REFINE_TYPE_WEAPON1 = 1, + REFINE_TYPE_WEAPON2 = 2, + REFINE_TYPE_WEAPON3 = 3, + REFINE_TYPE_WEAPON4 = 4, - REFINE_TYPE_MAX = 5 + REFINE_TYPE_MAX = 5 }; int status_get_refine_chance(enum refine_type wlv, int refine); -// Status changes listing. These code are for use by the server. +// Status changes listing. These code are for use by the server. typedef enum sc_type { - SC_NONE = -1, + SC_NONE = -1, - //First we enumerate common status ailments which are often used around. - SC_STONE = 0, - SC_COMMON_MIN = 0, // begin - SC_FREEZE, - SC_STUN, - SC_SLEEP, - SC_POISON, - SC_CURSE, - SC_SILENCE, - SC_CONFUSION, - SC_BLIND, - SC_BLEEDING, - SC_DPOISON, //10 - SC_COMMON_MAX = 10, // end + //First we enumerate common status ailments which are often used around. + SC_STONE = 0, + SC_COMMON_MIN = 0, // begin + SC_FREEZE, + SC_STUN, + SC_SLEEP, + SC_POISON, + SC_CURSE, + SC_SILENCE, + SC_CONFUSION, + SC_BLIND, + SC_BLEEDING, + SC_DPOISON, //10 + SC_COMMON_MAX = 10, // end + + //Next up, we continue on 20, to leave enough room for additional "common" ailments in the future. + SC_PROVOKE = 20, + SC_ENDURE, + SC_TWOHANDQUICKEN, + SC_CONCENTRATE, + SC_HIDING, + SC_CLOAKING, + SC_ENCPOISON, + SC_POISONREACT, + SC_QUAGMIRE, + SC_ANGELUS, + SC_BLESSING, //30 + SC_SIGNUMCRUCIS, + SC_INCREASEAGI, + SC_DECREASEAGI, + SC_SLOWPOISON, + SC_IMPOSITIO , + SC_SUFFRAGIUM, + SC_ASPERSIO, + SC_BENEDICTIO, + SC_KYRIE, + SC_MAGNIFICAT, //40 + SC_GLORIA, + SC_AETERNA, + SC_ADRENALINE, + SC_WEAPONPERFECTION, + SC_OVERTHRUST, + SC_MAXIMIZEPOWER, + SC_TRICKDEAD, + SC_LOUD, + SC_ENERGYCOAT, + SC_BROKENARMOR, //50 - NOTE: These two aren't used anywhere, and they have an icon... + SC_BROKENWEAPON, + SC_HALLUCINATION, + SC_WEIGHT50, + SC_WEIGHT90, + SC_ASPDPOTION0, + SC_ASPDPOTION1, + SC_ASPDPOTION2, + SC_ASPDPOTION3, + SC_SPEEDUP0, + SC_SPEEDUP1, //60 + SC_ATKPOTION, + SC_MATKPOTION, + SC_WEDDING, + SC_SLOWDOWN, + SC_ANKLE, + SC_KEEPING, + SC_BARRIER, + SC_STRIPWEAPON, + SC_STRIPSHIELD, + SC_STRIPARMOR, //70 + SC_STRIPHELM, + SC_CP_WEAPON, + SC_CP_SHIELD, + SC_CP_ARMOR, + SC_CP_HELM, + SC_AUTOGUARD, + SC_REFLECTSHIELD, + SC_SPLASHER, + SC_PROVIDENCE, + SC_DEFENDER, //80 + SC_MAGICROD, + SC_SPELLBREAKER, + SC_AUTOSPELL, + SC_SIGHTTRASHER, + SC_AUTOBERSERK, + SC_SPEARQUICKEN, + SC_AUTOCOUNTER, + SC_SIGHT, + SC_SAFETYWALL, + SC_RUWACH, //90 + SC_EXTREMITYFIST, + SC_EXPLOSIONSPIRITS, + SC_COMBO, + SC_BLADESTOP_WAIT, + SC_BLADESTOP, + SC_FIREWEAPON, + SC_WATERWEAPON, + SC_WINDWEAPON, + SC_EARTHWEAPON, + SC_VOLCANO, //100, + SC_DELUGE, + SC_VIOLENTGALE, + SC_WATK_ELEMENT, + SC_ARMOR, + SC_ARMOR_ELEMENT, + SC_NOCHAT, + SC_BABY, + SC_AURABLADE, + SC_PARRYING, + SC_CONCENTRATION, //110 + SC_TENSIONRELAX, + SC_BERSERK, + SC_FURY, + SC_GOSPEL, + SC_ASSUMPTIO, + SC_BASILICA, + SC_GUILDAURA, + SC_MAGICPOWER, + SC_EDP, + SC_TRUESIGHT, //120 + SC_WINDWALK, + SC_MELTDOWN, + SC_CARTBOOST, + SC_CHASEWALK, + SC_REJECTSWORD, + SC_MARIONETTE, + SC_MARIONETTE2, + SC_CHANGEUNDEAD, + SC_JOINTBEAT, + SC_MINDBREAKER, //130 + SC_MEMORIZE, + SC_FOGWALL, + SC_SPIDERWEB, + SC_DEVOTION, + SC_SACRIFICE, + SC_STEELBODY, + SC_ORCISH, + SC_READYSTORM, + SC_READYDOWN, + SC_READYTURN, //140 + SC_READYCOUNTER, + SC_DODGE, + SC_RUN, + SC_SHADOWWEAPON, + SC_ADRENALINE2, + SC_GHOSTWEAPON, + SC_KAIZEL, + SC_KAAHI, + SC_KAUPE, + SC_ONEHAND, //150 + SC_PRESERVE, + SC_BATTLEORDERS, + SC_REGENERATION, + SC_DOUBLECAST, + SC_GRAVITATION, + SC_MAXOVERTHRUST, + SC_LONGING, + SC_HERMODE, + SC_SHRINK, + SC_SIGHTBLASTER, //160 + SC_WINKCHARM, + SC_CLOSECONFINE, + SC_CLOSECONFINE2, + SC_DANCING, + SC_ELEMENTALCHANGE, + SC_RICHMANKIM, + SC_ETERNALCHAOS, + SC_DRUMBATTLE, + SC_NIBELUNGEN, + SC_ROKISWEIL, //170 + SC_INTOABYSS, + SC_SIEGFRIED, + SC_WHISTLE, + SC_ASSNCROS, + SC_POEMBRAGI, + SC_APPLEIDUN, + SC_MODECHANGE, + SC_HUMMING, + SC_DONTFORGETME, + SC_FORTUNE, //180 + SC_SERVICE4U, + SC_STOP, //Prevents inflicted chars from walking. [Skotlex] + SC_SPURT, + SC_SPIRIT, + SC_COMA, //Not a real SC_, it makes a char's HP/SP hit 1. + SC_INTRAVISION, + SC_INCALLSTATUS, + SC_INCSTR, + SC_INCAGI, + SC_INCVIT, //190 + SC_INCINT, + SC_INCDEX, + SC_INCLUK, + SC_INCHIT, + SC_INCHITRATE, + SC_INCFLEE, + SC_INCFLEERATE, + SC_INCMHPRATE, + SC_INCMSPRATE, + SC_INCATKRATE, //200 + SC_INCMATKRATE, + SC_INCDEFRATE, + SC_STRFOOD, + SC_AGIFOOD, + SC_VITFOOD, + SC_INTFOOD, + SC_DEXFOOD, + SC_LUKFOOD, + SC_HITFOOD, + SC_FLEEFOOD, //210 + SC_BATKFOOD, + SC_WATKFOOD, + SC_MATKFOOD, + SC_SCRESIST, //Increases resistance to status changes. + SC_XMAS, // Xmas Suit [Valaris] + SC_WARM, //SG skills [Komurka] + SC_SUN_COMFORT, + SC_MOON_COMFORT, + SC_STAR_COMFORT, + SC_FUSION, //220 + SC_SKILLRATE_UP, + SC_SKE, + SC_KAITE, + SC_SWOO, // [marquis007] + SC_SKA, // [marquis007] + SC_EARTHSCROLL, + SC_MIRACLE, //SG 'hidden' skill [Komurka] + SC_MADNESSCANCEL, + SC_ADJUSTMENT, + SC_INCREASING, //230 + SC_GATLINGFEVER, + SC_TATAMIGAESHI, + SC_UTSUSEMI, + SC_BUNSINJYUTSU, + SC_KAENSIN, + SC_SUITON, + SC_NEN, + SC_KNOWLEDGE, + SC_SMA, + SC_FLING, //240 + SC_AVOID, + SC_CHANGE, + SC_BLOODLUST, + SC_FLEET, + SC_SPEED, + SC_DEFENCE, + SC_INCASPDRATE, + SC_INCFLEE2 = 248, + SC_JAILED, + SC_ENCHANTARMS, //250 + SC_MAGICALATTACK, + SC_ARMORCHANGE, + SC_CRITICALWOUND, + SC_MAGICMIRROR, + SC_SLOWCAST, + SC_SUMMER, + SC_EXPBOOST, + SC_ITEMBOOST, + SC_BOSSMAPINFO, + SC_LIFEINSURANCE, //260 + SC_INCCRI, + //SC_INCDEF, + //SC_INCBASEATK = 263, + //SC_FASTCAST, + SC_MDEF_RATE = 265, + //SC_HPREGEN, + SC_INCHEALRATE = 267, + SC_PNEUMA, + SC_AUTOTRADE, + SC_KSPROTECTED, //270 + SC_ARMOR_RESIST = 271, + SC_SPCOST_RATE, + SC_COMMONSC_RESIST, + SC_SEVENWIND, + SC_DEF_RATE, + //SC_SPREGEN, + SC_WALKSPEED = 277, - //Next up, we continue on 20, to leave enough room for additional "common" ailments in the future. - SC_PROVOKE = 20, - SC_ENDURE, - SC_TWOHANDQUICKEN, - SC_CONCENTRATE, - SC_HIDING, - SC_CLOAKING, - SC_ENCPOISON, - SC_POISONREACT, - SC_QUAGMIRE, - SC_ANGELUS, - SC_BLESSING, //30 - SC_SIGNUMCRUCIS, - SC_INCREASEAGI, - SC_DECREASEAGI, - SC_SLOWPOISON, - SC_IMPOSITIO , - SC_SUFFRAGIUM, - SC_ASPERSIO, - SC_BENEDICTIO, - SC_KYRIE, - SC_MAGNIFICAT, //40 - SC_GLORIA, - SC_AETERNA, - SC_ADRENALINE, - SC_WEAPONPERFECTION, - SC_OVERTHRUST, - SC_MAXIMIZEPOWER, - SC_TRICKDEAD, - SC_LOUD, - SC_ENERGYCOAT, - SC_BROKENARMOR, //50 - NOTE: These two aren't used anywhere, and they have an icon... - SC_BROKENWEAPON, - SC_HALLUCINATION, - SC_WEIGHT50, - SC_WEIGHT90, - SC_ASPDPOTION0, - SC_ASPDPOTION1, - SC_ASPDPOTION2, - SC_ASPDPOTION3, - SC_SPEEDUP0, - SC_SPEEDUP1, //60 - SC_ATKPOTION, - SC_MATKPOTION, - SC_WEDDING, - SC_SLOWDOWN, - SC_ANKLE, - SC_KEEPING, - SC_BARRIER, - SC_STRIPWEAPON, - SC_STRIPSHIELD, - SC_STRIPARMOR, //70 - SC_STRIPHELM, - SC_CP_WEAPON, - SC_CP_SHIELD, - SC_CP_ARMOR, - SC_CP_HELM, - SC_AUTOGUARD, - SC_REFLECTSHIELD, - SC_SPLASHER, - SC_PROVIDENCE, - SC_DEFENDER, //80 - SC_MAGICROD, - SC_SPELLBREAKER, - SC_AUTOSPELL, - SC_SIGHTTRASHER, - SC_AUTOBERSERK, - SC_SPEARQUICKEN, - SC_AUTOCOUNTER, - SC_SIGHT, - SC_SAFETYWALL, - SC_RUWACH, //90 - SC_EXTREMITYFIST, - SC_EXPLOSIONSPIRITS, - SC_COMBO, - SC_BLADESTOP_WAIT, - SC_BLADESTOP, - SC_FIREWEAPON, - SC_WATERWEAPON, - SC_WINDWEAPON, - SC_EARTHWEAPON, - SC_VOLCANO, //100, - SC_DELUGE, - SC_VIOLENTGALE, - SC_WATK_ELEMENT, - SC_ARMOR, - SC_ARMOR_ELEMENT, - SC_NOCHAT, - SC_BABY, - SC_AURABLADE, - SC_PARRYING, - SC_CONCENTRATION, //110 - SC_TENSIONRELAX, - SC_BERSERK, - SC_FURY, - SC_GOSPEL, - SC_ASSUMPTIO, - SC_BASILICA, - SC_GUILDAURA, - SC_MAGICPOWER, - SC_EDP, - SC_TRUESIGHT, //120 - SC_WINDWALK, - SC_MELTDOWN, - SC_CARTBOOST, - SC_CHASEWALK, - SC_REJECTSWORD, - SC_MARIONETTE, - SC_MARIONETTE2, - SC_CHANGEUNDEAD, - SC_JOINTBEAT, - SC_MINDBREAKER, //130 - SC_MEMORIZE, - SC_FOGWALL, - SC_SPIDERWEB, - SC_DEVOTION, - SC_SACRIFICE, - SC_STEELBODY, - SC_ORCISH, - SC_READYSTORM, - SC_READYDOWN, - SC_READYTURN, //140 - SC_READYCOUNTER, - SC_DODGE, - SC_RUN, - SC_SHADOWWEAPON, - SC_ADRENALINE2, - SC_GHOSTWEAPON, - SC_KAIZEL, - SC_KAAHI, - SC_KAUPE, - SC_ONEHAND, //150 - SC_PRESERVE, - SC_BATTLEORDERS, - SC_REGENERATION, - SC_DOUBLECAST, - SC_GRAVITATION, - SC_MAXOVERTHRUST, - SC_LONGING, - SC_HERMODE, - SC_SHRINK, - SC_SIGHTBLASTER, //160 - SC_WINKCHARM, - SC_CLOSECONFINE, - SC_CLOSECONFINE2, - SC_DANCING, - SC_ELEMENTALCHANGE, - SC_RICHMANKIM, - SC_ETERNALCHAOS, - SC_DRUMBATTLE, - SC_NIBELUNGEN, - SC_ROKISWEIL, //170 - SC_INTOABYSS, - SC_SIEGFRIED, - SC_WHISTLE, - SC_ASSNCROS, - SC_POEMBRAGI, - SC_APPLEIDUN, - SC_MODECHANGE, - SC_HUMMING, - SC_DONTFORGETME, - SC_FORTUNE, //180 - SC_SERVICE4U, - SC_STOP, //Prevents inflicted chars from walking. [Skotlex] - SC_SPURT, - SC_SPIRIT, - SC_COMA, //Not a real SC_, it makes a char's HP/SP hit 1. - SC_INTRAVISION, - SC_INCALLSTATUS, - SC_INCSTR, - SC_INCAGI, - SC_INCVIT, //190 - SC_INCINT, - SC_INCDEX, - SC_INCLUK, - SC_INCHIT, - SC_INCHITRATE, - SC_INCFLEE, - SC_INCFLEERATE, - SC_INCMHPRATE, - SC_INCMSPRATE, - SC_INCATKRATE, //200 - SC_INCMATKRATE, - SC_INCDEFRATE, - SC_STRFOOD, - SC_AGIFOOD, - SC_VITFOOD, - SC_INTFOOD, - SC_DEXFOOD, - SC_LUKFOOD, - SC_HITFOOD, - SC_FLEEFOOD, //210 - SC_BATKFOOD, - SC_WATKFOOD, - SC_MATKFOOD, - SC_SCRESIST, //Increases resistance to status changes. - SC_XMAS, // Xmas Suit [Valaris] - SC_WARM, //SG skills [Komurka] - SC_SUN_COMFORT, - SC_MOON_COMFORT, - SC_STAR_COMFORT, - SC_FUSION, //220 - SC_SKILLRATE_UP, - SC_SKE, - SC_KAITE, - SC_SWOO, // [marquis007] - SC_SKA, // [marquis007] - SC_EARTHSCROLL, - SC_MIRACLE, //SG 'hidden' skill [Komurka] - SC_MADNESSCANCEL, - SC_ADJUSTMENT, - SC_INCREASING, //230 - SC_GATLINGFEVER, - SC_TATAMIGAESHI, - SC_UTSUSEMI, - SC_BUNSINJYUTSU, - SC_KAENSIN, - SC_SUITON, - SC_NEN, - SC_KNOWLEDGE, - SC_SMA, - SC_FLING, //240 - SC_AVOID, - SC_CHANGE, - SC_BLOODLUST, - SC_FLEET, - SC_SPEED, - SC_DEFENCE, - SC_INCASPDRATE, - SC_INCFLEE2 = 248, - SC_JAILED, - SC_ENCHANTARMS, //250 - SC_MAGICALATTACK, - SC_ARMORCHANGE, - SC_CRITICALWOUND, - SC_MAGICMIRROR, - SC_SLOWCAST, - SC_SUMMER, - SC_EXPBOOST, - SC_ITEMBOOST, - SC_BOSSMAPINFO, - SC_LIFEINSURANCE, //260 - SC_INCCRI, - //SC_INCDEF, - //SC_INCBASEATK = 263, - //SC_FASTCAST, - SC_MDEF_RATE = 265, - //SC_HPREGEN, - SC_INCHEALRATE = 267, - SC_PNEUMA, - SC_AUTOTRADE, - SC_KSPROTECTED, //270 - SC_ARMOR_RESIST = 271, - SC_SPCOST_RATE, - SC_COMMONSC_RESIST, - SC_SEVENWIND, - SC_DEF_RATE, - //SC_SPREGEN, - SC_WALKSPEED = 277, + // Mercenary Only Bonus Effects + SC_MERC_FLEEUP, + SC_MERC_ATKUP, + SC_MERC_HPUP, //280 + SC_MERC_SPUP, + SC_MERC_HITUP, + SC_MERC_QUICKEN, - // Mercenary Only Bonus Effects - SC_MERC_FLEEUP, - SC_MERC_ATKUP, - SC_MERC_HPUP, //280 - SC_MERC_SPUP, - SC_MERC_HITUP, - SC_MERC_QUICKEN, - - SC_REBIRTH, - //SC_SKILLCASTRATE, //285 - //SC_DEFRATIOATK, - //SC_HPDRAIN, - //SC_SKILLATKBONUS, - SC_ITEMSCRIPT = 289, - SC_S_LIFEPOTION, //290 - SC_L_LIFEPOTION, - SC_JEXPBOOST, - //SC_IGNOREDEF, - SC_HELLPOWER = 294, - SC_INVINCIBLE, //295 - SC_INVINCIBLEOFF, - SC_MANU_ATK, - SC_MANU_DEF, - SC_SPL_ATK, - SC_SPL_DEF, //300 - SC_MANU_MATK, - SC_SPL_MATK, - SC_FOOD_STR_CASH, - SC_FOOD_AGI_CASH, - SC_FOOD_VIT_CASH, - SC_FOOD_DEX_CASH, - SC_FOOD_INT_CASH, - SC_FOOD_LUK_CASH,//308 - /** - * 3rd - **/ - SC_FEAR,//309 - SC_BURNING,//310 - SC_FREEZING,//311 - /** - * Rune Knight - **/ - SC_ENCHANTBLADE,//312 - SC_DEATHBOUND,//313 - SC_MILLENNIUMSHIELD, - SC_CRUSHSTRIKE,//315 - SC_REFRESH, - SC_REUSE_REFRESH, - SC_GIANTGROWTH, - SC_STONEHARDSKIN, - SC_VITALITYACTIVATION,//320 - SC_STORMBLAST, - SC_FIGHTINGSPIRIT, - SC_ABUNDANCE, - /** - * Arch Bishop - **/ - SC_ADORAMUS, - SC_EPICLESIS,//325 - SC_ORATIO, - SC_LAUDAAGNUS, - SC_LAUDARAMUS, - SC_RENOVATIO, - SC_EXPIATIO,//330 - SC_DUPLELIGHT, - SC_SECRAMENT, - /** - * Warlock - **/ - SC_WHITEIMPRISON, - SC_MARSHOFABYSS, - SC_RECOGNIZEDSPELL,//335 - SC_STASIS, - SC_SPHERE_1, - SC_SPHERE_2, - SC_SPHERE_3, - SC_SPHERE_4,//340 - SC_SPHERE_5, - SC_READING_SB, - SC_FREEZINGSPELL, - /** - * Ranger - **/ - SC_FEARBREEZE, - SC_ELECTRICSHOCKER,//345 - SC_WUGDASH, - SC_BITE, - SC_CAMOUFLAGE, - /** - * Mechanic - **/ - SC_ACCELERATION, - SC_HOVERING,//350 - SC_SHAPESHIFT, - SC_INFRAREDSCAN, - SC_ANALYZE, - SC_MAGNETICFIELD, - SC_NEUTRALBARRIER,//355 - SC_NEUTRALBARRIER_MASTER, - SC_STEALTHFIELD, - SC_STEALTHFIELD_MASTER, - SC_OVERHEAT, - SC_OVERHEAT_LIMITPOINT,//360 - /** - * Guillotine Cross - **/ - SC_VENOMIMPRESS, - SC_POISONINGWEAPON, - SC_WEAPONBLOCKING, - SC_CLOAKINGEXCEED, - SC_HALLUCINATIONWALK,//365 - SC_HALLUCINATIONWALK_POSTDELAY, - SC_ROLLINGCUTTER, - SC_TOXIN, - SC_PARALYSE, - SC_VENOMBLEED,//370 - SC_MAGICMUSHROOM, - SC_DEATHHURT, - SC_PYREXIA, - SC_OBLIVIONCURSE, - SC_LEECHESEND,//375 - /** - * Royal Guard - **/ - SC_REFLECTDAMAGE, - SC_FORCEOFVANGUARD, - SC_SHIELDSPELL_DEF, - SC_SHIELDSPELL_MDEF, - SC_SHIELDSPELL_REF,//380 - SC_EXEEDBREAK, - SC_PRESTIGE, - SC_BANDING, - SC_BANDING_DEFENCE, - SC_EARTHDRIVE,//385 - SC_INSPIRATION, - /** - * Sorcerer - **/ - SC_SPELLFIST, - SC_CRYSTALIZE, - SC_STRIKING, - SC_WARMER,//390 - SC_VACUUM_EXTREME, - SC_PROPERTYWALK, - /** - * Minstrel / Wanderer + SC_REBIRTH, + //SC_SKILLCASTRATE, //285 + //SC_DEFRATIOATK, + //SC_HPDRAIN, + //SC_SKILLATKBONUS, + SC_ITEMSCRIPT = 289, + SC_S_LIFEPOTION, //290 + SC_L_LIFEPOTION, + SC_JEXPBOOST, + //SC_IGNOREDEF, + SC_HELLPOWER = 294, + SC_INVINCIBLE, //295 + SC_INVINCIBLEOFF, + SC_MANU_ATK, + SC_MANU_DEF, + SC_SPL_ATK, + SC_SPL_DEF, //300 + SC_MANU_MATK, + SC_SPL_MATK, + SC_FOOD_STR_CASH, + SC_FOOD_AGI_CASH, + SC_FOOD_VIT_CASH, + SC_FOOD_DEX_CASH, + SC_FOOD_INT_CASH, + SC_FOOD_LUK_CASH,//308 + /** + * 3rd + **/ + SC_FEAR,//309 + SC_BURNING,//310 + SC_FREEZING,//311 + /** + * Rune Knight + **/ + SC_ENCHANTBLADE,//312 + SC_DEATHBOUND,//313 + SC_MILLENNIUMSHIELD, + SC_CRUSHSTRIKE,//315 + SC_REFRESH, + SC_REUSE_REFRESH, + SC_GIANTGROWTH, + SC_STONEHARDSKIN, + SC_VITALITYACTIVATION,//320 + SC_STORMBLAST, + SC_FIGHTINGSPIRIT, + SC_ABUNDANCE, + /** + * Arch Bishop **/ - SC_SWINGDANCE, - SC_SYMPHONYOFLOVER, - SC_MOONLITSERENADE,//395 - SC_RUSHWINDMILL, - SC_ECHOSONG, - SC_HARMONIZE, - SC_VOICEOFSIREN, - SC_DEEPSLEEP,//400 - SC_SIRCLEOFNATURE, - SC_GLOOMYDAY, - SC_GLOOMYDAY_SK, - SC_SONGOFMANA, - SC_DANCEWITHWUG,//405 - SC_SATURDAYNIGHTFEVER, - SC_LERADSDEW, - SC_MELODYOFSINK, - SC_BEYONDOFWARCRY, - SC_UNLIMITEDHUMMINGVOICE,//410 - SC_SITDOWN_FORCE, - SC_NETHERWORLD, - /** - * Sura - **/ - SC_CRESCENTELBOW, - SC_CURSEDCIRCLE_ATKER, - SC_CURSEDCIRCLE_TARGET, - SC_LIGHTNINGWALK,//416 - SC_RAISINGDRAGON, - SC_GT_ENERGYGAIN, - SC_GT_CHANGE, - SC_GT_REVITALIZE, - /** - * Genetic - **/ - SC_GN_CARTBOOST,//427 - SC_THORNSTRAP, - SC_BLOODSUCKER, - SC_SMOKEPOWDER, - SC_TEARGAS, - SC_MANDRAGORA,//426 - SC_STOMACHACHE, - SC_MYSTERIOUS_POWDER, - SC_MELON_BOMB, - SC_BANANA_BOMB, - SC_BANANA_BOMB_SITDOWN,//431 - SC_SAVAGE_STEAK, - SC_COCKTAIL_WARG_BLOOD, - SC_MINOR_BBQ, - SC_SIROMA_ICE_TEA, - SC_DROCERA_HERB_STEAMED,//436 - SC_PUTTI_TAILS_NOODLES, - SC_BOOST500, - SC_FULL_SWING_K, - SC_MANA_PLUS, - SC_MUSTLE_M,//441 - SC_LIFE_FORCE_F, - SC_EXTRACT_WHITE_POTION_Z, - SC_VITATA_500, - SC_EXTRACT_SALAMINE_JUICE, - /** - * Shadow Chaser - **/ - SC__REPRODUCE,//446 - SC__AUTOSHADOWSPELL, - SC__SHADOWFORM, - SC__BODYPAINT, - SC__INVISIBILITY, - SC__DEADLYINFECT,//451 - SC__ENERVATION, - SC__GROOMY, - SC__IGNORANCE, - SC__LAZINESS, - SC__UNLUCKY,//456 - SC__WEAKNESS, - SC__STRIPACCESSORY, - SC__MANHOLE, - SC__BLOODYLUST,//460 - /** - * Elemental Spirits - **/ - SC_CIRCLE_OF_FIRE, - SC_CIRCLE_OF_FIRE_OPTION, - SC_FIRE_CLOAK, - SC_FIRE_CLOAK_OPTION, - SC_WATER_SCREEN,//465 - SC_WATER_SCREEN_OPTION, - SC_WATER_DROP, - SC_WATER_DROP_OPTION, - SC_WATER_BARRIER, - SC_WIND_STEP,//470 - SC_WIND_STEP_OPTION, - SC_WIND_CURTAIN, - SC_WIND_CURTAIN_OPTION, - SC_ZEPHYR, - SC_SOLID_SKIN,//475 - SC_SOLID_SKIN_OPTION, - SC_STONE_SHIELD, - SC_STONE_SHIELD_OPTION, - SC_POWER_OF_GAIA, - SC_PYROTECHNIC,//480 - SC_PYROTECHNIC_OPTION, - SC_HEATER, - SC_HEATER_OPTION, - SC_TROPIC, - SC_TROPIC_OPTION,//485 - SC_AQUAPLAY, - SC_AQUAPLAY_OPTION, - SC_COOLER, - SC_COOLER_OPTION, - SC_CHILLY_AIR,//490 - SC_CHILLY_AIR_OPTION, - SC_GUST, - SC_GUST_OPTION, - SC_BLAST, - SC_BLAST_OPTION,//495 - SC_WILD_STORM, - SC_WILD_STORM_OPTION, - SC_PETROLOGY, - SC_PETROLOGY_OPTION, - SC_CURSED_SOIL,//500 - SC_CURSED_SOIL_OPTION, - SC_UPHEAVAL, - SC_UPHEAVAL_OPTION, - SC_TIDAL_WEAPON, - SC_TIDAL_WEAPON_OPTION,//505 - SC_ROCK_CRUSHER, - SC_ROCK_CRUSHER_ATK, - /* Guild Aura */ - SC_LEADERSHIP, - SC_GLORYWOUNDS, - SC_SOULCOLD, //508 - SC_HAWKEYES, - /* ... */ - SC_ODINS_POWER, - SC_RAID, - /* Sorcerer .extra */ - SC_FIRE_INSIGNIA, - SC_WATER_INSIGNIA, - SC_WIND_INSIGNIA, //516 - SC_EARTH_INSIGNIA, - /* new pushcart */ - SC_PUSH_CART, - /* Warlock Spell books */ - SC_SPELLBOOK1, - SC_SPELLBOOK2, - SC_SPELLBOOK3, - SC_SPELLBOOK4, - SC_SPELLBOOK5, - SC_SPELLBOOK6, - /** - * In official server there are only 7 maximum number of spell books that can be memorized - * To increase the maximum value just add another status type before SC_MAXSPELLBOOK (ex. SC_SPELLBOOK7, SC_SPELLBOOK8 and so on) - **/ - SC_MAXSPELLBOOK, - /* Max HP & SP */ - SC_INCMHP, - SC_INCMSP, - SC_PARTYFLEE, // 531 - /** - * Kagerou & Oboro [malufett] - **/ - SC_MEIKYOUSISUI, - SC_JYUMONJIKIRI, - SC_KYOUGAKU, - SC_IZAYOI, - SC_ZENKAI, - SC_KAGEHUMI, - SC_KYOMU, - SC_KAGEMUSYA, - SC_ZANGETSU, - SC_GENSOU, - SC_AKAITSUKI, - - //homon S - SC_STYLE_CHANGE, + SC_ADORAMUS, + SC_EPICLESIS,//325 + SC_ORATIO, + SC_LAUDAAGNUS, + SC_LAUDARAMUS, + SC_RENOVATIO, + SC_EXPIATIO,//330 + SC_DUPLELIGHT, + SC_SECRAMENT, + /** + * Warlock + **/ + SC_WHITEIMPRISON, + SC_MARSHOFABYSS, + SC_RECOGNIZEDSPELL,//335 + SC_STASIS, + SC_SPHERE_1, + SC_SPHERE_2, + SC_SPHERE_3, + SC_SPHERE_4,//340 + SC_SPHERE_5, + SC_READING_SB, + SC_FREEZINGSPELL, + /** + * Ranger + **/ + SC_FEARBREEZE, + SC_ELECTRICSHOCKER,//345 + SC_WUGDASH, + SC_BITE, + SC_CAMOUFLAGE, + /** + * Mechanic + **/ + SC_ACCELERATION, + SC_HOVERING,//350 + SC_SHAPESHIFT, + SC_INFRAREDSCAN, + SC_ANALYZE, + SC_MAGNETICFIELD, + SC_NEUTRALBARRIER,//355 + SC_NEUTRALBARRIER_MASTER, + SC_STEALTHFIELD, + SC_STEALTHFIELD_MASTER, + SC_OVERHEAT, + SC_OVERHEAT_LIMITPOINT,//360 + /** + * Guillotine Cross + **/ + SC_VENOMIMPRESS, + SC_POISONINGWEAPON, + SC_WEAPONBLOCKING, + SC_CLOAKINGEXCEED, + SC_HALLUCINATIONWALK,//365 + SC_HALLUCINATIONWALK_POSTDELAY, + SC_ROLLINGCUTTER, + SC_TOXIN, + SC_PARALYSE, + SC_VENOMBLEED,//370 + SC_MAGICMUSHROOM, + SC_DEATHHURT, + SC_PYREXIA, + SC_OBLIVIONCURSE, + SC_LEECHESEND,//375 + /** + * Royal Guard + **/ + SC_REFLECTDAMAGE, + SC_FORCEOFVANGUARD, + SC_SHIELDSPELL_DEF, + SC_SHIELDSPELL_MDEF, + SC_SHIELDSPELL_REF,//380 + SC_EXEEDBREAK, + SC_PRESTIGE, + SC_BANDING, + SC_BANDING_DEFENCE, + SC_EARTHDRIVE,//385 + SC_INSPIRATION, + /** + * Sorcerer + **/ + SC_SPELLFIST, + SC_CRYSTALIZE, + SC_STRIKING, + SC_WARMER,//390 + SC_VACUUM_EXTREME, + SC_PROPERTYWALK, + /** + * Minstrel / Wanderer + **/ + SC_SWINGDANCE, + SC_SYMPHONYOFLOVER, + SC_MOONLITSERENADE,//395 + SC_RUSHWINDMILL, + SC_ECHOSONG, + SC_HARMONIZE, + SC_VOICEOFSIREN, + SC_DEEPSLEEP,//400 + SC_SIRCLEOFNATURE, + SC_GLOOMYDAY, + SC_GLOOMYDAY_SK, + SC_SONGOFMANA, + SC_DANCEWITHWUG,//405 + SC_SATURDAYNIGHTFEVER, + SC_LERADSDEW, + SC_MELODYOFSINK, + SC_BEYONDOFWARCRY, + SC_UNLIMITEDHUMMINGVOICE,//410 + SC_SITDOWN_FORCE, + SC_NETHERWORLD, + /** + * Sura + **/ + SC_CRESCENTELBOW, + SC_CURSEDCIRCLE_ATKER, + SC_CURSEDCIRCLE_TARGET, + SC_LIGHTNINGWALK,//416 + SC_RAISINGDRAGON, + SC_GT_ENERGYGAIN, + SC_GT_CHANGE, + SC_GT_REVITALIZE, + /** + * Genetic + **/ + SC_GN_CARTBOOST,//427 + SC_THORNSTRAP, + SC_BLOODSUCKER, + SC_SMOKEPOWDER, + SC_TEARGAS, + SC_MANDRAGORA,//426 + SC_STOMACHACHE, + SC_MYSTERIOUS_POWDER, + SC_MELON_BOMB, + SC_BANANA_BOMB, + SC_BANANA_BOMB_SITDOWN,//431 + SC_SAVAGE_STEAK, + SC_COCKTAIL_WARG_BLOOD, + SC_MINOR_BBQ, + SC_SIROMA_ICE_TEA, + SC_DROCERA_HERB_STEAMED,//436 + SC_PUTTI_TAILS_NOODLES, + SC_BOOST500, + SC_FULL_SWING_K, + SC_MANA_PLUS, + SC_MUSTLE_M,//441 + SC_LIFE_FORCE_F, + SC_EXTRACT_WHITE_POTION_Z, + SC_VITATA_500, + SC_EXTRACT_SALAMINE_JUICE, + /** + * Shadow Chaser + **/ + SC__REPRODUCE,//446 + SC__AUTOSHADOWSPELL, + SC__SHADOWFORM, + SC__BODYPAINT, + SC__INVISIBILITY, + SC__DEADLYINFECT,//451 + SC__ENERVATION, + SC__GROOMY, + SC__IGNORANCE, + SC__LAZINESS, + SC__UNLUCKY,//456 + SC__WEAKNESS, + SC__STRIPACCESSORY, + SC__MANHOLE, + SC__BLOODYLUST,//460 + /** + * Elemental Spirits + **/ + SC_CIRCLE_OF_FIRE, + SC_CIRCLE_OF_FIRE_OPTION, + SC_FIRE_CLOAK, + SC_FIRE_CLOAK_OPTION, + SC_WATER_SCREEN,//465 + SC_WATER_SCREEN_OPTION, + SC_WATER_DROP, + SC_WATER_DROP_OPTION, + SC_WATER_BARRIER, + SC_WIND_STEP,//470 + SC_WIND_STEP_OPTION, + SC_WIND_CURTAIN, + SC_WIND_CURTAIN_OPTION, + SC_ZEPHYR, + SC_SOLID_SKIN,//475 + SC_SOLID_SKIN_OPTION, + SC_STONE_SHIELD, + SC_STONE_SHIELD_OPTION, + SC_POWER_OF_GAIA, + SC_PYROTECHNIC,//480 + SC_PYROTECHNIC_OPTION, + SC_HEATER, + SC_HEATER_OPTION, + SC_TROPIC, + SC_TROPIC_OPTION,//485 + SC_AQUAPLAY, + SC_AQUAPLAY_OPTION, + SC_COOLER, + SC_COOLER_OPTION, + SC_CHILLY_AIR,//490 + SC_CHILLY_AIR_OPTION, + SC_GUST, + SC_GUST_OPTION, + SC_BLAST, + SC_BLAST_OPTION,//495 + SC_WILD_STORM, + SC_WILD_STORM_OPTION, + SC_PETROLOGY, + SC_PETROLOGY_OPTION, + SC_CURSED_SOIL,//500 + SC_CURSED_SOIL_OPTION, + SC_UPHEAVAL, + SC_UPHEAVAL_OPTION, + SC_TIDAL_WEAPON, + SC_TIDAL_WEAPON_OPTION,//505 + SC_ROCK_CRUSHER, + SC_ROCK_CRUSHER_ATK, + /* Guild Aura */ + SC_LEADERSHIP, + SC_GLORYWOUNDS, + SC_SOULCOLD, //508 + SC_HAWKEYES, + /* ... */ + SC_ODINS_POWER, + SC_RAID, + /* Sorcerer .extra */ + SC_FIRE_INSIGNIA, + SC_WATER_INSIGNIA, + SC_WIND_INSIGNIA, //516 + SC_EARTH_INSIGNIA, + /* new pushcart */ + SC_PUSH_CART, + /* Warlock Spell books */ + SC_SPELLBOOK1, + SC_SPELLBOOK2, + SC_SPELLBOOK3, + SC_SPELLBOOK4, + SC_SPELLBOOK5, + SC_SPELLBOOK6, +/** + * In official server there are only 7 maximum number of spell books that can be memorized + * To increase the maximum value just add another status type before SC_MAXSPELLBOOK (ex. SC_SPELLBOOK7, SC_SPELLBOOK8 and so on) + **/ + SC_MAXSPELLBOOK, + /* Max HP & SP */ + SC_INCMHP, + SC_INCMSP, + SC_PARTYFLEE, // 531 + /** + * Kagerou & Oboro [malufett] + **/ + SC_MEIKYOUSISUI, + SC_JYUMONJIKIRI, + SC_KYOUGAKU, + SC_IZAYOI, + SC_ZENKAI, + SC_KAGEHUMI, + SC_KYOMU, + SC_KAGEMUSYA, + SC_ZANGETSU, + SC_GENSOU, + SC_AKAITSUKI, + + //homon S + SC_STYLE_CHANGE, SC_GOLDENE_FERSE, SC_ANGRIFFS_MODUS, SC_ERASER_CUTTER, - SC_OVERED_BOOST, + SC_OVERED_BOOST, SC_LIGHT_OF_REGENE, SC_ASH, SC_GRANITIC_ARMOR, @@ -646,753 +646,755 @@ typedef enum sc_type { SC_PARALYSIS, SC_PAIN_KILLER, - -#ifdef RENEWAL - SC_EXTREMITYFIST2, + +#ifdef RENEWAL + SC_EXTREMITYFIST2, #endif - SC_MAX, //Automatically updated max, used in for's to check we are within bounds. + SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; // Official status change ids, used to display status icons on the client. enum si_type { - SI_BLANK = -1, - SI_PROVOKE = 0, - SI_ENDURE = 1, - SI_TWOHANDQUICKEN = 2, - SI_CONCENTRATE = 3, - SI_HIDING = 4, - SI_CLOAKING = 5, - SI_ENCPOISON = 6, - SI_POISONREACT = 7, - SI_QUAGMIRE = 8, - SI_ANGELUS = 9, - SI_BLESSING = 10, - SI_SIGNUMCRUCIS = 11, - SI_INCREASEAGI = 12, - SI_DECREASEAGI = 13, - SI_SLOWPOISON = 14, - SI_IMPOSITIO = 15, - SI_SUFFRAGIUM = 16, - SI_ASPERSIO = 17, - SI_BENEDICTIO = 18, - SI_KYRIE = 19, - SI_MAGNIFICAT = 20, - SI_GLORIA = 21, - SI_AETERNA = 22, - SI_ADRENALINE = 23, - SI_WEAPONPERFECTION = 24, - SI_OVERTHRUST = 25, - SI_MAXIMIZEPOWER = 26, - SI_RIDING = 27, - SI_FALCON = 28, - SI_TRICKDEAD = 29, - SI_LOUD = 30, - SI_ENERGYCOAT = 31, - SI_BROKENARMOR = 32, - SI_BROKENWEAPON = 33, - SI_HALLUCINATION = 34, - SI_WEIGHT50 = 35, - SI_WEIGHT90 = 36, - SI_ASPDPOTION0 = 37, - SI_ASPDPOTION1 = 38, - SI_ASPDPOTION2 = 39, - SI_ASPDPOTIONINFINITY = 40, - SI_SPEEDPOTION1 = 41, - // SI_MOVHASTE_INFINITY = 42, - // SI_AUTOCOUNTER = 43, - // SI_SPLASHER = 44, - // SI_ANKLESNARE = 45, - SI_ACTIONDELAY = 46, - // SI_NOACTION = 47, - // SI_IMPOSSIBLEPICKUP = 48, - // SI_BARRIER = 49, - SI_STRIPWEAPON = 50, - SI_STRIPSHIELD = 51, - SI_STRIPARMOR = 52, - SI_STRIPHELM = 53, - SI_CP_WEAPON = 54, - SI_CP_SHIELD = 55, - SI_CP_ARMOR = 56, - SI_CP_HELM = 57, - SI_AUTOGUARD = 58, - SI_REFLECTSHIELD = 59, - // SI_DEVOTION = 60, - SI_PROVIDENCE = 61, - SI_DEFENDER = 62, - // SI_MAGICROD = 63, - // SI_WEAPONPROPERTY = 64, - SI_AUTOSPELL = 65, - // SI_SPECIALZONE = 66, - // SI_MASK = 67, - SI_SPEARQUICKEN = 68, - // SI_BDPLAYING = 69, - // SI_WHISTLE = 70, - // SI_ASSASSINCROSS = 71, - // SI_POEMBRAGI = 72, - // SI_APPLEIDUN = 73, - // SI_HUMMING = 74, - // SI_DONTFORGETME = 75, - // SI_FORTUNEKISS = 76, - // SI_SERVICEFORYOU = 77, - // SI_RICHMANKIM = 78, - // SI_ETERNALCHAOS = 79, - // SI_DRUMBATTLEFIELD = 80, - // SI_RINGNIBELUNGEN = 81, - // SI_ROKISWEIL = 82, - // SI_INTOABYSS = 83, - // SI_SIEGFRIED = 84, - // SI_BLADESTOP = 85, - SI_EXPLOSIONSPIRITS = 86, - SI_STEELBODY = 87, - SI_EXTREMITYFIST = 88, - // SI_COMBOATTACK = 89, - SI_FIREWEAPON = 90, - SI_WATERWEAPON = 91, - SI_WINDWEAPON = 92, - SI_EARTHWEAPON = 93, - // SI_MAGICATTACK = 94, - SI_STOP = 95, - // SI_WEAPONBRAKER = 96, - SI_UNDEAD = 97, - // SI_POWERUP = 98, - // SI_AGIUP = 99, - // SI_SIEGEMODE = 100, - // SI_INVISIBLE = 101, - // SI_STATUSONE = 102, - SI_AURABLADE = 103, - SI_PARRYING = 104, - SI_CONCENTRATION = 105, - SI_TENSIONRELAX = 106, - SI_BERSERK = 107, - // SI_SACRIFICE = 108, - // SI_GOSPEL = 109, - SI_ASSUMPTIO = 110, - // SI_BASILICA = 111, - SI_LANDENDOW = 112, - SI_MAGICPOWER = 113, - SI_EDP = 114, - SI_TRUESIGHT = 115, - SI_WINDWALK = 116, - SI_MELTDOWN = 117, - SI_CARTBOOST = 118, - // SI_CHASEWALK = 119, - SI_REJECTSWORD = 120, - SI_MARIONETTE = 121, - SI_MARIONETTE2 = 122, - SI_MOONLIT = 123, - SI_BLEEDING = 124, - SI_JOINTBEAT = 125, - // SI_MINDBREAKER = 126, - // SI_MEMORIZE = 127, - // SI_FOGWALL = 128, - // SI_SPIDERWEB = 129, - SI_BABY = 130, - // SI_SUB_WEAPONPROPERTY = 131, - SI_AUTOBERSERK = 132, - SI_RUN = 133, - SI_BUMP = 134, - SI_READYSTORM = 135, - // SI_STORMKICK_READY = 136, - SI_READYDOWN = 137, - // SI_DOWNKICK_READY = 138, - SI_READYTURN = 139, - // SI_TURNKICK_READY = 140, - SI_READYCOUNTER = 141, - // SI_COUNTER_READY = 142, - SI_DODGE = 143, - // SI_DODGE_READY = 144, - SI_SPURT = 145, - SI_SHADOWWEAPON = 146, - SI_ADRENALINE2 = 147, - SI_GHOSTWEAPON = 148, - SI_SPIRIT = 149, - // SI_PLUSATTACKPOWER = 150, - // SI_PLUSMAGICPOWER = 151, - SI_DEVIL = 152, - SI_KAITE = 153, - // SI_SWOO = 154, - // SI_STAR2 = 155, - SI_KAIZEL = 156, - SI_KAAHI = 157, - SI_KAUPE = 158, - SI_SMA = 159, - SI_NIGHT = 160, - SI_ONEHAND = 161, - // SI_FRIEND = 162, - // SI_FRIENDUP = 163, - // SI_SG_WARM = 164, - SI_WARM = 165, - // 166 | The three show the exact same display: ultra red character (165, 166, 167) - // 167 | Their names would be SI_SG_SUN_WARM, SI_SG_MOON_WARM, SI_SG_STAR_WARM - // SI_EMOTION = 168, - SI_SUN_COMFORT = 169, - SI_MOON_COMFORT = 170, - SI_STAR_COMFORT = 171, - // SI_EXPUP = 172, - // SI_GDSKILL_BATTLEORDER = 173, - // SI_GDSKILL_REGENERATION = 174, - // SI_GDSKILL_POSTDELAY = 175, - // SI_RESISTHANDICAP = 176, - // SI_MAXHPPERCENT = 177, - // SI_MAXSPPERCENT = 178, - // SI_DEFENCE = 179, - // SI_SLOWDOWN = 180, - SI_PRESERVE = 181, - SI_INCSTR = 182, - // SI_NOT_EXTREMITYFIST = 183, - SI_INTRAVISION = 184, - // SI_MOVESLOW_POTION = 185, - SI_DOUBLECAST = 186, - // SI_GRAVITATION = 187, - SI_MAXOVERTHRUST = 188, - // SI_LONGING = 189, - // SI_HERMODE = 190, - SI_TAROT = 191, // the icon allows no doubt... but what is it really used for ?? [DracoRPG] - // SI_HLIF_AVOID = 192, - // SI_HFLI_FLEET = 193, - // SI_HFLI_SPEED = 194, - // SI_HLIF_CHANGE = 195, - // SI_HAMI_BLOODLUST = 196, - SI_SHRINK = 197, - SI_SIGHTBLASTER = 198, - SI_WINKCHARM = 199, - SI_CLOSECONFINE = 200, - SI_CLOSECONFINE2 = 201, - // SI_DISABLEMOVE = 202, - SI_MADNESSCANCEL = 203, //[blackhole89] - SI_GATLINGFEVER = 204, - SI_EARTHSCROLL = 205, - SI_UTSUSEMI = 206, - SI_BUNSINJYUTSU = 207, - SI_NEN = 208, - SI_ADJUSTMENT = 209, - SI_ACCURACY = 210, - // SI_NJ_SUITON = 211, - // SI_PET = 212, - // SI_MENTAL = 213, - // SI_EXPMEMORY = 214, - // SI_PERFORMANCE = 215, - // SI_GAIN = 216, - // SI_GRIFFON = 217, - // SI_DRIFT = 218, - // SI_WALLSHIFT = 219, - // SI_REINCARNATION = 220, - // SI_PATTACK = 221, - // SI_PSPEED = 222, - // SI_PDEFENSE = 223, - // SI_PCRITICAL = 224, - // SI_RANKING = 225, - // SI_PTRIPLE = 226, - // SI_DENERGY = 227, - // SI_WAVE1 = 228, - // SI_WAVE2 = 229, - // SI_WAVE3 = 230, - // SI_WAVE4 = 231, - // SI_DAURA = 232, - // SI_DFREEZER = 233, - // SI_DPUNISH = 234, - // SI_DBARRIER = 235, - // SI_DWARNING = 236, - // SI_MOUSEWHEEL = 237, - // SI_DGAUGE = 238, - // SI_DACCEL = 239, - // SI_DBLOCK = 240, - SI_FOODSTR = 241, - SI_FOODAGI = 242, - SI_FOODVIT = 243, - SI_FOODDEX = 244, - SI_FOODINT = 245, - SI_FOODLUK = 246, - SI_FOODFLEE = 247, - SI_FOODHIT = 248, - SI_FOODCRI = 249, - SI_EXPBOOST = 250, - SI_LIFEINSURANCE = 251, - SI_ITEMBOOST = 252, - SI_BOSSMAPINFO = 253, - // SI_DA_ENERGY = 254, - // SI_DA_FIRSTSLOT = 255, - // SI_DA_HEADDEF = 256, - // SI_DA_SPACE = 257, - // SI_DA_TRANSFORM = 258, - // SI_DA_ITEMREBUILD = 259, - // SI_DA_ILLUSION = 260, //All mobs display as Turtle General - // SI_DA_DARKPOWER = 261, - // SI_DA_EARPLUG = 262, - // SI_DA_CONTRACT = 263, //Bio Mob effect on you and SI_TRICKDEAD icon - // SI_DA_BLACK = 264, //For short time blurry screen - // SI_DA_MAGICCART = 265, - // SI_CRYSTAL = 266, - // SI_DA_REBUILD = 267, - // SI_DA_EDARKNESS = 268, - // SI_DA_EGUARDIAN = 269, - // SI_DA_TIMEOUT = 270, - SI_FOOD_STR_CASH = 271, - SI_FOOD_AGI_CASH = 272, - SI_FOOD_VIT_CASH = 273, - SI_FOOD_DEX_CASH = 274, - SI_FOOD_INT_CASH = 275, - SI_FOOD_LUK_CASH = 276, - SI_MERC_FLEEUP = 277, - SI_MERC_ATKUP = 278, - SI_MERC_HPUP = 279, - SI_MERC_SPUP = 280, - SI_MERC_HITUP = 281, - SI_SLOWCAST = 282, - // SI_MAGICMIRROR = 283, - // SI_STONESKIN = 284, - // SI_ANTIMAGIC = 285, - SI_CRITICALWOUND = 286, - // SI_NPC_DEFENDER = 287, - // SI_NOACTION_WAIT = 288, - SI_MOVHASTE_HORSE = 289, - SI_DEF_RATE = 290, - SI_MDEF_RATE = 291, - SI_INCHEALRATE = 292, - SI_S_LIFEPOTION = 293, - SI_L_LIFEPOTION = 294, - SI_INCCRI = 295, - SI_PLUSAVOIDVALUE = 296, - // SI_ATKER_ASPD = 297, - // SI_TARGET_ASPD = 298, - // SI_ATKER_MOVESPEED = 299, - SI_ATKER_BLOOD = 300, - SI_TARGET_BLOOD = 301, - SI_ARMOR_PROPERTY = 302, - // SI_REUSE_LIMIT_A = 303, - SI_HELLPOWER = 304, - // SI_STEAMPACK = 305, - // SI_REUSE_LIMIT_B = 306, - // SI_REUSE_LIMIT_C = 307, - // SI_REUSE_LIMIT_D = 308, - // SI_REUSE_LIMIT_E = 309, - // SI_REUSE_LIMIT_F = 310, - SI_INVINCIBLE = 311, - SI_CASH_PLUSONLYJOBEXP = 312, - SI_PARTYFLEE = 313, - // SI_ANGEL_PROTECT = 314, - SI_ENDURE_MDEF = 315, - SI_ENCHANTBLADE = 316, - SI_DEATHBOUND = 317, - SI_REFRESH = 318, - SI_GIANTGROWTH = 319, - SI_STONEHARDSKIN = 320, - SI_VITALITYACTIVATION = 321, - SI_FIGHTINGSPIRIT = 322, - SI_ABUNDANCE = 323, - SI_REUSE_MILLENNIUMSHIELD = 324, - SI_REUSE_CRUSHSTRIKE = 325, - SI_REUSE_REFRESH = 326, - SI_REUSE_STORMBLAST = 327, - SI_VENOMIMPRESS = 328, - SI_EPICLESIS = 329, - SI_ORATIO = 330, - SI_LAUDAAGNUS = 331, - SI_LAUDARAMUS = 332, - SI_CLOAKINGEXCEED = 333, - SI_HALLUCINATIONWALK = 334, - SI_HALLUCINATIONWALK_POSTDELAY = 335, - SI_RENOVATIO = 336, - SI_WEAPONBLOCKING = 337, - SI_WEAPONBLOCKING_POSTDELAY = 338, - SI_ROLLINGCUTTER = 339, - SI_EXPIATIO = 340, - SI_POISONINGWEAPON = 341, - SI_TOXIN = 342, - SI_PARALYSE = 343, - SI_VENOMBLEED = 344, - SI_MAGICMUSHROOM = 345, - SI_DEATHHURT = 346, - SI_PYREXIA = 347, - SI_OBLIVIONCURSE = 348, - SI_LEECHESEND = 349, - SI_DUPLELIGHT = 350, - SI_FROSTMISTY = 351, - SI_FEARBREEZE = 352, - SI_ELECTRICSHOCKER = 353, - SI_MARSHOFABYSS = 354, - SI_RECOGNIZEDSPELL = 355, - SI_STASIS = 356, - SI_WUGRIDER = 357, - SI_WUGDASH = 358, - SI_WUGBITE = 359, - SI_CAMOUFLAGE = 360, - SI_ACCELERATION = 361, - SI_HOVERING = 362, - SI_SPHERE_1 = 363, - SI_SPHERE_2 = 364, - SI_SPHERE_3 = 365, - SI_SPHERE_4 = 366, - SI_SPHERE_5 = 367, - SI_MVPCARD_TAOGUNKA = 368, - SI_MVPCARD_MISTRESS = 369, - SI_MVPCARD_ORCHERO = 370, - SI_MVPCARD_ORCLORD = 371, - SI_OVERHEAT_LIMITPOINT = 372, - SI_OVERHEAT = 373, - SI_SHAPESHIFT = 374, - SI_INFRAREDSCAN = 375, - SI_MAGNETICFIELD = 376, - SI_NEUTRALBARRIER = 377, - SI_NEUTRALBARRIER_MASTER = 378, - SI_STEALTHFIELD = 379, - SI_STEALTHFIELD_MASTER = 380, - SI_MANU_ATK = 381, - SI_MANU_DEF = 382, - SI_SPL_ATK = 383, - SI_SPL_DEF = 384, - SI_REPRODUCE = 385, - SI_MANU_MATK = 386, - SI_SPL_MATK = 387, - SI_STR_SCROLL = 388, - SI_INT_SCROLL = 389, - SI_LG_REFLECTDAMAGE = 390, - SI_FORCEOFVANGUARD = 391, - SI_BUCHEDENOEL = 392, - SI_AUTOSHADOWSPELL = 393, - SI_SHADOWFORM = 394, - SI_RAID = 395, - SI_SHIELDSPELL_DEF = 396, - SI_SHIELDSPELL_MDEF = 397, - SI_SHIELDSPELL_REF = 398, - SI_BODYPAINT = 399, - SI_EXEEDBREAK = 400, - SI_ADORAMUS = 401, - SI_PRESTIGE = 402, - SI_INVISIBILITY = 403, - SI_DEADLYINFECT = 404, - SI_BANDING = 405, - SI_EARTHDRIVE = 406, - SI_INSPIRATION = 407, - SI_ENERVATION = 408, - SI_GROOMY = 409, - SI_RAISINGDRAGON = 410, - SI_IGNORANCE = 411, - SI_LAZINESS = 412, - SI_LIGHTNINGWALK = 413, - SI_ACARAJE = 414, - SI_UNLUCKY = 415, - SI_CURSEDCIRCLE_ATKER = 416, - SI_CURSEDCIRCLE_TARGET = 417, - SI_WEAKNESS = 418, - SI_CRESCENTELBOW = 419, - SI_NOEQUIPACCESSARY = 420, - SI_STRIPACCESSARY = 421, - SI_MANHOLE = 422, - SI_POPECOOKIE = 423, - SI_FALLENEMPIRE = 424, - SI_GENTLETOUCH_ENERGYGAIN = 425, - SI_GENTLETOUCH_CHANGE = 426, - SI_GENTLETOUCH_REVITALIZE = 427, - SI_BLOODYLUST = 428, - SI_SWINGDANCE = 429, - SI_SYMPHONYOFLOVERS = 430, - SI_PROPERTYWALK = 431, - SI_SPELLFIST = 432, - SI_NETHERWORLD = 433, - SI_VOICEOFSIREN = 434, - SI_DEEPSLEEP = 435, - SI_SIRCLEOFNATURE = 436, - SI_COLD = 437, - SI_GLOOMYDAY = 438, - SI_SONGOFMANA = 439, - SI_CLOUDKILL = 440, - SI_DANCEWITHWUG = 441, - SI_RUSHWINDMILL = 442, - SI_ECHOSONG = 443, - SI_HARMONIZE = 444, - SI_STRIKING = 445, - SI_WARMER = 446, - SI_MOONLITSERENADE = 447, - SI_SATURDAYNIGHTFEVER = 448, - SI_SITDOWN_FORCE = 449, - SI_ANALYZE = 450, - SI_LERADSDEW = 451, - SI_MELODYOFSINK = 452, - SI_WARCRYOFBEYOND = 453, - SI_UNLIMITEDHUMMINGVOICE = 454, - SI_SPELLBOOK1 = 455, - SI_SPELLBOOK2 = 456, - SI_SPELLBOOK3 = 457, - SI_FREEZE_SP = 458, - SI_GN_TRAINING_SWORD = 459, - SI_GN_REMODELING_CART = 460, - SI_CARTSBOOST = 461, - SI_FIXEDCASTINGTM_REDUCE = 462, - SI_THORNTRAP = 463, - SI_BLOODSUCKER = 464, - SI_SPORE_EXPLOSION = 465, - SI_DEMONIC_FIRE = 466, - SI_FIRE_EXPANSION_SMOKE_POWDER = 467, - SI_FIRE_EXPANSION_TEAR_GAS = 468, - SI_BLOCKING_PLAY = 469, - SI_MANDRAGORA = 470, - SI_ACTIVATE = 471, - SI_SECRAMENT = 472, - SI_ASSUMPTIO2 = 473, - SI_TK_SEVENWIND = 474, - SI_LIMIT_ODINS_RECALL = 475, - SI_STOMACHACHE = 476, - SI_MYSTERIOUS_POWDER = 477, - SI_MELON_BOMB = 478, - SI_BANANA_BOMB_SITDOWN_POSTDELAY = 479, - SI_PROMOTE_HEALTH_RESERCH = 480, - SI_ENERGY_DRINK_RESERCH = 481, - SI_EXTRACT_WHITE_POTION_Z = 482, - SI_VITATA_500 = 483, - SI_EXTRACT_SALAMINE_JUICE = 484, - SI_BOOST500 = 485, - SI_FULL_SWING_K = 486, - SI_MANA_PLUS = 487, - SI_MUSTLE_M = 488, - SI_LIFE_FORCE_F = 489, - SI_VACUUM_EXTREME = 490, - SI_SAVAGE_STEAK = 491, - SI_COCKTAIL_WARG_BLOOD = 492, - SI_MINOR_BBQ = 493, - SI_SIROMA_ICE_TEA = 494, - SI_DROCERA_HERB_STEAMED = 495, - SI_PUTTI_TAILS_NOODLES = 496, - SI_BANANA_BOMB = 497, - SI_SUMMON_AGNI = 498, - SI_SPELLBOOK4 = 499, - SI_SPELLBOOK5 = 500, - SI_SPELLBOOK6 = 501, - SI_SPELLBOOK7 = 502, - SI_ELEMENTAL_AGGRESSIVE = 503, - SI_RETURN_TO_ELDICASTES = 504, - SI_BANDING_DEFENCE = 505, - SI_SKELSCROLL = 506, - SI_DISTRUCTIONSCROLL = 507, - SI_ROYALSCROLL = 508, - SI_IMMUNITYSCROLL = 509, - SI_MYSTICSCROLL = 510, - SI_BATTLESCROLL = 511, - SI_ARMORSCROLL = 512, - SI_FREYJASCROLL = 513, - SI_SOULSCROLL = 514, - SI_CIRCLE_OF_FIRE = 515, - SI_CIRCLE_OF_FIRE_OPTION = 516, - SI_FIRE_CLOAK = 517, - SI_FIRE_CLOAK_OPTION = 518, - SI_WATER_SCREEN = 519, - SI_WATER_SCREEN_OPTION = 520, - SI_WATER_DROP = 521, - SI_WATER_DROP_OPTION = 522, - SI_WIND_STEP = 523, - SI_WIND_STEP_OPTION = 524, - SI_WIND_CURTAIN = 525, - SI_WIND_CURTAIN_OPTION = 526, - SI_WATER_BARRIER = 527, - SI_ZEPHYR = 528, - SI_SOLID_SKIN = 529, - SI_SOLID_SKIN_OPTION = 530, - SI_STONE_SHIELD = 531, - SI_STONE_SHIELD_OPTION = 532, - SI_POWER_OF_GAIA = 533, - // SI_EL_WAIT = 534, - // SI_EL_PASSIVE = 535, - // SI_EL_DEFENSIVE = 536, - // SI_EL_OFFENSIVE = 537, - // SI_EL_COST = 538, - SI_PYROTECHNIC = 539, - SI_PYROTECHNIC_OPTION = 540, - SI_HEATER = 541, - SI_HEATER_OPTION = 542, - SI_TROPIC = 543, - SI_TROPIC_OPTION = 544, - SI_AQUAPLAY = 545, - SI_AQUAPLAY_OPTION = 546, - SI_COOLER = 547, - SI_COOLER_OPTION = 548, - SI_CHILLY_AIR = 549, - SI_CHILLY_AIR_OPTION = 550, - SI_GUST = 551, - SI_GUST_OPTION = 552, - SI_BLAST = 553, - SI_BLAST_OPTION = 554, - SI_WILD_STORM = 555, - SI_WILD_STORM_OPTION = 556, - SI_PETROLOGY = 557, - SI_PETROLOGY_OPTION = 558, - SI_CURSED_SOIL = 559, - SI_CURSED_SOIL_OPTION = 560, - SI_UPHEAVAL = 561, - SI_UPHEAVAL_OPTION = 562, - SI_TIDAL_WEAPON = 563, - SI_TIDAL_WEAPON_OPTION = 564, - SI_ROCK_CRUSHER = 565, - SI_ROCK_CRUSHER_ATK = 566, - SI_FIRE_INSIGNIA = 567, - SI_WATER_INSIGNIA = 568, - SI_WIND_INSIGNIA = 569, - SI_EARTH_INSIGNIA = 570, - SI_EQUIPED_FLOOR = 571, - SI_GUARDIAN_RECALL = 572, - SI_MORA_BUFF = 573, - SI_REUSE_LIMIT_G = 574, - SI_REUSE_LIMIT_H = 575, - SI_NEEDLE_OF_PARALYZE = 576, - SI_PAIN_KILLER = 577, - SI_G_LIFEPOTION = 578, - SI_VITALIZE_POTION = 579, - SI_LIGHT_OF_REGENE = 580, - SI_OVERED_BOOST = 581, - SI_SILENT_BREEZE = 582, - SI_ODINS_POWER = 583, - SI_STYLE_CHANGE = 584, - SI_SONIC_CLAW_POSTDELAY = 585, - // ID's 586 - 595 Currently Unused - SI_SILVERVEIN_RUSH_POSTDELAY = 596, - SI_MIDNIGHT_FRENZY_POSTDELAY = 597, - SI_GOLDENE_FERSE = 598, - SI_ANGRIFFS_MODUS = 599, - SI_TINDER_BREAKER = 600, - SI_TINDER_BREAKER_POSTDELAY = 601, - SI_CBC = 602, - SI_CBC_POSTDELAY = 603, - SI_EQC = 604, - SI_MAGMA_FLOW = 605, - SI_GRANITIC_ARMOR = 606, - SI_PYROCLASTIC = 607, - SI_VOLCANIC_ASH = 608, - SI_SPIRITS_SAVEINFO1 = 609, - SI_SPIRITS_SAVEINFO2 = 610, - SI_MAGIC_CANDY = 611, - SI_SEARCH_STORE_INFO = 612, - SI_ALL_RIDING = 613, - SI_ALL_RIDING_REUSE_LIMIT = 614, - SI_MACRO = 615, - SI_MACRO_POSTDELAY = 616, - SI_BEER_BOTTLE_CAP = 617, - SI_OVERLAPEXPUP = 618, - SI_PC_IZ_DUN05 = 619, - SI_CRUSHSTRIKE = 620, - SI_MONSTER_TRANSFORM = 621, - SI_SIT = 622, - SI_ONAIR = 623, - SI_MTF_ASPD = 624, - SI_MTF_RANGEATK = 625, - SI_MTF_MATK = 626, - SI_MTF_MLEATKED = 627, - SI_MTF_CRIDAMAGE = 628, - SI_REUSE_LIMIT_MTF = 629, - SI_MACRO_PERMIT = 630, - SI_MACRO_PLAY = 631, - SI_SKF_CAST = 632, - SI_SKF_ASPD = 633, - SI_SKF_ATK = 634, - SI_SKF_MATK = 635, - SI_REWARD_PLUSONLYJOBEXP = 636, - SI_HANDICAPSTATE_NORECOVER = 637, - SI_SET_NUM_DEF = 638, - SI_SET_NUM_MDEF = 639, - SI_SET_PER_DEF = 640, - SI_SET_PER_MDEF = 641, - SI_PARTYBOOKING_SEARCH_DEALY = 642, - SI_PARTYBOOKING_REGISTER_DEALY = 643, - SI_PERIOD_TIME_CHECK_DETECT_SKILL = 644, - SI_KO_JYUMONJIKIRI = 645, - SI_MEIKYOUSISUI = 646, - SI_ATTHASTE_CASH = 647, - SI_EQUIPPED_DIVINE_ARMOR = 648, - SI_EQUIPPED_HOLY_ARMOR = 649, - SI_2011RWC = 650, - SI_KYOUGAKU = 651, - SI_IZAYOI = 652, - SI_ZENKAI = 653, - SI_KG_KAGEHUMI = 654, - SI_KYOMU = 655, - SI_KAGEMUSYA = 656, - SI_ZANGETSU = 657, - SI_PHI_DEMON = 658, - SI_GENSOU = 659, - SI_AKAITSUKI = 660, - SI_TETANY = 661, - SI_GM_BATTLE = 662, - SI_GM_BATTLE2 = 663, - SI_2011RWC_SCROLL = 664, - SI_ACTIVE_MONSTER_TRANSFORM = 665, - SI_MYSTICPOWDER = 666, - SI_ECLAGE_RECALL = 667, - SI_ENTRY_QUEUE_APPLY_DELAY = 668, - SI_REUSE_LIMIT_ECL = 669, - SI_M_LIFEPOTION = 670, - SI_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT = 671, - SI_UNKNOWN_NAME = 672, - SI_ON_PUSH_CART = 673, - SI_HAT_EFFECT = 674, - SI_FLOWER_LEAF = 675, - SI_RAY_OF_PROTECTION = 676, - SI_GLASTHEIM_ATK = 677, - SI_GLASTHEIM_DEF = 678, - SI_GLASTHEIM_HEAL = 679, - SI_GLASTHEIM_HIDDEN = 680, - SI_GLASTHEIM_STATE = 681, - SI_GLASTHEIM_ITEMDEF = 682, - SI_GLASTHEIM_HPSP = 683, - SI_HOMUN_SKILL_POSTDELAY = 684, - SI_ALMIGHTY = 685, - SI_GVG_GIANT = 686, - SI_GVG_GOLEM = 687, - SI_GVG_STUN = 688, - SI_GVG_STONE = 689, - SI_GVG_FREEZ = 690, - SI_GVG_SLEEP = 691, - SI_GVG_CURSE = 692, - SI_GVG_SILENCE = 693, - SI_GVG_BLIND = 694, - SI_CLIENT_ONLY_EQUIP_ARROW = 695, - SI_CLAN_INFO = 696, - SI_JP_EVENT01 = 697, - SI_JP_EVENT02 = 698, - SI_JP_EVENT03 = 699, - SI_JP_EVENT04 = 700, - SI_TELEPORT_FIXEDCASTINGDELAY = 701, - SI_GEFFEN_MAGIC1 = 702, - SI_GEFFEN_MAGIC2 = 703, - SI_GEFFEN_MAGIC3 = 704, - SI_QUEST_BUFF1 = 705, - SI_QUEST_BUFF2 = 706, - SI_QUEST_BUFF3 = 707, - SI_REUSE_LIMIT_RECALL = 708, - SI_SAVEPOSITION = 709, - SI_MAX, + SI_BLANK = -1, + SI_PROVOKE = 0, + SI_ENDURE = 1, + SI_TWOHANDQUICKEN = 2, + SI_CONCENTRATE = 3, + SI_HIDING = 4, + SI_CLOAKING = 5, + SI_ENCPOISON = 6, + SI_POISONREACT = 7, + SI_QUAGMIRE = 8, + SI_ANGELUS = 9, + SI_BLESSING = 10, + SI_SIGNUMCRUCIS = 11, + SI_INCREASEAGI = 12, + SI_DECREASEAGI = 13, + SI_SLOWPOISON = 14, + SI_IMPOSITIO = 15, + SI_SUFFRAGIUM = 16, + SI_ASPERSIO = 17, + SI_BENEDICTIO = 18, + SI_KYRIE = 19, + SI_MAGNIFICAT = 20, + SI_GLORIA = 21, + SI_AETERNA = 22, + SI_ADRENALINE = 23, + SI_WEAPONPERFECTION = 24, + SI_OVERTHRUST = 25, + SI_MAXIMIZEPOWER = 26, + SI_RIDING = 27, + SI_FALCON = 28, + SI_TRICKDEAD = 29, + SI_LOUD = 30, + SI_ENERGYCOAT = 31, + SI_BROKENARMOR = 32, + SI_BROKENWEAPON = 33, + SI_HALLUCINATION = 34, + SI_WEIGHT50 = 35, + SI_WEIGHT90 = 36, + SI_ASPDPOTION0 = 37, + SI_ASPDPOTION1 = 38, + SI_ASPDPOTION2 = 39, + SI_ASPDPOTIONINFINITY = 40, + SI_SPEEDPOTION1 = 41, +// SI_MOVHASTE_INFINITY = 42, +// SI_AUTOCOUNTER = 43, +// SI_SPLASHER = 44, +// SI_ANKLESNARE = 45, + SI_ACTIONDELAY = 46, +// SI_NOACTION = 47, +// SI_IMPOSSIBLEPICKUP = 48, +// SI_BARRIER = 49, + SI_STRIPWEAPON = 50, + SI_STRIPSHIELD = 51, + SI_STRIPARMOR = 52, + SI_STRIPHELM = 53, + SI_CP_WEAPON = 54, + SI_CP_SHIELD = 55, + SI_CP_ARMOR = 56, + SI_CP_HELM = 57, + SI_AUTOGUARD = 58, + SI_REFLECTSHIELD = 59, +// SI_DEVOTION = 60, + SI_PROVIDENCE = 61, + SI_DEFENDER = 62, +// SI_MAGICROD = 63, +// SI_WEAPONPROPERTY = 64, + SI_AUTOSPELL = 65, +// SI_SPECIALZONE = 66, +// SI_MASK = 67, + SI_SPEARQUICKEN = 68, +// SI_BDPLAYING = 69, +// SI_WHISTLE = 70, +// SI_ASSASSINCROSS = 71, +// SI_POEMBRAGI = 72, +// SI_APPLEIDUN = 73, +// SI_HUMMING = 74, +// SI_DONTFORGETME = 75, +// SI_FORTUNEKISS = 76, +// SI_SERVICEFORYOU = 77, +// SI_RICHMANKIM = 78, +// SI_ETERNALCHAOS = 79, +// SI_DRUMBATTLEFIELD = 80, +// SI_RINGNIBELUNGEN = 81, +// SI_ROKISWEIL = 82, +// SI_INTOABYSS = 83, +// SI_SIEGFRIED = 84, +// SI_BLADESTOP = 85, + SI_EXPLOSIONSPIRITS = 86, + SI_STEELBODY = 87, + SI_EXTREMITYFIST = 88, +// SI_COMBOATTACK = 89, + SI_FIREWEAPON = 90, + SI_WATERWEAPON = 91, + SI_WINDWEAPON = 92, + SI_EARTHWEAPON = 93, +// SI_MAGICATTACK = 94, + SI_STOP = 95, +// SI_WEAPONBRAKER = 96, + SI_UNDEAD = 97, +// SI_POWERUP = 98, +// SI_AGIUP = 99, +// SI_SIEGEMODE = 100, +// SI_INVISIBLE = 101, +// SI_STATUSONE = 102, + SI_AURABLADE = 103, + SI_PARRYING = 104, + SI_CONCENTRATION = 105, + SI_TENSIONRELAX = 106, + SI_BERSERK = 107, +// SI_SACRIFICE = 108, +// SI_GOSPEL = 109, + SI_ASSUMPTIO = 110, +// SI_BASILICA = 111, + SI_LANDENDOW = 112, + SI_MAGICPOWER = 113, + SI_EDP = 114, + SI_TRUESIGHT = 115, + SI_WINDWALK = 116, + SI_MELTDOWN = 117, + SI_CARTBOOST = 118, +// SI_CHASEWALK = 119, + SI_REJECTSWORD = 120, + SI_MARIONETTE = 121, + SI_MARIONETTE2 = 122, + SI_MOONLIT = 123, + SI_BLEEDING = 124, + SI_JOINTBEAT = 125, +// SI_MINDBREAKER = 126, +// SI_MEMORIZE = 127, +// SI_FOGWALL = 128, +// SI_SPIDERWEB = 129, + SI_BABY = 130, +// SI_SUB_WEAPONPROPERTY = 131, + SI_AUTOBERSERK = 132, + SI_RUN = 133, + SI_BUMP = 134, + SI_READYSTORM = 135, +// SI_STORMKICK_READY = 136, + SI_READYDOWN = 137, +// SI_DOWNKICK_READY = 138, + SI_READYTURN = 139, +// SI_TURNKICK_READY = 140, + SI_READYCOUNTER = 141, +// SI_COUNTER_READY = 142, + SI_DODGE = 143, +// SI_DODGE_READY = 144, + SI_SPURT = 145, + SI_SHADOWWEAPON = 146, + SI_ADRENALINE2 = 147, + SI_GHOSTWEAPON = 148, + SI_SPIRIT = 149, +// SI_PLUSATTACKPOWER = 150, +// SI_PLUSMAGICPOWER = 151, + SI_DEVIL = 152, + SI_KAITE = 153, +// SI_SWOO = 154, +// SI_STAR2 = 155, + SI_KAIZEL = 156, + SI_KAAHI = 157, + SI_KAUPE = 158, + SI_SMA = 159, + SI_NIGHT = 160, + SI_ONEHAND = 161, +// SI_FRIEND = 162, +// SI_FRIENDUP = 163, +// SI_SG_WARM = 164, + SI_WARM = 165, +// 166 | The three show the exact same display: ultra red character (165, 166, 167) +// 167 | Their names would be SI_SG_SUN_WARM, SI_SG_MOON_WARM, SI_SG_STAR_WARM +// SI_EMOTION = 168, + SI_SUN_COMFORT = 169, + SI_MOON_COMFORT = 170, + SI_STAR_COMFORT = 171, +// SI_EXPUP = 172, +// SI_GDSKILL_BATTLEORDER = 173, +// SI_GDSKILL_REGENERATION = 174, +// SI_GDSKILL_POSTDELAY = 175, +// SI_RESISTHANDICAP = 176, +// SI_MAXHPPERCENT = 177, +// SI_MAXSPPERCENT = 178, +// SI_DEFENCE = 179, +// SI_SLOWDOWN = 180, + SI_PRESERVE = 181, + SI_INCSTR = 182, +// SI_NOT_EXTREMITYFIST = 183, + SI_INTRAVISION = 184, +// SI_MOVESLOW_POTION = 185, + SI_DOUBLECAST = 186, +// SI_GRAVITATION = 187, + SI_MAXOVERTHRUST = 188, +// SI_LONGING = 189, +// SI_HERMODE = 190, + SI_TAROT = 191, // the icon allows no doubt... but what is it really used for ?? [DracoRPG] +// SI_HLIF_AVOID = 192, +// SI_HFLI_FLEET = 193, +// SI_HFLI_SPEED = 194, +// SI_HLIF_CHANGE = 195, +// SI_HAMI_BLOODLUST = 196, + SI_SHRINK = 197, + SI_SIGHTBLASTER = 198, + SI_WINKCHARM = 199, + SI_CLOSECONFINE = 200, + SI_CLOSECONFINE2 = 201, +// SI_DISABLEMOVE = 202, + SI_MADNESSCANCEL = 203, //[blackhole89] + SI_GATLINGFEVER = 204, + SI_EARTHSCROLL = 205, + SI_UTSUSEMI = 206, + SI_BUNSINJYUTSU = 207, + SI_NEN = 208, + SI_ADJUSTMENT = 209, + SI_ACCURACY = 210, +// SI_NJ_SUITON = 211, +// SI_PET = 212, +// SI_MENTAL = 213, +// SI_EXPMEMORY = 214, +// SI_PERFORMANCE = 215, +// SI_GAIN = 216, +// SI_GRIFFON = 217, +// SI_DRIFT = 218, +// SI_WALLSHIFT = 219, +// SI_REINCARNATION = 220, +// SI_PATTACK = 221, +// SI_PSPEED = 222, +// SI_PDEFENSE = 223, +// SI_PCRITICAL = 224, +// SI_RANKING = 225, +// SI_PTRIPLE = 226, +// SI_DENERGY = 227, +// SI_WAVE1 = 228, +// SI_WAVE2 = 229, +// SI_WAVE3 = 230, +// SI_WAVE4 = 231, +// SI_DAURA = 232, +// SI_DFREEZER = 233, +// SI_DPUNISH = 234, +// SI_DBARRIER = 235, +// SI_DWARNING = 236, +// SI_MOUSEWHEEL = 237, +// SI_DGAUGE = 238, +// SI_DACCEL = 239, +// SI_DBLOCK = 240, + SI_FOODSTR = 241, + SI_FOODAGI = 242, + SI_FOODVIT = 243, + SI_FOODDEX = 244, + SI_FOODINT = 245, + SI_FOODLUK = 246, + SI_FOODFLEE = 247, + SI_FOODHIT = 248, + SI_FOODCRI = 249, + SI_EXPBOOST = 250, + SI_LIFEINSURANCE = 251, + SI_ITEMBOOST = 252, + SI_BOSSMAPINFO = 253, +// SI_DA_ENERGY = 254, +// SI_DA_FIRSTSLOT = 255, +// SI_DA_HEADDEF = 256, +// SI_DA_SPACE = 257, +// SI_DA_TRANSFORM = 258, +// SI_DA_ITEMREBUILD = 259, +// SI_DA_ILLUSION = 260, //All mobs display as Turtle General +// SI_DA_DARKPOWER = 261, +// SI_DA_EARPLUG = 262, +// SI_DA_CONTRACT = 263, //Bio Mob effect on you and SI_TRICKDEAD icon +// SI_DA_BLACK = 264, //For short time blurry screen +// SI_DA_MAGICCART = 265, +// SI_CRYSTAL = 266, +// SI_DA_REBUILD = 267, +// SI_DA_EDARKNESS = 268, +// SI_DA_EGUARDIAN = 269, +// SI_DA_TIMEOUT = 270, + SI_FOOD_STR_CASH = 271, + SI_FOOD_AGI_CASH = 272, + SI_FOOD_VIT_CASH = 273, + SI_FOOD_DEX_CASH = 274, + SI_FOOD_INT_CASH = 275, + SI_FOOD_LUK_CASH = 276, + SI_MERC_FLEEUP = 277, + SI_MERC_ATKUP = 278, + SI_MERC_HPUP = 279, + SI_MERC_SPUP = 280, + SI_MERC_HITUP = 281, + SI_SLOWCAST = 282, +// SI_MAGICMIRROR = 283, +// SI_STONESKIN = 284, +// SI_ANTIMAGIC = 285, + SI_CRITICALWOUND = 286, +// SI_NPC_DEFENDER = 287, +// SI_NOACTION_WAIT = 288, + SI_MOVHASTE_HORSE = 289, + SI_DEF_RATE = 290, + SI_MDEF_RATE = 291, + SI_INCHEALRATE = 292, + SI_S_LIFEPOTION = 293, + SI_L_LIFEPOTION = 294, + SI_INCCRI = 295, + SI_PLUSAVOIDVALUE = 296, +// SI_ATKER_ASPD = 297, +// SI_TARGET_ASPD = 298, +// SI_ATKER_MOVESPEED = 299, + SI_ATKER_BLOOD = 300, + SI_TARGET_BLOOD = 301, + SI_ARMOR_PROPERTY = 302, +// SI_REUSE_LIMIT_A = 303, + SI_HELLPOWER = 304, +// SI_STEAMPACK = 305, +// SI_REUSE_LIMIT_B = 306, +// SI_REUSE_LIMIT_C = 307, +// SI_REUSE_LIMIT_D = 308, +// SI_REUSE_LIMIT_E = 309, +// SI_REUSE_LIMIT_F = 310, + SI_INVINCIBLE = 311, + SI_CASH_PLUSONLYJOBEXP = 312, + SI_PARTYFLEE = 313, +// SI_ANGEL_PROTECT = 314, + SI_ENDURE_MDEF = 315, + SI_ENCHANTBLADE = 316, + SI_DEATHBOUND = 317, + SI_REFRESH = 318, + SI_GIANTGROWTH = 319, + SI_STONEHARDSKIN = 320, + SI_VITALITYACTIVATION = 321, + SI_FIGHTINGSPIRIT = 322, + SI_ABUNDANCE = 323, + SI_REUSE_MILLENNIUMSHIELD = 324, + SI_REUSE_CRUSHSTRIKE = 325, + SI_REUSE_REFRESH = 326, + SI_REUSE_STORMBLAST = 327, + SI_VENOMIMPRESS = 328, + SI_EPICLESIS = 329, + SI_ORATIO = 330, + SI_LAUDAAGNUS = 331, + SI_LAUDARAMUS = 332, + SI_CLOAKINGEXCEED = 333, + SI_HALLUCINATIONWALK = 334, + SI_HALLUCINATIONWALK_POSTDELAY = 335, + SI_RENOVATIO = 336, + SI_WEAPONBLOCKING = 337, + SI_WEAPONBLOCKING_POSTDELAY = 338, + SI_ROLLINGCUTTER = 339, + SI_EXPIATIO = 340, + SI_POISONINGWEAPON = 341, + SI_TOXIN = 342, + SI_PARALYSE = 343, + SI_VENOMBLEED = 344, + SI_MAGICMUSHROOM = 345, + SI_DEATHHURT = 346, + SI_PYREXIA = 347, + SI_OBLIVIONCURSE = 348, + SI_LEECHESEND = 349, + SI_DUPLELIGHT = 350, + SI_FROSTMISTY = 351, + SI_FEARBREEZE = 352, + SI_ELECTRICSHOCKER = 353, + SI_MARSHOFABYSS = 354, + SI_RECOGNIZEDSPELL = 355, + SI_STASIS = 356, + SI_WUGRIDER = 357, + SI_WUGDASH = 358, + SI_WUGBITE = 359, + SI_CAMOUFLAGE = 360, + SI_ACCELERATION = 361, + SI_HOVERING = 362, + SI_SPHERE_1 = 363, + SI_SPHERE_2 = 364, + SI_SPHERE_3 = 365, + SI_SPHERE_4 = 366, + SI_SPHERE_5 = 367, + SI_MVPCARD_TAOGUNKA = 368, + SI_MVPCARD_MISTRESS = 369, + SI_MVPCARD_ORCHERO = 370, + SI_MVPCARD_ORCLORD = 371, + SI_OVERHEAT_LIMITPOINT = 372, + SI_OVERHEAT = 373, + SI_SHAPESHIFT = 374, + SI_INFRAREDSCAN = 375, + SI_MAGNETICFIELD = 376, + SI_NEUTRALBARRIER = 377, + SI_NEUTRALBARRIER_MASTER = 378, + SI_STEALTHFIELD = 379, + SI_STEALTHFIELD_MASTER = 380, + SI_MANU_ATK = 381, + SI_MANU_DEF = 382, + SI_SPL_ATK = 383, + SI_SPL_DEF = 384, + SI_REPRODUCE = 385, + SI_MANU_MATK = 386, + SI_SPL_MATK = 387, + SI_STR_SCROLL = 388, + SI_INT_SCROLL = 389, + SI_LG_REFLECTDAMAGE = 390, + SI_FORCEOFVANGUARD = 391, + SI_BUCHEDENOEL = 392, + SI_AUTOSHADOWSPELL = 393, + SI_SHADOWFORM = 394, + SI_RAID = 395, + SI_SHIELDSPELL_DEF = 396, + SI_SHIELDSPELL_MDEF = 397, + SI_SHIELDSPELL_REF = 398, + SI_BODYPAINT = 399, + SI_EXEEDBREAK = 400, + SI_ADORAMUS = 401, + SI_PRESTIGE = 402, + SI_INVISIBILITY = 403, + SI_DEADLYINFECT = 404, + SI_BANDING = 405, + SI_EARTHDRIVE = 406, + SI_INSPIRATION = 407, + SI_ENERVATION = 408, + SI_GROOMY = 409, + SI_RAISINGDRAGON = 410, + SI_IGNORANCE = 411, + SI_LAZINESS = 412, + SI_LIGHTNINGWALK = 413, + SI_ACARAJE = 414, + SI_UNLUCKY = 415, + SI_CURSEDCIRCLE_ATKER = 416, + SI_CURSEDCIRCLE_TARGET = 417, + SI_WEAKNESS = 418, + SI_CRESCENTELBOW = 419, + SI_NOEQUIPACCESSARY = 420, + SI_STRIPACCESSARY = 421, + SI_MANHOLE = 422, + SI_POPECOOKIE = 423, + SI_FALLENEMPIRE = 424, + SI_GENTLETOUCH_ENERGYGAIN = 425, + SI_GENTLETOUCH_CHANGE = 426, + SI_GENTLETOUCH_REVITALIZE = 427, + SI_BLOODYLUST = 428, + SI_SWINGDANCE = 429, + SI_SYMPHONYOFLOVERS = 430, + SI_PROPERTYWALK = 431, + SI_SPELLFIST = 432, + SI_NETHERWORLD = 433, + SI_VOICEOFSIREN = 434, + SI_DEEPSLEEP = 435, + SI_SIRCLEOFNATURE = 436, + SI_COLD = 437, + SI_GLOOMYDAY = 438, + SI_SONGOFMANA = 439, + SI_CLOUDKILL = 440, + SI_DANCEWITHWUG = 441, + SI_RUSHWINDMILL = 442, + SI_ECHOSONG = 443, + SI_HARMONIZE = 444, + SI_STRIKING = 445, + SI_WARMER = 446, + SI_MOONLITSERENADE = 447, + SI_SATURDAYNIGHTFEVER = 448, + SI_SITDOWN_FORCE = 449, + SI_ANALYZE = 450, + SI_LERADSDEW = 451, + SI_MELODYOFSINK = 452, + SI_WARCRYOFBEYOND = 453, + SI_UNLIMITEDHUMMINGVOICE = 454, + SI_SPELLBOOK1 = 455, + SI_SPELLBOOK2 = 456, + SI_SPELLBOOK3 = 457, + SI_FREEZE_SP = 458, + SI_GN_TRAINING_SWORD = 459, + SI_GN_REMODELING_CART = 460, + SI_CARTSBOOST = 461, + SI_FIXEDCASTINGTM_REDUCE = 462, + SI_THORNTRAP = 463, + SI_BLOODSUCKER = 464, + SI_SPORE_EXPLOSION = 465, + SI_DEMONIC_FIRE = 466, + SI_FIRE_EXPANSION_SMOKE_POWDER = 467, + SI_FIRE_EXPANSION_TEAR_GAS = 468, + SI_BLOCKING_PLAY = 469, + SI_MANDRAGORA = 470, + SI_ACTIVATE = 471, + SI_SECRAMENT = 472, + SI_ASSUMPTIO2 = 473, + SI_TK_SEVENWIND = 474, + SI_LIMIT_ODINS_RECALL = 475, + SI_STOMACHACHE = 476, + SI_MYSTERIOUS_POWDER = 477, + SI_MELON_BOMB = 478, + SI_BANANA_BOMB_SITDOWN_POSTDELAY = 479, + SI_PROMOTE_HEALTH_RESERCH = 480, + SI_ENERGY_DRINK_RESERCH = 481, + SI_EXTRACT_WHITE_POTION_Z = 482, + SI_VITATA_500 = 483, + SI_EXTRACT_SALAMINE_JUICE = 484, + SI_BOOST500 = 485, + SI_FULL_SWING_K = 486, + SI_MANA_PLUS = 487, + SI_MUSTLE_M = 488, + SI_LIFE_FORCE_F = 489, + SI_VACUUM_EXTREME = 490, + SI_SAVAGE_STEAK = 491, + SI_COCKTAIL_WARG_BLOOD = 492, + SI_MINOR_BBQ = 493, + SI_SIROMA_ICE_TEA = 494, + SI_DROCERA_HERB_STEAMED = 495, + SI_PUTTI_TAILS_NOODLES = 496, + SI_BANANA_BOMB = 497, + SI_SUMMON_AGNI = 498, + SI_SPELLBOOK4 = 499, + SI_SPELLBOOK5 = 500, + SI_SPELLBOOK6 = 501, + SI_SPELLBOOK7 = 502, + SI_ELEMENTAL_AGGRESSIVE = 503, + SI_RETURN_TO_ELDICASTES = 504, + SI_BANDING_DEFENCE = 505, + SI_SKELSCROLL = 506, + SI_DISTRUCTIONSCROLL = 507, + SI_ROYALSCROLL = 508, + SI_IMMUNITYSCROLL = 509, + SI_MYSTICSCROLL = 510, + SI_BATTLESCROLL = 511, + SI_ARMORSCROLL = 512, + SI_FREYJASCROLL = 513, + SI_SOULSCROLL = 514, + SI_CIRCLE_OF_FIRE = 515, + SI_CIRCLE_OF_FIRE_OPTION = 516, + SI_FIRE_CLOAK = 517, + SI_FIRE_CLOAK_OPTION = 518, + SI_WATER_SCREEN = 519, + SI_WATER_SCREEN_OPTION = 520, + SI_WATER_DROP = 521, + SI_WATER_DROP_OPTION = 522, + SI_WIND_STEP = 523, + SI_WIND_STEP_OPTION = 524, + SI_WIND_CURTAIN = 525, + SI_WIND_CURTAIN_OPTION = 526, + SI_WATER_BARRIER = 527, + SI_ZEPHYR = 528, + SI_SOLID_SKIN = 529, + SI_SOLID_SKIN_OPTION = 530, + SI_STONE_SHIELD = 531, + SI_STONE_SHIELD_OPTION = 532, + SI_POWER_OF_GAIA = 533, + // SI_EL_WAIT = 534, + // SI_EL_PASSIVE = 535, + // SI_EL_DEFENSIVE = 536, + // SI_EL_OFFENSIVE = 537, + // SI_EL_COST = 538, + SI_PYROTECHNIC = 539, + SI_PYROTECHNIC_OPTION = 540, + SI_HEATER = 541, + SI_HEATER_OPTION = 542, + SI_TROPIC = 543, + SI_TROPIC_OPTION = 544, + SI_AQUAPLAY = 545, + SI_AQUAPLAY_OPTION = 546, + SI_COOLER = 547, + SI_COOLER_OPTION = 548, + SI_CHILLY_AIR = 549, + SI_CHILLY_AIR_OPTION = 550, + SI_GUST = 551, + SI_GUST_OPTION = 552, + SI_BLAST = 553, + SI_BLAST_OPTION = 554, + SI_WILD_STORM = 555, + SI_WILD_STORM_OPTION = 556, + SI_PETROLOGY = 557, + SI_PETROLOGY_OPTION = 558, + SI_CURSED_SOIL = 559, + SI_CURSED_SOIL_OPTION = 560, + SI_UPHEAVAL = 561, + SI_UPHEAVAL_OPTION = 562, + SI_TIDAL_WEAPON = 563, + SI_TIDAL_WEAPON_OPTION = 564, + SI_ROCK_CRUSHER = 565, + SI_ROCK_CRUSHER_ATK = 566, + SI_FIRE_INSIGNIA = 567, + SI_WATER_INSIGNIA = 568, + SI_WIND_INSIGNIA = 569, + SI_EARTH_INSIGNIA = 570, + SI_EQUIPED_FLOOR = 571, + SI_GUARDIAN_RECALL = 572, + SI_MORA_BUFF = 573, + SI_REUSE_LIMIT_G = 574, + SI_REUSE_LIMIT_H = 575, + SI_NEEDLE_OF_PARALYZE = 576, + SI_PAIN_KILLER = 577, + SI_G_LIFEPOTION = 578, + SI_VITALIZE_POTION = 579, + SI_LIGHT_OF_REGENE = 580, + SI_OVERED_BOOST = 581, + SI_SILENT_BREEZE = 582, + SI_ODINS_POWER = 583, + SI_STYLE_CHANGE = 584, + SI_SONIC_CLAW_POSTDELAY = 585, + // ID's 586 - 595 Currently Unused + SI_SILVERVEIN_RUSH_POSTDELAY = 596, + SI_MIDNIGHT_FRENZY_POSTDELAY = 597, + SI_GOLDENE_FERSE = 598, + SI_ANGRIFFS_MODUS = 599, + SI_TINDER_BREAKER = 600, + SI_TINDER_BREAKER_POSTDELAY = 601, + SI_CBC = 602, + SI_CBC_POSTDELAY = 603, + SI_EQC = 604, + SI_MAGMA_FLOW = 605, + SI_GRANITIC_ARMOR = 606, + SI_PYROCLASTIC = 607, + SI_VOLCANIC_ASH = 608, + SI_SPIRITS_SAVEINFO1 = 609, + SI_SPIRITS_SAVEINFO2 = 610, + SI_MAGIC_CANDY = 611, + SI_SEARCH_STORE_INFO = 612, + SI_ALL_RIDING = 613, + SI_ALL_RIDING_REUSE_LIMIT = 614, + SI_MACRO = 615, + SI_MACRO_POSTDELAY = 616, + SI_BEER_BOTTLE_CAP = 617, + SI_OVERLAPEXPUP = 618, + SI_PC_IZ_DUN05 = 619, + SI_CRUSHSTRIKE = 620, + SI_MONSTER_TRANSFORM = 621, + SI_SIT = 622, + SI_ONAIR = 623, + SI_MTF_ASPD = 624, + SI_MTF_RANGEATK = 625, + SI_MTF_MATK = 626, + SI_MTF_MLEATKED = 627, + SI_MTF_CRIDAMAGE = 628, + SI_REUSE_LIMIT_MTF = 629, + SI_MACRO_PERMIT = 630, + SI_MACRO_PLAY = 631, + SI_SKF_CAST = 632, + SI_SKF_ASPD = 633, + SI_SKF_ATK = 634, + SI_SKF_MATK = 635, + SI_REWARD_PLUSONLYJOBEXP = 636, + SI_HANDICAPSTATE_NORECOVER = 637, + SI_SET_NUM_DEF = 638, + SI_SET_NUM_MDEF = 639, + SI_SET_PER_DEF = 640, + SI_SET_PER_MDEF = 641, + SI_PARTYBOOKING_SEARCH_DEALY = 642, + SI_PARTYBOOKING_REGISTER_DEALY = 643, + SI_PERIOD_TIME_CHECK_DETECT_SKILL = 644, + SI_KO_JYUMONJIKIRI = 645, + SI_MEIKYOUSISUI = 646, + SI_ATTHASTE_CASH = 647, + SI_EQUIPPED_DIVINE_ARMOR = 648, + SI_EQUIPPED_HOLY_ARMOR = 649, + SI_2011RWC = 650, + SI_KYOUGAKU = 651, + SI_IZAYOI = 652, + SI_ZENKAI = 653, + SI_KG_KAGEHUMI = 654, + SI_KYOMU = 655, + SI_KAGEMUSYA = 656, + SI_ZANGETSU = 657, + SI_PHI_DEMON = 658, + SI_GENSOU = 659, + SI_AKAITSUKI = 660, + SI_TETANY = 661, + SI_GM_BATTLE = 662, + SI_GM_BATTLE2 = 663, + SI_2011RWC_SCROLL = 664, + SI_ACTIVE_MONSTER_TRANSFORM = 665, + SI_MYSTICPOWDER = 666, + SI_ECLAGE_RECALL = 667, + SI_ENTRY_QUEUE_APPLY_DELAY = 668, + SI_REUSE_LIMIT_ECL = 669, + SI_M_LIFEPOTION = 670, + SI_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT = 671, + SI_UNKNOWN_NAME = 672, + SI_ON_PUSH_CART = 673, + SI_HAT_EFFECT = 674, + SI_FLOWER_LEAF = 675, + SI_RAY_OF_PROTECTION = 676, + SI_GLASTHEIM_ATK = 677, + SI_GLASTHEIM_DEF = 678, + SI_GLASTHEIM_HEAL = 679, + SI_GLASTHEIM_HIDDEN = 680, + SI_GLASTHEIM_STATE = 681, + SI_GLASTHEIM_ITEMDEF = 682, + SI_GLASTHEIM_HPSP = 683, + SI_HOMUN_SKILL_POSTDELAY = 684, + SI_ALMIGHTY = 685, + SI_GVG_GIANT = 686, + SI_GVG_GOLEM = 687, + SI_GVG_STUN = 688, + SI_GVG_STONE = 689, + SI_GVG_FREEZ = 690, + SI_GVG_SLEEP = 691, + SI_GVG_CURSE = 692, + SI_GVG_SILENCE = 693, + SI_GVG_BLIND = 694, + SI_CLIENT_ONLY_EQUIP_ARROW = 695, + SI_CLAN_INFO = 696, + SI_JP_EVENT01 = 697, + SI_JP_EVENT02 = 698, + SI_JP_EVENT03 = 699, + SI_JP_EVENT04 = 700, + SI_TELEPORT_FIXEDCASTINGDELAY = 701, + SI_GEFFEN_MAGIC1 = 702, + SI_GEFFEN_MAGIC2 = 703, + SI_GEFFEN_MAGIC3 = 704, + SI_QUEST_BUFF1 = 705, + SI_QUEST_BUFF2 = 706, + SI_QUEST_BUFF3 = 707, + SI_REUSE_LIMIT_RECALL = 708, + SI_SAVEPOSITION = 709, + SI_MAX, }; // JOINTBEAT stackable ailments -enum e_joint_break { - BREAK_ANKLE = 0x01, // MoveSpeed reduced by 50% - BREAK_WRIST = 0x02, // ASPD reduced by 25% - BREAK_KNEE = 0x04, // MoveSpeed reduced by 30%, ASPD reduced by 10% - BREAK_SHOULDER = 0x08, // DEF reduced by 50% - BREAK_WAIST = 0x10, // DEF reduced by 25%, ATK reduced by 25% - BREAK_NECK = 0x20, // current attack does 2x damage, inflicts 'bleeding' for 30 seconds - BREAK_FLAGS = BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK, +enum e_joint_break +{ + BREAK_ANKLE = 0x01, // MoveSpeed reduced by 50% + BREAK_WRIST = 0x02, // ASPD reduced by 25% + BREAK_KNEE = 0x04, // MoveSpeed reduced by 30%, ASPD reduced by 10% + BREAK_SHOULDER = 0x08, // DEF reduced by 50% + BREAK_WAIST = 0x10, // DEF reduced by 25%, ATK reduced by 25% + BREAK_NECK = 0x20, // current attack does 2x damage, inflicts 'bleeding' for 30 seconds + BREAK_FLAGS = BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK, }; extern int current_equip_item_index; extern int current_equip_card_id; //Mode definitions to clear up code reading. [Skotlex] -enum e_mode { - MD_CANMOVE = 0x0001, - MD_LOOTER = 0x0002, - MD_AGGRESSIVE = 0x0004, - MD_ASSIST = 0x0008, - MD_CASTSENSOR_IDLE = 0x0010, - MD_BOSS = 0x0020, - MD_PLANT = 0x0040, - MD_CANATTACK = 0x0080, - MD_DETECTOR = 0x0100, - MD_CASTSENSOR_CHASE = 0x0200, - MD_CHANGECHASE = 0x0400, - MD_ANGRY = 0x0800, - MD_CHANGETARGET_MELEE = 0x1000, - MD_CHANGETARGET_CHASE = 0x2000, - MD_TARGETWEAK = 0x4000, - MD_MASK = 0xFFFF, +enum e_mode +{ + MD_CANMOVE = 0x0001, + MD_LOOTER = 0x0002, + MD_AGGRESSIVE = 0x0004, + MD_ASSIST = 0x0008, + MD_CASTSENSOR_IDLE = 0x0010, + MD_BOSS = 0x0020, + MD_PLANT = 0x0040, + MD_CANATTACK = 0x0080, + MD_DETECTOR = 0x0100, + MD_CASTSENSOR_CHASE = 0x0200, + MD_CHANGECHASE = 0x0400, + MD_ANGRY = 0x0800, + MD_CHANGETARGET_MELEE = 0x1000, + MD_CHANGETARGET_CHASE = 0x2000, + MD_TARGETWEAK = 0x4000, + MD_MASK = 0xFFFF, }; //Status change option definitions (options are what makes status changes visible to chars @@ -1400,153 +1402,155 @@ enum e_mode { //opt1: Non stackable status changes. enum { - OPT1_STONE = 1, //Petrified - OPT1_FREEZE, - OPT1_STUN, - OPT1_SLEEP, - //Aegis uses OPT1 = 5 to identify undead enemies (which also grants them immunity to the other opt1 changes) - OPT1_STONEWAIT=6, //Petrifying - OPT1_BURNING, - OPT1_IMPRISON, - OPT1_CRYSTALIZE, + OPT1_STONE = 1, //Petrified + OPT1_FREEZE, + OPT1_STUN, + OPT1_SLEEP, + //Aegis uses OPT1 = 5 to identify undead enemies (which also grants them immunity to the other opt1 changes) + OPT1_STONEWAIT=6, //Petrifying + OPT1_BURNING, + OPT1_IMPRISON, + OPT1_CRYSTALIZE, }; //opt2: Stackable status changes. enum { - OPT2_POISON = 0x0001, - OPT2_CURSE = 0x0002, - OPT2_SILENCE = 0x0004, - OPT2_SIGNUMCRUCIS = 0x0008, - OPT2_BLIND = 0x0010, - OPT2_ANGELUS = 0x0020, - OPT2_BLEEDING = 0x0040, - OPT2_DPOISON = 0x0080, - OPT2_FEAR = 0x0100, + OPT2_POISON = 0x0001, + OPT2_CURSE = 0x0002, + OPT2_SILENCE = 0x0004, + OPT2_SIGNUMCRUCIS = 0x0008, + OPT2_BLIND = 0x0010, + OPT2_ANGELUS = 0x0020, + OPT2_BLEEDING = 0x0040, + OPT2_DPOISON = 0x0080, + OPT2_FEAR = 0x0100, }; //opt3: (SHOW_EFST_*) enum { - OPT3_NORMAL = 0x00000000, - OPT3_QUICKEN = 0x00000001, - OPT3_OVERTHRUST = 0x00000002, - OPT3_ENERGYCOAT = 0x00000004, - OPT3_EXPLOSIONSPIRITS = 0x00000008, - OPT3_STEELBODY = 0x00000010, - OPT3_BLADESTOP = 0x00000020, - OPT3_AURABLADE = 0x00000040, - OPT3_BERSERK = 0x00000080, - OPT3_LIGHTBLADE = 0x00000100, - OPT3_MOONLIT = 0x00000200, - OPT3_MARIONETTE = 0x00000400, - OPT3_ASSUMPTIO = 0x00000800, - OPT3_WARM = 0x00001000, - OPT3_KAITE = 0x00002000, - OPT3_BUNSIN = 0x00004000, - OPT3_SOULLINK = 0x00008000, - OPT3_UNDEAD = 0x00010000, - OPT3_CONTRACT = 0x00020000, + OPT3_NORMAL = 0x00000000, + OPT3_QUICKEN = 0x00000001, + OPT3_OVERTHRUST = 0x00000002, + OPT3_ENERGYCOAT = 0x00000004, + OPT3_EXPLOSIONSPIRITS = 0x00000008, + OPT3_STEELBODY = 0x00000010, + OPT3_BLADESTOP = 0x00000020, + OPT3_AURABLADE = 0x00000040, + OPT3_BERSERK = 0x00000080, + OPT3_LIGHTBLADE = 0x00000100, + OPT3_MOONLIT = 0x00000200, + OPT3_MARIONETTE = 0x00000400, + OPT3_ASSUMPTIO = 0x00000800, + OPT3_WARM = 0x00001000, + OPT3_KAITE = 0x00002000, + OPT3_BUNSIN = 0x00004000, + OPT3_SOULLINK = 0x00008000, + OPT3_UNDEAD = 0x00010000, + OPT3_CONTRACT = 0x00020000, }; enum { - OPTION_NOTHING = 0x00000000, - OPTION_SIGHT = 0x00000001, - OPTION_HIDE = 0x00000002, - OPTION_CLOAK = 0x00000004, - OPTION_FALCON = 0x00000010, - OPTION_RIDING = 0x00000020, - OPTION_INVISIBLE = 0x00000040, - OPTION_ORCISH = 0x00000800, - OPTION_WEDDING = 0x00001000, - OPTION_RUWACH = 0x00002000, - OPTION_CHASEWALK = 0x00004000, - OPTION_FLYING = 0x00008000, //Note that clientside Flying and Xmas are 0x8000 for clients prior to 2007. - OPTION_XMAS = 0x00010000, - OPTION_TRANSFORM = 0x00020000, - OPTION_SUMMER = 0x00040000, - OPTION_DRAGON1 = 0x00080000, - OPTION_WUG = 0x00100000, - OPTION_WUGRIDER = 0x00200000, - OPTION_MADOGEAR = 0x00400000, - OPTION_DRAGON2 = 0x00800000, - OPTION_DRAGON3 = 0x01000000, - OPTION_DRAGON4 = 0x02000000, - OPTION_DRAGON5 = 0x04000000, - OPTION_MOUNTING = 0x08000000, - + OPTION_NOTHING = 0x00000000, + OPTION_SIGHT = 0x00000001, + OPTION_HIDE = 0x00000002, + OPTION_CLOAK = 0x00000004, + OPTION_FALCON = 0x00000010, + OPTION_RIDING = 0x00000020, + OPTION_INVISIBLE = 0x00000040, + OPTION_ORCISH = 0x00000800, + OPTION_WEDDING = 0x00001000, + OPTION_RUWACH = 0x00002000, + OPTION_CHASEWALK = 0x00004000, + OPTION_FLYING = 0x00008000, //Note that clientside Flying and Xmas are 0x8000 for clients prior to 2007. + OPTION_XMAS = 0x00010000, + OPTION_TRANSFORM = 0x00020000, + OPTION_SUMMER = 0x00040000, + OPTION_DRAGON1 = 0x00080000, + OPTION_WUG = 0x00100000, + OPTION_WUGRIDER = 0x00200000, + OPTION_MADOGEAR = 0x00400000, + OPTION_DRAGON2 = 0x00800000, + OPTION_DRAGON3 = 0x01000000, + OPTION_DRAGON4 = 0x02000000, + OPTION_DRAGON5 = 0x04000000, + OPTION_MOUNTING = 0x08000000, + #ifndef NEW_CARTS - OPTION_CART1 = 0x00000008, - OPTION_CART2 = 0x00000080, - OPTION_CART3 = 0x00000100, - OPTION_CART4 = 0x00000200, - OPTION_CART5 = 0x00000400, - - /* compound constant for older carts */ - OPTION_CART = OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5, + OPTION_CART1 = 0x00000008, + OPTION_CART2 = 0x00000080, + OPTION_CART3 = 0x00000100, + OPTION_CART4 = 0x00000200, + OPTION_CART5 = 0x00000400, + + /* compound constant for older carts */ + OPTION_CART = OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5, #endif - - // compound constants - OPTION_DRAGON = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5, - OPTION_MASK = ~OPTION_INVISIBLE, + + // compound constants + OPTION_DRAGON = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5, + OPTION_MASK = ~OPTION_INVISIBLE, }; //Defines for the manner system [Skotlex] -enum manner_flags { - MANNER_NOCHAT = 0x01, - MANNER_NOSKILL = 0x02, - MANNER_NOCOMMAND = 0x04, - MANNER_NOITEM = 0x08, - MANNER_NOROOM = 0x10, +enum manner_flags +{ + MANNER_NOCHAT = 0x01, + MANNER_NOSKILL = 0x02, + MANNER_NOCOMMAND = 0x04, + MANNER_NOITEM = 0x08, + MANNER_NOROOM = 0x10, }; /* Status Change State Flags */ enum scs_flag { - SCS_NOMOVECOND = 0x00000001, /* cond flag for nomove */ - SCS_NOMOVE = 0x00000002, /* unit unable to move */ - SCS_NOPICKITEMCOND = 0x00000004, /* cond flag for nopickitem */ - SCS_NOPICKITEM = 0x00000008, /* player unable to pick up items */ - SCS_NODROPITEMCOND = 0x00000010, /* cond flag for nodropitem */ - SCS_NODROPITEM = 0x00000020, /* player unable to drop items */ - SCS_NOCASTCOND = 0x00000040, /* cond flag for nocast */ - SCS_NOCAST = 0x00000080, /* unit unable to cast skills */ + SCS_NOMOVECOND = 0x00000001, /* cond flag for nomove */ + SCS_NOMOVE = 0x00000002, /* unit unable to move */ + SCS_NOPICKITEMCOND = 0x00000004, /* cond flag for nopickitem */ + SCS_NOPICKITEM = 0x00000008, /* player unable to pick up items */ + SCS_NODROPITEMCOND = 0x00000010, /* cond flag for nodropitem */ + SCS_NODROPITEM = 0x00000020, /* player unable to drop items */ + SCS_NOCASTCOND = 0x00000040, /* cond flag for nocast */ + SCS_NOCAST = 0x00000080, /* unit unable to cast skills */ }; //Define flags for the status_calc_bl function. [Skotlex] -enum scb_flag { - SCB_NONE = 0x00000000, - SCB_BASE = 0x00000001, - SCB_MAXHP = 0x00000002, - SCB_MAXSP = 0x00000004, - SCB_STR = 0x00000008, - SCB_AGI = 0x00000010, - SCB_VIT = 0x00000020, - SCB_INT = 0x00000040, - SCB_DEX = 0x00000080, - SCB_LUK = 0x00000100, - SCB_BATK = 0x00000200, - SCB_WATK = 0x00000400, - SCB_MATK = 0x00000800, - SCB_HIT = 0x00001000, - SCB_FLEE = 0x00002000, - SCB_DEF = 0x00004000, - SCB_DEF2 = 0x00008000, - SCB_MDEF = 0x00010000, - SCB_MDEF2 = 0x00020000, - SCB_SPEED = 0x00040000, - SCB_ASPD = 0x00080000, - SCB_DSPD = 0x00100000, - SCB_CRI = 0x00200000, - SCB_FLEE2 = 0x00400000, - SCB_ATK_ELE = 0x00800000, - SCB_DEF_ELE = 0x01000000, - SCB_MODE = 0x02000000, - SCB_SIZE = 0x04000000, - SCB_RACE = 0x08000000, - SCB_RANGE = 0x10000000, - SCB_REGEN = 0x20000000, - SCB_DYE = 0x40000000, // force cloth-dye change to 0 to avoid client crashes. +enum scb_flag +{ + SCB_NONE = 0x00000000, + SCB_BASE = 0x00000001, + SCB_MAXHP = 0x00000002, + SCB_MAXSP = 0x00000004, + SCB_STR = 0x00000008, + SCB_AGI = 0x00000010, + SCB_VIT = 0x00000020, + SCB_INT = 0x00000040, + SCB_DEX = 0x00000080, + SCB_LUK = 0x00000100, + SCB_BATK = 0x00000200, + SCB_WATK = 0x00000400, + SCB_MATK = 0x00000800, + SCB_HIT = 0x00001000, + SCB_FLEE = 0x00002000, + SCB_DEF = 0x00004000, + SCB_DEF2 = 0x00008000, + SCB_MDEF = 0x00010000, + SCB_MDEF2 = 0x00020000, + SCB_SPEED = 0x00040000, + SCB_ASPD = 0x00080000, + SCB_DSPD = 0x00100000, + SCB_CRI = 0x00200000, + SCB_FLEE2 = 0x00400000, + SCB_ATK_ELE = 0x00800000, + SCB_DEF_ELE = 0x01000000, + SCB_MODE = 0x02000000, + SCB_SIZE = 0x04000000, + SCB_RACE = 0x08000000, + SCB_RANGE = 0x10000000, + SCB_REGEN = 0x20000000, + SCB_DYE = 0x40000000, // force cloth-dye change to 0 to avoid client crashes. - SCB_BATTLE = 0x3FFFFFFE, - SCB_ALL = 0x3FFFFFFF + SCB_BATTLE = 0x3FFFFFFE, + SCB_ALL = 0x3FFFFFFF }; //Define to determine who gets HP/SP consumed on doing skills/etc. [Skotlex] @@ -1560,119 +1564,122 @@ enum scb_flag { //Required because players have two of these, one in status_data //and another for their left hand weapon. struct weapon_atk { - unsigned short atk, atk2; - unsigned short range; - unsigned char ele; -#ifdef RENEWAL - unsigned short matk, wlv; -#endif + unsigned short atk, atk2; + unsigned short range; + unsigned char ele; }; //For holding basic status (which can be modified by status changes) struct status_data { - unsigned int - hp, sp, // see status_cpy before adding members before hp and sp - max_hp, max_sp; - unsigned short - str, agi, vit, int_, dex, luk, - batk, - matk_min, matk_max, - speed, - amotion, adelay, dmotion, - mode; - short - hit, flee, cri, flee2, - def2, mdef2, + unsigned int + hp, sp, // see status_cpy before adding members before hp and sp + max_hp, max_sp; + unsigned short + str, agi, vit, int_, dex, luk, + batk, + matk_min, matk_max, + speed, + amotion, adelay, dmotion, + mode; + short + hit, flee, cri, flee2, + def2, mdef2, #ifdef RENEWAL_ASPD - aspd_rate2, + aspd_rate2, #endif - aspd_rate; - /** - * defType is RENEWAL dependent and defined in src/map/config/data/const.h - **/ - defType def,mdef; + aspd_rate; + /** + * defType is RENEWAL dependent and defined in src/map/config/data/const.h + **/ + defType def,mdef; - unsigned char - def_ele, ele_lv, - size, race; + unsigned char + def_ele, ele_lv, +#ifdef RENEWAL + /** + * in RE weapon level is used in several areas, keeping it here saves performance + **/ + wlv, +#endif + size, race; - struct weapon_atk rhw, lhw; //Right Hand/Left Hand Weapon. + struct weapon_atk rhw, lhw; //Right Hand/Left Hand Weapon. }; //Additional regen data that only players have. struct regen_data_sub { - unsigned short - hp,sp; + unsigned short + hp,sp; - //tick accumulation before healing. - struct { - unsigned int hp,sp; - } tick; - - //Regen rates (where every 1 means +100% regen) - struct { - unsigned char hp,sp; - } rate; + //tick accumulation before healing. + struct { + unsigned int hp,sp; + } tick; + + //Regen rates (where every 1 means +100% regen) + struct { + unsigned char hp,sp; + } rate; }; struct regen_data { - unsigned short flag; //Marks what stuff you may heal or not. - unsigned short - hp,sp,shp,ssp; - - //tick accumulation before healing. - struct { - unsigned int hp,sp,shp,ssp; - } tick; + unsigned short flag; //Marks what stuff you may heal or not. + unsigned short + hp,sp,shp,ssp; - //Regen rates (where every 1 means +100% regen) - struct { - unsigned char - hp,sp,shp,ssp; - } rate; + //tick accumulation before healing. + struct { + unsigned int hp,sp,shp,ssp; + } tick; + + //Regen rates (where every 1 means +100% regen) + struct { + unsigned char + hp,sp,shp,ssp; + } rate; + + struct { + unsigned walk:1; //Can you regen even when walking? + unsigned gc:1; //Tags when you should have double regen due to GVG castle + unsigned overweight :2; //overweight state (1: 50%, 2: 90%) + unsigned block :2; //Block regen flag (1: Hp, 2: Sp) + } state; - struct { - unsigned walk:1; //Can you regen even when walking? - unsigned gc:1; //Tags when you should have double regen due to GVG castle - unsigned overweight :2; //overweight state (1: 50%, 2: 90%) - unsigned block :2; //Block regen flag (1: Hp, 2: Sp) - } state; - - //skill-regen, sitting-skill-regen (since not all chars with regen need it) - struct regen_data_sub *sregen, *ssregen; + //skill-regen, sitting-skill-regen (since not all chars with regen need it) + struct regen_data_sub *sregen, *ssregen; }; struct status_change_entry { - int timer; - int val1,val2,val3,val4; + int timer; + int val1,val2,val3,val4; }; struct status_change { - unsigned int option;// effect state (bitfield) - unsigned int opt3;// skill state (bitfield) - unsigned short opt1;// body state - unsigned short opt2;// health state (bitfield) - unsigned char count; - //TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive. - unsigned char jb_flag; //Joint Beat type flag - struct { - unsigned char move; - unsigned char pickup; - unsigned char drop; - unsigned char cast; - } cant;/* status change state flags */ - //int sg_id; //ID of the previous Storm gust that hit you - short comet_x, comet_y; // Point where src casted Comet - required to calculate damage from this point - /** - * The Storm Gust counter was dropped in renewal - **/ + unsigned int option;// effect state (bitfield) + unsigned int opt3;// skill state (bitfield) + unsigned short opt1;// body state + unsigned short opt2;// health state (bitfield) + unsigned char count; + //TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive. + unsigned char jb_flag; //Joint Beat type flag + struct { + unsigned char move; + unsigned char pickup; + unsigned char drop; + unsigned char cast; + } cant;/* status change state flags */ + //int sg_id; //ID of the previous Storm gust that hit you + short comet_x, comet_y; // Point where src casted Comet - required to calculate damage from this point +/** + * The Storm Gust counter was dropped in renewal + **/ #ifndef RENEWAL - unsigned char sg_counter; //Storm gust counter (previous hits from storm gust) + unsigned char sg_counter; //Storm gust counter (previous hits from storm gust) #endif - unsigned char bs_counter; // Blood Sucker counter - struct status_change_entry *data[SC_MAX]; + unsigned char bs_counter; // Blood Sucker counter + struct status_change_entry *data[SC_MAX]; }; // for looking up associated data @@ -1687,7 +1694,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp,int sp //Define for standard HP/SP damage triggers. #define status_zap(bl, hp, sp) status_damage(NULL, bl, hp, sp, 0, 1) //Define for standard HP/SP skill-related cost triggers (mobs require no HP/SP to use skills) -int status_charge(struct block_list *bl, int hp, int sp); +int status_charge(struct block_list* bl, int hp, int sp); int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag); //Easier handling of status_percent_change #define status_percent_heal(bl, hp_rate, sp_rate) status_percent_change(NULL, bl, -(hp_rate), -(sp_rate), 0) @@ -1703,7 +1710,7 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per struct regen_data *status_get_regen_data(struct block_list *bl); struct status_data *status_get_status_data(struct block_list *bl); struct status_data *status_get_base_status(struct block_list *bl); -const char *status_get_name(struct block_list *bl); +const char * status_get_name(struct block_list *bl); int status_get_class(struct block_list *bl); int status_get_lv(struct block_list *bl); #define status_get_range(bl) status_get_status_data(bl)->rhw.range @@ -1745,6 +1752,12 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch #define status_get_race(bl) status_get_status_data(bl)->race #define status_get_size(bl) status_get_status_data(bl)->size #define status_get_mode(bl) status_get_status_data(bl)->mode +#ifdef RENEWAL + /** + * in RE weapon level is used in several areas, keeping it here saves performance + **/ + #define status_get_wlv(bl) status_get_status_data(bl)->wlv +#endif int status_get_party_id(struct block_list *bl); int status_get_guild_id(struct block_list *bl); int status_get_emblem_id(struct block_list *bl); @@ -1765,14 +1778,14 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti #define sc_start2(bl, type, rate, val1, val2, tick) status_change_start(bl,type,100*(rate),val1,val2,0,0,tick,0) #define sc_start4(bl, type, rate, val1, val2, val3, val4, tick) status_change_start(bl,type,100*(rate),val1,val2,val3,val4,tick,0) -int status_change_start(struct block_list *bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag); -int status_change_end_(struct block_list *bl, enum sc_type type, int tid, const char *file, int line); +int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag); +int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line); #define status_change_end(bl,type,tid) status_change_end_(bl,type,tid,__FILE__,__LINE__) int kaahi_heal_timer(int tid, unsigned int tick, int id, intptr_t data); int status_change_timer(int tid, unsigned int tick, int id, intptr_t data); -int status_change_timer_sub(struct block_list *bl, va_list ap); -int status_change_clear(struct block_list *bl, int type); -int status_change_clear_buffs(struct block_list *bl, int type); +int status_change_timer_sub(struct block_list* bl, va_list ap); +int status_change_clear(struct block_list* bl, int type); +int status_change_clear_buffs(struct block_list* bl, int type); #define status_calc_bl(bl, flag) status_calc_bl_(bl, (enum scb_flag)(flag), false) #define status_calc_mob(md, first) status_calc_bl_(&(md)->bl, SCB_ALL, first) @@ -1783,9 +1796,9 @@ int status_change_clear_buffs(struct block_list *bl, int type); #define status_calc_elemental(ed, first) status_calc_bl_(&(ed)->bl, SCB_ALL, first) void status_calc_bl_(struct block_list *bl, enum scb_flag flag, bool first); -int status_calc_mob_(struct mob_data *md, bool first); -int status_calc_pet_(struct pet_data *pd, bool first); -int status_calc_pc_(struct map_session_data *sd, bool first); +int status_calc_mob_(struct mob_data* md, bool first); +int status_calc_pet_(struct pet_data* pd, bool first); +int status_calc_pc_(struct map_session_data* sd, bool first); int status_calc_homunculus_(struct homun_data *hd, bool first); int status_calc_mercenary_(struct mercenary_data *md, bool first); int status_calc_elemental_(struct elemental_data *ed, bool first); @@ -1797,11 +1810,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str int status_check_skilluse(struct block_list *src, struct block_list *target, int skill_num, int flag); // [Skotlex] int status_check_visibility(struct block_list *src, struct block_list *target); //[Skotlex] -int status_change_spread(struct block_list *src, struct block_list *bl); - -#ifdef RENEWAL -unsigned short status_base_matk(const struct status_data* status, int level); -#endif +int status_change_spread( struct block_list *src, struct block_list *bl ); int status_readdb(void); int do_init_status(void); diff --git a/src/map/storage.c b/src/map/storage.c index e75891608..c66f12852 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -24,33 +24,34 @@ #include <string.h> -static DBMap *guild_storage_db; // int guild_id -> struct guild_storage* +static DBMap* guild_storage_db; // int guild_id -> struct guild_storage* /*========================================== * Sort items in the warehouse *------------------------------------------*/ static int storage_comp_item(const void *_i1, const void *_i2) { - struct item *i1 = (struct item *)_i1; - struct item *i2 = (struct item *)_i2; - - if (i1->nameid == i2->nameid) - return 0; - else if (!(i1->nameid) || !(i1->amount)) - return 1; - else if (!(i2->nameid) || !(i2->amount)) - return -1; - return i1->nameid - i2->nameid; + struct item *i1 = (struct item *)_i1; + struct item *i2 = (struct item *)_i2; + + if (i1->nameid == i2->nameid) + return 0; + else if (!(i1->nameid) || !(i1->amount)) + return 1; + else if (!(i2->nameid) || !(i2->amount)) + return -1; + return i1->nameid - i2->nameid; } //Sort item by storage_comp_item (nameid) -static void storage_sortitem(struct item *items, unsigned int size) +static void storage_sortitem(struct item* items, unsigned int size) { - nullpo_retv(items); + nullpo_retv(items); - if (battle_config.client_sort_storage) { - qsort(items, size, sizeof(struct item), storage_comp_item); - } + if( battle_config.client_sort_storage ) + { + qsort(items, size, sizeof(struct item), storage_comp_item); + } } /*========================================== @@ -58,12 +59,12 @@ static void storage_sortitem(struct item *items, unsigned int size) *------------------------------------------*/ int do_init_storage(void) // Called from map.c::do_init() { - guild_storage_db=idb_alloc(DB_OPT_RELEASE_DATA); - return 1; + guild_storage_db=idb_alloc(DB_OPT_RELEASE_DATA); + return 1; } void do_final_storage(void) // by [MC Cameri] { - guild_storage_db->destroy(guild_storage_db,NULL); + guild_storage_db->destroy(guild_storage_db,NULL); } /** @@ -72,17 +73,17 @@ void do_final_storage(void) // by [MC Cameri] */ static int storage_reconnect_sub(DBKey key, DBData *data, va_list ap) { - struct guild_storage *stor = db_data2ptr(data); - if (stor->dirty && stor->storage_status == 0) //Save closed storages. - storage_guild_storagesave(0, stor->guild_id,0); + struct guild_storage *stor = db_data2ptr(data); + if (stor->dirty && stor->storage_status == 0) //Save closed storages. + storage_guild_storagesave(0, stor->guild_id,0); - return 0; + return 0; } //Function to be invoked upon server reconnection to char. To save all 'dirty' storages [Skotlex] void do_reconnect_storage(void) { - guild_storage_db->foreach(guild_storage_db, storage_reconnect_sub); + guild_storage_db->foreach(guild_storage_db, storage_reconnect_sub); } /*========================================== @@ -92,22 +93,22 @@ void do_reconnect_storage(void) *------------------------------------------*/ int storage_storageopen(struct map_session_data *sd) { - nullpo_ret(sd); - - if (sd->state.storage_flag) - return 1; //Already open? - - if (!pc_can_give_items(sd)) { - //check is this GM level is allowed to put items to storage - clif_displaymessage(sd->fd, msg_txt(246)); - return 1; - } - - sd->state.storage_flag = 1; - storage_sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); - clif_storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); - clif_updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); - return 0; + nullpo_ret(sd); + + if(sd->state.storage_flag) + return 1; //Already open? + + if( !pc_can_give_items(sd) ) + { //check is this GM level is allowed to put items to storage + clif_displaymessage(sd->fd, msg_txt(246)); + return 1; + } + + sd->state.storage_flag = 1; + storage_sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); + clif_storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); + clif_updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); + return 0; } /* helper function @@ -115,229 +116,232 @@ int storage_storageopen(struct map_session_data *sd) */ int compare_item(struct item *a, struct item *b) { - if (a->nameid == b->nameid && - a->identify == b->identify && - a->refine == b->refine && - a->attribute == b->attribute && - a->expire_time == b->expire_time) { - int i; - for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++); - return (i == MAX_SLOTS); - } - return 0; + if( a->nameid == b->nameid && + a->identify == b->identify && + a->refine == b->refine && + a->attribute == b->attribute && + a->expire_time == b->expire_time ) + { + int i; + for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++); + return (i == MAX_SLOTS); + } + return 0; } /*========================================== * Internal add-item function. *------------------------------------------*/ -static int storage_additem(struct map_session_data *sd, struct item *item_data, int amount) +static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount) { - struct storage_data *stor = &sd->status.storage; - struct item_data *data; - int i; - - if (item_data->nameid <= 0 || amount <= 0) - return 1; - - data = itemdb_search(item_data->nameid); - - if (data->stack.storage && amount > data->stack.amount) { - // item stack limitation - return 1; - } - - if (!itemdb_canstore(item_data, pc_get_group_level(sd))) { - //Check if item is storable. [Skotlex] - clif_displaymessage(sd->fd, msg_txt(264)); - return 1; - } - - if (itemdb_isstackable2(data)) { - //Stackable - for (i = 0; i < MAX_STORAGE; i++) { - if (compare_item(&stor->items[i], item_data)) { - // existing items found, stack them - if (amount > MAX_AMOUNT - stor->items[i].amount || (data->stack.storage && amount > data->stack.amount - stor->items[i].amount)) - return 1; - stor->items[i].amount += amount; - clif_storageitemadded(sd,&stor->items[i],i,amount); - return 0; - } - } - } - - // find free slot - ARR_FIND(0, MAX_STORAGE, i, stor->items[i].nameid == 0); - if (i >= MAX_STORAGE) - return 1; - - // add item to slot - memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); - stor->storage_amount++; - stor->items[i].amount = amount; - clif_storageitemadded(sd,&stor->items[i],i,amount); - clif_updatestorageamount(sd, stor->storage_amount, MAX_STORAGE); - - return 0; + struct storage_data* stor = &sd->status.storage; + struct item_data *data; + int i; + + if( item_data->nameid <= 0 || amount <= 0 ) + return 1; + + data = itemdb_search(item_data->nameid); + + if( data->stack.storage && amount > data->stack.amount ) + {// item stack limitation + return 1; + } + + if( !itemdb_canstore(item_data, pc_get_group_level(sd)) ) + { //Check if item is storable. [Skotlex] + clif_displaymessage (sd->fd, msg_txt(264)); + return 1; + } + + if( itemdb_isstackable2(data) ) + {//Stackable + for( i = 0; i < MAX_STORAGE; i++ ) + { + if( compare_item(&stor->items[i], item_data) ) + {// existing items found, stack them + if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) ) + return 1; + stor->items[i].amount += amount; + clif_storageitemadded(sd,&stor->items[i],i,amount); + return 0; + } + } + } + + // find free slot + ARR_FIND( 0, MAX_STORAGE, i, stor->items[i].nameid == 0 ); + if( i >= MAX_STORAGE ) + return 1; + + // add item to slot + memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); + stor->storage_amount++; + stor->items[i].amount = amount; + clif_storageitemadded(sd,&stor->items[i],i,amount); + clif_updatestorageamount(sd, stor->storage_amount, MAX_STORAGE); + + return 0; } /*========================================== * Internal del-item function *------------------------------------------*/ -int storage_delitem(struct map_session_data *sd, int n, int amount) +int storage_delitem(struct map_session_data* sd, int n, int amount) { - if (sd->status.storage.items[n].nameid == 0 || sd->status.storage.items[n].amount < amount) - return 1; - - sd->status.storage.items[n].amount -= amount; - if (sd->status.storage.items[n].amount == 0) { - memset(&sd->status.storage.items[n],0,sizeof(sd->status.storage.items[0])); - sd->status.storage.storage_amount--; - if (sd->state.storage_flag == 1) clif_updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); - } - if (sd->state.storage_flag == 1) clif_storageitemremoved(sd,n,amount); - return 0; + if( sd->status.storage.items[n].nameid == 0 || sd->status.storage.items[n].amount < amount ) + return 1; + + sd->status.storage.items[n].amount -= amount; + if( sd->status.storage.items[n].amount == 0 ) + { + memset(&sd->status.storage.items[n],0,sizeof(sd->status.storage.items[0])); + sd->status.storage.storage_amount--; + if( sd->state.storage_flag == 1 ) clif_updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); + } + if( sd->state.storage_flag == 1 ) clif_storageitemremoved(sd,n,amount); + return 0; } /*========================================== * Add an item to the storage from the inventory. * @index : inventory idx * return - * 0 : fail - * 1 : success + * 0 : fail + * 1 : success *------------------------------------------*/ -int storage_storageadd(struct map_session_data *sd, int index, int amount) +int storage_storageadd(struct map_session_data* sd, int index, int amount) { - nullpo_ret(sd); + nullpo_ret(sd); - if (sd->status.storage.storage_amount > MAX_STORAGE) - return 0; // storage full + if( sd->status.storage.storage_amount > MAX_STORAGE ) + return 0; // storage full - if (index < 0 || index >= MAX_INVENTORY) - return 0; + if( index < 0 || index >= MAX_INVENTORY ) + return 0; - if (sd->status.inventory[index].nameid <= 0) - return 0; // No item on that spot + if( sd->status.inventory[index].nameid <= 0 ) + return 0; // No item on that spot - if (amount < 1 || amount > sd->status.inventory[index].amount) - return 0; + if( amount < 1 || amount > sd->status.inventory[index].amount ) + return 0; - if (storage_additem(sd,&sd->status.inventory[index],amount) == 0) - pc_delitem(sd,index,amount,0,4,LOG_TYPE_STORAGE); + if( storage_additem(sd,&sd->status.inventory[index],amount) == 0 ) + pc_delitem(sd,index,amount,0,4,LOG_TYPE_STORAGE); - return 1; + return 1; } /*========================================== * Retrieve an item from the storage into inventory * @index : storage idx * return - * 0 : fail - * 1 : success + * 0 : fail + * 1 : success *------------------------------------------*/ -int storage_storageget(struct map_session_data *sd, int index, int amount) +int storage_storageget(struct map_session_data* sd, int index, int amount) { - int flag; + int flag; - if (index < 0 || index >= MAX_STORAGE) - return 0; + if( index < 0 || index >= MAX_STORAGE ) + return 0; - if (sd->status.storage.items[index].nameid <= 0) - return 0; //Nothing there + if( sd->status.storage.items[index].nameid <= 0 ) + return 0; //Nothing there + + if( amount < 1 || amount > sd->status.storage.items[index].amount ) + return 0; - if (amount < 1 || amount > sd->status.storage.items[index].amount) - return 0; + if( (flag = pc_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 ) + storage_delitem(sd,index,amount); + else + clif_additem(sd,0,0,flag); - if ((flag = pc_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0) - storage_delitem(sd,index,amount); - else - clif_additem(sd,0,0,flag); - - return 1; + return 1; } /*========================================== * Move an item from cart to storage. * @index : cart inventory index * return - * 0 : fail - * 1 : success + * 0 : fail + * 1 : success *------------------------------------------*/ -int storage_storageaddfromcart(struct map_session_data *sd, int index, int amount) +int storage_storageaddfromcart(struct map_session_data* sd, int index, int amount) { - nullpo_ret(sd); - - if (sd->status.storage.storage_amount > MAX_STORAGE) - return 0; // storage full / storage closed + nullpo_ret(sd); - if (index < 0 || index >= MAX_CART) - return 0; + if( sd->status.storage.storage_amount > MAX_STORAGE ) + return 0; // storage full / storage closed - if (sd->status.cart[index].nameid <= 0) - return 0; //No item there. + if( index < 0 || index >= MAX_CART ) + return 0; - if (amount < 1 || amount > sd->status.cart[index].amount) - return 0; + if( sd->status.cart[index].nameid <= 0 ) + return 0; //No item there. + + if( amount < 1 || amount > sd->status.cart[index].amount ) + return 0; - if (storage_additem(sd,&sd->status.cart[index],amount) == 0) - pc_cart_delitem(sd,index,amount,0,LOG_TYPE_STORAGE); + if( storage_additem(sd,&sd->status.cart[index],amount) == 0 ) + pc_cart_delitem(sd,index,amount,0,LOG_TYPE_STORAGE); - return 1; + return 1; } /*========================================== * Get from Storage to the Cart inventory * @index : storage index * return - * 0 : fail - * 1 : success + * 0 : fail + * 1 : success *------------------------------------------*/ -int storage_storagegettocart(struct map_session_data *sd, int index, int amount) +int storage_storagegettocart(struct map_session_data* sd, int index, int amount) { - nullpo_ret(sd); - - if (index < 0 || index >= MAX_STORAGE) - return 0; - - if (sd->status.storage.items[index].nameid <= 0) - return 0; //Nothing there. - - if (amount < 1 || amount > sd->status.storage.items[index].amount) - return 0; - - if (pc_cart_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE) == 0) - storage_delitem(sd,index,amount); - - return 1; + nullpo_ret(sd); + + if( index < 0 || index >= MAX_STORAGE ) + return 0; + + if( sd->status.storage.items[index].nameid <= 0 ) + return 0; //Nothing there. + + if( amount < 1 || amount > sd->status.storage.items[index].amount ) + return 0; + + if( pc_cart_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE) == 0 ) + storage_delitem(sd,index,amount); + + return 1; } /*========================================== * Modified By Valaris to save upon closing [massdriller] *------------------------------------------*/ -void storage_storageclose(struct map_session_data *sd) +void storage_storageclose(struct map_session_data* sd) { - nullpo_retv(sd); + nullpo_retv(sd); - clif_storageclose(sd); + clif_storageclose(sd); - if (save_settings&4) - chrif_save(sd,0); //Invokes the storage saving as well. + if( save_settings&4 ) + chrif_save(sd,0); //Invokes the storage saving as well. - sd->state.storage_flag = 0; + sd->state.storage_flag = 0; } /*========================================== * When quitting the game. *------------------------------------------*/ -void storage_storage_quit(struct map_session_data *sd, int flag) +void storage_storage_quit(struct map_session_data* sd, int flag) { - nullpo_retv(sd); + nullpo_retv(sd); + + if (save_settings&4) + chrif_save(sd, flag); //Invokes the storage saving as well. - if (save_settings&4) - chrif_save(sd, flag); //Invokes the storage saving as well. - - sd->state.storage_flag = 0; + sd->state.storage_flag = 0; } /** @@ -345,370 +349,374 @@ void storage_storage_quit(struct map_session_data *sd, int flag) */ static DBData create_guildstorage(DBKey key, va_list args) { - struct guild_storage *gs = NULL; - gs = (struct guild_storage *) aCalloc(sizeof(struct guild_storage), 1); - gs->guild_id=key.i; - return db_ptr2data(gs); + struct guild_storage *gs = NULL; + gs = (struct guild_storage *) aCalloc(sizeof(struct guild_storage), 1); + gs->guild_id=key.i; + return db_ptr2data(gs); } -struct guild_storage *guild2storage(int guild_id) { - struct guild_storage *gs = NULL; - if (guild_search(guild_id) != NULL) - gs = idb_ensure(guild_storage_db,guild_id,create_guildstorage); - return gs; +struct guild_storage *guild2storage(int guild_id) +{ + struct guild_storage *gs = NULL; + if(guild_search(guild_id) != NULL) + gs = idb_ensure(guild_storage_db,guild_id,create_guildstorage); + return gs; } //For just locating a storage without creating one. [Skotlex] -struct guild_storage *guild2storage2(int guild_id) { - return (struct guild_storage *)idb_get(guild_storage_db,guild_id); +struct guild_storage *guild2storage2(int guild_id) +{ + return (struct guild_storage*)idb_get(guild_storage_db,guild_id); } int guild_storage_delete(int guild_id) { - idb_remove(guild_storage_db,guild_id); - return 0; + idb_remove(guild_storage_db,guild_id); + return 0; } /*========================================== * Attempt to open guild storage for sd * return -* 0 : success (open or req to create a new one) -* 1 : fail -* 2 : no guild for sd +* 0 : success (open or req to create a new one) +* 1 : fail +* 2 : no guild for sd *------------------------------------------*/ -int storage_guild_storageopen(struct map_session_data *sd) +int storage_guild_storageopen(struct map_session_data* sd) { - struct guild_storage *gstor; - - nullpo_ret(sd); - - if (sd->status.guild_id <= 0) - return 2; - - if (sd->state.storage_flag) - return 1; //Can't open both storages at a time. - - if (!pc_can_give_items(sd)) { //check is this GM level can open guild storage and store items [Lupus] - clif_displaymessage(sd->fd, msg_txt(246)); - return 1; - } - - if ((gstor = guild2storage2(sd->status.guild_id)) == NULL) { - intif_request_guild_storage(sd->status.account_id,sd->status.guild_id); - return 0; - } - if (gstor->storage_status) - return 1; - - gstor->storage_status = 1; - sd->state.storage_flag = 2; - storage_sortitem(gstor->items, ARRAYLENGTH(gstor->items)); - clif_storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items)); - clif_updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE); - return 0; + struct guild_storage *gstor; + + nullpo_ret(sd); + + if(sd->status.guild_id <= 0) + return 2; + + if(sd->state.storage_flag) + return 1; //Can't open both storages at a time. + + if( !pc_can_give_items(sd) ) { //check is this GM level can open guild storage and store items [Lupus] + clif_displaymessage(sd->fd, msg_txt(246)); + return 1; + } + + if((gstor = guild2storage2(sd->status.guild_id)) == NULL) { + intif_request_guild_storage(sd->status.account_id,sd->status.guild_id); + return 0; + } + if(gstor->storage_status) + return 1; + + gstor->storage_status = 1; + sd->state.storage_flag = 2; + storage_sortitem(gstor->items, ARRAYLENGTH(gstor->items)); + clif_storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items)); + clif_updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE); + return 0; } /*========================================== * Attempt to add an item in guild storage, then refresh it * return -* 0 : success -* 1 : fail +* 0 : success +* 1 : fail *------------------------------------------*/ -int guild_storage_additem(struct map_session_data *sd, struct guild_storage *stor, struct item *item_data, int amount) +int guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount) { - struct item_data *data; - int i; - - nullpo_retr(1, sd); - nullpo_retr(1, stor); - nullpo_retr(1, item_data); - - if (item_data->nameid <= 0 || amount <= 0) - return 1; - - data = itemdb_search(item_data->nameid); - - if (data->stack.guildstorage && amount > data->stack.amount) { - // item stack limitation - return 1; - } - - if (!itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time) { - //Check if item is storable. [Skotlex] - clif_displaymessage(sd->fd, msg_txt(264)); - return 1; - } - - if (itemdb_isstackable2(data)) { //Stackable - for (i=0; i<MAX_GUILD_STORAGE; i++) { - if (compare_item(&stor->items[i], item_data)) { - if (amount > MAX_AMOUNT - stor->items[i].amount || (data->stack.guildstorage && amount > data->stack.amount - stor->items[i].amount)) - return 1; - stor->items[i].amount+=amount; - clif_storageitemadded(sd,&stor->items[i],i,amount); - stor->dirty = 1; - return 0; - } - } - } - //Add item - for (i=0; i<MAX_GUILD_STORAGE && stor->items[i].nameid; i++); - - if (i>=MAX_GUILD_STORAGE) - return 1; - - memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); - stor->items[i].amount=amount; - stor->storage_amount++; - clif_storageitemadded(sd,&stor->items[i],i,amount); - clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); - stor->dirty = 1; - return 0; + struct item_data *data; + int i; + + nullpo_retr(1, sd); + nullpo_retr(1, stor); + nullpo_retr(1, item_data); + + if(item_data->nameid <= 0 || amount <= 0) + return 1; + + data = itemdb_search(item_data->nameid); + + if( data->stack.guildstorage && amount > data->stack.amount ) + {// item stack limitation + return 1; + } + + if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time ) + { //Check if item is storable. [Skotlex] + clif_displaymessage (sd->fd, msg_txt(264)); + return 1; + } + + if(itemdb_isstackable2(data)){ //Stackable + for(i=0;i<MAX_GUILD_STORAGE;i++){ + if(compare_item(&stor->items[i], item_data)) { + if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.guildstorage && amount > data->stack.amount - stor->items[i].amount ) ) + return 1; + stor->items[i].amount+=amount; + clif_storageitemadded(sd,&stor->items[i],i,amount); + stor->dirty = 1; + return 0; + } + } + } + //Add item + for(i=0;i<MAX_GUILD_STORAGE && stor->items[i].nameid;i++); + + if(i>=MAX_GUILD_STORAGE) + return 1; + + memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); + stor->items[i].amount=amount; + stor->storage_amount++; + clif_storageitemadded(sd,&stor->items[i],i,amount); + clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); + stor->dirty = 1; + return 0; } /*========================================== * Attempt to delete an item in guild storage, then refresh it * return -* 0 : success -* 1 : fail +* 0 : success +* 1 : fail *------------------------------------------*/ -int guild_storage_delitem(struct map_session_data *sd, struct guild_storage *stor, int n, int amount) +int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* stor, int n, int amount) { - nullpo_retr(1, sd); - nullpo_retr(1, stor); - - if (stor->items[n].nameid==0 || stor->items[n].amount<amount) - return 1; - - stor->items[n].amount-=amount; - if (stor->items[n].amount==0) { - memset(&stor->items[n],0,sizeof(stor->items[0])); - stor->storage_amount--; - clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); - } - clif_storageitemremoved(sd,n,amount); - stor->dirty = 1; - return 0; + nullpo_retr(1, sd); + nullpo_retr(1, stor); + + if(stor->items[n].nameid==0 || stor->items[n].amount<amount) + return 1; + + stor->items[n].amount-=amount; + if(stor->items[n].amount==0){ + memset(&stor->items[n],0,sizeof(stor->items[0])); + stor->storage_amount--; + clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); + } + clif_storageitemremoved(sd,n,amount); + stor->dirty = 1; + return 0; } /*========================================== * Attempt to add an item in guild storage from inventory, then refresh it * @index : inventory idx * return -* 0 : fail -* 1 : succes +* 0 : fail +* 1 : succes *------------------------------------------*/ -int storage_guild_storageadd(struct map_session_data *sd, int index, int amount) +int storage_guild_storageadd(struct map_session_data* sd, int index, int amount) { - struct guild_storage *stor; - - nullpo_ret(sd); - nullpo_ret(stor=guild2storage2(sd->status.guild_id)); - - if (!stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE) - return 0; - - if (index<0 || index>=MAX_INVENTORY) - return 0; - - if (sd->status.inventory[index].nameid <= 0) - return 0; - - if (amount < 1 || amount > sd->status.inventory[index].amount) - return 0; - - if (guild_storage_additem(sd,stor,&sd->status.inventory[index],amount)==0) - pc_delitem(sd,index,amount,0,4,LOG_TYPE_GSTORAGE); - - return 1; + struct guild_storage *stor; + + nullpo_ret(sd); + nullpo_ret(stor=guild2storage2(sd->status.guild_id)); + + if( !stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE ) + return 0; + + if( index<0 || index>=MAX_INVENTORY ) + return 0; + + if( sd->status.inventory[index].nameid <= 0 ) + return 0; + + if( amount < 1 || amount > sd->status.inventory[index].amount ) + return 0; + + if(guild_storage_additem(sd,stor,&sd->status.inventory[index],amount)==0) + pc_delitem(sd,index,amount,0,4,LOG_TYPE_GSTORAGE); + + return 1; } /*========================================== * Attempt to retrieve an item from guild storage to inventory, then refresh it * @index : storage idx * return -* 0 : fail -* 1 : succes +* 0 : fail +* 1 : succes *------------------------------------------*/ -int storage_guild_storageget(struct map_session_data *sd, int index, int amount) +int storage_guild_storageget(struct map_session_data* sd, int index, int amount) { - struct guild_storage *stor; - int flag; - - nullpo_ret(sd); - nullpo_ret(stor=guild2storage2(sd->status.guild_id)); - - if (!stor->storage_status) - return 0; - - if (index<0 || index>=MAX_GUILD_STORAGE) - return 0; - - if (stor->items[index].nameid <= 0) - return 0; - - if (amount < 1 || amount > stor->items[index].amount) - return 0; - - if ((flag = pc_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)) == 0) - guild_storage_delitem(sd,stor,index,amount); - else //inform fail - clif_additem(sd,0,0,flag); - // log_fromstorage(sd, index, 1); - - return 0; + struct guild_storage *stor; + int flag; + + nullpo_ret(sd); + nullpo_ret(stor=guild2storage2(sd->status.guild_id)); + + if(!stor->storage_status) + return 0; + + if(index<0 || index>=MAX_GUILD_STORAGE) + return 0; + + if(stor->items[index].nameid <= 0) + return 0; + + if(amount < 1 || amount > stor->items[index].amount) + return 0; + + if((flag = pc_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)) == 0) + guild_storage_delitem(sd,stor,index,amount); + else //inform fail + clif_additem(sd,0,0,flag); +// log_fromstorage(sd, index, 1); + + return 0; } /*========================================== * Attempt to add an item in guild storage from cart, then refresh it * @index : cart inventory idx * return -* 0 : fail -* 1 : succes +* 0 : fail +* 1 : succes *------------------------------------------*/ -int storage_guild_storageaddfromcart(struct map_session_data *sd, int index, int amount) +int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int amount) { - struct guild_storage *stor; + struct guild_storage *stor; - nullpo_ret(sd); - nullpo_ret(stor=guild2storage2(sd->status.guild_id)); + nullpo_ret(sd); + nullpo_ret(stor=guild2storage2(sd->status.guild_id)); - if (!stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE) - return 0; + if( !stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE ) + return 0; - if (index < 0 || index >= MAX_CART) - return 0; + if( index < 0 || index >= MAX_CART ) + return 0; - if (sd->status.cart[index].nameid <= 0) - return 0; + if( sd->status.cart[index].nameid <= 0 ) + return 0; + + if( amount < 1 || amount > sd->status.cart[index].amount ) + return 0; - if (amount < 1 || amount > sd->status.cart[index].amount) - return 0; + if(guild_storage_additem(sd,stor,&sd->status.cart[index],amount)==0) + pc_cart_delitem(sd,index,amount,0,LOG_TYPE_GSTORAGE); - if (guild_storage_additem(sd,stor,&sd->status.cart[index],amount)==0) - pc_cart_delitem(sd,index,amount,0,LOG_TYPE_GSTORAGE); - - return 1; + return 1; } /*========================================== * Attempt to retrieve an item from guild storage to cart, then refresh it * @index : storage idx * return -* 0 : fail -* 1 : succes +* 0 : fail +* 1 : succes *------------------------------------------*/ -int storage_guild_storagegettocart(struct map_session_data *sd, int index, int amount) +int storage_guild_storagegettocart(struct map_session_data* sd, int index, int amount) { - struct guild_storage *stor; - - nullpo_ret(sd); - nullpo_ret(stor=guild2storage2(sd->status.guild_id)); - - if (!stor->storage_status) - return 0; + struct guild_storage *stor; - if (index<0 || index>=MAX_GUILD_STORAGE) - return 0; + nullpo_ret(sd); + nullpo_ret(stor=guild2storage2(sd->status.guild_id)); - if (stor->items[index].nameid<=0) - return 0; + if(!stor->storage_status) + return 0; - if (amount < 1 || amount > stor->items[index].amount) - return 0; + if(index<0 || index>=MAX_GUILD_STORAGE) + return 0; + + if(stor->items[index].nameid<=0) + return 0; + + if(amount < 1 || amount > stor->items[index].amount) + return 0; - if (pc_cart_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)==0) - guild_storage_delitem(sd,stor,index,amount); + if(pc_cart_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)==0) + guild_storage_delitem(sd,stor,index,amount); - return 1; + return 1; } /*========================================== * Request to save guild storage * return -* 0 : fail (no storage) -* 1 : succes +* 0 : fail (no storage) +* 1 : succes *------------------------------------------*/ int storage_guild_storagesave(int account_id, int guild_id, int flag) { - struct guild_storage *stor = guild2storage2(guild_id); - - if (stor) { - if (flag) //Char quitting, close it. - stor->storage_status = 0; - if (stor->dirty) - intif_send_guild_storage(account_id,stor); - return 1; - } - return 0; + struct guild_storage *stor = guild2storage2(guild_id); + + if(stor) + { + if (flag) //Char quitting, close it. + stor->storage_status = 0; + if (stor->dirty) + intif_send_guild_storage(account_id,stor); + return 1; + } + return 0; } /*========================================== * ACK save of guild storage * return -* 0 : fail (no storage) -* 1 : succes +* 0 : fail (no storage) +* 1 : succes *------------------------------------------*/ int storage_guild_storagesaved(int guild_id) { - struct guild_storage *stor; - - if ((stor=guild2storage2(guild_id)) != NULL) { - if (stor->dirty && stor->storage_status == 0) { - //Storage has been correctly saved. - stor->dirty = 0; - } - return 1; - } - return 0; + struct guild_storage *stor; + + if((stor=guild2storage2(guild_id)) != NULL) { + if (stor->dirty && stor->storage_status == 0) + { //Storage has been correctly saved. + stor->dirty = 0; + } + return 1; + } + return 0; } //Close storage for sd and save it -int storage_guild_storageclose(struct map_session_data *sd) +int storage_guild_storageclose(struct map_session_data* sd) { - struct guild_storage *stor; - - nullpo_ret(sd); - nullpo_ret(stor=guild2storage2(sd->status.guild_id)); - - clif_storageclose(sd); - if (stor->storage_status) { - if (save_settings&4) - chrif_save(sd, 0); //This one also saves the storage. [Skotlex] - else - storage_guild_storagesave(sd->status.account_id, sd->status.guild_id,0); - stor->storage_status=0; - } - sd->state.storage_flag = 0; - - return 0; + struct guild_storage *stor; + + nullpo_ret(sd); + nullpo_ret(stor=guild2storage2(sd->status.guild_id)); + + clif_storageclose(sd); + if (stor->storage_status) + { + if (save_settings&4) + chrif_save(sd, 0); //This one also saves the storage. [Skotlex] + else + storage_guild_storagesave(sd->status.account_id, sd->status.guild_id,0); + stor->storage_status=0; + } + sd->state.storage_flag = 0; + + return 0; } -int storage_guild_storage_quit(struct map_session_data *sd, int flag) +int storage_guild_storage_quit(struct map_session_data* sd, int flag) { - struct guild_storage *stor; - - nullpo_ret(sd); - nullpo_ret(stor=guild2storage2(sd->status.guild_id)); - - if (flag) { - //Only during a guild break flag is 1 (don't save storage) - sd->state.storage_flag = 0; - stor->storage_status = 0; - clif_storageclose(sd); - if (save_settings&4) - chrif_save(sd,0); - return 0; - } - - if (stor->storage_status) { - if (save_settings&4) - chrif_save(sd,0); - else - storage_guild_storagesave(sd->status.account_id,sd->status.guild_id,1); - } - sd->state.storage_flag = 0; - stor->storage_status = 0; - - return 0; + struct guild_storage *stor; + + nullpo_ret(sd); + nullpo_ret(stor=guild2storage2(sd->status.guild_id)); + + if(flag) + { //Only during a guild break flag is 1 (don't save storage) + sd->state.storage_flag = 0; + stor->storage_status = 0; + clif_storageclose(sd); + if (save_settings&4) + chrif_save(sd,0); + return 0; + } + + if(stor->storage_status) { + if (save_settings&4) + chrif_save(sd,0); + else + storage_guild_storagesave(sd->status.account_id,sd->status.guild_id,1); + } + sd->state.storage_flag = 0; + stor->storage_status = 0; + + return 0; } diff --git a/src/map/storage.h b/src/map/storage.h index 8483ff012..5a38d865b 100644 --- a/src/map/storage.h +++ b/src/map/storage.h @@ -11,7 +11,7 @@ struct item; //#include "map.h" struct map_session_data; -int storage_delitem(struct map_session_data *sd, int n, int amount); +int storage_delitem(struct map_session_data* sd, int n, int amount); int storage_storageopen(struct map_session_data *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); @@ -23,7 +23,7 @@ void do_final_storage(void); void do_reconnect_storage(void); void storage_storage_quit(struct map_session_data *sd, int flag); -struct guild_storage *guild2storage(int guild_id); +struct guild_storage* guild2storage(int guild_id); int guild_storage_delete(int guild_id); int storage_guild_storageopen(struct map_session_data *sd); int guild_storage_additem(struct map_session_data *sd,struct guild_storage *stor,struct item *item_data,int amount); diff --git a/src/map/trade.c b/src/map/trade.c index 2196a74cc..0d01b54a6 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -29,62 +29,63 @@ *------------------------------------------*/ void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_sd) { - nullpo_retv(sd); - - if (map[sd->bl.m].flag.notrade) { - clif_displaymessage(sd->fd, msg_txt(272)); - return; //Can't trade in notrade mapflag maps. - } - - if (target_sd == NULL || sd == target_sd) { - clif_tradestart(sd, 1); // character does not exist - return; - } - - if (target_sd->npc_id) { - //Trade fails if you are using an NPC. - clif_tradestart(sd, 2); - return; - } - - if (!battle_config.invite_request_check) { - if (target_sd->guild_invite > 0 || target_sd->party_invite > 0 || target_sd->adopt_invite) { - clif_tradestart(sd, 2); - return; - } - } - - if (sd->trade_partner != 0) { // If a character tries to trade to another one then cancel the previous one - struct map_session_data *previous_sd = map_id2sd(sd->trade_partner); - if (previous_sd) { - previous_sd->trade_partner = 0; - clif_tradecancelled(previous_sd); - } // Once cancelled then continue to the new one. - sd->trade_partner = 0; - clif_tradecancelled(sd); - } - - if (target_sd->trade_partner != 0) { - clif_tradestart(sd, 2); // person is in another trade - return; - } - - if (!pc_can_give_items(sd) || !pc_can_give_items(target_sd)) { //check if both GMs are allowed to trade - clif_displaymessage(sd->fd, msg_txt(246)); - clif_tradestart(sd, 2); // GM is not allowed to trade - return; - } - - // Players can not request trade from far away, unless they are allowed to use @trade. - if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) && - (sd->bl.m != target_sd->bl.m || !check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE))) { - clif_tradestart(sd, 0); // too far - return ; - } - - target_sd->trade_partner = sd->status.account_id; - sd->trade_partner = target_sd->status.account_id; - clif_traderequest(target_sd, sd->status.name); + nullpo_retv(sd); + + if (map[sd->bl.m].flag.notrade) { + clif_displaymessage (sd->fd, msg_txt(272)); + return; //Can't trade in notrade mapflag maps. + } + + if (target_sd == NULL || sd == target_sd) { + clif_tradestart(sd, 1); // character does not exist + return; + } + + if (target_sd->npc_id) + { //Trade fails if you are using an NPC. + clif_tradestart(sd, 2); + return; + } + + if (!battle_config.invite_request_check) { + if (target_sd->guild_invite > 0 || target_sd->party_invite > 0 || target_sd->adopt_invite) { + clif_tradestart(sd, 2); + return; + } + } + + if ( sd->trade_partner != 0 ) { // If a character tries to trade to another one then cancel the previous one + struct map_session_data *previous_sd = map_id2sd(sd->trade_partner); + if( previous_sd ){ + previous_sd->trade_partner = 0; + clif_tradecancelled(previous_sd); + } // Once cancelled then continue to the new one. + sd->trade_partner = 0; + clif_tradecancelled(sd); + } + + if (target_sd->trade_partner != 0) { + clif_tradestart(sd, 2); // person is in another trade + return; + } + + if (!pc_can_give_items(sd) || !pc_can_give_items(target_sd)) //check if both GMs are allowed to trade + { + clif_displaymessage(sd->fd, msg_txt(246)); + clif_tradestart(sd, 2); // GM is not allowed to trade + return; + } + + // Players can not request trade from far away, unless they are allowed to use @trade. + if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) && + (sd->bl.m != target_sd->bl.m || !check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE))) { + clif_tradestart(sd, 0); // too far + return ; + } + + target_sd->trade_partner = sd->status.account_id; + sd->trade_partner = target_sd->status.account_id; + clif_traderequest(target_sd, sd->status.name); } /*========================================== @@ -100,67 +101,68 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta *------------------------------------------*/ void trade_tradeack(struct map_session_data *sd, int type) { - struct map_session_data *tsd; - nullpo_retv(sd); - - if (sd->state.trading || !sd->trade_partner) - return; //Already trading or no partner set. - - if ((tsd = map_id2sd(sd->trade_partner)) == NULL) { - clif_tradestart(sd, 1); // character does not exist - sd->trade_partner=0; - return; - } - - if (tsd->state.trading || tsd->trade_partner != sd->bl.id) { - clif_tradestart(sd, 2); - sd->trade_partner=0; - return; //Already trading or wrong partner. - } - - if (type == 4) { // Cancel - clif_tradestart(tsd, type); - clif_tradestart(sd, type); - sd->state.deal_locked = 0; - sd->trade_partner = 0; - tsd->state.deal_locked = 0; - tsd->trade_partner = 0; - return; - } - - if (type != 3) - return; //If client didn't send accept, it's a broken packet? - - // Players can not request trade from far away, unless they are allowed to use @trade. - // Check here as well since the original character could had warped. - if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) && - (sd->bl.m != tsd->bl.m || !check_distance_bl(&sd->bl, &tsd->bl, TRADE_DISTANCE))) { - clif_tradestart(sd, 0); // too far - sd->trade_partner=0; - tsd->trade_partner = 0; - return; - } - - //Check if you can start trade. - if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag || - tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag) { - //Fail - clif_tradestart(sd, 2); - clif_tradestart(tsd, 2); - sd->state.deal_locked = 0; - sd->trade_partner = 0; - tsd->state.deal_locked = 0; - tsd->trade_partner = 0; - return; - } - - //Initiate trade - sd->state.trading = 1; - tsd->state.trading = 1; - memset(&sd->deal, 0, sizeof(sd->deal)); - memset(&tsd->deal, 0, sizeof(tsd->deal)); - clif_tradestart(tsd, type); - clif_tradestart(sd, type); + struct map_session_data *tsd; + nullpo_retv(sd); + + if (sd->state.trading || !sd->trade_partner) + return; //Already trading or no partner set. + + if ((tsd = map_id2sd(sd->trade_partner)) == NULL) { + clif_tradestart(sd, 1); // character does not exist + sd->trade_partner=0; + return; + } + + if (tsd->state.trading || tsd->trade_partner != sd->bl.id) + { + clif_tradestart(sd, 2); + sd->trade_partner=0; + return; //Already trading or wrong partner. + } + + if (type == 4) { // Cancel + clif_tradestart(tsd, type); + clif_tradestart(sd, type); + sd->state.deal_locked = 0; + sd->trade_partner = 0; + tsd->state.deal_locked = 0; + tsd->trade_partner = 0; + return; + } + + if (type != 3) + return; //If client didn't send accept, it's a broken packet? + + // Players can not request trade from far away, unless they are allowed to use @trade. + // Check here as well since the original character could had warped. + if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) && + (sd->bl.m != tsd->bl.m || !check_distance_bl(&sd->bl, &tsd->bl, TRADE_DISTANCE))) { + clif_tradestart(sd, 0); // too far + sd->trade_partner=0; + tsd->trade_partner = 0; + return; + } + + //Check if you can start trade. + if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag || + tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag) + { //Fail + clif_tradestart(sd, 2); + clif_tradestart(tsd, 2); + sd->state.deal_locked = 0; + sd->trade_partner = 0; + tsd->state.deal_locked = 0; + tsd->trade_partner = 0; + return; + } + + //Initiate trade + sd->state.trading = 1; + tsd->state.trading = 1; + memset(&sd->deal, 0, sizeof(sd->deal)); + memset(&tsd->deal, 0, sizeof(tsd->deal)); + clif_tradestart(tsd, type); + clif_tradestart(sd, type); } /*========================================== @@ -170,60 +172,61 @@ void trade_tradeack(struct map_session_data *sd, int type) *------------------------------------------*/ int impossible_trade_check(struct map_session_data *sd) { - struct item inventory[MAX_INVENTORY]; - char message_to_gm[200]; - int i, index; - - nullpo_retr(1, sd); - - if (sd->deal.zeny > sd->status.zeny) { - pc_setglobalreg(sd,"ZENY_HACKER",1); - return -1; - } - - // get inventory of player - memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); - - // remove this part: arrows can be trade and equiped - // re-added! [celest] - // remove equiped items (they can not be trade) - for (i = 0; i < MAX_INVENTORY; i++) - if (inventory[i].nameid > 0 && inventory[i].equip && !(inventory[i].equip & EQP_AMMO)) - memset(&inventory[i], 0, sizeof(struct item)); - - // check items in player inventory - for (i = 0; i < 10; i++) { - if (!sd->deal.item[i].amount) - continue; - index = sd->deal.item[i].index; - if (inventory[index].amount < sd->deal.item[i].amount) { - // if more than the player have -> hack - 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, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); - sprintf(message_to_gm, msg_txt(539), inventory[index].amount, inventory[index].nameid, sd->deal.item[i].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, PC_PERM_RECEIVE_HACK_INFO, 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 - set_eof(sd->fd); // forced to disconnect because of the hack - // message about the ban - strcpy(message_to_gm, msg_txt(540)); // This player has been definitively 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) - set_eof(sd->fd); // forced to disconnect because of the hack - // message about the ban - sprintf(message_to_gm, msg_txt(507), battle_config.ban_hack_trade); // This player has been banned for %d minute(s). - } else - // message about the ban - strcpy(message_to_gm, msg_txt(508)); // This player hasn't been banned (Ban option is disabled). - - intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); - return 1; - } - inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory - } - return 0; + struct item inventory[MAX_INVENTORY]; + char message_to_gm[200]; + int i, index; + + nullpo_retr(1, sd); + + if(sd->deal.zeny > sd->status.zeny) + { + pc_setglobalreg(sd,"ZENY_HACKER",1); + return -1; + } + + // get inventory of player + memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); + + // remove this part: arrows can be trade and equiped + // re-added! [celest] + // remove equiped items (they can not be trade) + for (i = 0; i < MAX_INVENTORY; i++) + if (inventory[i].nameid > 0 && inventory[i].equip && !(inventory[i].equip & EQP_AMMO)) + memset(&inventory[i], 0, sizeof(struct item)); + + // check items in player inventory + for(i = 0; i < 10; i++) { + if (!sd->deal.item[i].amount) + continue; + index = sd->deal.item[i].index; + if (inventory[index].amount < sd->deal.item[i].amount) + { // if more than the player have -> hack + 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, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); + sprintf(message_to_gm, msg_txt(539), inventory[index].amount, inventory[index].nameid, sd->deal.item[i].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, PC_PERM_RECEIVE_HACK_INFO, 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 + set_eof(sd->fd); // forced to disconnect because of the hack + // message about the ban + strcpy(message_to_gm, msg_txt(540)); // This player has been definitively 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) + set_eof(sd->fd); // forced to disconnect because of the hack + // message about the ban + sprintf(message_to_gm, msg_txt(507), battle_config.ban_hack_trade); // This player has been banned for %d minute(s). + } else + // message about the ban + strcpy(message_to_gm, msg_txt(508)); // This player hasn't been banned (Ban option is disabled). + + intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); + return 1; + } + inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory + } + return 0; } /*========================================== @@ -231,86 +234,86 @@ int impossible_trade_check(struct map_session_data *sd) *------------------------------------------*/ int trade_check(struct map_session_data *sd, struct map_session_data *tsd) { - struct item inventory[MAX_INVENTORY]; - struct item inventory2[MAX_INVENTORY]; - struct item_data *data; - int trade_i, i, n; - short amount; - - // check zenys value against hackers (Zeny was already checked on time of adding, but you never know when you lost some zeny since then. - if (sd->deal.zeny > sd->status.zeny || (tsd->status.zeny > MAX_ZENY - sd->deal.zeny)) - return 0; - if (tsd->deal.zeny > tsd->status.zeny || (sd->status.zeny > MAX_ZENY - tsd->deal.zeny)) - return 0; - - // get inventory of player - memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); - memcpy(&inventory2, &tsd->status.inventory, sizeof(struct item) * MAX_INVENTORY); - - // check free slot in both inventory - for (trade_i = 0; trade_i < 10; trade_i++) { - amount = sd->deal.item[trade_i].amount; - if (amount) { - n = sd->deal.item[trade_i].index; - if (amount > inventory[n].amount) - return 0; //qty Exploit? - - data = itemdb_search(inventory[n].nameid); - i = MAX_INVENTORY; - if (itemdb_isstackable2(data)) { //Stackable item. - for (i = 0; i < MAX_INVENTORY; i++) - if (inventory2[i].nameid == inventory[n].nameid && - inventory2[i].card[0] == inventory[n].card[0] && inventory2[i].card[1] == inventory[n].card[1] && - inventory2[i].card[2] == inventory[n].card[2] && inventory2[i].card[3] == inventory[n].card[3]) { - if (inventory2[i].amount + amount > MAX_AMOUNT) - return 0; - inventory2[i].amount += amount; - inventory[n].amount -= amount; - break; - } - } - - if (i == MAX_INVENTORY) {// look for an empty slot. - for (i = 0; i < MAX_INVENTORY && inventory2[i].nameid; i++); - if (i == MAX_INVENTORY) - return 0; - memcpy(&inventory2[i], &inventory[n], sizeof(struct item)); - inventory2[i].amount = amount; - inventory[n].amount -= amount; - } - } - amount = tsd->deal.item[trade_i].amount; - if (!amount) - continue; - n = tsd->deal.item[trade_i].index; - if (amount > inventory2[n].amount) - return 0; - // search if it's possible to add item (for full inventory) - data = itemdb_search(inventory2[n].nameid); - i = MAX_INVENTORY; - if (itemdb_isstackable2(data)) { - for (i = 0; i < MAX_INVENTORY; i++) - if (inventory[i].nameid == inventory2[n].nameid && - inventory[i].card[0] == inventory2[n].card[0] && inventory[i].card[1] == inventory2[n].card[1] && - inventory[i].card[2] == inventory2[n].card[2] && inventory[i].card[3] == inventory2[n].card[3]) { - if (inventory[i].amount + amount > MAX_AMOUNT) - return 0; - inventory[i].amount += amount; - inventory2[n].amount -= amount; - break; - } - } - if (i == MAX_INVENTORY) { - for (i = 0; i < MAX_INVENTORY && inventory[i].nameid; i++); - if (i == MAX_INVENTORY) - return 0; - memcpy(&inventory[i], &inventory2[n], sizeof(struct item)); - inventory[i].amount = amount; - inventory2[n].amount -= amount; - } - } - - return 1; + struct item inventory[MAX_INVENTORY]; + struct item inventory2[MAX_INVENTORY]; + struct item_data *data; + int trade_i, i, n; + short amount; + + // check zenys value against hackers (Zeny was already checked on time of adding, but you never know when you lost some zeny since then. + if(sd->deal.zeny > sd->status.zeny || (tsd->status.zeny > MAX_ZENY - sd->deal.zeny)) + return 0; + if(tsd->deal.zeny > tsd->status.zeny || (sd->status.zeny > MAX_ZENY - tsd->deal.zeny)) + return 0; + + // get inventory of player + memcpy(&inventory, &sd->status.inventory, sizeof(struct item) * MAX_INVENTORY); + memcpy(&inventory2, &tsd->status.inventory, sizeof(struct item) * MAX_INVENTORY); + + // check free slot in both inventory + for(trade_i = 0; trade_i < 10; trade_i++) { + amount = sd->deal.item[trade_i].amount; + if (amount) { + n = sd->deal.item[trade_i].index; + if (amount > inventory[n].amount) + return 0; //qty Exploit? + + data = itemdb_search(inventory[n].nameid); + i = MAX_INVENTORY; + if (itemdb_isstackable2(data)) { //Stackable item. + for(i = 0; i < MAX_INVENTORY; i++) + if (inventory2[i].nameid == inventory[n].nameid && + inventory2[i].card[0] == inventory[n].card[0] && inventory2[i].card[1] == inventory[n].card[1] && + inventory2[i].card[2] == inventory[n].card[2] && inventory2[i].card[3] == inventory[n].card[3]) { + if (inventory2[i].amount + amount > MAX_AMOUNT) + return 0; + inventory2[i].amount += amount; + inventory[n].amount -= amount; + break; + } + } + + if (i == MAX_INVENTORY) {// look for an empty slot. + for(i = 0; i < MAX_INVENTORY && inventory2[i].nameid; i++); + if (i == MAX_INVENTORY) + return 0; + memcpy(&inventory2[i], &inventory[n], sizeof(struct item)); + inventory2[i].amount = amount; + inventory[n].amount -= amount; + } + } + amount = tsd->deal.item[trade_i].amount; + if (!amount) + continue; + n = tsd->deal.item[trade_i].index; + if (amount > inventory2[n].amount) + return 0; + // search if it's possible to add item (for full inventory) + data = itemdb_search(inventory2[n].nameid); + i = MAX_INVENTORY; + if (itemdb_isstackable2(data)) { + for(i = 0; i < MAX_INVENTORY; i++) + if (inventory[i].nameid == inventory2[n].nameid && + inventory[i].card[0] == inventory2[n].card[0] && inventory[i].card[1] == inventory2[n].card[1] && + inventory[i].card[2] == inventory2[n].card[2] && inventory[i].card[3] == inventory2[n].card[3]) { + if (inventory[i].amount + amount > MAX_AMOUNT) + return 0; + inventory[i].amount += amount; + inventory2[n].amount -= amount; + break; + } + } + if (i == MAX_INVENTORY) { + for(i = 0; i < MAX_INVENTORY && inventory[i].nameid; i++); + if (i == MAX_INVENTORY) + return 0; + memcpy(&inventory[i], &inventory2[n], sizeof(struct item)); + inventory[i].amount = amount; + inventory2[n].amount -= amount; + } + } + + return 1; } /*========================================== @@ -318,108 +321,113 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd) *------------------------------------------*/ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) { - struct map_session_data *target_sd; - struct item *item; - int trade_i, trade_weight; - int src_lv, dst_lv; - - nullpo_retv(sd); - if (!sd->state.trading || sd->state.deal_locked > 0) - return; //Can't add stuff. - - if ((target_sd = map_id2sd(sd->trade_partner)) == NULL) { - trade_tradecancel(sd); - return; - } - - if (amount == 0) { - //Why do this.. ~.~ just send an ack, the item won't display on the trade window. - clif_tradeitemok(sd, index, 0); - return; - } - - index -= 2; // 0 is for zeny, 1 is unknown. Gravity, go figure... - - //Item checks... - if (index < 0 || index >= MAX_INVENTORY) - return; - if (amount < 0 || amount > sd->status.inventory[index].amount) - return; - - item = &sd->status.inventory[index]; - src_lv = pc_get_group_level(sd); - dst_lv = pc_get_group_level(target_sd); - if (!itemdb_cantrade(item, src_lv, dst_lv) && //Can't trade - (pc_get_partner(sd) != target_sd || !itemdb_canpartnertrade(item, src_lv, dst_lv))) { //Can't partner-trade - clif_displaymessage(sd->fd, msg_txt(260)); - clif_tradeitemok(sd, index+2, 1); - return; - } - - if (item->expire_time) { - // Rental System - clif_displaymessage(sd->fd, msg_txt(260)); - clif_tradeitemok(sd, index+2, 1); - return; - } - - //Locate a trade position - ARR_FIND(0, 10, trade_i, sd->deal.item[trade_i].index == index || sd->deal.item[trade_i].amount == 0); - if (trade_i == 10) { //No space left - clif_tradeitemok(sd, index+2, 1); - return; - } - - trade_weight = sd->inventory_data[index]->weight * amount; - if (target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight) { - //fail to add item -- the player was over weighted. - clif_tradeitemok(sd, index+2, 1); - return; - } - - if (sd->deal.item[trade_i].index == index) { - //The same item as before is being readjusted. - if (sd->deal.item[trade_i].amount + amount > sd->status.inventory[index].amount) { - //packet deal exploit check - amount = sd->status.inventory[index].amount - sd->deal.item[trade_i].amount; - trade_weight = sd->inventory_data[index]->weight * amount; - } - sd->deal.item[trade_i].amount += amount; - } else { - //New deal item - sd->deal.item[trade_i].index = index; - sd->deal.item[trade_i].amount = amount; - } - sd->deal.weight += trade_weight; - - clif_tradeitemok(sd, index+2, 0); // Return the index as it was received - clif_tradeadditem(sd, target_sd, index+2, amount); + struct map_session_data *target_sd; + struct item *item; + int trade_i, trade_weight; + int src_lv, dst_lv; + + nullpo_retv(sd); + if( !sd->state.trading || sd->state.deal_locked > 0 ) + return; //Can't add stuff. + + if( (target_sd = map_id2sd(sd->trade_partner)) == NULL ) + { + trade_tradecancel(sd); + return; + } + + if( amount == 0 ) + { //Why do this.. ~.~ just send an ack, the item won't display on the trade window. + clif_tradeitemok(sd, index, 0); + return; + } + + index -= 2; // 0 is for zeny, 1 is unknown. Gravity, go figure... + + //Item checks... + if( index < 0 || index >= MAX_INVENTORY ) + return; + if( amount < 0 || amount > sd->status.inventory[index].amount ) + return; + + item = &sd->status.inventory[index]; + src_lv = pc_get_group_level(sd); + dst_lv = pc_get_group_level(target_sd); + if( !itemdb_cantrade(item, src_lv, dst_lv) && //Can't trade + (pc_get_partner(sd) != target_sd || !itemdb_canpartnertrade(item, src_lv, dst_lv)) ) //Can't partner-trade + { + clif_displaymessage (sd->fd, msg_txt(260)); + clif_tradeitemok(sd, index+2, 1); + return; + } + + if( item->expire_time ) + { // Rental System + clif_displaymessage (sd->fd, msg_txt(260)); + clif_tradeitemok(sd, index+2, 1); + return; + } + + //Locate a trade position + ARR_FIND( 0, 10, trade_i, sd->deal.item[trade_i].index == index || sd->deal.item[trade_i].amount == 0 ); + if( trade_i == 10 ) //No space left + { + clif_tradeitemok(sd, index+2, 1); + return; + } + + trade_weight = sd->inventory_data[index]->weight * amount; + if( target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight ) + { //fail to add item -- the player was over weighted. + clif_tradeitemok(sd, index+2, 1); + return; + } + + if( sd->deal.item[trade_i].index == index ) + { //The same item as before is being readjusted. + if( sd->deal.item[trade_i].amount + amount > sd->status.inventory[index].amount ) + { //packet deal exploit check + amount = sd->status.inventory[index].amount - sd->deal.item[trade_i].amount; + trade_weight = sd->inventory_data[index]->weight * amount; + } + sd->deal.item[trade_i].amount += amount; + } + else + { //New deal item + sd->deal.item[trade_i].index = index; + sd->deal.item[trade_i].amount = amount; + } + sd->deal.weight += trade_weight; + + clif_tradeitemok(sd, index+2, 0); // Return the index as it was received + clif_tradeadditem(sd, target_sd, index+2, amount); } /*========================================== * Adds the specified amount of zeny to the trade window *------------------------------------------*/ -void trade_tradeaddzeny(struct map_session_data *sd, int amount) +void trade_tradeaddzeny(struct map_session_data* sd, int amount) { - struct map_session_data *target_sd; - nullpo_retv(sd); - - if (!sd->state.trading || sd->state.deal_locked > 0) - return; //Can't add stuff. - - if ((target_sd = map_id2sd(sd->trade_partner)) == NULL) { - trade_tradecancel(sd); - return; - } - - if (amount < 0 || amount > sd->status.zeny || amount > MAX_ZENY - target_sd->status.zeny) { - // invalid values, no appropriate packet for it => abort - trade_tradecancel(sd); - return; - } - - sd->deal.zeny = amount; - clif_tradeadditem(sd, target_sd, 0, amount); + struct map_session_data* target_sd; + nullpo_retv(sd); + + if( !sd->state.trading || sd->state.deal_locked > 0 ) + return; //Can't add stuff. + + if( (target_sd = map_id2sd(sd->trade_partner)) == NULL ) + { + trade_tradecancel(sd); + return; + } + + if( amount < 0 || amount > sd->status.zeny || amount > MAX_ZENY - target_sd->status.zeny ) + { // invalid values, no appropriate packet for it => abort + trade_tradecancel(sd); + return; + } + + sd->deal.zeny = amount; + clif_tradeadditem(sd, target_sd, 0, amount); } /*========================================== @@ -427,19 +435,19 @@ void trade_tradeaddzeny(struct map_session_data *sd, int amount) *------------------------------------------*/ void trade_tradeok(struct map_session_data *sd) { - struct map_session_data *target_sd; - - if (sd->state.deal_locked || !sd->state.trading) - return; - - if ((target_sd = map_id2sd(sd->trade_partner)) == NULL) { - trade_tradecancel(sd); - return; - } - sd->state.deal_locked = 1; - clif_tradeitemok(sd, 0, 0); - clif_tradedeal_lock(sd, 0); - clif_tradedeal_lock(target_sd, 1); + struct map_session_data *target_sd; + + if(sd->state.deal_locked || !sd->state.trading) + return; + + if ((target_sd = map_id2sd(sd->trade_partner)) == NULL) { + trade_tradecancel(sd); + return; + } + sd->state.deal_locked = 1; + clif_tradeitemok(sd, 0, 0); + clif_tradedeal_lock(sd, 0); + clif_tradedeal_lock(target_sd, 1); } /*========================================== @@ -447,58 +455,58 @@ void trade_tradeok(struct map_session_data *sd) *------------------------------------------*/ void trade_tradecancel(struct map_session_data *sd) { - struct map_session_data *target_sd; - int trade_i; - - target_sd = map_id2sd(sd->trade_partner); - - if (!sd->state.trading) { - // Not trade acepted - if (target_sd) { - target_sd->trade_partner = 0; - clif_tradecancelled(target_sd); - } - sd->trade_partner = 0; - clif_tradecancelled(sd); - return; - } - - for (trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual) - if (!sd->deal.item[trade_i].amount) - continue; - clif_additem(sd, sd->deal.item[trade_i].index, sd->deal.item[trade_i].amount, 0); - sd->deal.item[trade_i].index = 0; - sd->deal.item[trade_i].amount = 0; - } - if (sd->deal.zeny) { - clif_updatestatus(sd, SP_ZENY); - sd->deal.zeny = 0; - } - - sd->state.deal_locked = 0; - sd->state.trading = 0; - sd->trade_partner = 0; - clif_tradecancelled(sd); - - if (!target_sd) - return; - - for (trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual) - if (!target_sd->deal.item[trade_i].amount) - continue; - clif_additem(target_sd, target_sd->deal.item[trade_i].index, target_sd->deal.item[trade_i].amount, 0); - target_sd->deal.item[trade_i].index = 0; - target_sd->deal.item[trade_i].amount = 0; - } - - if (target_sd->deal.zeny) { - clif_updatestatus(target_sd, SP_ZENY); - target_sd->deal.zeny = 0; - } - target_sd->state.deal_locked = 0; - target_sd->trade_partner = 0; - target_sd->state.trading = 0; - clif_tradecancelled(target_sd); + struct map_session_data *target_sd; + int trade_i; + + target_sd = map_id2sd(sd->trade_partner); + + if(!sd->state.trading) + { // Not trade acepted + if( target_sd ) { + target_sd->trade_partner = 0; + clif_tradecancelled(target_sd); + } + sd->trade_partner = 0; + clif_tradecancelled(sd); + return; + } + + for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual) + if (!sd->deal.item[trade_i].amount) + continue; + clif_additem(sd, sd->deal.item[trade_i].index, sd->deal.item[trade_i].amount, 0); + sd->deal.item[trade_i].index = 0; + sd->deal.item[trade_i].amount = 0; + } + if (sd->deal.zeny) { + clif_updatestatus(sd, SP_ZENY); + sd->deal.zeny = 0; + } + + sd->state.deal_locked = 0; + sd->state.trading = 0; + sd->trade_partner = 0; + clif_tradecancelled(sd); + + if (!target_sd) + return; + + for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual) + if (!target_sd->deal.item[trade_i].amount) + continue; + clif_additem(target_sd, target_sd->deal.item[trade_i].index, target_sd->deal.item[trade_i].amount, 0); + target_sd->deal.item[trade_i].index = 0; + target_sd->deal.item[trade_i].amount = 0; + } + + if (target_sd->deal.zeny) { + clif_updatestatus(target_sd, SP_ZENY); + target_sd->deal.zeny = 0; + } + target_sd->state.deal_locked = 0; + target_sd->trade_partner = 0; + target_sd->state.trading = 0; + clif_tradecancelled(target_sd); } /*========================================== @@ -506,93 +514,97 @@ void trade_tradecancel(struct map_session_data *sd) *------------------------------------------*/ void trade_tradecommit(struct map_session_data *sd) { - struct map_session_data *tsd; - int trade_i; - int flag; - - if (!sd->state.trading || !sd->state.deal_locked) //Locked should be 1 (pressed ok) before you can press trade. - return; - - if ((tsd = map_id2sd(sd->trade_partner)) == NULL) { - trade_tradecancel(sd); - return; - } - - sd->state.deal_locked = 2; - - if (tsd->state.deal_locked < 2) - return; //Not yet time for trading. - - //Now is a good time (to save on resources) to check that the trade can indeed be made and it's not exploitable. - // check exploit (trade more items that you have) - if (impossible_trade_check(sd)) { - trade_tradecancel(sd); - return; - } - // check exploit (trade more items that you have) - if (impossible_trade_check(tsd)) { - trade_tradecancel(tsd); - return; - } - // check for full inventory (can not add traded items) - if (!trade_check(sd,tsd)) { // check the both players - trade_tradecancel(sd); - return; - } - - // trade is accepted and correct. - for (trade_i = 0; trade_i < 10; trade_i++) { - int n; - if (sd->deal.item[trade_i].amount) { - n = sd->deal.item[trade_i].index; - - flag = pc_additem(tsd, &sd->status.inventory[n], sd->deal.item[trade_i].amount,LOG_TYPE_TRADE); - if (flag == 0) - pc_delitem(sd, n, sd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); - else - clif_additem(sd, n, sd->deal.item[trade_i].amount, 0); - sd->deal.item[trade_i].index = 0; - sd->deal.item[trade_i].amount = 0; - } - if (tsd->deal.item[trade_i].amount) { - n = tsd->deal.item[trade_i].index; - - flag = pc_additem(sd, &tsd->status.inventory[n], tsd->deal.item[trade_i].amount,LOG_TYPE_TRADE); - if (flag == 0) - pc_delitem(tsd, n, tsd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); - else - clif_additem(tsd, n, tsd->deal.item[trade_i].amount, 0); - tsd->deal.item[trade_i].index = 0; - tsd->deal.item[trade_i].amount = 0; - } - } - - if (sd->deal.zeny) { - pc_payzeny(sd ,sd->deal.zeny, LOG_TYPE_TRADE, tsd); - pc_getzeny(tsd,sd->deal.zeny,LOG_TYPE_TRADE, sd); - sd->deal.zeny = 0; - - } - if (tsd->deal.zeny) { - pc_payzeny(tsd,tsd->deal.zeny,LOG_TYPE_TRADE, sd); - pc_getzeny(sd ,tsd->deal.zeny,LOG_TYPE_TRADE, tsd); - tsd->deal.zeny = 0; - } - - sd->state.deal_locked = 0; - sd->trade_partner = 0; - sd->state.trading = 0; - - tsd->state.deal_locked = 0; - tsd->trade_partner = 0; - tsd->state.trading = 0; - - clif_tradecompleted(sd, 0); - clif_tradecompleted(tsd, 0); - - // save both player to avoid crash: they always have no advantage/disadvantage between the 2 players - if (save_settings&1) { - chrif_save(sd,0); - chrif_save(tsd,0); - } + struct map_session_data *tsd; + int trade_i; + int flag; + + if (!sd->state.trading || !sd->state.deal_locked) //Locked should be 1 (pressed ok) before you can press trade. + return; + + if ((tsd = map_id2sd(sd->trade_partner)) == NULL) { + trade_tradecancel(sd); + return; + } + + sd->state.deal_locked = 2; + + if (tsd->state.deal_locked < 2) + return; //Not yet time for trading. + + //Now is a good time (to save on resources) to check that the trade can indeed be made and it's not exploitable. + // check exploit (trade more items that you have) + if (impossible_trade_check(sd)) { + trade_tradecancel(sd); + return; + } + // check exploit (trade more items that you have) + if (impossible_trade_check(tsd)) { + trade_tradecancel(tsd); + return; + } + // check for full inventory (can not add traded items) + if (!trade_check(sd,tsd)) { // check the both players + trade_tradecancel(sd); + return; + } + + // trade is accepted and correct. + for( trade_i = 0; trade_i < 10; trade_i++ ) + { + int n; + if (sd->deal.item[trade_i].amount) + { + n = sd->deal.item[trade_i].index; + + flag = pc_additem(tsd, &sd->status.inventory[n], sd->deal.item[trade_i].amount,LOG_TYPE_TRADE); + if (flag == 0) + pc_delitem(sd, n, sd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); + else + clif_additem(sd, n, sd->deal.item[trade_i].amount, 0); + sd->deal.item[trade_i].index = 0; + sd->deal.item[trade_i].amount = 0; + } + if (tsd->deal.item[trade_i].amount) + { + n = tsd->deal.item[trade_i].index; + + flag = pc_additem(sd, &tsd->status.inventory[n], tsd->deal.item[trade_i].amount,LOG_TYPE_TRADE); + if (flag == 0) + pc_delitem(tsd, n, tsd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); + else + clif_additem(tsd, n, tsd->deal.item[trade_i].amount, 0); + tsd->deal.item[trade_i].index = 0; + tsd->deal.item[trade_i].amount = 0; + } + } + + if( sd->deal.zeny ) { + pc_payzeny(sd ,sd->deal.zeny, LOG_TYPE_TRADE, tsd); + pc_getzeny(tsd,sd->deal.zeny,LOG_TYPE_TRADE, sd); + sd->deal.zeny = 0; + + } + if ( tsd->deal.zeny) { + pc_payzeny(tsd,tsd->deal.zeny,LOG_TYPE_TRADE, sd); + pc_getzeny(sd ,tsd->deal.zeny,LOG_TYPE_TRADE, tsd); + tsd->deal.zeny = 0; + } + + sd->state.deal_locked = 0; + sd->trade_partner = 0; + sd->state.trading = 0; + + tsd->state.deal_locked = 0; + tsd->trade_partner = 0; + tsd->state.trading = 0; + + clif_tradecompleted(sd, 0); + clif_tradecompleted(tsd, 0); + + // save both player to avoid crash: they always have no advantage/disadvantage between the 2 players + if (save_settings&1) + { + chrif_save(sd,0); + chrif_save(tsd,0); + } } diff --git a/src/map/trade.h b/src/map/trade.h index 1b8cb4f75..6bb39936e 100644 --- a/src/map/trade.h +++ b/src/map/trade.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _TRADE_H_ -#define _TRADE_H_ +#ifndef _TRADE_H_ +#define _TRADE_H_ //#include "map.h" struct map_session_data; diff --git a/src/map/unit.c b/src/map/unit.c index 016e8cdd8..4827c0c68 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -40,19 +40,20 @@ #include <string.h> -const short dirx[8]= {0,-1,-1,-1,0,1,1,1}; -const short diry[8]= {1,1,0,-1,-1,-1,0,1}; - -struct unit_data *unit_bl2ud(struct block_list *bl) { - if (bl == NULL) return NULL; - if (bl->type == BL_PC) return &((struct map_session_data *)bl)->ud; - if (bl->type == BL_MOB) return &((struct mob_data *)bl)->ud; - if (bl->type == BL_PET) return &((struct pet_data *)bl)->ud; - if (bl->type == BL_NPC) return &((struct npc_data *)bl)->ud; - if (bl->type == BL_HOM) return &((struct homun_data *)bl)->ud; - if (bl->type == BL_MER) return &((struct mercenary_data *)bl)->ud; - if (bl->type == BL_ELEM) return &((struct elemental_data *)bl)->ud; - return NULL; +const short dirx[8]={0,-1,-1,-1,0,1,1,1}; +const short diry[8]={1,1,0,-1,-1,-1,0,1}; + +struct unit_data* unit_bl2ud(struct block_list *bl) +{ + if( bl == NULL) return NULL; + if( bl->type == BL_PC) return &((struct map_session_data*)bl)->ud; + if( bl->type == BL_MOB) return &((struct mob_data*)bl)->ud; + if( bl->type == BL_PET) return &((struct pet_data*)bl)->ud; + if( bl->type == BL_NPC) return &((struct npc_data*)bl)->ud; + if( bl->type == BL_HOM) return &((struct homun_data*)bl)->ud; + if( bl->type == BL_MER) return &((struct mercenary_data*)bl)->ud; + if( bl->type == BL_ELEM) return &((struct elemental_data*)bl)->ud; + return NULL; } static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data); @@ -60,665 +61,686 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data int unit_walktoxy_sub(struct block_list *bl) { - int i; - struct walkpath_data wpd; - struct unit_data *ud = NULL; - - nullpo_retr(1, bl); - ud = unit_bl2ud(bl); - if (ud == NULL) return 0; - - if (!path_search(&wpd,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS)) - return 0; - - memcpy(&ud->walkpath,&wpd,sizeof(wpd)); - - if (ud->target_to && ud->chaserange>1) { - //Generally speaking, the walk path is already to an adjacent tile - //so we only need to shorten the path if the range is greater than 1. - int dir; - //Trim the last part of the path to account for range, - //but always move at least one cell when requested to move. - for (i = ud->chaserange*10; i > 0 && ud->walkpath.path_len>1;) { - ud->walkpath.path_len--; - dir = ud->walkpath.path[ud->walkpath.path_len]; - if (dir&1) - i-=14; - else - i-=10; - ud->to_x -= dirx[dir]; - ud->to_y -= diry[dir]; - } - } - - ud->state.change_walk_target=0; - - if (bl->type == BL_PC) { - ((TBL_PC *)bl)->head_dir = 0; - clif_walkok((TBL_PC *)bl); - } - clif_move(ud); - - if (ud->walkpath.path_pos>=ud->walkpath.path_len) - i = -1; - else if (ud->walkpath.path[ud->walkpath.path_pos]&1) - i = status_get_speed(bl)*14/10; - else - i = status_get_speed(bl); - if (i > 0) - ud->walktimer = add_timer(gettick()+i,unit_walktoxy_timer,bl->id,i); - return 1; + int i; + struct walkpath_data wpd; + struct unit_data *ud = NULL; + + nullpo_retr(1, bl); + ud = unit_bl2ud(bl); + if(ud == NULL) return 0; + + if( !path_search(&wpd,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) ) + return 0; + + memcpy(&ud->walkpath,&wpd,sizeof(wpd)); + + if (ud->target_to && ud->chaserange>1) { + //Generally speaking, the walk path is already to an adjacent tile + //so we only need to shorten the path if the range is greater than 1. + int dir; + //Trim the last part of the path to account for range, + //but always move at least one cell when requested to move. + for (i = ud->chaserange*10; i > 0 && ud->walkpath.path_len>1;) { + ud->walkpath.path_len--; + dir = ud->walkpath.path[ud->walkpath.path_len]; + if(dir&1) + i-=14; + else + i-=10; + ud->to_x -= dirx[dir]; + ud->to_y -= diry[dir]; + } + } + + ud->state.change_walk_target=0; + + if (bl->type == BL_PC) { + ((TBL_PC *)bl)->head_dir = 0; + clif_walkok((TBL_PC*)bl); + } + clif_move(ud); + + if(ud->walkpath.path_pos>=ud->walkpath.path_len) + i = -1; + else if(ud->walkpath.path[ud->walkpath.path_pos]&1) + i = status_get_speed(bl)*14/10; + else + i = status_get_speed(bl); + if( i > 0) + ud->walktimer = add_timer(gettick()+i,unit_walktoxy_timer,bl->id,i); + return 1; } static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data) { - int i; - int x,y,dx,dy; - uint8 dir; - struct block_list *bl; - struct map_session_data *sd; - struct mob_data *md; - struct unit_data *ud; - struct mercenary_data *mrd; - - bl = map_id2bl(id); - if (bl == NULL) - return 0; - sd = BL_CAST(BL_PC, bl); - md = BL_CAST(BL_MOB, bl); - mrd = BL_CAST(BL_MER, bl); - ud = unit_bl2ud(bl); - - if (ud == NULL) return 0; - - if (ud->walktimer != tid) { - ShowError("unit_walk_timer mismatch %d != %d\n",ud->walktimer,tid); - return 0; - } - ud->walktimer = INVALID_TIMER; - if (bl->prev == NULL) return 0; // Stop moved because it is missing from the block_list - - if (ud->walkpath.path_pos>=ud->walkpath.path_len) - return 0; - - if (ud->walkpath.path[ud->walkpath.path_pos]>=8) - return 1; - x = bl->x; - y = bl->y; - - dir = ud->walkpath.path[ud->walkpath.path_pos]; - ud->dir = dir; - - dx = dirx[(int)dir]; - dy = diry[(int)dir]; - - if (map_getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS)) - return unit_walktoxy_sub(bl); - - //Refresh view for all those we lose sight - map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl); - - x += dx; - y += dy; - map_moveblock(bl, x, y, tick); - ud->walk_count++; //walked cell counter, to be used for walk-triggered skills. [Skotlex] - status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); //If you move, you lose your counters. [malufett] - - if (bl->x != x || bl->y != y || ud->walktimer != INVALID_TIMER) - return 0; //map_moveblock has altered the object beyond what we expected (moved/warped it) - - ud->walktimer = -2; // arbitrary non-INVALID_TIMER value to make the clif code send walking packets - map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl); - ud->walktimer = INVALID_TIMER; - - if (sd) { - if (sd->touching_id) - npc_touchnext_areanpc(sd,false); - if (map_getcell(bl->m,x,y,CELL_CHKNPC)) { - npc_touch_areanpc(sd,bl->m,x,y); - if (bl->prev == NULL) //Script could have warped char, abort remaining of the function. - return 0; - } else - sd->areanpc_id=0; - - if (sd->md && !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE)) { - // mercenary should be warped after being 3 seconds too far from the master [greenbox] - if (sd->md->masterteleport_timer == 0) { - sd->md->masterteleport_timer = gettick(); - } else if (DIFF_TICK(gettick(), sd->md->masterteleport_timer) > 3000) { - sd->md->masterteleport_timer = 0; - unit_warp(&sd->md->bl, sd->bl.m, sd->bl.x, sd->bl.y, CLR_TELEPORT); - } - } else if (sd->md) { - // reset the tick, he is not far anymore - sd->md->masterteleport_timer = 0; - } - } else if (md) { - if (map_getcell(bl->m,x,y,CELL_CHKNPC)) { - if (npc_touch_areanpc2(md)) return 0; // Warped - } else - md->areanpc_id = 0; - if (md->min_chase > md->db->range3) md->min_chase--; - //Walk skills are triggered regardless of target due to the idle-walk mob state. - //But avoid triggering on stop-walk calls. - if (tid != INVALID_TIMER && - !(ud->walk_count%WALK_SKILL_INTERVAL) && - mobskill_use(md, tick, -1)) { - if (!(ud->skillid == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)) { - //Skill used, abort walking - clif_fixpos(bl); //Fix position as walk has been cancelled. - return 0; - } - //Resend walk packet for proper Self Destruction display. - clif_move(ud); - } - } else if (mrd && mrd->master) { - if (!check_distance_bl(&mrd->master->bl, bl, MAX_MER_DISTANCE)) { - // mercenary should be warped after being 3 seconds too far from the master [greenbox] - if (mrd->masterteleport_timer == 0) { - mrd->masterteleport_timer = gettick(); - } else if (DIFF_TICK(gettick(), mrd->masterteleport_timer) > 3000) { - mrd->masterteleport_timer = 0; - unit_warp(bl, mrd->master->bl.id, mrd->master->bl.x, mrd->master->bl.y, CLR_TELEPORT); - } - } else { - mrd->masterteleport_timer = 0; - } - } - - if (tid == INVALID_TIMER) //A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant. - return 0; - - if (ud->state.change_walk_target) - return unit_walktoxy_sub(bl); - - ud->walkpath.path_pos++; - if (ud->walkpath.path_pos>=ud->walkpath.path_len) - i = -1; - else if (ud->walkpath.path[ud->walkpath.path_pos]&1) - i = status_get_speed(bl)*14/10; - else - i = status_get_speed(bl); - - if (i > 0) { - ud->walktimer = add_timer(tick+i,unit_walktoxy_timer,id,i); - if (md && DIFF_TICK(tick,md->dmgtick) < 3000) //not required not damaged recently - clif_move(ud); - } else if (ud->state.running) { - //Keep trying to run. - if (!(unit_run(bl) || unit_wugdash(bl,sd))) - ud->state.running = 0; - } else if (ud->target_to) { - //Update target trajectory. - struct block_list *tbl = map_id2bl(ud->target_to); - if (!tbl || !status_check_visibility(bl, tbl)) { //Cancel chase. - ud->to_x = bl->x; - ud->to_y = bl->y; - if (tbl && bl->type == BL_MOB && mob_warpchase((TBL_MOB *)bl, tbl)) - return 0; - ud->target_to = 0; - return 0; - } - if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange)) { - //Reached destination. - if (ud->state.attack_continue) { - //Aegis uses one before every attack, we should - //only need this one for syncing purposes. [Skotlex] - ud->target_to = 0; - clif_fixpos(bl); - unit_attack(bl, tbl->id, ud->state.attack_continue); - } - } else { //Update chase-path - unit_walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy|(ud->state.attack_continue?2:0)); - return 0; - } - } else { //Stopped walking. Update to_x and to_y to current location [Skotlex] - ud->to_x = bl->x; - ud->to_y = bl->y; - ud->target_to = 0; - } - return 0; + int i; + int x,y,dx,dy; + uint8 dir; + struct block_list *bl; + struct map_session_data *sd; + struct mob_data *md; + struct unit_data *ud; + struct mercenary_data *mrd; + + bl = map_id2bl(id); + if(bl == NULL) + return 0; + sd = BL_CAST(BL_PC, bl); + md = BL_CAST(BL_MOB, bl); + mrd = BL_CAST(BL_MER, bl); + ud = unit_bl2ud(bl); + + if(ud == NULL) return 0; + + if(ud->walktimer != tid){ + ShowError("unit_walk_timer mismatch %d != %d\n",ud->walktimer,tid); + return 0; + } + ud->walktimer = INVALID_TIMER; + if (bl->prev == NULL) return 0; // Stop moved because it is missing from the block_list + + if(ud->walkpath.path_pos>=ud->walkpath.path_len) + return 0; + + if(ud->walkpath.path[ud->walkpath.path_pos]>=8) + return 1; + x = bl->x; + y = bl->y; + + dir = ud->walkpath.path[ud->walkpath.path_pos]; + ud->dir = dir; + + dx = dirx[(int)dir]; + dy = diry[(int)dir]; + + if(map_getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS)) + return unit_walktoxy_sub(bl); + + //Refresh view for all those we lose sight + map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl); + + x += dx; + y += dy; + map_moveblock(bl, x, y, tick); + ud->walk_count++; //walked cell counter, to be used for walk-triggered skills. [Skotlex] + status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); //If you move, you lose your counters. [malufett] + + if (bl->x != x || bl->y != y || ud->walktimer != INVALID_TIMER) + return 0; //map_moveblock has altered the object beyond what we expected (moved/warped it) + + ud->walktimer = -2; // arbitrary non-INVALID_TIMER value to make the clif code send walking packets + map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl); + ud->walktimer = INVALID_TIMER; + + if(sd) { + if( sd->touching_id ) + npc_touchnext_areanpc(sd,false); + if(map_getcell(bl->m,x,y,CELL_CHKNPC)) { + npc_touch_areanpc(sd,bl->m,x,y); + if (bl->prev == NULL) //Script could have warped char, abort remaining of the function. + return 0; + } else + sd->areanpc_id=0; + + if( sd->md && !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE) ) + { + // mercenary should be warped after being 3 seconds too far from the master [greenbox] + if (sd->md->masterteleport_timer == 0) + { + sd->md->masterteleport_timer = gettick(); + } + else if (DIFF_TICK(gettick(), sd->md->masterteleport_timer) > 3000) + { + sd->md->masterteleport_timer = 0; + unit_warp( &sd->md->bl, sd->bl.m, sd->bl.x, sd->bl.y, CLR_TELEPORT ); + } + } + else if( sd->md ) + { + // reset the tick, he is not far anymore + sd->md->masterteleport_timer = 0; + } + } else if (md) { + if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) { + if( npc_touch_areanpc2(md) ) return 0; // Warped + } else + md->areanpc_id = 0; + if (md->min_chase > md->db->range3) md->min_chase--; + //Walk skills are triggered regardless of target due to the idle-walk mob state. + //But avoid triggering on stop-walk calls. + if(tid != INVALID_TIMER && + !(ud->walk_count%WALK_SKILL_INTERVAL) && + mobskill_use(md, tick, -1)) + { + if (!(ud->skillid == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)) + { //Skill used, abort walking + clif_fixpos(bl); //Fix position as walk has been cancelled. + return 0; + } + //Resend walk packet for proper Self Destruction display. + clif_move(ud); + } + } + else if( mrd && mrd->master ) + { + if (!check_distance_bl(&mrd->master->bl, bl, MAX_MER_DISTANCE)) + { + // mercenary should be warped after being 3 seconds too far from the master [greenbox] + if (mrd->masterteleport_timer == 0) + { + mrd->masterteleport_timer = gettick(); + } + else if (DIFF_TICK(gettick(), mrd->masterteleport_timer) > 3000) + { + mrd->masterteleport_timer = 0; + unit_warp( bl, mrd->master->bl.id, mrd->master->bl.x, mrd->master->bl.y, CLR_TELEPORT ); + } + } + else + { + mrd->masterteleport_timer = 0; + } + } + + if(tid == INVALID_TIMER) //A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant. + return 0; + + if(ud->state.change_walk_target) + return unit_walktoxy_sub(bl); + + ud->walkpath.path_pos++; + if(ud->walkpath.path_pos>=ud->walkpath.path_len) + i = -1; + else if(ud->walkpath.path[ud->walkpath.path_pos]&1) + i = status_get_speed(bl)*14/10; + else + i = status_get_speed(bl); + + if(i > 0) { + ud->walktimer = add_timer(tick+i,unit_walktoxy_timer,id,i); + if( md && DIFF_TICK(tick,md->dmgtick) < 3000 )//not required not damaged recently + clif_move(ud); + } else if(ud->state.running) { + //Keep trying to run. + if ( !(unit_run(bl) || unit_wugdash(bl,sd)) ) + ud->state.running = 0; + } + else if (ud->target_to) { + //Update target trajectory. + struct block_list *tbl = map_id2bl(ud->target_to); + if (!tbl || !status_check_visibility(bl, tbl)) { //Cancel chase. + ud->to_x = bl->x; + ud->to_y = bl->y; + if (tbl && bl->type == BL_MOB && mob_warpchase((TBL_MOB*)bl, tbl) ) + return 0; + ud->target_to = 0; + return 0; + } + if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange)) + { //Reached destination. + if (ud->state.attack_continue) + { //Aegis uses one before every attack, we should + //only need this one for syncing purposes. [Skotlex] + ud->target_to = 0; + clif_fixpos(bl); + unit_attack(bl, tbl->id, ud->state.attack_continue); + } + } else { //Update chase-path + unit_walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy|(ud->state.attack_continue?2:0)); + return 0; + } + } + else { //Stopped walking. Update to_x and to_y to current location [Skotlex] + ud->to_x = bl->x; + ud->to_y = bl->y; + ud->target_to = 0; + } + return 0; } static int unit_delay_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *bl = map_id2bl(id); + struct block_list *bl = map_id2bl(id); - if (!bl || bl->prev == NULL) - return 0; - unit_walktoxy(bl, (short)((data>>16)&0xffff), (short)(data&0xffff), 0); - return 1; + if (!bl || bl->prev == NULL) + return 0; + unit_walktoxy(bl, (short)((data>>16)&0xffff), (short)(data&0xffff), 0); + return 1; } //flag parameter: //&1 -> 1/0 = easy/hard //&2 -> force walking //&4 -> Delay walking if the reason you can't walk is the canwalk delay -int unit_walktoxy(struct block_list *bl, short x, short y, int flag) +int unit_walktoxy( struct block_list *bl, short x, short y, int flag) { - struct unit_data *ud = NULL; - struct status_change *sc = NULL; - - nullpo_ret(bl); - - ud = unit_bl2ud(bl); - - if (ud == NULL) return 0; - // disabled until we find the correct algorithm. [malufett] - //#ifdef OFFICIAL_WALKPATH - // if( !path_search_long(NULL, bl->m, bl->x, bl->y, x, y, CELL_CHKWALL) ) return 0; - //#endif - if (flag&4 && DIFF_TICK(ud->canmove_tick, gettick()) > 0 && - DIFF_TICK(ud->canmove_tick, gettick()) < 2000) { - // Delay walking command. [Skotlex] - add_timer(ud->canmove_tick+1, unit_delay_walktoxy_timer, bl->id, (x<<16)|(y&0xFFFF)); - return 1; - } - - if (!(flag&2) && (!(status_get_mode(bl)&MD_CANMOVE) || !unit_can_move(bl))) - return 0; - - ud->state.walk_easy = flag&1; - ud->to_x = x; - ud->to_y = y; - unit_set_target(ud, 0); - - sc = status_get_sc(bl); - if (sc && sc->data[SC_CONFUSION]) //Randomize the target position - map_random_dir(bl, &ud->to_x, &ud->to_y); - - if (ud->walktimer != INVALID_TIMER) { - // When you come to the center of the grid because the change of destination while you're walking right now - // Call a function from a timer unit_walktoxy_sub - ud->state.change_walk_target = 1; - return 1; - } - - if (ud->attacktimer != INVALID_TIMER) { - delete_timer(ud->attacktimer, unit_attack_timer); - ud->attacktimer = INVALID_TIMER; - } - - return unit_walktoxy_sub(bl); + struct unit_data* ud = NULL; + struct status_change* sc = NULL; + + nullpo_ret(bl); + + ud = unit_bl2ud(bl); + + if( ud == NULL) return 0; +// disabled until we find the correct algorithm. [malufett] +//#ifdef OFFICIAL_WALKPATH +// if( !path_search_long(NULL, bl->m, bl->x, bl->y, x, y, CELL_CHKWALL) ) return 0; +//#endif + if (flag&4 && DIFF_TICK(ud->canmove_tick, gettick()) > 0 && + DIFF_TICK(ud->canmove_tick, gettick()) < 2000) + { // Delay walking command. [Skotlex] + add_timer(ud->canmove_tick+1, unit_delay_walktoxy_timer, bl->id, (x<<16)|(y&0xFFFF)); + return 1; + } + + if(!(flag&2) && (!(status_get_mode(bl)&MD_CANMOVE) || !unit_can_move(bl))) + return 0; + + ud->state.walk_easy = flag&1; + ud->to_x = x; + ud->to_y = y; + unit_set_target(ud, 0); + + sc = status_get_sc(bl); + if (sc && sc->data[SC_CONFUSION]) //Randomize the target position + map_random_dir(bl, &ud->to_x, &ud->to_y); + + if(ud->walktimer != INVALID_TIMER) { + // When you come to the center of the grid because the change of destination while you're walking right now + // Call a function from a timer unit_walktoxy_sub + ud->state.change_walk_target = 1; + return 1; + } + + if(ud->attacktimer != INVALID_TIMER) { + delete_timer( ud->attacktimer, unit_attack_timer ); + ud->attacktimer = INVALID_TIMER; + } + + return unit_walktoxy_sub(bl); } //To set Mob's CHASE/FOLLOW states (shouldn't be done if there's no path to reach) -static inline void set_mobstate(struct block_list *bl, int flag) +static inline void set_mobstate(struct block_list* bl, int flag) { - struct mob_data *md = BL_CAST(BL_MOB,bl); + struct mob_data* md = BL_CAST(BL_MOB,bl); - if (md && flag) - md->state.skillstate = md->state.aggressive ? MSS_FOLLOW : MSS_RUSH; + if( md && flag ) + md->state.skillstate = md->state.aggressive ? MSS_FOLLOW : MSS_RUSH; } static int unit_walktobl_sub(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *bl = map_id2bl(id); - struct unit_data *ud = bl?unit_bl2ud(bl):NULL; - - if (ud && ud->walktimer == INVALID_TIMER && ud->target == data) { - if (DIFF_TICK(ud->canmove_tick, tick) > 0) //Keep waiting? - add_timer(ud->canmove_tick+1, unit_walktobl_sub, id, data); - else if (unit_can_move(bl)) { - if (unit_walktoxy_sub(bl)) - set_mobstate(bl, ud->state.attack_continue); - } - } - return 0; + struct block_list *bl = map_id2bl(id); + struct unit_data *ud = bl?unit_bl2ud(bl):NULL; + + if (ud && ud->walktimer == INVALID_TIMER && ud->target == data) + { + if (DIFF_TICK(ud->canmove_tick, tick) > 0) //Keep waiting? + add_timer(ud->canmove_tick+1, unit_walktobl_sub, id, data); + else if (unit_can_move(bl)) + { + if (unit_walktoxy_sub(bl)) + set_mobstate(bl, ud->state.attack_continue); + } + } + return 0; } // Chases a tbl. If the flag&1, use hard-path seek, // if flag&2, start attacking upon arrival within range, otherwise just walk to that character. int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int flag) { - struct unit_data *ud = NULL; - struct status_change *sc = NULL; - nullpo_ret(bl); - nullpo_ret(tbl); - - ud = unit_bl2ud(bl); - if (ud == NULL) return 0; - - if (!(status_get_mode(bl)&MD_CANMOVE)) - return 0; - - if (!unit_can_reach_bl(bl, tbl, distance_bl(bl, tbl)+1, flag&1, &ud->to_x, &ud->to_y)) { - ud->to_x = bl->x; - ud->to_y = bl->y; - ud->target_to = 0; - return 0; - } - - ud->state.walk_easy = flag&1; - ud->target_to = tbl->id; - ud->chaserange = range; //Note that if flag&2, this SHOULD be attack-range - ud->state.attack_continue = flag&2?1:0; //Chase to attack. - unit_set_target(ud, 0); - - sc = status_get_sc(bl); - if (sc && sc->data[SC_CONFUSION]) //Randomize the target position - map_random_dir(bl, &ud->to_x, &ud->to_y); - - if (ud->walktimer != INVALID_TIMER) { - ud->state.change_walk_target = 1; - set_mobstate(bl, flag&2); - return 1; - } - - if (DIFF_TICK(ud->canmove_tick, gettick()) > 0) { - //Can't move, wait a bit before invoking the movement. - add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target); - return 1; - } - - if (!unit_can_move(bl)) - return 0; - - if (ud->attacktimer != INVALID_TIMER) { - delete_timer(ud->attacktimer, unit_attack_timer); - ud->attacktimer = INVALID_TIMER; - } - - if (unit_walktoxy_sub(bl)) { - set_mobstate(bl, flag&2); - return 1; - } - return 0; + struct unit_data *ud = NULL; + struct status_change *sc = NULL; + nullpo_ret(bl); + nullpo_ret(tbl); + + ud = unit_bl2ud(bl); + if( ud == NULL) return 0; + + if (!(status_get_mode(bl)&MD_CANMOVE)) + return 0; + + if (!unit_can_reach_bl(bl, tbl, distance_bl(bl, tbl)+1, flag&1, &ud->to_x, &ud->to_y)) { + ud->to_x = bl->x; + ud->to_y = bl->y; + ud->target_to = 0; + return 0; + } + + ud->state.walk_easy = flag&1; + ud->target_to = tbl->id; + ud->chaserange = range; //Note that if flag&2, this SHOULD be attack-range + ud->state.attack_continue = flag&2?1:0; //Chase to attack. + unit_set_target(ud, 0); + + sc = status_get_sc(bl); + if (sc && sc->data[SC_CONFUSION]) //Randomize the target position + map_random_dir(bl, &ud->to_x, &ud->to_y); + + if(ud->walktimer != INVALID_TIMER) { + ud->state.change_walk_target = 1; + set_mobstate(bl, flag&2); + return 1; + } + + if(DIFF_TICK(ud->canmove_tick, gettick()) > 0) + { //Can't move, wait a bit before invoking the movement. + add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target); + return 1; + } + + if(!unit_can_move(bl)) + return 0; + + if(ud->attacktimer != INVALID_TIMER) { + delete_timer( ud->attacktimer, unit_attack_timer ); + ud->attacktimer = INVALID_TIMER; + } + + if (unit_walktoxy_sub(bl)) { + set_mobstate(bl, flag&2); + return 1; + } + return 0; } int unit_run(struct block_list *bl) { - struct status_change *sc = status_get_sc(bl); - short to_x,to_y,dir_x,dir_y; - int lv; - int i; - - if (!(sc && sc->data[SC_RUN])) - return 0; - - if (!unit_can_move(bl)) { - status_change_end(bl, SC_RUN, INVALID_TIMER); - return 0; - } - - lv = sc->data[SC_RUN]->val1; - dir_x = dirx[sc->data[SC_RUN]->val2]; - dir_y = diry[sc->data[SC_RUN]->val2]; - - // determine destination cell - to_x = bl->x; - to_y = bl->y; - for (i=0; i<AREA_SIZE; i++) { - if (!map_getcell(bl->m,to_x+dir_x,to_y+dir_y,CELL_CHKPASS)) - break; - - //if sprinting and there's a PC/Mob/NPC, block the path [Kevin] - if (sc->data[SC_RUN] && map_count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC)) - break; - - to_x += dir_x; - to_y += dir_y; - } - - if ((to_x == bl->x && to_y == bl->y) || (to_x == (bl->x+1) || to_y == (bl->y+1)) || (to_x == (bl->x-1) || to_y == (bl->y-1))) { - //If you can't run forward, you must be next to a wall, so bounce back. [Skotlex] - clif_status_change(bl, SI_BUMP, 1, 0, 0, 0, 0); - - //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] - unit_bl2ud(bl)->state.running = 0; - status_change_end(bl, SC_RUN, INVALID_TIMER); - - skill_blown(bl,bl,skill_get_blewcount(TK_RUN,lv),unit_getdir(bl),0); - clif_fixpos(bl); //Why is a clif_slide (skill_blown) AND a fixpos needed? Ask Aegis. - clif_status_change(bl, SI_BUMP, 0, 0, 0, 0, 0); - return 0; - } - if (unit_walktoxy(bl, to_x, to_y, 1)) - return 1; - //There must be an obstacle nearby. Attempt walking one cell at a time. - do { - to_x -= dir_x; - to_y -= dir_y; - } while (--i > 0 && !unit_walktoxy(bl, to_x, to_y, 1)); - if (i==0) { - // copy-paste from above - clif_status_change(bl, SI_BUMP, 1, 0, 0, 0, 0); - - //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] - unit_bl2ud(bl)->state.running = 0; - status_change_end(bl, SC_RUN, INVALID_TIMER); - - skill_blown(bl,bl,skill_get_blewcount(TK_RUN,lv),unit_getdir(bl),0); - clif_fixpos(bl); - clif_status_change(bl, SI_BUMP, 0, 0, 0, 0, 0); - return 0; - } - return 1; + struct status_change *sc = status_get_sc(bl); + short to_x,to_y,dir_x,dir_y; + int lv; + int i; + + if (!(sc && sc->data[SC_RUN])) + return 0; + + if (!unit_can_move(bl)) { + status_change_end(bl, SC_RUN, INVALID_TIMER); + return 0; + } + + lv = sc->data[SC_RUN]->val1; + dir_x = dirx[sc->data[SC_RUN]->val2]; + dir_y = diry[sc->data[SC_RUN]->val2]; + + // determine destination cell + to_x = bl->x; + to_y = bl->y; + for(i=0;i<AREA_SIZE;i++) + { + if(!map_getcell(bl->m,to_x+dir_x,to_y+dir_y,CELL_CHKPASS)) + break; + + //if sprinting and there's a PC/Mob/NPC, block the path [Kevin] + if(sc->data[SC_RUN] && map_count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC)) + break; + + to_x += dir_x; + to_y += dir_y; + } + + if( (to_x == bl->x && to_y == bl->y ) || (to_x == (bl->x+1) || to_y == (bl->y+1)) || (to_x == (bl->x-1) || to_y == (bl->y-1))) { + //If you can't run forward, you must be next to a wall, so bounce back. [Skotlex] + clif_status_change(bl, SI_BUMP, 1, 0, 0, 0, 0); + + //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] + unit_bl2ud(bl)->state.running = 0; + status_change_end(bl, SC_RUN, INVALID_TIMER); + + skill_blown(bl,bl,skill_get_blewcount(TK_RUN,lv),unit_getdir(bl),0); + clif_fixpos(bl); //Why is a clif_slide (skill_blown) AND a fixpos needed? Ask Aegis. + clif_status_change(bl, SI_BUMP, 0, 0, 0, 0, 0); + return 0; + } + if (unit_walktoxy(bl, to_x, to_y, 1)) + return 1; + //There must be an obstacle nearby. Attempt walking one cell at a time. + do { + to_x -= dir_x; + to_y -= dir_y; + } while (--i > 0 && !unit_walktoxy(bl, to_x, to_y, 1)); + if (i==0) { + // copy-paste from above + clif_status_change(bl, SI_BUMP, 1, 0, 0, 0, 0); + + //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] + unit_bl2ud(bl)->state.running = 0; + status_change_end(bl, SC_RUN, INVALID_TIMER); + + skill_blown(bl,bl,skill_get_blewcount(TK_RUN,lv),unit_getdir(bl),0); + clif_fixpos(bl); + clif_status_change(bl, SI_BUMP, 0, 0, 0, 0, 0); + return 0; + } + return 1; } //Exclusive function to Wug Dash state. [Jobbie/3CeAM] -int unit_wugdash(struct block_list *bl, struct map_session_data *sd) -{ - struct status_change *sc = status_get_sc(bl); - short to_x,to_y,dir_x,dir_y; - int lv; - int i; - if (!(sc && sc->data[SC_WUGDASH])) - return 0; - - nullpo_ret(sd); - nullpo_ret(bl); - - if (!unit_can_move(bl)) { - status_change_end(bl,SC_WUGDASH,INVALID_TIMER); - return 0; - } - - lv = sc->data[SC_WUGDASH]->val1; - dir_x = dirx[sc->data[SC_WUGDASH]->val2]; - dir_y = diry[sc->data[SC_WUGDASH]->val2]; - - to_x = bl->x; - to_y = bl->y; - for (i=0; i<AREA_SIZE; i++) { - if (!map_getcell(bl->m,to_x+dir_x,to_y+dir_y,CELL_CHKPASS)) - break; - - if (sc->data[SC_WUGDASH] && map_count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC)) - break; - - to_x += dir_x; - to_y += dir_y; - } - - if (to_x == bl->x && to_y == bl->y) { - - unit_bl2ud(bl)->state.running = 0; - status_change_end(bl,SC_WUGDASH,INVALID_TIMER); - - if (sd) { - clif_fixpos(bl); - skill_castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, gettick(), SD_LEVEL); - } - return 0; - } - if (unit_walktoxy(bl, to_x, to_y, 1)) - return 1; - do { - to_x -= dir_x; - to_y -= dir_y; - } while (--i > 0 && !unit_walktoxy(bl, to_x, to_y, 1)); - if (i==0) { - - unit_bl2ud(bl)->state.running = 0; - status_change_end(bl,SC_WUGDASH,INVALID_TIMER); - - if (sd) { - clif_fixpos(bl); - skill_castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, gettick(), SD_LEVEL); - } - return 0; - } - return 1; +int unit_wugdash(struct block_list *bl, struct map_session_data *sd) { + struct status_change *sc = status_get_sc(bl); + short to_x,to_y,dir_x,dir_y; + int lv; + int i; + if (!(sc && sc->data[SC_WUGDASH])) + return 0; + + nullpo_ret(sd); + nullpo_ret(bl); + + if (!unit_can_move(bl)) { + status_change_end(bl,SC_WUGDASH,INVALID_TIMER); + return 0; + } + + lv = sc->data[SC_WUGDASH]->val1; + dir_x = dirx[sc->data[SC_WUGDASH]->val2]; + dir_y = diry[sc->data[SC_WUGDASH]->val2]; + + to_x = bl->x; + to_y = bl->y; + for(i=0;i<AREA_SIZE;i++) + { + if(!map_getcell(bl->m,to_x+dir_x,to_y+dir_y,CELL_CHKPASS)) + break; + + if(sc->data[SC_WUGDASH] && map_count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC)) + break; + + to_x += dir_x; + to_y += dir_y; + } + + if(to_x == bl->x && to_y == bl->y) { + + unit_bl2ud(bl)->state.running = 0; + status_change_end(bl,SC_WUGDASH,INVALID_TIMER); + + if( sd ){ + clif_fixpos(bl); + skill_castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, gettick(), SD_LEVEL); + } + return 0; + } + if (unit_walktoxy(bl, to_x, to_y, 1)) + return 1; + do { + to_x -= dir_x; + to_y -= dir_y; + } while (--i > 0 && !unit_walktoxy(bl, to_x, to_y, 1)); + if (i==0) { + + unit_bl2ud(bl)->state.running = 0; + status_change_end(bl,SC_WUGDASH,INVALID_TIMER); + + if( sd ){ + clif_fixpos(bl); + skill_castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, gettick(), SD_LEVEL); + } + return 0; + } + return 1; } //Makes bl attempt to run dist cells away from target. Uses hard-paths. int unit_escape(struct block_list *bl, struct block_list *target, short dist) { - int dir = map_calc_dir(target, bl->x, bl->y); - while (dist > 0 && map_getcell(bl->m, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], CELL_CHKNOREACH)) - dist--; - return (dist > 0 && unit_walktoxy(bl, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], 0)); + int dir = map_calc_dir(target, bl->x, bl->y); + while( dist > 0 && map_getcell(bl->m, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], CELL_CHKNOREACH) ) + dist--; + return ( dist > 0 && unit_walktoxy(bl, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], 0) ); } //Instant warp function. int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath) { - short dx,dy; - uint8 dir; - struct unit_data *ud = NULL; - struct map_session_data *sd = NULL; - - nullpo_ret(bl); - sd = BL_CAST(BL_PC, bl); - ud = unit_bl2ud(bl); - - if (ud == NULL) return 0; - - unit_stop_walking(bl,1); - unit_stop_attack(bl); - - if (checkpath && (map_getcell(bl->m,dst_x,dst_y,CELL_CHKNOPASS) || !path_search(NULL,bl->m,bl->x,bl->y,dst_x,dst_y,easy,CELL_CHKNOREACH))) - return 0; // unreachable - - ud->to_x = dst_x; - ud->to_y = dst_y; - - dir = map_calc_dir(bl, dst_x, dst_y); - ud->dir = dir; - - dx = dst_x - bl->x; - dy = dst_y - bl->y; - - map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl); - - map_moveblock(bl, dst_x, dst_y, gettick()); - - ud->walktimer = -2; // arbitrary non-INVALID_TIMER value to make the clif code send walking packets - map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl); - ud->walktimer = INVALID_TIMER; - - if (sd) { - if (sd->touching_id) - npc_touchnext_areanpc(sd,false); - if (map_getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) { - npc_touch_areanpc(sd,bl->m,bl->x,bl->y); - if (bl->prev == NULL) //Script could have warped char, abort remaining of the function. - return 0; - } else - sd->areanpc_id=0; - - if (sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0) { - // Check if pet needs to be teleported. [Skotlex] - int flag = 0; - struct block_list *bl = &sd->pd->bl; - if (!checkpath && !path_search(NULL,bl->m,bl->x,bl->y,dst_x,dst_y,0,CELL_CHKNOPASS)) - flag = 1; - else if (!check_distance_bl(&sd->bl, bl, AREA_SIZE)) //Too far, teleport. - flag = 2; - if (flag) { - unit_movepos(bl,sd->bl.x,sd->bl.y, 0, 0); - clif_slide(bl,bl->x,bl->y); - } - } - } - return 1; + short dx,dy; + uint8 dir; + struct unit_data *ud = NULL; + struct map_session_data *sd = NULL; + + nullpo_ret(bl); + sd = BL_CAST(BL_PC, bl); + ud = unit_bl2ud(bl); + + if( ud == NULL) return 0; + + unit_stop_walking(bl,1); + unit_stop_attack(bl); + + if( checkpath && (map_getcell(bl->m,dst_x,dst_y,CELL_CHKNOPASS) || !path_search(NULL,bl->m,bl->x,bl->y,dst_x,dst_y,easy,CELL_CHKNOREACH)) ) + return 0; // unreachable + + ud->to_x = dst_x; + ud->to_y = dst_y; + + dir = map_calc_dir(bl, dst_x, dst_y); + ud->dir = dir; + + dx = dst_x - bl->x; + dy = dst_y - bl->y; + + map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl); + + map_moveblock(bl, dst_x, dst_y, gettick()); + + ud->walktimer = -2; // arbitrary non-INVALID_TIMER value to make the clif code send walking packets + map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl); + ud->walktimer = INVALID_TIMER; + + if(sd) { + if( sd->touching_id ) + npc_touchnext_areanpc(sd,false); + if(map_getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) { + npc_touch_areanpc(sd,bl->m,bl->x,bl->y); + if (bl->prev == NULL) //Script could have warped char, abort remaining of the function. + return 0; + } else + sd->areanpc_id=0; + + if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 ) + { // Check if pet needs to be teleported. [Skotlex] + int flag = 0; + struct block_list* bl = &sd->pd->bl; + if( !checkpath && !path_search(NULL,bl->m,bl->x,bl->y,dst_x,dst_y,0,CELL_CHKNOPASS) ) + flag = 1; + else if (!check_distance_bl(&sd->bl, bl, AREA_SIZE)) //Too far, teleport. + flag = 2; + if( flag ) + { + unit_movepos(bl,sd->bl.x,sd->bl.y, 0, 0); + clif_slide(bl,bl->x,bl->y); + } + } + } + return 1; } int unit_setdir(struct block_list *bl,unsigned char dir) { - struct unit_data *ud; - nullpo_ret(bl); - ud = unit_bl2ud(bl); - if (!ud) return 0; - ud->dir = dir; - if (bl->type == BL_PC) - ((TBL_PC *)bl)->head_dir = 0; - clif_changed_dir(bl, AREA); - return 0; + struct unit_data *ud; + nullpo_ret(bl ); + ud = unit_bl2ud(bl); + if (!ud) return 0; + ud->dir = dir; + if (bl->type == BL_PC) + ((TBL_PC *)bl)->head_dir = 0; + clif_changed_dir(bl, AREA); + return 0; } uint8 unit_getdir(struct block_list *bl) { - struct unit_data *ud; - nullpo_ret(bl); - ud = unit_bl2ud(bl); - if (!ud) return 0; - return ud->dir; + struct unit_data *ud; + nullpo_ret(bl ); + ud = unit_bl2ud(bl); + if (!ud) return 0; + return ud->dir; } // Pushes a unit by given amount of cells into given direction. Only // map cell restrictions are respected. // flag: // &1 Do not send position update packets. -int unit_blown(struct block_list *bl, int dx, int dy, int count, int flag) +int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag) { - if (count) { - struct map_session_data *sd; - struct skill_unit *su = NULL; - int nx, ny, result; - - sd = BL_CAST(BL_PC, bl); - su = BL_CAST(BL_SKILL, bl); - - result = path_blownpos(bl->m, bl->x, bl->y, dx, dy, count); - - nx = result>>16; - ny = result&0xffff; - - if (!su) { - unit_stop_walking(bl, 0); - } - - if (sd) { - sd->ud.to_x = nx; - sd->ud.to_y = ny; - } - - dx = nx-bl->x; - dy = ny-bl->y; - - if (dx || dy) { - map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl); - - if (su) { - skill_unit_move_unit_group(su->group, bl->m, dx, dy); - } else { - map_moveblock(bl, nx, ny, gettick()); - } - - map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl); - - if (!(flag&1)) { - clif_blown(bl); - } - - if (sd) { - if (sd->touching_id) { - npc_touchnext_areanpc(sd, false); - } - if (map_getcell(bl->m, bl->x, bl->y, CELL_CHKNPC)) { - npc_touch_areanpc(sd, bl->m, bl->x, bl->y); - } else { - sd->areanpc_id = 0; - } - } - } - - count = distance(dx, dy); - } - - return count; // return amount of knocked back cells + if(count) { + struct map_session_data* sd; + struct skill_unit* su = NULL; + int nx, ny, result; + + sd = BL_CAST(BL_PC, bl); + su = BL_CAST(BL_SKILL, bl); + + result = path_blownpos(bl->m, bl->x, bl->y, dx, dy, count); + + nx = result>>16; + ny = result&0xffff; + + if(!su) { + unit_stop_walking(bl, 0); + } + + if( sd ) { + sd->ud.to_x = nx; + sd->ud.to_y = ny; + } + + dx = nx-bl->x; + dy = ny-bl->y; + + if(dx || dy) { + map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl); + + if(su) { + skill_unit_move_unit_group(su->group, bl->m, dx, dy); + } else { + map_moveblock(bl, nx, ny, gettick()); + } + + map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl); + + if(!(flag&1)) { + clif_blown(bl); + } + + if(sd) { + if(sd->touching_id) { + npc_touchnext_areanpc(sd, false); + } + if(map_getcell(bl->m, bl->x, bl->y, CELL_CHKNPC)) { + npc_touch_areanpc(sd, bl->m, bl->x, bl->y); + } else { + sd->areanpc_id = 0; + } + } + } + + count = distance(dx, dy); + } + + return count; // return amount of knocked back cells } //Warps a unit/ud to a given map/position. @@ -726,70 +748,70 @@ int unit_blown(struct block_list *bl, int dx, int dy, int count, int flag) //it respects the no warp flags, so it is safe to call this without doing nowarpto/nowarp checks. int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) { - struct unit_data *ud; - nullpo_ret(bl); - ud = unit_bl2ud(bl); - - if (bl->prev==NULL || !ud) - return 1; - - if (type == CLR_DEAD) - //Type 1 is invalid, since you shouldn't warp a bl with the "death" - //animation, it messes up with unit_remove_map! [Skotlex] - return 1; - - if (m<0) m=bl->m; - - switch (bl->type) { - case BL_MOB: - if (map[bl->m].flag.monster_noteleport && ((TBL_MOB *)bl)->master_id == 0) - return 1; - if (m != bl->m && map[m].flag.nobranch && battle_config.mob_warp&4 && !(((TBL_MOB *)bl)->master_id)) - return 1; - break; - case BL_PC: - if (map[bl->m].flag.noteleport) - return 1; - break; - } - - if (x<0 || y<0) { - //Random map position. - if (!map_search_freecell(NULL, m, &x, &y, -1, -1, 1)) { - ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y); - return 2; - - } - } else if (map_getcell(m,x,y,CELL_CHKNOREACH)) { - //Invalid target cell - ShowWarning("unit_warp: Specified non-walkable target cell: %d (%s) at [%d,%d]\n", m, map[m].name, x,y); - - if (!map_search_freecell(NULL, m, &x, &y, 4, 4, 1)) { - //Can't find a nearby cell - ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y); - return 2; - } - } - - if (bl->type == BL_PC) //Use pc_setpos - return pc_setpos((TBL_PC *)bl, map_id2index(m), x, y, type); - - if (!unit_remove_map(bl, type)) - return 3; - - if (bl->m != m && battle_config.clear_unit_onwarp && - battle_config.clear_unit_onwarp&bl->type) - skill_clear_unitgroup(bl); - - bl->x=ud->to_x=x; - bl->y=ud->to_y=y; - bl->m=m; - - map_addblock(bl); - clif_spawn(bl); - skill_unit_move(bl,gettick(),1); - - return 0; + struct unit_data *ud; + nullpo_ret(bl); + ud = unit_bl2ud(bl); + + if(bl->prev==NULL || !ud) + return 1; + + if (type == CLR_DEAD) + //Type 1 is invalid, since you shouldn't warp a bl with the "death" + //animation, it messes up with unit_remove_map! [Skotlex] + return 1; + + if( m<0 ) m=bl->m; + + switch (bl->type) { + case BL_MOB: + if (map[bl->m].flag.monster_noteleport && ((TBL_MOB*)bl)->master_id == 0) + return 1; + if (m != bl->m && map[m].flag.nobranch && battle_config.mob_warp&4) + return 1; + break; + case BL_PC: + if (map[bl->m].flag.noteleport) + return 1; + break; + } + + if (x<0 || y<0) + { //Random map position. + if (!map_search_freecell(NULL, m, &x, &y, -1, -1, 1)) { + ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y); + return 2; + + } + } else if (map_getcell(m,x,y,CELL_CHKNOREACH)) + { //Invalid target cell + ShowWarning("unit_warp: Specified non-walkable target cell: %d (%s) at [%d,%d]\n", m, map[m].name, x,y); + + if (!map_search_freecell(NULL, m, &x, &y, 4, 4, 1)) + { //Can't find a nearby cell + ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y); + return 2; + } + } + + if (bl->type == BL_PC) //Use pc_setpos + return pc_setpos((TBL_PC*)bl, map_id2index(m), x, y, type); + + if (!unit_remove_map(bl, type)) + return 3; + + if (bl->m != m && battle_config.clear_unit_onwarp && + battle_config.clear_unit_onwarp&bl->type) + skill_clear_unitgroup(bl); + + bl->x=ud->to_x=x; + bl->y=ud->to_y=y; + bl->m=m; + + map_addblock(bl); + clif_spawn(bl); + skill_unit_move(bl,gettick(),1); + + return 0; } /*========================================== @@ -802,64 +824,64 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) *------------------------------------------*/ int unit_stop_walking(struct block_list *bl,int type) { - struct unit_data *ud; - const struct TimerData *td; - unsigned int tick; - nullpo_ret(bl); - - ud = unit_bl2ud(bl); - if (!ud || ud->walktimer == INVALID_TIMER) - return 0; - //NOTE: We are using timer data after deleting it because we know the - //delete_timer function does not messes with it. If the function's - //behaviour changes in the future, this code could break! - td = get_timer(ud->walktimer); - delete_timer(ud->walktimer, unit_walktoxy_timer); - ud->walktimer = INVALID_TIMER; - ud->state.change_walk_target = 0; - tick = gettick(); - if ((type&0x02 && !ud->walkpath.path_pos) //Force moving at least one cell. - || (type&0x04 && td && DIFF_TICK(td->tick, tick) <= td->data/2) //Enough time has passed to cover half-cell - ) { - ud->walkpath.path_len = ud->walkpath.path_pos+1; - unit_walktoxy_timer(INVALID_TIMER, tick, bl->id, ud->walkpath.path_pos); - } - - if (type&0x01) - clif_fixpos(bl); - - ud->walkpath.path_len = 0; - ud->walkpath.path_pos = 0; - ud->to_x = bl->x; - ud->to_y = bl->y; - if (bl->type == BL_PET && type&~0xff) - ud->canmove_tick = gettick() + (type>>8); - - //Readded, the check in unit_set_walkdelay means dmg during running won't fall through to this place in code [Kevin] - if (ud->state.running) { - status_change_end(bl, SC_RUN, INVALID_TIMER); - status_change_end(bl, SC_WUGDASH, INVALID_TIMER); - } - return 1; + struct unit_data *ud; + const struct TimerData* td; + unsigned int tick; + nullpo_ret(bl); + + ud = unit_bl2ud(bl); + if(!ud || ud->walktimer == INVALID_TIMER) + return 0; + //NOTE: We are using timer data after deleting it because we know the + //delete_timer function does not messes with it. If the function's + //behaviour changes in the future, this code could break! + td = get_timer(ud->walktimer); + delete_timer(ud->walktimer, unit_walktoxy_timer); + ud->walktimer = INVALID_TIMER; + ud->state.change_walk_target = 0; + tick = gettick(); + if( (type&0x02 && !ud->walkpath.path_pos) //Force moving at least one cell. + || (type&0x04 && td && DIFF_TICK(td->tick, tick) <= td->data/2) //Enough time has passed to cover half-cell + ) { + ud->walkpath.path_len = ud->walkpath.path_pos+1; + unit_walktoxy_timer(INVALID_TIMER, tick, bl->id, ud->walkpath.path_pos); + } + + if(type&0x01) + clif_fixpos(bl); + + ud->walkpath.path_len = 0; + ud->walkpath.path_pos = 0; + ud->to_x = bl->x; + ud->to_y = bl->y; + if(bl->type == BL_PET && type&~0xff) + ud->canmove_tick = gettick() + (type>>8); + + //Readded, the check in unit_set_walkdelay means dmg during running won't fall through to this place in code [Kevin] + if (ud->state.running) { + status_change_end(bl, SC_RUN, INVALID_TIMER); + status_change_end(bl, SC_WUGDASH, INVALID_TIMER); + } + return 1; } int unit_skilluse_id(struct block_list *src, int target_id, short skill_num, short skill_lv) { - if (skill_num < 0) return 0; + if(skill_num < 0) return 0; - return unit_skilluse_id2( - src, target_id, skill_num, skill_lv, - skill_castfix(src, skill_num, skill_lv), - skill_get_castcancel(skill_num) - ); + return unit_skilluse_id2( + src, target_id, skill_num, skill_lv, + skill_castfix(src, skill_num, skill_lv), + skill_get_castcancel(skill_num) + ); } int unit_is_walking(struct block_list *bl) { - struct unit_data *ud = unit_bl2ud(bl); - nullpo_ret(bl); - if (!ud) return 0; - return (ud->walktimer != INVALID_TIMER); + struct unit_data *ud = unit_bl2ud(bl); + nullpo_ret(bl); + if(!ud) return 0; + return (ud->walktimer != INVALID_TIMER); } /*========================================== @@ -867,54 +889,54 @@ int unit_is_walking(struct block_list *bl) *------------------------------------------*/ int unit_can_move(struct block_list *bl) { - struct map_session_data *sd; - struct unit_data *ud; - struct status_change *sc; - - nullpo_ret(bl); - ud = unit_bl2ud(bl); - sc = status_get_sc(bl); - sd = BL_CAST(BL_PC, bl); - - if (!ud) - return 0; - - if (ud->skilltimer != INVALID_TIMER && ud->skillid != LG_EXEEDBREAK && (!sd || !pc_checkskill(sd, SA_FREECAST) || skill_get_inf2(ud->skillid)&INF2_GUILD_SKILL)) - return 0; // prevent moving while casting - - if (DIFF_TICK(ud->canmove_tick, gettick()) > 0) - return 0; - - if (sd && ( - pc_issit(sd) || - sd->state.vending || - sd->state.buyingstore || - sd->state.blockedmove - )) - return 0; //Can't move - - if (sc) { - if (sc->cant.move /* status placed here are ones that cannot be cached by sc->cant.move for they depend on other conditions other than their availability */ - || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) - || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) - || (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && ( - !sc->data[SC_LONGING] || - (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT || - (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE - )) - || (sc->data[SC_CLOAKING] && //Need wall at level 1-2 - sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) - ) - return 0; - - if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING && (sc->opt1 != OPT1_CRYSTALIZE && bl->type != BL_MOB)) - return 0; - - if ((sc->option & OPTION_HIDE) && (!sd || pc_checkskill(sd, RG_TUNNELDRIVE) <= 0)) - return 0; - - } - return 1; + struct map_session_data *sd; + struct unit_data *ud; + struct status_change *sc; + + nullpo_ret(bl); + ud = unit_bl2ud(bl); + sc = status_get_sc(bl); + sd = BL_CAST(BL_PC, bl); + + if (!ud) + return 0; + + if (ud->skilltimer != INVALID_TIMER && ud->skillid != LG_EXEEDBREAK && (!sd || !pc_checkskill(sd, SA_FREECAST) || skill_get_inf2(ud->skillid)&INF2_GUILD_SKILL)) + return 0; // prevent moving while casting + + if (DIFF_TICK(ud->canmove_tick, gettick()) > 0) + return 0; + + if (sd && ( + pc_issit(sd) || + sd->state.vending || + sd->state.buyingstore || + sd->state.blockedmove + )) + return 0; //Can't move + + if (sc) { + if( sc->cant.move /* status placed here are ones that cannot be cached by sc->cant.move for they depend on other conditions other than their availability */ + || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) + || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) + || (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && ( + !sc->data[SC_LONGING] || + (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT || + (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE + ) ) + || (sc->data[SC_CLOAKING] && //Need wall at level 1-2 + sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) + ) + return 0; + + if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING && (sc->opt1 != OPT1_CRYSTALIZE && bl->type != BL_MOB)) + return 0; + + if ((sc->option & OPTION_HIDE) && (!sd || pc_checkskill(sd, RG_TUNNELDRIVE) <= 0)) + return 0; + + } + return 1; } /*========================================== @@ -924,19 +946,19 @@ int unit_can_move(struct block_list *bl) int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data) { - struct unit_data *ud = (struct unit_data *)data; - TBL_PC *sd = map_id2sd(id); + struct unit_data *ud = (struct unit_data *)data; + TBL_PC * sd = map_id2sd(id); - if (sd && pc_isridingwug(sd)) - clif_skill_nodamage(ud->bl,ud->bl,RA_WUGDASH,ud->skilllv, - sc_start4(ud->bl,status_skill2sc(RA_WUGDASH),100,ud->skilllv,unit_getdir(ud->bl),0,0,1)); - else - clif_skill_nodamage(ud->bl,ud->bl,TK_RUN,ud->skilllv, - sc_start4(ud->bl,status_skill2sc(TK_RUN),100,ud->skilllv,unit_getdir(ud->bl),0,0,0)); + if(sd && pc_isridingwug(sd)) + clif_skill_nodamage(ud->bl,ud->bl,RA_WUGDASH,ud->skilllv, + sc_start4(ud->bl,status_skill2sc(RA_WUGDASH),100,ud->skilllv,unit_getdir(ud->bl),0,0,1)); + else + clif_skill_nodamage(ud->bl,ud->bl,TK_RUN,ud->skilllv, + sc_start4(ud->bl,status_skill2sc(TK_RUN),100,ud->skilllv,unit_getdir(ud->bl),0,0,0)); - if (sd) clif_walkok(sd); + if (sd) clif_walkok(sd); - return 0; + return 0; } @@ -948,534 +970,555 @@ int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ int unit_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int type) { - struct unit_data *ud = unit_bl2ud(bl); - if (delay <= 0 || !ud) return 0; - - /** - * MvP mobs have no walk delay - **/ - if (bl->type == BL_MOB && (((TBL_MOB *)bl)->status.mode&MD_BOSS)) - return 0; - - if (type) { - if (DIFF_TICK(ud->canmove_tick, tick+delay) > 0) - return 0; - } else { - //Don't set walk delays when already trapped. - if (!unit_can_move(bl)) - return 0; - } - ud->canmove_tick = tick + delay; - if (ud->walktimer != INVALID_TIMER) { - //Stop walking, if chasing, readjust timers. - if (delay == 1) { - //Minimal delay (walk-delay) disabled. Just stop walking. - unit_stop_walking(bl,4); - } else { - //Resume running after can move again [Kevin] - if (ud->state.running) { - add_timer(ud->canmove_tick, unit_resume_running, bl->id, (intptr_t)ud); - } else { - unit_stop_walking(bl,2|4); - if (ud->target) - add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target); - } - } - } - return 1; + struct unit_data *ud = unit_bl2ud(bl); + if (delay <= 0 || !ud) return 0; + + /** + * MvP mobs have no walk delay + **/ + if( bl->type == BL_MOB && (((TBL_MOB*)bl)->status.mode&MD_BOSS) ) + return 0; + + if (type) { + if (DIFF_TICK(ud->canmove_tick, tick+delay) > 0) + return 0; + } else { + //Don't set walk delays when already trapped. + if (!unit_can_move(bl)) + return 0; + } + ud->canmove_tick = tick + delay; + if (ud->walktimer != INVALID_TIMER) + { //Stop walking, if chasing, readjust timers. + if (delay == 1) + { //Minimal delay (walk-delay) disabled. Just stop walking. + unit_stop_walking(bl,4); + } else { + //Resume running after can move again [Kevin] + if(ud->state.running) + { + add_timer(ud->canmove_tick, unit_resume_running, bl->id, (intptr_t)ud); + } + else + { + unit_stop_walking(bl,2|4); + if(ud->target) + add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target); + } + } + } + return 1; } int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, short skill_lv, int casttime, int castcancel) { - struct unit_data *ud; - struct status_data *tstatus; - struct status_change *sc; - struct map_session_data *sd = NULL; - struct block_list *target = NULL; - unsigned int tick = gettick(); - int temp = 0; - - nullpo_ret(src); - if (status_isdead(src)) - return 0; //Do not continue source is dead - - sd = BL_CAST(BL_PC, src); - ud = unit_bl2ud(src); - - if (ud == NULL) return 0; - sc = status_get_sc(src); - if (sc && !sc->count) - sc = NULL; //Unneeded - - //temp: used to signal combo-skills right now. - if (sc && sc->data[SC_COMBO] && (sc->data[SC_COMBO]->val1 == skill_num || - (sd?skill_check_condition_castbegin(sd,skill_num,skill_lv):0))) { - if (sc->data[SC_COMBO]->val2) - target_id = sc->data[SC_COMBO]->val2; - else - target_id = ud->target; - - if (skill_get_inf(skill_num)&INF_SELF_SKILL && skill_get_nk(skill_num)&NK_NO_DAMAGE) // exploit fix - target_id = src->id; - temp = 1; - } else if (target_id == src->id && - skill_get_inf(skill_num)&INF_SELF_SKILL && - skill_get_inf2(skill_num)&INF2_NO_TARGET_SELF) { - target_id = ud->target; //Auto-select target. [Skotlex] - temp = 1; - } - - if (sd) { - //Target_id checking. - if (skillnotok(skill_num, sd)) // [MouseJstr] - return 0; - - switch (skill_num) { - //Check for skills that auto-select target - case MO_CHAINCOMBO: - if (sc && sc->data[SC_BLADESTOP]) { - if ((target=map_id2bl(sc->data[SC_BLADESTOP]->val4)) == NULL) - return 0; - } - break; - case WE_MALE: - case WE_FEMALE: - if (!sd->status.partner_id) - return 0; - target = (struct block_list *)map_charid2sd(sd->status.partner_id); - if (!target) { - clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - } - if (target) - target_id = target->id; - } - if (src->type==BL_HOM) - switch (skill_num) { - //Homun-auto-target skills. - case HLIF_HEAL: - case HLIF_AVOID: - case HAMI_DEFENCE: - case HAMI_CASTLE: - target = battle_get_master(src); - if (!target) return 0; - target_id = target->id; - } - - if (!target) // choose default target - target = map_id2bl(target_id); - - if (!target || src->m != target->m || !src->prev || !target->prev) - return 0; - - if (battle_config.ksprotection && sd && mob_ksprotected(src, target)) - return 0; - - //Normally not needed because clif.c checks for it, but the at/char/script commands don't! [Skotlex] - if (ud->skilltimer != INVALID_TIMER && skill_num != SA_CASTCANCEL && skill_num != SO_SPELLFIST) - return 0; - - if (skill_get_inf2(skill_num)&INF2_NO_TARGET_SELF && src->id == target_id) - return 0; - - if (!status_check_skilluse(src, target, skill_num, 0)) - return 0; - - tstatus = status_get_status_data(target); - // Record the status of the previous skill) - if (sd) { - switch (skill_num) { - case SA_CASTCANCEL: - if (ud->skillid != skill_num) { - sd->skillid_old = ud->skillid; - sd->skilllv_old = ud->skilllv; - } - break; - case BD_ENCORE: - //Prevent using the dance skill if you no longer have the skill in your tree. - if (!sd->skillid_dance || pc_checkskill(sd,sd->skillid_dance)<=0) { - clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); - return 0; - } - sd->skillid_old = skill_num; - break; - case BD_LULLABY: - case BD_RICHMANKIM: - case BD_ETERNALCHAOS: - case BD_DRUMBATTLEFIELD: - case BD_RINGNIBELUNGEN: - case BD_ROKISWEIL: - case BD_INTOABYSS: - case BD_SIEGFRIED: - case CG_MOONLIT: - if (skill_check_pc_partner(sd, skill_num, &skill_lv, 1, 0) < 1) { - clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case WL_WHITEIMPRISON: - if (battle_check_target(src,target,BCT_SELF|BCT_ENEMY) < 0) { - clif_skill_fail(sd,skill_num,USESKILL_FAIL_TOTARGET,0); - return 0; - } - break; - case MG_FIREBOLT: - case MG_LIGHTNINGBOLT: - case MG_COLDBOLT: - sd->skillid_old = skill_num; - sd->skilllv_old = skill_lv; - break; - } - if (!skill_check_condition_castbegin(sd, skill_num, skill_lv)) - return 0; - } - - if (src->type == BL_MOB) - switch (skill_num) { - case NPC_SUMMONSLAVE: - case NPC_SUMMONMONSTER: - case AL_TELEPORT: - if (((TBL_MOB *)src)->master_id && ((TBL_MOB *)src)->special_state.ai) - return 0; - } - - //Check range when not using skill on yourself or is a combo-skill during attack - //(these are supposed to always have the same range as your attack) - if (src->id != target_id && (!temp || ud->attacktimer == INVALID_TIMER)) { - if (skill_get_state(ud->skillid) == ST_MOVE_ENABLE) { - if (!unit_can_reach_bl(src, target, skill_get_range2(src, skill_num,skill_lv) + 1, 1, NULL, NULL)) - return 0; // Walk-path check failed. - } else if (src->type == BL_MER && skill_num == MA_REMOVETRAP) { - if (!battle_check_range(battle_get_master(src), target, skill_get_range2(src, skill_num, skill_lv) + 1)) - return 0; // Aegis calc remove trap based on Master position, ignoring mercenary O.O - } else if (!battle_check_range(src, target, skill_get_range2(src, skill_num,skill_lv) + (skill_num == RG_CLOSECONFINE?0:2))) { - return 0; // Arrow-path check failed. - } - } - - if (!temp) //Stop attack on non-combo skills [Skotlex] - unit_stop_attack(src); - else if (ud->attacktimer != INVALID_TIMER) //Elsewise, delay current attack sequence - ud->attackabletime = tick + status_get_adelay(src); - - ud->state.skillcastcancel = castcancel; - - //temp: Used to signal force cast now. - temp = 0; - - switch (skill_num) { - case ALL_RESURRECTION: - if (battle_check_undead(tstatus->race,tstatus->def_ele)) { - temp = 1; - } else if (!status_isdead(target)) - return 0; //Can't cast on non-dead characters. - break; - case MO_FINGEROFFENSIVE: - if (sd) - casttime += casttime * min(skill_lv, sd->spiritball); - break; - case MO_EXTREMITYFIST: - if (sc && sc->data[SC_COMBO] && - (sc->data[SC_COMBO]->val1 == MO_COMBOFINISH || - sc->data[SC_COMBO]->val1 == CH_TIGERFIST || - sc->data[SC_COMBO]->val1 == CH_CHAINCRUSH)) - casttime = -1; - temp = 1; - break; - case SR_GATEOFHELL: - case SR_TIGERCANNON: - if (sc && sc->data[SC_COMBO] && - sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) - casttime = -1; - temp = 1; - break; - case SA_SPELLBREAKER: - temp = 1; - break; - case ST_CHASEWALK: - if (sc && sc->data[SC_CHASEWALK]) - casttime = -1; - break; - case TK_RUN: - if (sc && sc->data[SC_RUN]) - casttime = -1; - break; - case HP_BASILICA: - if (sc && sc->data[SC_BASILICA]) - casttime = -1; // No Casting time on basilica cancel - break; - case KN_CHARGEATK: { - unsigned int k = (distance_bl(src,target)-1)/3; //+100% every 3 cells of distance - if (k > 2) k = 2; // ...but hard-limited to 300%. - casttime += casttime * k; - } - break; - case GD_EMERGENCYCALL: //Emergency Call double cast when the user has learned Leap [Daegaladh] - if (sd && pc_checkskill(sd,TK_HIGHJUMP)) - casttime *= 2; - break; - case RA_WUGDASH: - if (sc && sc->data[SC_WUGDASH]) - casttime = -1; - break; - } - - // moved here to prevent Suffragium from ending if skill fails + struct unit_data *ud; + struct status_data *tstatus; + struct status_change *sc; + struct map_session_data *sd = NULL; + struct block_list * target = NULL; + unsigned int tick = gettick(); + int temp = 0; + + nullpo_ret(src); + if(status_isdead(src)) + return 0; //Do not continue source is dead + + sd = BL_CAST(BL_PC, src); + ud = unit_bl2ud(src); + + if(ud == NULL) return 0; + sc = status_get_sc(src); + if (sc && !sc->count) + sc = NULL; //Unneeded + + //temp: used to signal combo-skills right now. + if (sc && sc->data[SC_COMBO] && (sc->data[SC_COMBO]->val1 == skill_num || + (sd?skill_check_condition_castbegin(sd,skill_num,skill_lv):0) )) { + if (sc->data[SC_COMBO]->val2) + target_id = sc->data[SC_COMBO]->val2; + else + target_id = ud->target; + + if( skill_get_inf(skill_num)&INF_SELF_SKILL && skill_get_nk(skill_num)&NK_NO_DAMAGE )// exploit fix + target_id = src->id; + temp = 1; + } else + if ( target_id == src->id && + skill_get_inf(skill_num)&INF_SELF_SKILL && + skill_get_inf2(skill_num)&INF2_NO_TARGET_SELF ) + { + target_id = ud->target; //Auto-select target. [Skotlex] + temp = 1; + } + + if (sd) { + //Target_id checking. + if(skillnotok(skill_num, sd)) // [MouseJstr] + return 0; + + switch(skill_num) + { //Check for skills that auto-select target + case MO_CHAINCOMBO: + if (sc && sc->data[SC_BLADESTOP]){ + if ((target=map_id2bl(sc->data[SC_BLADESTOP]->val4)) == NULL) + return 0; + } + break; + case WE_MALE: + case WE_FEMALE: + if (!sd->status.partner_id) + return 0; + target = (struct block_list*)map_charid2sd(sd->status.partner_id); + if (!target) { + clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + } + if (target) + target_id = target->id; + } + if (src->type==BL_HOM) + switch(skill_num) + { //Homun-auto-target skills. + case HLIF_HEAL: + case HLIF_AVOID: + case HAMI_DEFENCE: + case HAMI_CASTLE: + target = battle_get_master(src); + if (!target) return 0; + target_id = target->id; + } + + if( !target ) // choose default target + target = map_id2bl(target_id); + + if( !target || src->m != target->m || !src->prev || !target->prev ) + return 0; + + if( battle_config.ksprotection && sd && mob_ksprotected(src, target) ) + return 0; + + //Normally not needed because clif.c checks for it, but the at/char/script commands don't! [Skotlex] + if(ud->skilltimer != INVALID_TIMER && skill_num != SA_CASTCANCEL && skill_num != SO_SPELLFIST) + return 0; + + if(skill_get_inf2(skill_num)&INF2_NO_TARGET_SELF && src->id == target_id) + return 0; + + if(!status_check_skilluse(src, target, skill_num, 0)) + return 0; + + tstatus = status_get_status_data(target); + // Record the status of the previous skill) + if(sd) { + switch(skill_num){ + case SA_CASTCANCEL: + if(ud->skillid != skill_num){ + sd->skillid_old = ud->skillid; + sd->skilllv_old = ud->skilllv; + } + break; + case BD_ENCORE: + //Prevent using the dance skill if you no longer have the skill in your tree. + if(!sd->skillid_dance || pc_checkskill(sd,sd->skillid_dance)<=0){ + clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); + return 0; + } + sd->skillid_old = skill_num; + break; + case BD_LULLABY: + case BD_RICHMANKIM: + case BD_ETERNALCHAOS: + case BD_DRUMBATTLEFIELD: + case BD_RINGNIBELUNGEN: + case BD_ROKISWEIL: + case BD_INTOABYSS: + case BD_SIEGFRIED: + case CG_MOONLIT: + if (skill_check_pc_partner(sd, skill_num, &skill_lv, 1, 0) < 1) + { + clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case WL_WHITEIMPRISON: + if( battle_check_target(src,target,BCT_SELF|BCT_ENEMY) < 0 ) { + clif_skill_fail(sd,skill_num,USESKILL_FAIL_TOTARGET,0); + return 0; + } + break; + case MG_FIREBOLT: + case MG_LIGHTNINGBOLT: + case MG_COLDBOLT: + sd->skillid_old = skill_num; + sd->skilllv_old = skill_lv; + break; + } + if (!skill_check_condition_castbegin(sd, skill_num, skill_lv)) + return 0; + } + + if( src->type == BL_MOB ) + switch( skill_num ) + { + case NPC_SUMMONSLAVE: + case NPC_SUMMONMONSTER: + case AL_TELEPORT: + if( ((TBL_MOB*)src)->master_id && ((TBL_MOB*)src)->special_state.ai ) + return 0; + } + + //Check range when not using skill on yourself or is a combo-skill during attack + //(these are supposed to always have the same range as your attack) + if( src->id != target_id && (!temp || ud->attacktimer == INVALID_TIMER) ) { + if( skill_get_state(ud->skillid) == ST_MOVE_ENABLE ) { + if( !unit_can_reach_bl(src, target, skill_get_range2(src, skill_num,skill_lv) + 1, 1, NULL, NULL) ) + return 0; // Walk-path check failed. + } else if( src->type == BL_MER && skill_num == MA_REMOVETRAP ) { + if( !battle_check_range(battle_get_master(src), target, skill_get_range2(src, skill_num, skill_lv) + 1) ) + return 0; // Aegis calc remove trap based on Master position, ignoring mercenary O.O + } else if( !battle_check_range(src, target, skill_get_range2(src, skill_num,skill_lv) + (skill_num == RG_CLOSECONFINE?0:2)) ) { + return 0; // Arrow-path check failed. + } + } + + if (!temp) //Stop attack on non-combo skills [Skotlex] + unit_stop_attack(src); + else if(ud->attacktimer != INVALID_TIMER) //Elsewise, delay current attack sequence + ud->attackabletime = tick + status_get_adelay(src); + + ud->state.skillcastcancel = castcancel; + + //temp: Used to signal force cast now. + temp = 0; + + switch(skill_num){ + case ALL_RESURRECTION: + if(battle_check_undead(tstatus->race,tstatus->def_ele)) { + temp = 1; + } else if (!status_isdead(target)) + return 0; //Can't cast on non-dead characters. + break; + case MO_FINGEROFFENSIVE: + if(sd) + casttime += casttime * min(skill_lv, sd->spiritball); + break; + case MO_EXTREMITYFIST: + if (sc && sc->data[SC_COMBO] && + (sc->data[SC_COMBO]->val1 == MO_COMBOFINISH || + sc->data[SC_COMBO]->val1 == CH_TIGERFIST || + sc->data[SC_COMBO]->val1 == CH_CHAINCRUSH)) + casttime = -1; + temp = 1; + break; + case SR_GATEOFHELL: + case SR_TIGERCANNON: + if (sc && sc->data[SC_COMBO] && + sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) + casttime = -1; + temp = 1; + break; + case SA_SPELLBREAKER: + temp = 1; + break; + case ST_CHASEWALK: + if (sc && sc->data[SC_CHASEWALK]) + casttime = -1; + break; + case TK_RUN: + if (sc && sc->data[SC_RUN]) + casttime = -1; + break; + case HP_BASILICA: + if( sc && sc->data[SC_BASILICA] ) + casttime = -1; // No Casting time on basilica cancel + break; + case KN_CHARGEATK: + { + unsigned int k = (distance_bl(src,target)-1)/3; //+100% every 3 cells of distance + if( k > 2 ) k = 2; // ...but hard-limited to 300%. + casttime += casttime * k; + } + break; + case GD_EMERGENCYCALL: //Emergency Call double cast when the user has learned Leap [Daegaladh] + if( sd && pc_checkskill(sd,TK_HIGHJUMP) ) + casttime *= 2; + break; + case RA_WUGDASH: + if (sc && sc->data[SC_WUGDASH]) + casttime = -1; + break; + } + + // moved here to prevent Suffragium from ending if skill fails #ifndef RENEWAL_CAST - if (!(skill_get_castnodex(skill_num, skill_lv)&2)) - casttime = skill_castfix_sc(src, casttime); + if (!(skill_get_castnodex(skill_num, skill_lv)&2)) + casttime = skill_castfix_sc(src, casttime); #else - casttime = skill_vfcastfix(src, casttime, skill_num, skill_lv); + casttime = skill_vfcastfix(src, casttime, skill_num, skill_lv); #endif - unit_stop_walking(src,1);// eventhough this is not how official works but this will do the trick. bugreport:6829 - // in official this is triggered even if no cast time. - clif_skillcasting(src, src->id, target_id, 0,0, skill_num, skill_get_ele(skill_num, skill_lv), casttime); - if (casttime > 0 || temp) { - if (sd && target->type == BL_MOB) { - TBL_MOB *md = (TBL_MOB *)target; - mobskill_event(md, src, tick, -1); //Cast targetted skill event. - if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) && - battle_check_target(target, src, BCT_ENEMY) > 0) { - switch (md->state.skillstate) { - case MSS_RUSH: - case MSS_FOLLOW: - if (!(tstatus->mode&MD_CASTSENSOR_CHASE)) - break; - md->target_id = src->id; - md->state.aggressive = (tstatus->mode&MD_ANGRY)?1:0; - md->min_chase = md->db->range3; - break; - case MSS_IDLE: - case MSS_WALK: - if (!(tstatus->mode&MD_CASTSENSOR_IDLE)) - break; - md->target_id = src->id; - md->state.aggressive = (tstatus->mode&MD_ANGRY)?1:0; - md->min_chase = md->db->range3; - break; - } - } - } - } - - if (casttime <= 0) - ud->state.skillcastcancel = 0; - - if (!sd || sd->skillitem != skill_num || skill_get_cast(skill_num,skill_lv)) - ud->canact_tick = tick + casttime + 100; - if (sd) { - switch (skill_num) { - case CG_ARROWVULCAN: - sd->canequip_tick = tick + casttime; - break; - } - } - ud->skilltarget = target_id; - ud->skillx = 0; - ud->skilly = 0; - ud->skillid = skill_num; - ud->skilllv = skill_lv; - - if (sc) { - /** - * why the if else chain: these 3 status do not stack, so its efficient that way. - **/ - if (sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4) && skill_num != AS_CLOAKING) { - status_change_end(src, SC_CLOAKING, INVALID_TIMER); - if (!src->prev) return 0; //Warped away! - } else if (sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4&4) && skill_num != GC_CLOAKINGEXCEED) { - status_change_end(src,SC_CLOAKINGEXCEED, INVALID_TIMER); - if (!src->prev) return 0; - } - } - - - if (casttime > 0) { - ud->skilltimer = add_timer(tick+casttime, skill_castend_id, src->id, 0); - if (sd && (pc_checkskill(sd,SA_FREECAST) > 0 || skill_num == LG_EXEEDBREAK)) - status_calc_bl(&sd->bl, SCB_SPEED); - } else - skill_castend_id(ud->skilltimer,tick,src->id,0); - - return 1; + unit_stop_walking(src,1);// eventhough this is not how official works but this will do the trick. bugreport:6829 + // in official this is triggered even if no cast time. + clif_skillcasting(src, src->id, target_id, 0,0, skill_num, skill_get_ele(skill_num, skill_lv), casttime); + if( casttime > 0 || temp ) + { + if (sd && target->type == BL_MOB) + { + TBL_MOB *md = (TBL_MOB*)target; + mobskill_event(md, src, tick, -1); //Cast targetted skill event. + if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) && + battle_check_target(target, src, BCT_ENEMY) > 0) + { + switch (md->state.skillstate) { + case MSS_RUSH: + case MSS_FOLLOW: + if (!(tstatus->mode&MD_CASTSENSOR_CHASE)) + break; + md->target_id = src->id; + md->state.aggressive = (tstatus->mode&MD_ANGRY)?1:0; + md->min_chase = md->db->range3; + break; + case MSS_IDLE: + case MSS_WALK: + if (!(tstatus->mode&MD_CASTSENSOR_IDLE)) + break; + md->target_id = src->id; + md->state.aggressive = (tstatus->mode&MD_ANGRY)?1:0; + md->min_chase = md->db->range3; + break; + } + } + } + } + + if( casttime <= 0 ) + ud->state.skillcastcancel = 0; + + if( !sd || sd->skillitem != skill_num || skill_get_cast(skill_num,skill_lv) ) + ud->canact_tick = tick + casttime + 100; + if( sd ) + { + switch( skill_num ) + { + case CG_ARROWVULCAN: + sd->canequip_tick = tick + casttime; + break; + } + } + ud->skilltarget = target_id; + ud->skillx = 0; + ud->skilly = 0; + ud->skillid = skill_num; + ud->skilllv = skill_lv; + + if( sc ) { + /** + * why the if else chain: these 3 status do not stack, so its efficient that way. + **/ + if( sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4) && skill_num != AS_CLOAKING ) { + status_change_end(src, SC_CLOAKING, INVALID_TIMER); + if (!src->prev) return 0; //Warped away! + } else if( sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4&4) && skill_num != GC_CLOAKINGEXCEED ) { + status_change_end(src,SC_CLOAKINGEXCEED, INVALID_TIMER); + if (!src->prev) return 0; + } + } + + + if( casttime > 0 ) + { + ud->skilltimer = add_timer( tick+casttime, skill_castend_id, src->id, 0 ); + if( sd && (pc_checkskill(sd,SA_FREECAST) > 0 || skill_num == LG_EXEEDBREAK) ) + status_calc_bl(&sd->bl, SCB_SPEED); + } + else + skill_castend_id(ud->skilltimer,tick,src->id,0); + + return 1; } int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, short skill_num, short skill_lv) { - if (skill_num < 0) - return 0; - return unit_skilluse_pos2( - src, skill_x, skill_y, skill_num, skill_lv, - skill_castfix(src, skill_num, skill_lv), - skill_get_castcancel(skill_num) - ); + if(skill_num < 0) + return 0; + return unit_skilluse_pos2( + src, skill_x, skill_y, skill_num, skill_lv, + skill_castfix(src, skill_num, skill_lv), + skill_get_castcancel(skill_num) + ); } -int unit_skilluse_pos2(struct block_list *src, short skill_x, short skill_y, short skill_num, short skill_lv, int casttime, int castcancel) +int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, short skill_num, short skill_lv, int casttime, int castcancel) { - struct map_session_data *sd = NULL; - struct unit_data *ud = NULL; - struct status_change *sc; - struct block_list bl; - unsigned int tick = gettick(); - - nullpo_ret(src); - - if (!src->prev) return 0; // not on the map - if (status_isdead(src)) return 0; - - sd = BL_CAST(BL_PC, src); - ud = unit_bl2ud(src); - if (ud == NULL) return 0; - - if (ud->skilltimer != INVALID_TIMER) //Normally not needed since clif.c checks for it, but at/char/script commands don't! [Skotlex] - return 0; - - sc = status_get_sc(src); - if (sc && !sc->count) - sc = NULL; - - if (sd) { - if (skillnotok(skill_num, sd) || !skill_check_condition_castbegin(sd, skill_num, skill_lv)) - return 0; - /** - * "WHY IS IT HEREE": pneuma cannot be cancelled past this point, the client displays the animation even, - * if we cancel it from nodamage_id, so it has to be here for it to not display the animation. - **/ - if (skill_num == AL_PNEUMA && map_getcell(src->m, skill_x, skill_y, CELL_CHKLANDPROTECTOR)) { - clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); - return 0; - } - } - - if (!status_check_skilluse(src, NULL, skill_num, 0)) - return 0; - - if (map_getcell(src->m, skill_x, skill_y, CELL_CHKWALL)) { - // can't cast ground targeted spells on wall cells - if (sd) clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); - return 0; - } + struct map_session_data *sd = NULL; + struct unit_data *ud = NULL; + struct status_change *sc; + struct block_list bl; + unsigned int tick = gettick(); + + nullpo_ret(src); + + if (!src->prev) return 0; // not on the map + if(status_isdead(src)) return 0; + + sd = BL_CAST(BL_PC, src); + ud = unit_bl2ud(src); + if(ud == NULL) return 0; + + if(ud->skilltimer != INVALID_TIMER) //Normally not needed since clif.c checks for it, but at/char/script commands don't! [Skotlex] + return 0; + + sc = status_get_sc(src); + if (sc && !sc->count) + sc = NULL; + + if( sd ) + { + if( skillnotok(skill_num, sd) || !skill_check_condition_castbegin(sd, skill_num, skill_lv) ) + return 0; + /** + * "WHY IS IT HEREE": pneuma cannot be cancelled past this point, the client displays the animation even, + * if we cancel it from nodamage_id, so it has to be here for it to not display the animation. + **/ + if( skill_num == AL_PNEUMA && map_getcell(src->m, skill_x, skill_y, CELL_CHKLANDPROTECTOR) ) { + clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); + return 0; + } + } + + if (!status_check_skilluse(src, NULL, skill_num, 0)) + return 0; + + if( map_getcell(src->m, skill_x, skill_y, CELL_CHKWALL) ) + {// can't cast ground targeted spells on wall cells + if (sd) clif_skill_fail(sd,skill_num,USESKILL_FAIL_LEVEL,0); + return 0; + } /* Check range and obstacle */ - bl.type = BL_NUL; - bl.m = src->m; - bl.x = skill_x; - bl.y = skill_y; - - if (skill_get_state(ud->skillid) == ST_MOVE_ENABLE) { - if (!unit_can_reach_bl(src, &bl, skill_get_range2(src, skill_num,skill_lv) + 1, 1, NULL, NULL)) - return 0; //Walk-path check failed. - } else if (!battle_check_range(src, &bl, skill_get_range2(src, skill_num,skill_lv) + 1)) - return 0; //Arrow-path check failed. - - unit_stop_attack(src); - - // moved here to prevent Suffragium from ending if skill fails + bl.type = BL_NUL; + bl.m = src->m; + bl.x = skill_x; + bl.y = skill_y; + + if( skill_get_state(ud->skillid) == ST_MOVE_ENABLE ) + { + if( !unit_can_reach_bl(src, &bl, skill_get_range2(src, skill_num,skill_lv) + 1, 1, NULL, NULL) ) + return 0; //Walk-path check failed. + } + else if( !battle_check_range(src, &bl, skill_get_range2(src, skill_num,skill_lv) + 1) ) + return 0; //Arrow-path check failed. + + unit_stop_attack(src); + + // moved here to prevent Suffragium from ending if skill fails #ifndef RENEWAL_CAST - if (!(skill_get_castnodex(skill_num, skill_lv)&2)) - casttime = skill_castfix_sc(src, casttime); + if (!(skill_get_castnodex(skill_num, skill_lv)&2)) + casttime = skill_castfix_sc(src, casttime); #else - casttime = skill_vfcastfix(src, casttime, skill_num, skill_lv); + casttime = skill_vfcastfix(src, casttime, skill_num, skill_lv ); #endif - ud->state.skillcastcancel = castcancel&&casttime>0?1:0; - if (!sd || sd->skillitem != skill_num || skill_get_cast(skill_num,skill_lv)) - ud->canact_tick = tick + casttime + 100; - // if( sd ) - // { - // switch( skill_num ) - // { - // case ????: - // sd->canequip_tick = tick + casttime; - // } - // } - ud->skillid = skill_num; - ud->skilllv = skill_lv; - ud->skillx = skill_x; - ud->skilly = skill_y; - ud->skilltarget = 0; - - if (sc) { - /** - * why the if else chain: these 3 status do not stack, so its efficient that way. - **/ - if (sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4)) { - status_change_end(src, SC_CLOAKING, INVALID_TIMER); - if (!src->prev) return 0; //Warped away! - } else if (sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4&4)) { - status_change_end(src, SC_CLOAKINGEXCEED, INVALID_TIMER); - if (!src->prev) return 0; - } - } - - unit_stop_walking(src,1); - // in official this is triggered even if no cast time. - clif_skillcasting(src, src->id, 0, skill_x, skill_y, skill_num, skill_get_ele(skill_num, skill_lv), casttime); - if (casttime > 0) { - ud->skilltimer = add_timer(tick+casttime, skill_castend_pos, src->id, 0); - if ((sd && pc_checkskill(sd,SA_FREECAST) > 0) || skill_num == LG_EXEEDBREAK) - status_calc_bl(&sd->bl, SCB_SPEED); - } else { - ud->skilltimer = INVALID_TIMER; - skill_castend_pos(ud->skilltimer,tick,src->id,0); - } - return 1; + ud->state.skillcastcancel = castcancel&&casttime>0?1:0; + if( !sd || sd->skillitem != skill_num || skill_get_cast(skill_num,skill_lv) ) + ud->canact_tick = tick + casttime + 100; +// if( sd ) +// { +// switch( skill_num ) +// { +// case ????: +// sd->canequip_tick = tick + casttime; +// } +// } + ud->skillid = skill_num; + ud->skilllv = skill_lv; + ud->skillx = skill_x; + ud->skilly = skill_y; + ud->skilltarget = 0; + + if( sc ) { + /** + * why the if else chain: these 3 status do not stack, so its efficient that way. + **/ + if (sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4)) { + status_change_end(src, SC_CLOAKING, INVALID_TIMER); + if (!src->prev) return 0; //Warped away! + } else if (sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4&4)) { + status_change_end(src, SC_CLOAKINGEXCEED, INVALID_TIMER); + if (!src->prev) return 0; + } + } + + unit_stop_walking(src,1); + // in official this is triggered even if no cast time. + clif_skillcasting(src, src->id, 0, skill_x, skill_y, skill_num, skill_get_ele(skill_num, skill_lv), casttime); + if( casttime > 0 ) + { + ud->skilltimer = add_timer( tick+casttime, skill_castend_pos, src->id, 0 ); + if( (sd && pc_checkskill(sd,SA_FREECAST) > 0) || skill_num == LG_EXEEDBREAK) + status_calc_bl(&sd->bl, SCB_SPEED); + } + else + { + ud->skilltimer = INVALID_TIMER; + skill_castend_pos(ud->skilltimer,tick,src->id,0); + } + return 1; } /*======================================== * update a block's attack target *----------------------------------------*/ -int unit_set_target(struct unit_data *ud, int target_id) +int unit_set_target(struct unit_data* ud, int target_id) { - struct unit_data *ux; - struct block_list *target; + struct unit_data * ux; + struct block_list* target; - nullpo_ret(ud); + nullpo_ret(ud); - if (ud->target != target_id) { - if (ud->target && (target = map_id2bl(ud->target)) && (ux = unit_bl2ud(target)) && ux->target_count > 0) - ux->target_count --; - if (target_id && (target = map_id2bl(target_id)) && (ux = unit_bl2ud(target))) - ux->target_count ++; - } + if( ud->target != target_id ) { + if( ud->target && (target = map_id2bl(ud->target)) && (ux = unit_bl2ud(target)) && ux->target_count > 0 ) + ux->target_count --; + if( target_id && (target = map_id2bl(target_id)) && (ux = unit_bl2ud(target)) ) + ux->target_count ++; + } - ud->target = target_id; - return 0; + ud->target = target_id; + return 0; } int unit_stop_attack(struct block_list *bl) { - struct unit_data *ud = unit_bl2ud(bl); - nullpo_ret(bl); + struct unit_data *ud = unit_bl2ud(bl); + nullpo_ret(bl); - if (!ud || ud->attacktimer == INVALID_TIMER) - return 0; + if(!ud || ud->attacktimer == INVALID_TIMER) + return 0; - delete_timer(ud->attacktimer, unit_attack_timer); - ud->attacktimer = INVALID_TIMER; - unit_set_target(ud, 0); - return 0; + delete_timer( ud->attacktimer, unit_attack_timer ); + ud->attacktimer = INVALID_TIMER; + unit_set_target(ud, 0); + return 0; } //Means current target is unattackable. For now only unlocks mobs. int unit_unattackable(struct block_list *bl) { - struct unit_data *ud = unit_bl2ud(bl); - if (ud) { - ud->state.attack_continue = 0; - unit_set_target(ud, 0); - } - - if (bl->type == BL_MOB) - mob_unlocktarget((struct mob_data *)bl, gettick()) ; - else if (bl->type == BL_PET) - pet_unlocktarget((struct pet_data *)bl); - return 0; + struct unit_data *ud = unit_bl2ud(bl); + if (ud) { + ud->state.attack_continue = 0; + unit_set_target(ud, 0); + } + + if(bl->type == BL_MOB) + mob_unlocktarget((struct mob_data*)bl, gettick()) ; + else if(bl->type == BL_PET) + pet_unlocktarget((struct pet_data*)bl); + return 0; } /*========================================== @@ -1484,87 +1527,87 @@ int unit_unattackable(struct block_list *bl) *------------------------------------------*/ int unit_attack(struct block_list *src,int target_id,int continuous) { - struct block_list *target; - struct unit_data *ud; - - nullpo_ret(ud = unit_bl2ud(src)); - - target = map_id2bl(target_id); - if (target==NULL || status_isdead(target)) { - unit_unattackable(src); - return 1; - } - - if (src->type == BL_PC) { - TBL_PC *sd = (TBL_PC *)src; - if (target->type == BL_NPC) { // monster npcs [Valaris] - npc_click(sd,(TBL_NPC *)target); // submitted by leinsirk10 [Celest] - return 0; - } - if (pc_is90overweight(sd) || pc_isridingwug(sd)) { // overweight or mounted on warg - stop attacking - unit_stop_attack(src); - return 0; - } - } - if (battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0)) { - unit_unattackable(src); - return 1; - } - ud->state.attack_continue = continuous; - unit_set_target(ud, target_id); - - if (continuous) //If you're to attack continously, set to auto-case character - ud->chaserange = status_get_range(src); - - //Just change target/type. [Skotlex] - if (ud->attacktimer != INVALID_TIMER) - return 0; - - //Set Mob's ANGRY/BERSERK states. - if (src->type == BL_MOB) - ((TBL_MOB *)src)->state.skillstate = ((TBL_MOB *)src)->state.aggressive?MSS_ANGRY:MSS_BERSERK; - - if (DIFF_TICK(ud->attackabletime, gettick()) > 0) - //Do attack next time it is possible. [Skotlex] - ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,src->id,0); - else //Attack NOW. - unit_attack_timer(INVALID_TIMER, gettick(), src->id, 0); - - return 0; + struct block_list *target; + struct unit_data *ud; + + nullpo_ret(ud = unit_bl2ud(src)); + + target = map_id2bl(target_id); + if( target==NULL || status_isdead(target) ) { + unit_unattackable(src); + return 1; + } + + if( src->type == BL_PC ) { + TBL_PC* sd = (TBL_PC*)src; + if( target->type == BL_NPC ) { // monster npcs [Valaris] + npc_click(sd,(TBL_NPC*)target); // submitted by leinsirk10 [Celest] + return 0; + } + if( pc_is90overweight(sd) || pc_isridingwug(sd) ) { // overweight or mounted on warg - stop attacking + unit_stop_attack(src); + return 0; + } + } + if( battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) ) { + unit_unattackable(src); + return 1; + } + ud->state.attack_continue = continuous; + unit_set_target(ud, target_id); + + if (continuous) //If you're to attack continously, set to auto-case character + ud->chaserange = status_get_range(src); + + //Just change target/type. [Skotlex] + if(ud->attacktimer != INVALID_TIMER) + return 0; + + //Set Mob's ANGRY/BERSERK states. + if(src->type == BL_MOB) + ((TBL_MOB*)src)->state.skillstate = ((TBL_MOB*)src)->state.aggressive?MSS_ANGRY:MSS_BERSERK; + + if(DIFF_TICK(ud->attackabletime, gettick()) > 0) + //Do attack next time it is possible. [Skotlex] + ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,src->id,0); + else //Attack NOW. + unit_attack_timer(INVALID_TIMER, gettick(), src->id, 0); + + return 0; } //Cancels an ongoing combo, resets attackable time and restarts the //attack timer to resume attacking after amotion time. [Skotlex] int unit_cancel_combo(struct block_list *bl) { - struct unit_data *ud; + struct unit_data *ud; - if (!status_change_end(bl, SC_COMBO, INVALID_TIMER)) - return 0; //Combo wasn't active. + if (!status_change_end(bl, SC_COMBO, INVALID_TIMER)) + return 0; //Combo wasn't active. - ud = unit_bl2ud(bl); - nullpo_ret(ud); + ud = unit_bl2ud(bl); + nullpo_ret(ud); - ud->attackabletime = gettick() + status_get_amotion(bl); + ud->attackabletime = gettick() + status_get_amotion(bl); - if (ud->attacktimer == INVALID_TIMER) - return 1; //Nothing more to do. + if (ud->attacktimer == INVALID_TIMER) + return 1; //Nothing more to do. - delete_timer(ud->attacktimer, unit_attack_timer); - ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,bl->id,0); - return 1; + delete_timer(ud->attacktimer, unit_attack_timer); + ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,bl->id,0); + return 1; } /*========================================== * *------------------------------------------*/ bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy) { - nullpo_retr(false, bl); + nullpo_retr(false, bl); - if (bl->x == x && bl->y == y) //Same place - return true; + if (bl->x == x && bl->y == y) //Same place + return true; - return path_search(NULL,bl->m,bl->x,bl->y,x,y,easy,CELL_CHKNOREACH); + return path_search(NULL,bl->m,bl->x,bl->y,x,y,easy,CELL_CHKNOREACH); } /*========================================== @@ -1572,230 +1615,234 @@ bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy) *------------------------------------------*/ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range, int easy, short *x, short *y) { - int i; - short dx,dy; - nullpo_retr(false, bl); - nullpo_retr(false, tbl); - - if (bl->m != tbl->m) - return false; - - if (bl->x==tbl->x && bl->y==tbl->y) - return true; - - if (range>0 && !check_distance_bl(bl, tbl, range)) - return false; - - // It judges whether it can adjoin or not. - dx=tbl->x - bl->x; - dy=tbl->y - bl->y; - dx=(dx>0)?1:((dx<0)?-1:0); - dy=(dy>0)?1:((dy<0)?-1:0); - - if (map_getcell(tbl->m,tbl->x-dx,tbl->y-dy,CELL_CHKNOPASS)) { - //Look for a suitable cell to place in. - for (i=0; i<9 && map_getcell(tbl->m,tbl->x-dirx[i],tbl->y-diry[i],CELL_CHKNOPASS); i++); - if (i==9) return false; //No valid cells. - dx = dirx[i]; - dy = diry[i]; - } - - if (x) *x = tbl->x-dx; - if (y) *y = tbl->y-dy; - return path_search(NULL,bl->m,bl->x,bl->y,tbl->x-dx,tbl->y-dy,easy,CELL_CHKNOREACH); + int i; + short dx,dy; + nullpo_retr(false, bl); + nullpo_retr(false, tbl); + + if( bl->m != tbl->m) + return false; + + if( bl->x==tbl->x && bl->y==tbl->y ) + return true; + + if(range>0 && !check_distance_bl(bl, tbl, range)) + return false; + + // It judges whether it can adjoin or not. + dx=tbl->x - bl->x; + dy=tbl->y - bl->y; + dx=(dx>0)?1:((dx<0)?-1:0); + dy=(dy>0)?1:((dy<0)?-1:0); + + if (map_getcell(tbl->m,tbl->x-dx,tbl->y-dy,CELL_CHKNOPASS)) + { //Look for a suitable cell to place in. + for(i=0;i<9 && map_getcell(tbl->m,tbl->x-dirx[i],tbl->y-diry[i],CELL_CHKNOPASS);i++); + if (i==9) return false; //No valid cells. + dx = dirx[i]; + dy = diry[i]; + } + + if (x) *x = tbl->x-dx; + if (y) *y = tbl->y-dy; + return path_search(NULL,bl->m,bl->x,bl->y,tbl->x-dx,tbl->y-dy,easy,CELL_CHKNOREACH); } /*========================================== * Calculates position of Pet/Mercenary/Homunculus/Elemental *------------------------------------------*/ -int unit_calc_pos(struct block_list *bl, int tx, int ty, int dir) +int unit_calc_pos(struct block_list *bl, int tx, int ty, int dir) { - int dx, dy, x, y, i, k; - struct unit_data *ud = unit_bl2ud(bl); - nullpo_ret(ud); - - if (dir < 0 || dir > 7) - return 1; - - ud->to_x = tx; - ud->to_y = ty; - - // 2 cells from Master Position - dx = -dirx[dir] * 2; - dy = -diry[dir] * 2; - x = tx + dx; - y = ty + dy; - - if (!unit_can_reach_pos(bl, x, y, 0)) { - if (dx > 0) x--; - else if (dx < 0) x++; - if (dy > 0) y--; - else if (dy < 0) y++; - if (!unit_can_reach_pos(bl, x, y, 0)) { - for (i = 0; i < 12; i++) { - k = rnd()%8; // Pick a Random Dir - dx = -dirx[k] * 2; - dy = -diry[k] * 2; - x = tx + dx; - y = ty + dy; - if (unit_can_reach_pos(bl, x, y, 0)) - break; - else { - if (dx > 0) x--; - else if (dx < 0) x++; - if (dy > 0) y--; - else if (dy < 0) y++; - if (unit_can_reach_pos(bl, x, y, 0)) - break; - } - } - if (i == 12) { - x = tx; - y = tx; // Exactly Master Position - if (!unit_can_reach_pos(bl, x, y, 0)) - return 1; - } - } - } - ud->to_x = x; - ud->to_y = y; - - return 0; + int dx, dy, x, y, i, k; + struct unit_data *ud = unit_bl2ud(bl); + nullpo_ret(ud); + + if( dir < 0 || dir > 7 ) + return 1; + + ud->to_x = tx; + ud->to_y = ty; + + // 2 cells from Master Position + dx = -dirx[dir] * 2; + dy = -diry[dir] * 2; + x = tx + dx; + y = ty + dy; + + if( !unit_can_reach_pos(bl, x, y, 0) ) + { + if( dx > 0 ) x--; else if( dx < 0 ) x++; + if( dy > 0 ) y--; else if( dy < 0 ) y++; + if( !unit_can_reach_pos(bl, x, y, 0) ) + { + for( i = 0; i < 12; i++ ) + { + k = rnd()%8; // Pick a Random Dir + dx = -dirx[k] * 2; + dy = -diry[k] * 2; + x = tx + dx; + y = ty + dy; + if( unit_can_reach_pos(bl, x, y, 0) ) + break; + else + { + if( dx > 0 ) x--; else if( dx < 0 ) x++; + if( dy > 0 ) y--; else if( dy < 0 ) y++; + if( unit_can_reach_pos(bl, x, y, 0) ) + break; + } + } + if( i == 12 ) + { + x = tx; y = tx; // Exactly Master Position + if( !unit_can_reach_pos(bl, x, y, 0) ) + return 1; + } + } + } + ud->to_x = x; + ud->to_y = y; + + return 0; } /*========================================== * Continuous Attack (function timer) *------------------------------------------*/ -static int unit_attack_timer_sub(struct block_list *src, int tid, unsigned int tick) +static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int tick) { - struct block_list *target; - struct unit_data *ud; - struct status_data *sstatus; - struct map_session_data *sd = NULL; - struct mob_data *md = NULL; - int range; - - if ((ud=unit_bl2ud(src))==NULL) - return 0; - if (ud->attacktimer != tid) { - ShowError("unit_attack_timer %d != %d\n",ud->attacktimer,tid); - return 0; - } - - sd = BL_CAST(BL_PC, src); - md = BL_CAST(BL_MOB, src); - ud->attacktimer = INVALID_TIMER; - target=map_id2bl(ud->target); - - if (src == NULL || src->prev == NULL || target==NULL || target->prev == NULL) - return 0; - - if (status_isdead(src) || status_isdead(target) || - battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) + struct block_list *target; + struct unit_data *ud; + struct status_data *sstatus; + struct map_session_data *sd = NULL; + struct mob_data *md = NULL; + int range; + + if( (ud=unit_bl2ud(src))==NULL ) + return 0; + if( ud->attacktimer != tid ) + { + ShowError("unit_attack_timer %d != %d\n",ud->attacktimer,tid); + return 0; + } + + sd = BL_CAST(BL_PC, src); + md = BL_CAST(BL_MOB, src); + ud->attacktimer = INVALID_TIMER; + target=map_id2bl(ud->target); + + if( src == NULL || src->prev == NULL || target==NULL || target->prev == NULL ) + return 0; + + if( status_isdead(src) || status_isdead(target) || + battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) #ifdef OFFICIAL_WALKPATH - || !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) + || !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) #endif - ) - return 0; // can't attack under these conditions - - if (src->m != target->m) { - if (src->type == BL_MOB && mob_warpchase((TBL_MOB *)src, target)) - return 1; // Follow up. - return 0; - } - - if (ud->skilltimer != INVALID_TIMER && !(sd && pc_checkskill(sd,SA_FREECAST) > 0)) - return 0; // can't attack while casting - - if (!battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick,tick) > 0 && !(sd && pc_checkskill(sd,SA_FREECAST) > 0)) { - // attacking when under cast delay has restrictions: - if (tid == INVALID_TIMER) { - //requested attack. - if (sd) clif_skill_fail(sd,1,USESKILL_FAIL_SKILLINTERVAL,0); - return 0; - } - //Otherwise, we are in a combo-attack, delay this until your canact time is over. [Skotlex] - if (ud->state.attack_continue) { - if (DIFF_TICK(ud->canact_tick, ud->attackabletime) > 0) - ud->attackabletime = ud->canact_tick; - ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,src->id,0); - } - return 1; - } - - sstatus = status_get_status_data(src); - range = sstatus->rhw.range + 1; - - if (unit_is_walking(target)) - range++; //Extra range when chasing - if (!check_distance_bl(src,target,range)) { //Chase if required. - if (sd) - clif_movetoattack(sd,target); - else if (ud->state.attack_continue) - unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2); - return 1; - } - if (!battle_check_range(src,target,range)) { - //Within range, but no direct line of attack - if (ud->state.attack_continue) { - if (ud->chaserange > 2) ud->chaserange-=2; - unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2); - } - return 1; - } - //Sync packet only for players. - //Non-players use the sync packet on the walk timer. [Skotlex] - if (tid == INVALID_TIMER && sd) clif_fixpos(src); - - if (DIFF_TICK(ud->attackabletime,tick) <= 0) { - if (battle_config.attack_direction_change && (src->type&battle_config.attack_direction_change)) { - ud->dir = map_calc_dir(src, target->x,target->y); - } - if (ud->walktimer != INVALID_TIMER) - unit_stop_walking(src,1); - if (md) { - if (mobskill_use(md,tick,-1)) - return 1; - if (sstatus->mode&MD_ASSIST && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME) { - // Link monsters nearby [Skotlex] - md->last_linktime = tick; - map_foreachinrange(mob_linksearch, src, md->db->range2, BL_MOB, md->class_, target, tick); - } - } - if (src->type == BL_PET && pet_attackskill((TBL_PET *)src, target->id)) - return 1; - - map_freeblock_lock(); - ud->attacktarget_lv = battle_weapon_attack(src,target,tick,0); - - if (sd && sd->status.pet_id > 0 && sd->pd && battle_config.pet_attack_support) - pet_target_check(sd,target,0); - map_freeblock_unlock(); - /** - * Applied when you're unable to attack (e.g. out of ammo) - * We should stop here otherwise timer keeps on and this happens endlessly - **/ - if (ud->attacktarget_lv == ATK_NONE) - return 1; - - ud->attackabletime = tick + sstatus->adelay; - // You can't move if you can't attack neither. - if (src->type&battle_config.attack_walk_delay) - unit_set_walkdelay(src, tick, sstatus->amotion, 1); - } - - if (ud->state.attack_continue) - ud->attacktimer = add_timer(ud->attackabletime,unit_attack_timer,src->id,0); - - return 1; + ) + return 0; // can't attack under these conditions + + if( src->m != target->m ) + { + if( src->type == BL_MOB && mob_warpchase((TBL_MOB*)src, target) ) + return 1; // Follow up. + return 0; + } + + if( ud->skilltimer != INVALID_TIMER && !(sd && pc_checkskill(sd,SA_FREECAST) > 0) ) + return 0; // can't attack while casting + + if( !battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick,tick) > 0 && !(sd && pc_checkskill(sd,SA_FREECAST) > 0) ) + { // attacking when under cast delay has restrictions: + if( tid == INVALID_TIMER ) + { //requested attack. + if(sd) clif_skill_fail(sd,1,USESKILL_FAIL_SKILLINTERVAL,0); + return 0; + } + //Otherwise, we are in a combo-attack, delay this until your canact time is over. [Skotlex] + if( ud->state.attack_continue ) + { + if( DIFF_TICK(ud->canact_tick, ud->attackabletime) > 0 ) + ud->attackabletime = ud->canact_tick; + ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,src->id,0); + } + return 1; + } + + sstatus = status_get_status_data(src); + range = sstatus->rhw.range + 1; + + if( unit_is_walking(target) ) + range++; //Extra range when chasing + if( !check_distance_bl(src,target,range) ) { //Chase if required. + if(sd) + clif_movetoattack(sd,target); + else if(ud->state.attack_continue) + unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2); + return 1; + } + if( !battle_check_range(src,target,range) ) { + //Within range, but no direct line of attack + if( ud->state.attack_continue ) { + if(ud->chaserange > 2) ud->chaserange-=2; + unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2); + } + return 1; + } + //Sync packet only for players. + //Non-players use the sync packet on the walk timer. [Skotlex] + if (tid == INVALID_TIMER && sd) clif_fixpos(src); + + if( DIFF_TICK(ud->attackabletime,tick) <= 0 ) + { + if (battle_config.attack_direction_change && (src->type&battle_config.attack_direction_change)) { + ud->dir = map_calc_dir(src, target->x,target->y ); + } + if(ud->walktimer != INVALID_TIMER) + unit_stop_walking(src,1); + if(md) { + if (mobskill_use(md,tick,-1)) + return 1; + if (sstatus->mode&MD_ASSIST && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME) + { // Link monsters nearby [Skotlex] + md->last_linktime = tick; + map_foreachinrange(mob_linksearch, src, md->db->range2, BL_MOB, md->class_, target, tick); + } + } + if(src->type == BL_PET && pet_attackskill((TBL_PET*)src, target->id)) + return 1; + + map_freeblock_lock(); + ud->attacktarget_lv = battle_weapon_attack(src,target,tick,0); + + if(sd && sd->status.pet_id > 0 && sd->pd && battle_config.pet_attack_support) + pet_target_check(sd,target,0); + map_freeblock_unlock(); + /** + * Applied when you're unable to attack (e.g. out of ammo) + * We should stop here otherwise timer keeps on and this happens endlessly + **/ + if( ud->attacktarget_lv == ATK_NONE ) + return 1; + + ud->attackabletime = tick + sstatus->adelay; +// You can't move if you can't attack neither. + if (src->type&battle_config.attack_walk_delay) + unit_set_walkdelay(src, tick, sstatus->amotion, 1); + } + + if(ud->state.attack_continue) + ud->attacktimer = add_timer(ud->attackabletime,unit_attack_timer,src->id,0); + + return 1; } static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct block_list *bl; - bl = map_id2bl(id); - if (bl && unit_attack_timer_sub(bl, tid, tick) == 0) - unit_unattackable(bl); - return 0; + struct block_list *bl; + bl = map_id2bl(id); + if(bl && unit_attack_timer_sub(bl, tid, tick) == 0) + unit_unattackable(bl); + return 0; } /*========================================== @@ -1805,85 +1852,87 @@ static int unit_attack_timer(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ int unit_skillcastcancel(struct block_list *bl,int type) { - struct map_session_data *sd = NULL; - struct unit_data *ud = unit_bl2ud(bl); - unsigned int tick=gettick(); - int ret=0, skill; - - nullpo_ret(bl); - if (!ud || ud->skilltimer == INVALID_TIMER) - return 0; //Nothing to cancel. - - sd = BL_CAST(BL_PC, bl); - - if (type&2) { - //See if it can be cancelled. - if (!ud->state.skillcastcancel) - return 0; - - if (sd && (sd->special_state.no_castcancel2 || - ((sd->sc.data[SC_UNLIMITEDHUMMINGVOICE] || sd->special_state.no_castcancel) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89] - return 0; - } - - ud->canact_tick = tick; - - if (type&1 && sd) - skill = sd->skillid_old; - else - skill = ud->skillid; - - if (skill_get_inf(skill) & INF_GROUND_SKILL) - ret=delete_timer(ud->skilltimer, skill_castend_pos); - else - ret=delete_timer(ud->skilltimer, skill_castend_id); - if (ret<0) - ShowError("delete timer error : skillid : %d\n",ret); - - ud->skilltimer = INVALID_TIMER; - - if (sd && pc_checkskill(sd,SA_FREECAST) > 0) - status_calc_bl(&sd->bl, SCB_SPEED); - - if (sd) { - switch (skill) { - case CG_ARROWVULCAN: - sd->canequip_tick = tick; - break; - } - } - - if (bl->type==BL_MOB)((TBL_MOB *)bl)->skillidx = -1; - - clif_skillcastcancel(bl); - return 1; + struct map_session_data *sd = NULL; + struct unit_data *ud = unit_bl2ud( bl); + unsigned int tick=gettick(); + int ret=0, skill; + + nullpo_ret(bl); + if (!ud || ud->skilltimer == INVALID_TIMER) + return 0; //Nothing to cancel. + + sd = BL_CAST(BL_PC, bl); + + if (type&2) { + //See if it can be cancelled. + if (!ud->state.skillcastcancel) + return 0; + + if (sd && (sd->special_state.no_castcancel2 || + ((sd->sc.data[SC_UNLIMITEDHUMMINGVOICE] || sd->special_state.no_castcancel) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89] + return 0; + } + + ud->canact_tick = tick; + + if(type&1 && sd) + skill = sd->skillid_old; + else + skill = ud->skillid; + + if (skill_get_inf(skill) & INF_GROUND_SKILL) + ret=delete_timer( ud->skilltimer, skill_castend_pos ); + else + ret=delete_timer( ud->skilltimer, skill_castend_id ); + if(ret<0) + ShowError("delete timer error : skillid : %d\n",ret); + + ud->skilltimer = INVALID_TIMER; + + if( sd && pc_checkskill(sd,SA_FREECAST) > 0 ) + status_calc_bl(&sd->bl, SCB_SPEED); + + if( sd ) + { + switch( skill ) + { + case CG_ARROWVULCAN: + sd->canequip_tick = tick; + break; + } + } + + if(bl->type==BL_MOB) ((TBL_MOB*)bl)->skillidx = -1; + + clif_skillcastcancel(bl); + return 1; } // unit_data initialization process void unit_dataset(struct block_list *bl) { - struct unit_data *ud; - nullpo_retv(ud = unit_bl2ud(bl)); - - memset(ud, 0, sizeof(struct unit_data)); - ud->bl = bl; - ud->walktimer = INVALID_TIMER; - ud->skilltimer = INVALID_TIMER; - ud->attacktimer = INVALID_TIMER; - ud->attackabletime = - ud->canact_tick = - ud->canmove_tick = gettick(); + struct unit_data *ud; + nullpo_retv(ud = unit_bl2ud(bl)); + + memset( ud, 0, sizeof( struct unit_data) ); + ud->bl = bl; + ud->walktimer = INVALID_TIMER; + ud->skilltimer = INVALID_TIMER; + ud->attacktimer = INVALID_TIMER; + ud->attackabletime = + ud->canact_tick = + ud->canmove_tick = gettick(); } /*========================================== * Counts the number of units attacking 'bl' *------------------------------------------*/ -int unit_counttargeted(struct block_list *bl) +int unit_counttargeted(struct block_list* bl) { - struct unit_data *ud; - if (bl && (ud = unit_bl2ud(bl))) - return ud->target_count; - return 0; + struct unit_data* ud; + if( bl && (ud = unit_bl2ud(bl)) ) + return ud->target_count; + return 0; } /*========================================== @@ -1891,12 +1940,12 @@ int unit_counttargeted(struct block_list *bl) *------------------------------------------*/ int unit_fixdamage(struct block_list *src,struct block_list *target,unsigned int tick,int sdelay,int ddelay,int damage,int div,int type,int damage2) { - nullpo_ret(target); + nullpo_ret(target); - if (damage+damage2 <= 0) - return 0; + if(damage+damage2 <= 0) + return 0; - return status_fix_damage(src,target,damage+damage2,clif_damage(target,target,tick,sdelay,ddelay,damage,div,type,damage2)); + return status_fix_damage(src,target,damage+damage2,clif_damage(target,target,tick,sdelay,ddelay,damage,div,type,damage2)); } /*========================================== @@ -1904,19 +1953,19 @@ int unit_fixdamage(struct block_list *src,struct block_list *target,unsigned int *------------------------------------------*/ int unit_changeviewsize(struct block_list *bl,short size) { - nullpo_ret(bl); - - size=(size<0)?-1:(size>0)?1:0; - - if (bl->type == BL_PC) { - ((TBL_PC *)bl)->state.size=size; - } else if (bl->type == BL_MOB) { - ((TBL_MOB *)bl)->special_state.size=size; - } else - return 0; - if (size!=0) - clif_specialeffect(bl,421+size, AREA); - return 0; + nullpo_ret(bl); + + size=(size<0)?-1:(size>0)?1:0; + + if(bl->type == BL_PC) { + ((TBL_PC*)bl)->state.size=size; + } else if(bl->type == BL_MOB) { + ((TBL_MOB*)bl)->special_state.size=size; + } else + return 0; + if(size!=0) + clif_specialeffect(bl,421+size, AREA); + return 0; } /*========================================== @@ -1926,249 +1975,256 @@ int unit_changeviewsize(struct block_list *bl,short size) * Otherwise it is assumed bl is being warped. * On-Kill specific stuff is not performed here, look at status_damage for that. *------------------------------------------*/ -int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char *file, int line, const char *func) +int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func) { - struct unit_data *ud = unit_bl2ud(bl); - struct status_change *sc = status_get_sc(bl); - nullpo_ret(ud); - - if (bl->prev == NULL) - return 0; //Already removed? - - map_freeblock_lock(); - - unit_set_target(ud, 0); - - if (ud->walktimer != INVALID_TIMER) - unit_stop_walking(bl,0); - if (ud->attacktimer != INVALID_TIMER) - unit_stop_attack(bl); - if (ud->skilltimer != INVALID_TIMER) - unit_skillcastcancel(bl,0); - - // Do not reset can-act delay. [Skotlex] - ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = gettick(); - if (sc && sc->count) { //map-change/warp dispells. - status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); - status_change_end(bl, SC_BASILICA, INVALID_TIMER); - status_change_end(bl, SC_ANKLE, INVALID_TIMER); - status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER); - status_change_end(bl, SC_BLADESTOP_WAIT, INVALID_TIMER); - status_change_end(bl, SC_RUN, INVALID_TIMER); - status_change_end(bl, SC_DANCING, INVALID_TIMER); - status_change_end(bl, SC_WARM, INVALID_TIMER); - status_change_end(bl, SC_DEVOTION, INVALID_TIMER); - status_change_end(bl, SC_MARIONETTE, INVALID_TIMER); - status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER); - status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); - status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); - status_change_end(bl, SC_HIDING, INVALID_TIMER); - // Ensure the bl is a PC; if so, we'll handle the removal of cloaking and cloaking exceed later - if (bl->type != BL_PC) { - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - } - status_change_end(bl, SC_CHASEWALK, INVALID_TIMER); - if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) - status_change_end(bl, SC_GOSPEL, INVALID_TIMER); - status_change_end(bl, SC_CHANGE, INVALID_TIMER); - status_change_end(bl, SC_STOP, INVALID_TIMER); - status_change_end(bl, SC_WUGDASH, INVALID_TIMER); - status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - status_change_end(bl, SC__MANHOLE, INVALID_TIMER); - status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER); - status_change_end(bl, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER); //callme before warp - } - - if (bl->type&(BL_CHAR|BL_PET)) { - skill_unit_move(bl,gettick(),4); - skill_cleartimerskill(bl); - } - - switch (bl->type) { - case BL_PC: { - struct map_session_data *sd = (struct map_session_data *)bl; - - //Leave/reject all invitations. - if (sd->chatID) - chat_leavechat(sd,0); - if (sd->trade_partner) - trade_tradecancel(sd); - buyingstore_close(sd); - searchstore_close(sd); - if (sd->state.storage_flag == 1) - storage_storage_quit(sd,0); - else if (sd->state.storage_flag == 2) - storage_guild_storage_quit(sd,0); - sd->state.storage_flag = 0; //Force close it when being warped. - if (sd->party_invite>0) - party_reply_invite(sd,sd->party_invite,0); - if (sd->guild_invite>0) - guild_reply_invite(sd,sd->guild_invite,0); - if (sd->guild_alliance>0) - guild_reply_reqalliance(sd,sd->guild_alliance_account,0); - if (sd->menuskill_id) - sd->menuskill_id = sd->menuskill_val = 0; - if (sd->touching_id && !sd->state.warping) // Only if the player isn't warping and there is a touching_id. - npc_touchnext_areanpc(sd,true); - - // Check if warping and not changing the map. - if (sd->state.warping && !sd->state.changemap) { - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - } - - sd->npc_shopid = 0; - sd->adopt_invite = 0; - - if (sd->pvp_timer != INVALID_TIMER) { - delete_timer(sd->pvp_timer,pc_calc_pvprank_timer); - sd->pvp_timer = INVALID_TIMER; - sd->pvp_rank = 0; - } - if (sd->duel_group > 0) - duel_leave(sd->duel_group, sd); - - if (pc_issit(sd)) { - pc_setstand(sd); - skill_sit(sd,0); - } - party_send_dot_remove(sd);//minimap dot fix [Kevin] - guild_send_dot_remove(sd); - bg_send_dot_remove(sd); - - if (map[bl->m].users <= 0 || sd->state.debug_remove_map) { - // this is only place where map users is decreased, if the mobs were removed too soon then this function was executed too many times [FlavioJS] - if (sd->debug_file == NULL || !(sd->state.debug_remove_map)) { - sd->debug_file = ""; - sd->debug_line = 0; - sd->debug_func = ""; - } - ShowDebug("unit_remove_map: unexpected state when removing player AID/CID:%d/%d" - " (active=%d connect_new=%d rewarp=%d changemap=%d debug_remove_map=%d)" - " from map=%s (users=%d)." - " Previous call from %s:%d(%s), current call from %s:%d(%s)." - " Please report this!!!\n", - sd->status.account_id, sd->status.char_id, - sd->state.active, sd->state.connect_new, sd->state.rewarp, sd->state.changemap, sd->state.debug_remove_map, - map[bl->m].name, map[bl->m].users, - sd->debug_file, sd->debug_line, sd->debug_func, file, line, func); - } else if (--map[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex] - map_removemobs(bl->m); - if (!(sd->sc.option&OPTION_INVISIBLE)) { - // decrement the number of active pvp players on the map - --map[bl->m].users_pvp; - } - if (map[bl->m].instance_id) { - instance[map[bl->m].instance_id].users--; - instance_check_idle(map[bl->m].instance_id); - } - sd->state.debug_remove_map = 1; // temporary state to track double remove_map's [FlavioJS] - sd->debug_file = file; - sd->debug_line = line; - sd->debug_func = func; - - break; - } - case BL_MOB: { - struct mob_data *md = (struct mob_data *)bl; - // Drop previous target mob_slave_keep_target: no. - if (!battle_config.mob_slave_keep_target) - md->target_id=0; - - md->attacked_id=0; - md->state.skillstate= MSS_IDLE; - - break; - } - case BL_PET: { - struct pet_data *pd = (struct pet_data *)bl; - if (pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active)) { - //If logging out, this is deleted on unit_free - clif_clearunit_area(bl,clrtype); - map_delblock(bl); - unit_free(bl,CLR_OUTSIGHT); - map_freeblock_unlock(); - return 0; - } - - break; - } - case BL_HOM: { - struct homun_data *hd = (struct homun_data *)bl; - ud->canact_tick = ud->canmove_tick; //It appears HOM do reset the can-act tick. - if (!hd->homunculus.intimacy && !(hd->master && !hd->master->state.active)) { - //If logging out, this is deleted on unit_free - clif_emotion(bl, E_SOB); - clif_clearunit_area(bl,clrtype); - map_delblock(bl); - unit_free(bl,CLR_OUTSIGHT); - map_freeblock_unlock(); - return 0; - } - break; - } - case BL_MER: { - struct mercenary_data *md = (struct mercenary_data *)bl; - ud->canact_tick = ud->canmove_tick; - if (mercenary_get_lifetime(md) <= 0 && !(md->master && !md->master->state.active)) { - clif_clearunit_area(bl,clrtype); - map_delblock(bl); - unit_free(bl,CLR_OUTSIGHT); - map_freeblock_unlock(); - return 0; - } - break; - } - case BL_ELEM: { - struct elemental_data *ed = (struct elemental_data *)bl; - ud->canact_tick = ud->canmove_tick; - if (elemental_get_lifetime(ed) <= 0 && !(ed->master && !ed->master->state.active)) { - clif_clearunit_area(bl,clrtype); - map_delblock(bl); - unit_free(bl,0); - map_freeblock_unlock(); - return 0; - } - break; - } - default: - break;// do nothing - } - /** - * BL_MOB is handled by mob_dead unless the monster is not dead. - **/ - if (bl->type != BL_MOB || !status_isdead(bl)) - clif_clearunit_area(bl,clrtype); - map_delblock(bl); - map_freeblock_unlock(); - return 1; + struct unit_data *ud = unit_bl2ud(bl); + struct status_change *sc = status_get_sc(bl); + nullpo_ret(ud); + + if(bl->prev == NULL) + return 0; //Already removed? + + map_freeblock_lock(); + + unit_set_target(ud, 0); + + if (ud->walktimer != INVALID_TIMER) + unit_stop_walking(bl,0); + if (ud->attacktimer != INVALID_TIMER) + unit_stop_attack(bl); + if (ud->skilltimer != INVALID_TIMER) + unit_skillcastcancel(bl,0); + +// Do not reset can-act delay. [Skotlex] + ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = gettick(); + if(sc && sc->count ) { //map-change/warp dispells. + status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); + status_change_end(bl, SC_BASILICA, INVALID_TIMER); + status_change_end(bl, SC_ANKLE, INVALID_TIMER); + status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER); + status_change_end(bl, SC_BLADESTOP_WAIT, INVALID_TIMER); + status_change_end(bl, SC_RUN, INVALID_TIMER); + status_change_end(bl, SC_DANCING, INVALID_TIMER); + status_change_end(bl, SC_WARM, INVALID_TIMER); + status_change_end(bl, SC_DEVOTION, INVALID_TIMER); + status_change_end(bl, SC_MARIONETTE, INVALID_TIMER); + status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER); + status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); + status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); + status_change_end(bl, SC_HIDING, INVALID_TIMER); + // Ensure the bl is a PC; if so, we'll handle the removal of cloaking and cloaking exceed later + if ( bl->type != BL_PC ) + { + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + } + status_change_end(bl, SC_CHASEWALK, INVALID_TIMER); + if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) + status_change_end(bl, SC_GOSPEL, INVALID_TIMER); + status_change_end(bl, SC_CHANGE, INVALID_TIMER); + status_change_end(bl, SC_STOP, INVALID_TIMER); + status_change_end(bl, SC_WUGDASH, INVALID_TIMER); + status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + status_change_end(bl, SC__MANHOLE, INVALID_TIMER); + status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER); + status_change_end(bl, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER); //callme before warp + } + + if (bl->type&(BL_CHAR|BL_PET)) { + skill_unit_move(bl,gettick(),4); + skill_cleartimerskill(bl); + } + + switch( bl->type ) { + case BL_PC: { + struct map_session_data *sd = (struct map_session_data*)bl; + + //Leave/reject all invitations. + if(sd->chatID) + chat_leavechat(sd,0); + if(sd->trade_partner) + trade_tradecancel(sd); + buyingstore_close(sd); + searchstore_close(sd); + if(sd->state.storage_flag == 1) + storage_storage_quit(sd,0); + else if (sd->state.storage_flag == 2) + storage_guild_storage_quit(sd,0); + sd->state.storage_flag = 0; //Force close it when being warped. + if(sd->party_invite>0) + party_reply_invite(sd,sd->party_invite,0); + if(sd->guild_invite>0) + guild_reply_invite(sd,sd->guild_invite,0); + if(sd->guild_alliance>0) + guild_reply_reqalliance(sd,sd->guild_alliance_account,0); + if(sd->menuskill_id) + sd->menuskill_id = sd->menuskill_val = 0; + if( sd->touching_id && !sd->state.warping ) // Only if the player isn't warping and there is a touching_id. + npc_touchnext_areanpc(sd,true); + + // Check if warping and not changing the map. + if ( sd->state.warping && !sd->state.changemap ) + { + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + } + + sd->npc_shopid = 0; + sd->adopt_invite = 0; + + if(sd->pvp_timer != INVALID_TIMER) { + delete_timer(sd->pvp_timer,pc_calc_pvprank_timer); + sd->pvp_timer = INVALID_TIMER; + sd->pvp_rank = 0; + } + if(sd->duel_group > 0) + duel_leave(sd->duel_group, sd); + + if(pc_issit(sd)) { + pc_setstand(sd); + skill_sit(sd,0); + } + party_send_dot_remove(sd);//minimap dot fix [Kevin] + guild_send_dot_remove(sd); + bg_send_dot_remove(sd); + + if( map[bl->m].users <= 0 || sd->state.debug_remove_map ) + {// this is only place where map users is decreased, if the mobs were removed too soon then this function was executed too many times [FlavioJS] + if( sd->debug_file == NULL || !(sd->state.debug_remove_map) ) + { + sd->debug_file = ""; + sd->debug_line = 0; + sd->debug_func = ""; + } + ShowDebug("unit_remove_map: unexpected state when removing player AID/CID:%d/%d" + " (active=%d connect_new=%d rewarp=%d changemap=%d debug_remove_map=%d)" + " from map=%s (users=%d)." + " Previous call from %s:%d(%s), current call from %s:%d(%s)." + " Please report this!!!\n", + sd->status.account_id, sd->status.char_id, + sd->state.active, sd->state.connect_new, sd->state.rewarp, sd->state.changemap, sd->state.debug_remove_map, + map[bl->m].name, map[bl->m].users, + sd->debug_file, sd->debug_line, sd->debug_func, file, line, func); + } + else + if (--map[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex] + map_removemobs(bl->m); + if( !(sd->sc.option&OPTION_INVISIBLE) ) + {// decrement the number of active pvp players on the map + --map[bl->m].users_pvp; + } + if( map[bl->m].instance_id ) + { + instance[map[bl->m].instance_id].users--; + instance_check_idle(map[bl->m].instance_id); + } + sd->state.debug_remove_map = 1; // temporary state to track double remove_map's [FlavioJS] + sd->debug_file = file; + sd->debug_line = line; + sd->debug_func = func; + + break; + } + case BL_MOB: { + struct mob_data *md = (struct mob_data*)bl; + // Drop previous target mob_slave_keep_target: no. + if (!battle_config.mob_slave_keep_target) + md->target_id=0; + + md->attacked_id=0; + md->state.skillstate= MSS_IDLE; + + break; + } + case BL_PET: { + struct pet_data *pd = (struct pet_data*)bl; + if( pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active) ) + { //If logging out, this is deleted on unit_free + clif_clearunit_area(bl,clrtype); + map_delblock(bl); + unit_free(bl,CLR_OUTSIGHT); + map_freeblock_unlock(); + return 0; + } + + break; + } + case BL_HOM: { + struct homun_data *hd = (struct homun_data *)bl; + ud->canact_tick = ud->canmove_tick; //It appears HOM do reset the can-act tick. + if( !hd->homunculus.intimacy && !(hd->master && !hd->master->state.active) ) + { //If logging out, this is deleted on unit_free + clif_emotion(bl, E_SOB); + clif_clearunit_area(bl,clrtype); + map_delblock(bl); + unit_free(bl,CLR_OUTSIGHT); + map_freeblock_unlock(); + return 0; + } + break; + } + case BL_MER: { + struct mercenary_data *md = (struct mercenary_data *)bl; + ud->canact_tick = ud->canmove_tick; + if( mercenary_get_lifetime(md) <= 0 && !(md->master && !md->master->state.active) ) + { + clif_clearunit_area(bl,clrtype); + map_delblock(bl); + unit_free(bl,CLR_OUTSIGHT); + map_freeblock_unlock(); + return 0; + } + break; + } + case BL_ELEM: { + struct elemental_data *ed = (struct elemental_data *)bl; + ud->canact_tick = ud->canmove_tick; + if( elemental_get_lifetime(ed) <= 0 && !(ed->master && !ed->master->state.active) ) + { + clif_clearunit_area(bl,clrtype); + map_delblock(bl); + unit_free(bl,0); + map_freeblock_unlock(); + return 0; + } + break; + } + default: break;// do nothing + } + /** + * BL_MOB is handled by mob_dead unless the monster is not dead. + **/ + if( bl->type != BL_MOB || !status_isdead(bl) ) + clif_clearunit_area(bl,clrtype); + map_delblock(bl); + map_freeblock_unlock(); + return 1; } void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype) { - unit_remove_map(&sd->bl,clrtype); - - if (clrtype == CLR_TELEPORT) clrtype = CLR_OUTSIGHT; //CLR_TELEPORT is the warp from logging out, but pets/homunc need to just 'vanish' instead of showing the warping out animation. - - if (sd->pd) - unit_remove_map(&sd->pd->bl, clrtype); - if (merc_is_hom_active(sd->hd)) - unit_remove_map(&sd->hd->bl, clrtype); - if (sd->md) - unit_remove_map(&sd->md->bl, clrtype); - if (sd->ed) - unit_remove_map(&sd->ed->bl, clrtype); + unit_remove_map(&sd->bl,clrtype); + + if (clrtype == CLR_TELEPORT) clrtype = CLR_OUTSIGHT; //CLR_TELEPORT is the warp from logging out, but pets/homunc need to just 'vanish' instead of showing the warping out animation. + + if(sd->pd) + unit_remove_map(&sd->pd->bl, clrtype); + if(merc_is_hom_active(sd->hd)) + unit_remove_map(&sd->hd->bl, clrtype); + if(sd->md) + unit_remove_map(&sd->md->bl, clrtype); + if(sd->ed) + unit_remove_map(&sd->ed->bl, clrtype); } void unit_free_pc(struct map_session_data *sd) { - if (sd->pd) unit_free(&sd->pd->bl,CLR_OUTSIGHT); - if (sd->hd) unit_free(&sd->hd->bl,CLR_OUTSIGHT); - if (sd->md) unit_free(&sd->md->bl,CLR_OUTSIGHT); - if (sd->ed) unit_free(&sd->ed->bl,CLR_OUTSIGHT); - unit_free(&sd->bl,CLR_TELEPORT); + if (sd->pd) unit_free(&sd->pd->bl,CLR_OUTSIGHT); + if (sd->hd) unit_free(&sd->hd->bl,CLR_OUTSIGHT); + if (sd->md) unit_free(&sd->md->bl,CLR_OUTSIGHT); + if (sd->ed) unit_free(&sd->ed->bl,CLR_OUTSIGHT); + unit_free(&sd->bl,CLR_TELEPORT); } /*========================================== @@ -2177,233 +2233,255 @@ void unit_free_pc(struct map_session_data *sd) *------------------------------------------*/ int unit_free(struct block_list *bl, clr_type clrtype) { - struct unit_data *ud = unit_bl2ud(bl); - nullpo_ret(ud); - - map_freeblock_lock(); - if (bl->prev) //Players are supposed to logout with a "warp" effect. - unit_remove_map(bl, clrtype); - - switch (bl->type) { - case BL_PC: { - struct map_session_data *sd = (struct map_session_data *)bl; - int i; - - if (status_isdead(bl)) - pc_setrestartvalue(sd,2); - - pc_delinvincibletimer(sd); - pc_delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),false); - pc_delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus2),false); - pc_delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),false); - - if (sd->followtimer != INVALID_TIMER) - pc_stop_following(sd); - - if (sd->duel_invite > 0) - duel_reject(sd->duel_invite, sd); - - // Notify friends that this char logged out. [Skotlex] - map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0); - party_send_logout(sd); - guild_send_memberinfoshort(sd,0); - pc_cleareventtimer(sd); - pc_inventory_rental_clear(sd); - pc_delspiritball(sd,sd->spiritball,1); - for (i = 1; i < 5; i++) - pc_del_talisman(sd, sd->talisman[i], i); - - if (sd->reg) { //Double logout already freed pointer fix... [Skotlex] - aFree(sd->reg); - sd->reg = NULL; - sd->reg_num = 0; - } - if (sd->regstr) { - int i; - for (i = 0; i < sd->regstr_num; ++i) - if (sd->regstr[i].data) - aFree(sd->regstr[i].data); - aFree(sd->regstr); - sd->regstr = NULL; - sd->regstr_num = 0; - } - if (sd->st && sd->st->state != RUN) { // free attached scripts that are waiting - script_free_state(sd->st); - sd->st = NULL; - sd->npc_id = 0; - } - if (sd->combos.count) { - aFree(sd->combos.bonus); - aFree(sd->combos.id); - sd->combos.count = 0; - } - break; - } - case BL_PET: { - struct pet_data *pd = (struct pet_data *)bl; - struct map_session_data *sd = pd->msd; - pet_hungry_timer_delete(pd); - if (pd->a_skill) { - aFree(pd->a_skill); - pd->a_skill = NULL; - } - if (pd->s_skill) { - if (pd->s_skill->timer != INVALID_TIMER) { - if (pd->s_skill->id) - delete_timer(pd->s_skill->timer, pet_skill_support_timer); - else - delete_timer(pd->s_skill->timer, pet_heal_timer); - } - aFree(pd->s_skill); - pd->s_skill = NULL; - } - if (pd->recovery) { - if (pd->recovery->timer != INVALID_TIMER) - delete_timer(pd->recovery->timer, pet_recovery_timer); - aFree(pd->recovery); - pd->recovery = NULL; - } - if (pd->bonus) { - if (pd->bonus->timer != INVALID_TIMER) - delete_timer(pd->bonus->timer, pet_skill_bonus_timer); - aFree(pd->bonus); - pd->bonus = NULL; - } - if (pd->loot) { - pet_lootitem_drop(pd,sd); - if (pd->loot->item) - aFree(pd->loot->item); - aFree(pd->loot); - pd->loot = NULL; - } - if (pd->pet.intimate > 0) - intif_save_petdata(pd->pet.account_id,&pd->pet); - else { - //Remove pet. - intif_delete_petdata(pd->pet.pet_id); - if (sd) sd->status.pet_id = 0; - } - if (sd) - sd->pd = NULL; - break; - } - case BL_MOB: { - struct mob_data *md = (struct mob_data *)bl; - if (md->spawn_timer != INVALID_TIMER) { - delete_timer(md->spawn_timer,mob_delayspawn); - md->spawn_timer = INVALID_TIMER; - } - if (md->deletetimer != INVALID_TIMER) { - delete_timer(md->deletetimer,mob_timer_delete); - md->deletetimer = INVALID_TIMER; - } - if (md->lootitem) { - aFree(md->lootitem); - md->lootitem=NULL; - } - if (md->guardian_data) { - struct guild_castle *gc = md->guardian_data->castle; - if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS) { - gc->guardian[md->guardian_data->number].id = 0; - } else { - int i; - ARR_FIND(0, gc->temp_guardians_max, i, gc->temp_guardians[i] == md->bl.id); - if (i < gc->temp_guardians_max) - gc->temp_guardians[i] = 0; - } - aFree(md->guardian_data); - md->guardian_data = NULL; - } - if (md->spawn) { - md->spawn->active--; - if (!md->spawn->state.dynamic) { - // permanently remove the mob - if (--md->spawn->num == 0) { - // Last freed mob is responsible for deallocating the group's spawn data. - aFree(md->spawn); - md->spawn = NULL; - } - } - } - if (md->base_status) { - aFree(md->base_status); - md->base_status = NULL; - } - if (mob_is_clone(md->class_)) - mob_clone_delete(md); - if (md->tomb_nid) - mvptomb_destroy(md); - break; - } - case BL_HOM: { - struct homun_data *hd = (TBL_HOM *)bl; - struct map_session_data *sd = hd->master; - merc_hom_hungry_timer_delete(hd); - if (hd->homunculus.intimacy > 0) - merc_save(hd); - else { - intif_homunculus_requestdelete(hd->homunculus.hom_id); - if (sd) - sd->status.hom_id = 0; - } - if (sd) - sd->hd = NULL; - break; - } - case BL_MER: { - struct mercenary_data *md = (TBL_MER *)bl; - struct map_session_data *sd = md->master; - if (mercenary_get_lifetime(md) > 0) - mercenary_save(md); - else { - intif_mercenary_delete(md->mercenary.mercenary_id); - if (sd) - sd->status.mer_id = 0; - } - if (sd) - sd->md = NULL; - - merc_contract_stop(md); - break; - } - case BL_ELEM: { - struct elemental_data *ed = (TBL_ELEM *)bl; - struct map_session_data *sd = ed->master; - if (elemental_get_lifetime(ed) > 0) - elemental_save(ed); - else { - intif_elemental_delete(ed->elemental.elemental_id); - if (sd) - sd->status.ele_id = 0; - } - if (sd) - sd->ed = NULL; - - elemental_summon_stop(ed); - break; - } - } - - skill_clear_unitgroup(bl); - status_change_clear(bl,1); - map_deliddb(bl); - if (bl->type != BL_PC) //Players are handled by map_quit - map_freeblock(bl); - map_freeblock_unlock(); - return 0; + struct unit_data *ud = unit_bl2ud( bl ); + nullpo_ret(ud); + + map_freeblock_lock(); + if( bl->prev ) //Players are supposed to logout with a "warp" effect. + unit_remove_map(bl, clrtype); + + switch( bl->type ) + { + case BL_PC: + { + struct map_session_data *sd = (struct map_session_data*)bl; + int i; + + if( status_isdead(bl) ) + pc_setrestartvalue(sd,2); + + pc_delinvincibletimer(sd); + pc_delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),false); + pc_delautobonus(sd,sd->autobonus2,ARRAYLENGTH(sd->autobonus2),false); + pc_delautobonus(sd,sd->autobonus3,ARRAYLENGTH(sd->autobonus3),false); + + if( sd->followtimer != INVALID_TIMER ) + pc_stop_following(sd); + + if( sd->duel_invite > 0 ) + duel_reject(sd->duel_invite, sd); + + // Notify friends that this char logged out. [Skotlex] + map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0); + party_send_logout(sd); + guild_send_memberinfoshort(sd,0); + pc_cleareventtimer(sd); + pc_inventory_rental_clear(sd); + pc_delspiritball(sd,sd->spiritball,1); + for(i = 1; i < 5; i++) + pc_del_talisman(sd, sd->talisman[i], i); + + if( sd->reg ) { //Double logout already freed pointer fix... [Skotlex] + aFree(sd->reg); + sd->reg = NULL; + sd->reg_num = 0; + } + if( sd->regstr ) { + int i; + for( i = 0; i < sd->regstr_num; ++i ) + if( sd->regstr[i].data ) + aFree(sd->regstr[i].data); + aFree(sd->regstr); + sd->regstr = NULL; + sd->regstr_num = 0; + } + if( sd->st && sd->st->state != RUN ) {// free attached scripts that are waiting + script_free_state(sd->st); + sd->st = NULL; + sd->npc_id = 0; + } + if( sd->combos.count ) { + aFree(sd->combos.bonus); + aFree(sd->combos.id); + sd->combos.count = 0; + } + break; + } + case BL_PET: + { + struct pet_data *pd = (struct pet_data*)bl; + struct map_session_data *sd = pd->msd; + pet_hungry_timer_delete(pd); + if( pd->a_skill ) + { + aFree(pd->a_skill); + pd->a_skill = NULL; + } + if( pd->s_skill ) + { + if (pd->s_skill->timer != INVALID_TIMER) { + if (pd->s_skill->id) + delete_timer(pd->s_skill->timer, pet_skill_support_timer); + else + delete_timer(pd->s_skill->timer, pet_heal_timer); + } + aFree(pd->s_skill); + pd->s_skill = NULL; + } + if( pd->recovery ) + { + if(pd->recovery->timer != INVALID_TIMER) + delete_timer(pd->recovery->timer, pet_recovery_timer); + aFree(pd->recovery); + pd->recovery = NULL; + } + if( pd->bonus ) + { + if (pd->bonus->timer != INVALID_TIMER) + delete_timer(pd->bonus->timer, pet_skill_bonus_timer); + aFree(pd->bonus); + pd->bonus = NULL; + } + if( pd->loot ) + { + pet_lootitem_drop(pd,sd); + if (pd->loot->item) + aFree(pd->loot->item); + aFree (pd->loot); + pd->loot = NULL; + } + if( pd->pet.intimate > 0 ) + intif_save_petdata(pd->pet.account_id,&pd->pet); + else + { //Remove pet. + intif_delete_petdata(pd->pet.pet_id); + if (sd) sd->status.pet_id = 0; + } + if( sd ) + sd->pd = NULL; + break; + } + case BL_MOB: + { + struct mob_data *md = (struct mob_data*)bl; + if( md->spawn_timer != INVALID_TIMER ) + { + delete_timer(md->spawn_timer,mob_delayspawn); + md->spawn_timer = INVALID_TIMER; + } + if( md->deletetimer != INVALID_TIMER ) + { + delete_timer(md->deletetimer,mob_timer_delete); + md->deletetimer = INVALID_TIMER; + } + if( md->lootitem ) + { + aFree(md->lootitem); + md->lootitem=NULL; + } + if( md->guardian_data ) + { + struct guild_castle* gc = md->guardian_data->castle; + if( md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS ) + { + gc->guardian[md->guardian_data->number].id = 0; + } + else + { + int i; + ARR_FIND(0, gc->temp_guardians_max, i, gc->temp_guardians[i] == md->bl.id); + if( i < gc->temp_guardians_max ) + gc->temp_guardians[i] = 0; + } + aFree(md->guardian_data); + md->guardian_data = NULL; + } + if( md->spawn ) + { + md->spawn->active--; + if( !md->spawn->state.dynamic ) + {// permanently remove the mob + if( --md->spawn->num == 0 ) + {// Last freed mob is responsible for deallocating the group's spawn data. + aFree(md->spawn); + md->spawn = NULL; + } + } + } + if( md->base_status) + { + aFree(md->base_status); + md->base_status = NULL; + } + if( mob_is_clone(md->class_) ) + mob_clone_delete(md); + if( md->tomb_nid ) + mvptomb_destroy(md); + break; + } + case BL_HOM: + { + struct homun_data *hd = (TBL_HOM*)bl; + struct map_session_data *sd = hd->master; + merc_hom_hungry_timer_delete(hd); + if( hd->homunculus.intimacy > 0 ) + merc_save(hd); + else + { + intif_homunculus_requestdelete(hd->homunculus.hom_id); + if( sd ) + sd->status.hom_id = 0; + } + if( sd ) + sd->hd = NULL; + break; + } + case BL_MER: + { + struct mercenary_data *md = (TBL_MER*)bl; + struct map_session_data *sd = md->master; + if( mercenary_get_lifetime(md) > 0 ) + mercenary_save(md); + else + { + intif_mercenary_delete(md->mercenary.mercenary_id); + if( sd ) + sd->status.mer_id = 0; + } + if( sd ) + sd->md = NULL; + + merc_contract_stop(md); + break; + } + case BL_ELEM: { + struct elemental_data *ed = (TBL_ELEM*)bl; + struct map_session_data *sd = ed->master; + if( elemental_get_lifetime(ed) > 0 ) + elemental_save(ed); + else { + intif_elemental_delete(ed->elemental.elemental_id); + if( sd ) + sd->status.ele_id = 0; + } + if( sd ) + sd->ed = NULL; + + elemental_summon_stop(ed); + break; + } + } + + skill_clear_unitgroup(bl); + status_change_clear(bl,1); + map_deliddb(bl); + if( bl->type != BL_PC ) //Players are handled by map_quit + map_freeblock(bl); + map_freeblock_unlock(); + return 0; } int do_init_unit(void) { - add_timer_func_list(unit_attack_timer, "unit_attack_timer"); - add_timer_func_list(unit_walktoxy_timer,"unit_walktoxy_timer"); - add_timer_func_list(unit_walktobl_sub, "unit_walktobl_sub"); - add_timer_func_list(unit_delay_walktoxy_timer,"unit_delay_walktoxy_timer"); - return 0; + add_timer_func_list(unit_attack_timer, "unit_attack_timer"); + add_timer_func_list(unit_walktoxy_timer,"unit_walktoxy_timer"); + add_timer_func_list(unit_walktobl_sub, "unit_walktobl_sub"); + add_timer_func_list(unit_delay_walktoxy_timer,"unit_delay_walktoxy_timer"); + return 0; } int do_final_unit(void) { - // nothing to do - return 0; + // nothing to do + return 0; } diff --git a/src/map/unit.h b/src/map/unit.h index 26797a84f..11f5fba0e 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -15,70 +15,70 @@ struct map_session_data; #include "skill.h" // struct skill_timerskill, struct skill_unit_group, struct skill_unit_group_tickset struct unit_data { - struct block_list *bl; - struct walkpath_data walkpath; - struct skill_timerskill *skilltimerskill[MAX_SKILLTIMERSKILL]; - struct skill_unit_group *skillunit[MAX_SKILLUNITGROUP]; - struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET]; - short attacktarget_lv; - short to_x,to_y; - short skillx,skilly; - short skillid,skilllv; - int skilltarget; - int skilltimer; - int target; - int target_to; - int attacktimer; - int walktimer; - int chaserange; - unsigned int attackabletime; - unsigned int canact_tick; - unsigned int canmove_tick; - uint8 dir; - unsigned char walk_count; - unsigned char target_count; - struct { - unsigned change_walk_target : 1 ; - unsigned skillcastcancel : 1 ; - unsigned attack_continue : 1 ; - unsigned walk_easy : 1 ; - unsigned running : 1; - unsigned speed_changed : 1; - } state; + struct block_list *bl; + struct walkpath_data walkpath; + struct skill_timerskill *skilltimerskill[MAX_SKILLTIMERSKILL]; + struct skill_unit_group *skillunit[MAX_SKILLUNITGROUP]; + struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET]; + short attacktarget_lv; + short to_x,to_y; + short skillx,skilly; + short skillid,skilllv; + int skilltarget; + int skilltimer; + int target; + int target_to; + int attacktimer; + int walktimer; + int chaserange; + unsigned int attackabletime; + unsigned int canact_tick; + unsigned int canmove_tick; + uint8 dir; + unsigned char walk_count; + unsigned char target_count; + struct { + unsigned change_walk_target : 1 ; + unsigned skillcastcancel : 1 ; + unsigned attack_continue : 1 ; + unsigned walk_easy : 1 ; + unsigned running : 1; + unsigned speed_changed : 1; + } state; }; struct view_data { #ifdef __64BIT__ - unsigned int class_; + unsigned int class_; #endif - unsigned short + unsigned short #ifndef __64BIT__ - class_, + class_, #endif - weapon, - shield, //Or left-hand weapon. - robe, - head_top, - head_mid, - head_bottom, - hair_style, - hair_color, - cloth_color; - char sex; - unsigned dead_sit : 2; + weapon, + shield, //Or left-hand weapon. + robe, + head_top, + head_mid, + head_bottom, + hair_style, + hair_color, + cloth_color; + char sex; + unsigned dead_sit : 2; }; // PC, MOB, PET に共通する処理を1つにまとめる計画 // 歩行開始 // 戻り値は、0 ( 成功 ), 1 ( 失敗 ) -int unit_walktoxy(struct block_list *bl, short x, short y, int easy); -int unit_walktobl(struct block_list *bl, struct block_list *target, int range, int easy); +int unit_walktoxy( struct block_list *bl, short x, short y, int easy); +int unit_walktobl( struct block_list *bl, struct block_list *target, int range, int easy); int unit_run(struct block_list *bl); int unit_calc_pos(struct block_list *bl, int tx, int ty, int dir); // 歩行停止 -// typeは以下の組み合わせ : +// typeは以下の組み合わせ : // 1: 位置情報の送信( この関数の後に位置情報を送信する場合は不要 ) // 2: ダメージディレイ有り // 4: 不明(MOBのみ?) @@ -93,7 +93,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool int unit_warp(struct block_list *bl, short map, short x, short y, clr_type type); int unit_setdir(struct block_list *bl,unsigned char dir); uint8 unit_getdir(struct block_list *bl); -int unit_blown(struct block_list *bl, int dx, int dy, int count, int flag); +int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag); // そこまで歩行でたどり着けるかの判定 bool unit_can_reach_pos(struct block_list *bl,int x,int y,int easy); @@ -110,24 +110,24 @@ int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, shor // スキル使用( 補正済みキャスト時間、キャンセル不可設定付き ) int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, short skill_lv, int casttime, int castcancel); -int unit_skilluse_pos2(struct block_list *src, short skill_x, short skill_y, short skill_num, short skill_lv, int casttime, int castcancel); +int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, short skill_num, short skill_lv, int casttime, int castcancel); // 詠唱キャンセル int unit_skillcastcancel(struct block_list *bl,int type); int unit_counttargeted(struct block_list *bl); -int unit_set_target(struct unit_data *ud, int target_id); +int unit_set_target(struct unit_data* ud, int target_id); // unit_data の初期化処理 void unit_dataset(struct block_list *bl); int unit_fixdamage(struct block_list *src,struct block_list *target,unsigned int tick,int sdelay,int ddelay,int damage,int div,int type,int damage2); // その他 -struct unit_data *unit_bl2ud(struct block_list *bl); +struct unit_data* unit_bl2ud(struct block_list *bl); void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype); void unit_free_pc(struct map_session_data *sd); #define unit_remove_map(bl,clrtype) unit_remove_map_(bl,clrtype,__FILE__,__LINE__,__func__) -int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char *file, int line, const char *func); +int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func); int unit_free(struct block_list *bl, clr_type clrtype); int unit_changeviewsize(struct block_list *bl,short size); diff --git a/src/map/vending.c b/src/map/vending.c index c796d77e5..0f8255788 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -25,379 +25,393 @@ static int vending_nextid = 0; /// Returns an unique vending shop id. static int vending_getuid(void) { - return vending_nextid++; + return vending_nextid++; } /*========================================== * Close shop *------------------------------------------*/ -void vending_closevending(struct map_session_data *sd) +void vending_closevending(struct map_session_data* sd) { - nullpo_retv(sd); + nullpo_retv(sd); - if (sd->state.vending) { - sd->state.vending = false; - clif_closevendingboard(&sd->bl, 0); - } + if( sd->state.vending ) + { + sd->state.vending = false; + clif_closevendingboard(&sd->bl, 0); + } } /*========================================== * Request a shop's item list *------------------------------------------*/ -void vending_vendinglistreq(struct map_session_data *sd, int id) +void vending_vendinglistreq(struct map_session_data* sd, int id) { - struct map_session_data *vsd; - nullpo_retv(sd); + struct map_session_data* vsd; + nullpo_retv(sd); - if ((vsd = map_id2sd(id)) == NULL) - return; - if (!vsd->state.vending) - return; // not vending + if( (vsd = map_id2sd(id)) == NULL ) + return; + if( !vsd->state.vending ) + return; // not vending - if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) { //check if both GMs are allowed to trade - // GM is not allowed to trade - clif_displaymessage(sd->fd, msg_txt(246)); - return; - } + if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) //check if both GMs are allowed to trade + { // GM is not allowed to trade + clif_displaymessage(sd->fd, msg_txt(246)); + return; + } - sd->vended_id = vsd->vender_id; // register vending uid + sd->vended_id = vsd->vender_id; // register vending uid - clif_vendinglist(sd, id, vsd->vending); + clif_vendinglist(sd, id, vsd->vending); } /*========================================== * Purchase item(s) from a shop *------------------------------------------*/ -void vending_purchasereq(struct map_session_data *sd, int aid, int uid, const uint8 *data, int count) +void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count) { - int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING]; - double z; - struct s_vending vending[MAX_VENDING]; // against duplicate packets - struct map_session_data *vsd = map_id2sd(aid); - - nullpo_retv(sd); - if (vsd == NULL || !vsd->state.vending || vsd->bl.id == sd->bl.id) - return; // invalid shop - - if (vsd->vender_id != uid) { - // shop has changed - clif_buyvending(sd, 0, 0, 6); // store information was incorrect - return; - } - - if (!searchstore_queryremote(sd, aid) && (sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE))) - return; // shop too far away - - searchstore_clearremote(sd); - - if (count < 1 || count > MAX_VENDING || count > vsd->vend_num) - return; // invalid amount of purchased items - - blank = pc_inventoryblank(sd); //number of free cells in the buyer's inventory - - // duplicate item in vending to check hacker with multiple packets - memcpy(&vending, &vsd->vending, sizeof(vsd->vending)); // copy vending list - - // some checks - z = 0.; // zeny counter - w = 0; // weight counter - for (i = 0; i < count; i++) { - short amount = *(uint16 *)(data + 4*i + 0); - short idx = *(uint16 *)(data + 4*i + 2); - idx -= 2; - - if (amount <= 0) - return; - - // check of item index in the cart - if (idx < 0 || idx >= MAX_CART) - return; - - ARR_FIND(0, vsd->vend_num, j, vsd->vending[j].index == idx); - if (j == vsd->vend_num) - return; //picked non-existing item - else - vend_list[i] = j; - - z += ((double)vsd->vending[j].value * (double)amount); - if (z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY) { - clif_buyvending(sd, idx, amount, 1); // you don't have enough zeny - return; - } - if (z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle_config.vending_over_max) { - clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // too much zeny = overflow - return; - - } - w += itemdb_weight(vsd->status.cart[idx].nameid) * amount; - if (w + sd->weight > sd->max_weight) { - clif_buyvending(sd, idx, amount, 2); // you can not buy, because overweight - return; - } - - //Check to see if cart/vend info is in sync. - if (vending[j].amount > vsd->status.cart[idx].amount) - vending[j].amount = vsd->status.cart[idx].amount; - - // if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples). - // here, we check cumulative amounts - if (vending[j].amount < amount) { - // send more quantity is not a hack (an other player can have buy items just before) - clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity - return; - } - - vending[j].amount -= amount; - - switch (pc_checkadditem(sd, vsd->status.cart[idx].nameid, amount)) { - case ADDITEM_EXIST: - break; //We'd add this item to the existing one (in buyers inventory) - case ADDITEM_NEW: - new_++; - if (new_ > blank) - return; //Buyer has no space in his inventory - break; - case ADDITEM_OVERAMOUNT: - return; //too many items - } - } - - pc_payzeny(sd, (int)z, LOG_TYPE_VENDING, vsd); - if (battle_config.vending_tax) - z -= z * (battle_config.vending_tax/10000.); - pc_getzeny(vsd, (int)z, LOG_TYPE_VENDING, sd); - - for (i = 0; i < count; i++) { - short amount = *(uint16 *)(data + 4*i + 0); - short idx = *(uint16 *)(data + 4*i + 2); - idx -= 2; - - // vending item - pc_additem(sd, &vsd->status.cart[idx], amount, LOG_TYPE_VENDING); - vsd->vending[vend_list[i]].amount -= amount; - pc_cart_delitem(vsd, idx, amount, 0, LOG_TYPE_VENDING); - clif_vendingreport(vsd, idx, amount); - - //print buyer's name - if (battle_config.buyer_name) { - char temp[256]; - sprintf(temp, msg_txt(265), sd->status.name); - clif_disp_onlyself(vsd,temp,strlen(temp)); - } - } - - // compact the vending list - for (i = 0, cursor = 0; i < vsd->vend_num; i++) { - if (vsd->vending[i].amount == 0) - continue; - - if (cursor != i) { // speedup - vsd->vending[cursor].index = vsd->vending[i].index; - vsd->vending[cursor].amount = vsd->vending[i].amount; - vsd->vending[cursor].value = vsd->vending[i].value; - } - - cursor++; - } - vsd->vend_num = cursor; - - //Always save BOTH: buyer and customer - if (save_settings&2) { - chrif_save(sd,0); - chrif_save(vsd,0); - } - - //check for @AUTOTRADE users [durf] - if (vsd->state.autotrade) { - //see if there is anything left in the shop - ARR_FIND(0, vsd->vend_num, i, vsd->vending[i].amount > 0); - if (i == vsd->vend_num) { - //Close Vending (this was automatically done by the client, we have to do it manually for autovenders) [Skotlex] - vending_closevending(vsd); - map_quit(vsd); //They have no reason to stay around anymore, do they? - } - } + int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING]; + double z; + struct s_vending vending[MAX_VENDING]; // against duplicate packets + struct map_session_data* vsd = map_id2sd(aid); + + nullpo_retv(sd); + if( vsd == NULL || !vsd->state.vending || vsd->bl.id == sd->bl.id ) + return; // invalid shop + + if( vsd->vender_id != uid ) + {// shop has changed + clif_buyvending(sd, 0, 0, 6); // store information was incorrect + return; + } + + if( !searchstore_queryremote(sd, aid) && ( sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE) ) ) + return; // shop too far away + + searchstore_clearremote(sd); + + if( count < 1 || count > MAX_VENDING || count > vsd->vend_num ) + return; // invalid amount of purchased items + + blank = pc_inventoryblank(sd); //number of free cells in the buyer's inventory + + // duplicate item in vending to check hacker with multiple packets + memcpy(&vending, &vsd->vending, sizeof(vsd->vending)); // copy vending list + + // some checks + z = 0.; // zeny counter + w = 0; // weight counter + for( i = 0; i < count; i++ ) + { + short amount = *(uint16*)(data + 4*i + 0); + short idx = *(uint16*)(data + 4*i + 2); + idx -= 2; + + if( amount <= 0 ) + return; + + // check of item index in the cart + if( idx < 0 || idx >= MAX_CART ) + return; + + ARR_FIND( 0, vsd->vend_num, j, vsd->vending[j].index == idx ); + if( j == vsd->vend_num ) + return; //picked non-existing item + else + vend_list[i] = j; + + z += ((double)vsd->vending[j].value * (double)amount); + if( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY ) + { + clif_buyvending(sd, idx, amount, 1); // you don't have enough zeny + return; + } + if( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle_config.vending_over_max ) + { + clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // too much zeny = overflow + return; + + } + w += itemdb_weight(vsd->status.cart[idx].nameid) * amount; + if( w + sd->weight > sd->max_weight ) + { + clif_buyvending(sd, idx, amount, 2); // you can not buy, because overweight + return; + } + + //Check to see if cart/vend info is in sync. + if( vending[j].amount > vsd->status.cart[idx].amount ) + vending[j].amount = vsd->status.cart[idx].amount; + + // if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples). + // here, we check cumulative amounts + if( vending[j].amount < amount ) + { + // send more quantity is not a hack (an other player can have buy items just before) + clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity + return; + } + + vending[j].amount -= amount; + + switch( pc_checkadditem(sd, vsd->status.cart[idx].nameid, amount) ) { + case ADDITEM_EXIST: + break; //We'd add this item to the existing one (in buyers inventory) + case ADDITEM_NEW: + new_++; + if (new_ > blank) + return; //Buyer has no space in his inventory + break; + case ADDITEM_OVERAMOUNT: + return; //too many items + } + } + + pc_payzeny(sd, (int)z, LOG_TYPE_VENDING, vsd); + if( battle_config.vending_tax ) + z -= z * (battle_config.vending_tax/10000.); + pc_getzeny(vsd, (int)z, LOG_TYPE_VENDING, sd); + + for( i = 0; i < count; i++ ) + { + short amount = *(uint16*)(data + 4*i + 0); + short idx = *(uint16*)(data + 4*i + 2); + idx -= 2; + + // vending item + pc_additem(sd, &vsd->status.cart[idx], amount, LOG_TYPE_VENDING); + vsd->vending[vend_list[i]].amount -= amount; + pc_cart_delitem(vsd, idx, amount, 0, LOG_TYPE_VENDING); + clif_vendingreport(vsd, idx, amount); + + //print buyer's name + if( battle_config.buyer_name ) + { + char temp[256]; + sprintf(temp, msg_txt(265), sd->status.name); + clif_disp_onlyself(vsd,temp,strlen(temp)); + } + } + + // compact the vending list + for( i = 0, cursor = 0; i < vsd->vend_num; i++ ) + { + if( vsd->vending[i].amount == 0 ) + continue; + + if( cursor != i ) // speedup + { + vsd->vending[cursor].index = vsd->vending[i].index; + vsd->vending[cursor].amount = vsd->vending[i].amount; + vsd->vending[cursor].value = vsd->vending[i].value; + } + + cursor++; + } + vsd->vend_num = cursor; + + //Always save BOTH: buyer and customer + if( save_settings&2 ) + { + chrif_save(sd,0); + chrif_save(vsd,0); + } + + //check for @AUTOTRADE users [durf] + if( vsd->state.autotrade ) + { + //see if there is anything left in the shop + ARR_FIND( 0, vsd->vend_num, i, vsd->vending[i].amount > 0 ); + if( i == vsd->vend_num ) + { + //Close Vending (this was automatically done by the client, we have to do it manually for autovenders) [Skotlex] + vending_closevending(vsd); + map_quit(vsd); //They have no reason to stay around anymore, do they? + } + } } -static int vending_checknearnpc_sub(struct block_list *bl, va_list args) -{ - struct npc_data *nd = (struct npc_data *)bl; - - if (nd->sc.option & (OPTION_HIDE|OPTION_INVISIBLE)) +static int vending_checknearnpc_sub(struct block_list* bl, va_list args) { + struct npc_data *nd = (struct npc_data*)bl; + + if( nd->sc.option & (OPTION_HIDE|OPTION_INVISIBLE) ) return 0; return 1; } -bool vending_checknearnpc(struct block_list *bl) -{ - - if (battle_config.min_npc_vending_distance > 0 && - map_foreachinrange(vending_checknearnpc_sub,bl, battle_config.min_npc_vending_distance, BL_NPC)) +bool vending_checknearnpc(struct block_list * bl) { + + if( battle_config.min_npc_vending_distance > 0 && + map_foreachinrange(vending_checknearnpc_sub,bl, battle_config.min_npc_vending_distance, BL_NPC) ) return true; - + return false; } /*========================================== * Open shop * data := {<index>.w <amount>.w <value>.l}[count] *------------------------------------------*/ -void vending_openvending(struct map_session_data *sd, const char *message, bool flag, const uint8 *data, int count) -{ - int i, j; - int vending_skill_lvl; - nullpo_retv(sd); - - if (!flag) // cancelled - return; // nothing to do - - if (pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) - return; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once - - vending_skill_lvl = pc_checkskill(sd, MC_VENDING); - // skill level and cart check - if (!vending_skill_lvl || !pc_iscarton(sd)) { - clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); - return; - } - - // check number of items in shop - if (count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl) { - // invalid item count - clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); - return; - } - //check if nearby npc, (perhaps we should check for nearby shop too - if (vending_checknearnpc(&sd->bl)) { +void vending_openvending(struct map_session_data* sd, const char* message, bool flag, const uint8* data, int count) { + int i, j; + int vending_skill_lvl; + nullpo_retv(sd); + + if( !flag ) // cancelled + return; // nothing to do + + if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) + return; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once + + vending_skill_lvl = pc_checkskill(sd, MC_VENDING); + // skill level and cart check + if( !vending_skill_lvl || !pc_iscarton(sd) ) + { + clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); + return; + } + + // check number of items in shop + if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) + { // invalid item count + clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); + return; + } + //check if nearby npc, (perhaps we should check for nearby shop too + if( vending_checknearnpc(&sd->bl) ) { char output[150]; sprintf(output,"You're too close to a NPC, you must be at least %d cells away from any NPC.",battle_config.min_npc_vending_distance); clif_displaymessage(sd->fd, output); clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); return; } - - - // filter out invalid items - i = 0; - for (j = 0; j < count; j++) { - short index = *(uint16 *)(data + 8*j + 0); - short amount = *(uint16 *)(data + 8*j + 2); - unsigned int value = *(uint32 *)(data + 8*j + 4); - - index -= 2; // offset adjustment (client says that the first cart position is 2) - - if (index < 0 || index >= MAX_CART // invalid position - || pc_cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity - //NOTE: official server does not do any of the following checks! - || !sd->status.cart[index].identify // unidentified item - || sd->status.cart[index].attribute == 1 // broken item - || sd->status.cart[index].expire_time // It should not be in the cart but just in case - || !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd))) // untradeable item - continue; - - sd->vending[i].index = index; - sd->vending[i].amount = amount; - sd->vending[i].value = cap_value(value, 0, (unsigned int)battle_config.vending_max_value); - - i++; // item successfully added - } - - if (i != j) - clif_displaymessage(sd->fd, msg_txt(266)); //"Some of your items cannot be vended and were removed from the shop." - - if (i == 0) { - // no valid item found - clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet - return; - } - sd->state.prevend = 0; - sd->state.vending = true; - sd->vender_id = vending_getuid(); - sd->vend_num = i; - safestrncpy(sd->message, message, MESSAGE_SIZE); - - pc_stop_walking(sd,1); - clif_openvending(sd,sd->bl.id,sd->vending); - clif_showvendingboard(&sd->bl,message,0); + + + // filter out invalid items + i = 0; + for( j = 0; j < count; j++ ) + { + short index = *(uint16*)(data + 8*j + 0); + short amount = *(uint16*)(data + 8*j + 2); + unsigned int value = *(uint32*)(data + 8*j + 4); + + index -= 2; // offset adjustment (client says that the first cart position is 2) + + if( index < 0 || index >= MAX_CART // invalid position + || pc_cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity + //NOTE: official server does not do any of the following checks! + || !sd->status.cart[index].identify // unidentified item + || sd->status.cart[index].attribute == 1 // broken item + || sd->status.cart[index].expire_time // It should not be in the cart but just in case + || !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item + continue; + + sd->vending[i].index = index; + sd->vending[i].amount = amount; + sd->vending[i].value = cap_value(value, 0, (unsigned int)battle_config.vending_max_value); + + i++; // item successfully added + } + + if( i != j ) + clif_displaymessage (sd->fd, msg_txt(266)); //"Some of your items cannot be vended and were removed from the shop." + + if( i == 0 ) + { // no valid item found + clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet + return; + } + sd->state.prevend = 0; + sd->state.vending = true; + sd->vender_id = vending_getuid(); + sd->vend_num = i; + safestrncpy(sd->message, message, MESSAGE_SIZE); + + pc_stop_walking(sd,1); + clif_openvending(sd,sd->bl.id,sd->vending); + clif_showvendingboard(&sd->bl,message,0); } /// Checks if an item is being sold in given player's vending. -bool vending_search(struct map_session_data *sd, unsigned short nameid) +bool vending_search(struct map_session_data* sd, unsigned short nameid) { - int i; + int i; - if (!sd->state.vending) { - // not vending - return false; - } + if( !sd->state.vending ) + {// not vending + return false; + } - ARR_FIND(0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)nameid); - if (i == sd->vend_num) { - // not found - return false; - } + ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)nameid ); + if( i == sd->vend_num ) + {// not found + return false; + } - return true; + return true; } /// Searches for all items in a vending, that match given ids, price and possible cards. /// @return Whether or not the search should be continued. -bool vending_searchall(struct map_session_data *sd, const struct s_search_store_search *s) +bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s) { - int i, c, slot; - unsigned int idx, cidx; - struct item *it; - - if (!sd->state.vending) { - // not vending - return true; - } - - for (idx = 0; idx < s->item_count; idx++) { - ARR_FIND(0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)s->itemlist[idx]); - if (i == sd->vend_num) { - // not found - continue; - } - it = &sd->status.cart[sd->vending[i].index]; - - if (s->min_price && s->min_price > sd->vending[i].value) { - // too low price - continue; - } - - if (s->max_price && s->max_price < sd->vending[i].value) { - // too high price - continue; - } - - if (s->card_count) { - // check cards - if (itemdb_isspecial(it->card[0])) { - // something, that is not a carded - continue; - } - slot = itemdb_slot(it->nameid); - - for (c = 0; c < slot && it->card[c]; c ++) { - ARR_FIND(0, s->card_count, cidx, s->cardlist[cidx] == it->card[c]); - if (cidx != s->card_count) { - // found - break; - } - } - - if (c == slot || !it->card[c]) { - // no card match - continue; - } - } - - if (!searchstore_result(s->search_sd, sd->vender_id, sd->status.account_id, sd->message, it->nameid, sd->vending[i].amount, sd->vending[i].value, it->card, it->refine)) { - // result set full - return false; - } - } - - return true; + int i, c, slot; + unsigned int idx, cidx; + struct item* it; + + if( !sd->state.vending ) + {// not vending + return true; + } + + for( idx = 0; idx < s->item_count; idx++ ) + { + ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)s->itemlist[idx] ); + if( i == sd->vend_num ) + {// not found + continue; + } + it = &sd->status.cart[sd->vending[i].index]; + + if( s->min_price && s->min_price > sd->vending[i].value ) + {// too low price + continue; + } + + if( s->max_price && s->max_price < sd->vending[i].value ) + {// too high price + continue; + } + + if( s->card_count ) + {// check cards + if( itemdb_isspecial(it->card[0]) ) + {// something, that is not a carded + continue; + } + slot = itemdb_slot(it->nameid); + + for( c = 0; c < slot && it->card[c]; c ++ ) + { + ARR_FIND( 0, s->card_count, cidx, s->cardlist[cidx] == it->card[c] ); + if( cidx != s->card_count ) + {// found + break; + } + } + + if( c == slot || !it->card[c] ) + {// no card match + continue; + } + } + + if( !searchstore_result(s->search_sd, sd->vender_id, sd->status.account_id, sd->message, it->nameid, sd->vending[i].amount, sd->vending[i].value, it->card, it->refine) ) + {// result set full + return false; + } + } + + return true; } diff --git a/src/map/vending.h b/src/map/vending.h index 17dad31cd..2ed52b9bd 100644 --- a/src/map/vending.h +++ b/src/map/vending.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _VENDING_H_ -#define _VENDING_H_ +#ifndef _VENDING_H_ +#define _VENDING_H_ #include "../common/cbasetypes.h" //#include "map.h" @@ -10,17 +10,17 @@ struct map_session_data; struct s_search_store_search; struct s_vending { - short index; //cart index (return item data) - short amount; //amout of the item for vending - unsigned int value; //at wich price + short index; //cart index (return item data) + short amount; //amout of the item for vending + unsigned int value; //at wich price }; -void vending_closevending(struct map_session_data *sd); -void vending_openvending(struct map_session_data *sd, const char *message, bool flag, const uint8 *data, int count); -void vending_vendinglistreq(struct map_session_data *sd, int id); -void vending_purchasereq(struct map_session_data *sd, int aid, int uid, const uint8 *data, int count); -bool vending_search(struct map_session_data *sd, unsigned short nameid); -bool vending_searchall(struct map_session_data *sd, const struct s_search_store_search *s); -bool vending_checknearnpc(struct block_list *bl); +void vending_closevending(struct map_session_data* sd); +void vending_openvending(struct map_session_data* sd, const char* message, bool flag, const uint8* data, int count); +void vending_vendinglistreq(struct map_session_data* sd, int id); +void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count); +bool vending_search(struct map_session_data* sd, unsigned short nameid); +bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s); +bool vending_checknearnpc(struct block_list * bl); #endif /* _VENDING_H_ */ |